mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2024-12-22 08:21:52 +00:00
[3.1.0] Continue building up validation functions
- Remove incorrect parsing of value aliases - Implement most allowed and value alias checks - Add assertIsBool, assertIsArray and assertIsLookup to ValidatorAtom - Publish string types in VarParser git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1647 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
parent
6b21a841c4
commit
0ee090bc7b
@ -3,6 +3,9 @@
|
||||
class HTMLPurifier_ConfigSchema_InterchangeBuilder
|
||||
{
|
||||
|
||||
/**
|
||||
* Used for processing DEFAULT, nothing else.
|
||||
*/
|
||||
protected $varParser;
|
||||
|
||||
public function __construct($varParser = null) {
|
||||
@ -70,18 +73,7 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
|
||||
}
|
||||
|
||||
if (isset($hash['VALUE-ALIASES'])) {
|
||||
$value_aliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
|
||||
// :TODO: Build corresponding test in Validator.php
|
||||
try {
|
||||
foreach ($value_aliases as $alias => $real) {
|
||||
// might want to allow users to use a different var parser
|
||||
// in this case
|
||||
$directive->valueAliases[$this->varParser->parse($alias, $directive->type, $directive->typeAllowsNull)] =
|
||||
$this->varParser->parse($real, $directive->type, $directive->typeAllowsNull);
|
||||
}
|
||||
} catch (HTMLPurifier_VarParserException $e) {
|
||||
throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in $alias => $real in VALUE-ALIASES in directive hash '$id'");
|
||||
}
|
||||
$directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
|
||||
}
|
||||
|
||||
if (isset($hash['ALIASES'])) {
|
||||
|
@ -79,16 +79,67 @@ class HTMLPurifier_ConfigSchema_Validator
|
||||
$this->validateId($d->id);
|
||||
$this->with($d, 'description')
|
||||
->assertNotEmpty();
|
||||
|
||||
// BEGIN - handled by InterchangeBuilder
|
||||
$this->with($d, 'type')
|
||||
->assertNotEmpty(); // handled by InterchangeBuilder
|
||||
// Much stricter default check, since we're using the base implementation.
|
||||
// handled by InterchangeBuilder
|
||||
->assertNotEmpty();
|
||||
$this->with($d, 'typeAllowsNull')
|
||||
->assertIsBool();
|
||||
try {
|
||||
// This also tests validity of $d->type
|
||||
$this->parser->parse($d->default, $d->type, $d->typeAllowsNull);
|
||||
} catch (HTMLPurifier_VarParserException $e) {
|
||||
$this->error('default', 'had error: ' . $e->getMessage());
|
||||
}
|
||||
// END - handled by InterchangeBuilder
|
||||
|
||||
if (!is_null($d->allowed) || !empty($d->valueAliases)) {
|
||||
// allowed and valueAliases require that we be dealing with
|
||||
// strings, so check for that early.
|
||||
if (!isset(HTMLPurifier_VarParser::$stringTypes[$d->type])) {
|
||||
$this->error('type', 'must be a string type when used with allowed or value aliases');
|
||||
}
|
||||
}
|
||||
|
||||
$this->validateDirectiveAllowed($d);
|
||||
$this->validateDirectiveValueAliases($d);
|
||||
|
||||
array_pop($this->context);
|
||||
}
|
||||
|
||||
public function validateDirectiveAllowed($d) {
|
||||
if (is_null($d->allowed)) return;
|
||||
$this->with($d, 'allowed')
|
||||
->assertNotEmpty()
|
||||
->assertIsLookup(); // handled by InterchangeBuilder
|
||||
$this->context[] = 'allowed';
|
||||
foreach ($d->allowed as $val => $x) {
|
||||
if (!is_string($val)) $this->error("value $val", 'must be a string');
|
||||
}
|
||||
array_pop($this->context);
|
||||
}
|
||||
|
||||
public function validateDirectiveValueAliases($d) {
|
||||
if (is_null($d->valueAliases)) return;
|
||||
$this->with($d, 'valueAliases')
|
||||
->assertIsArray(); // handled by InterchangeBuilder
|
||||
$this->context[] = 'valueAliases';
|
||||
foreach ($d->valueAliases as $alias => $real) {
|
||||
if (!is_string($alias)) $this->error("alias $alias", 'must be a string');
|
||||
if (!is_string($real)) $this->error("alias target $real from alias '$alias'", 'must be a string');
|
||||
if ($alias === $real) {
|
||||
$this->error("alias '$alias'", "must not be an alias to itself");
|
||||
}
|
||||
}
|
||||
if (!is_null($d->allowed)) {
|
||||
foreach ($d->valueAliases as $alias => $real) {
|
||||
if (isset($d->allowed[$alias])) {
|
||||
$this->error("alias '$alias'", 'must not be an allowed value');
|
||||
} elseif (!isset($d->allowed[$real])) {
|
||||
$this->error("alias '$alias'", 'must be an alias to an allowed value');
|
||||
}
|
||||
}
|
||||
}
|
||||
array_pop($this->context);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,16 @@ class HTMLPurifier_ConfigSchema_ValidatorAtom
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function assertIsBool() {
|
||||
if (!is_bool($this->contents)) $this->error('must be a boolean');
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function assertIsArray() {
|
||||
if (!is_array($this->contents)) $this->error('must be an array');
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function assertNotNull() {
|
||||
if ($this->contents === null) $this->error('must not be null');
|
||||
return $this;
|
||||
@ -39,6 +49,14 @@ class HTMLPurifier_ConfigSchema_ValidatorAtom
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function assertIsLookup() {
|
||||
$this->assertIsArray();
|
||||
foreach ($this->contents as $v) {
|
||||
if ($v !== true) $this->error('must be a lookup array');
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function error($msg) {
|
||||
throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg);
|
||||
}
|
||||
|
@ -24,6 +24,17 @@ class HTMLPurifier_VarParser
|
||||
'mixed' => true
|
||||
);
|
||||
|
||||
/**
|
||||
* Lookup table of types that are string, and can have aliases or
|
||||
* allowed value lists.
|
||||
*/
|
||||
static public $stringTypes = array(
|
||||
'string' => true,
|
||||
'istring' => true,
|
||||
'text' => true,
|
||||
'itext' => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* Validate a variable according to type. Throws
|
||||
* HTMLPurifier_VarParserException if invalid.
|
||||
|
@ -0,0 +1,10 @@
|
||||
ERROR: Value 3 in allowed in directive 'Ns.Dir' must be a string
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Generic namespace.
|
||||
----
|
||||
ID: Ns.Dir
|
||||
TYPE: string
|
||||
DESCRIPTION: Description
|
||||
DEFAULT: 'asdf'
|
||||
ALLOWED: 'asdf', 3
|
@ -0,0 +1,10 @@
|
||||
ERROR: Allowed in directive 'Ns.Dir' must not be empty
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Generic namespace.
|
||||
----
|
||||
ID: Ns.Dir
|
||||
TYPE: string
|
||||
DESCRIPTION: Description
|
||||
DEFAULT: 'asdf'
|
||||
ALLOWED:
|
@ -0,0 +1,10 @@
|
||||
ERROR: Type in directive 'Ns.Dir' must be a string type when used with allowed or value aliases
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Namespace
|
||||
----
|
||||
Ns.Dir
|
||||
DESCRIPTION: Directive
|
||||
TYPE: int
|
||||
DEFAULT: 3
|
||||
ALLOWED: 1, 2, 3
|
@ -0,0 +1,10 @@
|
||||
ERROR: Type in directive 'Ns.Dir' must be a string type when used with allowed or value aliases
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Namespace
|
||||
----
|
||||
Ns.Dir
|
||||
DESCRIPTION: Directive
|
||||
TYPE: int
|
||||
DEFAULT: 3
|
||||
VALUE-ALIASES: 2 => 3
|
@ -0,0 +1,10 @@
|
||||
ERROR: Alias 3 in valueAliases in directive 'Ns.Dir' must be a string
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Namespace
|
||||
----
|
||||
Ns.Dir
|
||||
DESCRIPTION: Directive
|
||||
TYPE: string
|
||||
DEFAULT: 'a'
|
||||
VALUE-ALIASES: 3 => 'a'
|
@ -0,0 +1,11 @@
|
||||
ERROR: Alias 'b' in valueAliases in directive 'Ns.Dir' must not be an allowed value
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Namespace
|
||||
----
|
||||
Ns.Dir
|
||||
DESCRIPTION: Directive
|
||||
TYPE: string
|
||||
DEFAULT: 'a'
|
||||
ALLOWED: 'a', 'b', 'c'
|
||||
VALUE-ALIASES: 'b' => 'c'
|
@ -0,0 +1,10 @@
|
||||
ERROR: Alias 'bar' in valueAliases in directive 'Ns.Dir' must not be an alias to itself
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Namespace
|
||||
----
|
||||
Ns.Dir
|
||||
DESCRIPTION: Directive
|
||||
TYPE: string
|
||||
DEFAULT: 'foo'
|
||||
VALUE-ALIASES: 'bar' => 'bar'
|
@ -0,0 +1,11 @@
|
||||
ERROR: Alias 'c' in valueAliases in directive 'Ns.Dir' must be an alias to an allowed value
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Namespace
|
||||
----
|
||||
Ns.Dir
|
||||
DESCRIPTION: Directive
|
||||
TYPE: string
|
||||
DEFAULT: 'a'
|
||||
ALLOWED: 'a', 'b'
|
||||
VALUE-ALIASES: 'c' => 'd'
|
@ -0,0 +1,10 @@
|
||||
ERROR: Alias target 3 from alias 'b' in valueAliases in directive 'Ns.Dir' must be a string
|
||||
----
|
||||
Ns
|
||||
DESCRIPTION: Namespace
|
||||
----
|
||||
Ns.Dir
|
||||
DESCRIPTION: Directive
|
||||
TYPE: string
|
||||
DEFAULT: 'a'
|
||||
VALUE-ALIASES: 'b' => 3
|
@ -55,4 +55,36 @@ class HTMLPurifier_ConfigSchema_ValidatorAtomTest extends UnitTestCase
|
||||
$this->makeAtom('')->assertNotEmpty();
|
||||
}
|
||||
|
||||
public function testAssertIsBool() {
|
||||
$this->makeAtom(false)->assertIsBool();
|
||||
}
|
||||
|
||||
public function testAssertIsBoolFail() {
|
||||
$this->expectValidationException("Property in context must be a boolean");
|
||||
$this->makeAtom('0')->assertIsBool();
|
||||
}
|
||||
|
||||
public function testAssertIsArray() {
|
||||
$this->makeAtom(array())->assertIsArray();
|
||||
}
|
||||
|
||||
public function testAssertIsArrayFail() {
|
||||
$this->expectValidationException("Property in context must be an array");
|
||||
$this->makeAtom('asdf')->assertIsArray();
|
||||
}
|
||||
|
||||
|
||||
public function testAssertIsLookup() {
|
||||
$this->makeAtom(array('foo' => true))->assertIsLookup();
|
||||
}
|
||||
|
||||
public function testAssertIsLookupFail() {
|
||||
$this->expectValidationException("Property in context must be a lookup array");
|
||||
$this->makeAtom(array('foo' => 4))->assertIsLookup();
|
||||
}
|
||||
|
||||
public function testAssertIsLookupFailIsArray() {
|
||||
$this->expectValidationException("Property in context must be an array");
|
||||
$this->makeAtom('asdf')->assertIsLookup();
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,42 @@ class HTMLPurifier_ConfigSchema_ValidatorTest extends UnitTestCase
|
||||
$this->validator->validate($this->interchange);
|
||||
}
|
||||
|
||||
public function testDirectiveTypeAllowsNullIsBool() {
|
||||
$this->makeNamespace('Ns');
|
||||
$d = $this->makeDirective('Ns', 'Dir');
|
||||
$d->default = 0;
|
||||
$d->type = 'int';
|
||||
$d->description = 'Description';
|
||||
$d->typeAllowsNull = 'yes';
|
||||
|
||||
$this->expectValidationException("TypeAllowsNull in directive 'Ns.Dir' must be a boolean");
|
||||
$this->validator->validate($this->interchange);
|
||||
}
|
||||
|
||||
public function testDirectiveValueAliasesIsArray() {
|
||||
$this->makeNamespace('Ns');
|
||||
$d = $this->makeDirective('Ns', 'Dir');
|
||||
$d->default = 'a';
|
||||
$d->type = 'string';
|
||||
$d->description = 'Description';
|
||||
$d->valueAliases = 2;
|
||||
|
||||
$this->expectValidationException("ValueAliases in directive 'Ns.Dir' must be an array");
|
||||
$this->validator->validate($this->interchange);
|
||||
}
|
||||
|
||||
public function testDirectiveAllowedIsLookup() {
|
||||
$this->makeNamespace('Ns');
|
||||
$d = $this->makeDirective('Ns', 'Dir');
|
||||
$d->default = 'foo';
|
||||
$d->type = 'string';
|
||||
$d->description = 'Description';
|
||||
$d->allowed = array('foo' => 1);
|
||||
|
||||
$this->expectValidationException("Allowed in directive 'Ns.Dir' must be a lookup array");
|
||||
$this->validator->validate($this->interchange);
|
||||
}
|
||||
|
||||
// helper functions
|
||||
|
||||
protected function makeNamespace($n) {
|
||||
|
Loading…
Reference in New Issue
Block a user