0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-09-18 18:25:18 +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
. Switched to purify()-wide Context object registry
. Refactored unit tests to minimize duplication
1.1.3, unknown projected release date
(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
require_once 'HTMLPurifier/AttrContext.php';
/**
* 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
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
@ -35,7 +37,7 @@ class HTMLPurifier_AttrDef_ID extends HTMLPurifier_AttrDef
$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
// 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 $config HTMLPurifier_Config object
* @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 = '';
if (!$config) $config = HTMLPurifier_Config::createDefault();
$this->_clean_utf8 = $config->get('Core', 'CleanUTF8DuringGeneration');

View File

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

View File

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

View File

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

View File

@ -11,7 +11,7 @@ class HTMLPurifier_AttrDefHarness extends UnitTestCase
function assertDef($string, $expect = true, $ini = false, $message = '%s') {
// $expect can be a string or bool
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();
$result = $this->def->validate($string, $this->config, $this->context);
if ($expect === true) {

View File

@ -3,7 +3,9 @@
require_once 'HTMLPurifier/Generator.php';
require_once 'HTMLPurifier/EntityLookup.php';
class HTMLPurifier_GeneratorTest extends UnitTestCase
require_once 'HTMLPurifier/Harness.php';
class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness
{
var $gen;
@ -15,11 +17,16 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
$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() {
$inputs = array();
$expect = array();
$config = array();
$inputs = $expect = array();
$inputs[0] = new HTMLPurifier_Token_Text('Foobar.<>');
$expect[0] = 'Foobar.&lt;&gt;';
@ -53,7 +60,7 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
$expect[7] = $theta_char;
foreach ($inputs as $i => $input) {
$result = $this->gen->generateFromToken($input);
$result = $this->obj->generateFromToken($input);
$this->assertEqual($result, $expect[$i]);
paintIf($result, $result != $expect[$i]);
}
@ -62,9 +69,7 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
function test_generateAttributes() {
$inputs = array();
$expect = array();
$config = array();
$inputs = $expect = array();
$inputs[0] = array();
$expect[0] = '';
@ -83,10 +88,8 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
$inputs[4] = array('title' => 'Theta is ' . $theta_char);
$expect[4] = 'title="Theta is ' . $theta_char . '"';
$default_config = HTMLPurifier_Config::createDefault();
foreach ($inputs as $i => $input) {
if (!isset($config[$i])) $config[$i] = $default_config;
$result = $this->gen->generateAttributes($input, $config[$i]);
$result = $this->obj->generateAttributes($input);
$this->assertEqual($result, $expect[$i]);
paintIf($result, $result != $expect[$i]);
}
@ -95,34 +98,26 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
function test_generateFromTokens() {
$inputs = array();
$expect = array();
$config = array();
$this->func = 'generateFromTokens';
$inputs[0] = array(
new HTMLPurifier_Token_Start('b'),
new HTMLPurifier_Token_Text('Foobar!'),
new HTMLPurifier_Token_End('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(
new HTMLPurifier_Token_Start('b'),
new HTMLPurifier_Token_Text('Foobar!'),
new HTMLPurifier_Token_End('b')
),
'<b>Foobar!</b>'
);
$this->assertResult(array(), '');
}
var $config;
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
$result = str_replace("\r\n", "\n", $result);
$result = str_replace("\r", "\n", $result);

View File

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

View File

@ -1,8 +1,8 @@
<?php
require_once('HTMLPurifier/Strategy.php');
require_once('HTMLPurifier/Strategy/Composite.php');
require_once('HTMLPurifier/Config.php');
require_once 'HTMLPurifier/Strategy.php';
require_once 'HTMLPurifier/Strategy/Composite.php';
require_once 'HTMLPurifier/Config.php';
class HTMLPurifier_Strategy_Composite_Test
extends HTMLPurifier_Strategy_Composite
@ -22,13 +22,13 @@ class HTMLPurifier_Strategy_CompositeTest extends UnitTestCase
generate_mock_once('HTMLPurifier_Strategy');
generate_mock_once('HTMLPurifier_Config');
generate_mock_once('HTMLPurifier_Context');
// setup a bunch of mock strategies to inject into our composite test
$mock_1 = new HTMLPurifier_StrategyMock($this);
$mock_2 = new HTMLPurifier_StrategyMock($this);
$mock_3 = new HTMLPurifier_StrategyMock($this);
$context = new HTMLPurifier_Context();
// setup the object
@ -42,7 +42,8 @@ class HTMLPurifier_Strategy_CompositeTest extends UnitTestCase
$input_3 = 'Processed by 1 and 2';
$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_2 = array($input_2, $config, $context);

View File

@ -3,36 +3,34 @@
require_once 'HTMLPurifier/StrategyHarness.php';
require_once 'HTMLPurifier/Strategy/Core.php';
class HTMLPurifier_Strategy_CoreTest
extends HTMLPurifier_StrategyHarness
class HTMLPurifier_Strategy_CoreTest extends HTMLPurifier_StrategyHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_Core();
}
function test() {
$strategy = new HTMLPurifier_Strategy_Core();
$inputs = array();
$expect = array();
$config = array();
$this->assertResult('');
$this->assertResult(
'<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/Strategy/FixNesting.php';
class HTMLPurifier_Strategy_FixNestingTest
extends HTMLPurifier_StrategyHarness
class HTMLPurifier_Strategy_FixNestingTest extends HTMLPurifier_StrategyHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_FixNesting();
}
function test() {
$strategy = new HTMLPurifier_Strategy_FixNesting();
$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
$this->assertResult('<b>Bold text</b>');
// legal inline and block
// as the parent element is considered FLOW
$inputs[1] = '<a href="about:blank">Blank</a><div>Block</div>';
$expect[1] = $inputs[1];
$this->assertResult('<a href="about:blank">Blank</a><div>Block</div>');
// illegal block in inline
$inputs[2] = '<b><div>Illegal div.</div></b>';
$expect[2] = '<b>Illegal div.</b>';
$this->assertResult(
'<b><div>Illegal div.</div></b>',
'<b>Illegal div.</b>'
);
// same test with different configuration (fragile)
$inputs[13] = '<b><div>Illegal div.</div></b>';
$expect[13] = '<b>&lt;div&gt;Illegal div.&lt;/div&gt;</b>';
$config[13] = $config_escape;
$this->assertResult(
'<b><div>Illegal div.</div></b>',
'<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
$inputs[3] = '<ul></ul>';
$expect[3] = '';
$this->assertResult('<ul></ul>', '');
// test illegal text which gets removed
$inputs[4] = '<ul>Illegal text<li>Legal item</li></ul>';
$expect[4] = '<ul><li>Legal item</li></ul>';
$this->assertResult(
'<ul>Illegal text<li>Legal item</li></ul>',
'<ul><li>Legal item</li></ul>'
);
// test custom table definition
$inputs[5] = '<table><tr><td>Cell 1</td></tr></table>';
$expect[5] = '<table><tr><td>Cell 1</td></tr></table>';
$inputs[6] = '<table></table>';
$expect[6] = '';
$this->assertResult(
'<table><tr><td>Cell 1</td></tr></table>',
'<table><tr><td>Cell 1</td></tr></table>'
);
$this->assertResult('<table></table>', '');
// breaks without the redundant checking code
$inputs[7] = '<table><tr></tr></table>';
$expect[7] = '';
$this->assertResult('<table><tr></tr></table>', '');
// special case, prevents scrolling one back to find parent
$inputs[8] = '<table><tr></tr><tr></tr></table>';
$expect[8] = '';
$this->assertResult('<table><tr></tr><tr></tr></table>', '');
// cascading rollbacks
$inputs[9] = '<table><tbody><tr></tr><tr></tr></tbody><tr></tr><tr></tr></table>';
$expect[9] = '';
$this->assertResult(
'<table><tbody><tr></tr><tr></tr></tbody><tr></tr><tr></tr></table>',
''
);
// rollbacks twice
$inputs[10] = '<table></table><table></table>';
$expect[10] = '';
$this->assertResult('<table></table><table></table>', '');
// block in inline ins not allowed
$inputs[11] = '<span><ins><div>Not allowed!</div></ins></span>';
$expect[11] = '<span><ins>Not allowed!</ins></span>';
$this->assertResult(
'<span><ins><div>Not allowed!</div></ins></span>',
'<span><ins>Not allowed!</ins></span>'
);
// block in inline ins not allowed
$inputs[14] = '<span><ins><div>Not allowed!</div></ins></span>';
$expect[14] = '<span><ins>&lt;div&gt;Not allowed!&lt;/div&gt;</ins></span>';
$config[14] = $config_escape;
$this->assertResult(
'<span><ins><div>Not allowed!</div></ins></span>',
'<span><ins>&lt;div&gt;Not allowed!&lt;/div&gt;</ins></span>',
array('Core.EscapeInvalidChildren' => true)
);
// test exclusions
$inputs[12] = '<a><span><a>Not allowed</a></span></a>';
$expect[12] = '<a><span></span></a>';
$this->assertResult(
'<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/Strategy/MakeWellFormed.php';
class HTMLPurifier_Strategy_MakeWellFormedTest
extends HTMLPurifier_StrategyHarness
class HTMLPurifier_Strategy_MakeWellFormedTest extends HTMLPurifier_StrategyHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_MakeWellFormed();
}
function test() {
$strategy = new HTMLPurifier_Strategy_MakeWellFormed();
$this->assertResult('');
$this->assertResult('This is <b>bold text</b>.');
$inputs = array();
$expect = array();
$this->assertResult(
'<b>Unclosed tag, gasp!',
'<b>Unclosed tag, gasp!</b>'
);
$inputs[0] = '';
$expect[0] = $inputs[0];
$this->assertResult(
'<b><i>Bold and italic?</b>',
'<b><i>Bold and italic?</i></b>'
);
$inputs[1] = 'This is <b>bold text</b>.';
$expect[1] = $inputs[1];
$this->assertResult(
'Unused end tags... recycle!</b>',
'Unused end tags... recycle!'
);
$inputs[2] = '<b>Unclosed tag, gasp!';
$expect[2] = '<b>Unclosed tag, gasp!</b>';
$this->assertResult(
'<br style="clear:both;">',
'<br style="clear:both;" />'
);
$inputs[3] = '<b><i>Bold and italic?</b>';
$expect[3] = '<b><i>Bold and italic?</i></b>';
// 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>';
$this->assertResult(
'<div style="clear:both;" />',
'<div style="clear:both;"></div>'
);
// test automatic paragraph closing
$inputs[7] = '<p>Paragraph 1<p>Paragraph 2';
$expect[7] = '<p>Paragraph 1</p><p>Paragraph 2</p>';
$this->assertResult(
'<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>';
$expect[8] = '<div><p>Paragraphs</p><p>In</p><p>A</p><p>Div</p></div>';
$this->assertResult(
'<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
$inputs[9] = '<ol><li>Item 1<li>Item 2</ol>';
$expect[9] = '<ol><li>Item 1</li><li>Item 2</li></ol>';
$this->assertStrategyWorks($strategy, $inputs, $expect);
$this->assertResult(
'<ol><li>Item 1<li>Item 2</ol>',
'<ol><li>Item 1</li><li>Item 2</li></ol>'
);
}
}

View File

@ -4,39 +4,44 @@ require_once 'HTMLPurifier/StrategyHarness.php';
require_once 'HTMLPurifier/Strategy/RemoveForeignElements.php';
class HTMLPurifier_Strategy_RemoveForeignElementsTest
extends HTMLPurifier_StrategyHarness
extends HTMLPurifier_StrategyHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_RemoveForeignElements();
}
function test() {
$strategy = new HTMLPurifier_Strategy_RemoveForeignElements();
$inputs = array();
$expect = array();
$this->assertResult('');
$inputs[0] = '';
$expect[0] = $inputs[0];
$this->assertResult('This is <b>bold text</b>.');
$inputs[1] = 'This is <b>bold text</b>.';
$expect[1] = $inputs[1];
$this->assertResult(
'<asdf>Bling</asdf><d href="bang">Bong</d><foobar />',
'BlingBong'
);
// [INVALID]
$inputs[2] = '<asdf>Bling</asdf><d href="bang">Bong</d><foobar />';
$expect[2] = 'BlingBong';
// test simple transform
$inputs[3] = '<menu><li>Item 1</li></menu>';
$expect[3] = '<ul><li>Item 1</li></ul>';
$this->assertResult(
'<menu><li>Item 1</li></menu>',
'<ul><li>Item 1</li></ul>'
);
// test center transform
$inputs[4] = '<center>Look I am Centered!</center>';
$expect[4] = '<div style="text-align:center;">Look I am Centered!</div>';
$this->assertResult(
'<center>Look I am Centered!</center>',
'<div style="text-align:center;">Look I am Centered!</div>'
);
// test font transform
$inputs[5] = '<font color="red" face="Arial" size="6">Big Warning!</font>';
$expect[5] = '<span style="color:red;font-family:Arial;font-size:xx-large;">Big Warning!</span>';
$this->assertResult(
'<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
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_Strategy_ValidateAttributes();
}
function test() {
$strategy = new HTMLPurifier_Strategy_ValidateAttributes();
// attribute order is VERY fragile, perhaps we should define
// an ordering scheme!
$inputs = array();
$expect = array();
$config = array();
$inputs[0] = '';
$expect[0] = '';
$this->assertResult('');
// test ids
$this->assertResult('<div id="valid">Preserve the ID.</div>');
$inputs[1] = '<div id="valid">Preserve the ID.</div>';
$expect[1] = $inputs[1];
$inputs[2] = '<div id="0invalid">Kill the ID.</div>';
$expect[2] = '<div>Kill the ID.</div>';
$this->assertResult(
'<div id="0invalid">Kill the ID.</div>',
'<div>Kill the ID.</div>'
);
// test id accumulator
$inputs[3] = '<div id="valid">Valid</div><div id="valid">Invalid</div>';
$expect[3] = '<div id="valid">Valid</div><div>Invalid</div>';
$this->assertResult(
'<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>';
$expect[4] = '<span>Bad dir.</span>';
$this->assertResult(
'<span dir="up-to-down">Bad dir.</span>',
'<span>Bad dir.</span>'
);
// test attribute case sensitivity
$inputs[5] = '<div ID="valid">Convert ID to lowercase.</div>';
$expect[5] = '<div id="valid">Convert ID to lowercase.</div>';
// test attribute key case sensitivity
$this->assertResult(
'<div ID="valid">Convert ID to lowercase.</div>',
'<div id="valid">Convert ID to lowercase.</div>'
);
// test simple attribute substitution
$inputs[6] = '<div id=" valid ">Trim whitespace.</div>';
$expect[6] = '<div id="valid">Trim whitespace.</div>';
$this->assertResult(
'<div id=" valid ">Trim whitespace.</div>',
'<div id="valid">Trim whitespace.</div>'
);
// test configuration id blacklist
$inputs[7] = '<div id="invalid">Invalid</div>';
$expect[7] = '<div>Invalid</div>';
$config[7] = HTMLPurifier_Config::createDefault();
$config[7]->set('Attr', 'IDBlacklist', array('invalid'));
$this->assertResult(
'<div id="invalid">Invalid</div>',
'<div>Invalid</div>',
array('Attr.IDBlacklist' => array('invalid'))
);
// test classes
$inputs[8] = '<div class="valid">Valid</div>';
$expect[8] = $inputs[8];
$this->assertResult('<div class="valid">Valid</div>');
$inputs[9] = '<div class="valid 0invalid">Keep valid.</div>';
$expect[9] = '<div class="valid">Keep valid.</div>';
$this->assertResult(
'<div class="valid 0invalid">Keep valid.</div>',
'<div class="valid">Keep valid.</div>'
);
// test title
$inputs[10] = '<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>';
$expect[10] = $inputs[10];
$this->assertResult(
'<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>'
);
// test lang
$inputs[11] = '<span lang="fr">La soupe.</span>';
$expect[11] = '<span lang="fr" xml:lang="fr">La soupe.</span>';
$this->assertResult(
'<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)
$inputs[12] = '<h1 align="center">Centered Headline</h1>';
$expect[12] = '<h1 style="text-align:center;">Centered Headline</h1>';
// test align
$this->assertResult(
'<h1 align="center">Centered Headline</h1>',
'<h1 style="text-align:center;">Centered Headline</h1>'
);
// test table
$inputs[13] =
$this->assertResult(
'<table frame="above" rules="rows" summary="A test table" border="2" cellpadding="5%" cellspacing="3" width="100%">
<col align="right" width="4*" />
<col charoff="5" align="char" width="1*" />
@ -87,44 +99,56 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
<tr>
<td colspan="2">Taken off the market</td>
</tr>
</table>';
$expect[13] = $inputs[13];
</table>'
);
// test URI
$inputs[14] = '<a href="http://www.google.com/">Google</a>';
$expect[14] = $inputs[14];
$this->assertResult('<a href="http://www.google.com/">Google</a>');
// test invalid URI
$inputs[15] = '<a href="javascript:badstuff();">Google</a>';
$expect[15] = '<a>Google</a>';
$this->assertResult(
'<a href="javascript:badstuff();">Google</a>',
'<a>Google</a>'
);
// test required attributes for img
$inputs[16] = '<img />';
$expect[16] = '<img src="" alt="Invalid image" />';
$this->assertResult(
'<img />',
'<img src="" alt="Invalid image" />'
);
$inputs[17] = '<img src="foobar.jpg" />';
$expect[17] = '<img src="foobar.jpg" alt="foobar.jpg" />';
$this->assertResult(
'<img src="foobar.jpg" />',
'<img src="foobar.jpg" alt="foobar.jpg" />'
);
$inputs[18] = '<img alt="pretty picture" />';
$expect[18] = '<img alt="pretty picture" src="" />';
$this->assertResult(
'<img alt="pretty picture" />',
'<img alt="pretty picture" src="" />'
);
// test required attributes for bdo
$inputs[19] = '<bdo>Go left.</bdo>';
$expect[19] = '<bdo dir="ltr">Go left.</bdo>';
$this->assertResult(
'<bdo>Go left.</bdo>',
'<bdo dir="ltr">Go left.</bdo>'
);
$inputs[20] = '<bdo dir="blahblah">Invalid value!</bdo>';
$expect[20] = '<bdo dir="ltr">Invalid value!</bdo>';
$this->assertResult(
'<bdo dir="blahblah">Invalid value!</bdo>',
'<bdo dir="ltr">Invalid value!</bdo>'
);
// comparison check for test 20
$inputs[21] = '<span dir="blahblah">Invalid value!</span>';
$expect[21] = '<span>Invalid value!</span>';
$this->assertResult(
'<span dir="blahblah">Invalid value!</span>',
'<span>Invalid value!</span>'
);
// test col.span is non-zero
$inputs[22] = '<col span="0" />';
$expect[22] = '<col />';
$this->assertStrategyWorks($strategy, $inputs, $expect, $config);
$this->assertResult(
'<col span="0" />',
'<col />'
);
}

View File

@ -1,41 +1,14 @@
<?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 HTMLPurifier_StrategyHarness() {
$this->UnitTestCase();
// 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]);
}
function setUp() {
$this->func = 'execute';
$this->to_tokens = true;
$this->to_html = true;
}
}