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

[2.0.1] Add error messages for FixNesting

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1249 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang 2007-06-26 23:43:28 +00:00
parent 9a66394abb
commit a005da8a4c
5 changed files with 88 additions and 21 deletions

View File

@ -10,27 +10,32 @@ $messages = array(
'ErrorCollector: No errors' => 'No errors detected. However, because error reporting is still incomplete, there may have been errors that the error collector was not notified of; please inspect the output HTML carefully.',
'ErrorCollector: At line' => ' at line $line',
'Lexer: Unclosed comment' => 'Unclosed comment',
'Lexer: Unescaped lt' => 'Unescaped less-than sign (<) should be &lt;',
'Lexer: Missing gt' => 'Missing greater-than sign (>), previous less-than sign (<) should be escaped',
'Lexer: Unclosed comment' => 'Unclosed comment',
'Lexer: Unescaped lt' => 'Unescaped less-than sign (<) should be &lt;',
'Lexer: Missing gt' => 'Missing greater-than sign (>), previous less-than sign (<) should be escaped',
'Lexer: Missing attribute key' => 'Attribute declaration has no key',
'Lexer: Missing end quote' => 'Attribute declaration has no end quote',
'Lexer: Missing end quote' => 'Attribute declaration has no end quote',
'Strategy_RemoveForeignElements: Tag transform' => '<$1> element transformed into $CurrentToken.Serialized',
'Strategy_RemoveForeignElements: Tag transform' => '<$1> element transformed into $CurrentToken.Serialized',
'Strategy_RemoveForeignElements: Missing required attribute' => '$CurrentToken.Compact element missing required attribute $1',
'Strategy_RemoveForeignElements: Foreign element to text' => 'Unrecognized $CurrentToken.Serialized tag converted to text',
'Strategy_RemoveForeignElements: Foreign element removed' => 'Unrecognized $CurrentToken.Serialized tag removed',
'Strategy_RemoveForeignElements: Comment removed' => 'Comment containing "$CurrentToken.Data" removed',
'Strategy_RemoveForeignElements: Script removed' => 'Script removed',
'Strategy_RemoveForeignElements: Token removed to end' => 'Tags and text starting from $1 element where removed to end',
'Strategy_RemoveForeignElements: Foreign element to text' => 'Unrecognized $CurrentToken.Serialized tag converted to text',
'Strategy_RemoveForeignElements: Foreign element removed' => 'Unrecognized $CurrentToken.Serialized tag removed',
'Strategy_RemoveForeignElements: Comment removed' => 'Comment containing "$CurrentToken.Data" removed',
'Strategy_RemoveForeignElements: Script removed' => 'Script removed',
'Strategy_RemoveForeignElements: Token removed to end' => 'Tags and text starting from $1 element where removed to end',
'Strategy_MakeWellFormed: Unnecessary end tag removed' => 'Unnecessary $CurrentToken.Serialized tag removed',
'Strategy_MakeWellFormed: Unnecessary end tag to text' => 'Unnecessary $CurrentToken.Serialized tag converted to text',
'Strategy_MakeWellFormed: Tag auto closed' => '$1.Compact started on line $1.Line auto-closed by $CurrentToken.Compact',
'Strategy_MakeWellFormed: Stray end tag removed' => 'Stray $CurrentToken.Serialized tag removed',
'Strategy_MakeWellFormed: Stray end tag to text' => 'Stray $CurrentToken.Serialized tag converted to text',
'Strategy_MakeWellFormed: Tag closed by element end' => '$1.Compact tag started on line $1.Line closed by end of $CurrentToken.Serialized',
'Strategy_MakeWellFormed: Tag closed by document end' => '$1.Compact tag started on line $1.Line closed by end of document',
'Strategy_MakeWellFormed: Tag auto closed' => '$1.Compact started on line $1.Line auto-closed by $CurrentToken.Compact',
'Strategy_MakeWellFormed: Stray end tag removed' => 'Stray $CurrentToken.Serialized tag removed',
'Strategy_MakeWellFormed: Stray end tag to text' => 'Stray $CurrentToken.Serialized tag converted to text',
'Strategy_MakeWellFormed: Tag closed by element end' => '$1.Compact tag started on line $1.Line closed by end of $CurrentToken.Serialized',
'Strategy_MakeWellFormed: Tag closed by document end' => '$1.Compact tag started on line $1.Line closed by end of document',
'Strategy_FixNesting: Node removed' => '$CurrentToken.Compact node removed',
'Strategy_FixNesting: Node excluded' => '$CurrentToken.Compact node removed due to descendant exclusion by ancestor element',
'Strategy_FixNesting: Node reorganized' => 'Contents of $CurrentToken.Compact node reorganized to enforce its content model',
'Strategy_FixNesting: Node contents removed' => 'Contents of $CurrentToken.Compact node removed',
);

View File

