0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-01-03 05:11:52 +00:00

[3.1.1] Memory optimizations for ConfigSchema. Changes include:

- Elimination of ConfigDef and subclasses in favor of stdclass. Most property names stay the same
- Added benchmark script for ConfigSchema
- Types are internally handled as magic integers. Use HTMLPurifier_VarParser->getTypeName to convert to human readable form. HTMLPurifier_VarParser still accepts strings.
- Parser in config schema only used for legacy interface


git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1764 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang 2008-05-23 16:43:24 +00:00
parent 9db891c3aa
commit 8ab30e24b7
18 changed files with 171 additions and 218 deletions

6
NEWS
View File

@ -31,6 +31,12 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
will still work--the new format, however, lets modules access the will still work--the new format, however, lets modules access the
configuration object for HTML namespace dependant tweaks. configuration object for HTML namespace dependant tweaks.
. AttrDef_HTML_Pixels now takes a single construction parameter, pixels. . AttrDef_HTML_Pixels now takes a single construction parameter, pixels.
. ConfigSchema data-structure heavily optimized; on average it uses half
the memory it did previously. The interface has changed accordingly,
consult changes to HTMLPurifier_Config for details.
. Variable parsing types now are magic integers instead of strings
. Added benchmark for ConfigSchema
3.1.0, released 2008-05-18 3.1.0, released 2008-05-18
# Unnecessary references to objects (vestiges of PHP4) removed from method # Unnecessary references to objects (vestiges of PHP4) removed from method

2
TODO
View File

@ -11,8 +11,6 @@ If no interest is expressed for a feature that may require a considerable
amount of effort to implement, it may get endlessly delayed. Do not be amount of effort to implement, it may get endlessly delayed. Do not be
afraid to cast your vote for the next feature to be implemented! afraid to cast your vote for the next feature to be implemented!
- Ability to fully turn off imagecrash fixes (attribute and CSS will require
two separate directives due to our architecture.)
- Investigate how early internal structures can be accessed; this would - Investigate how early internal structures can be accessed; this would
prevent structures from being parsed and serialized multiple times. prevent structures from being parsed and serialized multiple times.
- Figure out how to simultaneously set %CSS.Trusted and %HTML.Trusted (?) - Figure out how to simultaneously set %CSS.Trusted and %HTML.Trusted (?)

View File

@ -1,5 +1,9 @@
<?php <?php
chdir(dirname(__FILE__));
//require_once '../library/HTMLPurifier.path.php';
shell_exec('php ../maintenance/generate-schema-cache.php');
require_once '../library/HTMLPurifier.path.php'; require_once '../library/HTMLPurifier.path.php';
require_once 'HTMLPurifier.includes.php'; require_once 'HTMLPurifier.includes.php';

View File

@ -29,7 +29,6 @@ require 'HTMLPurifier/Definition.php';
require 'HTMLPurifier/CSSDefinition.php'; require 'HTMLPurifier/CSSDefinition.php';
require 'HTMLPurifier/ChildDef.php'; require 'HTMLPurifier/ChildDef.php';
require 'HTMLPurifier/Config.php'; require 'HTMLPurifier/Config.php';
require 'HTMLPurifier/ConfigDef.php';
require 'HTMLPurifier/ConfigSchema.php'; require 'HTMLPurifier/ConfigSchema.php';
require 'HTMLPurifier/ContentSets.php'; require 'HTMLPurifier/ContentSets.php';
require 'HTMLPurifier/Context.php'; require 'HTMLPurifier/Context.php';
@ -127,9 +126,6 @@ require 'HTMLPurifier/ChildDef/Required.php';
require 'HTMLPurifier/ChildDef/Optional.php'; require 'HTMLPurifier/ChildDef/Optional.php';
require 'HTMLPurifier/ChildDef/StrictBlockquote.php'; require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
require 'HTMLPurifier/ChildDef/Table.php'; require 'HTMLPurifier/ChildDef/Table.php';
require 'HTMLPurifier/ConfigDef/Directive.php';
require 'HTMLPurifier/ConfigDef/DirectiveAlias.php';
require 'HTMLPurifier/ConfigDef/Namespace.php';
require 'HTMLPurifier/DefinitionCache/Decorator.php'; require 'HTMLPurifier/DefinitionCache/Decorator.php';
require 'HTMLPurifier/DefinitionCache/Null.php'; require 'HTMLPurifier/DefinitionCache/Null.php';
require 'HTMLPurifier/DefinitionCache/Serializer.php'; require 'HTMLPurifier/DefinitionCache/Serializer.php';

