1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-08-03 12:47:56 +02:00

Compare commits

..

9 Commits

Author SHA1 Message Date
Edward Z. Yang
18e538317a Release 4.1.1.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-31 20:17:31 -07:00
Edward Z. Yang
96a4193fc9 Fix undefined index warnings in maintenance scripts.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-31 20:07:27 -07:00
Edward Z. Yang
00c66fa9cb Fix bug in parsing single attribute with entities.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-31 19:44:18 -07:00
Edward Z. Yang
d3abcb90e3 Rewrite CSS url() and font-family output logic.
The new logic is as follows:

* Given a URL to insert into url(), check that it is properly URL
  encoded (in particular, a doublequote and backslash never occurs
  within it) and then place it as url("http://example.com").

* Given a font name, if it is strictly alphanumeric, it is safe to omit
  quotes. Otherwise, wrap in double quotes and replace '"' with '\22 '
  (note trailing space) and '\' with '\5C ' (ditto).

We introduce expandCSSEscape() which is a hack for common parsing
idioms in CSS; this means that CSS escapes are now recognized inside
URLs as well as unquoted font names.

Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-31 18:45:21 -07:00
Edward Z. Yang
df3100b1b3 Make test script less chatty when log_errors is on.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-20 21:50:44 -04:00
Edward Z. Yang
143e1ad718 Remove shebang and +x from test script.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-20 21:21:26 -04:00
Edward Z. Yang
875b0febde Fix infinite loop involving wrapping formedness.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-17 23:22:51 -04:00
Edward Z. Yang
3166b8a10f Fix bug in background-position with center keyword.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-05 15:08:57 -04:00
Edward Z. Yang
1a70bffd5a Emit errors when body is extracted.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2010-05-04 13:41:09 -04:00
35 changed files with 195 additions and 122 deletions

View File

@@ -31,7 +31,7 @@ PROJECT_NAME = HTMLPurifier
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 4.1.0
PROJECT_NUMBER = 4.1.1
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

15
NEWS
View File

@@ -9,6 +9,21 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Internal change
==========================
4.1.1, released 2010-05-31
- Fix undefined index warnings in maintenance scripts.
- Fix bug in DirectLex for parsing elements with a single attribute
with entities.
- Rewrite CSS output logic for font-family and url(). Thanks Mario
Heiderich <mario.heiderich@googlemail.com> for reporting and Takeshi
Terada <t-terada@violet.plala.or.jp> for suggesting the fix.
- Emit an error for CollectErrors if a body is extracted
- Fix bug where in background-position for center keyword handling.
- Fix infinite loop when a wrapper element is inserted in a context
where it's not allowed. Thanks Lars <lars@renoz.dk> for reporting.
- Remove +x bit and shebang from index.php; only supported mode is to
explicitly call it with php.
- Make test script less chatty when log_errors is on.
4.1.0, released 2010-04-26
! Support proprietary height attribute on table element
! Support YouTube slideshows that contain /cp/ in their URL.

View File

@@ -1 +1 @@
4.1.0
4.1.1

View File

@@ -1,6 +1,5 @@
HTML Purifier 4.1 is a major security release that fixes an XSS
vulnerability exploitable on Internet Explorer. It also contains
a number of new features, including dramatically more flexible Flash
support, including %Output.FlashCompat to replace %HTML.SafeEmbed,
optional support for the data: URI scheme and better HTML parsing
capabilities.
HTML Purifier 4.1.1 is a major security and bugfix release that
improves on 4.1's fix for an XSS vulnerability exploitable on Internet
Explorer. It also contains a number of important bugfixes, including
the removal of improper logic that could result in infinite loops and
fixed parsing for single-attributes with entities with DirectLex.

View File

@@ -6,6 +6,7 @@
</file>
<file name="HTMLPurifier/Lexer.php">
<line>81</line>
<line>269</line>
</file>
<file name="HTMLPurifier/Lexer/DirectLex.php">
<line>53</line>

View File

