diff --git a/NEWS b/NEWS index 31c6eb29..1d3b5877 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier 3.3.0, unknown release date ! Implement CSS property 'overflow' when %CSS.AllowTricky is true. +! Implement generic property list classess - Fix bug with testEncodingSupportsASCII() algorithm when iconv() implementation does not do the "right thing" with characters not supported in the output set. diff --git a/library/HTMLPurifier/PropertyList.php b/library/HTMLPurifier/PropertyList.php new file mode 100644 index 00000000..4faeadfe --- /dev/null +++ b/library/HTMLPurifier/PropertyList.php @@ -0,0 +1,72 @@ +has($name)) return $this->data[$name]; + if ($this->parent) return $this->parent->get($name); + throw new HTMLPurifier_Exception("Key '$name' not found"); + } + + /** + * Sets the value of a key, for this plist + */ + public function set($name, $value) { + $this->data[$name] = $value; + } + + /** + * Returns true if a given key exists + */ + public function has($name) { + return array_key_exists($name, $this->data); + } + + /** + * Resets a value to the value of it's parent, usually the default. If + * no value is specified, the entire plist is reset. + */ + public function reset($name = null) { + if ($name == null) $this->data = array(); + else unset($this->data[$name]); + } + + /** + * Returns an iterator for traversing this array, optionally filtering + * for a certain prefix. + */ + public function getIterator($filter = null) { + $a = new ArrayObject($this->data); + return new HTMLPurifier_PropertyListIterator($a->getIterator(), $filter); + } + + /** + * Returns the parent plist. + */ + public function getParent() { + return $this->parent; + } + + /** + * Sets the parent plist. + */ + public function setParent($plist) { + $this->parent = $plist; + } +} diff --git a/library/HTMLPurifier/PropertyListIterator.php b/library/HTMLPurifier/PropertyListIterator.php new file mode 100644 index 00000000..204a340e --- /dev/null +++ b/library/HTMLPurifier/PropertyListIterator.php @@ -0,0 +1,30 @@ +l = strlen($filter); + $this->filter = $filter; + } + + public function accept() { + $key = $this->getInnerIterator()->key(); + if( strncmp($key, $this->filter, $this->l) !== 0 ) { + return false; + } + return true; + } + +} diff --git a/tests/HTMLPurifier/PropertyListTest.php b/tests/HTMLPurifier/PropertyListTest.php new file mode 100644 index 00000000..3c8fed02 --- /dev/null +++ b/tests/HTMLPurifier/PropertyListTest.php @@ -0,0 +1,85 @@ +set('key', 'value'); + $this->assertIdentical($plist->get('key'), 'value'); + } + + function testNotFound() { + $this->expectException(new HTMLPurifier_Exception("Key 'key' not found")); + $plist = new HTMLPurifier_PropertyList(); + $plist->get('key'); + } + + function testRecursion() { + $parent_plist = new HTMLPurifier_PropertyList(); + $parent_plist->set('key', 'value'); + $plist = new HTMLPurifier_PropertyList(); + $plist->setParent($parent_plist); + $this->assertIdentical($plist->get('key'), 'value'); + } + + function testOverride() { + $parent_plist = new HTMLPurifier_PropertyList(); + $parent_plist->set('key', 'value'); + $plist = new HTMLPurifier_PropertyList(); + $plist->setParent($parent_plist); + $plist->set('key', 'value2'); + $this->assertIdentical($plist->get('key'), 'value2'); + } + + function testRecursionNotFound() { + $this->expectException(new HTMLPurifier_Exception("Key 'key' not found")); + $parent_plist = new HTMLPurifier_PropertyList(); + $plist = new HTMLPurifier_PropertyList(); + $plist->setParent($parent_plist); + $this->assertIdentical($plist->get('key'), 'value'); + } + + function testHas() { + $plist = new HTMLPurifier_PropertyList(); + $this->assertIdentical($plist->has('key'), false); + $plist->set('key', 'value'); + $this->assertIdentical($plist->has('key'), true); + } + + function testReset() { + $plist = new HTMLPurifier_PropertyList(); + $plist->set('key1', 'value'); + $plist->set('key2', 'value'); + $plist->set('key3', 'value'); + $this->assertIdentical($plist->has('key1'), true); + $this->assertIdentical($plist->has('key2'), true); + $this->assertIdentical($plist->has('key3'), true); + $plist->reset('key2'); + $this->assertIdentical($plist->has('key1'), true); + $this->assertIdentical($plist->has('key2'), false); + $this->assertIdentical($plist->has('key3'), true); + $plist->reset(); + $this->assertIdentical($plist->has('key1'), false); + $this->assertIdentical($plist->has('key2'), false); + $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')); + } + +}