View File

@ -23,7 +23,6 @@ require_once $__dir . '/HTMLPurifier/Definition.php';
require_once $__dir . '/HTMLPurifier/CSSDefinition.php'; require_once $__dir . '/HTMLPurifier/CSSDefinition.php';
require_once $__dir . '/HTMLPurifier/ChildDef.php'; require_once $__dir . '/HTMLPurifier/ChildDef.php';
require_once $__dir . '/HTMLPurifier/Config.php'; require_once $__dir . '/HTMLPurifier/Config.php';
require_once $__dir . '/HTMLPurifier/ConfigDef.php';
require_once $__dir . '/HTMLPurifier/ConfigSchema.php'; require_once $__dir . '/HTMLPurifier/ConfigSchema.php';
require_once $__dir . '/HTMLPurifier/ContentSets.php'; require_once $__dir . '/HTMLPurifier/ContentSets.php';
require_once $__dir . '/HTMLPurifier/Context.php'; require_once $__dir . '/HTMLPurifier/Context.php';
@ -121,9 +120,6 @@ require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php'; require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
require_once $__dir . '/HTMLPurifier/ChildDef/Table.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Table.php';
require_once $__dir . '/HTMLPurifier/ConfigDef/Directive.php';
require_once $__dir . '/HTMLPurifier/ConfigDef/DirectiveAlias.php';
require_once $__dir . '/HTMLPurifier/ConfigDef/Namespace.php';
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php'; require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php';
require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php'; require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php';
require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php'; require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php';

View File