@@ -7,7 +7,7 @@
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
* FILE, changes will be overwritten the next time the script is run.
*
* @version 4.1.0
* @version 4.1.1
*
* @warning
* You must *not* include any other HTML Purifier files before this file,

View File

@@ -19,7 +19,7 @@
*/
/*
HTML Purifier 4.1.0 - Standards Compliant HTML Filtering
HTML Purifier 4.1.1 - Standards Compliant HTML Filtering
Copyright (C) 2006-2008 Edward Z. Yang
This library is free software; you can redistribute it and/or
@@ -55,10 +55,10 @@ class HTMLPurifier
{
/** Version of HTML Purifier */
public $version = '4.1.0';
public $version = '4.1.1';
/** Constant with version of HTML Purifier */
const VERSION = '4.1.0';
const VERSION = '4.1.1';
/** Global configuration object */
public $config;

View File

@@ -82,6 +82,42 @@ abstract class HTMLPurifier_AttrDef
return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
}
/**
* Parses a possibly escaped CSS string and returns the "pure"
* version of it.
*/
protected function expandCSSEscape($string) {
// flexibly parse it
$ret = '';
for ($i = 0, $c = strlen($string); $i < $c; $i++) {
if ($string[$i] === '\\') {
$i++;
if ($i >= $c) {
$ret .= '\\';
break;
}
if (ctype_xdigit($string[$i])) {
$code = $string[$i];
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
if (!ctype_xdigit($string[$i])) break;
$code .= $string[$i];
}
// We have to be extremely careful when adding
// new characters, to make sure we're not breaking
// the encoding.
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
$ret .= $char;
if ($i < $c && trim($string[$i]) !== '') $i--;
continue;
}
if ($string[$i] === "\n") continue;
}
$ret .= $string[$i];
}
return $ret;
}
}
// vim: et sw=4 sts=4

View File

@@ -59,7 +59,8 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
$keywords = array();
$keywords['h'] = false; // left, right
$keywords['v'] = false; // top, bottom
$keywords['c'] = false; // center
$keywords['ch'] = false; // center (first word)
$keywords['cv'] = false; // center (second word)
$measures = array();
$i = 0;
@@ -79,6 +80,13 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
if (isset($lookup[$lbit])) {
$status = $lookup[$lbit];
if ($status == 'c') {
if ($i == 0) {
$status = 'ch';
} else {
$status = 'cv';
}
}
$keywords[$status] = $lbit;
$i++;
}
@@ -101,20 +109,19 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
if (!$i) return false; // no valid values were caught
$ret = array();
// first keyword
if ($keywords['h']) $ret[] = $keywords['h'];
elseif (count($measures)) $ret[] = array_shift($measures);
elseif ($keywords['c']) {
$ret[] = $keywords['c'];
$keywords['c'] = false; // prevent re-use: center = center center
elseif ($keywords['ch']) {
$ret[] = $keywords['ch'];
$keywords['cv'] = false; // prevent re-use: center = center center
}
elseif (count($measures)) $ret[] = array_shift($measures);
if ($keywords['v']) $ret[] = $keywords['v'];
elseif ($keywords['cv']) $ret[] = $keywords['cv'];
elseif (count($measures)) $ret[] = array_shift($measures);
elseif ($keywords['c']) $ret[] = $keywords['c'];
if (empty($ret)) return false;
return implode(' ', $ret);

View File

@@ -34,37 +34,10 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
$quote = $font[0];
if ($font[$length - 1] !== $quote) continue;
$font = substr($font, 1, $length - 2);
$new_font = '';
for ($i = 0, $c = strlen($font); $i < $c; $i++) {
if ($font[$i] === '\\') {
$i++;
if ($i >= $c) {
$new_font .= '\\';
break;
}
if (ctype_xdigit($font[$i])) {
$code = $font[$i];
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
if (!ctype_xdigit($font[$i])) break;
$code .= $font[$i];
}
// We have to be extremely careful when adding
// new characters, to make sure we're not breaking
// the encoding.
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
$new_font .= $char;
if ($i < $c && trim($font[$i]) !== '') $i--;
continue;
}
if ($font[$i] === "\n") continue;
}
$new_font .= $font[$i];
}
$font = $new_font;
}
$font = $this->expandCSSEscape($font);
// $font is a pure representation of the font name
if (ctype_alnum($font) && $font !== '') {
@@ -73,12 +46,21 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
continue;
}
// complicated font, requires quoting
// bugger out on whitespace. form feed (0C) really
// shouldn't show up regardless
$font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
// armor single quotes and new lines
$font = str_replace("\\", "\\\\", $font);
$font = str_replace("'", "\\'", $font);
$final .= "'$font', ";
// These ugly transforms don't pose a security
// risk (as \\ and \" might). We could try to be clever and
// use single-quote wrapping when there is a double quote
// present, but I have choosen not to implement that.
// (warning: this code relies on the selection of quotation
// mark below)
$font = str_replace('\\', '\\5C ', $font);
$font = str_replace('"', '\\22 ', $font);
// complicated font, requires quoting
$final .= "\"$font\", "; // note that this will later get turned into &quot;
}
$final = rtrim($final, ', ');
if ($final === '') return false;

