0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-12-23 00:41:52 +00:00
- All important classes that use Context were migrated. Todo: Classes that currently use $config but not $context are AttrTransform (done in r493) and URIScheme+Registry (done in r500). There may be more classes, incl TagTransform (done in r497) that should have both $config and $context added.
- Strategy unit tests now migrated to use HTMLPurifier_Harness

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@485 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang 2006-10-01 21:55:13 +00:00
parent 8f515b9cda
commit 2d6bf12fe0
18 changed files with 282 additions and 307 deletions

1
NEWS
View File

@ -10,6 +10,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
1.2.0, unknown projected release date 1.2.0, unknown projected release date
. Switched to purify()-wide Context object registry . Switched to purify()-wide Context object registry
. Refactored unit tests to minimize duplication
1.1.3, unknown projected release date 1.1.3, unknown projected release date
(bugfix release, may be dropped if no major bugs are found before features) (bugfix release, may be dropped if no major bugs are found before features)

View File

@ -1,26 +0,0 @@
<?php
/**
* Internal data-structure used in attribute validation to accumulate state.
*
* This is a data-structure that holds objects that accumulate state, like
* HTMLPurifier_IDAccumulator. It's better than using globals!
*
* @note Many functions that accept this object have it as a mandatory
* parameter, even when there is no use for it. Though this is
* for the same reasons as why HTMLPurifier_Config is a mandatory
* parameter, it is also because you cannot assign a default value
* to a parameter passed by reference (passing by reference is essential
* for context to work in PHP 4).
*/
class HTMLPurifier_AttrContext
{
/**
* Contains an HTMLPurifier_IDAccumulator, which keeps track of used IDs.
* @public
*/
var $id_accumulator;
}
?>

View File

@ -1,7 +1,5 @@
<?php <?php
require_once 'HTMLPurifier/AttrContext.php';
/** /**
* Base class for all validating attribute definitions. * Base class for all validating attribute definitions.
* *

View File

@ -20,7 +20,9 @@ class HTMLPurifier_AttrDef_ID extends HTMLPurifier_AttrDef
$id = trim($id); // trim it first $id = trim($id); // trim it first
if ($id === '') return false; if ($id === '') return false;
if (isset($context->id_accumulator->ids[$id])) return false;
$id_accumulator = $context->get('IDAccumulator');
if (isset($id_accumulator->ids[$id])) return false;
// we purposely avoid using regex, hopefully this is faster // we purposely avoid using regex, hopefully this is faster
@ -35,7 +37,7 @@ class HTMLPurifier_AttrDef_ID extends HTMLPurifier_AttrDef
$result = ($trim === ''); $result = ($trim === '');
} }
if ($result) $context->id_accumulator->add($id); if ($result) $id_accumulator->add($id);
// if no change was made to the ID, return the result // if no change was made to the ID, return the result
// else, return the new id if stripping whitespace made it // else, return the new id if stripping whitespace made it

View File

@ -60,9 +60,8 @@ class HTMLPurifier_Generator
* @param $tokens Array of HTMLPurifier_Token * @param $tokens Array of HTMLPurifier_Token
* @param $config HTMLPurifier_Config object * @param $config HTMLPurifier_Config object
* @return Generated HTML * @return Generated HTML
* @note Only unit tests may omit configuration: internals MUST pass config
*/ */
function generateFromTokens($tokens, $config = null) { function generateFromTokens($tokens, $config, &$context) {
$html = ''; $html = '';
if (!$config) $config = HTMLPurifier_Config::createDefault(); if (!$config) $config = HTMLPurifier_Config::createDefault();
$this->_clean_utf8 = $config->get('Core', 'CleanUTF8DuringGeneration'); $this->_clean_utf8 = $config->get('Core', 'CleanUTF8DuringGeneration');

View File

@ -3,8 +3,6 @@
require_once 'HTMLPurifier/Strategy.php'; require_once 'HTMLPurifier/Strategy.php';
require_once 'HTMLPurifier/HTMLDefinition.php'; require_once 'HTMLPurifier/HTMLDefinition.php';
require_once 'HTMLPurifier/IDAccumulator.php'; require_once 'HTMLPurifier/IDAccumulator.php';
require_once 'HTMLPurifier/ConfigSchema.php';
require_once 'HTMLPurifier/AttrContext.php';
HTMLPurifier_ConfigSchema::define( HTMLPurifier_ConfigSchema::define(
'Attr', 'IDBlacklist', array(), 'list', 'Attr', 'IDBlacklist', array(), 'list',
@ -21,14 +19,10 @@ class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy
$definition = $config->getHTMLDefinition(); $definition = $config->getHTMLDefinition();
// setup StrategyContext // setup id_accumulator context
$attr_context = new HTMLPurifier_AttrContext(); $id_accumulator = new HTMLPurifier_IDAccumulator();
$id_accumulator->load($config->get('Attr', 'IDBlacklist'));
// setup ID accumulator and load it with blacklisted IDs $context->register('IDAccumulator', $id_accumulator);
// eventually, we'll have a dedicated context object to hold
// all these accumulators and caches. For now, just an IDAccumulator
$attr_context->id_accumulator = new HTMLPurifier_IDAccumulator();
$attr_context->id_accumulator->load($config->get('Attr', 'IDBlacklist'));
// create alias to global definition array, see also $defs // create alias to global definition array, see also $defs
// DEFINITION CALL // DEFINITION CALL
@ -81,14 +75,14 @@ class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy
} else { } else {
// validate according to the element's definition // validate according to the element's definition
$result = $defs[$attr_key]->validate( $result = $defs[$attr_key]->validate(
$value, $config, $attr_context $value, $config, $context
); );
} }
} elseif ( isset($d_defs[$attr_key]) ) { } elseif ( isset($d_defs[$attr_key]) ) {
// there is a global definition defined, validate according // there is a global definition defined, validate according
// to the global definition // to the global definition
$result = $d_defs[$attr_key]->validate( $result = $d_defs[$attr_key]->validate(
$value, $config, $attr_context $value, $config, $context
); );
} else { } else {
// system never heard of the attribute? DELETE! // system never heard of the attribute? DELETE!
@ -123,6 +117,8 @@ class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy
// could interfere with flyweight implementation // could interfere with flyweight implementation
$tokens[$key]->attributes = $attr; $tokens[$key]->attributes = $attr;
} }
$context->destroy('IDAccumulator');
return $tokens; return $tokens;
} }

