0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-12-22 08:21:52 +00:00

Fix two bugs with caching of customized raw definitions.

The first bug is that we will repeatedly write out the result
of a customized raw definition to the filesystem, even when a cache
entry already exists.

The second bug is that caching these definitions doesn't actually
work (the cache entry is written but never used.)  A new API
for retrieving raw definitions permits the user to take advantage
of caching.

Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
This commit is contained in:
Edward Z. Yang 2010-12-30 23:51:53 +00:00
parent 6dcc37cb55
commit f3d050c517
11 changed files with 375 additions and 91 deletions

8
NEWS
View File

@ -9,7 +9,11 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Internal change . Internal change
========================== ==========================
4.2.1, unknown release date 4.3.0, unknown release date
# Fixed broken caching of customized raw definitions, but requires an
API change. The old API still works but will emit a warning,
see http://htmlpurifier.org/docs/enduser-customize.html#optimized
for how to upgrade your code.
! Added %HTML.Nofollow to add rel="nofollow" to external links. ! Added %HTML.Nofollow to add rel="nofollow" to external links.
! More types of SPL autoloaders allowed on later versions of PHP. ! More types of SPL autoloaders allowed on later versions of PHP.
! Implementations for position, top, left, right, bottom, z-index ! Implementations for position, top, left, right, bottom, z-index
@ -24,6 +28,8 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
This safety check is only done for HTMLPurifier.auto.php; if you This safety check is only done for HTMLPurifier.auto.php; if you
are using standalone or the specialized includes files, you're are using standalone or the specialized includes files, you're
expected to know what you're doing. expected to know what you're doing.
- Stop repeatedly writing the cache file after I'm done customizing a
raw definition.
4.2.0, released 2010-09-15 4.2.0, released 2010-09-15
! Added %Core.RemoveProcessingInstructions, which lets you remove ! Added %Core.RemoveProcessingInstructions, which lets you remove

View File