@ -125,7 +125,7 @@ class HTMLPurifier_Config
E_USER_WARNING); E_USER_WARNING);
return; return;
} }
if ($this->def->info[$namespace][$key]->class == 'alias') { if (isset($this->def->info[$namespace][$key]->isAlias)) {
$d = $this->def->info[$namespace][$key]; $d = $this->def->info[$namespace][$key];
trigger_error('Cannot get value from aliased directive, use real name ' . $d->namespace . '.' . $d->name, trigger_error('Cannot get value from aliased directive, use real name ' . $d->namespace . '.' . $d->name,
E_USER_ERROR); E_USER_ERROR);
@ -196,7 +196,7 @@ class HTMLPurifier_Config
E_USER_WARNING); E_USER_WARNING);
return; return;
} }
if ($this->def->info[$namespace][$key]->class == 'alias') { if (isset($this->def->info[$namespace][$key]->isAlias)) {
if ($from_alias) { if ($from_alias) {
trigger_error('Double-aliases not allowed, please fix '. trigger_error('Double-aliases not allowed, please fix '.
'ConfigSchema bug with' . "$namespace.$key", E_USER_ERROR); 'ConfigSchema bug with' . "$namespace.$key", E_USER_ERROR);
@ -212,10 +212,10 @@ class HTMLPurifier_Config
$value = $this->parser->parse( $value = $this->parser->parse(
$value, $value,
$type = $this->def->info[$namespace][$key]->type, $type = $this->def->info[$namespace][$key]->type,
$this->def->info[$namespace][$key]->allow_null isset($this->def->info[$namespace][$key]->allow_null)
); );
} catch (HTMLPurifier_VarParserException $e) { } catch (HTMLPurifier_VarParserException $e) {
trigger_error('Value for ' . "$namespace.$key" . ' is of invalid type, should be ' . $type, E_USER_WARNING); trigger_error('Value for ' . "$namespace.$key" . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING);
return; return;
} }
if (is_string($value)) { if (is_string($value)) {
@ -223,9 +223,9 @@ class HTMLPurifier_Config
if (isset($this->def->info[$namespace][$key]->aliases[$value])) { if (isset($this->def->info[$namespace][$key]->aliases[$value])) {
$value = $this->def->info[$namespace][$key]->aliases[$value]; $value = $this->def->info[$namespace][$key]->aliases[$value];
} }
if ($this->def->info[$namespace][$key]->allowed !== true) { if (isset($this->def->info[$namespace][$key])) {
// check to see if the value is allowed // check to see if the value is allowed
if (!isset($this->def->info[$namespace][$key]->allowed[$value])) { if (isset($this->def->info[$namespace][$key]->allowed) && !isset($this->def->info[$namespace][$key]->allowed[$value])) {
trigger_error('Value not supported, valid values are: ' . trigger_error('Value not supported, valid values are: ' .
$this->_listify($this->def->info[$namespace][$key]->allowed), E_USER_WARNING); $this->_listify($this->def->info[$namespace][$key]->allowed), E_USER_WARNING);
return; return;
@ -386,7 +386,7 @@ class HTMLPurifier_Config
if (isset($blacklisted_directives["$ns.$directive"])) continue; if (isset($blacklisted_directives["$ns.$directive"])) continue;
if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue; if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue;
} }
if ($def->class == 'alias') continue; if (isset($def->isAlias)) continue;
if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue; if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue;
$ret[] = array($ns, $directive); $ret[] = array($ns, $directive);
} }

View File

@ -1,9 +0,0 @@
<?php
/**
* Base class for configuration entity
*/
abstract class HTMLPurifier_ConfigDef {
public $class = false;
}

View File

@ -1,55 +0,0 @@
<?php
/**
* Structure object containing definition of a directive.
* @note This structure does not contain default values
*/
class HTMLPurifier_ConfigDef_Directive extends HTMLPurifier_ConfigDef
{
public $class = 'directive';
public function __construct(
$type = null,
$allow_null = null,
$allowed = null,
$aliases = null
) {
if ( $type !== null) $this->type = $type;
if ( $allow_null !== null) $this->allow_null = $allow_null;
if ( $allowed !== null) $this->allowed = $allowed;
if ( $aliases !== null) $this->aliases = $aliases;
}
/**
* 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)
*/
public $type = 'mixed';
/**
* Is null allowed? Has no effect for mixed type.
* @bool
*/
public $allow_null = false;
/**
* Lookup table of allowed values of the element, bool true if all allowed.
*/
public $allowed = true;
/**
* Hash of value aliases, i.e. values that are equivalent.
*/
public $aliases = array();
}

View File

@ -1,24 +0,0 @@
<?php
/**
* Structure object describing a directive alias
*/
class HTMLPurifier_ConfigDef_DirectiveAlias extends HTMLPurifier_ConfigDef
{
public $class = 'alias';
/**
* Namespace being aliased to
*/
public $namespace;
/**
* Directive being aliased to
*/
public $name;
public function __construct($namespace, $name) {
$this->namespace = $namespace;
$this->name = $name;
}
}

View File

@ -1,10 +0,0 @@
<?php
/**
* Structure object describing of a namespace
*/
class HTMLPurifier_ConfigDef_Namespace extends HTMLPurifier_ConfigDef
{
public $class = 'namespace';
}

View File

@ -12,7 +12,28 @@ class HTMLPurifier_ConfigSchema {
public $defaults = array(); public $defaults = array();
/** /**
* Definition of the directives. * Definition of the directives. The structure of this is:
*
* array(
* 'Namespace' => array(
* 'Directive' => new stdclass(),
* )
* )
*
* The stdclass may have the following properties:
*
* - If isAlias isn't set:
* - type: Integer type of directive, see HTMLPurifier_VarParser for definitions
* - allow_null: If set, this directive allows null values
* - aliases: If set, an associative array of value aliases to real values
* - allowed: If set, a lookup array of allowed (string) values
* - If isAlias is set:
* - namespace: Namespace this directive aliases to
* - name: Directive name this directive aliases to
*
* This class is friendly with HTMLPurifier_Config. If you need introspection
* about the schema, you're better of using the ConfigSchema_Interchange,
* which uses more memory but has much richer information.
*/ */
public $info = array(); public $info = array();
@ -21,15 +42,6 @@ class HTMLPurifier_ConfigSchema {
*/ */
static protected $singleton; static protected $singleton;
/**
* Variable parser.
*/
protected $parser;
public function __construct() {
$this->parser = new HTMLPurifier_VarParser_Flexible();
}
/** /**
* Unserializes the default ConfigSchema. * Unserializes the default ConfigSchema.
*/ */
@ -62,11 +74,11 @@ class HTMLPurifier_ConfigSchema {
* @param $allow_null Whether or not to allow null values * @param $allow_null Whether or not to allow null values
*/ */
public function add($namespace, $name, $default, $type, $allow_null) { public function add($namespace, $name, $default, $type, $allow_null) {
$default = $this->parser->parse($default, $type, $allow_null); $obj = new stdclass();
$this->info[$namespace][$name] = new HTMLPurifier_ConfigDef_Directive(); $obj->type = is_int($type) ? $type : HTMLPurifier_VarParser::$types[$type];
$this->info[$namespace][$name]->type = $type; if ($allow_null) $obj->allow_null = true;
$this->info[$namespace][$name]->allow_null = $allow_null; $this->info[$namespace][$name] = $obj;
$this->defaults[$namespace][$name] = $default; $this->defaults[$namespace][$name] = $default;
} }
/** /**
@ -90,6 +102,9 @@ class HTMLPurifier_ConfigSchema {
* @param $aliases Hash of aliased values to the real alias * @param $aliases Hash of aliased values to the real alias
*/ */
public function addValueAliases($namespace, $name, $aliases) { public function addValueAliases($namespace, $name, $aliases) {
if (!isset($this->info[$namespace][$name]->aliases)) {
$this->info[$namespace][$name]->aliases = array();
}
foreach ($aliases as $alias => $real) { foreach ($aliases as $alias => $real) {
$this->info[$namespace][$name]->aliases[$alias] = $real; $this->info[$namespace][$name]->aliases[$alias] = $real;
} }
@ -104,7 +119,6 @@ class HTMLPurifier_ConfigSchema {
* @param $allowed Lookup array of allowed values * @param $allowed Lookup array of allowed values
*/ */
public function addAllowedValues($namespace, $name, $allowed) { public function addAllowedValues($namespace, $name, $allowed) {
$type = $this->info[$namespace][$name]->type;
$this->info[$namespace][$name]->allowed = $allowed; $this->info[$namespace][$name]->allowed = $allowed;
} }
@ -116,7 +130,11 @@ class HTMLPurifier_ConfigSchema {
* @param $new_name Directive that the alias will be to * @param $new_name Directive that the alias will be to
*/ */
public function addAlias($namespace, $name, $new_namespace, $new_name) { public function addAlias($namespace, $name, $new_namespace, $new_name) {
$this->info[$namespace][$name] = new HTMLPurifier_ConfigDef_DirectiveAlias($new_namespace, $new_name); $obj = new stdclass;
$obj->namespace = $new_namespace;
$obj->name = $new_name;
$obj->isAlias = true;
$this->info[$namespace][$name] = $obj;
} }
// DEPRECATED METHODS // DEPRECATED METHODS
@ -124,7 +142,6 @@ class HTMLPurifier_ConfigSchema {
/** @see HTMLPurifier_ConfigSchema->set() */ /** @see HTMLPurifier_ConfigSchema->set() */
public static function define($namespace, $name, $default, $type, $description) { public static function define($namespace, $name, $default, $type, $description) {
HTMLPurifier_ConfigSchema::deprecated(__METHOD__); HTMLPurifier_ConfigSchema::deprecated(__METHOD__);
// process modifiers (OPTIMIZE!)
$type_values = explode('/', $type, 2); $type_values = explode('/', $type, 2);
$type = $type_values[0]; $type = $type_values[0];
$modifier = isset($type_values[1]) ? $type_values[1] : false; $modifier = isset($type_values[1]) ? $type_values[1] : false;
@ -168,7 +185,8 @@ class HTMLPurifier_ConfigSchema {
/** @deprecated, use HTMLPurifier_VarParser->parse() */ /** @deprecated, use HTMLPurifier_VarParser->parse() */
public function validate($a, $b, $c = false) { public function validate($a, $b, $c = false) {
trigger_error("HTMLPurifier_ConfigSchema->validate deprecated, use HTMLPurifier_VarParser->parse instead", E_USER_NOTICE); trigger_error("HTMLPurifier_ConfigSchema->validate deprecated, use HTMLPurifier_VarParser->parse instead", E_USER_NOTICE);
return $this->parser->parse($a, $b, $c); $parser = new HTMLPurifier_VarParser();
return $parser->parse($a, $b, $c);
} }
/** /**

View File

@ -111,7 +111,8 @@ class HTMLPurifier_ConfigSchema_Validator
if (!is_null($d->allowed) || !empty($d->valueAliases)) { if (!is_null($d->allowed) || !empty($d->valueAliases)) {
// allowed and valueAliases require that we be dealing with // allowed and valueAliases require that we be dealing with
// strings, so check for that early. // strings, so check for that early.
if (!isset(HTMLPurifier_VarParser::$stringTypes[$d->type])) { $d_int = HTMLPurifier_VarParser::$types[$d->type];
if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) {
$this->error('type', 'must be a string type when used with allowed or value aliases'); $this->error('type', 'must be a string type when used with allowed or value aliases');
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -7,21 +7,34 @@
class HTMLPurifier_VarParser class HTMLPurifier_VarParser
{ {
const STRING = 0;
const ISTRING = 1;
const TEXT = 2;
const ITEXT = 3;
const INT = 4;
const FLOAT = 5;
const BOOL = 6;
const LOOKUP = 7;
const ALIST = 8;
const HASH = 9;
const MIXED = 10;
/** /**
* Lookup table of allowed types. * Lookup table of allowed types. Mainly for backwards compatibility, but
* also convenient for transforming string type names to the integer constants.
*/ */
static public $types = array( static public $types = array(
'string' => true, 'string' => self::STRING,
'istring' => true, 'istring' => self::ISTRING,
'text' => true, 'text' => self::TEXT,
'itext' => true, 'itext' => self::ITEXT,
'int' => true, 'int' => self::INT,
'float' => true, 'float' => self::FLOAT,
'bool' => true, 'bool' => self::BOOL,
'lookup' => true, 'lookup' => self::LOOKUP,
'list' => true, 'list' => self::ALIST,
'hash' => true, 'hash' => self::HASH,
'mixed' => true 'mixed' => self::MIXED
); );
/** /**
@ -29,10 +42,10 @@ class HTMLPurifier_VarParser
* allowed value lists. * allowed value lists.
*/ */
static public $stringTypes = array( static public $stringTypes = array(
'string' => true, self::STRING => true,
'istring' => true, self::ISTRING => true,
'text' => true, self::TEXT => true,
'itext' => true, self::ITEXT => true,
); );
/** /**
@ -46,42 +59,46 @@ class HTMLPurifier_VarParser
* @return Validated and type-coerced variable * @return Validated and type-coerced variable
*/ */
final public function parse($var, $type, $allow_null = false) { final public function parse($var, $type, $allow_null = false) {
if (!isset(HTMLPurifier_VarParser::$types[$type])) { if (is_string($type)) {
throw new HTMLPurifier_VarParserException("Invalid type '$type'"); if (!isset(HTMLPurifier_VarParser::$types[$type])) {
throw new HTMLPurifier_VarParserException("Invalid type '$type'");
} else {
$type = HTMLPurifier_VarParser::$types[$type];
}
} }
$var = $this->parseImplementation($var, $type, $allow_null); $var = $this->parseImplementation($var, $type, $allow_null);
if ($allow_null && $var === null) return null; if ($allow_null && $var === null) return null;
// These are basic checks, to make sure nothing horribly wrong // These are basic checks, to make sure nothing horribly wrong
// happened in our implementations. // happened in our implementations.
switch ($type) { switch ($type) {
case 'string': case (self::STRING):
case 'istring': case (self::ISTRING):
case 'text': case (self::TEXT):
case 'itext': case (self::ITEXT):
if (!is_string($var)) break; if (!is_string($var)) break;
if ($type[0] == 'i') $var = strtolower($var); if ($type == self::ISTRING || $type == self::ITEXT) $var = strtolower($var);
return $var; return $var;
case 'int': case (self::INT):
if (!is_int($var)) break; if (!is_int($var)) break;
return $var; return $var;
case 'float': case (self::FLOAT):
if (!is_float($var)) break; if (!is_float($var)) break;
return $var; return $var;
case 'bool': case (self::BOOL):
if (!is_bool($var)) break; if (!is_bool($var)) break;
return $var; return $var;
case 'lookup': case (self::LOOKUP):
case 'list': case (self::ALIST):
case 'hash': case (self::HASH):
if (!is_array($var)) break; if (!is_array($var)) break;
if ($type === 'lookup') { if ($type === self::LOOKUP) {
foreach ($var as $k) if ($k !== true) $this->error('Lookup table contains value other than true'); foreach ($var as $k) if ($k !== true) $this->error('Lookup table contains value other than true');
} elseif ($type === 'list') { } elseif ($type === self::ALIST) {
$keys = array_keys($var); $keys = array_keys($var);
if (array_keys($keys) !== $keys) $this->error('Indices for list are not uniform'); if (array_keys($keys) !== $keys) $this->error('Indices for list are not uniform');
} }
return $var; return $var;
case 'mixed': case (self::MIXED):
return $var; return $var;
default: default:
$this->errorInconsistent(get_class($this), $type); $this->errorInconsistent(get_class($this), $type);
@ -111,7 +128,7 @@ class HTMLPurifier_VarParser
* updating subclasses. * updating subclasses.
*/ */
protected function errorInconsistent($class, $type) { protected function errorInconsistent($class, $type) {
throw new HTMLPurifier_Exception("Inconsistency in $class: $type not implemented"); throw new HTMLPurifier_Exception("Inconsistency in $class: ".HTMLPurifier_VarParser::getTypeName($type)." not implemented");
} }
/** /**
@ -119,7 +136,17 @@ class HTMLPurifier_VarParser
*/ */
protected function errorGeneric($var, $type) { protected function errorGeneric($var, $type) {
$vtype = gettype($var); $vtype = gettype($var);
$this->error("Expected type $type, got $vtype"); $this->error("Expected type ".HTMLPurifier_VarParser::getTypeName($type).", got $vtype");
}
static public function getTypeName($type) {
static $lookup;
if (!$lookup) {
// Lazy load the alternative lookup table
$lookup = array_flip(HTMLPurifier_VarParser::$types);
}
if (!isset($lookup[$type])) return 'unknown';
return $lookup[$type];
} }
} }

View File

@ -14,19 +14,19 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
// Note: if code "breaks" from the switch, it triggers a generic // Note: if code "breaks" from the switch, it triggers a generic
// exception to be thrown. Specific errors can be specifically // exception to be thrown. Specific errors can be specifically
// done here. // done here.
case 'mixed': case self::MIXED :
case 'istring': case self::ISTRING :
case 'string': case self::STRING :
case 'text': case self::TEXT :
case 'itext': case self::ITEXT :
return $var; return $var;
case 'int': case self::INT :
if (is_string($var) && ctype_digit($var)) $var = (int) $var; if (is_string($var) && ctype_digit($var)) $var = (int) $var;
return $var; return $var;
case 'float': case self::FLOAT :
if ((is_string($var) && is_numeric($var)) || is_int($var)) $var = (float) $var; if ((is_string($var) && is_numeric($var)) || is_int($var)) $var = (float) $var;
return $var; return $var;
case 'bool': case self::BOOL :
if (is_int($var) && ($var === 0 || $var === 1)) { if (is_int($var) && ($var === 0 || $var === 1)) {
$var = (bool) $var; $var = (bool) $var;
} elseif (is_string($var)) { } elseif (is_string($var)) {
@ -39,9 +39,9 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
} }
} }
return $var; return $var;
case 'list': case self::ALIST :
case 'hash': case self::HASH :
case 'lookup': case self::LOOKUP :
if (is_string($var)) { if (is_string($var)) {
// special case: technically, this is an array with // special case: technically, this is an array with
// a single empty string item, but having an empty // a single empty string item, but having an empty
@ -56,7 +56,7 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
} }
// remove spaces // remove spaces
foreach ($var as $i => $j) $var[$i] = trim($j); foreach ($var as $i => $j) $var[$i] = trim($j);
if ($type === 'hash') { if ($type === self::HASH) {
// key:value,key2:value2 // key:value,key2:value2
$nvar = array(); $nvar = array();
foreach ($var as $keypair) { foreach ($var as $keypair) {
@ -70,8 +70,8 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
if (!is_array($var)) break; if (!is_array($var)) break;
$keys = array_keys($var); $keys = array_keys($var);
if ($keys === array_keys($keys)) { if ($keys === array_keys($keys)) {
if ($type == 'list') return $var; if ($type == self::ALIST) return $var;
elseif ($type == 'lookup') { elseif ($type == self::LOOKUP) {
$new = array(); $new = array();
foreach ($var as $key) { foreach ($var as $key) {
$new[$key] = true; $new[$key] = true;
@ -79,7 +79,7 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
return $new; return $new;
} else break; } else break;
} }
if ($type === 'lookup') { if ($type === self::LOOKUP) {
foreach ($var as $key => $value) { foreach ($var as $key => $value) {
$var[$key] = true; $var[$key] = true;
} }

View File

@ -21,16 +21,12 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
$this->schema->add('Car', 'Seats', 5, 'int', false); $this->schema->add('Car', 'Seats', 5, 'int', false);
$this->assertIdentical($this->schema->defaults['Car']['Seats'], 5); $this->assertIdentical($this->schema->defaults['Car']['Seats'], 5);
$this->assertIdentical($this->schema->info['Car']['Seats'], $this->assertIdentical($this->schema->info['Car']['Seats']->type, HTMLPurifier_VarParser::INT);
new HTMLPurifier_ConfigDef_Directive('int')
);
$this->schema->add('Car', 'Age', null, 'int', true); $this->schema->add('Car', 'Age', null, 'int', true);
$this->assertIdentical($this->schema->defaults['Car']['Age'], null); $this->assertIdentical($this->schema->defaults['Car']['Age'], null);
$this->assertIdentical($this->schema->info['Car']['Age'], $this->assertIdentical($this->schema->info['Car']['Age']->type, HTMLPurifier_VarParser::INT);
new HTMLPurifier_ConfigDef_Directive('int', true)
);
} }
@ -45,15 +41,13 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
); );
$this->assertIdentical($this->schema->defaults['QuantumNumber']['Difficulty'], null); $this->assertIdentical($this->schema->defaults['QuantumNumber']['Difficulty'], null);
$this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty'], $this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty']->type, HTMLPurifier_VarParser::STRING);
new HTMLPurifier_ConfigDef_Directive( $this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty']->allow_null, true);
'string', $this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty']->allowed,
true, array(
array( 'easy' => true,
'easy' => true, 'medium' => true,
'medium' => true, 'hard' => true
'hard' => true
)
) )
); );
@ -82,20 +76,19 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
); );
$this->assertIdentical($this->schema->defaults['Abbrev']['HTH'], 'Happy to Help'); $this->assertIdentical($this->schema->defaults['Abbrev']['HTH'], 'Happy to Help');
$this->assertIdentical($this->schema->info['Abbrev']['HTH'], $this->assertIdentical($this->schema->info['Abbrev']['HTH']->type, HTMLPurifier_VarParser::STRING);
new HTMLPurifier_ConfigDef_Directive( $this->assertIdentical($this->schema->info['Abbrev']['HTH']->allowed,
'string', array(
false, 'Happy to Help' => true,
array( 'Hope that Helps' => true,
'Happy to Help' => true, 'HAIL THE HAND!' => true
'Hope that Helps' => true, )
'HAIL THE HAND!' => true );
), $this->assertIdentical($this->schema->info['Abbrev']['HTH']->aliases,
array( array(
'happy' => 'Happy to Help', 'happy' => 'Happy to Help',
'hope' => 'Hope that Helps', 'hope' => 'Hope that Helps',
'hail' => 'HAIL THE HAND!' 'hail' => 'HAIL THE HAND!'
)
) )
); );
@ -107,9 +100,9 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
$this->schema->addAlias('Home', 'Carpet', 'Home', 'Rug'); $this->schema->addAlias('Home', 'Carpet', 'Home', 'Rug');
$this->assertTrue(!isset($this->schema->defaults['Home']['Carpet'])); $this->assertTrue(!isset($this->schema->defaults['Home']['Carpet']));
$this->assertIdentical($this->schema->info['Home']['Carpet'], $this->assertIdentical($this->schema->info['Home']['Carpet']->namespace, 'Home');
new HTMLPurifier_ConfigDef_DirectiveAlias('Home', 'Rug') $this->assertIdentical($this->schema->info['Home']['Carpet']->name, 'Rug');
); $this->assertIdentical($this->schema->info['Home']['Carpet']->isAlias, true);
} }

View File

@ -29,6 +29,14 @@ class HTMLPurifier_SimpleTest_Reporter extends HTMLReporter
flush(); flush();
} }
public function paintFooter($test_name) {
if (function_exists('xdebug_peak_memory_usage')) {
$max_mem = number_format(xdebug_peak_memory_usage());
echo "<div>Max memory usage: $max_mem bytes</div>";
}
parent::paintFooter($test_name);
}
protected function getCss() { protected function getCss() {
$css = parent::getCss(); $css = parent::getCss();
$css .= ' $css .= '

View File

@ -6,7 +6,7 @@ class HTMLPurifier_VarParser_FlexibleTest extends HTMLPurifier_VarParserHarness
function testValidate() { function testValidate() {
$this->assertValid('foobar', 'string'); $this->assertValid('foobar', 'string');
$this->assertValid('foobar', 'text'); // aliases, lstring = long string $this->assertValid('foobar', 'text');
$this->assertValid('FOOBAR', 'istring', 'foobar'); $this->assertValid('FOOBAR', 'istring', 'foobar');
$this->assertValid('FOOBAR', 'itext', 'foobar'); $this->assertValid('FOOBAR', 'itext', 'foobar');
@ -51,6 +51,10 @@ class HTMLPurifier_VarParser_FlexibleTest extends HTMLPurifier_VarParserHarness
} }
function testValidate_withMagicNumbers() {
$this->assertValid('foobar', HTMLPurifier_VarParser::STRING);
}
function testValidate_null() { function testValidate_null() {
$this->assertIdentical($this->parser->parse(null, 'string', true), null); $this->assertIdentical($this->parser->parse(null, 'string', true), null);
$this->expectException('HTMLPurifier_VarParserException'); $this->expectException('HTMLPurifier_VarParserException');