mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-01-03 05:11:52 +00:00
Revamp configuration files so that more rules can be added, internal organization is more logical, and descriptions are captured.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@327 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
parent
0d4ee2ba37
commit
24cde9c891
@ -6,8 +6,9 @@ help you find the correct functionality more quickly. Here they are:
|
||||
|
||||
All classes occupy the HTMLPurifier pseudo-namespace.
|
||||
This means that all classes are prefixed with HTMLPurifier_. As such, all
|
||||
names under HTMLPurifier_ are reserved, and userspace extensions should
|
||||
be registered in a different namespace (or the main namespace).
|
||||
names under HTMLPurifier_ are reserved. I recommend that you use the name
|
||||
HTMLPurifierX_YourName_ClassName, especially if you want to take advantage
|
||||
of HTMLPurifier_ConfigDef.
|
||||
|
||||
All classes correspond to their path if library/ was in the include path
|
||||
HTMLPurifier_AttrDef is located at HTMLPurifier/AttrDef.php; replace
|
||||
|
@ -28,6 +28,26 @@ require_once 'HTMLPurifier/HTMLDefinition.php';
|
||||
require_once 'HTMLPurifier/Generator.php';
|
||||
require_once 'HTMLPurifier/Strategy/Core.php';
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'Encoding', 'utf-8', 'istring',
|
||||
'Defines the input and output character encodings to use. HTMLPurifier '.
|
||||
'internally uses UTF-8, making that the painless default choice. Note '.
|
||||
'certain implementations of HTMLPurifier_Lexer are intelligent enough '.
|
||||
'automatically detect encoding, however, output format will always be '.
|
||||
'this value.'
|
||||
);
|
||||
HTMLPurifier_ConfigDef::defineAllowedValues(
|
||||
'Core', 'Encoding', array(
|
||||
'utf-8',
|
||||
'iso-8859-1'
|
||||
)
|
||||
);
|
||||
HTMLPurifier_ConfigDef::defineValueAliases(
|
||||
'Core', 'Encoding', array(
|
||||
'iso8859-1' => 'iso-8859-1'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Main library execution class.
|
||||
*
|
||||
|
@ -6,7 +6,7 @@ require_once 'HTMLPurifier/URISchemeRegistry.php';
|
||||
require_once 'HTMLPurifier/AttrDef/Host.php';
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'URI', 'DefaultScheme', 'http',
|
||||
'URI', 'DefaultScheme', 'http', 'string',
|
||||
'Defines through what scheme the output will be served, in order to '.
|
||||
'select the proper object validator when no scheme information is present.'
|
||||
);
|
||||
|
@ -5,11 +5,14 @@ require_once 'HTMLPurifier/AttrTransform.php';
|
||||
// this MUST be placed in post, as it assumes that any value in dir is valid
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Attr', 'DefaultTextDir', 'ltr',
|
||||
'Attr', 'DefaultTextDir', 'ltr', 'string',
|
||||
'Defines the default text direction (ltr or rtl) of the document '.
|
||||
'being parsed. This generally is the same as the value of the dir '.
|
||||
'attribute in HTML, or ltr if that is not specified.'
|
||||
);
|
||||
HTMLPurifier_ConfigDef::defineAllowedValues(
|
||||
'Attr', 'DefaultTextDir', array( 'ltr', 'rtl' )
|
||||
);
|
||||
|
||||
/**
|
||||
* Post-trasnform that ensures that bdo tags have the dir attribute set.
|
||||
|
@ -5,7 +5,7 @@ require_once 'HTMLPurifier/AttrTransform.php';
|
||||
// must be called POST validation
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Attr', 'DefaultInvalidImage', '',
|
||||
'Attr', 'DefaultInvalidImage', '', 'string',
|
||||
'This is the default image an img tag will be pointed to if it does '.
|
||||
'not have a valid src attribute. In future versions, we may allow the '.
|
||||
'image tag to be removed completely, but due to design issues, this is '.
|
||||
@ -13,7 +13,7 @@ HTMLPurifier_ConfigDef::define(
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Attr', 'DefaultInvalidImageAlt', 'Invalid image',
|
||||
'Attr', 'DefaultInvalidImageAlt', 'Invalid image', 'string',
|
||||
'This is the content of the alt tag of an invalid image if the user '.
|
||||
'had not previously specified an alt attribute. It has no effect when the '.
|
||||
'image is valid but there was no alt attribute present.'
|
||||
|
@ -13,7 +13,7 @@
|
||||
// in order to make it self correcting
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'EscapeInvalidChildren', false,
|
||||
'Core', 'EscapeInvalidChildren', false, 'bool',
|
||||
'When true, a child is found that is not allowed in the context of the '.
|
||||
'parent element will be transformed into text as if it were ASCII. When '.
|
||||
'false, that element and all internal tags will be dropped, though text '.
|
||||
|
@ -20,12 +20,18 @@ class HTMLPurifier_Config
|
||||
*/
|
||||
var $conf;
|
||||
|
||||
/**
|
||||
* Reference HTMLPurifier_ConfigDef for value checking
|
||||
*/
|
||||
var $def;
|
||||
|
||||
/**
|
||||
* @param $definition HTMLPurifier_ConfigDef that defines what directives
|
||||
* are allowed.
|
||||
*/
|
||||
function HTMLPurifier_Config(&$definition) {
|
||||
$this->conf = $definition->info; // set up the defaults
|
||||
$this->conf = $definition->defaults; // set up, copy in defaults
|
||||
$this->def = $definition; // keep a copy around for checking
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,7 +52,7 @@ class HTMLPurifier_Config
|
||||
function get($namespace, $key) {
|
||||
if (!isset($this->conf[$namespace][$key])) {
|
||||
trigger_error('Cannot retrieve value of undefined directive',
|
||||
E_USER_ERROR);
|
||||
E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
return $this->conf[$namespace][$key];
|
||||
@ -61,7 +67,26 @@ class HTMLPurifier_Config
|
||||
function set($namespace, $key, $value) {
|
||||
if (!isset($this->conf[$namespace][$key])) {
|
||||
trigger_error('Cannot set undefined directive to value',
|
||||
E_USER_ERROR);
|
||||
E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
if (is_string($value)) {
|
||||
// resolve value alias if defined
|
||||
if (isset($this->def->info[$namespace][$key]->aliases[$value])) {
|
||||
$value = $this->def->info[$namespace][$key]->aliases[$value];
|
||||
}
|
||||
if ($this->def->info[$namespace][$key]->allowed !== true) {
|
||||
// check to see if the value is allowed
|
||||
if (!isset($this->def->info[$namespace][$key]->allowed[$value])) {
|
||||
trigger_error('Value not supported', E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$value = $this->def->validate($value,
|
||||
$this->def->info[$namespace][$key]->type);
|
||||
if ($value === null) {
|
||||
trigger_error('Value is of invalid type', E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
$this->conf[$namespace][$key] = $value;
|
||||
|
@ -7,11 +7,36 @@
|
||||
class HTMLPurifier_ConfigDef {
|
||||
|
||||
/**
|
||||
* Currently defined directives (and namespaces).
|
||||
* Defaults of the directives and namespaces.
|
||||
* @note This shares the exact same structure as HTMLPurifier_Config::$conf
|
||||
*/
|
||||
var $defaults = array();
|
||||
|
||||
/**
|
||||
* Definition of the directives.
|
||||
*/
|
||||
var $info = array();
|
||||
|
||||
/**
|
||||
* Definition of namespaces.
|
||||
*/
|
||||
var $info_namespace = array();
|
||||
|
||||
/**
|
||||
* Lookup table of allowed types.
|
||||
*/
|
||||
var $types = array(
|
||||
'string' => true,
|
||||
'istring' => true,
|
||||
'int' => true,
|
||||
'float' => true,
|
||||
'bool' => true,
|
||||
'lookup' => true,
|
||||
'list' => true,
|
||||
'hash' => true,
|
||||
'mixed' => true
|
||||
);
|
||||
|
||||
/**
|
||||
* Initializes the default namespaces.
|
||||
*/
|
||||
@ -44,9 +69,14 @@ class HTMLPurifier_ConfigDef {
|
||||
* @param $namespace Namespace the directive is in
|
||||
* @param $name Key of directive
|
||||
* @param $default Default value of directive
|
||||
* @param $type Allowed type of the directive. See
|
||||
* HTMLPurifier_DirectiveDef::$type for allowed values
|
||||
* @param $description Description of directive for documentation
|
||||
*/
|
||||
function define($namespace, $name, $default, $description) {
|
||||
function define(
|
||||
$namespace, $name, $default, $type,
|
||||
$description
|
||||
) {
|
||||
$def =& HTMLPurifier_ConfigDef::instance();
|
||||
if (!isset($def->info[$namespace])) {
|
||||
trigger_error('Cannot define directive for undefined namespace',
|
||||
@ -54,11 +84,33 @@ class HTMLPurifier_ConfigDef {
|
||||
return;
|
||||
}
|
||||
if (isset($def->info[$namespace][$name])) {
|
||||
// this behavior is at risk of change
|
||||
trigger_error('Cannot redefine directive', E_USER_ERROR);
|
||||
if (
|
||||
$def->info[$namespace][$name]->type !== $type ||
|
||||
$def->defaults[$namespace][$name] !== $default
|
||||
) {
|
||||
trigger_error('Inconsistent default or type, cannot redefine');
|
||||
return;
|
||||
}
|
||||
$def->info[$namespace][$name] = $default;
|
||||
} else {
|
||||
if (!isset($def->types[$type])) {
|
||||
trigger_error('Invalid type for configuration directive',
|
||||
E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
if ($def->validate($default, $type) === null) {
|
||||
trigger_error('Default value does not match directive type',
|
||||
E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
$def->info[$namespace][$name] =
|
||||
new HTMLPurifier_ConfigEntity_Directive();
|
||||
$def->info[$namespace][$name]->type = $type;
|
||||
$def->defaults[$namespace][$name] = $default;
|
||||
}
|
||||
$backtrace = debug_backtrace();
|
||||
$file = $def->mungeFilename($backtrace[0]['file']);
|
||||
$line = $backtrace[0]['line'];
|
||||
$def->info[$namespace][$name]->addDescription($file,$line,$description);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -73,8 +125,187 @@ class HTMLPurifier_ConfigDef {
|
||||
return;
|
||||
}
|
||||
$def->info[$namespace] = array();
|
||||
$def->info_namespace[$namespace] = new HTMLPurifier_ConfigEntity_Namespace();
|
||||
$backtrace = debug_backtrace();
|
||||
$file = $def->mungeFilename($backtrace[0]['file']);
|
||||
$line = $backtrace[0]['line'];
|
||||
$def->info_namespace[$namespace]->addDescription($file,$line,$description);
|
||||
$def->defaults[$namespace] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a directive value alias.
|
||||
*
|
||||
* Directive value aliases are convenient for developers because it lets
|
||||
* them set a directive to several values and get the same result.
|
||||
* @param $namespace Directive's namespace
|
||||
* @param $name Name of Directive
|
||||
* @param $alias Name of aliased value
|
||||
* @param $real Value aliased value will be converted into
|
||||
*/
|
||||
function defineValueAliases($namespace, $name, $aliases) {
|
||||
$def =& HTMLPurifier_ConfigDef::instance();
|
||||
if (!isset($def->info[$namespace][$name])) {
|
||||
trigger_error('Cannot set value alias for non-existant directive',
|
||||
E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
foreach ($aliases as $alias => $real) {
|
||||
if (!$def->info[$namespace][$name] !== true &&
|
||||
!isset($def->info[$namespace][$name]->allowed[$real])
|
||||
) {
|
||||
trigger_error('Cannot define alias to value that is not allowed',
|
||||
E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
if (isset($def->info[$namespace][$name]->allowed[$alias])) {
|
||||
trigger_error('Cannot define alias over allowed value',
|
||||
E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
$def->info[$namespace][$name]->aliases[$alias] = $real;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a set of allowed values for a directive.
|
||||
* @param $namespace Namespace of directive
|
||||
* @param $name Name of directive
|
||||
* @param $allowed_values Arraylist of allowed values
|
||||
*/
|
||||
function defineAllowedValues($namespace, $name, $allowed_values) {
|
||||
$def =& HTMLPurifier_ConfigDef::instance();
|
||||
if (!isset($def->info[$namespace][$name])) {
|
||||
trigger_error('Cannot define allowed values for undefined directive',
|
||||
E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
if ($def->info[$namespace][$name]->allowed === true) {
|
||||
$def->info[$namespace][$name]->allowed = array();
|
||||
}
|
||||
foreach ($allowed_values as $value) {
|
||||
$def->info[$namespace][$name]->allowed[$value] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a variable according to type. Return null if invalid.
|
||||
*/
|
||||
function validate($var, $type) {
|
||||
if (!isset($this->types[$type])) {
|
||||
trigger_error('Invalid type', E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
switch ($type) {
|
||||
case 'mixed':
|
||||
return $var;
|
||||
case 'istring':
|
||||
case 'string':
|
||||
if (!is_string($var)) return;
|
||||
if ($type === 'istring') $var = strtolower($var);
|
||||
return $var;
|
||||
case 'int':
|
||||
if (is_string($var) && ctype_digit($var)) $var = (int) $var;
|
||||
elseif (!is_int($var)) return;
|
||||
return $var;
|
||||
case 'float':
|
||||
if (is_string($var) && is_numeric($var)) $var = (float) $var;
|
||||
elseif (!is_float($var)) return;
|
||||
return $var;
|
||||
case 'bool':
|
||||
if (is_int($var) && ($var === 0 || $var === 1)) {
|
||||
$var = (bool) $var;
|
||||
} elseif (!is_bool($var)) return;
|
||||
return $var;
|
||||
case 'list':
|
||||
case 'hash':
|
||||
case 'lookup':
|
||||
if (!is_array($var)) return;
|
||||
$keys = array_keys($var);
|
||||
if ($keys === array_keys($keys)) {
|
||||
if ($type == 'list') return $var;
|
||||
elseif ($type == 'lookup') {
|
||||
$new = array();
|
||||
foreach ($var as $key) {
|
||||
$new[$key] = true;
|
||||
}
|
||||
return $new;
|
||||
} else return;
|
||||
}
|
||||
if ($type === 'lookup') {
|
||||
foreach ($var as $key => $value) {
|
||||
$var[$key] = true;
|
||||
}
|
||||
}
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
function mungeFilename($filename) {
|
||||
$offset = strrpos($filename, 'HTMLPurifier');
|
||||
$filename = substr($filename, $offset);
|
||||
$filename = str_replace('\\', '/', $filename);
|
||||
return $filename;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Base class for configuration entity
|
||||
*/
|
||||
class HTMLPurifier_ConfigEntity
|
||||
{
|
||||
/**
|
||||
* Plaintext descriptions of the configuration entity is. Organized by
|
||||
* file and line number, so multiple descriptions are allowed.
|
||||
*/
|
||||
var $descriptions = array();
|
||||
|
||||
/**
|
||||
* Adds a description to the array
|
||||
*/
|
||||
function addDescription($file, $line, $description) {
|
||||
if (!isset($this->descriptions[$file])) $this->descriptions[$file] = array();
|
||||
$this->descriptions[$file][$line] = $description;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure object describing of a namespace
|
||||
*/
|
||||
class HTMLPurifier_ConfigEntity_Namespace extends HTMLPurifier_ConfigEntity {}
|
||||
|
||||
/**
|
||||
* Structure object containing definition of a directive.
|
||||
* @note This structure does not contain default values
|
||||
*/
|
||||
class HTMLPurifier_ConfigEntity_Directive extends HTMLPurifier_ConfigEntity
|
||||
{
|
||||
|
||||
/**
|
||||
* Hash of value aliases, i.e. values that are equivalent.
|
||||
*/
|
||||
var $aliases = array();
|
||||
|
||||
/**
|
||||
* Lookup table of allowed values of the element, bool true if all allowed.
|
||||
*/
|
||||
var $allowed = true;
|
||||
|
||||
/**
|
||||
* Allowed type of the directive. Values are:
|
||||
* - string
|
||||
* - istring (case insensitive string)
|
||||
* - int
|
||||
* - float
|
||||
* - bool
|
||||
* - lookup (array of value => true)
|
||||
* - list (regular numbered index array)
|
||||
* - hash (array of key => value)
|
||||
* - mixed (anything goes)
|
||||
*/
|
||||
var $type = 'mixed';
|
||||
|
||||
}
|
||||
|
||||
?>
|
@ -5,7 +5,7 @@
|
||||
require_once 'HTMLPurifier/Lexer.php';
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'CleanUTF8DuringGeneration', false,
|
||||
'Core', 'CleanUTF8DuringGeneration', false, 'bool',
|
||||
'When true, HTMLPurifier_Generator will also check all strings it '.
|
||||
'escapes for UTF-8 well-formedness as a defense in depth measure. '.
|
||||
'This could cause a considerable performance impact, and is not '.
|
||||
|
@ -3,7 +3,7 @@
|
||||
require_once 'HTMLPurifier/Token.php';
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'AcceptFullDocuments', true,
|
||||
'Core', 'AcceptFullDocuments', true, 'bool',
|
||||
'This parameter determines whether or not the filter should accept full '.
|
||||
'HTML documents, not just HTML fragments. When on, it will '.
|
||||
'drop all sections except the content between body. Depending on '.
|
||||
|
@ -9,7 +9,7 @@
|
||||
*/
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'EscapeInvalidTags', false,
|
||||
'Core', 'EscapeInvalidTags', false, 'bool',
|
||||
'When true, invalid tags will be written back to the document as plain '.
|
||||
'text. Otherwise, they are silently dropped.'
|
||||
);
|
||||
|
@ -7,7 +7,7 @@ require_once 'HTMLPurifier/ConfigDef.php';
|
||||
require_once 'HTMLPurifier/AttrContext.php';
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Attr', 'IDBlacklist', array(),
|
||||
'Attr', 'IDBlacklist', array(), 'list',
|
||||
'Array of IDs not allowed in the document.');
|
||||
|
||||
/**
|
||||
|
@ -11,13 +11,13 @@ HTMLPurifier_ConfigDef::define(
|
||||
// for Usenet, these two are similar, but distinct
|
||||
'nntp' => true, // individual Netnews articles
|
||||
'news' => true // newsgroup or individual Netnews articles),
|
||||
),
|
||||
), 'lookup',
|
||||
'Whitelist that defines the schemes that a URI is allowed to have. This '.
|
||||
'prevents XSS attacks from using pseudo-schemes like javascript or mocha.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'URI', 'OverrideAllowedSchemes', true,
|
||||
'URI', 'OverrideAllowedSchemes', true, 'bool',
|
||||
'If this is set to true (which it is by default), you can override '.
|
||||
'%URI.AllowedSchemes by simply registering a HTMLPurifier_URIScheme '.
|
||||
'to the registry. If false, you will also have to update that directive '.
|
||||
|
@ -27,38 +27,261 @@ class HTMLPurifier_ConfigDefTest extends UnitTestCase
|
||||
|
||||
function testNormal() {
|
||||
|
||||
HTMLPurifier_ConfigDef::defineNamespace('Core', 'Configuration that '.
|
||||
'is always available.');
|
||||
$this->assertIdentical( array(
|
||||
'Core' => array()
|
||||
), $this->our_copy->info);
|
||||
$file = $this->our_copy->mungeFilename(__FILE__);
|
||||
|
||||
// note that the description is silently dropped
|
||||
HTMLPurifier_ConfigDef::define('Core', 'Name', 'default value',
|
||||
'This is a description of the directive.');
|
||||
$this->assertIdentical( array(
|
||||
// define a namespace
|
||||
$description = 'Configuration that is always available.';
|
||||
HTMLPurifier_ConfigDef::defineNamespace(
|
||||
'Core', $description
|
||||
); $line = __LINE__;
|
||||
$this->assertIdentical($this->our_copy->defaults, array(
|
||||
'Core' => array()
|
||||
));
|
||||
$this->assertIdentical($this->our_copy->info, array(
|
||||
'Core' => array()
|
||||
));
|
||||
$namespace = new HTMLPurifier_ConfigEntity_Namespace();
|
||||
$namespace->addDescription($file, $line, $description);
|
||||
$this->assertIdentical($this->our_copy->info_namespace, array(
|
||||
'Core' => $namespace
|
||||
));
|
||||
|
||||
|
||||
|
||||
// define a directive
|
||||
$description = 'This is a description of the directive.';
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'Name', 'default value', 'string',
|
||||
$description
|
||||
); $line = __LINE__;
|
||||
$this->assertIdentical($this->our_copy->defaults, array(
|
||||
'Core' => array(
|
||||
'Name' => 'default value'
|
||||
)
|
||||
), $this->our_copy->info);
|
||||
));
|
||||
$directive = new HTMLPurifier_ConfigEntity_Directive();
|
||||
$directive->type = 'string';
|
||||
$directive->addDescription($file, $line, $description);
|
||||
$this->assertIdentical($this->our_copy->info, array(
|
||||
'Core' => array(
|
||||
'Name' => $directive
|
||||
)
|
||||
));
|
||||
|
||||
// test an invalid namespace
|
||||
HTMLPurifier_ConfigDef::define('Extension', 'Name', false, 'This is '.
|
||||
'for an extension, but we have not defined its namespace!');
|
||||
|
||||
|
||||
// define a directive in an undefined namespace
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Extension', 'Name', false, 'bool',
|
||||
'This is for an extension, but we have not defined its namespace!'
|
||||
);
|
||||
$this->assertError('Cannot define directive for undefined namespace');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
// test overloading already defined value
|
||||
// ACTUALLY, we probably should allow this behavior, which simply
|
||||
// means that two class files need that directive. Using debug_backtrace
|
||||
// we could probably figure which files those are too! :-D
|
||||
HTMLPurifier_ConfigDef::define('Core', 'Name', 89,
|
||||
'What, you\'re not allowed to overload directives? Bummer!');
|
||||
$this->assertError('Cannot redefine directive');
|
||||
|
||||
|
||||
// redefine a value in a valid manner
|
||||
$description = 'Alternative configuration definition';
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'Name', 'default value', 'string',
|
||||
$description
|
||||
); $line = __LINE__;
|
||||
$this->assertNoErrors();
|
||||
$directive->addDescription($file, $line, $description);
|
||||
$this->assertIdentical($this->our_copy->info, array(
|
||||
'Core' => array(
|
||||
'Name' => $directive
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
|
||||
// redefine a directive in an invalid manner
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'Name', 'different default', 'string',
|
||||
'Inconsistent default or type, cannot redefine'
|
||||
);
|
||||
$this->assertError('Inconsistent default or type, cannot redefine');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
|
||||
|
||||
// make an enumeration
|
||||
HTMLPurifier_ConfigDef::defineAllowedValues(
|
||||
'Core', 'Name', array(
|
||||
'Real Value',
|
||||
'Real Value 2'
|
||||
)
|
||||
);
|
||||
$directive->allowed = array(
|
||||
'Real Value' => true,
|
||||
'Real Value 2' => true
|
||||
);
|
||||
$this->assertIdentical($this->our_copy->info, array(
|
||||
'Core' => array(
|
||||
'Name' => $directive
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
|
||||
// redefinition of enumeration is cumulative
|
||||
HTMLPurifier_ConfigDef::defineAllowedValues(
|
||||
'Core', 'Name', array(
|
||||
'Real Value 3',
|
||||
)
|
||||
);
|
||||
$directive->allowed['Real Value 3'] = true;
|
||||
$this->assertIdentical($this->our_copy->info, array(
|
||||
'Core' => array(
|
||||
'Name' => $directive
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
|
||||
// cannot define enumeration for undefined directive
|
||||
HTMLPurifier_ConfigDef::defineAllowedValues(
|
||||
'Core', 'Foobar', array(
|
||||
'Real Value 9',
|
||||
)
|
||||
);
|
||||
$this->assertError('Cannot define allowed values for undefined directive');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
|
||||
|
||||
// test defining value aliases for an enumerated value
|
||||
HTMLPurifier_ConfigDef::defineValueAliases(
|
||||
'Core', 'Name', array(
|
||||
'Aliased Value' => 'Real Value'
|
||||
)
|
||||
);
|
||||
$directive->aliases['Aliased Value'] = 'Real Value';
|
||||
$this->assertIdentical($this->our_copy->info, array(
|
||||
'Core' => array(
|
||||
'Name' => $directive
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
|
||||
// redefine should be cumulative
|
||||
HTMLPurifier_ConfigDef::defineValueAliases(
|
||||
'Core', 'Name', array(
|
||||
'Aliased Value 2' => 'Real Value 2'
|
||||
)
|
||||
);
|
||||
$directive->aliases['Aliased Value 2'] = 'Real Value 2';
|
||||
$this->assertIdentical($this->our_copy->info, array(
|
||||
'Core' => array(
|
||||
'Name' => $directive
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
|
||||
// cannot create alias to not-allowed value
|
||||
HTMLPurifier_ConfigDef::defineValueAliases(
|
||||
'Core', 'Name', array(
|
||||
'Aliased Value 3' => 'Invalid Value'
|
||||
)
|
||||
);
|
||||
$this->assertError('Cannot define alias to value that is not allowed');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
|
||||
|
||||
// cannot create alias for already allowed value
|
||||
HTMLPurifier_ConfigDef::defineValueAliases(
|
||||
'Core', 'Name', array(
|
||||
'Real Value' => 'Real Value 2'
|
||||
)
|
||||
);
|
||||
$this->assertError('Cannot define alias over allowed value');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
|
||||
|
||||
// define a directive with an invalid type
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'Foobar', false, 'omen',
|
||||
'Omen is not a valid type, so we reject this.'
|
||||
);
|
||||
|
||||
$this->assertError('Invalid type for configuration directive');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
|
||||
|
||||
// define a directive with inconsistent type
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'Foobaz', 10, 'string',
|
||||
'If we say string, we should mean it, not integer 10.'
|
||||
);
|
||||
|
||||
$this->assertError('Default value does not match directive type');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function assertValid($var, $type, $ret = null) {
|
||||
$ret = ($ret === null) ? $var : $ret;
|
||||
$this->assertIdentical($this->our_copy->validate($var, $type), $ret);
|
||||
}
|
||||
|
||||
function assertInvalid($var, $type) {
|
||||
$this->assertIdentical($this->our_copy->validate($var, $type), null);
|
||||
}
|
||||
|
||||
function testValidate() {
|
||||
|
||||
$this->assertValid('foobar', 'string');
|
||||
$this->assertValid('FOOBAR', 'istring', 'foobar');
|
||||
$this->assertValid(34, 'int');
|
||||
$this->assertValid(3.34, 'float');
|
||||
$this->assertValid(false, 'bool');
|
||||
$this->assertValid(0, 'bool', false);
|
||||
$this->assertValid(1, 'bool', true);
|
||||
$this->assertInvalid(34, 'bool');
|
||||
$this->assertValid(array('1', '2', '3'), 'list');
|
||||
$this->assertValid(array('1' => true, '2' => true), 'lookup');
|
||||
$this->assertValid(array('1', '2'), 'lookup', array('1' => true, '2' => true));
|
||||
$this->assertValid(array('foo' => 'bar'), 'hash');
|
||||
$this->assertInvalid(array(0 => 'moo'), 'hash');
|
||||
$this->assertValid(array(1 => 'moo'), 'hash');
|
||||
$this->assertValid(23, 'mixed');
|
||||
|
||||
}
|
||||
|
||||
function assertMungeFilename($oldname, $newname) {
|
||||
$this->assertIdentical(
|
||||
$this->our_copy->mungeFilename($oldname),
|
||||
$newname
|
||||
);
|
||||
}
|
||||
|
||||
function testMungeFilename() {
|
||||
|
||||
$this->assertMungeFilename(
|
||||
'C:\\php\\libs\\htmlpurifier\\library\\HTMLPurifier\\AttrDef.php',
|
||||
'HTMLPurifier/AttrDef.php'
|
||||
);
|
||||
|
||||
$this->assertMungeFilename(
|
||||
'C:\\php\\libs\\htmlpurifier\\library\\HTMLPurifier.php',
|
||||
'HTMLPurifier.php'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,25 +5,51 @@ require_once 'HTMLPurifier/Config.php';
|
||||
class HTMLPurifier_ConfigTest extends UnitTestCase
|
||||
{
|
||||
|
||||
var $our_copy, $old_copy;
|
||||
|
||||
function setUp() {
|
||||
$our_copy = new HTMLPurifier_ConfigDef();
|
||||
$this->old_copy = HTMLPurifier_ConfigDef::instance();
|
||||
$this->our_copy =& HTMLPurifier_ConfigDef::instance($our_copy);
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
HTMLPurifier_ConfigDef::instance($this->old_copy);
|
||||
}
|
||||
|
||||
function test() {
|
||||
|
||||
$def = new HTMLPurifier_ConfigDef();
|
||||
$def->info = array(
|
||||
'Core' => array('Key' => false),
|
||||
'Attr' => array('Key' => 42),
|
||||
'Extension' => array('Pert' => 'moo')
|
||||
HTMLPurifier_ConfigDef::defineNamespace('Core', 'Corestuff');
|
||||
HTMLPurifier_ConfigDef::defineNamespace('Attr', 'Attributes');
|
||||
HTMLPurifier_ConfigDef::defineNamespace('Extension', 'Extensible');
|
||||
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Core', 'Key', false, 'bool', 'A boolean directive.'
|
||||
);
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Attr', 'Key', 42, 'int', 'An integer directive.'
|
||||
);
|
||||
HTMLPurifier_ConfigDef::define(
|
||||
'Extension', 'Pert', 'foo', 'string', 'A string directive.'
|
||||
);
|
||||
|
||||
$config = new HTMLPurifier_Config($def);
|
||||
HTMLPurifier_ConfigDef::defineAllowedValues(
|
||||
'Extension', 'Pert', array('foo', 'moo')
|
||||
);
|
||||
HTMLPurifier_ConfigDef::defineValueAliases(
|
||||
'Extension', 'Pert', array('cow' => 'moo')
|
||||
);
|
||||
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
|
||||
// test default value retrieval
|
||||
$this->assertIdentical($config->get('Core', 'Key'), false);
|
||||
$this->assertIdentical($config->get('Attr', 'Key'), 42);
|
||||
$this->assertIdentical($config->get('Extension', 'Pert'), 'moo');
|
||||
$this->assertIdentical($config->get('Extension', 'Pert'), 'foo');
|
||||
|
||||
// set some values
|
||||
$config->set('Core', 'Key', 'foobar');
|
||||
$this->assertIdentical($config->get('Core', 'Key'), 'foobar');
|
||||
$config->set('Core', 'Key', true);
|
||||
$this->assertIdentical($config->get('Core', 'Key'), true);
|
||||
|
||||
// try to retrieve undefined value
|
||||
$config->get('Core', 'NotDefined');
|
||||
@ -37,6 +63,23 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
// try to set not allowed value
|
||||
$config->set('Extension', 'Pert', 'wizard');
|
||||
$this->assertError('Value not supported');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
// try to set not allowed value
|
||||
$config->set('Extension', 'Pert', 34);
|
||||
$this->assertError('Value is of invalid type');
|
||||
$this->assertNoErrors();
|
||||
$this->swallowErrors();
|
||||
|
||||
// set aliased value
|
||||
$config->set('Extension', 'Pert', 'cow');
|
||||
$this->assertNoErrors();
|
||||
$this->assertIdentical($config->get('Extension', 'Pert'), 'moo');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user