@ -146,7 +146,9 @@
<pre>$config = HTMLPurifier_Config::createDefault(); <pre>$config = HTMLPurifier_Config::createDefault();
$config-&gt;set('HTML.DefinitionID', 'enduser-customize.html tutorial'); $config-&gt;set('HTML.DefinitionID', 'enduser-customize.html tutorial');
$config-&gt;set('HTML.DefinitionRev', 1); $config-&gt;set('HTML.DefinitionRev', 1);
$def = $config-&gt;getHTMLDefinition(true);</pre> if ($def = $config-&gt;maybeGetRawHTMLDefinition()) {
// our code will go here
}</pre>
<p> <p>
Assuming that HTML Purifier has already been properly loaded (hint: Assuming that HTML Purifier has already been properly loaded (hint:
@ -174,23 +176,15 @@ $def = $config-&gt;getHTMLDefinition(true);</pre>
</li> </li>
<li> <li>
The fourth line retrieves a raw <code>HTMLPurifier_HTMLDefinition</code> The fourth line retrieves a raw <code>HTMLPurifier_HTMLDefinition</code>
object that we will be tweaking. If the parameter was removed, we object that we will be tweaking. Interestingly enough, we have
would be retrieving a fully formed definition object, which is somewhat placed it in an if block: this is because
useless for customization purposes. <code>maybeGetRawHTMLDefinition</code>, as its name suggests, may
return a NULL, in which case we should skip doing any
initialization. This, in fact, will correspond to when our fully
customized object is already in the cache.
</li> </li>
</ul> </ul>
<h3>Broken backwards-compatibility</h3>
<p>
Those of you who have already been twiddling around with the raw
HTML definition object, you'll be noticing that you're getting an error
when you attempt to retrieve the raw definition object without specifying
a DefinitionID. It is vital to caching (see below) that you make a unique
name for your customized definition, so make up something right now and
things will operate again.
</p>
<h2>Turn off caching</h2> <h2>Turn off caching</h2>
<p> <p>
@ -781,6 +775,75 @@ $form-&gt;excludes = array('form' => true);</strong></pre>
<li><a href="http://repo.or.cz/w/htmlpurifier.git?a=blob;hb=HEAD;f=library/HTMLPurifier/ElementDef.php"><code>library/HTMLPurifier/ElementDef.php</code></a></li> <li><a href="http://repo.or.cz/w/htmlpurifier.git?a=blob;hb=HEAD;f=library/HTMLPurifier/ElementDef.php"><code>library/HTMLPurifier/ElementDef.php</code></a></li>
</ul> </ul>
<h2 id="optimized">Notes for HTML Purifier 4.2.0 and earlier</h3>
<p>
Previously, this tutorial gave some incorrect template code for
editing raw definitions, and that template code will now produce the
error <q>Due to a documentation error in previous version of HTML
Purifier...</q> Here is how to mechanically transform old-style
code into new-style code.
</p>
<p>
First, identify all code that edits the raw definition object, and
put it together. Ensure none of this code must be run on every
request; if some sub-part needs to always be run, move it outside
this block. Here is an example below, with the raw definition
object code bolded.
</p>
<pre>$config = HTMLPurifier_Config::createDefault();
$config-&gt;set('HTML.DefinitionID', 'enduser-customize.html tutorial');
$config-&gt;set('HTML.DefinitionRev', 1);
$def = $config-&gt;getHTMLDefinition(true);
<strong>$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');</strong>
$purifier = new HTMLPurifier($config);</pre>
<p>
Next, replace the raw definition retrieval with a
maybeGetRawHTMLDefinition method call inside an if conditional, and
place the editing code inside that if block.
</p>
<pre>$config = HTMLPurifier_Config::createDefault();
$config-&gt;set('HTML.DefinitionID', 'enduser-customize.html tutorial');
$config-&gt;set('HTML.DefinitionRev', 1);
<strong>if ($def = $config-&gt;maybeGetRawHTMLDefinition()) {
$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
}</strong>
$purifier = new HTMLPurifier($config);</pre>
<p>
And you're done! Alternatively, if you're OK with not ever caching
your code, the following will still work and not emit warnings.
</p>
<pre>$config = HTMLPurifier_Config::createDefault();
$def = $config-&gt;getHTMLDefinition(true);
$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
$purifier = new HTMLPurifier($config);</pre>
<p>
A slightly less efficient version of this was what was going on with
old versions of HTML Purifier.
</p>
<p>
<em>Technical notes:</em> ajh pointed out on <a
href="http://htmlpurifier.org/phorum/read.php?5,5164,5169#msg-5169">in a forum topic</a> that
HTML Purifier appeared to be repeatedly writing to the cache even
when a cache entry already existed. Investigation lead to the
discovery of the following infelicity: caching of customized
definitions didn't actually work! The problem was that even though
a cache file would be written out at the end of the process, there
was no way for HTML Purifier to say, <q>Actually, I've already got a
copy of your work, no need to reconfigure your
customizations</q>. This required the API to change: placing
all of the customizations to the raw definition object in a
conditional which could be skipped.
</p>
</body></html> </body></html>
<!-- vim: et sw=4 sts=4 <!-- vim: et sw=4 sts=4

View File

@ -76,7 +76,8 @@ class HTMLPurifier_Config
/** /**
* Set to false if you do not want line and file numbers in errors * Set to false if you do not want line and file numbers in errors
* (useful when unit testing) * (useful when unit testing). This will also compress some errors
* and exceptions.
*/ */
public $chatty = true; public $chatty = true;
@ -318,26 +319,64 @@ class HTMLPurifier_Config
* Retrieves object reference to the HTML definition. * Retrieves object reference to the HTML definition.
* @param $raw Return a copy that has not been setup yet. Must be * @param $raw Return a copy that has not been setup yet. Must be
* called before it's been setup, otherwise won't work. * called before it's been setup, otherwise won't work.
* @param $optimized If true, this method may return null, to
* indicate that a cached version of the modified
* definition object is available and no further edits
* are necessary. Consider using
* maybeGetRawHTMLDefinition, which is more explicitly
* named, instead.
*/ */
public function getHTMLDefinition($raw = false) { public function getHTMLDefinition($raw = false, $optimized = false) {
return $this->getDefinition('HTML', $raw); return $this->getDefinition('HTML', $raw, $optimized);
} }
/** /**
* Retrieves object reference to the CSS definition * Retrieves object reference to the CSS definition
* @param $raw Return a copy that has not been setup yet. Must be * @param $raw Return a copy that has not been setup yet. Must be
* called before it's been setup, otherwise won't work. * called before it's been setup, otherwise won't work.
* @param $optimized If true, this method may return null, to
* indicate that a cached version of the modified
* definition object is available and no further edits
* are necessary. Consider using
* maybeGetRawCSSDefinition, which is more explicitly
* named, instead.
*/ */
public function getCSSDefinition($raw = false) { public function getCSSDefinition($raw = false, $optimized = false) {
return $this->getDefinition('CSS', $raw); return $this->getDefinition('CSS', $raw, $optimized);
}
/**
* Retrieves object reference to the URI definition
* @param $raw Return a copy that has not been setup yet. Must be
* called before it's been setup, otherwise won't work.
* @param $optimized If true, this method may return null, to
* indicate that a cached version of the modified
* definition object is available and no further edits
* are necessary. Consider using
* maybeGetRawURIDefinition, which is more explicitly
* named, instead.
*/
public function getURIDefinition($raw = false, $optimized = false) {
return $this->getDefinition('URI', $raw, $optimized);
} }
/** /**
* Retrieves a definition * Retrieves a definition
* @param $type Type of definition: HTML, CSS, etc * @param $type Type of definition: HTML, CSS, etc
* @param $raw Whether or not definition should be returned raw * @param $raw Whether or not definition should be returned raw
* @param $optimized Only has an effect when $raw is true. Whether
* or not to return null if the result is already present in
* the cache. This is off by default for backwards
* compatibility reasons, but you need to do things this
* way in order to ensure that caching is done properly.
* Check out enduser-customize.html for more details.
* We probably won't ever change this default, as much as the
* maybe semantics is the "right thing to do."
*/ */
public function getDefinition($type, $raw = false) { public function getDefinition($type, $raw = false, $optimized = false) {
if ($optimized && !$raw) {
throw new HTMLPurifier_Exception("Cannot set optimized = true when raw = false");
}
if (!$this->finalized) $this->autoFinalize(); if (!$this->finalized) $this->autoFinalize();
// temporarily suspend locks, so we can handle recursive definition calls // temporarily suspend locks, so we can handle recursive definition calls
$lock = $this->lock; $lock = $this->lock;
@ -346,52 +385,137 @@ class HTMLPurifier_Config
$cache = $factory->create($type, $this); $cache = $factory->create($type, $this);
$this->lock = $lock; $this->lock = $lock;
if (!$raw) { if (!$raw) {
// see if we can quickly supply a definition // full definition
// ---------------
// check if definition is in memory
if (!empty($this->definitions[$type])) { if (!empty($this->definitions[$type])) {
if (!$this->definitions[$type]->setup) { $def = $this->definitions[$type];
$this->definitions[$type]->setup($this); // check if the definition is setup
$cache->set($this->definitions[$type], $this); if ($def->setup) {
return $def;
} else {
$def->setup($this);
if ($def->optimized) $cache->add($def, $this);
return $def;
} }
return $this->definitions[$type];
} }
// memory check missed, try cache // check if definition is in cache
$this->definitions[$type] = $cache->get($this); $def = $cache->get($this);
if ($this->definitions[$type]) { if ($def) {
// definition in cache, return it // definition in cache, save to memory and return it
return $this->definitions[$type]; $this->definitions[$type] = $def;
return $def;
} }
} elseif ( // initialize it
!empty($this->definitions[$type]) && $def = $this->initDefinition($type);
!$this->definitions[$type]->setup // set it up
) { $this->lock = $type;
// raw requested, raw in memory, quick return $def->setup($this);
return $this->definitions[$type]; $this->lock = null;
// save in cache
$cache->add($def, $this);
// return it
return $def;
} else {
// raw definition
// --------------
// check preconditions
$def = null;
if ($optimized) {
if (is_null($this->get($type . '.DefinitionID'))) {
// fatally error out if definition ID not set
throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID");
}
}
if (!empty($this->definitions[$type])) {
$def = $this->definitions[$type];
if ($def->setup && !$optimized) {
$extra = $this->chatty ? " (try moving this code block earlier in your initialization)" : "";
throw new HTMLPurifier_Exception("Cannot retrieve raw definition after it has already been setup" . $extra);
}
if ($def->optimized === null) {
$extra = $this->chatty ? " (try flushing your cache)" : "";
throw new HTMLPurifier_Exception("Optimization status of definition is unknown" . $extra);
}
if ($def->optimized !== $optimized) {
$msg = $optimized ? "optimized" : "unoptimized";
$extra = $this->chatty ? " (this backtrace is for the first inconsistent call, which was for a $msg raw definition)" : "";
throw new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals" . $extra);
}
}
// check if definition was in memory
if ($def) {
if ($def->setup) {
// invariant: $optimized === true (checked above)
return null;
} else {
return $def;
}
}
// if optimized, check if definition was in cache
// (because we do the memory check first, this formulation
// is prone to cache slamming, but I think
// guaranteeing that either /all/ of the raw
// setup code or /none/ of it is run is more important.)
if ($optimized) {
// This code path only gets run once; once we put
// something in $definitions (which is guaranteed by the
// trailing code), we always short-circuit above.
$def = $cache->get($this);
if ($def) {
// save the full definition for later, but don't
// return it yet
$this->definitions[$type] = $def;
return null;
}
}
// check invariants for creation
if (!$optimized) {
if (!is_null($this->get($type . '.DefinitionID'))) {
if ($this->chatty) {
$this->triggerError("Due to a documentation error in previous version of HTML Purifier, your definitions are not being cached. If this is OK, you can remove the %$type.DefinitionRev and %$type.DefinitionID declaration. Otherwise, modify your code to use maybeGetRawDefinition, and test if the returned value is null before making any edits (if it is null, that means that a cached version is available, and no raw operations are necessary). See <a href='http://htmlpurifier.org/docs/enduser-customize.html#optimized'>Customize</a> for more details", E_USER_WARNING);
} else {
$this->triggerError("Useless DefinitionID declaration", E_USER_WARNING);
}
}
}
// initialize it
$def = $this->initDefinition($type);
$def->optimized = $optimized;
return $def;
} }
throw new HTMLPurifier_Exception("The impossible happened!");
}
private function initDefinition($type) {
// quick checks failed, let's create the object // quick checks failed, let's create the object
if ($type == 'HTML') { if ($type == 'HTML') {
$this->definitions[$type] = new HTMLPurifier_HTMLDefinition(); $def = new HTMLPurifier_HTMLDefinition();
} elseif ($type == 'CSS') { } elseif ($type == 'CSS') {
$this->definitions[$type] = new HTMLPurifier_CSSDefinition(); $def = new HTMLPurifier_CSSDefinition();
} elseif ($type == 'URI') { } elseif ($type == 'URI') {
$this->definitions[$type] = new HTMLPurifier_URIDefinition(); $def = new HTMLPurifier_URIDefinition();
} else { } else {
throw new HTMLPurifier_Exception("Definition of $type type not supported"); throw new HTMLPurifier_Exception("Definition of $type type not supported");
} }
// quick abort if raw $this->definitions[$type] = $def;
if ($raw) { return $def;
if (is_null($this->get($type . '.DefinitionID'))) { }
// fatally error out if definition ID not set
throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID"); public function maybeGetRawDefinition($name) {
} return $this->getDefinition($name, true, true);
return $this->definitions[$type]; }
}
// set it up public function maybeGetRawHTMLDefinition() {
$this->lock = $type; return $this->getDefinition('HTML', true, true);
$this->definitions[$type]->setup($this); }
$this->lock = null;
// save in cache public function maybeGetRawCSSDefinition() {
$cache->set($this->definitions[$type], $this); return $this->getDefinition('CSS', true, true);
return $this->definitions[$type]; }
public function maybeGetRawURIDefinition() {
return $this->getDefinition('URI', true, true);
} }
/** /**
@ -549,17 +673,22 @@ class HTMLPurifier_Config
/** /**
* Produces a nicely formatted error message by supplying the * Produces a nicely formatted error message by supplying the
* stack frame information from two levels up and OUTSIDE of * stack frame information OUTSIDE of HTMLPurifier_Config.
* HTMLPurifier_Config.
*/ */
protected function triggerError($msg, $no) { protected function triggerError($msg, $no) {
// determine previous stack frame // determine previous stack frame
$backtrace = debug_backtrace(); $extra = '';
if ($this->chatty && isset($backtrace[1])) { if ($this->chatty) {
$frame = $backtrace[1]; $trace = debug_backtrace();
$extra = " on line {$frame['line']} in file {$frame['file']}"; // zip(tail(trace), trace) -- but PHP is not Haskell har har
} else { for ($i = 0, $c = count($trace); $i < $c - 1; $i++) {
$extra = ''; if ($trace[$i + 1]['class'] === 'HTMLPurifier_Config') {
continue;
}
$frame = $trace[$i];
$extra = " invoked on line {$frame['line']} in file {$frame['file']}";
break;
}
} }
trigger_error($msg . $extra, $no); trigger_error($msg . $extra, $no);
} }