View File

@@ -34,20 +34,16 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
$uri = substr($uri, 1, $new_length - 1);
}
$keys = array( '(', ')', ',', ' ', '"', "'");
$values = array('\\(', '\\)', '\\,', '\\ ', '\\"', "\\'");
$uri = str_replace($values, $keys, $uri);
$uri = $this->expandCSSEscape($uri);
$result = parent::validate($uri, $config, $context);
if ($result === false) return false;
// escape necessary characters according to CSS spec
// except for the comma, none of these should appear in the
// URI at all
$result = str_replace($keys, $values, $result);
// extra sanity check; should have been done by URI
$result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
return "url('$result')";
return "url(\"$result\")";
}

View File

@@ -20,7 +20,7 @@ class HTMLPurifier_Config
/**
* HTML Purifier's version
*/
public $version = '4.1.0';
public $version = '4.1.1';
/**
* Bool indicator whether or not to automatically finalize

View File

@@ -23,6 +23,7 @@ $messages = array(
'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: Extracted body' => 'Removed document metadata tags',
'Strategy_RemoveForeignElements: Tag transform' => '<$1> element transformed into $CurrentToken.Serialized',
'Strategy_RemoveForeignElements: Missing required attribute' => '$CurrentToken.Compact element missing required attribute $1',

View File

@@ -265,7 +265,15 @@ class HTMLPurifier_Lexer
// extract body from document if applicable
if ($config->get('Core.ConvertDocumentToFragment')) {
$html = $this->extractBody($html);
$e = false;
if ($config->get('Core.CollectErrors')) {
$e =& $context->get('ErrorCollector');
}
$new_html = $this->extractBody($html);
if ($e && $new_html != $html) {
$e->send(E_WARNING, 'Lexer: Extracted body');
}
$html = $new_html;
}
// expand entities that aren't the big five

View File

@@ -384,7 +384,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
}
}
if ($value === false) $value = '';
return array($key => $value);
return array($key => $this->parseData($value));
}
// setup loop environment

View File

@@ -165,6 +165,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
$token = $tokens[$t];
//echo '<br>'; printTokens($tokens, $t); printTokens($this->stack);
//flush();
// quick-check: if it's not a tag, no need to process
if (empty($token->is_tag)) {
@@ -221,11 +222,14 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
}
if ($autoclose && $definition->info[$token->name]->wrap) {
// check if this is actually a wrap (mmm wraps!)
// Check if an element can be wrapped by another
// element to make it valid in a context (for
// example, <ul><ul> needs a <li> in between)
$wrapname = $definition->info[$token->name]->wrap;
$wrapdef = $definition->info[$wrapname];
$elements = $wrapdef->child->getAllowedElements($config);
if (isset($elements[$token->name])) {
$parent_elements = $definition->info[$parent->name]->child->getAllowedElements($config);
if (isset($elements[$token->name]) && isset($parent_elements[$wrapname])) {
$newtoken = new HTMLPurifier_Token_Start($wrapname);
$this->insertBefore($newtoken);
$reprocess = true;

View File

@@ -18,8 +18,7 @@ function e($cmd) {
if ($status) exit($status);
}
$php = $_SERVER['argv'][1];
if (!$php) $php = 'php';
$php = empty($_SERVER['argv'][1]) ? 'php' : $_SERVER['argv'][1];
e($php . ' generate-includes.php');
e($php . ' generate-schema-cache.php');

View File

@@ -80,8 +80,9 @@ function get_dependency_lookup($file) {
if (strncmp('class', $line, 5) === 0) {
// The implementation here is fragile and will break if we attempt
// to use interfaces. Beware!
list(, $parent) = explode(' extends ', trim($line, ' {'."\n\r"), 2);
if (empty($parent)) break;
$arr = explode(' extends ', trim($line, ' {'."\n\r"), 2);
if (count($arr) < 2) break;
$parent = $arr[1];
$dep_file = HTMLPurifier_Bootstrap::getPath($parent);
if (!$dep_file) break;
$deps[$dep_file] = true;

View File

@@ -28,13 +28,13 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPositionTest extends HTMLPurifier_AttrD
// reordered due to internal impl details
$this->assertDef('top left', 'left top');
$this->assertDef('top center', 'center top');
$this->assertDef('top center', 'top');
$this->assertDef('top right', 'right top');
$this->assertDef('center left', 'left center');
$this->assertDef('center center', 'center'); // two centers collide
$this->assertDef('center right', 'right center');
$this->assertDef('center left', 'left');
$this->assertDef('center center', 'center');
$this->assertDef('center right', 'right');
$this->assertDef('bottom left', 'left bottom');
$this->assertDef('bottom center', 'center bottom');
$this->assertDef('bottom center', 'bottom');
$this->assertDef('bottom right', 'right bottom');
// more cases from the defined syntax

View File

@@ -8,12 +8,12 @@ class HTMLPurifier_AttrDef_CSS_BackgroundTest extends HTMLPurifier_AttrDefHarnes
$config = HTMLPurifier_Config::createDefault();
$this->def = new HTMLPurifier_AttrDef_CSS_Background($config);
$valid = '#333 url(\'chess.png\') repeat fixed 50% top';
$valid = '#333 url("chess.png") repeat fixed 50% top';
$this->assertDef($valid);
$this->assertDef('url("chess.png") #333 50% top repeat fixed', $valid);
$this->assertDef('url(\'chess.png\') #333 50% top repeat fixed', $valid);
$this->assertDef(
'rgb(34, 56, 33) url(chess.png) repeat fixed top',
'rgb(34,56,33) url(\'chess.png\') repeat fixed top'
'rgb(34,56,33) url("chess.png") repeat fixed top'
);
}

View File

@@ -8,29 +8,29 @@ class HTMLPurifier_AttrDef_CSS_FontFamilyTest extends HTMLPurifier_AttrDefHarnes
$this->def = new HTMLPurifier_AttrDef_CSS_FontFamily();
$this->assertDef('Gill, Helvetica, sans-serif');
$this->assertDef('\'Times New Roman\', serif');
$this->assertDef('"Times New Roman"', "'Times New Roman'");
$this->assertDef('"Times New Roman", serif');
$this->assertDef('\'Times New Roman\'', '"Times New Roman"');
$this->assertDef('01234');
$this->assertDef(',', false);
$this->assertDef('Times New Roman, serif', '\'Times New Roman\', serif');
$this->assertDef($d = "'John\\'s Font'");
$this->assertDef('Times New Roman, serif', '"Times New Roman", serif');
$this->assertDef($d = '"John\'s Font"');
$this->assertDef("John's Font", $d);
$this->assertDef($d = "'\xE5\xAE\x8B\xE4\xBD\x93'");
$this->assertDef($d = "\"\xE5\xAE\x8B\xE4\xBD\x93\"");
$this->assertDef("\xE5\xAE\x8B\xE4\xBD\x93", $d);
$this->assertDef("'\\','f'", "'\\\\', f");
$this->assertDef("'\\01'", "''");
$this->assertDef("'\\20'", "' '");
$this->assertDef("\\0020", "'\\\\0020'");
$this->assertDef("'\\','f'", "\"\\5C \", f");
$this->assertDef("'\\01'", "\"\"");
$this->assertDef("'\\20'", "\" \"");
$this->assertDef("\\0020", "\" \"");
$this->assertDef("'\\000045'", "E");
$this->assertDef("','", false);
$this->assertDef("',' foobar','", "' foobar'");
$this->assertDef("'\\27'", "'\''");
$this->assertDef('"\\22"', "'\"'");
$this->assertDef('"\\""', "'\"'");
$this->assertDef('"\'"', "'\\''");
$this->assertDef("',' foobar','", "\" foobar\"");
$this->assertDef("'\\27'", "\"'\"");
$this->assertDef('"\\22"', "\"\\22 \"");
$this->assertDef('"\\""', "\"\\22 \"");
$this->assertDef('"\'"', "\"'\"");
$this->assertDef("'\\000045a'", "Ea");
$this->assertDef("'\\00045 a'", "Ea");
$this->assertDef("'\\00045 a'", "'E a'");
$this->assertDef("'\\00045 a'", "\"E a\"");
$this->assertDef("'\\\nf'", "f");
}

View File

@@ -11,10 +11,10 @@ class HTMLPurifier_AttrDef_CSS_FontTest extends HTMLPurifier_AttrDefHarness
// hodgepodge of usage cases from W3C spec, but " -> '
$this->assertDef('12px/14px sans-serif');
$this->assertDef('80% sans-serif');
$this->assertDef('x-large/110% \'New Century Schoolbook\', serif');
$this->assertDef('x-large/110% "New Century Schoolbook", serif');
$this->assertDef('bold italic large Palatino, serif');
$this->assertDef('normal small-caps 120%/120% fantasy');
$this->assertDef('300 italic 1.3em/1.7em \'FB Armada\', sans-serif');
$this->assertDef('300 italic 1.3em/1.7em "FB Armada", sans-serif');
$this->assertDef('600 9px Charcoal');
$this->assertDef('600 9px/ 12px Charcoal', '600 9px/12px Charcoal');

View File

@@ -13,14 +13,14 @@ class HTMLPurifier_AttrDef_CSS_ListStyleTest extends HTMLPurifier_AttrDefHarness
$this->assertDef('circle outside');
$this->assertDef('inside');
$this->assertDef('none');
$this->assertDef('url(\'foo.gif\')');
$this->assertDef('circle url(\'foo.gif\') inside');
$this->assertDef('url("foo.gif")');
$this->assertDef('circle url("foo.gif") inside');
// invalid values
$this->assertDef('outside inside', 'outside');
// ordering
$this->assertDef('url(foo.gif) none', 'none url(\'foo.gif\')');
$this->assertDef('url(foo.gif) none', 'none url("foo.gif")');
$this->assertDef('circle lower-alpha', 'circle');
// the spec is ambiguous about what happens in these
// cases, so we're going off the W3C CSS validator

View File

@@ -12,20 +12,16 @@ class HTMLPurifier_AttrDef_CSS_URITest extends HTMLPurifier_AttrDefHarness
// we could be nice but we won't be
$this->assertDef('http://www.example.com/', false);
// no quotes are used, since that's the most widely supported
// syntax
$this->assertDef('url(', false);
$this->assertDef('url(\'\')', true);
$result = "url('http://www.example.com/')";
$this->assertDef('url("")', true);
$result = 'url("http://www.example.com/")';
$this->assertDef('url(http://www.example.com/)', $result);
$this->assertDef('url("http://www.example.com/")', $result);
$this->assertDef("url('http://www.example.com/')", $result);
$this->assertDef(
' url( "http://www.example.com/" ) ', $result);
// escaping
$this->assertDef("url(http://www.example.com/foo,bar\))",
"url('http://www.example.com/foo\,bar\)')");
'url("http://www.example.com/foo,bar)")');
}
}

View File

@@ -25,7 +25,7 @@ class HTMLPurifier_AttrDef_CSSTest extends HTMLPurifier_AttrDefHarness
$this->assertDef('text-transform:capitalize;');
$this->assertDef('background-color:rgb(0,0,255);');
$this->assertDef('background-color:transparent;');
$this->assertDef('background:#333 url(\'chess.png\') repeat fixed 50% top;');
$this->assertDef('background:#333 url("chess.png") repeat fixed 50% top;');
$this->assertDef('color:#F00;');
$this->assertDef('border-top-color:#F00;');
$this->assertDef('border-color:#F00 #FF0;');
@@ -62,7 +62,7 @@ class HTMLPurifier_AttrDef_CSSTest extends HTMLPurifier_AttrDefHarness
$this->assertDef('width:-50px;', false);
$this->assertDef('text-decoration:underline;');
$this->assertDef('font-family:sans-serif;');
$this->assertDef('font-family:Gill, \'Times New Roman\', sans-serif;');
$this->assertDef('font-family:Gill, "Times New Roman", sans-serif;');
$this->assertDef('font:12px serif;');
$this->assertDef('border:1px solid #000;');
$this->assertDef('border-bottom:2em double #FF00FA;');
@@ -73,9 +73,9 @@ class HTMLPurifier_AttrDef_CSSTest extends HTMLPurifier_AttrDefHarness
$this->assertDef('vertical-align:12px;');
$this->assertDef('vertical-align:50%;');
$this->assertDef('table-layout:fixed;');
$this->assertDef('list-style-image:url(\'nice.jpg\');');
$this->assertDef('list-style:disc url(\'nice.jpg\') inside;');
$this->assertDef('background-image:url(\'foo.jpg\');');
$this->assertDef('list-style-image:url("nice.jpg");');
$this->assertDef('list-style:disc url("nice.jpg") inside;');
$this->assertDef('background-image:url("foo.jpg");');
$this->assertDef('background-image:none;');
$this->assertDef('background-repeat:repeat-y;');
$this->assertDef('background-attachment:fixed;');

View File

@@ -81,7 +81,7 @@ class HTMLPurifier_Filter_ExtractStyleBlocksTest extends HTMLPurifier_Harness
function test_cleanCSS_angledBrackets() {
$this->assertCleanCSS(
".class {\nfont-family:'</style>';\n}",
".class {\nfont-family:'\\3C /style\\3E ';\n}"
".class {\nfont-family:\"\\3C /style\\3E \";\n}"
);
}
@@ -99,14 +99,14 @@ class HTMLPurifier_Filter_ExtractStyleBlocksTest extends HTMLPurifier_Harness
function test_cleanCSS_escapeCodes() {
$this->assertCleanCSS(
".class {\nfont-family:'\\3C /style\\3E ';\n}"
".class {\nfont-family:\"\\3C /style\\3E \";\n}"
);
}
function test_cleanCSS_noEscapeCodes() {
$this->config->set('Filter.ExtractStyleBlocks.Escaping', false);
$this->assertCleanCSS(
".class {\nfont-family:'</style>';\n}"
".class {\nfont-family:\"</style>\";\n}"
);
}

View File

@@ -0,0 +1,5 @@
--HTML--
<i><ul></ul></i>
--EXPECT--
<i></i><i></i>
--# vim: et sw=4 sts=4

View File

@@ -7,5 +7,5 @@ URI.MungeResources = true
<img src="http://example.com" style="background-image:url(http://example.com);" alt="example.com" />
--EXPECT--
<a href="/redirect?s=http%3A%2F%2Fexample.com&amp;t=c15354f3953dfec262c55b1403067e0d045a3059&amp;r=&amp;n=a&amp;m=href&amp;p=">Link</a>
<img src="/redirect?s=http%3A%2F%2Fexample.com&amp;t=c15354f3953dfec262c55b1403067e0d045a3059&amp;r=1&amp;n=img&amp;m=src&amp;p=" style="background-image:url('/redirect?s=http%3A%2F%2Fexample.com&amp;t=c15354f3953dfec262c55b1403067e0d045a3059&amp;r=1&amp;n=img&amp;m=style&amp;p=background-image');" alt="example.com" />
<img src="/redirect?s=http%3A%2F%2Fexample.com&amp;t=c15354f3953dfec262c55b1403067e0d045a3059&amp;r=1&amp;n=img&amp;m=src&amp;p=" style="background-image:url(&quot;/redirect?s=http%3A%2F%2Fexample.com&amp;t=c15354f3953dfec262c55b1403067e0d045a3059&amp;r=1&amp;n=img&amp;m=style&amp;p=background-image&quot;);" alt="example.com" />
--# vim: et sw=4 sts=4

View File

@@ -4,5 +4,5 @@ if (!function_exists('iconv')) return true;
Core.Encoding = "Shift_JIS"
Core.EscapeNonASCIICharacters = true
--HTML--
<b style="font-family:'&#165;';">111</b>
<b style="font-family:&quot;&#165;&quot;;">111</b>
--# vim: et sw=4 sts=4

View File

@@ -3,7 +3,7 @@ if (!function_exists('iconv')) return true;
--INI--
Core.Encoding = Shift_JIS
--HTML--
<b style="font-family:'&#165;';">111</b>
<b style="font-family:&quot;&#165;&quot;;">111</b>
--EXPECT--
<b style="font-family:'';">111</b>
<b style="font-family:&quot;&quot;;">111</b>
--# vim: et sw=4 sts=4

View File

@@ -1,5 +1,5 @@
--HTML--
<table background="logo.png"><tr><td>asdf</td></tr></table>
--EXPECT--
<table style="background-image:url('logo.png');"><tr><td>asdf</td></tr></table>
<table style="background-image:url(&quot;logo.png&quot;);"><tr><td>asdf</td></tr></table>
--# vim: et sw=4 sts=4

View File

@@ -13,6 +13,11 @@ class HTMLPurifier_Lexer_DirectLex_ErrorsTest extends HTMLPurifier_ErrorsHarness
$lexer->parseAttributeString($input, $this->config, $this->context);
}
function testExtractBody() {
$this->expectErrorCollection(E_WARNING, 'Lexer: Extracted body');
$this->invoke('<body>foo</body>');
}
function testUnclosedComment() {
$this->expectErrorCollection(E_WARNING, 'Lexer: Unclosed comment');
$this->expectContext('CurrentLine', 1);

View File

@@ -262,6 +262,15 @@ class HTMLPurifier_LexerTest extends HTMLPurifier_Harness
);
}
function test_tokenizeHTML_singleAttribute() {
$this->assertTokenization(
'<br style="&amp;" />',
array(
new HTMLPurifier_Token_Empty('br', array('style' => '&'))
)
);
}
function test_tokenizeHTML_emptyTag() {
$this->assertTokenization(
'<br />',

View File

@@ -118,8 +118,8 @@ class HTMLPurifier_Strategy_MakeWellFormedTest extends HTMLPurifier_StrategyHarn
function testNestedOl() {
$this->assertResult(
'<ol><ol></ol></ol>',
'<ol><li><ol></ol></li></ol>'
'<ol><ol><li>foo</li></ol></ol>',
'<ol><li><ol><li>foo</li></ol></li></ol>'
);
}

11
tests/index.php Executable file → Normal file
View File

@@ -1,4 +1,3 @@
#!/usr/bin/php
<?php
/** @file
@@ -24,6 +23,16 @@
* $test_files) do not have underscores in their names.
*/
// HTML Purifier runs error free on E_STRICT, so if code reports
// errors, we want to know about it.
error_reporting(E_ALL | E_STRICT);
// Because we always want to know about errors, and because SimpleTest
// will notify us about them, logging the errors to stderr is
// counterproductive and in fact the wrong thing when a test case
// exercises an error condition to detect for it.
ini_set('log_errors', false);
define('HTMLPurifierTest', 1);
define('HTMLPURIFIER_SCHEMA_STRICT', true); // validate schemas
chdir(dirname(__FILE__));