View File

@ -23,7 +23,7 @@ class HTMLPurifier_AttrDef_CompositeTest extends HTMLPurifier_AttrDefHarness
generate_mock_once('HTMLPurifier_AttrDef'); generate_mock_once('HTMLPurifier_AttrDef');
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$context = new HTMLPurifier_AttrContext(); $context = new HTMLPurifier_Context();
// first test: value properly validates on first definition // first test: value properly validates on first definition
// so second def is never called // so second def is never called

View File

@ -9,8 +9,9 @@ class HTMLPurifier_AttrDef_IDTest extends HTMLPurifier_AttrDefHarness
function test() { function test() {
$this->context = new HTMLPurifier_AttrContext(); $this->context = new HTMLPurifier_Context();
$this->context->id_accumulator = new HTMLPurifier_IDAccumulator(); $id_accumulator = new HTMLPurifier_IDAccumulator();
$this->context->register('IDAccumulator', $id_accumulator);
$this->def = new HTMLPurifier_AttrDef_ID(); $this->def = new HTMLPurifier_AttrDef_ID();
// valid ID names // valid ID names

View File

@ -11,7 +11,7 @@ class HTMLPurifier_AttrDefHarness extends UnitTestCase
function assertDef($string, $expect = true, $ini = false, $message = '%s') { function assertDef($string, $expect = true, $ini = false, $message = '%s') {
// $expect can be a string or bool // $expect can be a string or bool
if (!$this->config) $this->config = HTMLPurifier_Config::createDefault(); if (!$this->config) $this->config = HTMLPurifier_Config::createDefault();
if (!$this->context) $this->context = new HTMLPurifier_AttrContext(); if (!$this->context) $this->context = new HTMLPurifier_Context();
if ($ini) $this->setUpAssertDef(); if ($ini) $this->setUpAssertDef();
$result = $this->def->validate($string, $this->config, $this->context); $result = $this->def->validate($string, $this->config, $this->context);
if ($expect === true) { if ($expect === true) {

View File

@ -3,7 +3,9 @@
require_once 'HTMLPurifier/Generator.php'; require_once 'HTMLPurifier/Generator.php';
require_once 'HTMLPurifier/EntityLookup.php'; require_once 'HTMLPurifier/EntityLookup.php';
class HTMLPurifier_GeneratorTest extends UnitTestCase require_once 'HTMLPurifier/Harness.php';
class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness
{ {
var $gen; var $gen;
@ -15,11 +17,16 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
$this->_entity_lookup = HTMLPurifier_EntityLookup::instance(); $this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
} }
function setUp() {
$this->obj = new HTMLPurifier_Generator();
$this->func = null;
$this->to_tokens = false;
$this->to_html = false;
}
function test_generateFromToken() { function test_generateFromToken() {
$inputs = array(); $inputs = $expect = array();
$expect = array();
$config = array();
$inputs[0] = new HTMLPurifier_Token_Text('Foobar.<>'); $inputs[0] = new HTMLPurifier_Token_Text('Foobar.<>');
$expect[0] = 'Foobar.&lt;&gt;'; $expect[0] = 'Foobar.&lt;&gt;';
@ -53,7 +60,7 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
$expect[7] = $theta_char; $expect[7] = $theta_char;
foreach ($inputs as $i => $input) { foreach ($inputs as $i => $input) {
$result = $this->gen->generateFromToken($input); $result = $this->obj->generateFromToken($input);
$this->assertEqual($result, $expect[$i]); $this->assertEqual($result, $expect[$i]);
paintIf($result, $result != $expect[$i]); paintIf($result, $result != $expect[$i]);
} }
@ -62,9 +69,7 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
function test_generateAttributes() { function test_generateAttributes() {
$inputs = array(); $inputs = $expect = array();
$expect = array();
$config = array();
$inputs[0] = array(); $inputs[0] = array();
$expect[0] = ''; $expect[0] = '';
@ -83,10 +88,8 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
$inputs[4] = array('title' => 'Theta is ' . $theta_char); $inputs[4] = array('title' => 'Theta is ' . $theta_char);
$expect[4] = 'title="Theta is ' . $theta_char . '"'; $expect[4] = 'title="Theta is ' . $theta_char . '"';
$default_config = HTMLPurifier_Config::createDefault();
foreach ($inputs as $i => $input) { foreach ($inputs as $i => $input) {
if (!isset($config[$i])) $config[$i] = $default_config; $result = $this->obj->generateAttributes($input);
$result = $this->gen->generateAttributes($input, $config[$i]);
$this->assertEqual($result, $expect[$i]); $this->assertEqual($result, $expect[$i]);
paintIf($result, $result != $expect[$i]); paintIf($result, $result != $expect[$i]);
} }
@ -95,34 +98,26 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
function test_generateFromTokens() { function test_generateFromTokens() {
$inputs = array(); $this->func = 'generateFromTokens';
$expect = array();
$config = array();
$inputs[0] = array( $this->assertResult(
array(
new HTMLPurifier_Token_Start('b'), new HTMLPurifier_Token_Start('b'),
new HTMLPurifier_Token_Text('Foobar!'), new HTMLPurifier_Token_Text('Foobar!'),
new HTMLPurifier_Token_End('b') new HTMLPurifier_Token_End('b')
),
'<b>Foobar!</b>'
); );
$expect[0] = '<b>Foobar!</b>';
$inputs[1] = array();
$expect[1] = '';
$default_config = HTMLPurifier_Config::createDefault();
foreach ($inputs as $i => $input) {
if (!isset($config[$i])) $config[$i] = $default_config;
$result = $this->gen->generateFromTokens($input, $config[$i]);
$this->assertEqual($expect[$i], $result);
paintIf($result, $result != $expect[$i]);
}
$this->assertResult(array(), '');
} }
var $config; var $config;
function assertGeneration($tokens, $expect) { function assertGeneration($tokens, $expect) {
$result = $this->gen->generateFromTokens($tokens, $this->config); $context = new HTMLPurifier_Context();
$result = $this->gen->generateFromTokens(
$tokens, $this->config, $context);
// normalized newlines, this probably should be put somewhere else // normalized newlines, this probably should be put somewhere else
$result = str_replace("\r\n", "\n", $result); $result = str_replace("\r\n", "\n", $result);
$result = str_replace("\r", "\n", $result); $result = str_replace("\r", "\n", $result);

View File

@ -1,5 +1,7 @@
<?php <?php
require_once 'HTMLPurifier/Lexer/DirectLex.php';
/** /**
* General-purpose test-harness that makes testing functions that require * General-purpose test-harness that makes testing functions that require
* configuration and context objects easier when those two parameters are * configuration and context objects easier when those two parameters are

View File

@ -1,8 +1,8 @@
<?php <?php
require_once('HTMLPurifier/Strategy.php'); require_once 'HTMLPurifier/Strategy.php';
require_once('HTMLPurifier/Strategy/Composite.php'); require_once 'HTMLPurifier/Strategy/Composite.php';
require_once('HTMLPurifier/Config.php'); require_once 'HTMLPurifier/Config.php';
class HTMLPurifier_Strategy_Composite_Test class HTMLPurifier_Strategy_Composite_Test
extends HTMLPurifier_Strategy_Composite extends HTMLPurifier_Strategy_Composite
@ -22,13 +22,13 @@ class HTMLPurifier_Strategy_CompositeTest extends UnitTestCase
generate_mock_once('HTMLPurifier_Strategy'); generate_mock_once('HTMLPurifier_Strategy');
generate_mock_once('HTMLPurifier_Config'); generate_mock_once('HTMLPurifier_Config');
generate_mock_once('HTMLPurifier_Context');
// setup a bunch of mock strategies to inject into our composite test // setup a bunch of mock strategies to inject into our composite test
$mock_1 = new HTMLPurifier_StrategyMock($this); $mock_1 = new HTMLPurifier_StrategyMock($this);
$mock_2 = new HTMLPurifier_StrategyMock($this); $mock_2 = new HTMLPurifier_StrategyMock($this);
$mock_3 = new HTMLPurifier_StrategyMock($this); $mock_3 = new HTMLPurifier_StrategyMock($this);
$context = new HTMLPurifier_Context();
// setup the object // setup the object
@ -43,6 +43,7 @@ class HTMLPurifier_Strategy_CompositeTest extends UnitTestCase
$input_4 = 'Processed by 1, 2 and 3'; // expected output $input_4 = 'Processed by 1, 2 and 3'; // expected output
$config = new HTMLPurifier_ConfigMock(); $config = new HTMLPurifier_ConfigMock();
$context = new HTMLPurifier_ContextMock();
$params_1 = array($input_1, $config, $context); $params_1 = array($input_1, $config, $context);
$params_2 = array($input_2, $config, $context); $params_2 = array($input_2, $config, $context);

View File

@ -3,36 +3,34 @@
require_once 'HTMLPurifier/StrategyHarness.php'; require_once 'HTMLPurifier/StrategyHarness.php';
require_once 'HTMLPurifier/Strategy/Core.php'; require_once 'HTMLPurifier/Strategy/Core.php';
class HTMLPurifier_Strategy_CoreTest class HTMLPurifier_Strategy_CoreTest extends HTMLPurifier_StrategyHarness
extends HTMLPurifier_StrategyHarness
{ {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_Core();
}
function test() { function test() {
$strategy = new HTMLPurifier_Strategy_Core();
$inputs = array(); $this->assertResult('');
$expect = array(); $this->assertResult(
$config = array(); '<b>Make well formed.',
'<b>Make well formed.</b>'
);
$this->assertResult(
'<b><div>Fix nesting.</div></b>',
'<b>Fix nesting.</b>'
);
$this->assertResult(
'<asdf>Foreign element removal.</asdf>',
'Foreign element removal.'
);
$this->assertResult(
'<foo><b><div>All three.</div></b>',
'<b>All three.</b>'
);
$config_escape = HTMLPurifier_Config::createDefault();
$config_escape->set('Core', 'EscapeInvalidChildren', true);
$inputs[0] = '';
$expect[0] = '';
$inputs[1] = '<b>Make well formed.';
$expect[1] = '<b>Make well formed.</b>';
$inputs[2] = '<b><div>Fix nesting.</div></b>';
$expect[2] = '<b>Fix nesting.</b>';
$inputs[3] = '<asdf>Foreign element removal.</asdf>';
$expect[3] = 'Foreign element removal.';
$inputs[4] = '<foo><b><div>All three.</div></b>';
$expect[4] = '<b>All three.</b>';
$this->assertStrategyWorks($strategy, $inputs, $expect, $config);
} }
} }

View File

@ -3,89 +3,86 @@
require_once 'HTMLPurifier/StrategyHarness.php'; require_once 'HTMLPurifier/StrategyHarness.php';
require_once 'HTMLPurifier/Strategy/FixNesting.php'; require_once 'HTMLPurifier/Strategy/FixNesting.php';
class HTMLPurifier_Strategy_FixNestingTest class HTMLPurifier_Strategy_FixNestingTest extends HTMLPurifier_StrategyHarness
extends HTMLPurifier_StrategyHarness
{ {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_FixNesting();
}
function test() { function test() {
$strategy = new HTMLPurifier_Strategy_FixNesting(); // legal inline
$this->assertResult('<b>Bold text</b>');
$inputs = array();
$expect = array();
$config = array();
$config_escape = HTMLPurifier_Config::createDefault();
$config_escape->set('Core', 'EscapeInvalidChildren', true);
// next id = 4
// legal inline nesting
$inputs[0] = '<b>Bold text</b>';
$expect[0] = $inputs[0];
// legal inline and block // legal inline and block
// as the parent element is considered FLOW // as the parent element is considered FLOW
$inputs[1] = '<a href="about:blank">Blank</a><div>Block</div>'; $this->assertResult('<a href="about:blank">Blank</a><div>Block</div>');
$expect[1] = $inputs[1];
// illegal block in inline // illegal block in inline
$inputs[2] = '<b><div>Illegal div.</div></b>'; $this->assertResult(
$expect[2] = '<b>Illegal div.</b>'; '<b><div>Illegal div.</div></b>',
'<b>Illegal div.</b>'
);
// same test with different configuration (fragile) // same test with different configuration (fragile)
$inputs[13] = '<b><div>Illegal div.</div></b>'; $this->assertResult(
$expect[13] = '<b>&lt;div&gt;Illegal div.&lt;/div&gt;</b>'; '<b><div>Illegal div.</div></b>',
$config[13] = $config_escape; '<b>&lt;div&gt;Illegal div.&lt;/div&gt;</b>',
array('Core.EscapeInvalidChildren' => true)
);
// test of empty set that's required, resulting in removal of node // test of empty set that's required, resulting in removal of node
$inputs[3] = '<ul></ul>'; $this->assertResult('<ul></ul>', '');
$expect[3] = '';
// test illegal text which gets removed // test illegal text which gets removed
$inputs[4] = '<ul>Illegal text<li>Legal item</li></ul>'; $this->assertResult(
$expect[4] = '<ul><li>Legal item</li></ul>'; '<ul>Illegal text<li>Legal item</li></ul>',
'<ul><li>Legal item</li></ul>'
);
// test custom table definition // test custom table definition
$this->assertResult(
$inputs[5] = '<table><tr><td>Cell 1</td></tr></table>'; '<table><tr><td>Cell 1</td></tr></table>',
$expect[5] = '<table><tr><td>Cell 1</td></tr></table>'; '<table><tr><td>Cell 1</td></tr></table>'
);
$inputs[6] = '<table></table>'; $this->assertResult('<table></table>', '');
$expect[6] = '';
// breaks without the redundant checking code // breaks without the redundant checking code
$inputs[7] = '<table><tr></tr></table>'; $this->assertResult('<table><tr></tr></table>', '');
$expect[7] = '';
// special case, prevents scrolling one back to find parent // special case, prevents scrolling one back to find parent
$inputs[8] = '<table><tr></tr><tr></tr></table>'; $this->assertResult('<table><tr></tr><tr></tr></table>', '');
$expect[8] = '';
// cascading rollbacks // cascading rollbacks
$inputs[9] = '<table><tbody><tr></tr><tr></tr></tbody><tr></tr><tr></tr></table>'; $this->assertResult(
$expect[9] = ''; '<table><tbody><tr></tr><tr></tr></tbody><tr></tr><tr></tr></table>',
''
);
// rollbacks twice // rollbacks twice
$inputs[10] = '<table></table><table></table>'; $this->assertResult('<table></table><table></table>', '');
$expect[10] = '';
// block in inline ins not allowed // block in inline ins not allowed
$inputs[11] = '<span><ins><div>Not allowed!</div></ins></span>'; $this->assertResult(
$expect[11] = '<span><ins>Not allowed!</ins></span>'; '<span><ins><div>Not allowed!</div></ins></span>',
'<span><ins>Not allowed!</ins></span>'
);
// block in inline ins not allowed // block in inline ins not allowed
$inputs[14] = '<span><ins><div>Not allowed!</div></ins></span>'; $this->assertResult(
$expect[14] = '<span><ins>&lt;div&gt;Not allowed!&lt;/div&gt;</ins></span>'; '<span><ins><div>Not allowed!</div></ins></span>',
$config[14] = $config_escape; '<span><ins>&lt;div&gt;Not allowed!&lt;/div&gt;</ins></span>',
array('Core.EscapeInvalidChildren' => true)
);
// test exclusions // test exclusions
$inputs[12] = '<a><span><a>Not allowed</a></span></a>'; $this->assertResult(
$expect[12] = '<a><span></span></a>'; '<a><span><a>Not allowed</a></span></a>',
'<a><span></span></a>'
);
// next test is *15*
$this->assertStrategyWorks($strategy, $inputs, $expect, $config);
} }
} }

View File

@ -3,53 +3,62 @@
require_once 'HTMLPurifier/StrategyHarness.php'; require_once 'HTMLPurifier/StrategyHarness.php';
require_once 'HTMLPurifier/Strategy/MakeWellFormed.php'; require_once 'HTMLPurifier/Strategy/MakeWellFormed.php';
class HTMLPurifier_Strategy_MakeWellFormedTest class HTMLPurifier_Strategy_MakeWellFormedTest extends HTMLPurifier_StrategyHarness
extends HTMLPurifier_StrategyHarness
{ {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_MakeWellFormed();
}
function test() { function test() {
$strategy = new HTMLPurifier_Strategy_MakeWellFormed(); $this->assertResult('');
$this->assertResult('This is <b>bold text</b>.');
$inputs = array(); $this->assertResult(
$expect = array(); '<b>Unclosed tag, gasp!',
'<b>Unclosed tag, gasp!</b>'
);
$inputs[0] = ''; $this->assertResult(
$expect[0] = $inputs[0]; '<b><i>Bold and italic?</b>',
'<b><i>Bold and italic?</i></b>'
);
$inputs[1] = 'This is <b>bold text</b>.'; $this->assertResult(
$expect[1] = $inputs[1]; 'Unused end tags... recycle!</b>',
'Unused end tags... recycle!'
);
$inputs[2] = '<b>Unclosed tag, gasp!'; $this->assertResult(
$expect[2] = '<b>Unclosed tag, gasp!</b>'; '<br style="clear:both;">',
'<br style="clear:both;" />'
);
$inputs[3] = '<b><i>Bold and italic?</b>'; $this->assertResult(
$expect[3] = '<b><i>Bold and italic?</i></b>'; '<div style="clear:both;" />',
'<div style="clear:both;"></div>'
// CHANGE THIS BEHAVIOR! );
$inputs[4] = 'Unused end tags... recycle!</b>';
$expect[4] = 'Unused end tags... recycle!';
$inputs[5] = '<br style="clear:both;">';
$expect[5] = '<br style="clear:both;" />';
$inputs[6] = '<div style="clear:both;" />';
$expect[6] = '<div style="clear:both;"></div>';
// test automatic paragraph closing // test automatic paragraph closing
$inputs[7] = '<p>Paragraph 1<p>Paragraph 2'; $this->assertResult(
$expect[7] = '<p>Paragraph 1</p><p>Paragraph 2</p>'; '<p>Paragraph 1<p>Paragraph 2',
'<p>Paragraph 1</p><p>Paragraph 2</p>'
);
$inputs[8] = '<div><p>Paragraphs<p>In<p>A<p>Div</div>'; $this->assertResult(
$expect[8] = '<div><p>Paragraphs</p><p>In</p><p>A</p><p>Div</p></div>'; '<div><p>Paragraphs<p>In<p>A<p>Div</div>',
'<div><p>Paragraphs</p><p>In</p><p>A</p><p>Div</p></div>'
);
// automatic list closing // automatic list closing
$inputs[9] = '<ol><li>Item 1<li>Item 2</ol>'; $this->assertResult(
$expect[9] = '<ol><li>Item 1</li><li>Item 2</li></ol>'; '<ol><li>Item 1<li>Item 2</ol>',
'<ol><li>Item 1</li><li>Item 2</li></ol>'
$this->assertStrategyWorks($strategy, $inputs, $expect); );
} }
} }

View File

@ -7,36 +7,41 @@ class HTMLPurifier_Strategy_RemoveForeignElementsTest
extends HTMLPurifier_StrategyHarness extends HTMLPurifier_StrategyHarness
{ {
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_RemoveForeignElements();
}
function test() { function test() {
$strategy = new HTMLPurifier_Strategy_RemoveForeignElements();
$inputs = array(); $this->assertResult('');
$expect = array();
$inputs[0] = ''; $this->assertResult('This is <b>bold text</b>.');
$expect[0] = $inputs[0];
$inputs[1] = 'This is <b>bold text</b>.'; $this->assertResult(
$expect[1] = $inputs[1]; '<asdf>Bling</asdf><d href="bang">Bong</d><foobar />',
'BlingBong'
);
// [INVALID] $this->assertResult(
$inputs[2] = '<asdf>Bling</asdf><d href="bang">Bong</d><foobar />'; '<menu><li>Item 1</li></menu>',
$expect[2] = 'BlingBong'; '<ul><li>Item 1</li></ul>'
);
// test simple transform
$inputs[3] = '<menu><li>Item 1</li></menu>';
$expect[3] = '<ul><li>Item 1</li></ul>';
// test center transform // test center transform
$inputs[4] = '<center>Look I am Centered!</center>'; $this->assertResult(
$expect[4] = '<div style="text-align:center;">Look I am Centered!</div>'; '<center>Look I am Centered!</center>',
'<div style="text-align:center;">Look I am Centered!</div>'
);
// test font transform // test font transform
$inputs[5] = '<font color="red" face="Arial" size="6">Big Warning!</font>'; $this->assertResult(
$expect[5] = '<span style="color:red;font-family:Arial;font-size:xx-large;">Big Warning!</span>'; '<font color="red" face="Arial" size="6">Big Warning!</font>',
'<span style="color:red;font-family:Arial;font-size:xx-large;">Big'.
' Warning!</span>'
);
$this->assertStrategyWorks($strategy, $inputs, $expect);
} }
} }

View File

@ -8,71 +8,83 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
HTMLPurifier_StrategyHarness HTMLPurifier_StrategyHarness
{ {
function test() { function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_ValidateAttributes();
}
$strategy = new HTMLPurifier_Strategy_ValidateAttributes(); function test() {
// attribute order is VERY fragile, perhaps we should define // attribute order is VERY fragile, perhaps we should define
// an ordering scheme! // an ordering scheme!
$inputs = array(); $this->assertResult('');
$expect = array();
$config = array();
$inputs[0] = '';
$expect[0] = '';
// test ids // test ids
$this->assertResult('<div id="valid">Preserve the ID.</div>');
$inputs[1] = '<div id="valid">Preserve the ID.</div>'; $this->assertResult(
$expect[1] = $inputs[1]; '<div id="0invalid">Kill the ID.</div>',
'<div>Kill the ID.</div>'
$inputs[2] = '<div id="0invalid">Kill the ID.</div>'; );
$expect[2] = '<div>Kill the ID.</div>';
// test id accumulator // test id accumulator
$inputs[3] = '<div id="valid">Valid</div><div id="valid">Invalid</div>'; $this->assertResult(
$expect[3] = '<div id="valid">Valid</div><div>Invalid</div>'; '<div id="valid">Valid</div><div id="valid">Invalid</div>',
'<div id="valid">Valid</div><div>Invalid</div>'
);
$inputs[4] = '<span dir="up-to-down">Bad dir.</span>'; $this->assertResult(
$expect[4] = '<span>Bad dir.</span>'; '<span dir="up-to-down">Bad dir.</span>',
'<span>Bad dir.</span>'
);
// test attribute case sensitivity // test attribute key case sensitivity
$inputs[5] = '<div ID="valid">Convert ID to lowercase.</div>'; $this->assertResult(
$expect[5] = '<div id="valid">Convert ID to lowercase.</div>'; '<div ID="valid">Convert ID to lowercase.</div>',
'<div id="valid">Convert ID to lowercase.</div>'
);
// test simple attribute substitution // test simple attribute substitution
$inputs[6] = '<div id=" valid ">Trim whitespace.</div>'; $this->assertResult(
$expect[6] = '<div id="valid">Trim whitespace.</div>'; '<div id=" valid ">Trim whitespace.</div>',
'<div id="valid">Trim whitespace.</div>'
);
// test configuration id blacklist // test configuration id blacklist
$inputs[7] = '<div id="invalid">Invalid</div>'; $this->assertResult(
$expect[7] = '<div>Invalid</div>'; '<div id="invalid">Invalid</div>',
$config[7] = HTMLPurifier_Config::createDefault(); '<div>Invalid</div>',
$config[7]->set('Attr', 'IDBlacklist', array('invalid')); array('Attr.IDBlacklist' => array('invalid'))
);
// test classes // test classes
$inputs[8] = '<div class="valid">Valid</div>'; $this->assertResult('<div class="valid">Valid</div>');
$expect[8] = $inputs[8];
$inputs[9] = '<div class="valid 0invalid">Keep valid.</div>'; $this->assertResult(
$expect[9] = '<div class="valid">Keep valid.</div>'; '<div class="valid 0invalid">Keep valid.</div>',
'<div class="valid">Keep valid.</div>'
);
// test title // test title
$inputs[10] = '<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>'; $this->assertResult(
$expect[10] = $inputs[10]; '<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>'
);
// test lang // test lang
$inputs[11] = '<span lang="fr">La soupe.</span>'; $this->assertResult(
$expect[11] = '<span lang="fr" xml:lang="fr">La soupe.</span>'; '<span lang="fr">La soupe.</span>',
'<span lang="fr" xml:lang="fr">La soupe.</span>'
);
// test align (won't work till CSS validation is implemented) // test align
$inputs[12] = '<h1 align="center">Centered Headline</h1>'; $this->assertResult(
$expect[12] = '<h1 style="text-align:center;">Centered Headline</h1>'; '<h1 align="center">Centered Headline</h1>',
'<h1 style="text-align:center;">Centered Headline</h1>'
);
// test table // test table
$inputs[13] = $this->assertResult(
'<table frame="above" rules="rows" summary="A test table" border="2" cellpadding="5%" cellspacing="3" width="100%"> '<table frame="above" rules="rows" summary="A test table" border="2" cellpadding="5%" cellspacing="3" width="100%">
<col align="right" width="4*" /> <col align="right" width="4*" />
<col charoff="5" align="char" width="1*" /> <col charoff="5" align="char" width="1*" />
@ -87,44 +99,56 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
<tr> <tr>
<td colspan="2">Taken off the market</td> <td colspan="2">Taken off the market</td>
</tr> </tr>
</table>'; </table>'
);
$expect[13] = $inputs[13];
// test URI // test URI
$inputs[14] = '<a href="http://www.google.com/">Google</a>'; $this->assertResult('<a href="http://www.google.com/">Google</a>');
$expect[14] = $inputs[14];
// test invalid URI // test invalid URI
$inputs[15] = '<a href="javascript:badstuff();">Google</a>'; $this->assertResult(
$expect[15] = '<a>Google</a>'; '<a href="javascript:badstuff();">Google</a>',
'<a>Google</a>'
);
// test required attributes for img // test required attributes for img
$inputs[16] = '<img />'; $this->assertResult(
$expect[16] = '<img src="" alt="Invalid image" />'; '<img />',
'<img src="" alt="Invalid image" />'
);
$inputs[17] = '<img src="foobar.jpg" />'; $this->assertResult(
$expect[17] = '<img src="foobar.jpg" alt="foobar.jpg" />'; '<img src="foobar.jpg" />',
'<img src="foobar.jpg" alt="foobar.jpg" />'
);
$inputs[18] = '<img alt="pretty picture" />'; $this->assertResult(
$expect[18] = '<img alt="pretty picture" src="" />'; '<img alt="pretty picture" />',
'<img alt="pretty picture" src="" />'
);
// test required attributes for bdo // test required attributes for bdo
$inputs[19] = '<bdo>Go left.</bdo>'; $this->assertResult(
$expect[19] = '<bdo dir="ltr">Go left.</bdo>'; '<bdo>Go left.</bdo>',
'<bdo dir="ltr">Go left.</bdo>'
);
$inputs[20] = '<bdo dir="blahblah">Invalid value!</bdo>'; $this->assertResult(
$expect[20] = '<bdo dir="ltr">Invalid value!</bdo>'; '<bdo dir="blahblah">Invalid value!</bdo>',
'<bdo dir="ltr">Invalid value!</bdo>'
);
// comparison check for test 20 // comparison check for test 20
$inputs[21] = '<span dir="blahblah">Invalid value!</span>'; $this->assertResult(
$expect[21] = '<span>Invalid value!</span>'; '<span dir="blahblah">Invalid value!</span>',
'<span>Invalid value!</span>'
);
// test col.span is non-zero // test col.span is non-zero
$inputs[22] = '<col span="0" />'; $this->assertResult(
$expect[22] = '<col />'; '<col span="0" />',
'<col />'
$this->assertStrategyWorks($strategy, $inputs, $expect, $config); );
} }

View File

@ -1,41 +1,14 @@
<?php <?php
require_once 'HTMLPurifier/Lexer/DirectLex.php'; require_once 'HTMLPurifier/Harness.php';
class HTMLPurifier_StrategyHarness extends UnitTestCase class HTMLPurifier_StrategyHarness extends HTMLPurifier_Harness
{ {
var $lex, $gen; function setUp() {
$this->func = 'execute';
function HTMLPurifier_StrategyHarness() { $this->to_tokens = true;
$this->UnitTestCase(); $this->to_html = true;
// we can't use the DOM lexer since it does too much stuff
// automatically, however, we should be able to use it
// interchangeably if we wanted to...
if (true) {
$this->lex = new HTMLPurifier_Lexer_DirectLex();
} else {
require_once 'HTMLPurifier/Lexer/DOMLex.php';
$this->lex = new HTMLPurifier_Lexer_DOMLex();
}
$this->gen = new HTMLPurifier_Generator();
}
function assertStrategyWorks($strategy, $inputs, $expect, $config = array()) {
$context = new HTMLPurifier_Context();
foreach ($inputs as $i => $input) {
if (!isset($config[$i])) {
$config[$i] = HTMLPurifier_Config::createDefault();
}
$tokens = $this->lex->tokenizeHTML($input, $config[$i], $context);
$result_tokens = $strategy->execute($tokens, $config[$i], $context);
$result = $this->gen->generateFromTokens($result_tokens, $config[$i]);
$this->assertEqual($expect[$i], $result, "Test $i: %s");
paintIf($result, $result != $expect[$i]);
}
} }
} }