diff --git a/library/HTMLPurifier/Strategy/MakeWellFormed.php b/library/HTMLPurifier/Strategy/MakeWellFormed.php
index 24a14bff..0698c4e4 100644
--- a/library/HTMLPurifier/Strategy/MakeWellFormed.php
+++ b/library/HTMLPurifier/Strategy/MakeWellFormed.php
@@ -274,20 +274,23 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
$reprocess = true;
continue;
}
- foreach ($this->injectors as $i => $injector) {
- if (isset($token->skip[$i])) continue;
- if ($token->rewind !== null && $token->rewind !== $i) continue;
- $injector->handleEnd($token);
- $this->processToken($token, $i);
- $reprocess = true;
- break;
- }
- if ($reprocess) continue;
- // first, check for the simplest case: everything closes neatly
+ // first, check for the simplest case: everything closes neatly.
+ // Eventually, everything passes through here; if there are problems
+ // we modify the input stream accordingly and then punt, so that
+ // the tokens get processed again.
$current_parent = array_pop($this->stack);
if ($current_parent->name == $token->name) {
$token->start = $current_parent;
+ foreach ($this->injectors as $i => $injector) {
+ if (isset($token->skip[$i])) continue;
+ if ($token->rewind !== null && $token->rewind !== $i) continue;
+ $injector->handleEnd($token);
+ $this->processToken($token, $i);
+ $this->stack[] = $current_parent;
+ $reprocess = true;
+ break;
+ }
continue;
}
@@ -343,6 +346,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
$this->insertBefore($new_token);
}
$reprocess = true;
+ continue;
}
$context->destroy('CurrentNesting');
diff --git a/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjector.php b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjector.php
new file mode 100644
index 00000000..0673aee9
--- /dev/null
+++ b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjector.php
@@ -0,0 +1,16 @@
+name == 'div') return;
+ $token = array(
+ new HTMLPurifier_Token_Start('b'),
+ new HTMLPurifier_Token_Text('Comment'),
+ new HTMLPurifier_Token_End('b'),
+ $token
+ );
+ }
+}
diff --git a/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjectorTest.php b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjectorTest.php
new file mode 100644
index 00000000..ea0025a2
--- /dev/null
+++ b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndInsertInjectorTest.php
@@ -0,0 +1,37 @@
+obj = new HTMLPurifier_Strategy_MakeWellFormed();
+ $this->config->set('AutoFormat', 'Custom', array(
+ new HTMLPurifier_Strategy_MakeWellFormed_EndInsertInjector()
+ ));
+ }
+ function testEmpty() {
+ $this->assertResult('');
+ }
+ function testNormal() {
+ $this->assertResult('Foo', 'FooComment');
+ }
+ function testEndOfDocumentProcessing() {
+ $this->assertResult('Foo', 'FooComment');
+ }
+ function testDoubleEndOfDocumentProcessing() {
+ $this->assertResult('Foo', 'FooCommentComment');
+ }
+ function testEndOfNodeProcessing() {
+ $this->assertResult('
Foo
', 'FooComment
');
+ }
+ function testEmptyToStartEndProcessing() {
+ $this->assertResult('', 'Comment');
+ }
+ function testSpuriousEndTag() {
+ $this->assertResult('', '');
+ }
+ function testLessButStillSpuriousEndTag() {
+ $this->assertResult('', '');
+ }
+}
+
diff --git a/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjector.php b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjector.php
new file mode 100644
index 00000000..9352c1e4
--- /dev/null
+++ b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjector.php
@@ -0,0 +1,27 @@
+_InjectorTest_EndRewindInjector_delete)) {
+ $token = false;
+ }
+ }
+ public function handleText(&$token) {
+ $token = false;
+ }
+ public function handleEnd(&$token) {
+ $i = null;
+ if (
+ $this->backward($i, $prev) &&
+ $prev instanceof HTMLPurifier_Token_Start &&
+ $prev->name == 'span'
+ ) {
+ $token = false;
+ $prev->_InjectorTest_EndRewindInjector_delete = true;
+ $this->rewind($i);
+ }
+ }
+}
diff --git a/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjectorTest.php b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjectorTest.php
new file mode 100644
index 00000000..ef906e84
--- /dev/null
+++ b/tests/HTMLPurifier/Strategy/MakeWellFormed/EndRewindInjectorTest.php
@@ -0,0 +1,32 @@
+obj = new HTMLPurifier_Strategy_MakeWellFormed();
+ $this->config->set('AutoFormat', 'Custom', array(
+ new HTMLPurifier_Strategy_MakeWellFormed_EndRewindInjector()
+ ));
+ }
+ function testBasic() {
+ $this->assertResult('');
+ }
+ function testFunction() {
+ $this->assertResult('asdf','');
+ }
+ function testFailedFunction() {
+ $this->assertResult('asdasdfasdf','');
+ }
+ function testPadded() {
+ $this->assertResult('asdf','');
+ }
+ function testDoubled() {
+ $this->config->set('AutoFormat', 'Custom', array(
+ new HTMLPurifier_Strategy_MakeWellFormed_EndRewindInjector(),
+ new HTMLPurifier_Strategy_MakeWellFormed_EndRewindInjector(),
+ ));
+ $this->assertResult('asdf', '');
+ }
+}
+
diff --git a/tests/HTMLPurifier/Strategy/MakeWellFormed/SkipInjector.php b/tests/HTMLPurifier/Strategy/MakeWellFormed/SkipInjector.php
new file mode 100644
index 00000000..9ee8e826
--- /dev/null
+++ b/tests/HTMLPurifier/Strategy/MakeWellFormed/SkipInjector.php
@@ -0,0 +1,10 @@
+obj = new HTMLPurifier_Strategy_MakeWellFormed();
+ $this->config->set('AutoFormat', 'Custom', array(
+ new HTMLPurifier_Strategy_MakeWellFormed_SkipInjector()
+ ));
+ }
+ function testEmpty() {
+ $this->assertResult('');
+ }
+ function testMultiply() {
+ $this->assertResult('
', '
');
+ }
+ function testMultiplyMultiply() {
+ $this->config->set('AutoFormat', 'Custom', array(
+ new HTMLPurifier_Strategy_MakeWellFormed_SkipInjector(),
+ new HTMLPurifier_Strategy_MakeWellFormed_SkipInjector()
+ ));
+ $this->assertResult('
', '
');
+ }
+}
+
diff --git a/tests/HTMLPurifier/Strategy/MakeWellFormed_InjectorTest.php b/tests/HTMLPurifier/Strategy/MakeWellFormed_InjectorTest.php
index 80685727..212b2d4c 100644
--- a/tests/HTMLPurifier/Strategy/MakeWellFormed_InjectorTest.php
+++ b/tests/HTMLPurifier/Strategy/MakeWellFormed_InjectorTest.php
@@ -16,9 +16,13 @@ class HTMLPurifier_Strategy_MakeWellFormed_InjectorTest extends HTMLPurifier_Str
$mock = new HTMLPurifier_InjectorMock();
$b = new HTMLPurifier_Token_End('b');
$b->skip = array(0 => true);
+ $b->start = new HTMLPurifier_Token_Start('b');
+ $b->start->skip = array(0 => true, 1 => true);
$mock->expectAt(0, 'handleEnd', array($b));
$i = new HTMLPurifier_Token_End('i');
+ $i->start = new HTMLPurifier_Token_Start('i');
$i->skip = array(0 => true);
+ $i->start->skip = array(0 => true, 1 => true);
$mock->expectAt(1, 'handleEnd', array($i));
$mock->expectCallCount('handleEnd', 2);
$mock->setReturnValue('getRewind', false);