@ -54,6 +54,9 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
$is_inline = $definition->info_parent_def->descendants_are_inline;
$context->register('IsInline', $is_inline);
// setup error collector
$e =& $context->get('ErrorCollector', true);
//####################################################################//
// Loop initialization
@ -67,6 +70,11 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// processed, i.e. there won't be empty exclusions.
$exclude_stack = array();
// variable that contains the start token while we are processing
// nodes. This enables error reporting to do its job
$start_token = false;
$context->register('CurrentToken', $start_token);
//####################################################################//
// Loop
@ -100,6 +108,8 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// $i is index of start token
// $j is index of end token
$start_token = $tokens[$i]; // to make token available via CurrentToken
//################################################################//
// Gather information on parent
@ -200,6 +210,14 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
} elseif($result === false) {
// remove entire node
if ($e) {
if ($excluded) {
$e->send(E_ERROR, 'Strategy_FixNesting: Node excluded');
} else {
$e->send(E_ERROR, 'Strategy_FixNesting: Node removed');
}
}
// calculate length of inner tokens and current tokens
$length = $j - $i + 1;
@ -216,7 +234,7 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// this is a rought heuristic that covers 100% of HTML's
// cases and 99% of all other cases. A child definition
// that would be tricked by this would be something like:
// ( | a b c) where it's all or nothing. Fortunantely,
// ( | a b c) where it's all or nothing. Fortunately,
// our current implementation claims that that case would
// not allow empty, even if it did
if (!$parent_def->child->allow_empty) {
@ -234,6 +252,14 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// calculate length of inner tokens
$length = $j - $i - 1;
if ($e) {
if (empty($result) && $length) {
$e->send(E_ERROR, 'Strategy_FixNesting: Node contents removed');
} else {
$e->send(E_WARNING, 'Strategy_FixNesting: Node reorganized');
}
}
// perform replacement
array_splice($tokens, $i + 1, $length, $result);
@ -291,6 +317,7 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// remove context variables
$context->destroy('IsInline');
$context->destroy('CurrentToken');
//####################################################################//
// Return

View File

@ -0,0 +1,39 @@
<?php
require_once 'HTMLPurifier/Strategy/ErrorsHarness.php';
require_once 'HTMLPurifier/Strategy/FixNesting.php';
class HTMLPurifier_Strategy_FixNesting_ErrorsTest extends HTMLPurifier_Strategy_ErrorsHarness
{
function getStrategy() {
return new HTMLPurifier_Strategy_FixNesting();
}
function testNodeRemoved() {
$this->expectErrorCollection(E_ERROR, 'Strategy_FixNesting: Node removed');
$this->expectContext('CurrentToken', new HTMLPurifier_Token_Start('ul', array(), 1));
$this->invoke('<ul></ul>');
}
function testNodeExcluded() {
$this->expectErrorCollection(E_ERROR, 'Strategy_FixNesting: Node excluded');
$this->expectContext('CurrentToken', new HTMLPurifier_Token_Start('a', array(), 2));
$this->invoke("<a>\n<a></a></a>");
}
function testNodeReorganized() {
$this->expectErrorCollection(E_WARNING, 'Strategy_FixNesting: Node reorganized');
$this->expectContext('CurrentToken', new HTMLPurifier_Token_Start('span', array(), 1));
$this->invoke("<span>Valid<div>Invalid</div></span>");
}
function testNodeContentsRemoved() {
$this->expectErrorCollection(E_ERROR, 'Strategy_FixNesting: Node contents removed');
$this->expectContext('CurrentToken', new HTMLPurifier_Token_Start('span', array(), 1));
$this->invoke("<span><div></div></span>");
}
}
?>

View File

@ -3,11 +3,6 @@
require_once 'HTMLPurifier/Strategy/ErrorsHarness.php';
require_once 'HTMLPurifier/Strategy/MakeWellFormed.php';
/*
'Strategy_MakeWellFormed: Tag closed by element end' => '',
'Strategy_MakeWellFormed: Tag closed by document end' => '',
*/
class HTMLPurifier_Strategy_MakeWellFormed_ErrorsTest extends HTMLPurifier_Strategy_ErrorsHarness
{

View File

@ -93,6 +93,7 @@ $test_files[] = 'HTMLPurifier/PercentEncoderTest.php';
$test_files[] = 'HTMLPurifier/Strategy/CompositeTest.php';
$test_files[] = 'HTMLPurifier/Strategy/CoreTest.php';
$test_files[] = 'HTMLPurifier/Strategy/FixNestingTest.php';
$test_files[] = 'HTMLPurifier/Strategy/FixNesting_ErrorsTest.php';
$test_files[] = 'HTMLPurifier/Strategy/MakeWellFormedTest.php';
$test_files[] = 'HTMLPurifier/Strategy/MakeWellFormed_ErrorsTest.php';
$test_files[] = 'HTMLPurifier/Strategy/RemoveForeignElementsTest.php';