From b9094d5ec8b45c249bb14f245ffa96dee802779f Mon Sep 17 00:00:00 2001 From: "Edward Z. Yang" Date: Mon, 2 Feb 2009 18:42:23 -0500 Subject: [PATCH] Convert HTMLPurifier_Config to use property list backend. Signed-off-by: Edward Z. Yang --- NEWS | 1 + library/HTMLPurifier/Config.php | 36 ++++++++++-------- library/HTMLPurifier/ConfigSchema.php | 10 +++++ library/HTMLPurifier/ConfigSchema/schema.ser | Bin 7540 -> 11324 bytes library/HTMLPurifier/PropertyList.php | 22 ++++++++--- tests/HTMLPurifier/PropertyListTest.php | 38 +++++++++++-------- 6 files changed, 71 insertions(+), 36 deletions(-) diff --git a/NEWS b/NEWS index 7398a75f..1a221172 100644 --- a/NEWS +++ b/NEWS @@ -28,6 +28,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier tested on Linux. . Removed trailing whitespace from all text files, see remote-trailing-whitespace.php maintenance script. +. Convert configuration to use property list backend. 3.2.0, released 2008-10-31 # Using %Core.CollectErrors forces line number/column tracking on, whereas diff --git a/library/HTMLPurifier/Config.php b/library/HTMLPurifier/Config.php index 48848d19..299bc0f0 100644 --- a/library/HTMLPurifier/Config.php +++ b/library/HTMLPurifier/Config.php @@ -41,11 +41,6 @@ class HTMLPurifier_Config */ protected $serial; - /** - * Two-level associative array of configuration directives - */ - protected $conf; - /** * Parser for variables */ @@ -68,13 +63,18 @@ class HTMLPurifier_Config */ protected $finalized = false; + /** + * Property list containing configuration directives. + */ + protected $plist; + /** * @param $definition HTMLPurifier_ConfigSchema that defines what directives * are allowed. */ public function __construct($definition) { - $this->conf = $definition->defaults; // set up, copy in defaults - $this->def = $definition; // keep a copy around for checking + $this->plist = new HTMLPurifier_PropertyList($definition->defaultPlist); + $this->def = $definition; // keep a copy around for checking $this->parser = new HTMLPurifier_VarParser_Flexible(); } @@ -118,7 +118,7 @@ class HTMLPurifier_Config * @param $key String key */ public function get($namespace, $key) { - if (!$this->finalized && $this->autoFinalize) $this->finalize(); + if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); if (!isset($this->def->info[$namespace][$key])) { // can't add % due to SimpleTest bug trigger_error('Cannot retrieve value of undefined directive ' . htmlspecialchars("$namespace.$key"), @@ -131,7 +131,7 @@ class HTMLPurifier_Config E_USER_ERROR); return; } - return $this->conf[$namespace][$key]; + return $this->plist->get("$namespace.$key"); } /** @@ -139,13 +139,14 @@ class HTMLPurifier_Config * @param $namespace String namespace */ public function getBatch($namespace) { - if (!$this->finalized && $this->autoFinalize) $this->finalize(); + if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); if (!isset($this->def->info[$namespace])) { trigger_error('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace), E_USER_WARNING); return; } - return $this->conf[$namespace]; + $full = $this->getAll(); + return $full[$namespace]; } /** @@ -179,8 +180,13 @@ class HTMLPurifier_Config * Retrieves all directives, organized by namespace */ public function getAll() { - if (!$this->finalized && $this->autoFinalize) $this->finalize(); - return $this->conf; + if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); + $ret = array(); + foreach ($this->plist->squash() as $name => $value) { + list($ns, $key) = explode('.', $name, 2); + $ret[$ns][$key] = $value; + } + return $ret; } /** @@ -240,7 +246,7 @@ class HTMLPurifier_Config return; } } - $this->conf[$namespace][$key] = $value; + $this->plist->set("$namespace.$key", $value); // reset definitions if the directives they depend on changed // this is a very costly process, so it's discouraged @@ -285,7 +291,7 @@ class HTMLPurifier_Config * @param $raw Whether or not definition should be returned raw */ public function getDefinition($type, $raw = false) { - if (!$this->finalized && $this->autoFinalize) $this->finalize(); + if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); $factory = HTMLPurifier_DefinitionCacheFactory::instance(); $cache = $factory->create($type, $this); if (!$raw) { diff --git a/library/HTMLPurifier/ConfigSchema.php b/library/HTMLPurifier/ConfigSchema.php index 3e2563c2..340ed7db 100644 --- a/library/HTMLPurifier/ConfigSchema.php +++ b/library/HTMLPurifier/ConfigSchema.php @@ -11,6 +11,11 @@ class HTMLPurifier_ConfigSchema { */ public $defaults = array(); + /** + * The default property list. Do not edit this property list. + */ + public $defaultPlist; + /** * Definition of the directives. The structure of this is: * @@ -47,6 +52,10 @@ class HTMLPurifier_ConfigSchema { */ static protected $singleton; + public function __construct() { + $this->defaultPlist = new HTMLPurifier_PropertyList(); + } + /** * Unserializes the default ConfigSchema. */ @@ -84,6 +93,7 @@ class HTMLPurifier_ConfigSchema { if ($allow_null) $obj->allow_null = true; $this->info[$namespace][$name] = $obj; $this->defaults[$namespace][$name] = $default; + $this->defaultPlist->set("$namespace.$name", $default); } /** diff --git a/library/HTMLPurifier/ConfigSchema/schema.ser b/library/HTMLPurifier/ConfigSchema/schema.ser index 1ac5ff691eb70c078010f273ba80ef8619bb2034..1eaecd11f856504cde09c1b302c7c1cfd65ec00b 100644 GIT binary patch delta 2360 zcmZuz%WoS+7;h4h*nzYGCC!7VD62xHBCOb^(5w$3wOz%+PE71dMI6d_ckB#V?<}*k zc~Dh3aYaOX;=n2RLx)jSJs5v$MMqIeEYL?|Y74+P^*ic73Ay zv-Q#3qjJTzTskC?C%YaCrB&OrEB9<`r{8IJBf*A@iYHyc11jWc8x`!T{WP>cw5@A* zuen4Lt48e23i2xN+t#*}qIBN9RRACQ`^&|*&G)wF@nh=l(<3z6u%A8yqYb0@(_%68 z5dSl`cz!WkfH2BSeEs_J`OD?PrlD_4teuss3Dxw;z@x2(RU6nFwa_kqkO*3h2Oe<_ zbz*5mNLe|}N%!f9o&;8H7p;xkR--HEkeyh-1eEwwzMtB5Z!2M&JH*Rrs1zc}A967! zvJ}6VSUf9Z8X2!1g_4hRCBXV*;sy%?k3g~g!$t)zQ9S&SC1IQr4pQ zVsd#1-cYRpW%QY3+*iG4b~))13OnSaH6FF8KavMnNJynz+1LnF-OEWJ96`aTBq9q0 zJ*gAtfR^IU)a^SsNSf?X!HCDcqM}RCB{sDJnb)}h-5;h_-+@{xqRu^!ICG*iU`4fw zKZ?kRDiF4Xv7nEzrdmo*sA!D?7++N)!;k-(UMZ?Js)VafQ0^(NBw93`1Imdq4ZjkOy1hfwfM!%^n4WnToQb8 zb7cX;{?Fp?nOp0SBeWY&m>y8-W<#L3ak;S6z=6r@G(9@b)J z6;=w+T}^yf`1K4jP=qc*gFEsxfc#X6j8(P{c(atqm}R2;rkHFlxx-7NLcysSFxRC% zT($U@;_F46B#r3z;@X*sdU?-a2Vu!@9AICSGL#(B#|eS)aT(lb5SrYs*gtHeGVGBd z9FYN5Ik~^ktyFTjH~0c}ER~sXJqc$cV;jhQ=ALf5;L4oqGz?1G^oXi!3%JJAWf7cF zKxyK|Kh7>}roHbAIJ7xbrr(bd8{)w$RDsIxMKXxsR{IM}XPS#a6YefO_Ly&42$2$g zj|+*eYl z>A;t|2S;xVqR!K{@=a!truM+pDBdGkC!Xtrtcz987?}!S)T$=m=(e+cn$~E{80s-L9 XOpwe!8iG&YIQY7tr{_=R7U%y1%zE8P delta 17 YcmdlJ@x^L_BBRkpB?sQkS~5Zc06b;|VgLXD diff --git a/library/HTMLPurifier/PropertyList.php b/library/HTMLPurifier/PropertyList.php index 247eb3b9..2b99fb7b 100644 --- a/library/HTMLPurifier/PropertyList.php +++ b/library/HTMLPurifier/PropertyList.php @@ -15,11 +15,18 @@ class HTMLPurifier_PropertyList */ protected $parent; + protected $cache; + + public function __construct($parent = null) { + $this->parent = $parent; + } + /** * Recursively retrieves the value for a key */ public function get($name) { if ($this->has($name)) return $this->data[$name]; + // possible performance bottleneck, convert to iterative if necessary if ($this->parent) return $this->parent->get($name); throw new HTMLPurifier_Exception("Key '$name' not found"); } @@ -48,12 +55,17 @@ class HTMLPurifier_PropertyList } /** - * Returns an iterator for traversing this array, optionally filtering - * for a certain prefix. + * Squashes this property list and all of its property lists into a single + * array, and returns the array. This value is cached by default. + * @param $force If true, ignores the cache and regenerates the array. */ - public function getIterator($filter = null) { - $a = new ArrayObject($this->data); - return new HTMLPurifier_PropertyListIterator($a->getIterator(), $filter); + public function squash($force = false) { + if ($this->cache !== null && !$force) return $this->cache; + if ($this->parent) { + return $this->cache = array_merge($this->parent->squash($force), $this->data); + } else { + return $this->cache = $this->data; + } } /** diff --git a/tests/HTMLPurifier/PropertyListTest.php b/tests/HTMLPurifier/PropertyListTest.php index 964a7313..a2d4811e 100644 --- a/tests/HTMLPurifier/PropertyListTest.php +++ b/tests/HTMLPurifier/PropertyListTest.php @@ -65,23 +65,29 @@ class HTMLPurifier_PropertyListTest extends UnitTestCase $this->assertIdentical($plist->has('key3'), false); } - function testIterator() { - $plist = new HTMLPurifier_PropertyList(); - $plist->set('nkey1', 'v'); - $plist->set('nkey2', 'v'); - $plist->set('rkey3', 'v'); - $a = array(); - foreach ($plist->getIterator() as $key => $value) { - $a[$key] = $value; - } - $this->assertIdentical($a, array('nkey1' => 'v', 'nkey2' => 'v', 'rkey3' => 'v')); - $a = array(); - foreach ($plist->getIterator('nkey') as $key => $value) { - $a[$key] = $value; - } - $this->assertIdentical($a, array('nkey1' => 'v', 'nkey2' => 'v')); + function testSquash() { + $parent = new HTMLPurifier_PropertyList(); + $parent->set('key1', 'hidden'); + $parent->set('key2', 2); + $plist = new HTMLPurifier_PropertyList($parent); + $plist->set('key1', 1); + $plist->set('key3', 3); + $this->assertIdentical( + $plist->squash(), + array('key1' => 1, 'key2' => 2, 'key3' => 3) + ); + // updates don't show up... + $plist->set('key2', 22); + $this->assertIdentical( + $plist->squash(), + array('key1' => 1, 'key2' => 2, 'key3' => 3) + ); + // until you force + $this->assertIdentical( + $plist->squash(true), + array('key1' => 1, 'key2' => 22, 'key3' => 3) + ); } - } // vim: et sw=4 sts=4