From 5e366b25f83ba3ad277776c35d2d848e850cc398 Mon Sep 17 00:00:00 2001 From: "Edward Z. Yang" Date: Sat, 20 Jan 2007 18:43:58 +0000 Subject: [PATCH] [1.4.0] Support for configuration directive aliases added. git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@668 48356398-32a2-884e-a903-53898d9a118a --- NEWS | 4 +- TODO | 4 +- configdoc/generate.php | 2 + library/HTMLPurifier/Config.php | 19 +++++++- library/HTMLPurifier/ConfigSchema.php | 65 ++++++++++++++++++++++++- tests/HTMLPurifier/ConfigSchemaTest.php | 24 +++++++++ tests/HTMLPurifier/ConfigTest.php | 18 +++++++ 7 files changed, 130 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 06c071f6..9b546dbe 100644 --- a/NEWS +++ b/NEWS @@ -17,7 +17,9 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier ! Configuration documentation looks nicer ! Added %Core.EscapeNonASCIICharacters to workaround loss of Unicode characters while %Core.Encoding is set to a non-UTF-8 encoding. -- Replaced version check with functionality check for DOM +! Support for configuration directive aliases added +- Replaced version check with functionality check for DOM (thanks Stephen + Khoo) . Added smoketest 'all.php', which loads all other smoketests via frames . Implemented AttrDef_CSSURI for url(http://google.com) style declarations . Added convenient single test selector form on test runner diff --git a/TODO b/TODO index 32b0088e..ee219f8d 100644 --- a/TODO +++ b/TODO @@ -9,13 +9,13 @@ TODO List 1.4 release # Add hooks for custom behavior (for instance, YouTube preservation) - # Implement all non-essential attribute transforms - Aggressive caching + - Upgrade SimpleTest testing code to newest version ? Rich set* methods and config file loaders for HTMLPurifier_Config ? Configuration profiles: sets of directives that get set with one func call - ? ConfigSchema directive aliases (so we can rename some of them) 1.5 release + # Implement all non-essential attribute transforms # URI validation routines tighter (see docs/dev-code-quality.html) (COMPLEX) # Advanced URI filtering schemes (see docs/proposal-new-directives.txt) # Error logging for filtering/cleanup procedures diff --git a/configdoc/generate.php b/configdoc/generate.php index 93328356..14335e98 100644 --- a/configdoc/generate.php +++ b/configdoc/generate.php @@ -99,6 +99,8 @@ foreach($schema->info as $namespace_name => $namespace_info) { foreach ($namespace_info as $name => $info) { + if ($info->class == 'alias') continue; + $dom_directive = $dom_document->createElement('directive'); $dom_namespace->appendChild($dom_directive); diff --git a/library/HTMLPurifier/Config.php b/library/HTMLPurifier/Config.php index 43c5681d..dfc734d7 100644 --- a/library/HTMLPurifier/Config.php +++ b/library/HTMLPurifier/Config.php @@ -75,12 +75,17 @@ class HTMLPurifier_Config * @param $namespace String namespace * @param $key String key */ - function get($namespace, $key) { + function get($namespace, $key, $from_alias = false) { if (!isset($this->def->info[$namespace][$key])) { trigger_error('Cannot retrieve value of undefined directive', E_USER_WARNING); return; } + if ($this->def->info[$namespace][$key]->class == 'alias') { + trigger_error('Cannot get value from aliased directive, use real name', + E_USER_ERROR); + return; + } return $this->conf[$namespace][$key]; } @@ -103,12 +108,22 @@ class HTMLPurifier_Config * @param $key String key * @param $value Mixed value */ - function set($namespace, $key, $value) { + function set($namespace, $key, $value, $from_alias = false) { if (!isset($this->def->info[$namespace][$key])) { trigger_error('Cannot set undefined directive to value', E_USER_WARNING); return; } + if ($this->def->info[$namespace][$key]->class == 'alias') { + if ($from_alias) { + trigger_error('Double-aliases not allowed, please fix '. + 'ConfigSchema bug'); + } + $this->set($this->def->info[$namespace][$key]->namespace, + $this->def->info[$namespace][$key]->name, + $value, true); + return; + } $value = $this->def->validate( $value, $this->def->info[$namespace][$key]->type, diff --git a/library/HTMLPurifier/ConfigSchema.php b/library/HTMLPurifier/ConfigSchema.php index 6969c1d2..b5199a20 100644 --- a/library/HTMLPurifier/ConfigSchema.php +++ b/library/HTMLPurifier/ConfigSchema.php @@ -224,6 +224,46 @@ class HTMLPurifier_ConfigSchema { } } + /** + * Defines a directive alias for backwards compatibility + * @static + * @param $namespace + * @param $name Directive that will be aliased + * @param $new_namespace + * @param $new_name Directive that the alias will be to + */ + function defineAlias($namespace, $name, $new_namespace, $new_name) { + $def =& HTMLPurifier_ConfigSchema::instance(); + if (!isset($def->info[$namespace])) { + trigger_error('Cannot define directive alias for undefined namespace', + E_USER_ERROR); + return; + } + if (!ctype_alnum($name)) { + trigger_error('Directive name must be alphanumeric', + E_USER_ERROR); + return; + } + if (isset($def->info[$namespace][$name])) { + trigger_error('Cannot define alias over directive', + E_USER_ERROR); + return; + } + if (!isset($def->info[$new_namespace][$new_name])) { + trigger_error('Cannot define alias to undefined directive', + E_USER_ERROR); + return; + } + if ($def->info[$new_namespace][$new_name]->class == 'alias') { + trigger_error('Cannot define alias to alias', + E_USER_ERROR); + return; + } + $def->info[$namespace][$name] = new HTMLPurifier_ConfigEntity_DirectiveAlias(); + $def->info[$namespace][$name]->namespace = $new_namespace; + $def->info[$namespace][$name]->name = $new_name; + } + /** * Validate a variable according to type. Return null if invalid. */ @@ -318,13 +358,17 @@ class HTMLPurifier_ConfigSchema { /** * Base class for configuration entity */ -class HTMLPurifier_ConfigEntity {} +class HTMLPurifier_ConfigEntity { + var $class = false; +} /** * Structure object describing of a namespace */ class HTMLPurifier_ConfigEntity_Namespace extends HTMLPurifier_ConfigEntity { + var $class = 'namespace'; + /** * String description of what kinds of directives go in this namespace. */ @@ -339,6 +383,8 @@ class HTMLPurifier_ConfigEntity_Namespace extends HTMLPurifier_ConfigEntity { class HTMLPurifier_ConfigEntity_Directive extends HTMLPurifier_ConfigEntity { + var $class = 'directive'; + /** * Hash of value aliases, i.e. values that are equivalent. */ @@ -385,4 +431,21 @@ class HTMLPurifier_ConfigEntity_Directive extends HTMLPurifier_ConfigEntity } +/** + * Structure object describing a directive alias + */ +class HTMLPurifier_ConfigEntity_DirectiveAlias extends HTMLPurifier_ConfigEntity +{ + var $class = 'alias'; + + /** + * Namespace being aliased to + */ + var $namespace; + /** + * Directive being aliased to + */ + var $name; +} + ?> diff --git a/tests/HTMLPurifier/ConfigSchemaTest.php b/tests/HTMLPurifier/ConfigSchemaTest.php index f21c5ad1..7c81d480 100644 --- a/tests/HTMLPurifier/ConfigSchemaTest.php +++ b/tests/HTMLPurifier/ConfigSchemaTest.php @@ -251,6 +251,30 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase $this->assertError('Namespace name must be alphanumeric'); $this->assertNoErrors(); + // alias related tests + + HTMLPurifier_ConfigSchema::defineNamespace('Home', 'Sweet home.'); + HTMLPurifier_ConfigSchema::define('Home', 'Rug', 3, 'int', 'ID.'); + HTMLPurifier_ConfigSchema::defineAlias('Home', 'Carpet', 'Home', 'Rug'); + + $this->expectError('Cannot define directive alias for undefined namespace'); + HTMLPurifier_ConfigSchema::defineAlias('Store', 'Rug', 'Home', 'Rug'); + + $this->expectError('Directive name must be alphanumeric'); + HTMLPurifier_ConfigSchema::defineAlias('Home', 'R.g', 'Home', 'Rug'); + + HTMLPurifier_ConfigSchema::define('Home', 'Rugger', 'Bob Max', 'string', 'Name of.'); + $this->expectError('Cannot define alias over directive'); + HTMLPurifier_ConfigSchema::defineAlias('Home', 'Rugger', 'Home', 'Rug'); + + $this->expectError('Cannot define alias to undefined directive'); + HTMLPurifier_ConfigSchema::defineAlias('Home', 'Rug2', 'Home', 'Rugavan'); + + $this->expectError('Cannot define alias to alias'); + HTMLPurifier_ConfigSchema::defineAlias('Home', 'Rug2', 'Home', 'Carpet'); + + + } function assertValid($var, $type, $ret = null) { diff --git a/tests/HTMLPurifier/ConfigTest.php b/tests/HTMLPurifier/ConfigTest.php index a7eb6115..e4634107 100644 --- a/tests/HTMLPurifier/ConfigTest.php +++ b/tests/HTMLPurifier/ConfigTest.php @@ -199,6 +199,24 @@ class HTMLPurifier_ConfigTest extends UnitTestCase } + function testAliases() { + + HTMLPurifier_ConfigSchema::defineNamespace('Home', 'Sweet home.'); + HTMLPurifier_ConfigSchema::define('Home', 'Rug', 3, 'int', 'ID.'); + HTMLPurifier_ConfigSchema::defineAlias('Home', 'Carpet', 'Home', 'Rug'); + + $config = HTMLPurifier_Config::createDefault(); + + $this->assertEqual($config->get('Home', 'Rug'), 3); + + $this->expectError('Cannot get value from aliased directive, use real name'); + $config->get('Home', 'Carpet'); + + $config->set('Home', 'Carpet', 999); + $this->assertEqual($config->get('Home', 'Rug'), 999); + + } + } ?> \ No newline at end of file