View File

@ -1,6 +1,6 @@
HTML.Nofollow HTML.Nofollow
TYPE: bool TYPE: bool
VERSION: 4.2.1 VERSION: 4.3.0
DEFAULT: FALSE DEFAULT: FALSE
--DESCRIPTION-- --DESCRIPTION--
If enabled, nofollow rel attributes are added to all outgoing links. If enabled, nofollow rel attributes are added to all outgoing links.

View File

@ -12,6 +12,17 @@ abstract class HTMLPurifier_Definition
*/ */
public $setup = false; public $setup = false;
/**
* If true, write out the final definition object to the cache after
* setup. This will be true only if all invocations to get a raw
* definition object are also optimized. This does not cause file
* system thrashing because on subsequent calls the cached object
* is used and any writes to the raw definition object are short
* circuited. See enduser-customize.html for the high-level
* picture.
*/
public $optimized = null;
/** /**
* What type of definition is it? * What type of definition is it?
*/ */

View File

@ -18,8 +18,6 @@ class HTMLPurifier_AttrValidator_ErrorsTest extends HTMLPurifier_ErrorsHarness
} }
function testAttributesTransformedGlobalPre() { function testAttributesTransformedGlobalPre() {
$this->config->set('HTML.DefinitionID',
'HTMLPurifier_AttrValidator_ErrorsTest::testAttributesTransformedGlobalPre');
$def = $this->config->getHTMLDefinition(true); $def = $this->config->getHTMLDefinition(true);
generate_mock_once('HTMLPurifier_AttrTransform'); generate_mock_once('HTMLPurifier_AttrTransform');
$transform = new HTMLPurifier_AttrTransformMock(); $transform = new HTMLPurifier_AttrTransformMock();

View File

@ -4,6 +4,7 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
{ {
protected $schema; protected $schema;
protected $oldFactory;
public function setUp() { public function setUp() {
// set up a dummy schema object for testing // set up a dummy schema object for testing
@ -230,23 +231,58 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
$this->assertNotEqual($def, $old_def); $this->assertNotEqual($def, $old_def);
$this->assertTrue($def->setup); $this->assertTrue($def->setup);
// test retrieval of raw definition }
function test_getHTMLDefinition_deprecatedRawError() {
$config = HTMLPurifier_Config::createDefault();
$config->chatty = false;
// test deprecated retrieval of raw definition
$config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->test_getHTMLDefinition()'); $config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->test_getHTMLDefinition()');
$config->set('HTML.DefinitionRev', 3); $config->set('HTML.DefinitionRev', 3);
$this->expectError("Useless DefinitionID declaration");
$def = $config->getHTMLDefinition(true); $def = $config->getHTMLDefinition(true);
$this->assertNotEqual($def, $old_def);
$this->assertEqual(false, $def->setup); $this->assertEqual(false, $def->setup);
// auto initialization // auto initialization
$config->getHTMLDefinition(); $config->getHTMLDefinition();
$this->assertTrue($def->setup); $this->assertTrue($def->setup);
}
function test_getHTMLDefinition_optimizedRawError() {
$this->expectException(new HTMLPurifier_Exception("Cannot set optimized = true when raw = false"));
$config = HTMLPurifier_Config::createDefault();
$config->getHTMLDefinition(false, true);
}
function test_getHTMLDefinition_rawAfterSetupError() {
$this->expectException(new HTMLPurifier_Exception("Cannot retrieve raw definition after it has already been setup"));
$config = HTMLPurifier_Config::createDefault();
$config->chatty = false;
$config->getHTMLDefinition();
$config->getHTMLDefinition(true);
}
function test_getHTMLDefinition_inconsistentOptimizedError() {
$this->expectError("Useless DefinitionID declaration");
$this->expectException(new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals"));
$config = HTMLPurifier_Config::create(array('HTML.DefinitionID' => 'HTMLPurifier_ConfigTest->test_getHTMLDefinition_inconsistentOptimizedError'));
$config->chatty = false;
$config->getHTMLDefinition(true, false);
$config->getHTMLDefinition(true, true);
}
function test_getHTMLDefinition_inconsistentOptimizedError2() {
$this->expectException(new HTMLPurifier_Exception("Inconsistent use of optimized and unoptimized raw definition retrievals"));
$config = HTMLPurifier_Config::create(array('HTML.DefinitionID' => 'HTMLPurifier_ConfigTest->test_getHTMLDefinition_inconsistentOptimizedError2'));
$config->chatty = false;
$config->getHTMLDefinition(true, true);
$config->getHTMLDefinition(true, false);
} }
function test_getHTMLDefinition_rawError() { function test_getHTMLDefinition_rawError() {
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$this->expectException(new HTMLPurifier_Exception('Cannot retrieve raw version without specifying %HTML.DefinitionID')); $this->expectException(new HTMLPurifier_Exception('Cannot retrieve raw version without specifying %HTML.DefinitionID'));
$def = $config->getHTMLDefinition(true); $def = $config->getHTMLDefinition(true, true);
} }
function test_getCSSDefinition() { function test_getCSSDefinition() {
@ -458,6 +494,64 @@ class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
$this->assertIdentical($config, $config2); $this->assertIdentical($config, $config2);
} }
function testDefinitionCachingNothing() {
list($mock, $config) = $this->setupCacheMock('HTML');
// should not touch the cache
$mock->expectNever('get');
$mock->expectNever('add');
$mock->expectNever('set');
$config->getDefinition('HTML', true);
$config->getDefinition('HTML', true);
$config->getDefinition('HTML');
$this->teardownCacheMock();
}
function testDefinitionCachingOptimized() {
list($mock, $config) = $this->setupCacheMock('HTML');
$mock->expectNever('set');
$config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->testDefinitionCachingOptimized');
$mock->expectOnce('get');
$mock->setReturnValue('get', null);
$this->assertTrue($config->maybeGetRawHTMLDefinition());
$this->assertTrue($config->maybeGetRawHTMLDefinition());
$mock->expectOnce('add');
$config->getDefinition('HTML');
$this->teardownCacheMock();
}
function testDefinitionCachingOptimizedHit() {
$fake_config = HTMLPurifier_Config::createDefault();
$fake_def = $fake_config->getHTMLDefinition();
list($mock, $config) = $this->setupCacheMock('HTML');
// should never frob cache
$mock->expectNever('add');
$mock->expectNever('set');
$config->set('HTML.DefinitionID', 'HTMLPurifier_ConfigTest->testDefinitionCachingOptimizedHit');
$mock->expectOnce('get');
$mock->setReturnValue('get', $fake_def);
$this->assertNull($config->maybeGetRawHTMLDefinition());
$config->getDefinition('HTML');
$config->getDefinition('HTML');
$this->teardownCacheMock();
}
protected function setupCacheMock($type) {
// inject our definition cache mock globally (borrowed from
// DefinitionFactoryTest)
generate_mock_once("HTMLPurifier_DefinitionCacheFactory");
$factory = new HTMLPurifier_DefinitionCacheFactoryMock();
$this->oldFactory = HTMLPurifier_DefinitionCacheFactory::instance();
HTMLPurifier_DefinitionCacheFactory::instance($factory);
generate_mock_once("HTMLPurifier_DefinitionCache");
$mock = new HTMLPurifier_DefinitionCacheMock();
$config = HTMLPurifier_Config::createDefault();
$factory->setReturnValue('create', $mock, array($type, $config));
return array($mock, $config);
}
protected function teardownCacheMock() {
HTMLPurifier_DefinitionCacheFactory::instance($this->oldFactory);
}
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@ -172,6 +172,7 @@ class HTMLPurifier_DefinitionCache_SerializerTest extends HTMLPurifier_Definitio
* Asserts that a file does not exist, ignoring the stat cache * Asserts that a file does not exist, ignoring the stat cache
*/ */
function assertFileNotExist($file) { function assertFileNotExist($file) {
clearstatcache();
$this->assertFalse(file_exists($file), 'Expected ' . $file . ' does not exist'); $this->assertFalse(file_exists($file), 'Expected ' . $file . ' does not exist');
} }

View File

@ -254,9 +254,7 @@ a[href|title]
function test_addAttribute() { function test_addAttribute() {
$config = HTMLPurifier_Config::create(array( $config = HTMLPurifier_Config::createDefault();
'HTML.DefinitionID' => 'HTMLPurifier_HTMLDefinitionTest->test_addAttribute'
));
$def = $config->getHTMLDefinition(true); $def = $config->getHTMLDefinition(true);
$def->addAttribute('span', 'custom', 'Enum#attribute'); $def->addAttribute('span', 'custom', 'Enum#attribute');
@ -269,9 +267,7 @@ a[href|title]
function test_addAttribute_multiple() { function test_addAttribute_multiple() {
$config = HTMLPurifier_Config::create(array( $config = HTMLPurifier_Config::createDefault();
'HTML.DefinitionID' => 'HTMLPurifier_HTMLDefinitionTest->test_addAttribute_multiple'
));
$def = $config->getHTMLDefinition(true); $def = $config->getHTMLDefinition(true);
$def->addAttribute('span', 'custom', 'Enum#attribute'); $def->addAttribute('span', 'custom', 'Enum#attribute');
$def->addAttribute('span', 'foo', 'Text'); $def->addAttribute('span', 'foo', 'Text');
@ -285,9 +281,7 @@ a[href|title]
function test_addElement() { function test_addElement() {
$config = HTMLPurifier_Config::create(array( $config = HTMLPurifier_Config::createDefault();
'HTML.DefinitionID' => 'HTMLPurifier_HTMLDefinitionTest->test_addElement'
));
$def = $config->getHTMLDefinition(true); $def = $config->getHTMLDefinition(true);
$def->addElement('marquee', 'Inline', 'Inline', 'Common', array('width' => 'Length')); $def->addElement('marquee', 'Inline', 'Inline', 'Common', array('width' => 'Length'));
@ -299,8 +293,6 @@ a[href|title]
} }
function test_injector() { function test_injector() {
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injector');
generate_mock_once('HTMLPurifier_Injector'); generate_mock_once('HTMLPurifier_Injector');
$injector = new HTMLPurifier_InjectorMock(); $injector = new HTMLPurifier_InjectorMock();
$injector->name = 'MyInjector'; $injector->name = 'MyInjector';
@ -317,8 +309,6 @@ a[href|title]
} }
function test_injectorMissingNeeded() { function test_injectorMissingNeeded() {
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injectorMissingNeeded');
generate_mock_once('HTMLPurifier_Injector'); generate_mock_once('HTMLPurifier_Injector');
$injector = new HTMLPurifier_InjectorMock(); $injector = new HTMLPurifier_InjectorMock();
$injector->name = 'MyInjector'; $injector->name = 'MyInjector';
@ -333,8 +323,6 @@ a[href|title]
} }
function test_injectorIntegration() { function test_injectorIntegration() {
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injectorIntegration');
$module = $this->config->getHTMLDefinition(true)->getAnonymousModule(); $module = $this->config->getHTMLDefinition(true)->getAnonymousModule();
$module->info_injector[] = 'Linkify'; $module->info_injector[] = 'Linkify';
@ -345,8 +333,6 @@ a[href|title]
} }
function test_injectorIntegrationFail() { function test_injectorIntegrationFail() {
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLDefinitionTest->test_injectorIntegrationFail');
$this->config->set('HTML.Allowed', 'p'); $this->config->set('HTML.Allowed', 'p');
$module = $this->config->getHTMLDefinition(true)->getAnonymousModule(); $module = $this->config->getHTMLDefinition(true)->getAnonymousModule();

View File

@ -5,7 +5,6 @@ class HTMLPurifier_HTMLModule_SafeEmbedTest extends HTMLPurifier_HTMLModuleHarne
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
$this->config->set('HTML.DefinitionID', 'HTMLPurifier_HTMLModule_SafeEmbedTest');
$def = $this->config->getHTMLDefinition(true); $def = $this->config->getHTMLDefinition(true);
$def->manager->addModule('SafeEmbed'); $def->manager->addModule('SafeEmbed');
} }

View File

@ -80,9 +80,6 @@ alert(&lt;b&gt;bold&lt;/b&gt;);
} }
function testRequiredAttributesTestNotPerformedOnEndTag() { function testRequiredAttributesTestNotPerformedOnEndTag() {
$this->config->set('HTML.DefinitionID',
'HTMLPurifier_Strategy_RemoveForeignElementsTest'.
'->testRequiredAttributesTestNotPerformedOnEndTag');
$def = $this->config->getHTMLDefinition(true); $def = $this->config->getHTMLDefinition(true);
$def->addElement('f', 'Block', 'Optional: #PCDATA', false, array('req*' => 'Text')); $def->addElement('f', 'Block', 'Optional: #PCDATA', false, array('req*' => 'Text'));
$this->assertResult('<f req="text">Foo</f> Bar'); $this->assertResult('<f req="text">Foo</f> Bar');