diff --git a/library/HTMLPurifier/Config.php b/library/HTMLPurifier/Config.php index 25522d58..3f0004e8 100644 --- a/library/HTMLPurifier/Config.php +++ b/library/HTMLPurifier/Config.php @@ -23,6 +23,11 @@ require_once 'HTMLPurifier/DefinitionCache.php'; class HTMLPurifier_Config { + /** + * HTML Purifier's version + */ + var $version = '1.6.1'; + /** * Two-level associative array of configuration directives */ diff --git a/library/HTMLPurifier/DefinitionCache.php b/library/HTMLPurifier/DefinitionCache.php index 7e9942f3..cb4d87fc 100644 --- a/library/HTMLPurifier/DefinitionCache.php +++ b/library/HTMLPurifier/DefinitionCache.php @@ -6,8 +6,6 @@ require_once 'HTMLPurifier/DefinitionCache/Serializer.php'; * Abstract class representing Definition cache managers that implements * useful common methods and is a factory. * @note The configuration object is transformed into the key used by the cache - * @todo Implement flush() - * @todo Implement replace() * @todo Get some sort of versioning variable so the library can easily * invalidate the cache with a new version * @todo Make the test runner cache aware and allow the user to easily @@ -16,7 +14,6 @@ require_once 'HTMLPurifier/DefinitionCache/Serializer.php'; * cache their custom HTMLDefinition, which can be loaded * via a configuration directive * @todo Implement memcached - * @todo Perform type checking on $def objects */ class HTMLPurifier_DefinitionCache { @@ -50,6 +47,20 @@ class HTMLPurifier_DefinitionCache return new HTMLPurifier_DefinitionCache_Serializer($name); } + /** + * Checks if a definition's type jives with the cache's type + * @note Throws an error on failure + * @param $def Definition object to check + * @return Boolean true if good, false if not + */ + function checkDefType($def) { + if ($def->type !== $this->type) { + trigger_error("Cannot use definition of type {$def->type} in cache for {$this->type}"); + return false; + } + return true; + } + /** * Adds a definition object to the cache */ @@ -64,6 +75,13 @@ class HTMLPurifier_DefinitionCache trigger_error('Cannot call abstract method', E_USER_ERROR); } + /** + * Replace an object in the cache + */ + function replace($def, $config) { + trigger_error('Cannot call abstract method', E_USER_ERROR); + } + /** * Retrieves a definition object from the cache */ @@ -78,6 +96,13 @@ class HTMLPurifier_DefinitionCache trigger_error('Cannot call abstract method', E_USER_ERROR); } + /** + * Clears all objects from cache + */ + function flush($config) { + trigger_error('Cannot call abstract method', E_USER_ERROR); + } + } ?> \ No newline at end of file diff --git a/library/HTMLPurifier/DefinitionCache/Serializer.php b/library/HTMLPurifier/DefinitionCache/Serializer.php index 26471433..75d18acc 100644 --- a/library/HTMLPurifier/DefinitionCache/Serializer.php +++ b/library/HTMLPurifier/DefinitionCache/Serializer.php @@ -7,16 +7,25 @@ class HTMLPurifier_DefinitionCache_Serializer extends { function add($def, $config) { + if (!$this->checkDefType($def)) return; $file = $this->generateFilePath($config); if (file_exists($file)) return false; return $this->_write($file, serialize($def)); } function set($def, $config) { + if (!$this->checkDefType($def)) return; $file = $this->generateFilePath($config); return $this->_write($file, serialize($def)); } + function replace($def, $config) { + if (!$this->checkDefType($def)) return; + $file = $this->generateFilePath($config); + if (!file_exists($file)) return false; + return $this->_write($file, serialize($def)); + } + function get($config) { $file = $this->generateFilePath($config); if (!file_exists($file)) return false; @@ -29,13 +38,34 @@ class HTMLPurifier_DefinitionCache_Serializer extends return unlink($file); } + function flush() { + $dir = $this->generateDirectoryPath(); + $dh = opendir($dir); + while (false !== ($filename = readdir($dh))) { + if (empty($filename)) continue; + if ($filename[0] === '.') continue; + // optimization: md5 + .ser will always be 36 char long + // needs to be changed if we change the identifier + if (strlen($filename) !== 36) continue; + unlink($dir . '/' . $filename); + } + } + /** * Generates the file path to the serial file corresponding to * the configuration and definition name */ function generateFilePath($config) { $key = $this->generateKey($config); - return dirname(__FILE__) . '/Serializer/' . $this->type . '/' . $key . '.ser'; + return $this->generateDirectoryPath() . '/' . $key . '.ser'; + } + + /** + * Generates the path to the directory contain this cache's serial files + * @note No trailing slash + */ + function generateDirectoryPath() { + return dirname(__FILE__) . '/Serializer/' . $this->type; } /** diff --git a/release1-update.php b/release1-update.php index c3ab0d84..05b6b904 100644 --- a/release1-update.php +++ b/release1-update.php @@ -77,6 +77,19 @@ if (!$c) { } file_put_contents('library/HTMLPurifier.php', $htmlpurifier_c); +$config_c = file_get_contents('library/HTMLPurifier/Config.php'); +$config_c = preg_replace( + '/var \$version = \'.+?\';/', + "var \$version = '$version';", + $config_c, + 1, $c +); +if (!$c) { + echo 'Could not update Config.php, missing var $version.' . PHP_EOL; + exit; +} +file_put_contents('library/HTMLPurifier/Config.php', $config_c); + echo "Review changes, write something in WHATSNEW, and then SVN commit with log 'Release $version.'" . PHP_EOL; ?> \ No newline at end of file diff --git a/tests/HTMLPurifier/DefinitionCache/SerializerTest.php b/tests/HTMLPurifier/DefinitionCache/SerializerTest.php index 16ada892..506652dc 100644 --- a/tests/HTMLPurifier/DefinitionCache/SerializerTest.php +++ b/tests/HTMLPurifier/DefinitionCache/SerializerTest.php @@ -91,30 +91,43 @@ class HTMLPurifier_DefinitionCache_SerializerTest extends UnitTestCase $this->assertNotEqual ($def_original, $def_3); // did not change! $this->assertIdentical($def_3, $def_2); + $cache->replace($def_original, $config); + $def_4 = $cache->get($config); + $this->assertIdentical($def_original, $def_4); + $cache->remove($config); $this->assertFileNotExist($file); - $def_4 = $cache->get($config); - $this->assertFalse($def_4); + $this->assertFalse($cache->replace($def_original, $config)); + $def_5 = $cache->get($config); + $this->assertFalse($def_5); } function test_errors() { - /*$cache = new HTMLPurifier_DefinitionCache_Serializer('Test'); + $cache = new HTMLPurifier_DefinitionCache_Serializer('Test'); $def = new HTMLPurifier_Definition(); $def->setup = true; $def->type = 'NotTest'; + $config = $this->generateConfigMock(array('Test' => 'foo')); - $this->expectError('Cannot add definition of type NotTest to cache for Test');*/ + $this->expectError('Cannot use definition of type NotTest in cache for Test'); + $cache->add($def, $config); + + $this->expectError('Cannot use definition of type NotTest in cache for Test'); + $cache->set($def, $config); + + $this->expectError('Cannot use definition of type NotTest in cache for Test'); + $cache->replace($def, $config); } function test_flush() { - /* - $cache = new HTMLPurifier_DefinitionCache_Serializer(); - $config1 = $this->generateConfigMock(array('Candles' => 1)); - $config2 = $this->generateConfigMock(array('Candles' => 2)); - $config3 = $this->generateConfigMock(array('Candles' => 3)); + $cache = new HTMLPurifier_DefinitionCache_Serializer('Test'); + + $config1 = $this->generateConfigMock(array('Test' => 1)); + $config2 = $this->generateConfigMock(array('Test' => 2)); + $config3 = $this->generateConfigMock(array('Test' => 3)); $def1 = $this->generateDefinition(array('info_candles' => 1)); $def2 = $this->generateDefinition(array('info_candles' => 2)); @@ -124,12 +137,16 @@ class HTMLPurifier_DefinitionCache_SerializerTest extends UnitTestCase $cache->add($def2, $config2); $cache->add($def3, $config3); - $this->assertTrue($cache->get('Test', $config1)); - $this->assertTrue($cache->get('Test', $config2)); - $this->assertTrue($cache->get('Test', $config3)); + $this->assertEqual($def1, $cache->get($config1)); + $this->assertEqual($def2, $cache->get($config2)); + $this->assertEqual($def3, $cache->get($config3)); + + $cache->flush(); + + $this->assertFalse($cache->get($config1)); + $this->assertFalse($cache->get($config2)); + $this->assertFalse($cache->get($config3)); - $cache->flush('Test'); - */ } /**