0
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2024-09-18 18:25:18 +00:00
+ PHP4 reference/foreach cruft in Injector removed
. Unit tests for Injector improved
. Some todo stuff updated

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk@1462 48356398-32a2-884e-a903-53898d9a118a
This commit is contained in:
Edward Z. Yang 2007-12-05 01:26:28 +00:00
parent 7ddd9d0afe
commit b5546ff6f0
6 changed files with 44 additions and 24 deletions

2
NEWS
View File

@ -15,7 +15,9 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
to it.
+ Visibility declarations added
+ Constructor methods renamed to __construct()
+ PHP4 reference/foreach cruft removed (in progress)
! CSS properties are no case-insensitive
. Unit tests for Injector improved
2.1.3, released 2007-11-05
! tests/multitest.php allows you to test multiple versions by running

3
TODO
View File

@ -11,6 +11,9 @@ If no interest is expressed for a feature that may required a considerable
amount of effort to implement, it may get endlessly delayed. Do not be
afraid to cast your vote for the next feature to be implemented!
3.0 release [Go PHP5!]
- Convert all &$context calls to $context, as PHP5 passes objects by value
3.1 release [Error'ed]
# Error logging for filtering/cleanup procedures
- XSS-attempt detection

View File

@ -134,6 +134,7 @@ class HTMLPurifier
*/
public function purify($html, $config = null) {
// todo: make the config merge in, instead of replace
$config = $config ? HTMLPurifier_Config::create($config) : $this->config;
// implementation is partially environment dependant, partially

View File

@ -8,7 +8,7 @@
* @todo Allow injectors to request a re-run on their output. This
* would help if an operation is recursive.
*/
class HTMLPurifier_Injector
abstract class HTMLPurifier_Injector
{
/**

View File

@ -39,7 +39,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
$result = array();
$generator = new HTMLPurifier_Generator();
$escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
$e =& $context->get('ErrorCollector', true);
$e = $context->get('ErrorCollector', true);
// member variables
$this->currentNesting = array();
@ -49,8 +49,8 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
// context variables
$context->register('CurrentNesting', $this->currentNesting);
$context->register('InputIndex', $this->inputIndex);
$context->register('InputTokens', $tokens);
$context->register('InputIndex', $this->inputIndex);
$context->register('InputTokens', $tokens);
// -- begin INJECTOR --
@ -81,23 +81,22 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
// give the injectors references to the definition and context
// variables for performance reasons
foreach ($this->injectors as $i => $x) {
$error = $this->injectors[$i]->prepare($config, $context);
foreach ($this->injectors as $i => $injector) {
$error = $injector->prepare($config, $context);
if (!$error) continue;
list($injector) = array_splice($this->injectors, $i, 1);
$name = $injector->name;
trigger_error("Cannot enable $name injector because $error is not allowed", E_USER_WARNING);
array_splice($this->injectors, $i, 1); // rm the injector
trigger_error("Cannot enable {$injector->name} injector because $error is not allowed", E_USER_WARNING);
}
// warning: most foreach loops follow the convention $i => $x.
// be sure, for PHP4 compatibility, to only perform write operations
// directly referencing the object using $i: $x is only safe for reads
// warning: most foreach loops follow the convention $i => $injector.
// Don't define these as loop-wide variables, please!
// -- end INJECTOR --
$token = false;
$context->register('CurrentToken', $token);
// isset is in loop because $tokens size changes during loop exec
for ($this->inputIndex = 0; isset($tokens[$this->inputIndex]); $this->inputIndex++) {
// if all goes well, this token will be passed through unharmed
@ -105,16 +104,16 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
//printTokens($tokens, $this->inputIndex);
foreach ($this->injectors as $i => $x) {
if ($x->skip > 0) $this->injectors[$i]->skip--;
foreach ($this->injectors as $injector) {
if ($injector->skip > 0) $injector->skip--;
}
// quick-check: if it's not a tag, no need to process
if (empty( $token->is_tag )) {
if ($token->type === 'text') {
// injector handler code; duplicated for performance reasons
foreach ($this->injectors as $i => $x) {
if (!$x->skip) $this->injectors[$i]->handleText($token);
foreach ($this->injectors as $i => $injector) {
if (!$injector->skip) $injector->handleText($token);
if (is_array($token)) {
$this->currentInjector = $i;
break;
@ -171,8 +170,8 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
// injector handler code; duplicated for performance reasons
if ($ok) {
foreach ($this->injectors as $i => $x) {
if (!$x->skip) $this->injectors[$i]->handleElement($token);
foreach ($this->injectors as $i => $injector) {
if (!$injector->skip) $injector->handleElement($token);
if (is_array($token)) {
$this->currentInjector = $i;
break;
@ -202,8 +201,8 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
$current_parent = array_pop($this->currentNesting);
if ($current_parent->name == $token->name) {
$result[] = $token;
foreach ($this->injectors as $i => $x) {
$this->injectors[$i]->notifyEnd($token);
foreach ($this->injectors as $i => $injector) {
$injector->notifyEnd($token);
}
continue;
}
@ -242,12 +241,13 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
// okay, we found it, close all the skipped tags
// note that skipped tags contains the element we need closed
for ($i = count($skipped_tags) - 1; $i >= 0; $i--) {
// please don't redefine $i!
if ($i && $e && !isset($skipped_tags[$i]->armor['MakeWellFormed_TagClosedError'])) {
$e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$i]);
}
$result[] = $new_token = new HTMLPurifier_Token_End($skipped_tags[$i]->name);
foreach ($this->injectors as $j => $x) { // $j, not $i!!!
$this->injectors[$j]->notifyEnd($new_token);
foreach ($this->injectors as $injector) {
$injector->notifyEnd($new_token);
}
}
@ -263,12 +263,13 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
// not using $skipped_tags since it would invariably be all of them
if (!empty($this->currentNesting)) {
for ($i = count($this->currentNesting) - 1; $i >= 0; $i--) {
// please don't redefine $i!
if ($e && !isset($this->currentNesting[$i]->armor['MakeWellFormed_TagClosedError'])) {
$e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by document end', $this->currentNesting[$i]);
}
$result[] = $new_token = new HTMLPurifier_Token_End($this->currentNesting[$i]->name);
foreach ($this->injectors as $j => $x) { // $j, not $i!!!
$this->injectors[$j]->notifyEnd($new_token);
foreach ($this->injectors as $injector) {
$injector->notifyEnd($new_token);
}
}
}

View File

@ -26,6 +26,19 @@ class HTMLPurifier_Strategy_MakeWellFormed_InjectorTest extends HTMLPurifier_Str
$this->assertResult('<i><b>asdf</b>', '<i><b>asdf</b></i>');
}
function testErrorRequiredElementNotAllowed() {
$this->config->set('HTML', 'Allowed', '');
$this->expectError('Cannot enable AutoParagraph injector because p is not allowed');
$this->expectError('Cannot enable Linkify injector because a is not allowed');
$this->assertResult('Foobar');
}
function testErrorRequiredAttributeNotAllowed() {
$this->config->set('HTML', 'Allowed', 'a,p');
$this->expectError('Cannot enable Linkify injector because a.href is not allowed');
$this->assertResult('<p>http://example.com</p>');
}
function testOnlyAutoParagraph() {
$this->assertResult(
'Foobar',