mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2024-12-23 00:41:52 +00:00
[2.1.2] Refactory merge-library.php script
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1396 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
parent
85cdea0120
commit
e45cc503a2
2
NEWS
2
NEWS
@ -32,6 +32,8 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
|||||||
the $config and $context member variables
|
the $config and $context member variables
|
||||||
. HTML wrapper in DOMLex now takes DTD identifiers into account; doesn't
|
. HTML wrapper in DOMLex now takes DTD identifiers into account; doesn't
|
||||||
really make a difference, but is good for completeness sake
|
really make a difference, but is good for completeness sake
|
||||||
|
. merge-library.php script refactored for greater code reusability and
|
||||||
|
PHP4 compatibility
|
||||||
|
|
||||||
2.1.1, released 2007-08-04
|
2.1.1, released 2007-08-04
|
||||||
- Fix show-stopper bug in %URI.MakeAbsolute functionality
|
- Fix show-stopper bug in %URI.MakeAbsolute functionality
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
require_once 'compat-function-file-put-contents.php';
|
||||||
|
|
||||||
function assertCli() {
|
function assertCli() {
|
||||||
if (php_sapi_name() != 'cli' && !getenv('PHP_IS_CLI')) {
|
if (php_sapi_name() != 'cli' && !getenv('PHP_IS_CLI')) {
|
||||||
echo 'Script cannot be called from web-browser (if you are calling via cli,
|
echo 'Script cannot be called from web-browser (if you are calling via cli,
|
||||||
@ -7,3 +9,135 @@ set environment variable PHP_IS_CLI to work around this).';
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filesystem tools not provided by default; can recursively create, copy
|
||||||
|
* and delete folders. Some template methods are provided for extensibility.
|
||||||
|
* @note This class must be instantiated to be used, although it does
|
||||||
|
* not maintain state.
|
||||||
|
*/
|
||||||
|
class FSTools
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively creates a directory
|
||||||
|
* @param string $folder Name of folder to create
|
||||||
|
* @note Adapted from the PHP manual comment 76612
|
||||||
|
*/
|
||||||
|
function mkdir($folder) {
|
||||||
|
$folders = preg_split("#[\\\\/]#", $folder);
|
||||||
|
$base = '';
|
||||||
|
for($i = 0, $c = count($folders); $i < $c; $i++) {
|
||||||
|
if(empty($folders[$i])) {
|
||||||
|
if (!$i) {
|
||||||
|
// special case for root level
|
||||||
|
$base .= DIRECTORY_SEPARATOR;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$base .= $folders[$i];
|
||||||
|
if(!is_dir($base)){
|
||||||
|
mkdir($base);
|
||||||
|
}
|
||||||
|
$base .= DIRECTORY_SEPARATOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a file, or recursively copy a folder and its contents; modified
|
||||||
|
* so that copied files, if PHP, have includes removed
|
||||||
|
*
|
||||||
|
* @author Aidan Lister <aidan@php.net>
|
||||||
|
* @version 1.0.1-modified
|
||||||
|
* @link http://aidanlister.com/repos/v/function.copyr.php
|
||||||
|
* @param string $source Source path
|
||||||
|
* @param string $dest Destination path
|
||||||
|
* @return bool Returns TRUE on success, FALSE on failure
|
||||||
|
*/
|
||||||
|
function copyr($source, $dest) {
|
||||||
|
// Simple copy for a file
|
||||||
|
if (is_file($source)) {
|
||||||
|
return $this->copy($source, $dest);
|
||||||
|
}
|
||||||
|
// Make destination directory
|
||||||
|
if (!is_dir($dest)) {
|
||||||
|
mkdir($dest);
|
||||||
|
}
|
||||||
|
// Loop through the folder
|
||||||
|
$dir = dir($source);
|
||||||
|
while (false !== $entry = $dir->read()) {
|
||||||
|
// Skip pointers
|
||||||
|
if ($entry == '.' || $entry == '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!$this->copyable($entry)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Deep copy directories
|
||||||
|
if ($dest !== "$source/$entry") {
|
||||||
|
$this->copyr("$source/$entry", "$dest/$entry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Clean up
|
||||||
|
$dir->close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stub for PHP's built-in copy function, can be used to overload
|
||||||
|
* functionality
|
||||||
|
*/
|
||||||
|
function copy($source, $dest) {
|
||||||
|
return copy($source, $dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overloadable function that tests a filename for copyability. By
|
||||||
|
* default, everything should be copied; you can restrict things to
|
||||||
|
* ignore hidden files, unreadable files, etc.
|
||||||
|
*/
|
||||||
|
function copyable($file) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a file, or a folder and its contents
|
||||||
|
*
|
||||||
|
* @author Aidan Lister <aidan@php.net>
|
||||||
|
* @version 1.0.3
|
||||||
|
* @link http://aidanlister.com/repos/v/function.rmdirr.php
|
||||||
|
* @param string $dirname Directory to delete
|
||||||
|
* @return bool Returns TRUE on success, FALSE on failure
|
||||||
|
*/
|
||||||
|
function rmdirr($dirname)
|
||||||
|
{
|
||||||
|
// Sanity check
|
||||||
|
if (!file_exists($dirname)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple delete for a file
|
||||||
|
if (is_file($dirname) || is_link($dirname)) {
|
||||||
|
return unlink($dirname);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop through the folder
|
||||||
|
$dir = dir($dirname);
|
||||||
|
while (false !== $entry = $dir->read()) {
|
||||||
|
// Skip pointers
|
||||||
|
if ($entry == '.' || $entry == '..') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Recurse
|
||||||
|
$this->rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
$dir->close();
|
||||||
|
return rmdir($dirname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
107
maintenance/compat-function-file-put-contents.php
Normal file
107
maintenance/compat-function-file-put-contents.php
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
// $Id: file_put_contents.php,v 1.27 2007/04/17 10:09:56 arpad Exp $
|
||||||
|
|
||||||
|
|
||||||
|
if (!defined('FILE_USE_INCLUDE_PATH')) {
|
||||||
|
define('FILE_USE_INCLUDE_PATH', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined('LOCK_EX')) {
|
||||||
|
define('LOCK_EX', 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined('FILE_APPEND')) {
|
||||||
|
define('FILE_APPEND', 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace file_put_contents()
|
||||||
|
*
|
||||||
|
* @category PHP
|
||||||
|
* @package PHP_Compat
|
||||||
|
* @license LGPL - http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* @copyright 2004-2007 Aidan Lister <aidan@php.net>, Arpad Ray <arpad@php.net>
|
||||||
|
* @link http://php.net/function.file_put_contents
|
||||||
|
* @author Aidan Lister <aidan@php.net>
|
||||||
|
* @version $Revision: 1.27 $
|
||||||
|
* @internal resource_context is not supported
|
||||||
|
* @since PHP 5
|
||||||
|
* @require PHP 4.0.0 (user_error)
|
||||||
|
*/
|
||||||
|
function php_compat_file_put_contents($filename, $content, $flags = null, $resource_context = null)
|
||||||
|
{
|
||||||
|
// If $content is an array, convert it to a string
|
||||||
|
if (is_array($content)) {
|
||||||
|
$content = implode('', $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we don't have a string, throw an error
|
||||||
|
if (!is_scalar($content)) {
|
||||||
|
user_error('file_put_contents() The 2nd parameter should be either a string or an array',
|
||||||
|
E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the length of data to write
|
||||||
|
$length = strlen($content);
|
||||||
|
|
||||||
|
// Check what mode we are using
|
||||||
|
$mode = ($flags & FILE_APPEND) ?
|
||||||
|
'a' :
|
||||||
|
'wb';
|
||||||
|
|
||||||
|
// Check if we're using the include path
|
||||||
|
$use_inc_path = ($flags & FILE_USE_INCLUDE_PATH) ?
|
||||||
|
true :
|
||||||
|
false;
|
||||||
|
|
||||||
|
// Open the file for writing
|
||||||
|
if (($fh = @fopen($filename, $mode, $use_inc_path)) === false) {
|
||||||
|
user_error('file_put_contents() failed to open stream: Permission denied',
|
||||||
|
E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to get an exclusive lock
|
||||||
|
$use_lock = ($flags & LOCK_EX) ? true : false ;
|
||||||
|
if ($use_lock === true) {
|
||||||
|
if (!flock($fh, LOCK_EX)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to the file
|
||||||
|
$bytes = 0;
|
||||||
|
if (($bytes = @fwrite($fh, $content)) === false) {
|
||||||
|
$errormsg = sprintf('file_put_contents() Failed to write %d bytes to %s',
|
||||||
|
$length,
|
||||||
|
$filename);
|
||||||
|
user_error($errormsg, E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the handle
|
||||||
|
@fclose($fh);
|
||||||
|
|
||||||
|
// Check all the data was written
|
||||||
|
if ($bytes != $length) {
|
||||||
|
$errormsg = sprintf('file_put_contents() Only %d of %d bytes written, possibly out of free disk space.',
|
||||||
|
$bytes,
|
||||||
|
$length);
|
||||||
|
user_error($errormsg, E_USER_WARNING);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return length
|
||||||
|
return $bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Define
|
||||||
|
if (!function_exists('file_put_contents')) {
|
||||||
|
function file_put_contents($filename, $content, $flags = null, $resource_context = null)
|
||||||
|
{
|
||||||
|
return php_compat_file_put_contents($filename, $content, $flags, $resource_context);
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,29 @@ assertCli();
|
|||||||
$GLOBALS['loaded'] = array('HTMLPurifier.php' => true);
|
$GLOBALS['loaded'] = array('HTMLPurifier.php' => true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $text Text to replace includes from
|
* Custom FSTools for this script that overloads some behavior
|
||||||
|
* @warning The overloading of copy() is not necessarily global for
|
||||||
|
* this script. Watch out!
|
||||||
|
*/
|
||||||
|
class MergeLibraryFSTools extends FSTools
|
||||||
|
{
|
||||||
|
function copyable($entry) {
|
||||||
|
// Skip hidden files
|
||||||
|
if ($entry[0] == '.') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
function copy($source, $dest) {
|
||||||
|
copy_and_remove_includes($source, $dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$FS = new MergeLibraryFSTools();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the includes inside PHP source code with the corresponding
|
||||||
|
* source.
|
||||||
|
* @param string $text PHP source code to replace includes from
|
||||||
*/
|
*/
|
||||||
function replace_includes($text) {
|
function replace_includes($text) {
|
||||||
return preg_replace_callback(
|
return preg_replace_callback(
|
||||||
@ -32,6 +54,8 @@ function replace_includes($text) {
|
|||||||
/**
|
/**
|
||||||
* Removes leading PHP tags from included files. Assumes that there is
|
* Removes leading PHP tags from included files. Assumes that there is
|
||||||
* no trailing tag.
|
* no trailing tag.
|
||||||
|
* @note This is safe for files that have internal <?php
|
||||||
|
* @param string $text Text to have leading PHP tag from
|
||||||
*/
|
*/
|
||||||
function remove_php_tags($text) {
|
function remove_php_tags($text) {
|
||||||
return substr($text, 5);
|
return substr($text, 5);
|
||||||
@ -40,128 +64,44 @@ function remove_php_tags($text) {
|
|||||||
/**
|
/**
|
||||||
* Creates an appropriate blank file, recursively generating directories
|
* Creates an appropriate blank file, recursively generating directories
|
||||||
* if necessary
|
* if necessary
|
||||||
|
* @param string $file Filename to create blank for
|
||||||
*/
|
*/
|
||||||
function create_blank($file) {
|
function create_blank($file) {
|
||||||
|
global $FS;
|
||||||
$dir = dirname($file);
|
$dir = dirname($file);
|
||||||
$base = realpath('../tests/blanks/') . DIRECTORY_SEPARATOR ;
|
$base = realpath('../tests/blanks/') . DIRECTORY_SEPARATOR ;
|
||||||
if ($dir != '.') mkdir_deep($base . $dir);
|
if ($dir != '.') {
|
||||||
|
$FS->mkdir($base . $dir);
|
||||||
|
}
|
||||||
file_put_contents($base . $file, '');
|
file_put_contents($base . $file, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively creates a directory
|
|
||||||
* @note Adapted from the PHP manual comment 76612
|
|
||||||
*/
|
|
||||||
function mkdir_deep($folder) {
|
|
||||||
$folders = preg_split("#[\\\\/]#", $folder);
|
|
||||||
$base = '';
|
|
||||||
for($i = 0, $c = count($folders); $i < $c; $i++) {
|
|
||||||
if(empty($folders[$i])) {
|
|
||||||
if (!$i) {
|
|
||||||
// special case for root level
|
|
||||||
$base .= DIRECTORY_SEPARATOR;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$base .= $folders[$i];
|
|
||||||
if(!is_dir($base)){
|
|
||||||
mkdir($base);
|
|
||||||
}
|
|
||||||
$base .= DIRECTORY_SEPARATOR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy a file, or recursively copy a folder and its contents
|
|
||||||
*
|
|
||||||
* @author Aidan Lister <aidan@php.net>
|
|
||||||
* @version 1.0.1
|
|
||||||
* @link http://aidanlister.com/repos/v/function.copyr.php
|
|
||||||
* @param string $source Source path
|
|
||||||
* @param string $dest Destination path
|
|
||||||
* @return bool Returns TRUE on success, FALSE on failure
|
|
||||||
*/
|
|
||||||
function copyr($source, $dest) {
|
|
||||||
// Simple copy for a file
|
|
||||||
if (is_file($source)) {
|
|
||||||
return copy_and_remove_includes($source, $dest);
|
|
||||||
}
|
|
||||||
// Make destination directory
|
|
||||||
if (!is_dir($dest)) {
|
|
||||||
mkdir($dest);
|
|
||||||
}
|
|
||||||
// Loop through the folder
|
|
||||||
$dir = dir($source);
|
|
||||||
while (false !== $entry = $dir->read()) {
|
|
||||||
// Skip pointers
|
|
||||||
if ($entry == '.' || $entry == '..') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Skip hidden files
|
|
||||||
if ($entry[0] == '.') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Deep copy directories
|
|
||||||
if ($dest !== "$source/$entry") {
|
|
||||||
copyr("$source/$entry", "$dest/$entry");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Clean up
|
|
||||||
$dir->close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a file, or a folder and its contents
|
|
||||||
*
|
|
||||||
* @author Aidan Lister <aidan@php.net>
|
|
||||||
* @version 1.0.3
|
|
||||||
* @link http://aidanlister.com/repos/v/function.rmdirr.php
|
|
||||||
* @param string $dirname Directory to delete
|
|
||||||
* @return bool Returns TRUE on success, FALSE on failure
|
|
||||||
*/
|
|
||||||
function rmdirr($dirname)
|
|
||||||
{
|
|
||||||
// Sanity check
|
|
||||||
if (!file_exists($dirname)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple delete for a file
|
|
||||||
if (is_file($dirname) || is_link($dirname)) {
|
|
||||||
return unlink($dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through the folder
|
|
||||||
$dir = dir($dirname);
|
|
||||||
while (false !== $entry = $dir->read()) {
|
|
||||||
// Skip pointers
|
|
||||||
if ($entry == '.' || $entry == '..') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recurse
|
|
||||||
rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up
|
|
||||||
$dir->close();
|
|
||||||
return rmdir($dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies the contents of a directory to the standalone directory
|
* Copies the contents of a directory to the standalone directory
|
||||||
|
* @param string $dir Directory to copy
|
||||||
*/
|
*/
|
||||||
function make_dir_standalone($dir) {
|
function make_dir_standalone($dir) {
|
||||||
return copyr($dir, 'standalone/' . $dir);
|
global $FS;
|
||||||
|
return $FS->copyr($dir, 'standalone/' . $dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the contents of a file to the standalone directory
|
||||||
|
* @param string $file File to copy
|
||||||
|
*/
|
||||||
function make_file_standalone($file) {
|
function make_file_standalone($file) {
|
||||||
mkdir_deep('standalone/' . dirname($file));
|
global $FS;
|
||||||
|
$FS->mkdir('standalone/' . dirname($file));
|
||||||
copy_and_remove_includes($file, 'standalone/' . $file);
|
copy_and_remove_includes($file, 'standalone/' . $file);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a file to another location recursively, if it is a PHP file
|
||||||
|
* remove includes
|
||||||
|
* @param string $file Original file
|
||||||
|
* @param string $sfile New location of file
|
||||||
|
*/
|
||||||
function copy_and_remove_includes($file, $sfile) {
|
function copy_and_remove_includes($file, $sfile) {
|
||||||
$contents = file_get_contents($file);
|
$contents = file_get_contents($file);
|
||||||
if (strrchr($file, '.') === '.php') $contents = replace_includes($contents);
|
if (strrchr($file, '.') === '.php') $contents = replace_includes($contents);
|
||||||
@ -174,8 +114,13 @@ function copy_and_remove_includes($file, $sfile) {
|
|||||||
*/
|
*/
|
||||||
function replace_includes_callback($matches) {
|
function replace_includes_callback($matches) {
|
||||||
$file = $matches[1];
|
$file = $matches[1];
|
||||||
// PHP 5 only file / PEAR files
|
$preserve = array(
|
||||||
$preserve = array('HTMLPurifier/Lexer/DOMLex.php'=>1, 'HTMLPurifier/Printer.php'=>1, 'XML/HTMLSax3.php'=>1);
|
// PHP 5 only
|
||||||
|
'HTMLPurifier/Lexer/DOMLex.php' => 1,
|
||||||
|
'HTMLPurifier/Printer.php' => 1,
|
||||||
|
// PEAR (external)
|
||||||
|
'XML/HTMLSax3.php' => 1
|
||||||
|
);
|
||||||
if (isset($preserve[$file])) {
|
if (isset($preserve[$file])) {
|
||||||
return $matches[0];
|
return $matches[0];
|
||||||
}
|
}
|
||||||
@ -200,16 +145,22 @@ file_put_contents('HTMLPurifier.standalone.php', $contents);
|
|||||||
echo ' done!' . PHP_EOL;
|
echo ' done!' . PHP_EOL;
|
||||||
|
|
||||||
echo 'Creating standalone directory...';
|
echo 'Creating standalone directory...';
|
||||||
rmdirr('standalone'); // ensure a clean copy
|
$FS->rmdirr('standalone'); // ensure a clean copy
|
||||||
mkdir_deep('standalone/HTMLPurifier/DefinitionCache/Serializer');
|
|
||||||
|
// data files
|
||||||
|
$FS->mkdir('standalone/HTMLPurifier/DefinitionCache/Serializer');
|
||||||
make_dir_standalone('HTMLPurifier/EntityLookup');
|
make_dir_standalone('HTMLPurifier/EntityLookup');
|
||||||
|
|
||||||
|
// non-standard inclusion setup
|
||||||
make_dir_standalone('HTMLPurifier/Language');
|
make_dir_standalone('HTMLPurifier/Language');
|
||||||
|
|
||||||
|
// optional components
|
||||||
make_file_standalone('HTMLPurifier/Printer.php');
|
make_file_standalone('HTMLPurifier/Printer.php');
|
||||||
make_dir_standalone('HTMLPurifier/Printer');
|
make_dir_standalone('HTMLPurifier/Printer');
|
||||||
make_dir_standalone('HTMLPurifier/Filter');
|
make_dir_standalone('HTMLPurifier/Filter');
|
||||||
make_file_standalone('HTMLPurifier/Lexer/PEARSax3.php'); // not incl by default
|
make_file_standalone('HTMLPurifier/Lexer/PEARSax3.php');
|
||||||
|
|
||||||
// PHP 5 only files
|
// PHP 5 only files
|
||||||
make_file_standalone('HTMLPurifier/Lexer/DOMLex.php');
|
make_file_standalone('HTMLPurifier/Lexer/DOMLex.php');
|
||||||
make_file_standalone('HTMLPurifier/Lexer/PH5P.php');
|
make_file_standalone('HTMLPurifier/Lexer/PH5P.php');
|
||||||
echo ' done!' . PHP_EOL;
|
echo ' done!' . PHP_EOL;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user