From d9e60350d388e7a8c7db1e402e871ebcbe9fca26 Mon Sep 17 00:00:00 2001 From: "Edward Z. Yang" Date: Mon, 18 Aug 2008 22:13:58 -0400 Subject: [PATCH] Migrate AttrValidator to nested error format; modify generator logic in ErrorCollector. AttrValidator's changes are fairly self-explanatory, but ErrorCollector's changes are worth a little discussion. ErrorCollector can use generators at various points during its flow control; there are two distinct generators that it should use: 1. The one used for the output, and 2. The one used for the error output. These will usually be the same, but in the odd case where they need to be different, getHTMLFormatted() will accept an alterate configuration object with an appropriate doctype. Signed-off-by: Edward Z. Yang --- library/HTMLPurifier/AttrValidator.php | 30 +++++++++++++++--- library/HTMLPurifier/ErrorCollector.php | 6 ++-- .../HTMLPurifier/AttrValidator_ErrorsTest.php | 31 ++++++++++++++++--- 3 files changed, 54 insertions(+), 13 deletions(-) diff --git a/library/HTMLPurifier/AttrValidator.php b/library/HTMLPurifier/AttrValidator.php index ba4510e3..9d692513 100644 --- a/library/HTMLPurifier/AttrValidator.php +++ b/library/HTMLPurifier/AttrValidator.php @@ -49,15 +49,23 @@ class HTMLPurifier_AttrValidator // do global transformations (pre) // nothing currently utilizes this foreach ($definition->info_attr_transform_pre as $transform) { + if ($e) $e->start(); $attr = $transform->transform($o = $attr, $config, $context); - if ($e && ($attr != $o)) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + if ($e) { + if ($attr != $o) $e->end(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + else $e->end(); + } } // do local transformations only applicable to this element (pre) // ex.

to

foreach ($definition->info[$token->name]->attr_transform_pre as $transform) { + if ($e) $e->start(); $attr = $transform->transform($o = $attr, $config, $context); - if ($e && ($attr != $o)) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + if ($e) { + if ($attr != $o) $e->end(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + else $e->end(); + } } // create alias to this element's attribute definition array, see @@ -72,6 +80,7 @@ class HTMLPurifier_AttrValidator // Watch out for name collisions: $key has previously been used foreach ($attr as $attr_key => $value) { + if ($e) $e->start(); // call the definition if ( isset($defs[$attr_key]) ) { // there is a local definition defined @@ -103,7 +112,7 @@ class HTMLPurifier_AttrValidator if ($result === false || $result === null) { // this is a generic error message that should replaced // with more specific ones when possible - if ($e) $e->send(E_ERROR, 'AttrValidator: Attribute removed'); + if ($e) $e->end(E_ERROR, 'AttrValidator: Attribute removed'); // remove the attribute unset($attr[$attr_key]); @@ -114,6 +123,9 @@ class HTMLPurifier_AttrValidator // simple substitution $attr[$attr_key] = $result; + if ($e) $e->end(); + } else { + if ($e) $e->end(); } // we'd also want slightly more complicated substitution @@ -129,14 +141,22 @@ class HTMLPurifier_AttrValidator // global (error reporting untested) foreach ($definition->info_attr_transform_post as $transform) { + if ($e) $e->start(); $attr = $transform->transform($o = $attr, $config, $context); - if ($e && ($attr != $o)) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + if ($e) { + if ($attr != $o) $e->end(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + else $e->end(); + } } // local (error reporting untested) foreach ($definition->info[$token->name]->attr_transform_post as $transform) { + if ($e) $e->start(); $attr = $transform->transform($o = $attr, $config, $context); - if ($e && ($attr != $o)) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + if ($e) { + if ($attr != $o) $e->end(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); + else $e->end(); + } } $token->attr = $attr; diff --git a/library/HTMLPurifier/ErrorCollector.php b/library/HTMLPurifier/ErrorCollector.php index fe8c8eff..9d101e42 100644 --- a/library/HTMLPurifier/ErrorCollector.php +++ b/library/HTMLPurifier/ErrorCollector.php @@ -25,10 +25,9 @@ class HTMLPurifier_ErrorCollector public function __construct($context) { $this->locale =& $context->get('Locale'); - $this->generator =& $context->get('Generator'); $this->context = $context; $this->_current =& $this->_stacks[0]; - $this->errors =& $this->_stacks[0]; + $this->errors =& $this->_stacks[0]; } /** @@ -141,6 +140,7 @@ class HTMLPurifier_ErrorCollector public function getHTMLFormatted($config, $errors = null) { $ret = array(); + $generator = new HTMLPurifier_Generator($config, $this->context); if ($errors === null) $errors = $this->errors; // sort error array by line @@ -161,7 +161,7 @@ class HTMLPurifier_ErrorCollector list($line, $severity, $msg, $children) = $error; $string = ''; $string .= '' . $this->locale->getErrorName($severity) . ': '; - $string .= $this->generator->escape($msg); + $string .= $generator->escape($msg); if ($line) { // have javascript link generation that causes // textarea to skip to the specified line diff --git a/tests/HTMLPurifier/AttrValidator_ErrorsTest.php b/tests/HTMLPurifier/AttrValidator_ErrorsTest.php index d3242c06..a8e61cad 100644 --- a/tests/HTMLPurifier/AttrValidator_ErrorsTest.php +++ b/tests/HTMLPurifier/AttrValidator_ErrorsTest.php @@ -3,6 +3,15 @@ class HTMLPurifier_AttrValidator_ErrorsTest extends HTMLPurifier_ErrorsHarness { + public function setup() { + parent::setup(); + $config = HTMLPurifier_Config::createDefault(); + $this->language = HTMLPurifier_LanguageFactory::instance()->create($config, $this->context); + $this->context->register('Locale', $this->language); + $this->collector = new HTMLPurifier_ErrorCollector($this->context); + $this->context->register('Generator', new HTMLPurifier_Generator($config, $this->context)); + } + protected function invoke($input) { $validator = new HTMLPurifier_AttrValidator(); $validator->validateToken($input, $this->config, $this->context); @@ -18,28 +27,40 @@ class HTMLPurifier_AttrValidator_ErrorsTest extends HTMLPurifier_ErrorsHarness $output = array('class' => 'value'); // must be valid $transform->setReturnValue('transform', $output, array($input, new AnythingExpectation(), new AnythingExpectation())); $def->info_attr_transform_pre[] = $transform; - $this->expectErrorCollection(E_NOTICE, 'AttrValidator: Attributes transformed', $input, $output); + $token = new HTMLPurifier_Token_Start('span', $input, 1); $this->invoke($token); + + $result = $this->collector->getRaw(); + $expect = array( + array(1, E_NOTICE, 'Attributes on transformed from original to class', array()), + ); + $this->assertIdentical($result, $expect); } function testAttributesTransformedLocalPre() { $this->config->set('HTML', 'TidyLevel', 'heavy'); $input = array('align' => 'right'); $output = array('style' => 'text-align:right;'); - $this->expectErrorCollection(E_NOTICE, 'AttrValidator: Attributes transformed', $input, $output); $token = new HTMLPurifier_Token_Start('p', $input, 1); $this->invoke($token); + $result = $this->collector->getRaw(); + $expect = array( + array(1, E_NOTICE, 'Attributes on

transformed from align to style', array()), + ); + $this->assertIdentical($result, $expect); } // too lazy to check for global post and global pre function testAttributeRemoved() { - $this->expectErrorCollection(E_ERROR, 'AttrValidator: Attribute removed'); - $this->expectContext('CurrentAttr', 'foobar'); $token = new HTMLPurifier_Token_Start('p', array('foobar' => 'right'), 1); - $this->expectContext('CurrentToken', $token); $this->invoke($token); + $result = $this->collector->getRaw(); + $expect = array( + array(1, E_ERROR, 'foobar attribute on

removed', array()), + ); + $this->assertIdentical($result, $expect); } }