更新vendor
This commit is contained in:
parent
459a88214b
commit
26c7590195
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload.php @generated by Composer
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 50600) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, $err);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo $err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
$err,
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once __DIR__ . '/composer/autoload_real.php';
|
||||||
|
|
||||||
|
return ComposerAutoloaderInitb6df9475fad16a473d4508387130aca7::getLoader();
|
|
@ -0,0 +1,119 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proxy PHP file generated by Composer
|
||||||
|
*
|
||||||
|
* This file includes the referenced bin path (../symfony/var-dumper/Resources/bin/var-dump-server)
|
||||||
|
* using a stream wrapper to prevent the shebang from being output on PHP<8
|
||||||
|
*
|
||||||
|
* @generated
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
$GLOBALS['_composer_bin_dir'] = __DIR__;
|
||||||
|
$GLOBALS['_composer_autoload_path'] = __DIR__ . '/..'.'/autoload.php';
|
||||||
|
|
||||||
|
if (PHP_VERSION_ID < 80000) {
|
||||||
|
if (!class_exists('Composer\BinProxyWrapper')) {
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class BinProxyWrapper
|
||||||
|
{
|
||||||
|
private $handle;
|
||||||
|
private $position;
|
||||||
|
private $realpath;
|
||||||
|
|
||||||
|
public function stream_open($path, $mode, $options, &$opened_path)
|
||||||
|
{
|
||||||
|
// get rid of phpvfscomposer:// prefix for __FILE__ & __DIR__ resolution
|
||||||
|
$opened_path = substr($path, 17);
|
||||||
|
$this->realpath = realpath($opened_path) ?: $opened_path;
|
||||||
|
$opened_path = $this->realpath;
|
||||||
|
$this->handle = fopen($this->realpath, $mode);
|
||||||
|
$this->position = 0;
|
||||||
|
|
||||||
|
return (bool) $this->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_read($count)
|
||||||
|
{
|
||||||
|
$data = fread($this->handle, $count);
|
||||||
|
|
||||||
|
if ($this->position === 0) {
|
||||||
|
$data = preg_replace('{^#!.*\r?\n}', '', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->position += strlen($data);
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_cast($castAs)
|
||||||
|
{
|
||||||
|
return $this->handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_close()
|
||||||
|
{
|
||||||
|
fclose($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_lock($operation)
|
||||||
|
{
|
||||||
|
return $operation ? flock($this->handle, $operation) : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_seek($offset, $whence)
|
||||||
|
{
|
||||||
|
if (0 === fseek($this->handle, $offset, $whence)) {
|
||||||
|
$this->position = ftell($this->handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_tell()
|
||||||
|
{
|
||||||
|
return $this->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_eof()
|
||||||
|
{
|
||||||
|
return feof($this->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_stat()
|
||||||
|
{
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stream_set_option($option, $arg1, $arg2)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function url_stat($path, $flags)
|
||||||
|
{
|
||||||
|
$path = substr($path, 17);
|
||||||
|
if (file_exists($path)) {
|
||||||
|
return stat($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(function_exists('stream_get_wrappers') && in_array('phpvfscomposer', stream_get_wrappers(), true))
|
||||||
|
|| (function_exists('stream_wrapper_register') && stream_wrapper_register('phpvfscomposer', 'Composer\BinProxyWrapper'))
|
||||||
|
) {
|
||||||
|
return include("phpvfscomposer://" . __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return include __DIR__ . '/..'.'/symfony/var-dumper/Resources/bin/var-dump-server';
|
|
@ -0,0 +1,5 @@
|
||||||
|
@ECHO OFF
|
||||||
|
setlocal DISABLEDELAYEDEXPANSION
|
||||||
|
SET BIN_TARGET=%~dp0/var-dump-server
|
||||||
|
SET COMPOSER_RUNTIME_BIN_DIR=%~dp0
|
||||||
|
php "%BIN_TARGET%" %*
|
|
@ -0,0 +1,579 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||||
|
*
|
||||||
|
* $loader = new \Composer\Autoload\ClassLoader();
|
||||||
|
*
|
||||||
|
* // register classes with namespaces
|
||||||
|
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||||
|
* $loader->add('Symfony', __DIR__.'/framework');
|
||||||
|
*
|
||||||
|
* // activate the autoloader
|
||||||
|
* $loader->register();
|
||||||
|
*
|
||||||
|
* // to enable searching the include path (eg. for PEAR packages)
|
||||||
|
* $loader->setUseIncludePath(true);
|
||||||
|
*
|
||||||
|
* In this example, if you try to use a class in the Symfony\Component
|
||||||
|
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||||
|
* the autoloader will first look for the class under the component/
|
||||||
|
* directory, and it will then fallback to the framework/ directory if not
|
||||||
|
* found before giving up.
|
||||||
|
*
|
||||||
|
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||||
|
*
|
||||||
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
* @see https://www.php-fig.org/psr/psr-0/
|
||||||
|
* @see https://www.php-fig.org/psr/psr-4/
|
||||||
|
*/
|
||||||
|
class ClassLoader
|
||||||
|
{
|
||||||
|
/** @var \Closure(string):void */
|
||||||
|
private static $includeFile;
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $vendorDir;
|
||||||
|
|
||||||
|
// PSR-4
|
||||||
|
/**
|
||||||
|
* @var array<string, array<string, int>>
|
||||||
|
*/
|
||||||
|
private $prefixLengthsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var array<string, list<string>>
|
||||||
|
*/
|
||||||
|
private $prefixDirsPsr4 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr4 = array();
|
||||||
|
|
||||||
|
// PSR-0
|
||||||
|
/**
|
||||||
|
* List of PSR-0 prefixes
|
||||||
|
*
|
||||||
|
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
|
||||||
|
*
|
||||||
|
* @var array<string, array<string, list<string>>>
|
||||||
|
*/
|
||||||
|
private $prefixesPsr0 = array();
|
||||||
|
/**
|
||||||
|
* @var list<string>
|
||||||
|
*/
|
||||||
|
private $fallbackDirsPsr0 = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $useIncludePath = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
private $classMap = array();
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
private $classMapAuthoritative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, bool>
|
||||||
|
*/
|
||||||
|
private $missingClasses = array();
|
||||||
|
|
||||||
|
/** @var string|null */
|
||||||
|
private $apcuPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<string, self>
|
||||||
|
*/
|
||||||
|
private static $registeredLoaders = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string|null $vendorDir
|
||||||
|
*/
|
||||||
|
public function __construct($vendorDir = null)
|
||||||
|
{
|
||||||
|
$this->vendorDir = $vendorDir;
|
||||||
|
self::initializeIncludeClosure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixes()
|
||||||
|
{
|
||||||
|
if (!empty($this->prefixesPsr0)) {
|
||||||
|
return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, list<string>>
|
||||||
|
*/
|
||||||
|
public function getPrefixesPsr4()
|
||||||
|
{
|
||||||
|
return $this->prefixDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirs()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return list<string>
|
||||||
|
*/
|
||||||
|
public function getFallbackDirsPsr4()
|
||||||
|
{
|
||||||
|
return $this->fallbackDirsPsr4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string, string> Array of classname => path
|
||||||
|
*/
|
||||||
|
public function getClassMap()
|
||||||
|
{
|
||||||
|
return $this->classMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, string> $classMap Class to filename map
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addClassMap(array $classMap)
|
||||||
|
{
|
||||||
|
if ($this->classMap) {
|
||||||
|
$this->classMap = array_merge($this->classMap, $classMap);
|
||||||
|
} else {
|
||||||
|
$this->classMap = $classMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix, either
|
||||||
|
* appending or prepending to the ones previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 root directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr0 = array_merge(
|
||||||
|
$this->fallbackDirsPsr0,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$first = $prefix[0];
|
||||||
|
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = $paths;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($prepend) {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixesPsr0[$first][$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||||
|
$this->prefixesPsr0[$first][$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace, either
|
||||||
|
* appending or prepending to the ones previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
* @param bool $prepend Whether to prepend the directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addPsr4($prefix, $paths, $prepend = false)
|
||||||
|
{
|
||||||
|
$paths = (array) $paths;
|
||||||
|
if (!$prefix) {
|
||||||
|
// Register directories for the root namespace.
|
||||||
|
if ($prepend) {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->fallbackDirsPsr4
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->fallbackDirsPsr4 = array_merge(
|
||||||
|
$this->fallbackDirsPsr4,
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||||
|
// Register directories for a new namespace.
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = $paths;
|
||||||
|
} elseif ($prepend) {
|
||||||
|
// Prepend directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$paths,
|
||||||
|
$this->prefixDirsPsr4[$prefix]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Append directories for an already registered namespace.
|
||||||
|
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||||
|
$this->prefixDirsPsr4[$prefix],
|
||||||
|
$paths
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-0 directories for a given prefix,
|
||||||
|
* replacing any others previously set for this prefix.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix
|
||||||
|
* @param list<string>|string $paths The PSR-0 base directories
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function set($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr0 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a set of PSR-4 directories for a given namespace,
|
||||||
|
* replacing any others previously set for this namespace.
|
||||||
|
*
|
||||||
|
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||||
|
* @param list<string>|string $paths The PSR-4 base directories
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setPsr4($prefix, $paths)
|
||||||
|
{
|
||||||
|
if (!$prefix) {
|
||||||
|
$this->fallbackDirsPsr4 = (array) $paths;
|
||||||
|
} else {
|
||||||
|
$length = strlen($prefix);
|
||||||
|
if ('\\' !== $prefix[$length - 1]) {
|
||||||
|
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||||
|
}
|
||||||
|
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||||
|
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns on searching the include path for class files.
|
||||||
|
*
|
||||||
|
* @param bool $useIncludePath
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUseIncludePath($useIncludePath)
|
||||||
|
{
|
||||||
|
$this->useIncludePath = $useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to check if the autoloader uses the include path to check
|
||||||
|
* for classes.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function getUseIncludePath()
|
||||||
|
{
|
||||||
|
return $this->useIncludePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turns off searching the prefix and fallback directories for classes
|
||||||
|
* that have not been registered with the class map.
|
||||||
|
*
|
||||||
|
* @param bool $classMapAuthoritative
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||||
|
{
|
||||||
|
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should class lookup fail if not found in the current class map?
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isClassMapAuthoritative()
|
||||||
|
{
|
||||||
|
return $this->classMapAuthoritative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||||
|
*
|
||||||
|
* @param string|null $apcuPrefix
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setApcuPrefix($apcuPrefix)
|
||||||
|
{
|
||||||
|
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function getApcuPrefix()
|
||||||
|
{
|
||||||
|
return $this->apcuPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @param bool $prepend Whether to prepend the autoloader or not
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register($prepend = false)
|
||||||
|
{
|
||||||
|
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||||
|
|
||||||
|
if (null === $this->vendorDir) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($prepend) {
|
||||||
|
self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
|
||||||
|
} else {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
self::$registeredLoaders[$this->vendorDir] = $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters this instance as an autoloader.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function unregister()
|
||||||
|
{
|
||||||
|
spl_autoload_unregister(array($this, 'loadClass'));
|
||||||
|
|
||||||
|
if (null !== $this->vendorDir) {
|
||||||
|
unset(self::$registeredLoaders[$this->vendorDir]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the given class or interface.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
* @return true|null True if loaded, null otherwise
|
||||||
|
*/
|
||||||
|
public function loadClass($class)
|
||||||
|
{
|
||||||
|
if ($file = $this->findFile($class)) {
|
||||||
|
$includeFile = self::$includeFile;
|
||||||
|
$includeFile($file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds the path to the file where the class is defined.
|
||||||
|
*
|
||||||
|
* @param string $class The name of the class
|
||||||
|
*
|
||||||
|
* @return string|false The path if found, false otherwise
|
||||||
|
*/
|
||||||
|
public function findFile($class)
|
||||||
|
{
|
||||||
|
// class map lookup
|
||||||
|
if (isset($this->classMap[$class])) {
|
||||||
|
return $this->classMap[$class];
|
||||||
|
}
|
||||||
|
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||||
|
if ($hit) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->findFileWithExtension($class, '.php');
|
||||||
|
|
||||||
|
// Search for Hack files if we are running on HHVM
|
||||||
|
if (false === $file && defined('HHVM_VERSION')) {
|
||||||
|
$file = $this->findFileWithExtension($class, '.hh');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null !== $this->apcuPrefix) {
|
||||||
|
apcu_add($this->apcuPrefix.$class, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $file) {
|
||||||
|
// Remember that this class does not exist.
|
||||||
|
$this->missingClasses[$class] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the currently registered loaders keyed by their corresponding vendor directories.
|
||||||
|
*
|
||||||
|
* @return array<string, self>
|
||||||
|
*/
|
||||||
|
public static function getRegisteredLoaders()
|
||||||
|
{
|
||||||
|
return self::$registeredLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $class
|
||||||
|
* @param string $ext
|
||||||
|
* @return string|false
|
||||||
|
*/
|
||||||
|
private function findFileWithExtension($class, $ext)
|
||||||
|
{
|
||||||
|
// PSR-4 lookup
|
||||||
|
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
|
||||||
|
$first = $class[0];
|
||||||
|
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||||
|
$subPath = $class;
|
||||||
|
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||||
|
$subPath = substr($subPath, 0, $lastPos);
|
||||||
|
$search = $subPath . '\\';
|
||||||
|
if (isset($this->prefixDirsPsr4[$search])) {
|
||||||
|
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||||
|
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||||
|
if (file_exists($file = $dir . $pathEnd)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-4 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 lookup
|
||||||
|
if (false !== $pos = strrpos($class, '\\')) {
|
||||||
|
// namespaced class name
|
||||||
|
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||||
|
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||||
|
} else {
|
||||||
|
// PEAR-like class name
|
||||||
|
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->prefixesPsr0[$first])) {
|
||||||
|
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||||
|
if (0 === strpos($class, $prefix)) {
|
||||||
|
foreach ($dirs as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 fallback dirs
|
||||||
|
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||||
|
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PSR-0 include paths.
|
||||||
|
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private static function initializeIncludeClosure()
|
||||||
|
{
|
||||||
|
if (self::$includeFile !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope isolated include.
|
||||||
|
*
|
||||||
|
* Prevents access to $this/self from included files.
|
||||||
|
*
|
||||||
|
* @param string $file
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
self::$includeFile = \Closure::bind(static function($file) {
|
||||||
|
include $file;
|
||||||
|
}, null, null);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,359 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Composer.
|
||||||
|
*
|
||||||
|
* (c) Nils Adermann <naderman@naderman.de>
|
||||||
|
* Jordi Boggiano <j.boggiano@seld.be>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Composer;
|
||||||
|
|
||||||
|
use Composer\Autoload\ClassLoader;
|
||||||
|
use Composer\Semver\VersionParser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is copied in every Composer installed project and available to all
|
||||||
|
*
|
||||||
|
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions
|
||||||
|
*
|
||||||
|
* To require its presence, you can require `composer-runtime-api ^2.0`
|
||||||
|
*
|
||||||
|
* @final
|
||||||
|
*/
|
||||||
|
class InstalledVersions
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var mixed[]|null
|
||||||
|
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
|
||||||
|
*/
|
||||||
|
private static $installed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool|null
|
||||||
|
*/
|
||||||
|
private static $canGetVendors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array[]
|
||||||
|
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static $installedByVendor = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names which are present, either by being installed, replaced or provided
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackages()
|
||||||
|
{
|
||||||
|
$packages = array();
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
$packages[] = array_keys($installed['versions']);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 === \count($packages)) {
|
||||||
|
return $packages[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all package names with a specific type e.g. 'library'
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
* @return string[]
|
||||||
|
* @psalm-return list<string>
|
||||||
|
*/
|
||||||
|
public static function getInstalledPackagesByType($type)
|
||||||
|
{
|
||||||
|
$packagesByType = array();
|
||||||
|
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
foreach ($installed['versions'] as $name => $package) {
|
||||||
|
if (isset($package['type']) && $package['type'] === $type) {
|
||||||
|
$packagesByType[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $packagesByType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package is installed
|
||||||
|
*
|
||||||
|
* This also returns true if the package name is provided or replaced by another package
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @param bool $includeDevRequirements
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isInstalled($packageName, $includeDevRequirements = true)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (isset($installed['versions'][$packageName])) {
|
||||||
|
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given package satisfies a version constraint
|
||||||
|
*
|
||||||
|
* e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
|
||||||
|
*
|
||||||
|
* Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
|
||||||
|
*
|
||||||
|
* @param VersionParser $parser Install composer/semver to have access to this class and functionality
|
||||||
|
* @param string $packageName
|
||||||
|
* @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function satisfies(VersionParser $parser, $packageName, $constraint)
|
||||||
|
{
|
||||||
|
$constraint = $parser->parseConstraints((string) $constraint);
|
||||||
|
$provided = $parser->parseConstraints(self::getVersionRanges($packageName));
|
||||||
|
|
||||||
|
return $provided->matches($constraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a version constraint representing all the range(s) which are installed for a given package
|
||||||
|
*
|
||||||
|
* It is easier to use this via isInstalled() with the $constraint argument if you need to check
|
||||||
|
* whether a given version of a package is installed, and not just whether it exists
|
||||||
|
*
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string Version constraint usable with composer/semver
|
||||||
|
*/
|
||||||
|
public static function getVersionRanges($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ranges = array();
|
||||||
|
if (isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
$ranges[] = $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('aliases', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('replaced', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
|
||||||
|
}
|
||||||
|
if (array_key_exists('provided', $installed['versions'][$packageName])) {
|
||||||
|
$ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(' || ', $ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
|
||||||
|
*/
|
||||||
|
public static function getPrettyVersion($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['pretty_version'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['pretty_version'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
|
||||||
|
*/
|
||||||
|
public static function getReference($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($installed['versions'][$packageName]['reference'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed['versions'][$packageName]['reference'];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $packageName
|
||||||
|
* @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
|
||||||
|
*/
|
||||||
|
public static function getInstallPath($packageName)
|
||||||
|
{
|
||||||
|
foreach (self::getInstalled() as $installed) {
|
||||||
|
if (!isset($installed['versions'][$packageName])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
|
||||||
|
*/
|
||||||
|
public static function getRootPackage()
|
||||||
|
{
|
||||||
|
$installed = self::getInstalled();
|
||||||
|
|
||||||
|
return $installed[0]['root'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw installed.php data for custom implementations
|
||||||
|
*
|
||||||
|
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}
|
||||||
|
*/
|
||||||
|
public static function getRawData()
|
||||||
|
{
|
||||||
|
@trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
self::$installed = include __DIR__ . '/installed.php';
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the raw data of all installed.php which are currently loaded for custom implementations
|
||||||
|
*
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
public static function getAllRawData()
|
||||||
|
{
|
||||||
|
return self::getInstalled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets you reload the static array from another file
|
||||||
|
*
|
||||||
|
* This is only useful for complex integrations in which a project needs to use
|
||||||
|
* this class but then also needs to execute another project's autoloader in process,
|
||||||
|
* and wants to ensure both projects have access to their version of installed.php.
|
||||||
|
*
|
||||||
|
* A typical case would be PHPUnit, where it would need to make sure it reads all
|
||||||
|
* the data it needs from this class, then call reload() with
|
||||||
|
* `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
|
||||||
|
* the project in which it runs can then also use this class safely, without
|
||||||
|
* interference between PHPUnit's dependencies and the project's dependencies.
|
||||||
|
*
|
||||||
|
* @param array[] $data A vendor/composer/installed.php data set
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data
|
||||||
|
*/
|
||||||
|
public static function reload($data)
|
||||||
|
{
|
||||||
|
self::$installed = $data;
|
||||||
|
self::$installedByVendor = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array[]
|
||||||
|
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
|
||||||
|
*/
|
||||||
|
private static function getInstalled()
|
||||||
|
{
|
||||||
|
if (null === self::$canGetVendors) {
|
||||||
|
self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
|
||||||
|
}
|
||||||
|
|
||||||
|
$installed = array();
|
||||||
|
|
||||||
|
if (self::$canGetVendors) {
|
||||||
|
foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
|
||||||
|
if (isset(self::$installedByVendor[$vendorDir])) {
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir];
|
||||||
|
} elseif (is_file($vendorDir.'/composer/installed.php')) {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require $vendorDir.'/composer/installed.php';
|
||||||
|
$installed[] = self::$installedByVendor[$vendorDir] = $required;
|
||||||
|
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
|
||||||
|
self::$installed = $installed[count($installed) - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === self::$installed) {
|
||||||
|
// only require the installed.php file if this file is loaded from its dumped location,
|
||||||
|
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
|
||||||
|
if (substr(__DIR__, -8, 1) !== 'C') {
|
||||||
|
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */
|
||||||
|
$required = require __DIR__ . '/installed.php';
|
||||||
|
self::$installed = $required;
|
||||||
|
} else {
|
||||||
|
self::$installed = array();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self::$installed !== array()) {
|
||||||
|
$installed[] = self::$installed;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $installed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished
|
||||||
|
to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_classmap.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||||
|
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||||
|
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||||
|
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||||
|
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||||
|
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||||
|
);
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_files.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php',
|
||||||
|
'35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php',
|
||||||
|
'2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
|
||||||
|
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||||
|
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
|
||||||
|
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||||
|
'dc1275c308c5b416beb314b6317daca2' => $vendorDir . '/overtrue/pinyin/src/const.php',
|
||||||
|
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||||
|
'1cfd2761b63b0a29ed23657ea394cb2d' => $vendorDir . '/topthink/think-captcha/src/helper.php',
|
||||||
|
);
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_namespaces.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'),
|
||||||
|
'' => array($baseDir . '/extend'),
|
||||||
|
);
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_psr4.php @generated by Composer
|
||||||
|
|
||||||
|
$vendorDir = dirname(__DIR__);
|
||||||
|
$baseDir = dirname($vendorDir);
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'think\\view\\driver\\' => array($vendorDir . '/topthink/think-view/src'),
|
||||||
|
'think\\trace\\' => array($vendorDir . '/topthink/think-trace/src'),
|
||||||
|
'think\\captcha\\' => array($vendorDir . '/topthink/think-captcha/src'),
|
||||||
|
'think\\app\\' => array($vendorDir . '/topthink/think-multi-app/src'),
|
||||||
|
'think\\' => array($vendorDir . '/topthink/think-helper/src', $vendorDir . '/topthink/think-orm/src', $vendorDir . '/topthink/framework/src/think', $vendorDir . '/topthink/think-filesystem/src', $vendorDir . '/topthink/think-template/src'),
|
||||||
|
'app\\' => array($baseDir . '/app'),
|
||||||
|
'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
|
||||||
|
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
||||||
|
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
|
||||||
|
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
|
||||||
|
'Symfony\\Component\\VarDumper\\' => array($vendorDir . '/symfony/var-dumper'),
|
||||||
|
'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'),
|
||||||
|
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
|
||||||
|
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src', $vendorDir . '/psr/http-factory/src'),
|
||||||
|
'Psr\\Http\\Client\\' => array($vendorDir . '/psr/http-client/src'),
|
||||||
|
'Psr\\Container\\' => array($vendorDir . '/psr/container/src'),
|
||||||
|
'PhpOffice\\PhpSpreadsheet\\' => array($vendorDir . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet'),
|
||||||
|
'PHPMailer\\PHPMailer\\' => array($vendorDir . '/phpmailer/phpmailer/src'),
|
||||||
|
'Overtrue\\Pinyin\\' => array($vendorDir . '/overtrue/pinyin/src'),
|
||||||
|
'MyCLabs\\Enum\\' => array($vendorDir . '/myclabs/php-enum/src'),
|
||||||
|
'Matrix\\' => array($vendorDir . '/markbaker/matrix/classes/src'),
|
||||||
|
'League\\MimeTypeDetection\\' => array($vendorDir . '/league/mime-type-detection/src'),
|
||||||
|
'League\\Flysystem\\' => array($vendorDir . '/league/flysystem/src'),
|
||||||
|
'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
|
||||||
|
'Complex\\' => array($vendorDir . '/markbaker/complex/classes/src'),
|
||||||
|
);
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_real.php @generated by Composer
|
||||||
|
|
||||||
|
class ComposerAutoloaderInitb6df9475fad16a473d4508387130aca7
|
||||||
|
{
|
||||||
|
private static $loader;
|
||||||
|
|
||||||
|
public static function loadClassLoader($class)
|
||||||
|
{
|
||||||
|
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||||
|
require __DIR__ . '/ClassLoader.php';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Composer\Autoload\ClassLoader
|
||||||
|
*/
|
||||||
|
public static function getLoader()
|
||||||
|
{
|
||||||
|
if (null !== self::$loader) {
|
||||||
|
return self::$loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
require __DIR__ . '/platform_check.php';
|
||||||
|
|
||||||
|
spl_autoload_register(array('ComposerAutoloaderInitb6df9475fad16a473d4508387130aca7', 'loadClassLoader'), true, true);
|
||||||
|
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||||
|
spl_autoload_unregister(array('ComposerAutoloaderInitb6df9475fad16a473d4508387130aca7', 'loadClassLoader'));
|
||||||
|
|
||||||
|
require __DIR__ . '/autoload_static.php';
|
||||||
|
call_user_func(\Composer\Autoload\ComposerStaticInitb6df9475fad16a473d4508387130aca7::getInitializer($loader));
|
||||||
|
|
||||||
|
$loader->register(true);
|
||||||
|
|
||||||
|
$filesToLoad = \Composer\Autoload\ComposerStaticInitb6df9475fad16a473d4508387130aca7::$files;
|
||||||
|
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||||
|
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||||
|
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||||
|
|
||||||
|
require $file;
|
||||||
|
}
|
||||||
|
}, null, null);
|
||||||
|
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||||
|
$requireFile($fileIdentifier, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,221 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// autoload_static.php @generated by Composer
|
||||||
|
|
||||||
|
namespace Composer\Autoload;
|
||||||
|
|
||||||
|
class ComposerStaticInitb6df9475fad16a473d4508387130aca7
|
||||||
|
{
|
||||||
|
public static $files = array (
|
||||||
|
'9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php',
|
||||||
|
'35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php',
|
||||||
|
'2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
|
||||||
|
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
|
||||||
|
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
|
||||||
|
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||||
|
'dc1275c308c5b416beb314b6317daca2' => __DIR__ . '/..' . '/overtrue/pinyin/src/const.php',
|
||||||
|
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
|
||||||
|
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixLengthsPsr4 = array (
|
||||||
|
't' =>
|
||||||
|
array (
|
||||||
|
'think\\view\\driver\\' => 18,
|
||||||
|
'think\\trace\\' => 12,
|
||||||
|
'think\\captcha\\' => 14,
|
||||||
|
'think\\app\\' => 10,
|
||||||
|
'think\\' => 6,
|
||||||
|
),
|
||||||
|
'a' =>
|
||||||
|
array (
|
||||||
|
'app\\' => 4,
|
||||||
|
),
|
||||||
|
'Z' =>
|
||||||
|
array (
|
||||||
|
'ZipStream\\' => 10,
|
||||||
|
),
|
||||||
|
'S' =>
|
||||||
|
array (
|
||||||
|
'Symfony\\Polyfill\\Php80\\' => 23,
|
||||||
|
'Symfony\\Polyfill\\Php72\\' => 23,
|
||||||
|
'Symfony\\Polyfill\\Mbstring\\' => 26,
|
||||||
|
'Symfony\\Component\\VarDumper\\' => 28,
|
||||||
|
),
|
||||||
|
'P' =>
|
||||||
|
array (
|
||||||
|
'Psr\\SimpleCache\\' => 16,
|
||||||
|
'Psr\\Log\\' => 8,
|
||||||
|
'Psr\\Http\\Message\\' => 17,
|
||||||
|
'Psr\\Http\\Client\\' => 16,
|
||||||
|
'Psr\\Container\\' => 14,
|
||||||
|
'PhpOffice\\PhpSpreadsheet\\' => 25,
|
||||||
|
'PHPMailer\\PHPMailer\\' => 20,
|
||||||
|
),
|
||||||
|
'O' =>
|
||||||
|
array (
|
||||||
|
'Overtrue\\Pinyin\\' => 16,
|
||||||
|
),
|
||||||
|
'M' =>
|
||||||
|
array (
|
||||||
|
'MyCLabs\\Enum\\' => 13,
|
||||||
|
'Matrix\\' => 7,
|
||||||
|
),
|
||||||
|
'L' =>
|
||||||
|
array (
|
||||||
|
'League\\MimeTypeDetection\\' => 25,
|
||||||
|
'League\\Flysystem\\' => 17,
|
||||||
|
),
|
||||||
|
'F' =>
|
||||||
|
array (
|
||||||
|
'Firebase\\JWT\\' => 13,
|
||||||
|
),
|
||||||
|
'C' =>
|
||||||
|
array (
|
||||||
|
'Complex\\' => 8,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixDirsPsr4 = array (
|
||||||
|
'think\\view\\driver\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/topthink/think-view/src',
|
||||||
|
),
|
||||||
|
'think\\trace\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/topthink/think-trace/src',
|
||||||
|
),
|
||||||
|
'think\\captcha\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/topthink/think-captcha/src',
|
||||||
|
),
|
||||||
|
'think\\app\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/topthink/think-multi-app/src',
|
||||||
|
),
|
||||||
|
'think\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/topthink/think-helper/src',
|
||||||
|
1 => __DIR__ . '/..' . '/topthink/think-orm/src',
|
||||||
|
2 => __DIR__ . '/..' . '/topthink/framework/src/think',
|
||||||
|
3 => __DIR__ . '/..' . '/topthink/think-filesystem/src',
|
||||||
|
4 => __DIR__ . '/..' . '/topthink/think-template/src',
|
||||||
|
),
|
||||||
|
'app\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/../..' . '/app',
|
||||||
|
),
|
||||||
|
'ZipStream\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src',
|
||||||
|
),
|
||||||
|
'Symfony\\Polyfill\\Php80\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
||||||
|
),
|
||||||
|
'Symfony\\Polyfill\\Php72\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
|
||||||
|
),
|
||||||
|
'Symfony\\Polyfill\\Mbstring\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
|
||||||
|
),
|
||||||
|
'Symfony\\Component\\VarDumper\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/symfony/var-dumper',
|
||||||
|
),
|
||||||
|
'Psr\\SimpleCache\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/simple-cache/src',
|
||||||
|
),
|
||||||
|
'Psr\\Log\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
|
||||||
|
),
|
||||||
|
'Psr\\Http\\Message\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/http-message/src',
|
||||||
|
1 => __DIR__ . '/..' . '/psr/http-factory/src',
|
||||||
|
),
|
||||||
|
'Psr\\Http\\Client\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/http-client/src',
|
||||||
|
),
|
||||||
|
'Psr\\Container\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/psr/container/src',
|
||||||
|
),
|
||||||
|
'PhpOffice\\PhpSpreadsheet\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/phpoffice/phpspreadsheet/src/PhpSpreadsheet',
|
||||||
|
),
|
||||||
|
'PHPMailer\\PHPMailer\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/phpmailer/phpmailer/src',
|
||||||
|
),
|
||||||
|
'Overtrue\\Pinyin\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/overtrue/pinyin/src',
|
||||||
|
),
|
||||||
|
'MyCLabs\\Enum\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/myclabs/php-enum/src',
|
||||||
|
),
|
||||||
|
'Matrix\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/markbaker/matrix/classes/src',
|
||||||
|
),
|
||||||
|
'League\\MimeTypeDetection\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/league/mime-type-detection/src',
|
||||||
|
),
|
||||||
|
'League\\Flysystem\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/league/flysystem/src',
|
||||||
|
),
|
||||||
|
'Firebase\\JWT\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
|
||||||
|
),
|
||||||
|
'Complex\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/markbaker/complex/classes/src',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $prefixesPsr0 = array (
|
||||||
|
'H' =>
|
||||||
|
array (
|
||||||
|
'HTMLPurifier' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $fallbackDirsPsr0 = array (
|
||||||
|
0 => __DIR__ . '/../..' . '/extend',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $classMap = array (
|
||||||
|
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||||
|
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||||
|
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||||
|
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||||
|
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||||
|
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function getInitializer(ClassLoader $loader)
|
||||||
|
{
|
||||||
|
return \Closure::bind(function () use ($loader) {
|
||||||
|
$loader->prefixLengthsPsr4 = ComposerStaticInitb6df9475fad16a473d4508387130aca7::$prefixLengthsPsr4;
|
||||||
|
$loader->prefixDirsPsr4 = ComposerStaticInitb6df9475fad16a473d4508387130aca7::$prefixDirsPsr4;
|
||||||
|
$loader->prefixesPsr0 = ComposerStaticInitb6df9475fad16a473d4508387130aca7::$prefixesPsr0;
|
||||||
|
$loader->fallbackDirsPsr0 = ComposerStaticInitb6df9475fad16a473d4508387130aca7::$fallbackDirsPsr0;
|
||||||
|
$loader->classMap = ComposerStaticInitb6df9475fad16a473d4508387130aca7::$classMap;
|
||||||
|
|
||||||
|
}, null, ClassLoader::class);
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,293 @@
|
||||||
|
<?php return array(
|
||||||
|
'root' => array(
|
||||||
|
'name' => 'gougu/dev',
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => NULL,
|
||||||
|
'type' => 'project',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev' => true,
|
||||||
|
),
|
||||||
|
'versions' => array(
|
||||||
|
'ezyang/htmlpurifier' => array(
|
||||||
|
'pretty_version' => 'v4.16.0',
|
||||||
|
'version' => '4.16.0.0',
|
||||||
|
'reference' => '523407fb06eb9e5f3d59889b3978d5bfe94299c8',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../ezyang/htmlpurifier',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'firebase/php-jwt' => array(
|
||||||
|
'pretty_version' => 'v6.8.1',
|
||||||
|
'version' => '6.8.1.0',
|
||||||
|
'reference' => '5dbc8959427416b8ee09a100d7a8588c00fb2e26',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../firebase/php-jwt',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'gougu/dev' => array(
|
||||||
|
'pretty_version' => '1.0.0+no-version-set',
|
||||||
|
'version' => '1.0.0.0',
|
||||||
|
'reference' => NULL,
|
||||||
|
'type' => 'project',
|
||||||
|
'install_path' => __DIR__ . '/../../',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'league/flysystem' => array(
|
||||||
|
'pretty_version' => '2.5.0',
|
||||||
|
'version' => '2.5.0.0',
|
||||||
|
'reference' => '8aaffb653c5777781b0f7f69a5d937baf7ab6cdb',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../league/flysystem',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'league/mime-type-detection' => array(
|
||||||
|
'pretty_version' => '1.13.0',
|
||||||
|
'version' => '1.13.0.0',
|
||||||
|
'reference' => 'a6dfb1194a2946fcdc1f38219445234f65b35c96',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../league/mime-type-detection',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'maennchen/zipstream-php' => array(
|
||||||
|
'pretty_version' => '2.4.0',
|
||||||
|
'version' => '2.4.0.0',
|
||||||
|
'reference' => '3fa72e4c71a43f9e9118752a5c90e476a8dc9eb3',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../maennchen/zipstream-php',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'markbaker/complex' => array(
|
||||||
|
'pretty_version' => '3.0.2',
|
||||||
|
'version' => '3.0.2.0',
|
||||||
|
'reference' => '95c56caa1cf5c766ad6d65b6344b807c1e8405b9',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../markbaker/complex',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'markbaker/matrix' => array(
|
||||||
|
'pretty_version' => '3.0.1',
|
||||||
|
'version' => '3.0.1.0',
|
||||||
|
'reference' => '728434227fe21be27ff6d86621a1b13107a2562c',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../markbaker/matrix',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'myclabs/php-enum' => array(
|
||||||
|
'pretty_version' => '1.8.4',
|
||||||
|
'version' => '1.8.4.0',
|
||||||
|
'reference' => 'a867478eae49c9f59ece437ae7f9506bfaa27483',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../myclabs/php-enum',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'overtrue/pinyin' => array(
|
||||||
|
'pretty_version' => '4.1.0',
|
||||||
|
'version' => '4.1.0.0',
|
||||||
|
'reference' => '4d0fb4f27f0c79e81c9489e0c0ae4a4f8837eae7',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../overtrue/pinyin',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'phpmailer/phpmailer' => array(
|
||||||
|
'pretty_version' => 'v6.8.1',
|
||||||
|
'version' => '6.8.1.0',
|
||||||
|
'reference' => 'e88da8d679acc3824ff231fdc553565b802ac016',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../phpmailer/phpmailer',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'phpoffice/phpspreadsheet' => array(
|
||||||
|
'pretty_version' => '1.29.0',
|
||||||
|
'version' => '1.29.0.0',
|
||||||
|
'reference' => 'fde2ccf55eaef7e86021ff1acce26479160a0fa0',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../phpoffice/phpspreadsheet',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/container' => array(
|
||||||
|
'pretty_version' => '1.1.2',
|
||||||
|
'version' => '1.1.2.0',
|
||||||
|
'reference' => '513e0666f7216c7459170d56df27dfcefe1689ea',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/container',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-client' => array(
|
||||||
|
'pretty_version' => '1.0.3',
|
||||||
|
'version' => '1.0.3.0',
|
||||||
|
'reference' => 'bb5906edc1c324c9a05aa0873d40117941e5fa90',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-client',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-factory' => array(
|
||||||
|
'pretty_version' => '1.0.2',
|
||||||
|
'version' => '1.0.2.0',
|
||||||
|
'reference' => 'e616d01114759c4c489f93b099585439f795fe35',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-factory',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/http-message' => array(
|
||||||
|
'pretty_version' => '1.1',
|
||||||
|
'version' => '1.1.0.0',
|
||||||
|
'reference' => 'cb6ce4845ce34a8ad9e68117c10ee90a29919eba',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/http-message',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/log' => array(
|
||||||
|
'pretty_version' => '1.1.4',
|
||||||
|
'version' => '1.1.4.0',
|
||||||
|
'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/log',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'psr/simple-cache' => array(
|
||||||
|
'pretty_version' => '1.0.1',
|
||||||
|
'version' => '1.0.1.0',
|
||||||
|
'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../psr/simple-cache',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'symfony/polyfill-mbstring' => array(
|
||||||
|
'pretty_version' => 'v1.28.0',
|
||||||
|
'version' => '1.28.0.0',
|
||||||
|
'reference' => '42292d99c55abe617799667f454222c54c60e229',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/polyfill-mbstring',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => true,
|
||||||
|
),
|
||||||
|
'symfony/polyfill-php72' => array(
|
||||||
|
'pretty_version' => 'v1.28.0',
|
||||||
|
'version' => '1.28.0.0',
|
||||||
|
'reference' => '70f4aebd92afca2f865444d30a4d2151c13c3179',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/polyfill-php72',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => true,
|
||||||
|
),
|
||||||
|
'symfony/polyfill-php80' => array(
|
||||||
|
'pretty_version' => 'v1.28.0',
|
||||||
|
'version' => '1.28.0.0',
|
||||||
|
'reference' => '6caa57379c4aec19c0a12a38b59b26487dcfe4b5',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => true,
|
||||||
|
),
|
||||||
|
'symfony/var-dumper' => array(
|
||||||
|
'pretty_version' => 'v4.4.47',
|
||||||
|
'version' => '4.4.47.0',
|
||||||
|
'reference' => '1069c7a3fca74578022fab6f81643248d02f8e63',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../symfony/var-dumper',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => true,
|
||||||
|
),
|
||||||
|
'topthink/framework' => array(
|
||||||
|
'pretty_version' => 'v6.1.4',
|
||||||
|
'version' => '6.1.4.0',
|
||||||
|
'reference' => '66eb9cf4d627df12911344cd328faf9bb596bf2c',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/framework',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'topthink/think-captcha' => array(
|
||||||
|
'pretty_version' => 'v3.0.9',
|
||||||
|
'version' => '3.0.9.0',
|
||||||
|
'reference' => 'b1ef360670578214edeebcf824aaf6ab7ee0528b',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-captcha',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'topthink/think-filesystem' => array(
|
||||||
|
'pretty_version' => 'v2.0.2',
|
||||||
|
'version' => '2.0.2.0',
|
||||||
|
'reference' => 'c08503232fcae0c3c7fefae5e6b5c841ffe09f2f',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-filesystem',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'topthink/think-helper' => array(
|
||||||
|
'pretty_version' => 'v3.1.6',
|
||||||
|
'version' => '3.1.6.0',
|
||||||
|
'reference' => '769acbe50a4274327162f9c68ec2e89a38eb2aff',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-helper',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'topthink/think-multi-app' => array(
|
||||||
|
'pretty_version' => 'v1.0.17',
|
||||||
|
'version' => '1.0.17.0',
|
||||||
|
'reference' => '4055a6187296ac16c0bc7bbab4ed5d92f82f791c',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-multi-app',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'topthink/think-orm' => array(
|
||||||
|
'pretty_version' => 'v2.0.61',
|
||||||
|
'version' => '2.0.61.0',
|
||||||
|
'reference' => '10528ebf4a5106b19c3bac9c6deae7a67ff49de6',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-orm',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'topthink/think-template' => array(
|
||||||
|
'pretty_version' => 'v2.0.9',
|
||||||
|
'version' => '2.0.9.0',
|
||||||
|
'reference' => '6d25642ae0e306166742fd7073dc7a159e18073c',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-template',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
'topthink/think-trace' => array(
|
||||||
|
'pretty_version' => 'v1.6',
|
||||||
|
'version' => '1.6.0.0',
|
||||||
|
'reference' => '136cd5d97e8bdb780e4b5c1637c588ed7ca3e142',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-trace',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => true,
|
||||||
|
),
|
||||||
|
'topthink/think-view' => array(
|
||||||
|
'pretty_version' => 'v1.0.14',
|
||||||
|
'version' => '1.0.14.0',
|
||||||
|
'reference' => 'edce0ae2c9551ab65f9e94a222604b0dead3576d',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../topthink/think-view',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// platform_check.php @generated by Composer
|
||||||
|
|
||||||
|
$issues = array();
|
||||||
|
|
||||||
|
if (!(PHP_VERSION_ID >= 80000)) {
|
||||||
|
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.0". You are running ' . PHP_VERSION . '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($issues) {
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('HTTP/1.1 500 Internal Server Error');
|
||||||
|
}
|
||||||
|
if (!ini_get('display_errors')) {
|
||||||
|
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
|
||||||
|
fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
|
||||||
|
} elseif (!headers_sent()) {
|
||||||
|
echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trigger_error(
|
||||||
|
'Composer detected issues in your platform: ' . implode(' ', $issues),
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
# [4.16.0](https://github.com/ezyang/htmlpurifier/compare/v4.15.0...v4.16.0) (2022-09-18)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add semantic release ([#307](https://github.com/ezyang/htmlpurifier/issues/307)) ([db31243](https://github.com/ezyang/htmlpurifier/commit/db312435cb9d8d73395f75f9642a43ba6de5e903)), closes [#322](https://github.com/ezyang/htmlpurifier/issues/322) [#323](https://github.com/ezyang/htmlpurifier/issues/323) [#326](https://github.com/ezyang/htmlpurifier/issues/326) [#327](https://github.com/ezyang/htmlpurifier/issues/327) [#328](https://github.com/ezyang/htmlpurifier/issues/328) [#329](https://github.com/ezyang/htmlpurifier/issues/329) [#330](https://github.com/ezyang/htmlpurifier/issues/330) [#331](https://github.com/ezyang/htmlpurifier/issues/331) [#332](https://github.com/ezyang/htmlpurifier/issues/332) [#333](https://github.com/ezyang/htmlpurifier/issues/333) [#337](https://github.com/ezyang/htmlpurifier/issues/337) [#335](https://github.com/ezyang/htmlpurifier/issues/335) [ezyang/htmlpurifier#334](https://github.com/ezyang/htmlpurifier/issues/334) [#336](https://github.com/ezyang/htmlpurifier/issues/336) [#338](https://github.com/ezyang/htmlpurifier/issues/338)
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
CREDITS
|
||||||
|
|
||||||
|
Almost everything written by Edward Z. Yang (Ambush Commander). Lots of thanks
|
||||||
|
to the DevNetwork Community for their help (see docs/ref-devnetwork.html for
|
||||||
|
more details), Feyd especially (namely IPv6 and optimization). Thanks to RSnake
|
||||||
|
for letting me package his fantastic XSS cheatsheet for a smoketest.
|
||||||
|
|
||||||
|
vim: et sw=4 sts=4
|
|
@ -0,0 +1,504 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
vim: et sw=4 sts=4
|
|
@ -0,0 +1,29 @@
|
||||||
|
HTML Purifier [![Build Status](https://github.com/ezyang/htmlpurifier/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ezyang/htmlpurifier/actions/workflows/ci.yml)
|
||||||
|
=============
|
||||||
|
|
||||||
|
HTML Purifier is an HTML filtering solution that uses a unique combination
|
||||||
|
of robust whitelists and aggressive parsing to ensure that not only are
|
||||||
|
XSS attacks thwarted, but the resulting HTML is standards compliant.
|
||||||
|
|
||||||
|
HTML Purifier is oriented towards richly formatted documents from
|
||||||
|
untrusted sources that require CSS and a full tag-set. This library can
|
||||||
|
be configured to accept a more restrictive set of tags, but it won't be
|
||||||
|
as efficient as more bare-bones parsers. It will, however, do the job
|
||||||
|
right, which may be more important.
|
||||||
|
|
||||||
|
Places to go:
|
||||||
|
|
||||||
|
* See INSTALL for a quick installation guide
|
||||||
|
* See docs/ for developer-oriented documentation, code examples and
|
||||||
|
an in-depth installation guide.
|
||||||
|
* See WYSIWYG for information on editors like TinyMCE and FCKeditor
|
||||||
|
|
||||||
|
HTML Purifier can be found on the web at: [http://htmlpurifier.org/](http://htmlpurifier.org/)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Package available on [Composer](https://packagist.org/packages/ezyang/htmlpurifier).
|
||||||
|
|
||||||
|
If you're using Composer to manage dependencies, you can use
|
||||||
|
|
||||||
|
$ composer require ezyang/htmlpurifier
|
|
@ -0,0 +1 @@
|
||||||
|
4.15.0
|
|
@ -0,0 +1,44 @@
|
||||||
|
{
|
||||||
|
"name": "ezyang/htmlpurifier",
|
||||||
|
"description": "Standards compliant HTML filter written in PHP",
|
||||||
|
"type": "library",
|
||||||
|
"keywords": ["html"],
|
||||||
|
"homepage": "http://htmlpurifier.org/",
|
||||||
|
"license": "LGPL-2.1-or-later",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Edward Z. Yang",
|
||||||
|
"email": "admin@htmlpurifier.org",
|
||||||
|
"homepage": "http://ezyang.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"cerdic/css-tidy": "^1.7 || ^2.0",
|
||||||
|
"simpletest/simpletest": "dev-master"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-0": { "HTMLPurifier": "library/" },
|
||||||
|
"files": ["library/HTMLPurifier.composer.php"],
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/library/HTMLPurifier/Language/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
|
||||||
|
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
|
||||||
|
"ext-bcmath": "Used for unit conversion and imagecrash protection",
|
||||||
|
"ext-tidy": "Used for pretty-printing HTML"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"sort-packages": true
|
||||||
|
},
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/ezyang/simpletest.git"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a stub include that automatically configures the include path.
|
||||||
|
*/
|
||||||
|
|
||||||
|
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||||
|
require_once 'HTMLPurifier/Bootstrap.php';
|
||||||
|
require_once 'HTMLPurifier.autoload.php';
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Legacy autoloader for systems lacking spl_autoload_register
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
spl_autoload_register(function($class)
|
||||||
|
{
|
||||||
|
return HTMLPurifier_Bootstrap::autoload($class);
|
||||||
|
});
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Convenience file that registers autoload handler for HTML Purifier.
|
||||||
|
* It also does some sanity checks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {
|
||||||
|
// We need unregister for our pre-registering functionality
|
||||||
|
HTMLPurifier_Bootstrap::registerAutoload();
|
||||||
|
if (function_exists('__autoload')) {
|
||||||
|
// Be polite and ensure that userland autoload gets retained
|
||||||
|
spl_autoload_register('__autoload');
|
||||||
|
}
|
||||||
|
} elseif (!function_exists('__autoload')) {
|
||||||
|
require dirname(__FILE__) . '/HTMLPurifier.autoload-legacy.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
// phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.zend_ze1_compatibility_modeRemoved
|
||||||
|
if (ini_get('zend.ze1_compatibility_mode')) {
|
||||||
|
trigger_error("HTML Purifier is not compatible with zend.ze1_compatibility_mode; please turn it off", E_USER_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?php
|
||||||
|
if (!defined('HTMLPURIFIER_PREFIX')) {
|
||||||
|
define('HTMLPURIFIER_PREFIX', dirname(__FILE__));
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Defines a function wrapper for HTML Purifier for quick use.
|
||||||
|
* @note ''HTMLPurifier()'' is NOT the same as ''new HTMLPurifier()''
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purify HTML.
|
||||||
|
* @param string $html String HTML to purify
|
||||||
|
* @param mixed $config Configuration to use, can be any value accepted by
|
||||||
|
* HTMLPurifier_Config::create()
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function HTMLPurifier($html, $config = null)
|
||||||
|
{
|
||||||
|
static $purifier = false;
|
||||||
|
if (!$purifier) {
|
||||||
|
$purifier = new HTMLPurifier();
|
||||||
|
}
|
||||||
|
return $purifier->purify($html, $config);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,235 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* This file was auto-generated by generate-includes.php and includes all of
|
||||||
|
* the core files required by HTML Purifier. Use this if performance is a
|
||||||
|
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
|
||||||
|
* FILE, changes will be overwritten the next time the script is run.
|
||||||
|
*
|
||||||
|
* @version 4.15.0
|
||||||
|
*
|
||||||
|
* @warning
|
||||||
|
* You must *not* include any other HTML Purifier files before this file,
|
||||||
|
* because 'require' not 'require_once' is used.
|
||||||
|
*
|
||||||
|
* @warning
|
||||||
|
* This file requires that the include path contains the HTML Purifier
|
||||||
|
* library directory; this is not auto-set.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require 'HTMLPurifier.php';
|
||||||
|
require 'HTMLPurifier/Arborize.php';
|
||||||
|
require 'HTMLPurifier/AttrCollections.php';
|
||||||
|
require 'HTMLPurifier/AttrDef.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform.php';
|
||||||
|
require 'HTMLPurifier/AttrTypes.php';
|
||||||
|
require 'HTMLPurifier/AttrValidator.php';
|
||||||
|
require 'HTMLPurifier/Bootstrap.php';
|
||||||
|
require 'HTMLPurifier/Definition.php';
|
||||||
|
require 'HTMLPurifier/CSSDefinition.php';
|
||||||
|
require 'HTMLPurifier/ChildDef.php';
|
||||||
|
require 'HTMLPurifier/Config.php';
|
||||||
|
require 'HTMLPurifier/ConfigSchema.php';
|
||||||
|
require 'HTMLPurifier/ContentSets.php';
|
||||||
|
require 'HTMLPurifier/Context.php';
|
||||||
|
require 'HTMLPurifier/DefinitionCache.php';
|
||||||
|
require 'HTMLPurifier/DefinitionCacheFactory.php';
|
||||||
|
require 'HTMLPurifier/Doctype.php';
|
||||||
|
require 'HTMLPurifier/DoctypeRegistry.php';
|
||||||
|
require 'HTMLPurifier/ElementDef.php';
|
||||||
|
require 'HTMLPurifier/Encoder.php';
|
||||||
|
require 'HTMLPurifier/EntityLookup.php';
|
||||||
|
require 'HTMLPurifier/EntityParser.php';
|
||||||
|
require 'HTMLPurifier/ErrorCollector.php';
|
||||||
|
require 'HTMLPurifier/ErrorStruct.php';
|
||||||
|
require 'HTMLPurifier/Exception.php';
|
||||||
|
require 'HTMLPurifier/Filter.php';
|
||||||
|
require 'HTMLPurifier/Generator.php';
|
||||||
|
require 'HTMLPurifier/HTMLDefinition.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule.php';
|
||||||
|
require 'HTMLPurifier/HTMLModuleManager.php';
|
||||||
|
require 'HTMLPurifier/IDAccumulator.php';
|
||||||
|
require 'HTMLPurifier/Injector.php';
|
||||||
|
require 'HTMLPurifier/Language.php';
|
||||||
|
require 'HTMLPurifier/LanguageFactory.php';
|
||||||
|
require 'HTMLPurifier/Length.php';
|
||||||
|
require 'HTMLPurifier/Lexer.php';
|
||||||
|
require 'HTMLPurifier/Node.php';
|
||||||
|
require 'HTMLPurifier/PercentEncoder.php';
|
||||||
|
require 'HTMLPurifier/PropertyList.php';
|
||||||
|
require 'HTMLPurifier/PropertyListIterator.php';
|
||||||
|
require 'HTMLPurifier/Queue.php';
|
||||||
|
require 'HTMLPurifier/Strategy.php';
|
||||||
|
require 'HTMLPurifier/StringHash.php';
|
||||||
|
require 'HTMLPurifier/StringHashParser.php';
|
||||||
|
require 'HTMLPurifier/TagTransform.php';
|
||||||
|
require 'HTMLPurifier/Token.php';
|
||||||
|
require 'HTMLPurifier/TokenFactory.php';
|
||||||
|
require 'HTMLPurifier/URI.php';
|
||||||
|
require 'HTMLPurifier/URIDefinition.php';
|
||||||
|
require 'HTMLPurifier/URIFilter.php';
|
||||||
|
require 'HTMLPurifier/URIParser.php';
|
||||||
|
require 'HTMLPurifier/URIScheme.php';
|
||||||
|
require 'HTMLPurifier/URISchemeRegistry.php';
|
||||||
|
require 'HTMLPurifier/UnitConverter.php';
|
||||||
|
require 'HTMLPurifier/VarParser.php';
|
||||||
|
require 'HTMLPurifier/VarParserException.php';
|
||||||
|
require 'HTMLPurifier/Zipper.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/Clone.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/Enum.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/Integer.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/Lang.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/Switch.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/Text.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/URI.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Number.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Background.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Border.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Color.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Font.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Length.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/CSS/URI.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/Class.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/Color.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/ContentEditable.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/ID.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/Length.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/URI/Email.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/URI/Host.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||||
|
require 'HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Background.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/BdoDir.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/BgColor.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Border.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Input.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Lang.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Length.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Name.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/NameSync.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Nofollow.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/SafeObject.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/SafeParam.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||||
|
require 'HTMLPurifier/AttrTransform/Textarea.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/Chameleon.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/Custom.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/Empty.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/List.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/Required.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/Optional.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||||
|
require 'HTMLPurifier/ChildDef/Table.php';
|
||||||
|
require 'HTMLPurifier/DefinitionCache/Decorator.php';
|
||||||
|
require 'HTMLPurifier/DefinitionCache/Null.php';
|
||||||
|
require 'HTMLPurifier/DefinitionCache/Serializer.php';
|
||||||
|
require 'HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||||
|
require 'HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Bdo.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Edit.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Forms.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Hypertext.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Iframe.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Image.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Legacy.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/List.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Name.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Nofollow.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Object.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Presentation.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Proprietary.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Ruby.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/SafeObject.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Scripting.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tables.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Target.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Text.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tidy.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tidy/Name.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||||
|
require 'HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||||
|
require 'HTMLPurifier/Injector/AutoParagraph.php';
|
||||||
|
require 'HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||||
|
require 'HTMLPurifier/Injector/Linkify.php';
|
||||||
|
require 'HTMLPurifier/Injector/PurifierLinkify.php';
|
||||||
|
require 'HTMLPurifier/Injector/RemoveEmpty.php';
|
||||||
|
require 'HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||||
|
require 'HTMLPurifier/Injector/SafeObject.php';
|
||||||
|
require 'HTMLPurifier/Lexer/DOMLex.php';
|
||||||
|
require 'HTMLPurifier/Lexer/DirectLex.php';
|
||||||
|
require 'HTMLPurifier/Node/Comment.php';
|
||||||
|
require 'HTMLPurifier/Node/Element.php';
|
||||||
|
require 'HTMLPurifier/Node/Text.php';
|
||||||
|
require 'HTMLPurifier/Strategy/Composite.php';
|
||||||
|
require 'HTMLPurifier/Strategy/Core.php';
|
||||||
|
require 'HTMLPurifier/Strategy/FixNesting.php';
|
||||||
|
require 'HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||||
|
require 'HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||||
|
require 'HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||||
|
require 'HTMLPurifier/TagTransform/Font.php';
|
||||||
|
require 'HTMLPurifier/TagTransform/Simple.php';
|
||||||
|
require 'HTMLPurifier/Token/Comment.php';
|
||||||
|
require 'HTMLPurifier/Token/Tag.php';
|
||||||
|
require 'HTMLPurifier/Token/Empty.php';
|
||||||
|
require 'HTMLPurifier/Token/End.php';
|
||||||
|
require 'HTMLPurifier/Token/Start.php';
|
||||||
|
require 'HTMLPurifier/Token/Text.php';
|
||||||
|
require 'HTMLPurifier/URIFilter/DisableExternal.php';
|
||||||
|
require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||||
|
require 'HTMLPurifier/URIFilter/DisableResources.php';
|
||||||
|
require 'HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||||
|
require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||||
|
require 'HTMLPurifier/URIFilter/Munge.php';
|
||||||
|
require 'HTMLPurifier/URIFilter/SafeIframe.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/data.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/file.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/ftp.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/http.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/https.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/mailto.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/news.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/nntp.php';
|
||||||
|
require 'HTMLPurifier/URIScheme/tel.php';
|
||||||
|
require 'HTMLPurifier/VarParser/Flexible.php';
|
||||||
|
require 'HTMLPurifier/VarParser/Native.php';
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Emulation layer for code that used kses(), substituting in HTML Purifier.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__FILE__) . '/HTMLPurifier.auto.php';
|
||||||
|
|
||||||
|
function kses($string, $allowed_html, $allowed_protocols = null)
|
||||||
|
{
|
||||||
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
|
$allowed_elements = array();
|
||||||
|
$allowed_attributes = array();
|
||||||
|
foreach ($allowed_html as $element => $attributes) {
|
||||||
|
$allowed_elements[$element] = true;
|
||||||
|
foreach ($attributes as $attribute => $x) {
|
||||||
|
$allowed_attributes["$element.$attribute"] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$config->set('HTML.AllowedElements', $allowed_elements);
|
||||||
|
$config->set('HTML.AllowedAttributes', $allowed_attributes);
|
||||||
|
if ($allowed_protocols !== null) {
|
||||||
|
$config->set('URI.AllowedSchemes', $allowed_protocols);
|
||||||
|
}
|
||||||
|
$purifier = new HTMLPurifier($config);
|
||||||
|
return $purifier->purify($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Convenience stub file that adds HTML Purifier's library file to the path
|
||||||
|
* without any other side-effects.
|
||||||
|
*/
|
||||||
|
|
||||||
|
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,297 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*! @mainpage
|
||||||
|
*
|
||||||
|
* HTML Purifier is an HTML filter that will take an arbitrary snippet of
|
||||||
|
* HTML and rigorously test, validate and filter it into a version that
|
||||||
|
* is safe for output onto webpages. It achieves this by:
|
||||||
|
*
|
||||||
|
* -# Lexing (parsing into tokens) the document,
|
||||||
|
* -# Executing various strategies on the tokens:
|
||||||
|
* -# Removing all elements not in the whitelist,
|
||||||
|
* -# Making the tokens well-formed,
|
||||||
|
* -# Fixing the nesting of the nodes, and
|
||||||
|
* -# Validating attributes of the nodes; and
|
||||||
|
* -# Generating HTML from the purified tokens.
|
||||||
|
*
|
||||||
|
* However, most users will only need to interface with the HTMLPurifier
|
||||||
|
* and HTMLPurifier_Config.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
HTML Purifier 4.15.0 - Standards Compliant HTML Filtering
|
||||||
|
Copyright (C) 2006-2008 Edward Z. Yang
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Facade that coordinates HTML Purifier's subsystems in order to purify HTML.
|
||||||
|
*
|
||||||
|
* @note There are several points in which configuration can be specified
|
||||||
|
* for HTML Purifier. The precedence of these (from lowest to
|
||||||
|
* highest) is as follows:
|
||||||
|
* -# Instance: new HTMLPurifier($config)
|
||||||
|
* -# Invocation: purify($html, $config)
|
||||||
|
* These configurations are entirely independent of each other and
|
||||||
|
* are *not* merged (this behavior may change in the future).
|
||||||
|
*
|
||||||
|
* @todo We need an easier way to inject strategies using the configuration
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version of HTML Purifier.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
public $version = '4.15.0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constant with version of HTML Purifier.
|
||||||
|
*/
|
||||||
|
const VERSION = '4.15.0';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global configuration object.
|
||||||
|
* @type HTMLPurifier_Config
|
||||||
|
*/
|
||||||
|
public $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of extra filter objects to run on HTML,
|
||||||
|
* for backwards compatibility.
|
||||||
|
* @type HTMLPurifier_Filter[]
|
||||||
|
*/
|
||||||
|
private $filters = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single instance of HTML Purifier.
|
||||||
|
* @type HTMLPurifier
|
||||||
|
*/
|
||||||
|
private static $instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_Strategy_Core
|
||||||
|
*/
|
||||||
|
protected $strategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_Generator
|
||||||
|
*/
|
||||||
|
protected $generator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resultant context of last run purification.
|
||||||
|
* Is an array of contexts if the last called method was purifyArray().
|
||||||
|
* @type HTMLPurifier_Context
|
||||||
|
*/
|
||||||
|
public $context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the purifier.
|
||||||
|
*
|
||||||
|
* @param HTMLPurifier_Config|mixed $config Optional HTMLPurifier_Config object
|
||||||
|
* for all instances of the purifier, if omitted, a default
|
||||||
|
* configuration is supplied (which can be overridden on a
|
||||||
|
* per-use basis).
|
||||||
|
* The parameter can also be any type that
|
||||||
|
* HTMLPurifier_Config::create() supports.
|
||||||
|
*/
|
||||||
|
public function __construct($config = null)
|
||||||
|
{
|
||||||
|
$this->config = HTMLPurifier_Config::create($config);
|
||||||
|
$this->strategy = new HTMLPurifier_Strategy_Core();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a filter to process the output. First come first serve
|
||||||
|
*
|
||||||
|
* @param HTMLPurifier_Filter $filter HTMLPurifier_Filter object
|
||||||
|
*/
|
||||||
|
public function addFilter($filter)
|
||||||
|
{
|
||||||
|
trigger_error(
|
||||||
|
'HTMLPurifier->addFilter() is deprecated, use configuration directives' .
|
||||||
|
' in the Filter namespace or Filter.Custom',
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
$this->filters[] = $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters an HTML snippet/document to be XSS-free and standards-compliant.
|
||||||
|
*
|
||||||
|
* @param string $html String of HTML to purify
|
||||||
|
* @param HTMLPurifier_Config $config Config object for this operation,
|
||||||
|
* if omitted, defaults to the config object specified during this
|
||||||
|
* object's construction. The parameter can also be any type
|
||||||
|
* that HTMLPurifier_Config::create() supports.
|
||||||
|
*
|
||||||
|
* @return string Purified HTML
|
||||||
|
*/
|
||||||
|
public function purify($html, $config = null)
|
||||||
|
{
|
||||||
|
// :TODO: make the config merge in, instead of replace
|
||||||
|
$config = $config ? HTMLPurifier_Config::create($config) : $this->config;
|
||||||
|
|
||||||
|
// implementation is partially environment dependant, partially
|
||||||
|
// configuration dependant
|
||||||
|
$lexer = HTMLPurifier_Lexer::create($config);
|
||||||
|
|
||||||
|
$context = new HTMLPurifier_Context();
|
||||||
|
|
||||||
|
// setup HTML generator
|
||||||
|
$this->generator = new HTMLPurifier_Generator($config, $context);
|
||||||
|
$context->register('Generator', $this->generator);
|
||||||
|
|
||||||
|
// set up global context variables
|
||||||
|
if ($config->get('Core.CollectErrors')) {
|
||||||
|
// may get moved out if other facilities use it
|
||||||
|
$language_factory = HTMLPurifier_LanguageFactory::instance();
|
||||||
|
$language = $language_factory->create($config, $context);
|
||||||
|
$context->register('Locale', $language);
|
||||||
|
|
||||||
|
$error_collector = new HTMLPurifier_ErrorCollector($context);
|
||||||
|
$context->register('ErrorCollector', $error_collector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup id_accumulator context, necessary due to the fact that
|
||||||
|
// AttrValidator can be called from many places
|
||||||
|
$id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
|
||||||
|
$context->register('IDAccumulator', $id_accumulator);
|
||||||
|
|
||||||
|
$html = HTMLPurifier_Encoder::convertToUTF8($html, $config, $context);
|
||||||
|
|
||||||
|
// setup filters
|
||||||
|
$filter_flags = $config->getBatch('Filter');
|
||||||
|
$custom_filters = $filter_flags['Custom'];
|
||||||
|
unset($filter_flags['Custom']);
|
||||||
|
$filters = array();
|
||||||
|
foreach ($filter_flags as $filter => $flag) {
|
||||||
|
if (!$flag) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strpos($filter, '.') !== false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$class = "HTMLPurifier_Filter_$filter";
|
||||||
|
$filters[] = new $class;
|
||||||
|
}
|
||||||
|
foreach ($custom_filters as $filter) {
|
||||||
|
// maybe "HTMLPurifier_Filter_$filter", but be consistent with AutoFormat
|
||||||
|
$filters[] = $filter;
|
||||||
|
}
|
||||||
|
$filters = array_merge($filters, $this->filters);
|
||||||
|
// maybe prepare(), but later
|
||||||
|
|
||||||
|
for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) {
|
||||||
|
$html = $filters[$i]->preFilter($html, $config, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
// purified HTML
|
||||||
|
$html =
|
||||||
|
$this->generator->generateFromTokens(
|
||||||
|
// list of tokens
|
||||||
|
$this->strategy->execute(
|
||||||
|
// list of un-purified tokens
|
||||||
|
$lexer->tokenizeHTML(
|
||||||
|
// un-purified HTML
|
||||||
|
$html,
|
||||||
|
$config,
|
||||||
|
$context
|
||||||
|
),
|
||||||
|
$config,
|
||||||
|
$context
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
for ($i = $filter_size - 1; $i >= 0; $i--) {
|
||||||
|
$html = $filters[$i]->postFilter($html, $config, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
$html = HTMLPurifier_Encoder::convertFromUTF8($html, $config, $context);
|
||||||
|
$this->context =& $context;
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters an array of HTML snippets
|
||||||
|
*
|
||||||
|
* @param string[] $array_of_html Array of html snippets
|
||||||
|
* @param HTMLPurifier_Config $config Optional config object for this operation.
|
||||||
|
* See HTMLPurifier::purify() for more details.
|
||||||
|
*
|
||||||
|
* @return string[] Array of purified HTML
|
||||||
|
*/
|
||||||
|
public function purifyArray($array_of_html, $config = null)
|
||||||
|
{
|
||||||
|
$context_array = array();
|
||||||
|
$array = array();
|
||||||
|
foreach($array_of_html as $key=>$value){
|
||||||
|
if (is_array($value)) {
|
||||||
|
$array[$key] = $this->purifyArray($value, $config);
|
||||||
|
} else {
|
||||||
|
$array[$key] = $this->purify($value, $config);
|
||||||
|
}
|
||||||
|
$context_array[$key] = $this->context;
|
||||||
|
}
|
||||||
|
$this->context = $context_array;
|
||||||
|
return $array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton for enforcing just one HTML Purifier in your system
|
||||||
|
*
|
||||||
|
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||||
|
* HTMLPurifier instance to overload singleton with,
|
||||||
|
* or HTMLPurifier_Config instance to configure the
|
||||||
|
* generated version with.
|
||||||
|
*
|
||||||
|
* @return HTMLPurifier
|
||||||
|
*/
|
||||||
|
public static function instance($prototype = null)
|
||||||
|
{
|
||||||
|
if (!self::$instance || $prototype) {
|
||||||
|
if ($prototype instanceof HTMLPurifier) {
|
||||||
|
self::$instance = $prototype;
|
||||||
|
} elseif ($prototype) {
|
||||||
|
self::$instance = new HTMLPurifier($prototype);
|
||||||
|
} else {
|
||||||
|
self::$instance = new HTMLPurifier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton for enforcing just one HTML Purifier in your system
|
||||||
|
*
|
||||||
|
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||||
|
* HTMLPurifier instance to overload singleton with,
|
||||||
|
* or HTMLPurifier_Config instance to configure the
|
||||||
|
* generated version with.
|
||||||
|
*
|
||||||
|
* @return HTMLPurifier
|
||||||
|
* @note Backwards compatibility, see instance()
|
||||||
|
*/
|
||||||
|
public static function getInstance($prototype = null)
|
||||||
|
{
|
||||||
|
return HTMLPurifier::instance($prototype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,229 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* This file was auto-generated by generate-includes.php and includes all of
|
||||||
|
* the core files required by HTML Purifier. This is a convenience stub that
|
||||||
|
* includes all files using dirname(__FILE__) and require_once. PLEASE DO NOT
|
||||||
|
* EDIT THIS FILE, changes will be overwritten the next time the script is run.
|
||||||
|
*
|
||||||
|
* Changes to include_path are not necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$__dir = dirname(__FILE__);
|
||||||
|
|
||||||
|
require_once $__dir . '/HTMLPurifier.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Arborize.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrCollections.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTypes.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrValidator.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Bootstrap.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Definition.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/CSSDefinition.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Config.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ConfigSchema.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ContentSets.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Context.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DefinitionCache.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DefinitionCacheFactory.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Doctype.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DoctypeRegistry.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ElementDef.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Encoder.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/EntityLookup.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/EntityParser.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ErrorCollector.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ErrorStruct.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Exception.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Filter.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Generator.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLDefinition.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModuleManager.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/IDAccumulator.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Language.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Length.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Lexer.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Node.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/PropertyList.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/PropertyListIterator.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Queue.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Strategy.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/StringHash.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/StringHashParser.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/TagTransform.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Token.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/TokenFactory.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URI.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIDefinition.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIParser.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/UnitConverter.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/VarParser.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/VarParserException.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Zipper.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/Switch.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/Text.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Number.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Background.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Border.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Color.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Font.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Class.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ContentEditable.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Background.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/BdoDir.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/BgColor.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Border.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Input.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/NameSync.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Nofollow.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/Empty.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/List.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/ChildDef/Table.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Bdo.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Edit.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Forms.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Hypertext.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Iframe.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Image.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Legacy.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/List.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Name.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Nofollow.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Name.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector/AutoParagraph.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector/Linkify.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector/PurifierLinkify.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector/RemoveEmpty.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Node/Comment.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Node/Element.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Node/Text.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Strategy/Composite.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Strategy/Core.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/TagTransform/Font.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/TagTransform/Simple.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Token/Comment.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Token/Tag.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Token/Empty.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Token/End.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Token/Start.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/Token/Text.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter/DisableResources.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter/Munge.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIFilter/SafeIframe.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/data.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/file.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/http.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/news.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/nntp.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/URIScheme/tel.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/VarParser/Flexible.php';
|
||||||
|
require_once $__dir . '/HTMLPurifier/VarParser/Native.php';
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a stream of HTMLPurifier_Token into an HTMLPurifier_Node,
|
||||||
|
* and back again.
|
||||||
|
*
|
||||||
|
* @note This transformation is not an equivalence. We mutate the input
|
||||||
|
* token stream to make it so; see all [MUT] markers in code.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_Arborize
|
||||||
|
{
|
||||||
|
public static function arborize($tokens, $config, $context) {
|
||||||
|
$definition = $config->getHTMLDefinition();
|
||||||
|
$parent = new HTMLPurifier_Token_Start($definition->info_parent);
|
||||||
|
$stack = array($parent->toNode());
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
$token->skip = null; // [MUT]
|
||||||
|
$token->carryover = null; // [MUT]
|
||||||
|
if ($token instanceof HTMLPurifier_Token_End) {
|
||||||
|
$token->start = null; // [MUT]
|
||||||
|
$r = array_pop($stack);
|
||||||
|
//assert($r->name === $token->name);
|
||||||
|
//assert(empty($token->attr));
|
||||||
|
$r->endCol = $token->col;
|
||||||
|
$r->endLine = $token->line;
|
||||||
|
$r->endArmor = $token->armor;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$node = $token->toNode();
|
||||||
|
$stack[count($stack)-1]->children[] = $node;
|
||||||
|
if ($token instanceof HTMLPurifier_Token_Start) {
|
||||||
|
$stack[] = $node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//assert(count($stack) == 1);
|
||||||
|
return $stack[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function flatten($node, $config, $context) {
|
||||||
|
$level = 0;
|
||||||
|
$nodes = array($level => new HTMLPurifier_Queue(array($node)));
|
||||||
|
$closingTokens = array();
|
||||||
|
$tokens = array();
|
||||||
|
do {
|
||||||
|
while (!$nodes[$level]->isEmpty()) {
|
||||||
|
$node = $nodes[$level]->shift(); // FIFO
|
||||||
|
list($start, $end) = $node->toTokenPair();
|
||||||
|
if ($level > 0) {
|
||||||
|
$tokens[] = $start;
|
||||||
|
}
|
||||||
|
if ($end !== NULL) {
|
||||||
|
$closingTokens[$level][] = $end;
|
||||||
|
}
|
||||||
|
if ($node instanceof HTMLPurifier_Node_Element) {
|
||||||
|
$level++;
|
||||||
|
$nodes[$level] = new HTMLPurifier_Queue();
|
||||||
|
foreach ($node->children as $childNode) {
|
||||||
|
$nodes[$level]->push($childNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$level--;
|
||||||
|
if ($level && isset($closingTokens[$level])) {
|
||||||
|
while ($token = array_pop($closingTokens[$level])) {
|
||||||
|
$tokens[] = $token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ($level > 0);
|
||||||
|
return $tokens;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines common attribute collections that modules reference
|
||||||
|
*/
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrCollections
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associative array of attribute collections, indexed by name.
|
||||||
|
* @type array
|
||||||
|
*/
|
||||||
|
public $info = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs all expansions on internal data for use by other inclusions
|
||||||
|
* It also collects all attribute collection extensions from
|
||||||
|
* modules
|
||||||
|
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||||
|
* @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members
|
||||||
|
*/
|
||||||
|
public function __construct($attr_types, $modules)
|
||||||
|
{
|
||||||
|
$this->doConstruct($attr_types, $modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function doConstruct($attr_types, $modules)
|
||||||
|
{
|
||||||
|
// load extensions from the modules
|
||||||
|
foreach ($modules as $module) {
|
||||||
|
foreach ($module->attr_collections as $coll_i => $coll) {
|
||||||
|
if (!isset($this->info[$coll_i])) {
|
||||||
|
$this->info[$coll_i] = array();
|
||||||
|
}
|
||||||
|
foreach ($coll as $attr_i => $attr) {
|
||||||
|
if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
|
||||||
|
// merge in includes
|
||||||
|
$this->info[$coll_i][$attr_i] = array_merge(
|
||||||
|
$this->info[$coll_i][$attr_i],
|
||||||
|
$attr
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$this->info[$coll_i][$attr_i] = $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// perform internal expansions and inclusions
|
||||||
|
foreach ($this->info as $name => $attr) {
|
||||||
|
// merge attribute collections that include others
|
||||||
|
$this->performInclusions($this->info[$name]);
|
||||||
|
// replace string identifiers with actual attribute objects
|
||||||
|
$this->expandIdentifiers($this->info[$name], $attr_types);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a reference to an attribute associative array and performs
|
||||||
|
* all inclusions specified by the zero index.
|
||||||
|
* @param array &$attr Reference to attribute array
|
||||||
|
*/
|
||||||
|
public function performInclusions(&$attr)
|
||||||
|
{
|
||||||
|
if (!isset($attr[0])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$merge = $attr[0];
|
||||||
|
$seen = array(); // recursion guard
|
||||||
|
// loop through all the inclusions
|
||||||
|
for ($i = 0; isset($merge[$i]); $i++) {
|
||||||
|
if (isset($seen[$merge[$i]])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$seen[$merge[$i]] = true;
|
||||||
|
// foreach attribute of the inclusion, copy it over
|
||||||
|
if (!isset($this->info[$merge[$i]])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($this->info[$merge[$i]] as $key => $value) {
|
||||||
|
if (isset($attr[$key])) {
|
||||||
|
continue;
|
||||||
|
} // also catches more inclusions
|
||||||
|
$attr[$key] = $value;
|
||||||
|
}
|
||||||
|
if (isset($this->info[$merge[$i]][0])) {
|
||||||
|
// recursion
|
||||||
|
$merge = array_merge($merge, $this->info[$merge[$i]][0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($attr[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expands all string identifiers in an attribute array by replacing
|
||||||
|
* them with the appropriate values inside HTMLPurifier_AttrTypes
|
||||||
|
* @param array &$attr Reference to attribute array
|
||||||
|
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||||
|
*/
|
||||||
|
public function expandIdentifiers(&$attr, $attr_types)
|
||||||
|
{
|
||||||
|
// because foreach will process new elements we add, make sure we
|
||||||
|
// skip duplicates
|
||||||
|
$processed = array();
|
||||||
|
|
||||||
|
foreach ($attr as $def_i => $def) {
|
||||||
|
// skip inclusions
|
||||||
|
if ($def_i === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($processed[$def_i])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine whether or not attribute is required
|
||||||
|
if ($required = (strpos($def_i, '*') !== false)) {
|
||||||
|
// rename the definition
|
||||||
|
unset($attr[$def_i]);
|
||||||
|
$def_i = trim($def_i, '*');
|
||||||
|
$attr[$def_i] = $def;
|
||||||
|
}
|
||||||
|
|
||||||
|
$processed[$def_i] = true;
|
||||||
|
|
||||||
|
// if we've already got a literal object, move on
|
||||||
|
if (is_object($def)) {
|
||||||
|
// preserve previous required
|
||||||
|
$attr[$def_i]->required = ($required || $attr[$def_i]->required);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($def === false) {
|
||||||
|
unset($attr[$def_i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($t = $attr_types->get($def)) {
|
||||||
|
$attr[$def_i] = $t;
|
||||||
|
$attr[$def_i]->required = $required;
|
||||||
|
} else {
|
||||||
|
unset($attr[$def_i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,144 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for all validating attribute definitions.
|
||||||
|
*
|
||||||
|
* This family of classes forms the core for not only HTML attribute validation,
|
||||||
|
* but also any sort of string that needs to be validated or cleaned (which
|
||||||
|
* means CSS properties and composite definitions are defined here too).
|
||||||
|
* Besides defining (through code) what precisely makes the string valid,
|
||||||
|
* subclasses are also responsible for cleaning the code if possible.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells us whether or not an HTML attribute is minimized.
|
||||||
|
* Has no meaning in other contexts.
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
public $minimized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells us whether or not an HTML attribute is required.
|
||||||
|
* Has no meaning in other contexts
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
public $required = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates and cleans passed string according to a definition.
|
||||||
|
*
|
||||||
|
* @param string $string String to be validated and cleaned.
|
||||||
|
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
|
||||||
|
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object.
|
||||||
|
*/
|
||||||
|
abstract public function validate($string, $config, $context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method that parses a string as if it were CDATA.
|
||||||
|
*
|
||||||
|
* This method process a string in the manner specified at
|
||||||
|
* <http://www.w3.org/TR/html4/types.html#h-6.2> by removing
|
||||||
|
* leading and trailing whitespace, ignoring line feeds, and replacing
|
||||||
|
* carriage returns and tabs with spaces. While most useful for HTML
|
||||||
|
* attributes specified as CDATA, it can also be applied to most CSS
|
||||||
|
* values.
|
||||||
|
*
|
||||||
|
* @note This method is not entirely standards compliant, as trim() removes
|
||||||
|
* more types of whitespace than specified in the spec. In practice,
|
||||||
|
* this is rarely a problem, as those extra characters usually have
|
||||||
|
* already been removed by HTMLPurifier_Encoder.
|
||||||
|
*
|
||||||
|
* @warning This processing is inconsistent with XML's whitespace handling
|
||||||
|
* as specified by section 3.3.3 and referenced XHTML 1.0 section
|
||||||
|
* 4.7. However, note that we are NOT necessarily
|
||||||
|
* parsing XML, thus, this behavior may still be correct. We
|
||||||
|
* assume that newlines have been normalized.
|
||||||
|
*/
|
||||||
|
public function parseCDATA($string)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
$string = str_replace(array("\n", "\t", "\r"), ' ', $string);
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method for creating this class from a string.
|
||||||
|
* @param string $string String construction info
|
||||||
|
* @return HTMLPurifier_AttrDef Created AttrDef object corresponding to $string
|
||||||
|
*/
|
||||||
|
public function make($string)
|
||||||
|
{
|
||||||
|
// default implementation, return a flyweight of this object.
|
||||||
|
// If $string has an effect on the returned object (i.e. you
|
||||||
|
// need to overload this method), it is best
|
||||||
|
// to clone or instantiate new copies. (Instantiation is safer.)
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
|
||||||
|
* properly. THIS IS A HACK!
|
||||||
|
* @param string $string a CSS colour definition
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function mungeRgb($string)
|
||||||
|
{
|
||||||
|
$p = '\s*(\d+(\.\d+)?([%]?))\s*';
|
||||||
|
|
||||||
|
if (preg_match('/(rgba|hsla)\(/', $string)) {
|
||||||
|
return preg_replace('/(rgba|hsla)\('.$p.','.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8,\11)', $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
return preg_replace('/(rgb|hsl)\('.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8)', $string);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a possibly escaped CSS string and returns the "pure"
|
||||||
|
* version of it.
|
||||||
|
*/
|
||||||
|
protected function expandCSSEscape($string)
|
||||||
|
{
|
||||||
|
// flexibly parse it
|
||||||
|
$ret = '';
|
||||||
|
for ($i = 0, $c = strlen($string); $i < $c; $i++) {
|
||||||
|
if ($string[$i] === '\\') {
|
||||||
|
$i++;
|
||||||
|
if ($i >= $c) {
|
||||||
|
$ret .= '\\';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ctype_xdigit($string[$i])) {
|
||||||
|
$code = $string[$i];
|
||||||
|
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
|
||||||
|
if (!ctype_xdigit($string[$i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$code .= $string[$i];
|
||||||
|
}
|
||||||
|
// We have to be extremely careful when adding
|
||||||
|
// new characters, to make sure we're not breaking
|
||||||
|
// the encoding.
|
||||||
|
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
|
||||||
|
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$ret .= $char;
|
||||||
|
if ($i < $c && trim($string[$i]) !== '') {
|
||||||
|
$i--;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($string[$i] === "\n") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ret .= $string[$i];
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,136 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the HTML attribute style, otherwise known as CSS.
|
||||||
|
* @note We don't implement the whole CSS specification, so it might be
|
||||||
|
* difficult to reuse this component in the context of validating
|
||||||
|
* actual stylesheet declarations.
|
||||||
|
* @note If we were really serious about validating the CSS, we would
|
||||||
|
* tokenize the styles and then parse the tokens. Obviously, we
|
||||||
|
* are not doing that. Doing that could seriously harm performance,
|
||||||
|
* but would make these components a lot more viable for a CSS
|
||||||
|
* filtering solution.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $css
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($css, $config, $context)
|
||||||
|
{
|
||||||
|
$css = $this->parseCDATA($css);
|
||||||
|
|
||||||
|
$definition = $config->getCSSDefinition();
|
||||||
|
$allow_duplicates = $config->get("CSS.AllowDuplicates");
|
||||||
|
|
||||||
|
|
||||||
|
// According to the CSS2.1 spec, the places where a
|
||||||
|
// non-delimiting semicolon can appear are in strings
|
||||||
|
// escape sequences. So here is some dumb hack to
|
||||||
|
// handle quotes.
|
||||||
|
$len = strlen($css);
|
||||||
|
$accum = "";
|
||||||
|
$declarations = array();
|
||||||
|
$quoted = false;
|
||||||
|
for ($i = 0; $i < $len; $i++) {
|
||||||
|
$c = strcspn($css, ";'\"", $i);
|
||||||
|
$accum .= substr($css, $i, $c);
|
||||||
|
$i += $c;
|
||||||
|
if ($i == $len) break;
|
||||||
|
$d = $css[$i];
|
||||||
|
if ($quoted) {
|
||||||
|
$accum .= $d;
|
||||||
|
if ($d == $quoted) {
|
||||||
|
$quoted = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($d == ";") {
|
||||||
|
$declarations[] = $accum;
|
||||||
|
$accum = "";
|
||||||
|
} else {
|
||||||
|
$accum .= $d;
|
||||||
|
$quoted = $d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($accum != "") $declarations[] = $accum;
|
||||||
|
|
||||||
|
$propvalues = array();
|
||||||
|
$new_declarations = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the current CSS property being validated.
|
||||||
|
*/
|
||||||
|
$property = false;
|
||||||
|
$context->register('CurrentCSSProperty', $property);
|
||||||
|
|
||||||
|
foreach ($declarations as $declaration) {
|
||||||
|
if (!$declaration) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strpos($declaration, ':')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list($property, $value) = explode(':', $declaration, 2);
|
||||||
|
$property = trim($property);
|
||||||
|
$value = trim($value);
|
||||||
|
$ok = false;
|
||||||
|
do {
|
||||||
|
if (isset($definition->info[$property])) {
|
||||||
|
$ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ctype_lower($property)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$property = strtolower($property);
|
||||||
|
if (isset($definition->info[$property])) {
|
||||||
|
$ok = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (0);
|
||||||
|
if (!$ok) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// inefficient call, since the validator will do this again
|
||||||
|
if (strtolower(trim($value)) !== 'inherit') {
|
||||||
|
// inherit works for everything (but only on the base property)
|
||||||
|
$result = $definition->info[$property]->validate(
|
||||||
|
$value,
|
||||||
|
$config,
|
||||||
|
$context
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$result = 'inherit';
|
||||||
|
}
|
||||||
|
if ($result === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($allow_duplicates) {
|
||||||
|
$new_declarations .= "$property:$result;";
|
||||||
|
} else {
|
||||||
|
$propvalues[$property] = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$context->destroy('CurrentCSSProperty');
|
||||||
|
|
||||||
|
// procedure does not write the new CSS simultaneously, so it's
|
||||||
|
// slightly inefficient, but it's the only way of getting rid of
|
||||||
|
// duplicates. Perhaps config to optimize it, but not now.
|
||||||
|
|
||||||
|
foreach ($propvalues as $prop => $value) {
|
||||||
|
$new_declarations .= "$prop:$value;";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $new_declarations ? $new_declarations : false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct(false); // opacity is non-negative, but we will clamp it
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $number
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function validate($number, $config, $context)
|
||||||
|
{
|
||||||
|
$result = parent::validate($number, $config, $context);
|
||||||
|
if ($result === false) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
$float = (float)$result;
|
||||||
|
if ($float < 0.0) {
|
||||||
|
$result = '0';
|
||||||
|
}
|
||||||
|
if ($float > 1.0) {
|
||||||
|
$result = '1';
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates shorthand CSS property background.
|
||||||
|
* @warning Does not support url tokens that have internal spaces.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local copy of component validators.
|
||||||
|
* @type HTMLPurifier_AttrDef[]
|
||||||
|
* @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
|
||||||
|
*/
|
||||||
|
protected $info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
*/
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$def = $config->getCSSDefinition();
|
||||||
|
$this->info['background-color'] = $def->info['background-color'];
|
||||||
|
$this->info['background-image'] = $def->info['background-image'];
|
||||||
|
$this->info['background-repeat'] = $def->info['background-repeat'];
|
||||||
|
$this->info['background-attachment'] = $def->info['background-attachment'];
|
||||||
|
$this->info['background-position'] = $def->info['background-position'];
|
||||||
|
$this->info['background-size'] = $def->info['background-size'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
// regular pre-processing
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// munge rgb() decl if necessary
|
||||||
|
$string = $this->mungeRgb($string);
|
||||||
|
|
||||||
|
// assumes URI doesn't have spaces in it
|
||||||
|
$bits = explode(' ', $string); // bits to process
|
||||||
|
|
||||||
|
$caught = array();
|
||||||
|
$caught['color'] = false;
|
||||||
|
$caught['image'] = false;
|
||||||
|
$caught['repeat'] = false;
|
||||||
|
$caught['attachment'] = false;
|
||||||
|
$caught['position'] = false;
|
||||||
|
$caught['size'] = false;
|
||||||
|
|
||||||
|
$i = 0; // number of catches
|
||||||
|
|
||||||
|
foreach ($bits as $bit) {
|
||||||
|
if ($bit === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($caught as $key => $status) {
|
||||||
|
if ($key != 'position') {
|
||||||
|
if ($status !== false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$r = $this->info['background-' . $key]->validate($bit, $config, $context);
|
||||||
|
} else {
|
||||||
|
$r = $bit;
|
||||||
|
}
|
||||||
|
if ($r === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($key == 'position') {
|
||||||
|
if ($caught[$key] === false) {
|
||||||
|
$caught[$key] = '';
|
||||||
|
}
|
||||||
|
$caught[$key] .= $r . ' ';
|
||||||
|
} else {
|
||||||
|
$caught[$key] = $r;
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$i) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($caught['position'] !== false) {
|
||||||
|
$caught['position'] = $this->info['background-position']->
|
||||||
|
validate($caught['position'], $config, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = array();
|
||||||
|
foreach ($caught as $value) {
|
||||||
|
if ($value === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$ret[] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($ret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return implode(' ', $ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
157
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
vendored
Normal file
157
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
vendored
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/* W3C says:
|
||||||
|
[ // adjective and number must be in correct order, even if
|
||||||
|
// you could switch them without introducing ambiguity.
|
||||||
|
// some browsers support that syntax
|
||||||
|
[
|
||||||
|
<percentage> | <length> | left | center | right
|
||||||
|
]
|
||||||
|
[
|
||||||
|
<percentage> | <length> | top | center | bottom
|
||||||
|
]?
|
||||||
|
] |
|
||||||
|
[ // this signifies that the vertical and horizontal adjectives
|
||||||
|
// can be arbitrarily ordered, however, there can only be two,
|
||||||
|
// one of each, or none at all
|
||||||
|
[
|
||||||
|
left | center | right
|
||||||
|
] ||
|
||||||
|
[
|
||||||
|
top | center | bottom
|
||||||
|
]
|
||||||
|
]
|
||||||
|
top, left = 0%
|
||||||
|
center, (none) = 50%
|
||||||
|
bottom, right = 100%
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* QuirksMode says:
|
||||||
|
keyword + length/percentage must be ordered correctly, as per W3C
|
||||||
|
|
||||||
|
Internet Explorer and Opera, however, support arbitrary ordering. We
|
||||||
|
should fix it up.
|
||||||
|
|
||||||
|
Minor issue though, not strictly necessary.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// control freaks may appreciate the ability to convert these to
|
||||||
|
// percentages or something, but it's not necessary
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the value of background-position.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_CSS_Length
|
||||||
|
*/
|
||||||
|
protected $length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_CSS_Percentage
|
||||||
|
*/
|
||||||
|
protected $percentage;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
|
||||||
|
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
$bits = explode(' ', $string);
|
||||||
|
|
||||||
|
$keywords = array();
|
||||||
|
$keywords['h'] = false; // left, right
|
||||||
|
$keywords['v'] = false; // top, bottom
|
||||||
|
$keywords['ch'] = false; // center (first word)
|
||||||
|
$keywords['cv'] = false; // center (second word)
|
||||||
|
$measures = array();
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
$lookup = array(
|
||||||
|
'top' => 'v',
|
||||||
|
'bottom' => 'v',
|
||||||
|
'left' => 'h',
|
||||||
|
'right' => 'h',
|
||||||
|
'center' => 'c'
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach ($bits as $bit) {
|
||||||
|
if ($bit === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for keyword
|
||||||
|
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
|
||||||
|
if (isset($lookup[$lbit])) {
|
||||||
|
$status = $lookup[$lbit];
|
||||||
|
if ($status == 'c') {
|
||||||
|
if ($i == 0) {
|
||||||
|
$status = 'ch';
|
||||||
|
} else {
|
||||||
|
$status = 'cv';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$keywords[$status] = $lbit;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for length
|
||||||
|
$r = $this->length->validate($bit, $config, $context);
|
||||||
|
if ($r !== false) {
|
||||||
|
$measures[] = $r;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test for percentage
|
||||||
|
$r = $this->percentage->validate($bit, $config, $context);
|
||||||
|
if ($r !== false) {
|
||||||
|
$measures[] = $r;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$i) {
|
||||||
|
return false;
|
||||||
|
} // no valid values were caught
|
||||||
|
|
||||||
|
$ret = array();
|
||||||
|
|
||||||
|
// first keyword
|
||||||
|
if ($keywords['h']) {
|
||||||
|
$ret[] = $keywords['h'];
|
||||||
|
} elseif ($keywords['ch']) {
|
||||||
|
$ret[] = $keywords['ch'];
|
||||||
|
$keywords['cv'] = false; // prevent re-use: center = center center
|
||||||
|
} elseif (count($measures)) {
|
||||||
|
$ret[] = array_shift($measures);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($keywords['v']) {
|
||||||
|
$ret[] = $keywords['v'];
|
||||||
|
} elseif ($keywords['cv']) {
|
||||||
|
$ret[] = $keywords['cv'];
|
||||||
|
} elseif (count($measures)) {
|
||||||
|
$ret[] = array_shift($measures);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($ret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return implode(' ', $ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the border property as defined by CSS.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local copy of properties this property is shorthand for.
|
||||||
|
* @type HTMLPurifier_AttrDef[]
|
||||||
|
*/
|
||||||
|
protected $info = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
*/
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$def = $config->getCSSDefinition();
|
||||||
|
$this->info['border-width'] = $def->info['border-width'];
|
||||||
|
$this->info['border-style'] = $def->info['border-style'];
|
||||||
|
$this->info['border-top-color'] = $def->info['border-top-color'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
$string = $this->mungeRgb($string);
|
||||||
|
$bits = explode(' ', $string);
|
||||||
|
$done = array(); // segments we've finished
|
||||||
|
$ret = ''; // return value
|
||||||
|
foreach ($bits as $bit) {
|
||||||
|
foreach ($this->info as $propname => $validator) {
|
||||||
|
if (isset($done[$propname])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$r = $validator->validate($bit, $config, $context);
|
||||||
|
if ($r !== false) {
|
||||||
|
$ret .= $r . ' ';
|
||||||
|
$done[$propname] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rtrim($ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,161 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates Color as defined by CSS.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_CSS_AlphaValue
|
||||||
|
*/
|
||||||
|
protected $alpha;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $color
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($color, $config, $context)
|
||||||
|
{
|
||||||
|
static $colors = null;
|
||||||
|
if ($colors === null) {
|
||||||
|
$colors = $config->get('Core.ColorKeywords');
|
||||||
|
}
|
||||||
|
|
||||||
|
$color = trim($color);
|
||||||
|
if ($color === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lower = strtolower($color);
|
||||||
|
if (isset($colors[$lower])) {
|
||||||
|
return $colors[$lower];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
|
||||||
|
$length = strlen($color);
|
||||||
|
if (strpos($color, ')') !== $length - 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get used function : rgb, rgba, hsl or hsla
|
||||||
|
$function = $matches[1];
|
||||||
|
|
||||||
|
$parameters_size = 3;
|
||||||
|
$alpha_channel = false;
|
||||||
|
if (substr($function, -1) === 'a') {
|
||||||
|
$parameters_size = 4;
|
||||||
|
$alpha_channel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allowed types for values :
|
||||||
|
* parameter_position => [type => max_value]
|
||||||
|
*/
|
||||||
|
$allowed_types = array(
|
||||||
|
1 => array('percentage' => 100, 'integer' => 255),
|
||||||
|
2 => array('percentage' => 100, 'integer' => 255),
|
||||||
|
3 => array('percentage' => 100, 'integer' => 255),
|
||||||
|
);
|
||||||
|
$allow_different_types = false;
|
||||||
|
|
||||||
|
if (strpos($function, 'hsl') !== false) {
|
||||||
|
$allowed_types = array(
|
||||||
|
1 => array('integer' => 360),
|
||||||
|
2 => array('percentage' => 100),
|
||||||
|
3 => array('percentage' => 100),
|
||||||
|
);
|
||||||
|
$allow_different_types = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$values = trim(str_replace($function, '', $color), ' ()');
|
||||||
|
|
||||||
|
$parts = explode(',', $values);
|
||||||
|
if (count($parts) !== $parameters_size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = false;
|
||||||
|
$new_parts = array();
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
$i++;
|
||||||
|
$part = trim($part);
|
||||||
|
|
||||||
|
if ($part === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// different check for alpha channel
|
||||||
|
if ($alpha_channel === true && $i === count($parts)) {
|
||||||
|
$result = $this->alpha->validate($part, $config, $context);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_parts[] = (string)$result;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (substr($part, -1) === '%') {
|
||||||
|
$current_type = 'percentage';
|
||||||
|
} else {
|
||||||
|
$current_type = 'integer';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!array_key_exists($current_type, $allowed_types[$i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$type) {
|
||||||
|
$type = $current_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($allow_different_types === false && $type != $current_type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$max_value = $allowed_types[$i][$current_type];
|
||||||
|
|
||||||
|
if ($current_type == 'integer') {
|
||||||
|
// Return value between range 0 -> $max_value
|
||||||
|
$new_parts[] = (int)max(min($part, $max_value), 0);
|
||||||
|
} elseif ($current_type == 'percentage') {
|
||||||
|
$new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_values = implode(',', $new_parts);
|
||||||
|
|
||||||
|
$color = $function . '(' . $new_values . ')';
|
||||||
|
} else {
|
||||||
|
// hexadecimal handling
|
||||||
|
if ($color[0] === '#') {
|
||||||
|
$hex = substr($color, 1);
|
||||||
|
} else {
|
||||||
|
$hex = $color;
|
||||||
|
$color = '#' . $color;
|
||||||
|
}
|
||||||
|
$length = strlen($hex);
|
||||||
|
if ($length !== 3 && $length !== 6) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ctype_xdigit($hex)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $color;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows multiple validators to attempt to validate attribute.
|
||||||
|
*
|
||||||
|
* Composite is just what it sounds like: a composite of many validators.
|
||||||
|
* This means that multiple HTMLPurifier_AttrDef objects will have a whack
|
||||||
|
* at the string. If one of them passes, that's what is returned. This is
|
||||||
|
* especially useful for CSS values, which often are a choice between
|
||||||
|
* an enumerated set of predefined values or a flexible data type.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of objects that may process strings.
|
||||||
|
* @type HTMLPurifier_AttrDef[]
|
||||||
|
* @todo Make protected
|
||||||
|
*/
|
||||||
|
public $defs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects
|
||||||
|
*/
|
||||||
|
public function __construct($defs)
|
||||||
|
{
|
||||||
|
$this->defs = $defs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
foreach ($this->defs as $i => $def) {
|
||||||
|
$result = $this->defs[$i]->validate($string, $config, $context);
|
||||||
|
if ($result !== false) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
44
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
vendored
Normal file
44
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorator which enables CSS properties to be disabled for specific elements.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef
|
||||||
|
*/
|
||||||
|
public $def;
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
public $element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||||
|
* @param string $element Element to deny
|
||||||
|
*/
|
||||||
|
public function __construct($def, $element)
|
||||||
|
{
|
||||||
|
$this->def = $def;
|
||||||
|
$this->element = $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if CurrentToken is set and equal to $this->element
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$token = $context->get('CurrentToken', true);
|
||||||
|
if ($token && $token->name == $this->element) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->def->validate($string, $config, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Microsoft's proprietary filter: CSS property
|
||||||
|
* @note Currently supports the alpha filter. In the future, this will
|
||||||
|
* probably need an extensible framework
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_Integer
|
||||||
|
*/
|
||||||
|
protected $intValidator;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->intValidator = new HTMLPurifier_AttrDef_Integer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $value
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($value, $config, $context)
|
||||||
|
{
|
||||||
|
$value = $this->parseCDATA($value);
|
||||||
|
if ($value === 'none') {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
// if we looped this we could support multiple filters
|
||||||
|
$function_length = strcspn($value, '(');
|
||||||
|
$function = trim(substr($value, 0, $function_length));
|
||||||
|
if ($function !== 'alpha' &&
|
||||||
|
$function !== 'Alpha' &&
|
||||||
|
$function !== 'progid:DXImageTransform.Microsoft.Alpha'
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$cursor = $function_length + 1;
|
||||||
|
$parameters_length = strcspn($value, ')', $cursor);
|
||||||
|
$parameters = substr($value, $cursor, $parameters_length);
|
||||||
|
$params = explode(',', $parameters);
|
||||||
|
$ret_params = array();
|
||||||
|
$lookup = array();
|
||||||
|
foreach ($params as $param) {
|
||||||
|
list($key, $value) = explode('=', $param);
|
||||||
|
$key = trim($key);
|
||||||
|
$value = trim($value);
|
||||||
|
if (isset($lookup[$key])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($key !== 'opacity') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$value = $this->intValidator->validate($value, $config, $context);
|
||||||
|
if ($value === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$int = (int)$value;
|
||||||
|
if ($int > 100) {
|
||||||
|
$value = '100';
|
||||||
|
}
|
||||||
|
if ($int < 0) {
|
||||||
|
$value = '0';
|
||||||
|
}
|
||||||
|
$ret_params[] = "$key=$value";
|
||||||
|
$lookup[$key] = true;
|
||||||
|
}
|
||||||
|
$ret_parameters = implode(',', $ret_params);
|
||||||
|
$ret_function = "$function($ret_parameters)";
|
||||||
|
return $ret_function;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,176 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates shorthand CSS property font.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local copy of validators
|
||||||
|
* @type HTMLPurifier_AttrDef[]
|
||||||
|
* @note If we moved specific CSS property definitions to their own
|
||||||
|
* classes instead of having them be assembled at run time by
|
||||||
|
* CSSDefinition, this wouldn't be necessary. We'd instantiate
|
||||||
|
* our own copies.
|
||||||
|
*/
|
||||||
|
protected $info = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
*/
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$def = $config->getCSSDefinition();
|
||||||
|
$this->info['font-style'] = $def->info['font-style'];
|
||||||
|
$this->info['font-variant'] = $def->info['font-variant'];
|
||||||
|
$this->info['font-weight'] = $def->info['font-weight'];
|
||||||
|
$this->info['font-size'] = $def->info['font-size'];
|
||||||
|
$this->info['line-height'] = $def->info['line-height'];
|
||||||
|
$this->info['font-family'] = $def->info['font-family'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
static $system_fonts = array(
|
||||||
|
'caption' => true,
|
||||||
|
'icon' => true,
|
||||||
|
'menu' => true,
|
||||||
|
'message-box' => true,
|
||||||
|
'small-caption' => true,
|
||||||
|
'status-bar' => true
|
||||||
|
);
|
||||||
|
|
||||||
|
// regular pre-processing
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if it's one of the keywords
|
||||||
|
$lowercase_string = strtolower($string);
|
||||||
|
if (isset($system_fonts[$lowercase_string])) {
|
||||||
|
return $lowercase_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bits = explode(' ', $string); // bits to process
|
||||||
|
$stage = 0; // this indicates what we're looking for
|
||||||
|
$caught = array(); // which stage 0 properties have we caught?
|
||||||
|
$stage_1 = array('font-style', 'font-variant', 'font-weight');
|
||||||
|
$final = ''; // output
|
||||||
|
|
||||||
|
for ($i = 0, $size = count($bits); $i < $size; $i++) {
|
||||||
|
if ($bits[$i] === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch ($stage) {
|
||||||
|
case 0: // attempting to catch font-style, font-variant or font-weight
|
||||||
|
foreach ($stage_1 as $validator_name) {
|
||||||
|
if (isset($caught[$validator_name])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$r = $this->info[$validator_name]->validate(
|
||||||
|
$bits[$i],
|
||||||
|
$config,
|
||||||
|
$context
|
||||||
|
);
|
||||||
|
if ($r !== false) {
|
||||||
|
$final .= $r . ' ';
|
||||||
|
$caught[$validator_name] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// all three caught, continue on
|
||||||
|
if (count($caught) >= 3) {
|
||||||
|
$stage = 1;
|
||||||
|
}
|
||||||
|
if ($r !== false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: // attempting to catch font-size and perhaps line-height
|
||||||
|
$found_slash = false;
|
||||||
|
if (strpos($bits[$i], '/') !== false) {
|
||||||
|
list($font_size, $line_height) =
|
||||||
|
explode('/', $bits[$i]);
|
||||||
|
if ($line_height === '') {
|
||||||
|
// ooh, there's a space after the slash!
|
||||||
|
$line_height = false;
|
||||||
|
$found_slash = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$font_size = $bits[$i];
|
||||||
|
$line_height = false;
|
||||||
|
}
|
||||||
|
$r = $this->info['font-size']->validate(
|
||||||
|
$font_size,
|
||||||
|
$config,
|
||||||
|
$context
|
||||||
|
);
|
||||||
|
if ($r !== false) {
|
||||||
|
$final .= $r;
|
||||||
|
// attempt to catch line-height
|
||||||
|
if ($line_height === false) {
|
||||||
|
// we need to scroll forward
|
||||||
|
for ($j = $i + 1; $j < $size; $j++) {
|
||||||
|
if ($bits[$j] === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($bits[$j] === '/') {
|
||||||
|
if ($found_slash) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
$found_slash = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$line_height = $bits[$j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// slash already found
|
||||||
|
$found_slash = true;
|
||||||
|
$j = $i;
|
||||||
|
}
|
||||||
|
if ($found_slash) {
|
||||||
|
$i = $j;
|
||||||
|
$r = $this->info['line-height']->validate(
|
||||||
|
$line_height,
|
||||||
|
$config,
|
||||||
|
$context
|
||||||
|
);
|
||||||
|
if ($r !== false) {
|
||||||
|
$final .= '/' . $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$final .= ' ';
|
||||||
|
$stage = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case 2: // attempting to catch font-family
|
||||||
|
$font_family =
|
||||||
|
implode(' ', array_slice($bits, $i, $size - $i));
|
||||||
|
$r = $this->info['font-family']->validate(
|
||||||
|
$font_family,
|
||||||
|
$config,
|
||||||
|
$context
|
||||||
|
);
|
||||||
|
if ($r !== false) {
|
||||||
|
$final .= $r . ' ';
|
||||||
|
// processing completed successfully
|
||||||
|
return rtrim($final);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,219 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a font family list according to CSS spec
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
protected $mask = null;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->mask = '_- ';
|
||||||
|
for ($c = 'a'; $c <= 'z'; $c++) {
|
||||||
|
$this->mask .= $c;
|
||||||
|
}
|
||||||
|
for ($c = 'A'; $c <= 'Z'; $c++) {
|
||||||
|
$this->mask .= $c;
|
||||||
|
}
|
||||||
|
for ($c = '0'; $c <= '9'; $c++) {
|
||||||
|
$this->mask .= $c;
|
||||||
|
} // cast-y, but should be fine
|
||||||
|
// special bytes used by UTF-8
|
||||||
|
for ($i = 0x80; $i <= 0xFF; $i++) {
|
||||||
|
// We don't bother excluding invalid bytes in this range,
|
||||||
|
// because the our restriction of well-formed UTF-8 will
|
||||||
|
// prevent these from ever occurring.
|
||||||
|
$this->mask .= chr($i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
PHP's internal strcspn implementation is
|
||||||
|
O(length of string * length of mask), making it inefficient
|
||||||
|
for large masks. However, it's still faster than
|
||||||
|
preg_match 8)
|
||||||
|
for (p = s1;;) {
|
||||||
|
spanp = s2;
|
||||||
|
do {
|
||||||
|
if (*spanp == c || p == s1_end) {
|
||||||
|
return p - s1;
|
||||||
|
}
|
||||||
|
} while (spanp++ < (s2_end - 1));
|
||||||
|
c = *++p;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// possible optimization: invert the mask.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
static $generic_names = array(
|
||||||
|
'serif' => true,
|
||||||
|
'sans-serif' => true,
|
||||||
|
'monospace' => true,
|
||||||
|
'fantasy' => true,
|
||||||
|
'cursive' => true
|
||||||
|
);
|
||||||
|
$allowed_fonts = $config->get('CSS.AllowedFonts');
|
||||||
|
|
||||||
|
// assume that no font names contain commas in them
|
||||||
|
$fonts = explode(',', $string);
|
||||||
|
$final = '';
|
||||||
|
foreach ($fonts as $font) {
|
||||||
|
$font = trim($font);
|
||||||
|
if ($font === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// match a generic name
|
||||||
|
if (isset($generic_names[$font])) {
|
||||||
|
if ($allowed_fonts === null || isset($allowed_fonts[$font])) {
|
||||||
|
$final .= $font . ', ';
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// match a quoted name
|
||||||
|
if ($font[0] === '"' || $font[0] === "'") {
|
||||||
|
$length = strlen($font);
|
||||||
|
if ($length <= 2) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$quote = $font[0];
|
||||||
|
if ($font[$length - 1] !== $quote) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$font = substr($font, 1, $length - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
$font = $this->expandCSSEscape($font);
|
||||||
|
|
||||||
|
// $font is a pure representation of the font name
|
||||||
|
|
||||||
|
if ($allowed_fonts !== null && !isset($allowed_fonts[$font])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctype_alnum($font) && $font !== '') {
|
||||||
|
// very simple font, allow it in unharmed
|
||||||
|
$final .= $font . ', ';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bugger out on whitespace. form feed (0C) really
|
||||||
|
// shouldn't show up regardless
|
||||||
|
$font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
|
||||||
|
|
||||||
|
// Here, there are various classes of characters which need
|
||||||
|
// to be treated differently:
|
||||||
|
// - Alphanumeric characters are essentially safe. We
|
||||||
|
// handled these above.
|
||||||
|
// - Spaces require quoting, though most parsers will do
|
||||||
|
// the right thing if there aren't any characters that
|
||||||
|
// can be misinterpreted
|
||||||
|
// - Dashes rarely occur, but they fairly unproblematic
|
||||||
|
// for parsing/rendering purposes.
|
||||||
|
// The above characters cover the majority of Western font
|
||||||
|
// names.
|
||||||
|
// - Arbitrary Unicode characters not in ASCII. Because
|
||||||
|
// most parsers give little thought to Unicode, treatment
|
||||||
|
// of these codepoints is basically uniform, even for
|
||||||
|
// punctuation-like codepoints. These characters can
|
||||||
|
// show up in non-Western pages and are supported by most
|
||||||
|
// major browsers, for example: "MS 明朝" is a
|
||||||
|
// legitimate font-name
|
||||||
|
// <http://ja.wikipedia.org/wiki/MS_明朝>. See
|
||||||
|
// the CSS3 spec for more examples:
|
||||||
|
// <http://www.w3.org/TR/2011/WD-css3-fonts-20110324/localizedfamilynames.png>
|
||||||
|
// You can see live samples of these on the Internet:
|
||||||
|
// <http://www.google.co.jp/search?q=font-family+MS+明朝|ゴシック>
|
||||||
|
// However, most of these fonts have ASCII equivalents:
|
||||||
|
// for example, 'MS Mincho', and it's considered
|
||||||
|
// professional to use ASCII font names instead of
|
||||||
|
// Unicode font names. Thanks Takeshi Terada for
|
||||||
|
// providing this information.
|
||||||
|
// The following characters, to my knowledge, have not been
|
||||||
|
// used to name font names.
|
||||||
|
// - Single quote. While theoretically you might find a
|
||||||
|
// font name that has a single quote in its name (serving
|
||||||
|
// as an apostrophe, e.g. Dave's Scribble), I haven't
|
||||||
|
// been able to find any actual examples of this.
|
||||||
|
// Internet Explorer's cssText translation (which I
|
||||||
|
// believe is invoked by innerHTML) normalizes any
|
||||||
|
// quoting to single quotes, and fails to escape single
|
||||||
|
// quotes. (Note that this is not IE's behavior for all
|
||||||
|
// CSS properties, just some sort of special casing for
|
||||||
|
// font-family). So a single quote *cannot* be used
|
||||||
|
// safely in the font-family context if there will be an
|
||||||
|
// innerHTML/cssText translation. Note that Firefox 3.x
|
||||||
|
// does this too.
|
||||||
|
// - Double quote. In IE, these get normalized to
|
||||||
|
// single-quotes, no matter what the encoding. (Fun
|
||||||
|
// fact, in IE8, the 'content' CSS property gained
|
||||||
|
// support, where they special cased to preserve encoded
|
||||||
|
// double quotes, but still translate unadorned double
|
||||||
|
// quotes into single quotes.) So, because their
|
||||||
|
// fixpoint behavior is identical to single quotes, they
|
||||||
|
// cannot be allowed either. Firefox 3.x displays
|
||||||
|
// single-quote style behavior.
|
||||||
|
// - Backslashes are reduced by one (so \\ -> \) every
|
||||||
|
// iteration, so they cannot be used safely. This shows
|
||||||
|
// up in IE7, IE8 and FF3
|
||||||
|
// - Semicolons, commas and backticks are handled properly.
|
||||||
|
// - The rest of the ASCII punctuation is handled properly.
|
||||||
|
// We haven't checked what browsers do to unadorned
|
||||||
|
// versions, but this is not important as long as the
|
||||||
|
// browser doesn't /remove/ surrounding quotes (as IE does
|
||||||
|
// for HTML).
|
||||||
|
//
|
||||||
|
// With these results in hand, we conclude that there are
|
||||||
|
// various levels of safety:
|
||||||
|
// - Paranoid: alphanumeric, spaces and dashes(?)
|
||||||
|
// - International: Paranoid + non-ASCII Unicode
|
||||||
|
// - Edgy: Everything except quotes, backslashes
|
||||||
|
// - NoJS: Standards compliance, e.g. sod IE. Note that
|
||||||
|
// with some judicious character escaping (since certain
|
||||||
|
// types of escaping doesn't work) this is theoretically
|
||||||
|
// OK as long as innerHTML/cssText is not called.
|
||||||
|
// We believe that international is a reasonable default
|
||||||
|
// (that we will implement now), and once we do more
|
||||||
|
// extensive research, we may feel comfortable with dropping
|
||||||
|
// it down to edgy.
|
||||||
|
|
||||||
|
// Edgy: alphanumeric, spaces, dashes, underscores and Unicode. Use of
|
||||||
|
// str(c)spn assumes that the string was already well formed
|
||||||
|
// Unicode (which of course it is).
|
||||||
|
if (strspn($font, $this->mask) !== strlen($font)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Historical:
|
||||||
|
// In the absence of innerHTML/cssText, these ugly
|
||||||
|
// transforms don't pose a security risk (as \\ and \"
|
||||||
|
// might--these escapes are not supported by most browsers).
|
||||||
|
// We could try to be clever and use single-quote wrapping
|
||||||
|
// when there is a double quote present, but I have choosen
|
||||||
|
// not to implement that. (NOTE: you can reduce the amount
|
||||||
|
// of escapes by one depending on what quoting style you use)
|
||||||
|
// $font = str_replace('\\', '\\5C ', $font);
|
||||||
|
// $font = str_replace('"', '\\22 ', $font);
|
||||||
|
// $font = str_replace("'", '\\27 ', $font);
|
||||||
|
|
||||||
|
// font possibly with spaces, requires quoting
|
||||||
|
$final .= "'$font', ";
|
||||||
|
}
|
||||||
|
$final = rtrim($final, ', ');
|
||||||
|
if ($final === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $final;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates based on {ident} CSS grammar production
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
|
||||||
|
// early abort: '' and '0' (strings that convert to false) are invalid
|
||||||
|
if (!$string) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
|
||||||
|
if (!preg_match($pattern, $string)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
56
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
vendored
Normal file
56
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
vendored
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorator which enables !important to be used in CSS values.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef
|
||||||
|
*/
|
||||||
|
public $def;
|
||||||
|
/**
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
public $allow;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||||
|
* @param bool $allow Whether or not to allow !important
|
||||||
|
*/
|
||||||
|
public function __construct($def, $allow = false)
|
||||||
|
{
|
||||||
|
$this->def = $def;
|
||||||
|
$this->allow = $allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intercepts and removes !important if necessary
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
// test for ! and important tokens
|
||||||
|
$string = trim($string);
|
||||||
|
$is_important = false;
|
||||||
|
// :TODO: optimization: test directly for !important and ! important
|
||||||
|
if (strlen($string) >= 9 && substr($string, -9) === 'important') {
|
||||||
|
$temp = rtrim(substr($string, 0, -9));
|
||||||
|
// use a temp, because we might want to restore important
|
||||||
|
if (strlen($temp) >= 1 && substr($temp, -1) === '!') {
|
||||||
|
$string = rtrim(substr($temp, 0, -1));
|
||||||
|
$is_important = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$string = $this->def->validate($string, $config, $context);
|
||||||
|
if ($this->allow && $is_important) {
|
||||||
|
$string .= ' !important';
|
||||||
|
}
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Length as defined by CSS.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_Length|string
|
||||||
|
*/
|
||||||
|
protected $min;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_Length|string
|
||||||
|
*/
|
||||||
|
protected $max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_Length|string $min Minimum length, or null for no bound. String is also acceptable.
|
||||||
|
* @param HTMLPurifier_Length|string $max Maximum length, or null for no bound. String is also acceptable.
|
||||||
|
*/
|
||||||
|
public function __construct($min = null, $max = null)
|
||||||
|
{
|
||||||
|
$this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
|
||||||
|
$this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
|
||||||
|
// Optimizations
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($string === '0') {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
if (strlen($string) === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = HTMLPurifier_Length::make($string);
|
||||||
|
if (!$length->isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->min) {
|
||||||
|
$c = $length->compareTo($this->min);
|
||||||
|
if ($c === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($c < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->max) {
|
||||||
|
$c = $length->compareTo($this->max);
|
||||||
|
if ($c === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($c > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $length->toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,112 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates shorthand CSS property list-style.
|
||||||
|
* @warning Does not support url tokens that have internal spaces.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local copy of validators.
|
||||||
|
* @type HTMLPurifier_AttrDef[]
|
||||||
|
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
|
||||||
|
*/
|
||||||
|
protected $info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
*/
|
||||||
|
public function __construct($config)
|
||||||
|
{
|
||||||
|
$def = $config->getCSSDefinition();
|
||||||
|
$this->info['list-style-type'] = $def->info['list-style-type'];
|
||||||
|
$this->info['list-style-position'] = $def->info['list-style-position'];
|
||||||
|
$this->info['list-style-image'] = $def->info['list-style-image'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
// regular pre-processing
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// assumes URI doesn't have spaces in it
|
||||||
|
$bits = explode(' ', strtolower($string)); // bits to process
|
||||||
|
|
||||||
|
$caught = array();
|
||||||
|
$caught['type'] = false;
|
||||||
|
$caught['position'] = false;
|
||||||
|
$caught['image'] = false;
|
||||||
|
|
||||||
|
$i = 0; // number of catches
|
||||||
|
$none = false;
|
||||||
|
|
||||||
|
foreach ($bits as $bit) {
|
||||||
|
if ($i >= 3) {
|
||||||
|
return;
|
||||||
|
} // optimization bit
|
||||||
|
if ($bit === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($caught as $key => $status) {
|
||||||
|
if ($status !== false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
|
||||||
|
if ($r === false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($r === 'none') {
|
||||||
|
if ($none) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
$none = true;
|
||||||
|
}
|
||||||
|
if ($key == 'image') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$caught[$key] = $r;
|
||||||
|
$i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$i) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret = array();
|
||||||
|
|
||||||
|
// construct type
|
||||||
|
if ($caught['type']) {
|
||||||
|
$ret[] = $caught['type'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct image
|
||||||
|
if ($caught['image']) {
|
||||||
|
$ret[] = $caught['image'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// construct position
|
||||||
|
if ($caught['position']) {
|
||||||
|
$ret[] = $caught['position'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($ret)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return implode(' ', $ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Framework class for strings that involve multiple values.
|
||||||
|
*
|
||||||
|
* Certain CSS properties such as border-width and margin allow multiple
|
||||||
|
* lengths to be specified. This class can take a vanilla border-width
|
||||||
|
* definition and multiply it, usually into a max of four.
|
||||||
|
*
|
||||||
|
* @note Even though the CSS specification isn't clear about it, inherit
|
||||||
|
* can only be used alone: it will never manifest as part of a multi
|
||||||
|
* shorthand declaration. Thus, this class does not allow inherit.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Instance of component definition to defer validation to.
|
||||||
|
* @type HTMLPurifier_AttrDef
|
||||||
|
* @todo Make protected
|
||||||
|
*/
|
||||||
|
public $single;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max number of values allowed.
|
||||||
|
* @todo Make protected
|
||||||
|
*/
|
||||||
|
public $max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply
|
||||||
|
* @param int $max Max number of values allowed (usually four)
|
||||||
|
*/
|
||||||
|
public function __construct($single, $max = 4)
|
||||||
|
{
|
||||||
|
$this->single = $single;
|
||||||
|
$this->max = $max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = $this->mungeRgb($this->parseCDATA($string));
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
|
||||||
|
$length = count($parts);
|
||||||
|
$final = '';
|
||||||
|
for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
|
||||||
|
if (ctype_space($parts[$i])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$result = $this->single->validate($parts[$i], $config, $context);
|
||||||
|
if ($result !== false) {
|
||||||
|
$final .= $result . ' ';
|
||||||
|
$num++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($final === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return rtrim($final);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a number as defined by the CSS spec.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not only positive values are allowed.
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $non_negative = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $non_negative indicates whether negatives are forbidden
|
||||||
|
*/
|
||||||
|
public function __construct($non_negative = false)
|
||||||
|
{
|
||||||
|
$this->non_negative = $non_negative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $number
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return string|bool
|
||||||
|
* @warning Some contexts do not pass $config, $context. These
|
||||||
|
* variables should not be used without checking HTMLPurifier_Length
|
||||||
|
*/
|
||||||
|
public function validate($number, $config, $context)
|
||||||
|
{
|
||||||
|
$number = $this->parseCDATA($number);
|
||||||
|
|
||||||
|
if ($number === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($number === '0') {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
$sign = '';
|
||||||
|
switch ($number[0]) {
|
||||||
|
case '-':
|
||||||
|
if ($this->non_negative) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$sign = '-';
|
||||||
|
case '+':
|
||||||
|
$number = substr($number, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctype_digit($number)) {
|
||||||
|
$number = ltrim($number, '0');
|
||||||
|
return $number ? $sign . $number : '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Period is the only non-numeric character allowed
|
||||||
|
if (strpos($number, '.') === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
list($left, $right) = explode('.', $number, 2);
|
||||||
|
|
||||||
|
if ($left === '' && $right === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($left !== '' && !ctype_digit($left)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove leading zeros until positive number or a zero stays left
|
||||||
|
if (ltrim($left, '0') != '') {
|
||||||
|
$left = ltrim($left, '0');
|
||||||
|
} else {
|
||||||
|
$left = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
$right = rtrim($right, '0');
|
||||||
|
|
||||||
|
if ($right === '') {
|
||||||
|
return $left ? $sign . $left : '0';
|
||||||
|
} elseif (!ctype_digit($right)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $sign . $left . '.' . $right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a Percentage as defined by the CSS spec.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance to defer number validation to.
|
||||||
|
* @type HTMLPurifier_AttrDef_CSS_Number
|
||||||
|
*/
|
||||||
|
protected $number_def;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $non_negative Whether to forbid negative values
|
||||||
|
*/
|
||||||
|
public function __construct($non_negative = false)
|
||||||
|
{
|
||||||
|
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$length = strlen($string);
|
||||||
|
if ($length === 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($string[$length - 1] !== '%') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$number = substr($string, 0, $length - 1);
|
||||||
|
$number = $this->number_def->validate($number, $config, $context);
|
||||||
|
|
||||||
|
if ($number === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return "$number%";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
46
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
vendored
Normal file
46
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the value for the CSS property text-decoration
|
||||||
|
* @note This class could be generalized into a version that acts sort of
|
||||||
|
* like Enum except you can compound the allowed values.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
static $allowed_values = array(
|
||||||
|
'line-through' => true,
|
||||||
|
'overline' => true,
|
||||||
|
'underline' => true,
|
||||||
|
);
|
||||||
|
|
||||||
|
$string = strtolower($this->parseCDATA($string));
|
||||||
|
|
||||||
|
if ($string === 'none') {
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts = explode(' ', $string);
|
||||||
|
$final = '';
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
if (isset($allowed_values[$part])) {
|
||||||
|
$final .= $part . ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$final = rtrim($final);
|
||||||
|
if ($final === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $final;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a URI in CSS syntax, which uses url('http://example.com')
|
||||||
|
* @note While theoretically speaking a URI in a CSS document could
|
||||||
|
* be non-embedded, as of CSS2 there is no such usage so we're
|
||||||
|
* generalizing it. This may need to be changed in the future.
|
||||||
|
* @warning Since HTMLPurifier_AttrDef_CSS blindly uses semicolons as
|
||||||
|
* the separator, you cannot put a literal semicolon in
|
||||||
|
* in the URI. Try percent encoding it, in that case.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct(true); // always embedded
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $uri_string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($uri_string, $config, $context)
|
||||||
|
{
|
||||||
|
// parse the URI out of the string and then pass it onto
|
||||||
|
// the parent object
|
||||||
|
|
||||||
|
$uri_string = $this->parseCDATA($uri_string);
|
||||||
|
if (strpos($uri_string, 'url(') !== 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$uri_string = substr($uri_string, 4);
|
||||||
|
if (strlen($uri_string) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$new_length = strlen($uri_string) - 1;
|
||||||
|
if ($uri_string[$new_length] != ')') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$uri = trim(substr($uri_string, 0, $new_length));
|
||||||
|
|
||||||
|
if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
|
||||||
|
$quote = $uri[0];
|
||||||
|
$new_length = strlen($uri) - 1;
|
||||||
|
if ($uri[$new_length] !== $quote) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$uri = substr($uri, 1, $new_length - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$uri = $this->expandCSSEscape($uri);
|
||||||
|
|
||||||
|
$result = parent::validate($uri, $config, $context);
|
||||||
|
|
||||||
|
if ($result === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extra sanity check; should have been done by URI
|
||||||
|
$result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
|
||||||
|
|
||||||
|
// suspicious characters are ()'; we're going to percent encode
|
||||||
|
// them for safety.
|
||||||
|
$result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result);
|
||||||
|
|
||||||
|
// there's an extra bug where ampersands lose their escaping on
|
||||||
|
// an innerHTML cycle, so a very unlucky query parameter could
|
||||||
|
// then change the meaning of the URL. Unfortunately, there's
|
||||||
|
// not much we can do about that...
|
||||||
|
return "url(\"$result\")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy AttrDef that mimics another AttrDef, BUT it generates clones
|
||||||
|
* with make.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* What we're cloning.
|
||||||
|
* @type HTMLPurifier_AttrDef
|
||||||
|
*/
|
||||||
|
protected $clone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param HTMLPurifier_AttrDef $clone
|
||||||
|
*/
|
||||||
|
public function __construct($clone)
|
||||||
|
{
|
||||||
|
$this->clone = $clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $v
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($v, $config, $context)
|
||||||
|
{
|
||||||
|
return $this->clone->validate($v, $config, $context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @return HTMLPurifier_AttrDef
|
||||||
|
*/
|
||||||
|
public function make($string)
|
||||||
|
{
|
||||||
|
return clone $this->clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Enum = Enumerated
|
||||||
|
/**
|
||||||
|
* Validates a keyword against a list of valid values.
|
||||||
|
* @warning The case-insensitive compare of this function uses PHP's
|
||||||
|
* built-in strtolower and ctype_lower functions, which may
|
||||||
|
* cause problems with international comparisons
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup table of valid values.
|
||||||
|
* @type array
|
||||||
|
* @todo Make protected
|
||||||
|
*/
|
||||||
|
public $valid_values = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bool indicating whether or not enumeration is case sensitive.
|
||||||
|
* @note In general this is always case insensitive.
|
||||||
|
*/
|
||||||
|
protected $case_sensitive = false; // values according to W3C spec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $valid_values List of valid values
|
||||||
|
* @param bool $case_sensitive Whether or not case sensitive
|
||||||
|
*/
|
||||||
|
public function __construct($valid_values = array(), $case_sensitive = false)
|
||||||
|
{
|
||||||
|
$this->valid_values = array_flip($valid_values);
|
||||||
|
$this->case_sensitive = $case_sensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
if (!$this->case_sensitive) {
|
||||||
|
// we may want to do full case-insensitive libraries
|
||||||
|
$string = ctype_lower($string) ? $string : strtolower($string);
|
||||||
|
}
|
||||||
|
$result = isset($this->valid_values[$string]);
|
||||||
|
|
||||||
|
return $result ? $string : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string In form of comma-delimited list of case-insensitive
|
||||||
|
* valid values. Example: "foo,bar,baz". Prepend "s:" to make
|
||||||
|
* case sensitive
|
||||||
|
* @return HTMLPurifier_AttrDef_Enum
|
||||||
|
*/
|
||||||
|
public function make($string)
|
||||||
|
{
|
||||||
|
if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
|
||||||
|
$string = substr($string, 2);
|
||||||
|
$sensitive = true;
|
||||||
|
} else {
|
||||||
|
$sensitive = false;
|
||||||
|
}
|
||||||
|
$values = explode(',', $string);
|
||||||
|
return new HTMLPurifier_AttrDef_Enum($values, $sensitive);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a boolean attribute
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
public $minimized = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool|string $name
|
||||||
|
*/
|
||||||
|
public function __construct($name = false)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string Name of attribute
|
||||||
|
* @return HTMLPurifier_AttrDef_HTML_Bool
|
||||||
|
*/
|
||||||
|
public function make($string)
|
||||||
|
{
|
||||||
|
return new HTMLPurifier_AttrDef_HTML_Bool($string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements special behavior for class attribute (normally NMTOKENS)
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
protected function split($string, $config, $context)
|
||||||
|
{
|
||||||
|
// really, this twiddle should be lazy loaded
|
||||||
|
$name = $config->getDefinition('HTML')->doctype->name;
|
||||||
|
if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
|
||||||
|
return parent::split($string, $config, $context);
|
||||||
|
} else {
|
||||||
|
return preg_split('/\s+/', $string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $tokens
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function filter($tokens, $config, $context)
|
||||||
|
{
|
||||||
|
$allowed = $config->get('Attr.AllowedClasses');
|
||||||
|
$forbidden = $config->get('Attr.ForbiddenClasses');
|
||||||
|
$ret = array();
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
if (($allowed === null || isset($allowed[$token])) &&
|
||||||
|
!isset($forbidden[$token]) &&
|
||||||
|
// We need this O(n) check because of PHP's array
|
||||||
|
// implementation that casts -0 to 0.
|
||||||
|
!in_array($token, $ret, true)
|
||||||
|
) {
|
||||||
|
$ret[] = $token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a color according to the HTML spec.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
static $colors = null;
|
||||||
|
if ($colors === null) {
|
||||||
|
$colors = $config->get('Core.ColorKeywords');
|
||||||
|
}
|
||||||
|
|
||||||
|
$string = trim($string);
|
||||||
|
|
||||||
|
if (empty($string)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$lower = strtolower($string);
|
||||||
|
if (isset($colors[$lower])) {
|
||||||
|
return $colors[$lower];
|
||||||
|
}
|
||||||
|
if ($string[0] === '#') {
|
||||||
|
$hex = substr($string, 1);
|
||||||
|
} else {
|
||||||
|
$hex = $string;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = strlen($hex);
|
||||||
|
if ($length !== 3 && $length !== 6) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ctype_xdigit($hex)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($length === 3) {
|
||||||
|
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
|
||||||
|
}
|
||||||
|
return "#$hex";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
16
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ContentEditable.php
vendored
Normal file
16
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ContentEditable.php
vendored
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrDef_HTML_ContentEditable extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$allowed = array('false');
|
||||||
|
if ($config->get('HTML.Trusted')) {
|
||||||
|
$allowed = array('', 'true', 'false');
|
||||||
|
}
|
||||||
|
|
||||||
|
$enum = new HTMLPurifier_AttrDef_Enum($allowed);
|
||||||
|
|
||||||
|
return $enum->validate($string, $config, $context);
|
||||||
|
}
|
||||||
|
}
|
38
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
vendored
Normal file
38
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special-case enum attribute definition that lazy loads allowed frame targets
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type array
|
||||||
|
*/
|
||||||
|
public $valid_values = false; // uninitialized value
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $case_sensitive = false;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
if ($this->valid_values === false) {
|
||||||
|
$this->valid_values = $config->get('Attr.AllowedFrameTargets');
|
||||||
|
}
|
||||||
|
return parent::validate($string, $config, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the HTML attribute ID.
|
||||||
|
* @warning Even though this is the id processor, it
|
||||||
|
* will ignore the directive Attr:IDBlacklist, since it will only
|
||||||
|
* go according to the ID accumulator. Since the accumulator is
|
||||||
|
* automatically generated, it will have already absorbed the
|
||||||
|
* blacklist. If you're hacking around, make sure you use load()!
|
||||||
|
*/
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
// selector is NOT a valid thing to use for IDREFs, because IDREFs
|
||||||
|
// *must* target IDs that exist, whereas selector #ids do not.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not we're validating an ID in a CSS
|
||||||
|
* selector context.
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $selector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $selector
|
||||||
|
*/
|
||||||
|
public function __construct($selector = false)
|
||||||
|
{
|
||||||
|
$this->selector = $selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $id
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($id, $config, $context)
|
||||||
|
{
|
||||||
|
if (!$this->selector && !$config->get('Attr.EnableID')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = trim($id); // trim it first
|
||||||
|
|
||||||
|
if ($id === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$prefix = $config->get('Attr.IDPrefix');
|
||||||
|
if ($prefix !== '') {
|
||||||
|
$prefix .= $config->get('Attr.IDPrefixLocal');
|
||||||
|
// prevent re-appending the prefix
|
||||||
|
if (strpos($id, $prefix) !== 0) {
|
||||||
|
$id = $prefix . $id;
|
||||||
|
}
|
||||||
|
} elseif ($config->get('Attr.IDPrefixLocal') !== '') {
|
||||||
|
trigger_error(
|
||||||
|
'%Attr.IDPrefixLocal cannot be used unless ' .
|
||||||
|
'%Attr.IDPrefix is set',
|
||||||
|
E_USER_WARNING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->selector) {
|
||||||
|
$id_accumulator =& $context->get('IDAccumulator');
|
||||||
|
if (isset($id_accumulator->ids[$id])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we purposely avoid using regex, hopefully this is faster
|
||||||
|
|
||||||
|
if ($config->get('Attr.ID.HTML5') === true) {
|
||||||
|
if (preg_match('/[\t\n\x0b\x0c ]/', $id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ctype_alpha($id)) {
|
||||||
|
// OK
|
||||||
|
} else {
|
||||||
|
if (!ctype_alpha(@$id[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// primitive style of regexps, I suppose
|
||||||
|
$trim = trim(
|
||||||
|
$id,
|
||||||
|
'A..Za..z0..9:-._'
|
||||||
|
);
|
||||||
|
if ($trim !== '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$regexp = $config->get('Attr.IDBlacklistRegexp');
|
||||||
|
if ($regexp && preg_match($regexp, $id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->selector) {
|
||||||
|
$id_accumulator->add($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no change was made to the ID, return the result
|
||||||
|
// else, return the new id if stripping whitespace made it
|
||||||
|
// valid, or return false.
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the HTML type length (not to be confused with CSS's length).
|
||||||
|
*
|
||||||
|
* This accepts integer pixels or percentages as lengths for certain
|
||||||
|
* HTML attributes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parent_result = parent::validate($string, $config, $context);
|
||||||
|
if ($parent_result !== false) {
|
||||||
|
return $parent_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = strlen($string);
|
||||||
|
$last_char = $string[$length - 1];
|
||||||
|
|
||||||
|
if ($last_char !== '%') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$points = substr($string, 0, $length - 1);
|
||||||
|
|
||||||
|
if (!is_numeric($points)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$points = (int)$points;
|
||||||
|
|
||||||
|
if ($points < 0) {
|
||||||
|
return '0%';
|
||||||
|
}
|
||||||
|
if ($points > 100) {
|
||||||
|
return '100%';
|
||||||
|
}
|
||||||
|
return ((string)$points) . '%';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a rel/rev link attribute against a directive of allowed values
|
||||||
|
* @note We cannot use Enum because link types allow multiple
|
||||||
|
* values.
|
||||||
|
* @note Assumes link types are ASCII text
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name config attribute to pull.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
*/
|
||||||
|
public function __construct($name)
|
||||||
|
{
|
||||||
|
$configLookup = array(
|
||||||
|
'rel' => 'AllowedRel',
|
||||||
|
'rev' => 'AllowedRev'
|
||||||
|
);
|
||||||
|
if (!isset($configLookup[$name])) {
|
||||||
|
trigger_error(
|
||||||
|
'Unrecognized attribute name for link ' .
|
||||||
|
'relationship.',
|
||||||
|
E_USER_ERROR
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->name = $configLookup[$name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$allowed = $config->get('Attr.' . $this->name);
|
||||||
|
if (empty($allowed)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$string = $this->parseCDATA($string);
|
||||||
|
$parts = explode(' ', $string);
|
||||||
|
|
||||||
|
// lookup to prevent duplicates
|
||||||
|
$ret_lookup = array();
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
$part = strtolower(trim($part));
|
||||||
|
if (!isset($allowed[$part])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$ret_lookup[$part] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($ret_lookup)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$string = implode(' ', array_keys($ret_lookup));
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
60
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
vendored
Normal file
60
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
vendored
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a MultiLength as defined by the HTML spec.
|
||||||
|
*
|
||||||
|
* A multilength is either a integer (pixel count), a percentage, or
|
||||||
|
* a relative number.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parent_result = parent::validate($string, $config, $context);
|
||||||
|
if ($parent_result !== false) {
|
||||||
|
return $parent_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
$length = strlen($string);
|
||||||
|
$last_char = $string[$length - 1];
|
||||||
|
|
||||||
|
if ($last_char !== '*') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$int = substr($string, 0, $length - 1);
|
||||||
|
|
||||||
|
if ($int == '') {
|
||||||
|
return '*';
|
||||||
|
}
|
||||||
|
if (!is_numeric($int)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$int = (int)$int;
|
||||||
|
if ($int < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($int == 0) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
if ($int == 1) {
|
||||||
|
return '*';
|
||||||
|
}
|
||||||
|
return ((string)$int) . '*';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates contents based on NMTOKENS attribute type.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
|
||||||
|
// early abort: '' and '0' (strings that convert to false) are invalid
|
||||||
|
if (!$string) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tokens = $this->split($string, $config, $context);
|
||||||
|
$tokens = $this->filter($tokens, $config, $context);
|
||||||
|
if (empty($tokens)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return implode(' ', $tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits a space separated list of tokens into its constituent parts.
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function split($string, $config, $context)
|
||||||
|
{
|
||||||
|
// OPTIMIZABLE!
|
||||||
|
// do the preg_match, capture all subpatterns for reformulation
|
||||||
|
|
||||||
|
// we don't support U+00A1 and up codepoints or
|
||||||
|
// escaping because I don't know how to do that with regexps
|
||||||
|
// and plus it would complicate optimization efforts (you never
|
||||||
|
// see that anyway).
|
||||||
|
$pattern = '/(?:(?<=\s)|\A)' . // look behind for space or string start
|
||||||
|
'((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)' .
|
||||||
|
'(?:(?=\s)|\z)/'; // look ahead for space or string end
|
||||||
|
preg_match_all($pattern, $string, $matches);
|
||||||
|
return $matches[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template method for removing certain tokens based on arbitrary criteria.
|
||||||
|
* @note If we wanted to be really functional, we'd do an array_filter
|
||||||
|
* with a callback. But... we're not.
|
||||||
|
* @param array $tokens
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function filter($tokens, $config, $context)
|
||||||
|
{
|
||||||
|
return $tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates an integer representation of pixels according to the HTML spec.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type int
|
||||||
|
*/
|
||||||
|
protected $max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $max
|
||||||
|
*/
|
||||||
|
public function __construct($max = null)
|
||||||
|
{
|
||||||
|
$this->max = $max;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
if ($string === '0') {
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
if ($string === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$length = strlen($string);
|
||||||
|
if (substr($string, $length - 2) == 'px') {
|
||||||
|
$string = substr($string, 0, $length - 2);
|
||||||
|
}
|
||||||
|
if (!is_numeric($string)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$int = (int)$string;
|
||||||
|
|
||||||
|
if ($int < 0) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// upper-bound value, extremely high values can
|
||||||
|
// crash operating systems, see <http://ha.ckers.org/imagecrash.html>
|
||||||
|
// WARNING, above link WILL crash you if you're using Windows
|
||||||
|
|
||||||
|
if ($this->max !== null && $int > $this->max) {
|
||||||
|
return (string)$this->max;
|
||||||
|
}
|
||||||
|
return (string)$int;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @return HTMLPurifier_AttrDef
|
||||||
|
*/
|
||||||
|
public function make($string)
|
||||||
|
{
|
||||||
|
if ($string === '') {
|
||||||
|
$max = null;
|
||||||
|
} else {
|
||||||
|
$max = (int)$string;
|
||||||
|
}
|
||||||
|
$class = get_class($this);
|
||||||
|
return new $class($max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates an integer.
|
||||||
|
* @note While this class was modeled off the CSS definition, no currently
|
||||||
|
* allowed CSS uses this type. The properties that do are: widows,
|
||||||
|
* orphans, z-index, counter-increment, counter-reset. Some of the
|
||||||
|
* HTML attributes, however, find use for a non-negative version of this.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not negative values are allowed.
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $negative = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not zero is allowed.
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $zero = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not positive values are allowed.
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $positive = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $negative Bool indicating whether or not negative values are allowed
|
||||||
|
* @param $zero Bool indicating whether or not zero is allowed
|
||||||
|
* @param $positive Bool indicating whether or not positive values are allowed
|
||||||
|
*/
|
||||||
|
public function __construct($negative = true, $zero = true, $positive = true)
|
||||||
|
{
|
||||||
|
$this->negative = $negative;
|
||||||
|
$this->zero = $zero;
|
||||||
|
$this->positive = $positive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $integer
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($integer, $config, $context)
|
||||||
|
{
|
||||||
|
$integer = $this->parseCDATA($integer);
|
||||||
|
if ($integer === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we could possibly simply typecast it to integer, but there are
|
||||||
|
// certain fringe cases that must not return an integer.
|
||||||
|
|
||||||
|
// clip leading sign
|
||||||
|
if ($this->negative && $integer[0] === '-') {
|
||||||
|
$digits = substr($integer, 1);
|
||||||
|
if ($digits === '0') {
|
||||||
|
$integer = '0';
|
||||||
|
} // rm minus sign for zero
|
||||||
|
} elseif ($this->positive && $integer[0] === '+') {
|
||||||
|
$digits = $integer = substr($integer, 1); // rm unnecessary plus
|
||||||
|
} else {
|
||||||
|
$digits = $integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// test if it's numeric
|
||||||
|
if (!ctype_digit($digits)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform scope tests
|
||||||
|
if (!$this->zero && $integer == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$this->positive && $integer > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!$this->negative && $integer < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the HTML attribute lang, effectively a language code.
|
||||||
|
* @note Built according to RFC 3066, which obsoleted RFC 1766
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$string = trim($string);
|
||||||
|
if (!$string) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subtags = explode('-', $string);
|
||||||
|
$num_subtags = count($subtags);
|
||||||
|
|
||||||
|
if ($num_subtags == 0) { // sanity check
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process primary subtag : $subtags[0]
|
||||||
|
$length = strlen($subtags[0]);
|
||||||
|
switch ($length) {
|
||||||
|
case 0:
|
||||||
|
return false;
|
||||||
|
case 1:
|
||||||
|
if (!($subtags[0] == 'x' || $subtags[0] == 'i')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
if (!ctype_alpha($subtags[0])) {
|
||||||
|
return false;
|
||||||
|
} elseif (!ctype_lower($subtags[0])) {
|
||||||
|
$subtags[0] = strtolower($subtags[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_string = $subtags[0];
|
||||||
|
if ($num_subtags == 1) {
|
||||||
|
return $new_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process second subtag : $subtags[1]
|
||||||
|
$length = strlen($subtags[1]);
|
||||||
|
if ($length == 0 || ($length == 1 && $subtags[1] != 'x') || $length > 8 || !ctype_alnum($subtags[1])) {
|
||||||
|
return $new_string;
|
||||||
|
}
|
||||||
|
if (!ctype_lower($subtags[1])) {
|
||||||
|
$subtags[1] = strtolower($subtags[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$new_string .= '-' . $subtags[1];
|
||||||
|
if ($num_subtags == 2) {
|
||||||
|
return $new_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process all other subtags, index 2 and up
|
||||||
|
for ($i = 2; $i < $num_subtags; $i++) {
|
||||||
|
$length = strlen($subtags[$i]);
|
||||||
|
if ($length == 0 || $length > 8 || !ctype_alnum($subtags[$i])) {
|
||||||
|
return $new_string;
|
||||||
|
}
|
||||||
|
if (!ctype_lower($subtags[$i])) {
|
||||||
|
$subtags[$i] = strtolower($subtags[$i]);
|
||||||
|
}
|
||||||
|
$new_string .= '-' . $subtags[$i];
|
||||||
|
}
|
||||||
|
return $new_string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decorator that, depending on a token, switches between two definitions.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_Switch
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef
|
||||||
|
*/
|
||||||
|
protected $withTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef
|
||||||
|
*/
|
||||||
|
protected $withoutTag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $tag Tag name to switch upon
|
||||||
|
* @param HTMLPurifier_AttrDef $with_tag Call if token matches tag
|
||||||
|
* @param HTMLPurifier_AttrDef $without_tag Call if token doesn't match, or there is no token
|
||||||
|
*/
|
||||||
|
public function __construct($tag, $with_tag, $without_tag)
|
||||||
|
{
|
||||||
|
$this->tag = $tag;
|
||||||
|
$this->withTag = $with_tag;
|
||||||
|
$this->withoutTag = $without_tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$token = $context->get('CurrentToken', true);
|
||||||
|
if (!$token || $token->name !== $this->tag) {
|
||||||
|
return $this->withoutTag->validate($string, $config, $context);
|
||||||
|
} else {
|
||||||
|
return $this->withTag->validate($string, $config, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates arbitrary text according to the HTML spec.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
return $this->parseCDATA($string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,111 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a URI as defined by RFC 3986.
|
||||||
|
* @note Scheme-specific mechanics deferred to HTMLPurifier_URIScheme
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_URIParser
|
||||||
|
*/
|
||||||
|
protected $parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type bool
|
||||||
|
*/
|
||||||
|
protected $embedsResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $embeds_resource Does the URI here result in an extra HTTP request?
|
||||||
|
*/
|
||||||
|
public function __construct($embeds_resource = false)
|
||||||
|
{
|
||||||
|
$this->parser = new HTMLPurifier_URIParser();
|
||||||
|
$this->embedsResource = (bool)$embeds_resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @return HTMLPurifier_AttrDef_URI
|
||||||
|
*/
|
||||||
|
public function make($string)
|
||||||
|
{
|
||||||
|
$embeds = ($string === 'embedded');
|
||||||
|
return new HTMLPurifier_AttrDef_URI($embeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $uri
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($uri, $config, $context)
|
||||||
|
{
|
||||||
|
if ($config->get('URI.Disable')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$uri = $this->parseCDATA($uri);
|
||||||
|
|
||||||
|
// parse the URI
|
||||||
|
$uri = $this->parser->parse($uri);
|
||||||
|
if ($uri === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add embedded flag to context for validators
|
||||||
|
$context->register('EmbeddedURI', $this->embedsResource);
|
||||||
|
|
||||||
|
$ok = false;
|
||||||
|
do {
|
||||||
|
|
||||||
|
// generic validation
|
||||||
|
$result = $uri->validate($config, $context);
|
||||||
|
if (!$result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// chained filtering
|
||||||
|
$uri_def = $config->getDefinition('URI');
|
||||||
|
$result = $uri_def->filter($uri, $config, $context);
|
||||||
|
if (!$result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// scheme-specific validation
|
||||||
|
$scheme_obj = $uri->getSchemeObj($config, $context);
|
||||||
|
if (!$scheme_obj) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ($this->embedsResource && !$scheme_obj->browsable) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
$result = $scheme_obj->validate($uri, $config, $context);
|
||||||
|
if (!$result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post chained filtering
|
||||||
|
$result = $uri_def->postFilter($uri, $config, $context);
|
||||||
|
if (!$result) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// survived gauntlet
|
||||||
|
$ok = true;
|
||||||
|
|
||||||
|
} while (false);
|
||||||
|
|
||||||
|
$context->destroy('EmbeddedURI');
|
||||||
|
if (!$ok) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// back to string
|
||||||
|
return $uri->toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpacks a mailbox into its display-name and address
|
||||||
|
* @param string $string
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function unpack($string)
|
||||||
|
{
|
||||||
|
// needs to be implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// sub-implementations
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
29
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
vendored
Normal file
29
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primitive email validation class based on the regexp found at
|
||||||
|
* http://www.regular-expressions.info/email.html
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_URI_Email
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
// no support for named mailboxes i.e. "Bob <bob@example.com>"
|
||||||
|
// that needs more percent encoding to be done
|
||||||
|
if ($string == '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$string = trim($string);
|
||||||
|
$result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string);
|
||||||
|
return $result ? $string : false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IPv4 sub-validator.
|
||||||
|
* @type HTMLPurifier_AttrDef_URI_IPv4
|
||||||
|
*/
|
||||||
|
protected $ipv4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IPv6 sub-validator.
|
||||||
|
* @type HTMLPurifier_AttrDef_URI_IPv6
|
||||||
|
*/
|
||||||
|
protected $ipv6;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
|
||||||
|
$this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $string
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($string, $config, $context)
|
||||||
|
{
|
||||||
|
$length = strlen($string);
|
||||||
|
// empty hostname is OK; it's usually semantically equivalent:
|
||||||
|
// the default host as defined by a URI scheme is used:
|
||||||
|
//
|
||||||
|
// If the URI scheme defines a default for host, then that
|
||||||
|
// default applies when the host subcomponent is undefined
|
||||||
|
// or when the registered name is empty (zero length).
|
||||||
|
if ($string === '') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
if ($length > 1 && $string[0] === '[' && $string[$length - 1] === ']') {
|
||||||
|
//IPv6
|
||||||
|
$ip = substr($string, 1, $length - 2);
|
||||||
|
$valid = $this->ipv6->validate($ip, $config, $context);
|
||||||
|
if ($valid === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return '[' . $valid . ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to do checks on unusual encodings too
|
||||||
|
$ipv4 = $this->ipv4->validate($string, $config, $context);
|
||||||
|
if ($ipv4 !== false) {
|
||||||
|
return $ipv4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A regular domain name.
|
||||||
|
|
||||||
|
// This doesn't match I18N domain names, but we don't have proper IRI support,
|
||||||
|
// so force users to insert Punycode.
|
||||||
|
|
||||||
|
// There is not a good sense in which underscores should be
|
||||||
|
// allowed, since it's technically not! (And if you go as
|
||||||
|
// far to allow everything as specified by the DNS spec...
|
||||||
|
// well, that's literally everything, modulo some space limits
|
||||||
|
// for the components and the overall name (which, by the way,
|
||||||
|
// we are NOT checking!). So we (arbitrarily) decide this:
|
||||||
|
// let's allow underscores wherever we would have allowed
|
||||||
|
// hyphens, if they are enabled. This is a pretty good match
|
||||||
|
// for browser behavior, for example, a large number of browsers
|
||||||
|
// cannot handle foo_.example.com, but foo_bar.example.com is
|
||||||
|
// fairly well supported.
|
||||||
|
$underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : '';
|
||||||
|
|
||||||
|
// Based off of RFC 1738, but amended so that
|
||||||
|
// as per RFC 3696, the top label need only not be all numeric.
|
||||||
|
// The productions describing this are:
|
||||||
|
$a = '[a-z]'; // alpha
|
||||||
|
$an = '[a-z0-9]'; // alphanum
|
||||||
|
$and = "[a-z0-9-$underscore]"; // alphanum | "-"
|
||||||
|
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||||
|
$domainlabel = "$an(?:$and*$an)?";
|
||||||
|
// AMENDED as per RFC 3696
|
||||||
|
// toplabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||||
|
// side condition: not all numeric
|
||||||
|
$toplabel = "$an(?:$and*$an)?";
|
||||||
|
// hostname = *( domainlabel "." ) toplabel [ "." ]
|
||||||
|
if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $matches)) {
|
||||||
|
if (!ctype_digit($matches[1])) {
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PHP 5.3 and later support this functionality natively
|
||||||
|
if (function_exists('idn_to_ascii')) {
|
||||||
|
if (defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46')) {
|
||||||
|
$string = idn_to_ascii($string, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
|
||||||
|
} else {
|
||||||
|
$string = idn_to_ascii($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have Net_IDNA2 support, we can support IRIs by
|
||||||
|
// punycoding them. (This is the most portable thing to do,
|
||||||
|
// since otherwise we have to assume browsers support
|
||||||
|
} elseif ($config->get('Core.EnableIDNA')) {
|
||||||
|
$idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
|
||||||
|
// we need to encode each period separately
|
||||||
|
$parts = explode('.', $string);
|
||||||
|
try {
|
||||||
|
$new_parts = array();
|
||||||
|
foreach ($parts as $part) {
|
||||||
|
$encodable = false;
|
||||||
|
for ($i = 0, $c = strlen($part); $i < $c; $i++) {
|
||||||
|
if (ord($part[$i]) > 0x7a) {
|
||||||
|
$encodable = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$encodable) {
|
||||||
|
$new_parts[] = $part;
|
||||||
|
} else {
|
||||||
|
$new_parts[] = $idna->encode($part);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$string = implode('.', $new_parts);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
// XXX error reporting
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Try again
|
||||||
|
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
|
||||||
|
return $string;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates an IPv4 address
|
||||||
|
* @author Feyd @ forums.devnetwork.net (public domain)
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_URI_IPv4 extends HTMLPurifier_AttrDef
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IPv4 regex, protected so that IPv6 can reuse it.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $ip4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $aIP
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($aIP, $config, $context)
|
||||||
|
{
|
||||||
|
if (!$this->ip4) {
|
||||||
|
$this->_loadRegex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preg_match('#^' . $this->ip4 . '$#s', $aIP)) {
|
||||||
|
return $aIP;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lazy load function to prevent regex from being stuffed in
|
||||||
|
* cache.
|
||||||
|
*/
|
||||||
|
protected function _loadRegex()
|
||||||
|
{
|
||||||
|
$oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255
|
||||||
|
$this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates an IPv6 address.
|
||||||
|
* @author Feyd @ forums.devnetwork.net (public domain)
|
||||||
|
* @note This function requires brackets to have been removed from address
|
||||||
|
* in URI.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $aIP
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public function validate($aIP, $config, $context)
|
||||||
|
{
|
||||||
|
if (!$this->ip4) {
|
||||||
|
$this->_loadRegex();
|
||||||
|
}
|
||||||
|
|
||||||
|
$original = $aIP;
|
||||||
|
|
||||||
|
$hex = '[0-9a-fA-F]';
|
||||||
|
$blk = '(?:' . $hex . '{1,4})';
|
||||||
|
$pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128
|
||||||
|
|
||||||
|
// prefix check
|
||||||
|
if (strpos($aIP, '/') !== false) {
|
||||||
|
if (preg_match('#' . $pre . '$#s', $aIP, $find)) {
|
||||||
|
$aIP = substr($aIP, 0, 0 - strlen($find[0]));
|
||||||
|
unset($find);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPv4-compatiblity check
|
||||||
|
if (preg_match('#(?<=:' . ')' . $this->ip4 . '$#s', $aIP, $find)) {
|
||||||
|
$aIP = substr($aIP, 0, 0 - strlen($find[0]));
|
||||||
|
$ip = explode('.', $find[0]);
|
||||||
|
$ip = array_map('dechex', $ip);
|
||||||
|
$aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
|
||||||
|
unset($find, $ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compression check
|
||||||
|
$aIP = explode('::', $aIP);
|
||||||
|
$c = count($aIP);
|
||||||
|
if ($c > 2) {
|
||||||
|
return false;
|
||||||
|
} elseif ($c == 2) {
|
||||||
|
list($first, $second) = $aIP;
|
||||||
|
$first = explode(':', $first);
|
||||||
|
$second = explode(':', $second);
|
||||||
|
|
||||||
|
if (count($first) + count($second) > 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count($first) < 8) {
|
||||||
|
array_push($first, '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
array_splice($first, 8 - count($second), 8, $second);
|
||||||
|
$aIP = $first;
|
||||||
|
unset($first, $second);
|
||||||
|
} else {
|
||||||
|
$aIP = explode(':', $aIP[0]);
|
||||||
|
}
|
||||||
|
$c = count($aIP);
|
||||||
|
|
||||||
|
if ($c != 8) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the pieces should be 16-bit hex strings. Are they?
|
||||||
|
foreach ($aIP as $piece) {
|
||||||
|
if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $original;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes an entire attribute array for corrections needing multiple values.
|
||||||
|
*
|
||||||
|
* Occasionally, a certain attribute will need to be removed and popped onto
|
||||||
|
* another value. Instead of creating a complex return syntax for
|
||||||
|
* HTMLPurifier_AttrDef, we just pass the whole attribute array to a
|
||||||
|
* specialized object and have that do the special work. That is the
|
||||||
|
* family of HTMLPurifier_AttrTransform.
|
||||||
|
*
|
||||||
|
* An attribute transformation can be assigned to run before or after
|
||||||
|
* HTMLPurifier_AttrDef validation. See HTMLPurifier_HTMLDefinition for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abstract class HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract: makes changes to the attributes dependent on multiple values.
|
||||||
|
*
|
||||||
|
* @param array $attr Assoc array of attributes, usually from
|
||||||
|
* HTMLPurifier_Token_Tag::$attr
|
||||||
|
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
|
||||||
|
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object
|
||||||
|
* @return array Processed attribute array.
|
||||||
|
*/
|
||||||
|
abstract public function transform($attr, $config, $context);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepends CSS properties to the style attribute, creating the
|
||||||
|
* attribute if it doesn't exist.
|
||||||
|
* @param array &$attr Attribute array to process (passed by reference)
|
||||||
|
* @param string $css CSS to prepend
|
||||||
|
*/
|
||||||
|
public function prependCSS(&$attr, $css)
|
||||||
|
{
|
||||||
|
$attr['style'] = isset($attr['style']) ? $attr['style'] : '';
|
||||||
|
$attr['style'] = $css . $attr['style'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves and removes an attribute
|
||||||
|
* @param array &$attr Attribute array to process (passed by reference)
|
||||||
|
* @param mixed $key Key of attribute to confiscate
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function confiscateAttr(&$attr, $key)
|
||||||
|
{
|
||||||
|
if (!isset($attr[$key])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$value = $attr[$key];
|
||||||
|
unset($attr[$key]);
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
28
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php
vendored
Normal file
28
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-transform that changes proprietary background attribute to CSS.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['background'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$background = $this->confiscateAttr($attr, 'background');
|
||||||
|
// some validation should happen here
|
||||||
|
|
||||||
|
$this->prependCSS($attr, "background-image:url($background);");
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// this MUST be placed in post, as it assumes that any value in dir is valid
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-trasnform that ensures that bdo tags have the dir attribute set.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (isset($attr['dir'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$attr['dir'] = $config->get('Attr.DefaultTextDir');
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-transform that changes deprecated bgcolor attribute to CSS.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['bgcolor'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bgcolor = $this->confiscateAttr($attr, 'bgcolor');
|
||||||
|
// some validation should happen here
|
||||||
|
|
||||||
|
$this->prependCSS($attr, "background-color:$bgcolor;");
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-transform that changes converts a boolean attribute to fixed CSS
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_BoolToCSS extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Name of boolean attribute that is trigger.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $attr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CSS declarations to add to style, needs trailing semicolon.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $css;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $attr attribute name to convert from
|
||||||
|
* @param string $css CSS declarations to add to style (needs semicolon)
|
||||||
|
*/
|
||||||
|
public function __construct($attr, $css)
|
||||||
|
{
|
||||||
|
$this->attr = $attr;
|
||||||
|
$this->css = $css;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr[$this->attr])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
unset($attr[$this->attr]);
|
||||||
|
$this->prependCSS($attr, $this->css);
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-transform that changes deprecated border attribute to CSS.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['border'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$border_width = $this->confiscateAttr($attr, 'border');
|
||||||
|
// some validation should happen here
|
||||||
|
$this->prependCSS($attr, "border:{$border_width}px solid;");
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,68 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic pre-transform that converts an attribute with a fixed number of
|
||||||
|
* values (enumerated) to CSS.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Name of attribute to transform from.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $attr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup array of attribute values to CSS.
|
||||||
|
* @type array
|
||||||
|
*/
|
||||||
|
protected $enumToCSS = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Case sensitivity of the matching.
|
||||||
|
* @type bool
|
||||||
|
* @warning Currently can only be guaranteed to work with ASCII
|
||||||
|
* values.
|
||||||
|
*/
|
||||||
|
protected $caseSensitive = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $attr Attribute name to transform from
|
||||||
|
* @param array $enum_to_css Lookup array of attribute values to CSS
|
||||||
|
* @param bool $case_sensitive Case sensitivity indicator, default false
|
||||||
|
*/
|
||||||
|
public function __construct($attr, $enum_to_css, $case_sensitive = false)
|
||||||
|
{
|
||||||
|
$this->attr = $attr;
|
||||||
|
$this->enumToCSS = $enum_to_css;
|
||||||
|
$this->caseSensitive = (bool)$case_sensitive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr[$this->attr])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = trim($attr[$this->attr]);
|
||||||
|
unset($attr[$this->attr]);
|
||||||
|
|
||||||
|
if (!$this->caseSensitive) {
|
||||||
|
$value = strtolower($value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($this->enumToCSS[$value])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$this->prependCSS($attr, $this->enumToCSS[$value]);
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
47
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php
vendored
Normal file
47
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// must be called POST validation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transform that supplies default values for the src and alt attributes
|
||||||
|
* in img tags, as well as prevents the img tag from being removed
|
||||||
|
* because of a missing alt tag. This needs to be registered as both
|
||||||
|
* a pre and post attribute transform.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
$src = true;
|
||||||
|
if (!isset($attr['src'])) {
|
||||||
|
if ($config->get('Core.RemoveInvalidImg')) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$attr['src'] = $config->get('Attr.DefaultInvalidImage');
|
||||||
|
$src = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($attr['alt'])) {
|
||||||
|
if ($src) {
|
||||||
|
$alt = $config->get('Attr.DefaultImageAlt');
|
||||||
|
if ($alt === null) {
|
||||||
|
$attr['alt'] = basename($attr['src']);
|
||||||
|
} else {
|
||||||
|
$attr['alt'] = $alt;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-transform that changes deprecated hspace and vspace attributes to CSS
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_ImgSpace extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $attr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type array
|
||||||
|
*/
|
||||||
|
protected $css = array(
|
||||||
|
'hspace' => array('left', 'right'),
|
||||||
|
'vspace' => array('top', 'bottom')
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $attr
|
||||||
|
*/
|
||||||
|
public function __construct($attr)
|
||||||
|
{
|
||||||
|
$this->attr = $attr;
|
||||||
|
if (!isset($this->css[$attr])) {
|
||||||
|
trigger_error(htmlspecialchars($attr) . ' is not valid space attribute');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr[$this->attr])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$width = $this->confiscateAttr($attr, $this->attr);
|
||||||
|
// some validation could happen here
|
||||||
|
|
||||||
|
if (!isset($this->css[$this->attr])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
$style = '';
|
||||||
|
foreach ($this->css[$this->attr] as $suffix) {
|
||||||
|
$property = "margin-$suffix";
|
||||||
|
$style .= "$property:{$width}px;";
|
||||||
|
}
|
||||||
|
$this->prependCSS($attr, $style);
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs miscellaneous cross attribute validation and filtering for
|
||||||
|
* input elements. This is meant to be a post-transform.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_HTML_Pixels
|
||||||
|
*/
|
||||||
|
protected $pixels;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->pixels = new HTMLPurifier_AttrDef_HTML_Pixels();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['type'])) {
|
||||||
|
$t = 'text';
|
||||||
|
} else {
|
||||||
|
$t = strtolower($attr['type']);
|
||||||
|
}
|
||||||
|
if (isset($attr['checked']) && $t !== 'radio' && $t !== 'checkbox') {
|
||||||
|
unset($attr['checked']);
|
||||||
|
}
|
||||||
|
if (isset($attr['maxlength']) && $t !== 'text' && $t !== 'password') {
|
||||||
|
unset($attr['maxlength']);
|
||||||
|
}
|
||||||
|
if (isset($attr['size']) && $t !== 'text' && $t !== 'password') {
|
||||||
|
$result = $this->pixels->validate($attr['size'], $config, $context);
|
||||||
|
if ($result === false) {
|
||||||
|
unset($attr['size']);
|
||||||
|
} else {
|
||||||
|
$attr['size'] = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($attr['src']) && $t !== 'image') {
|
||||||
|
unset($attr['src']);
|
||||||
|
}
|
||||||
|
if (!isset($attr['value']) && ($t === 'radio' || $t === 'checkbox')) {
|
||||||
|
$attr['value'] = '';
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-transform that copies lang's value to xml:lang (and vice-versa)
|
||||||
|
* @note Theoretically speaking, this could be a pre-transform, but putting
|
||||||
|
* post is more efficient.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
$lang = isset($attr['lang']) ? $attr['lang'] : false;
|
||||||
|
$xml_lang = isset($attr['xml:lang']) ? $attr['xml:lang'] : false;
|
||||||
|
|
||||||
|
if ($lang !== false && $xml_lang === false) {
|
||||||
|
$attr['xml:lang'] = $lang;
|
||||||
|
} elseif ($xml_lang !== false) {
|
||||||
|
$attr['lang'] = $xml_lang;
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for handling width/height length attribute transformations to CSS
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
protected $cssName;
|
||||||
|
|
||||||
|
public function __construct($name, $css_name = null)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
$this->cssName = $css_name ? $css_name : $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr[$this->name])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$length = $this->confiscateAttr($attr, $this->name);
|
||||||
|
if (ctype_digit($length)) {
|
||||||
|
$length .= 'px';
|
||||||
|
}
|
||||||
|
$this->prependCSS($attr, $this->cssName . ":$length;");
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pre-transform that changes deprecated name attribute to ID if necessary
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
// Abort early if we're using relaxed definition of name
|
||||||
|
if ($config->get('HTML.Attr.Name.UseCDATA')) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
if (!isset($attr['name'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$id = $this->confiscateAttr($attr, 'name');
|
||||||
|
if (isset($attr['id'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$attr['id'] = $id;
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post-transform that performs validation to the name attribute; if
|
||||||
|
* it is present with an equivalent id attribute, it is passed through;
|
||||||
|
* otherwise validation is performed.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_HTML_ID
|
||||||
|
*/
|
||||||
|
public $idDef;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['name'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$name = $attr['name'];
|
||||||
|
if (isset($attr['id']) && $attr['id'] === $name) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
$result = $this->idDef->validate($name, $config, $context);
|
||||||
|
if ($result === false) {
|
||||||
|
unset($attr['name']);
|
||||||
|
} else {
|
||||||
|
$attr['name'] = $result;
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// must be called POST validation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds rel="nofollow" to all outbound links. This transform is
|
||||||
|
* only attached if Attr.Nofollow is TRUE.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_Nofollow extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_URIParser
|
||||||
|
*/
|
||||||
|
private $parser;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->parser = new HTMLPurifier_URIParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['href'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Kind of inefficient
|
||||||
|
$url = $this->parser->parse($attr['href']);
|
||||||
|
$scheme = $url->getSchemeObj($config, $context);
|
||||||
|
|
||||||
|
if ($scheme->browsable && !$url->isLocal($config, $context)) {
|
||||||
|
if (isset($attr['rel'])) {
|
||||||
|
$rels = explode(' ', $attr['rel']);
|
||||||
|
if (!in_array('nofollow', $rels)) {
|
||||||
|
$rels[] = 'nofollow';
|
||||||
|
}
|
||||||
|
$attr['rel'] = implode(' ', $rels);
|
||||||
|
} else {
|
||||||
|
$attr['rel'] = 'nofollow';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrTransform_SafeEmbed extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
public $name = "SafeEmbed";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
$attr['allowscriptaccess'] = 'never';
|
||||||
|
$attr['allownetworking'] = 'internal';
|
||||||
|
$attr['type'] = 'application/x-shockwave-flash';
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
28
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php
vendored
Normal file
28
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes default type for all objects. Currently only supports flash.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_SafeObject extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
public $name = "SafeObject";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['type'])) {
|
||||||
|
$attr['type'] = 'application/x-shockwave-flash';
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates name/value pairs in param tags to be used in safe objects. This
|
||||||
|
* will only allow name values it recognizes, and pre-fill certain attributes
|
||||||
|
* with required values.
|
||||||
|
*
|
||||||
|
* @note
|
||||||
|
* This class only supports Flash. In the future, Quicktime support
|
||||||
|
* may be added.
|
||||||
|
*
|
||||||
|
* @warning
|
||||||
|
* This class expects an injector to add the necessary parameters tags.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_SafeParam extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
public $name = "SafeParam";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_URI
|
||||||
|
*/
|
||||||
|
private $uri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_AttrDef_Enum
|
||||||
|
*/
|
||||||
|
public $wmode;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->uri = new HTMLPurifier_AttrDef_URI(true); // embedded
|
||||||
|
$this->wmode = new HTMLPurifier_AttrDef_Enum(array('window', 'opaque', 'transparent'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
// If we add support for other objects, we'll need to alter the
|
||||||
|
// transforms.
|
||||||
|
switch ($attr['name']) {
|
||||||
|
// application/x-shockwave-flash
|
||||||
|
// Keep this synchronized with Injector/SafeObject.php
|
||||||
|
case 'allowScriptAccess':
|
||||||
|
$attr['value'] = 'never';
|
||||||
|
break;
|
||||||
|
case 'allowNetworking':
|
||||||
|
$attr['value'] = 'internal';
|
||||||
|
break;
|
||||||
|
case 'allowFullScreen':
|
||||||
|
if ($config->get('HTML.FlashAllowFullScreen')) {
|
||||||
|
$attr['value'] = ($attr['value'] == 'true') ? 'true' : 'false';
|
||||||
|
} else {
|
||||||
|
$attr['value'] = 'false';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'wmode':
|
||||||
|
$attr['value'] = $this->wmode->validate($attr['value'], $config, $context);
|
||||||
|
break;
|
||||||
|
case 'movie':
|
||||||
|
case 'src':
|
||||||
|
$attr['name'] = "movie";
|
||||||
|
$attr['value'] = $this->uri->validate($attr['value'], $config, $context);
|
||||||
|
break;
|
||||||
|
case 'flashvars':
|
||||||
|
// we're going to allow arbitrary inputs to the SWF, on
|
||||||
|
// the reasoning that it could only hack the SWF, not us.
|
||||||
|
break;
|
||||||
|
// add other cases to support other param name/value pairs
|
||||||
|
default:
|
||||||
|
$attr['name'] = $attr['value'] = null;
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
23
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php
vendored
Normal file
23
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements required attribute stipulation for <script>
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['type'])) {
|
||||||
|
$attr['type'] = 'text/javascript';
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
45
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php
vendored
Normal file
45
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php
vendored
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// must be called POST validation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds target="blank" to all outbound links. This transform is
|
||||||
|
* only attached if Attr.TargetBlank is TRUE. This works regardless
|
||||||
|
* of whether or not Attr.AllowedFrameTargets
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @type HTMLPurifier_URIParser
|
||||||
|
*/
|
||||||
|
private $parser;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->parser = new HTMLPurifier_URIParser();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (!isset($attr['href'])) {
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX Kind of inefficient
|
||||||
|
$url = $this->parser->parse($attr['href']);
|
||||||
|
$scheme = $url->getSchemeObj($config, $context);
|
||||||
|
|
||||||
|
if ($scheme->browsable && !$url->isBenign($config, $context)) {
|
||||||
|
$attr['target'] = '_blank';
|
||||||
|
}
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim: et sw=4 sts=4
|
37
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php
vendored
Normal file
37
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// must be called POST validation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds rel="noopener" to any links which target a different window
|
||||||
|
* than the current one. This is used to prevent malicious websites
|
||||||
|
* from silently replacing the original window, which could be used
|
||||||
|
* to do phishing.
|
||||||
|
* This transform is controlled by %HTML.TargetNoopener.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_TargetNoopener extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (isset($attr['rel'])) {
|
||||||
|
$rels = explode(' ', $attr['rel']);
|
||||||
|
} else {
|
||||||
|
$rels = array();
|
||||||
|
}
|
||||||
|
if (isset($attr['target']) && !in_array('noopener', $rels)) {
|
||||||
|
$rels[] = 'noopener';
|
||||||
|
}
|
||||||
|
if (!empty($rels) || isset($attr['rel'])) {
|
||||||
|
$attr['rel'] = implode(' ', $rels);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
37
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php
vendored
Normal file
37
vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php
vendored
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// must be called POST validation
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds rel="noreferrer" to any links which target a different window
|
||||||
|
* than the current one. This is used to prevent malicious websites
|
||||||
|
* from silently replacing the original window, which could be used
|
||||||
|
* to do phishing.
|
||||||
|
* This transform is controlled by %HTML.TargetNoreferrer.
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrTransform_TargetNoreferrer extends HTMLPurifier_AttrTransform
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $attr
|
||||||
|
* @param HTMLPurifier_Config $config
|
||||||
|
* @param HTMLPurifier_Context $context
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function transform($attr, $config, $context)
|
||||||
|
{
|
||||||
|
if (isset($attr['rel'])) {
|
||||||
|
$rels = explode(' ', $attr['rel']);
|
||||||
|
} else {
|
||||||
|
$rels = array();
|
||||||
|
}
|
||||||
|
if (isset($attr['target']) && !in_array('noreferrer', $rels)) {
|
||||||
|
$rels[] = 'noreferrer';
|
||||||
|
}
|
||||||
|
if (!empty($rels) || isset($attr['rel'])) {
|
||||||
|
$attr['rel'] = implode(' ', $rels);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $attr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue