1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-08-04 13:18:00 +02:00

Compare commits

..

20 Commits

Author SHA1 Message Date
Edward Z. Yang
9db861e356 Release 2.1.3, merged in 1404 to HEAD.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1444 48356398-32a2-884e-a903-53898d9a118a
2007-11-06 04:34:33 +00:00
Edward Z. Yang
b3f0e6c86c Release 2.1.2, merged in 1368 to HEAD.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1404 48356398-32a2-884e-a903-53898d9a118a
2007-09-03 15:40:43 +00:00
Edward Z. Yang
80c60bb9b5 Release 2.1.0, merged in 1255 to HEAD.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1368 48356398-32a2-884e-a903-53898d9a118a
2007-08-05 02:02:46 +00:00
Edward Z. Yang
503e76081b Revert to 2.0.1, it appears that the 2.1.0 merge was done improperly.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1367 48356398-32a2-884e-a903-53898d9a118a
2007-08-05 01:42:52 +00:00
Edward Z. Yang
678a593e62 Release 2.1.0, merged in 1313 to HEAD.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1352 48356398-32a2-884e-a903-53898d9a118a
2007-08-03 03:20:49 +00:00
Edward Z. Yang
495164e938 Release 2.0.1, merged in 1181 to HEAD.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1255 48356398-32a2-884e-a903-53898d9a118a
2007-06-27 14:30:45 +00:00
Edward Z. Yang
42858ad594 Finish up with a few more files that didn't get updated. Hrmm..
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1181 48356398-32a2-884e-a903-53898d9a118a
2007-06-21 00:53:09 +00:00
Edward Z. Yang
5ecb11f19a Tack on missing basic smoketests.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1180 48356398-32a2-884e-a903-53898d9a118a
2007-06-21 00:42:00 +00:00
Edward Z. Yang
0101311193 Release 2.0.0, merged in 1026 to HEAD.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1179 48356398-32a2-884e-a903-53898d9a118a
2007-06-21 00:36:12 +00:00
Edward Z. Yang
c35eb3e95f Release 1.6.1, merged in 931 to HEAD.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@1026 48356398-32a2-884e-a903-53898d9a118a
2007-05-05 20:49:49 +00:00
Edward Z. Yang
b829e76bbf Release 1.6.0, merged in r875-930.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@931 48356398-32a2-884e-a903-53898d9a118a
2007-04-02 03:09:23 +00:00
Edward Z. Yang
e967680250 Really release 1.5.0.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@876 48356398-32a2-884e-a903-53898d9a118a
2007-03-24 02:19:11 +00:00
Edward Z. Yang
dd2fd06591 Release 1.5.0, merged in r688-867.
- LanguageFactory::instance() declared static
- HTMLModuleManagerTest pass by reference bug fixed, merge back into trunk scheduled

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@869 48356398-32a2-884e-a903-53898d9a118a
2007-03-24 01:04:06 +00:00
Edward Z. Yang
cec7a1c087 Release 1.4.1, merged in 685-687.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@689 48356398-32a2-884e-a903-53898d9a118a
2007-01-21 21:54:03 +00:00
Edward Z. Yang
c2d3d5b859 Release 1.4.0.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@682 48356398-32a2-884e-a903-53898d9a118a
2007-01-21 17:45:33 +00:00
Edward Z. Yang
9a84e11f34 Merge in r657-674, prompted by near release of 1.4.0.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@675 48356398-32a2-884e-a903-53898d9a118a
2007-01-21 16:07:36 +00:00
Edward Z. Yang
37ea1673dd Merge in r649-656, prompted by changing two of Encoder's functions to static.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@657 48356398-32a2-884e-a903-53898d9a118a
2007-01-19 02:28:53 +00:00
Edward Z. Yang
5395d8b4bd Renamed remotely
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/strict@649 48356398-32a2-884e-a903-53898d9a118a
2007-01-16 22:03:54 +00:00
Edward Z. Yang
c980e76197 Moved remotely
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/trunk-strict@648 48356398-32a2-884e-a903-53898d9a118a
2007-01-16 22:03:00 +00:00
Edward Z. Yang
2bf912d528 Commit strict version of HTML Purifier.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/trunk-strict@647 48356398-32a2-884e-a903-53898d9a118a
2007-01-16 21:59:29 +00:00
106 changed files with 489 additions and 1886 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 = 2.1.5
PROJECT_NUMBER = 2.1.3
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
@@ -539,8 +539,7 @@ EXCLUDE_PATTERNS = */tests/* \
*/maintenance/* \
*/smoketests/* \
*/library/standalone/* \
*/.svn* \
*/conf/*
*/.svn*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the output.

10
INSTALL
View File

@@ -14,17 +14,15 @@ basic sanity checks to get the most out of this library.
---------------------------------------------------------------------------
1. Compatibility
THIS IS A DEPRECATED PHP4 VERSION OF HTML PURIFIER.
If you are running PHP5, please go to http://htmlpurifier.org to download
the latest version. This version of HTML Purifier is only actively tested
from PHP 4.3.7 to PHP 5.0.5. Essential security will be released for this branch
HTML Purifier works in both PHP 4 and PHP 5, and is actively tested from
PHP 4.3.7 and up (see tests/multitest.php for specific versions). It has
no core dependencies with other libraries. PHP 4 support will be
deprecated on December 31, 2007, at which time only essential security
fixes will be issued for the PHP 4 version until August 8, 2008.
These optional extensions can enhance the capabilities of HTML Purifier:
* iconv : Converts text to and from non-UTF-8 encodings
* bcmath : Used for unit conversion and imagecrash protection
* tidy : Used for pretty-printing HTML

60
NEWS
View File

@@ -9,64 +9,6 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Internal change
==========================
ERRATA
- PH5P is seriously broken here; it can result in fatal errors and exceptions.
If you desire to use it, please use it with the latest, PHP5-only version of
HTML Purifier.
2.1.5, released 2008-06-19
! More robust imagecrash protection with height/width CSS with %CSS.MaxImgLength,
and height/width HTML with %HTML.MaxImgLength.
- AttrValidator operations are now atomic; updates to attributes are not
manifest in token until end of operations. This prevents naughty internal
code from directly modifying CurrentToken when they're not supposed to.
- Percent encoding checks enabled for URI query and fragment
- Disable percent height/width attributes for img
- Fix stray backslashes in font-family; CSS Unicode character escapes are
now properly resolved (although *only* in font-family).
- Improve parseCDATA algorithm to take into account newline normalization
- Account for browser confusion between Yen character and backslash in
Shift_JIS encoding. This fix generalizes to any other encoding which is not
a strict superset of printable ASCII.
- Improved adherence to Unicode by checking for non-character codepoints.
Thanks Geoffrey Sneddon for reporting. This may result in degraded
performance for extremely large inputs.
- Allow CSS property-value pair ''text-decoration: none''
. Added HTMLPurifier_UnitConverter and HTMLPurifier_Length for convenient
handling of CSS-style lengths. HTMLPurifier_AttrDef_CSS_Length now uses
this class.
. API of HTMLPurifier_AttrDef_CSS_Length changed from __construct($disable_negative)
to __construct($min, $max). __construct(true) is equivalent to
__construct('0'). (replace __construct with HTMLPurifier_AttrDef_CSS_Length)
. Added HTMLPurifier_AttrDef_Switch class
. Rename HTMLPurifier_HTMLModule_Tidy->construct() to setup() and bubble method
up inheritance hierarchy to HTMLPurifier_HTMLModule. All HTMLModules
get this called with the configuration object. All modules now
use this rather than __construct(), although legacy code using constructors
will still work--the new format, however, lets modules access the
configuration object for HTML namespace dependant tweaks.
. AttrDef_HTML_Pixels now takes a single construction parameter, pixels.
2.1.4, released 2008-05-18
! DefinitionCacheFactory now can register new implementations
! CSS properties are now case-insensitive
! Encoder optimized with valid UTF-8 input
! HTML Purifier's URI handling is a lot more robust, with much stricter
validation checks and better percent encoding handling.
- Colors missing # but in hex form will be corrected
- CSS Number algorithm improved
- Autoclose now operates iteratively, i.e. <span><span><div> now has
both span tags closed.
- Fix bug with trusted script handling in libxml versions later than 2.6.28.
- Fix bug in comment parsing with DirectLex
- Fix bug with rgb(0, 1, 2) color syntax with spaces inside shorthand syntax
- HTMLPurifier_HTMLDefinition->addAttribute can now be called multiple times
on the same element without emitting errors.
- Iconv uses set_error_handler instead of shut-up operator
- Add protection against imagecrash attack with CSS height/width
- HTMLPurifier::getInstance() renamed to HTMLPurifier::instance() for consistency
- Fixed bug with fallback languages in LanguageFactory
2.1.3, released 2007-11-05
! tests/multitest.php allows you to test multiple versions by running
tests/index.php through multiple interpreters using `phpv` shell
@@ -356,6 +298,8 @@ ERRATA
%Attr.IDBlacklistRegexp
- Error messages are emitted when you attempt to "allow" elements or
attributes that HTML Purifier does not support
- Fix segfault in unit test. The problem is not very reproduceable and
I don't know what causes it, but a six line patch fixed it.

1
TODO
View File

@@ -1,4 +1,3 @@
TODO List
= KEY ====================

View File

@@ -1 +1 @@
2.1.5
2.1.3

View File

@@ -1,7 +1,6 @@
Security and bugfix release 2.1.5 is a backport that fixes two vulnerabilities
related to CSS, one of which only occurs under Shift_JIS. It also improves
imagecrash protection (percent CSS width and height is now disabled for
images, and you can control the bounds with %CSS.MaxImgLength and
%HTML.MaxImgLength). Finally, there are number of bug fixes, most notably
support for text-decoration: none, improved adherence to Unicode and increased
percent encoding checks.
Stability release 2.1.3 fixes a slew of minor bugs found in HTML Purifier,
and also includes some internal code enhancements and refactorings.
Notably, tests/multitest.php automates testing in multiple versions,
fatal AttrDef_URI_Email error fixed, blockquote contents are more lenient
in HTML 4.01 Strict and fatal errors involving ID tags in img tags were
fixed.

View File

@@ -22,7 +22,7 @@
*/
/*
HTML Purifier 2.1.5 - Standards Compliant HTML Filtering
HTML Purifier 2.1.3 - Standards Compliant HTML Filtering
Copyright (C) 2006-2007 Edward Z. Yang
This library is free software; you can redistribute it and/or
@@ -83,7 +83,7 @@ since 2.0.0.
class HTMLPurifier
{
var $version = '2.1.5';
var $version = '2.1.3';
var $config;
var $filters = array();
@@ -213,10 +213,10 @@ class HTMLPurifier
* @param $prototype Optional prototype HTMLPurifier instance to
* overload singleton with.
*/
function &instance($prototype = null) {
static function &getInstance($prototype = null) {
static $htmlpurifier;
if (!$htmlpurifier || $prototype) {
if (is_a($prototype, 'HTMLPurifier')) {
if ($prototype instanceof HTMLPurifier) {
$htmlpurifier = $prototype;
} elseif ($prototype) {
$htmlpurifier = new HTMLPurifier($prototype);
@@ -227,9 +227,6 @@ class HTMLPurifier
return $htmlpurifier;
}
function &getInstance($prototype = null) {
return HTMLPurifier::instance($prototype);
}
}

View File

@@ -54,15 +54,18 @@ class HTMLPurifier_AttrDef
*
* @warning This processing is inconsistent with XML's whitespace handling
* as specified by section 3.3.3 and referenced XHTML 1.0 section
* 4.7. However, note that we are NOT necessarily
* parsing XML, thus, this behavior may still be correct. We
* assume that newlines have been normalized.
* 4.7. Compliant processing requires all line breaks normalized
* to "\n", so the fix is not as simple as fixing it in this
* function. Trim and whitespace collapsing are supposed to only
* occur in NMTOKENs. However, note that we are NOT necessarily
* parsing XML, thus, this behavior may still be correct.
*
* @public
*/
function parseCDATA($string) {
$string = trim($string);
$string = str_replace(array("\n", "\t", "\r"), ' ', $string);
$string = str_replace("\n", '', $string);
$string = str_replace(array("\r", "\t"), ' ', $string);
return $string;
}
@@ -79,13 +82,5 @@ class HTMLPurifier_AttrDef
return $this;
}
/**
* Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
* properly. THIS IS A HACK!
*/
function mungeRgb($string) {
return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
}
}

View File

@@ -38,20 +38,7 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
list($property, $value) = explode(':', $declaration, 2);
$property = trim($property);
$value = trim($value);
$ok = false;
do {
if (isset($definition->info[$property])) {
$ok = true;
break;
}
if (ctype_lower($property)) break;
$property = strtolower($property);
if (isset($definition->info[$property])) {
$ok = true;
break;
}
} while(0);
if (!$ok) continue;
if (!isset($definition->info[$property])) continue;
// inefficient call, since the validator will do this again
if (strtolower(trim($value)) !== 'inherit') {
// inherit works for everything (but only on the base property)

View File

@@ -31,9 +31,6 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
$string = $this->parseCDATA($string);
if ($string === '') return false;
// munge rgb() decl if necessary
$string = $this->mungeRgb($string);
// assumes URI doesn't have spaces in it
$bits = explode(' ', strtolower($string)); // bits to process

View File

@@ -22,7 +22,7 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
function validate($string, $config, &$context) {
$string = $this->parseCDATA($string);
$string = $this->mungeRgb($string);
// we specifically will not support rgb() syntax with spaces
$bits = explode(' ', $string);
$done = array(); // segments we've finished
$ret = ''; // return value

View File

@@ -39,13 +39,20 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
if ($colors === null) $colors = $config->get('Core', 'ColorKeywords');
$color = trim($color);
if ($color === '') return false;
if (!$color) return false;
$lower = strtolower($color);
if (isset($colors[$lower])) return $colors[$lower];
if (strpos($color, 'rgb(') !== false) {
if ($color[0] === '#') {
// hexadecimal handling
$hex = substr($color, 1);
$length = strlen($hex);
if ($length !== 3 && $length !== 6) return false;
if (!ctype_xdigit($hex)) return false;
} else {
// rgb literal handling
if (strpos($color, 'rgb(')) return false;
$length = strlen($color);
if (strpos($color, ')') !== $length - 1) return false;
$triad = substr($color, 4, $length - 4 - 1);
@@ -83,17 +90,6 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
}
$new_triad = implode(',', $new_parts);
$color = "rgb($new_triad)";
} else {
// hexadecimal handling
if ($color[0] === '#') {
$hex = substr($color, 1);
} else {
$hex = $color;
$color = '#' . $color;
}
$length = strlen($hex);
if ($length !== 3 && $length !== 6) return false;
if (!ctype_xdigit($hex)) return false;
}
return $color;

View File

@@ -1,26 +0,0 @@
<?php
/**
* Decorator which enables CSS properties to be disabled for specific elements.
*/
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
{
var $def, $element;
/**
* @param $def Definition to wrap
* @param $element Element to deny
*/
function HTMLPurifier_AttrDef_CSS_DenyElementDecorator(&$def, $element) {
$this->def =& $def;
$this->element = $element;
}
/**
* Checks if CurrentToken is set and equal to $this->element
*/
function validate($string, $config, $context) {
$token = $context->get('CurrentToken', true);
if ($token && $token->name == $this->element) return false;
return $this->def->validate($string, $config, $context);
}
}

View File

@@ -19,6 +19,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
'cursive' => true
);
$string = $this->parseCDATA($string);
// assume that no font names contain commas in them
$fonts = explode(',', $string);
$final = '';
@@ -37,40 +38,13 @@ 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;
// double-backslash processing is buggy
$font = str_replace("\\$quote", $quote, $font); // de-escape quote
$font = str_replace("\\\n", "\n", $font); // de-escape newlines
}
// $font is a pure representation of the font name
if (ctype_alnum($font) && $font !== '') {
if (ctype_alnum($font)) {
// very simple font, allow it in unharmed
$final .= $font . ', ';
continue;
@@ -79,8 +53,8 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
// complicated font, requires quoting
// armor single quotes and new lines
$font = str_replace("\\", "\\\\", $font);
$font = str_replace("'", "\\'", $font);
$font = str_replace("\n", "\\\n", $font);
$final .= "'$font', ";
}
$final = rtrim($final, ', ');

View File

@@ -1,7 +1,7 @@
<?php
require_once 'HTMLPurifier/Length.php';
require_once 'HTMLPurifier/UnitConverter.php';
require_once 'HTMLPurifier/AttrDef.php';
require_once 'HTMLPurifier/AttrDef/CSS/Number.php';
/**
* Represents a Length as defined by CSS.
@@ -9,40 +9,46 @@ require_once 'HTMLPurifier/UnitConverter.php';
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
{
var $min, $max;
/**
* Valid unit lookup table.
* @warning The code assumes all units are two characters long. Be careful
* if we have to change this behavior!
*/
var $units = array('em' => true, 'ex' => true, 'px' => true, 'in' => true,
'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true);
/**
* Instance of HTMLPurifier_AttrDef_Number to defer number validation to
*/
var $number_def;
/**
* @param HTMLPurifier_Length $max Minimum length, or null for no bound. String is also acceptable.
* @param HTMLPurifier_Length $max Maximum length, or null for no bound. String is also acceptable.
* @param $non_negative Bool indication whether or not negative values are
* allowed.
*/
function HTMLPurifier_AttrDef_CSS_Length($min = null, $max = null) {
$this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
$this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
function HTMLPurifier_AttrDef_CSS_Length($non_negative = false) {
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
}
function validate($string, $config, $context) {
$string = $this->parseCDATA($string);
function validate($length, $config, &$context) {
// Optimizations
if ($string === '') return false;
if ($string === '0') return '0';
if (strlen($string) === 1) return false;
$length = $this->parseCDATA($length);
if ($length === '') return false;
if ($length === '0') return '0';
$strlen = strlen($length);
if ($strlen === 1) return false; // impossible!
$length = HTMLPurifier_Length::make($string);
if (!$length->isValid()) return false;
// we assume all units are two characters
$unit = substr($length, $strlen - 2);
if (!ctype_lower($unit)) $unit = strtolower($unit);
$number = substr($length, 0, $strlen - 2);
if ($this->min) {
$c = $length->compareTo($this->min);
if ($c === false) return false;
if ($c < 0) return false;
}
if ($this->max) {
$c = $length->compareTo($this->max);
if ($c === false) return false;
if ($c > 0) return false;
}
if (!isset($this->units[$unit])) return false;
$number = $this->number_def->validate($number, $config, $context);
if ($number === false) return false;
return $number . $unit;
return $length->toString();
}
}

View File

@@ -18,11 +18,6 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
$this->non_negative = $non_negative;
}
/**
* @warning Some contexts do not pass $config, $context. These
* variables should not be used without checking HTMLPurifier_Length.
* This might not work properly in PHP4.
*/
function validate($number, $config, &$context) {
$number = $this->parseCDATA($number);

View File

@@ -15,13 +15,10 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
static $allowed_values = array(
'line-through' => true,
'overline' => true,
'underline' => true,
'underline' => true
);
$string = strtolower($this->parseCDATA($string));
if ($string === 'none') return $string;
$parts = explode(' ', $string);
$final = '';
foreach ($parts as $part) {

View File

@@ -8,12 +8,6 @@ require_once 'HTMLPurifier/AttrDef.php';
class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
{
var $max;
function HTMLPurifier_AttrDef_HTML_Pixels($max = null) {
$this->max = $max;
}
function validate($string, $config, &$context) {
$string = trim($string);
@@ -32,18 +26,11 @@ class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
// crash operating systems, see <http://ha.ckers.org/imagecrash.html>
// WARNING, above link WILL crash you if you're using Windows
if ($this->max !== null && $int > $this->max) return (string) $this->max;
if ($int > 1200) return '1200';
return (string) $int;
}
function make($string) {
if ($string === '') $max = null;
else $max = (int) $string;
$class = get_class($this);
return new $class($max);
}
}

View File

@@ -1,32 +0,0 @@
<?php
/**
* Decorator that, depending on a token, switches between two definitions.
*/
class HTMLPurifier_AttrDef_Switch
{
var $tag;
var $withTag, $withoutTag;
/**
* @param string $tag Tag name to switch upon
* @param HTMLPurifier_AttrDef $with_tag Call if token matches tag
* @param HTMLPurifier_AttrDef $without_tag Call if token doesn't match, or there is no token
*/
function HTMLPurifier_AttrDef_Switch($tag, $with_tag, $without_tag) {
$this->tag = $tag;
$this->withTag = $with_tag;
$this->withoutTag = $without_tag;
}
function validate($string, $config, $context) {
$token = $context->get('CurrentToken', true);
if (!$token || $token->name !== $this->tag) {
return $this->withoutTag->validate($string, $config, $context);
} else {
return $this->withTag->validate($string, $config, $context);
}
}
}

View File

@@ -68,7 +68,7 @@ HTMLPurifier_ConfigSchema::define(
class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
{
var $parser;
var $parser, $percentEncoder;
var $embedsResource;
/**
@@ -76,6 +76,7 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
*/
function HTMLPurifier_AttrDef_URI($embeds_resource = false) {
$this->parser = new HTMLPurifier_URIParser();
$this->percentEncoder = new HTMLPurifier_PercentEncoder();
$this->embedsResource = (bool) $embeds_resource;
}
@@ -83,7 +84,9 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
if ($config->get('URI', 'Disable')) return false;
// initial operations
$uri = $this->parseCDATA($uri);
$uri = $this->percentEncoder->normalize($uri);
// parse the URI
$uri = $this->parser->parse($uri);
@@ -119,6 +122,13 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
$context->destroy('EmbeddedURI');
if (!$ok) return false;
// munge scheme off if necessary (this must be last)
if (!is_null($uri->scheme) && is_null($uri->host)) {
if ($uri_def->defaultScheme == $uri->scheme) {
$uri->scheme = null;
}
}
// back to string
$result = $uri->toString();

View File

@@ -40,23 +40,11 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
$ipv4 = $this->ipv4->validate($string, $config, $context);
if ($ipv4 !== false) return $ipv4;
// A regular domain name.
// validate a domain name here, do filtering, etc etc etc
// This breaks I18N domain names, but we don't have proper IRI support,
// so force users to insert Punycode. If there's complaining we'll
// try to fix things into an international friendly form.
// The productions describing this are:
$a = '[a-z]'; // alpha
$an = '[a-z0-9]'; // alphanum
$and = '[a-z0-9-]'; // alphanum | "-"
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
$domainlabel = "$an($and*$an)?";
// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
$toplabel = "$a($and*$an)?";
// hostname = *( domainlabel "." ) toplabel [ "." ]
$match = preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string);
if (!$match) return false;
// We could use this, but it would break I18N domain names
//$match = preg_match('/^[a-z0-9][\w\-\.]*[a-z0-9]$/i', $string);
//if (!$match) return false;
return $string;
}

View File

@@ -40,8 +40,8 @@ class HTMLPurifier_AttrValidator
// DEFINITION CALL
$d_defs = $definition->info_global_attr;
// don't update token until the very end, to ensure an atomic update
$attr = $token->attr;
// reference attributes for easy manipulation
$attr =& $token->attr;
// do global transformations (pre)
// nothing currently utilizes this
@@ -136,8 +136,6 @@ class HTMLPurifier_AttrValidator
if ($e && ($attr != $o)) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
}
$token->attr = $attr;
// destroy CurrentToken if we made it ourselves
if (!$current_token) $context->destroy('CurrentToken');

View File

@@ -7,7 +7,6 @@ require_once 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
require_once 'HTMLPurifier/AttrDef/CSS/Border.php';
require_once 'HTMLPurifier/AttrDef/CSS/Color.php';
require_once 'HTMLPurifier/AttrDef/CSS/Composite.php';
require_once 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
require_once 'HTMLPurifier/AttrDef/CSS/Font.php';
require_once 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
require_once 'HTMLPurifier/AttrDef/CSS/Length.php';
@@ -17,7 +16,6 @@ require_once 'HTMLPurifier/AttrDef/CSS/Percentage.php';
require_once 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
require_once 'HTMLPurifier/AttrDef/CSS/URI.php';
require_once 'HTMLPurifier/AttrDef/Enum.php';
require_once 'HTMLPurifier/AttrDef/Switch.php';
HTMLPurifier_ConfigSchema::define(
'CSS', 'DefinitionRev', 1, 'int', '
@@ -28,20 +26,6 @@ HTMLPurifier_ConfigSchema::define(
</p>
');
HTMLPurifier_ConfigSchema::define(
'CSS', 'MaxImgLength', '1200px', 'string/null', '
<p>
This parameter sets the maximum allowed length on <code>img</code> tags,
effectively the <code>width</code> and <code>height</code> properties.
Only absolute units of measurement (in, pt, pc, mm, cm) and pixels (px) are allowed. This is
in place to prevent imagecrash attacks, disable with null at your own risk.
This directive is similar to %HTML.MaxImgLength, and both should be
concurrently edited, although there are
subtle differences in the input format (the CSS max is a number with
a unit).
</p>
');
/**
* Defines allowed CSS attributes and what their values are.
* @see HTMLPurifier_HTMLDefinition
@@ -132,7 +116,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
$this->info['border-left-width'] =
$this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')),
new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
new HTMLPurifier_AttrDef_CSS_Length(true) //disallow negative
));
$this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
@@ -158,7 +142,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
$this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_Enum(array('normal')),
new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Length(true),
new HTMLPurifier_AttrDef_CSS_Percentage(true)
));
@@ -180,7 +164,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
$this->info['padding-bottom'] =
$this->info['padding-left'] =
$this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Length(true),
new HTMLPurifier_AttrDef_CSS_Percentage(true)
));
@@ -191,25 +175,13 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
new HTMLPurifier_AttrDef_CSS_Percentage()
));
$trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length('0'),
$this->info['width'] =
$this->info['height'] =
new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length(true),
new HTMLPurifier_AttrDef_CSS_Percentage(true),
new HTMLPurifier_AttrDef_Enum(array('auto'))
));
$max = $config->get('CSS', 'MaxImgLength');
$this->info['width'] =
$this->info['height'] =
$max === null ?
$trusted_wh :
new HTMLPurifier_AttrDef_Switch('img',
// For img tags:
new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length('0', $max),
new HTMLPurifier_AttrDef_Enum(array('auto'))
)),
// For everyone else:
$trusted_wh
);
$this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();

View File

@@ -42,7 +42,7 @@ class HTMLPurifier_Config
/**
* HTML Purifier's version
*/
var $version = '2.1.5';
var $version = '2.1.3';
/**
* Two-level associative array of configuration directives
@@ -99,11 +99,8 @@ class HTMLPurifier_Config
* or a string filename of an ini file.
* @return Configured HTMLPurifier_Config object
*/
function create($config) {
if (is_a($config, 'HTMLPurifier_Config')) {
// pass-through
return $config;
}
static function create($config) {
if ($config instanceof HTMLPurifier_Config) return $config;
$ret = HTMLPurifier_Config::createDefault();
if (is_string($config)) $ret->loadIni($config);
elseif (is_array($config)) $ret->loadArray($config);
@@ -115,7 +112,7 @@ class HTMLPurifier_Config
* @static
* @return Default HTMLPurifier_Config object.
*/
function createDefault() {
static function createDefault() {
$definition =& HTMLPurifier_ConfigSchema::instance();
$config = new HTMLPurifier_Config($definition);
return $config;
@@ -368,7 +365,7 @@ class HTMLPurifier_Config
* @param $allowed List of allowed namespaces/directives
* @static
*/
function getAllowedDirectivesForForm($allowed) {
static function getAllowedDirectivesForForm($allowed) {
$schema = HTMLPurifier_ConfigSchema::instance();
if ($allowed !== true) {
if (is_string($allowed)) $allowed = array($allowed);
@@ -413,7 +410,7 @@ class HTMLPurifier_Config
* @param $mq_fix Boolean whether or not to enable magic quotes fix
* @static
*/
function loadArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
static function loadArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
$ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix);
$config = HTMLPurifier_Config::create($ret);
return $config;
@@ -433,7 +430,7 @@ class HTMLPurifier_Config
* strict parts of HTMLPurifier_Config
* @static
*/
function prepareArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
static function prepareArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
$array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
$mq = get_magic_quotes_gpc() && $mq_fix;

View File

@@ -82,7 +82,7 @@ class HTMLPurifier_ConfigSchema {
* Retrieves an instance of the application-wide configuration definition.
* @static
*/
function &instance($prototype = null) {
static function &instance($prototype = null) {
static $instance;
if ($prototype !== null) {
$instance = $prototype;
@@ -104,7 +104,7 @@ class HTMLPurifier_ConfigSchema {
* HTMLPurifier_DirectiveDef::$type for allowed values
* @param $description Description of directive for documentation
*/
function define($namespace, $name, $default, $type, $description) {
static function define($namespace, $name, $default, $type, $description) {
$def =& HTMLPurifier_ConfigSchema::instance();
// basic sanity checks
@@ -177,7 +177,7 @@ class HTMLPurifier_ConfigSchema {
* @param $namespace Namespace's name
* @param $description Description of the namespace
*/
function defineNamespace($namespace, $description) {
static function defineNamespace($namespace, $description) {
$def =& HTMLPurifier_ConfigSchema::instance();
if (HTMLPURIFIER_SCHEMA_STRICT) {
if (isset($def->info[$namespace])) {
@@ -212,7 +212,7 @@ class HTMLPurifier_ConfigSchema {
* @param $alias Name of aliased value
* @param $real Value aliased value will be converted into
*/
function defineValueAliases($namespace, $name, $aliases) {
static function defineValueAliases($namespace, $name, $aliases) {
$def =& HTMLPurifier_ConfigSchema::instance();
if (HTMLPURIFIER_SCHEMA_STRICT && !isset($def->info[$namespace][$name])) {
trigger_error('Cannot set value alias for non-existant directive',
@@ -245,7 +245,7 @@ class HTMLPurifier_ConfigSchema {
* @param $name Name of directive
* @param $allowed_values Arraylist of allowed values
*/
function defineAllowedValues($namespace, $name, $allowed_values) {
static function defineAllowedValues($namespace, $name, $allowed_values) {
$def =& HTMLPurifier_ConfigSchema::instance();
if (HTMLPURIFIER_SCHEMA_STRICT && !isset($def->info[$namespace][$name])) {
trigger_error('Cannot define allowed values for undefined directive',
@@ -285,7 +285,7 @@ class HTMLPurifier_ConfigSchema {
* @param $new_namespace
* @param $new_name Directive that the alias will be to
*/
function defineAlias($namespace, $name, $new_namespace, $new_name) {
static function defineAlias($namespace, $name, $new_namespace, $new_name) {
$def =& HTMLPurifier_ConfigSchema::instance();
if (HTMLPURIFIER_SCHEMA_STRICT) {
if (!isset($def->info[$namespace])) {
@@ -428,7 +428,7 @@ class HTMLPurifier_ConfigSchema {
*/
function isError($var) {
if (!is_object($var)) return false;
if (!is_a($var, 'HTMLPurifier_Error')) return false;
if (!($var instanceof HTMLPurifier_Error)) return false;
return true;
}
}

View File

@@ -120,9 +120,6 @@ class HTMLPurifier_DefinitionCache
/**
* Clears all expired (older version or revision) objects from cache
* @note Be carefuly implementing this method as flush. Flush must
* not interfere with other Definition types, and cleanup()
* should not be repeatedly called by userland code.
*/
function cleanup($config) {
trigger_error('Cannot call abstract method', E_USER_ERROR);

View File

@@ -1,7 +1,6 @@
<?php
require_once 'HTMLPurifier/DefinitionCache.php';
require_once 'HTMLPurifier/DefinitionCache/Serializer.php';
HTMLPurifier_ConfigSchema::define(
'Cache', 'DefinitionImpl', 'Serializer', 'string/null', '
@@ -11,6 +10,10 @@ to disable caching (not recommended, as you will see a definite
performance degradation). This directive has been available since 2.0.0.
');
HTMLPurifier_ConfigSchema::defineAllowedValues(
'Cache', 'DefinitionImpl', array('Serializer')
);
HTMLPurifier_ConfigSchema::defineAlias(
'Core', 'DefinitionCache',
'Cache', 'DefinitionImpl'
@@ -24,7 +27,6 @@ class HTMLPurifier_DefinitionCacheFactory
{
var $caches = array('Serializer' => array());
var $implementations = array();
var $decorators = array();
/**
@@ -38,7 +40,7 @@ class HTMLPurifier_DefinitionCacheFactory
* Retrieves an instance of global definition cache factory.
* @static
*/
function &instance($prototype = null) {
static function &instance($prototype = null) {
static $instance;
if ($prototype !== null) {
$instance = $prototype;
@@ -49,21 +51,14 @@ class HTMLPurifier_DefinitionCacheFactory
return $instance;
}
/**
* Registers a new definition cache object
* @param $short Short name of cache object, for reference
* @param $long Full class name of cache object, for construction
*/
function register($short, $long) {
$this->implementations[$short] = $long;
}
/**
* Factory method that creates a cache object based on configuration
* @param $name Name of definitions handled by cache
* @param $config Instance of HTMLPurifier_Config
*/
function &create($type, $config) {
// only one implementation as for right now, $config will
// be used to determine implementation
$method = $config->get('Cache', 'DefinitionImpl');
if ($method === null) {
$null = new HTMLPurifier_DefinitionCache_Null($type);
@@ -72,17 +67,7 @@ class HTMLPurifier_DefinitionCacheFactory
if (!empty($this->caches[$method][$type])) {
return $this->caches[$method][$type];
}
if (
isset($this->implementations[$method]) &&
class_exists($class = $this->implementations[$method])
) {
$cache = new $class($type);
} else {
if ($method != 'Serializer') {
trigger_error("Unrecognized DefinitionCache $method, using Serializer instead", E_USER_WARNING);
}
$cache = new HTMLPurifier_DefinitionCache_Serializer($type);
}
foreach ($this->decorators as $decorator) {
$new_cache = $decorator->decorate($cache);
// prevent infinite recursion in PHP 4

View File

@@ -82,7 +82,7 @@ class HTMLPurifier_ElementDef
/**
* List of the names of required attributes this element has. Dynamically
* populated by HTMLPurifier_HTMLDefinition::getElement
* populated.
* @public
*/
var $required_attr = array();
@@ -110,7 +110,7 @@ class HTMLPurifier_ElementDef
* Low-level factory constructor for creating new standalone element defs
* @static
*/
function create($safe, $content_model, $content_model_type, $attr) {
static function create($safe, $content_model, $content_model_type, $attr) {
$def = new HTMLPurifier_ElementDef();
$def->safe = (bool) $safe;
$def->content_model = $content_model;

View File

@@ -62,12 +62,6 @@ class HTMLPurifier_Encoder
trigger_error('Cannot instantiate encoder, call methods statically', E_USER_ERROR);
}
/**
* Error-handler that mutes errors, alternative to shut-up operator.
*/
function muteErrorHandler() {}
/**
/**
* Cleans a UTF-8 string for well-formedness and SGML validity
*
@@ -94,15 +88,28 @@ class HTMLPurifier_Encoder
* would need that, and I'm probably not going to implement them.
* Once again, PHP 6 should solve all our problems.
*/
function cleanUTF8($str, $force_php = false) {
static function cleanUTF8($str, $force_php = false) {
// UTF-8 validity is checked since PHP 4.3.5
// This is an optimization: if the string is already valid UTF-8, no
// need to do PHP stuff. 99% of the time, this will be the case.
// The regexp matches the XML char production, as well as well as excluding
// non-SGML codepoints U+007F to U+009F
if (preg_match('/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/Du', $str)) {
return $str;
static $non_sgml_chars = array();
if (empty($non_sgml_chars)) {
for ($i = 0; $i <= 31; $i++) {
// non-SGML ASCII chars
// save \r, \t and \n
if ($i == 9 || $i == 13 || $i == 10) continue;
$non_sgml_chars[chr($i)] = '';
}
for ($i = 127; $i <= 159; $i++) {
$non_sgml_chars[HTMLPurifier_Encoder::unichr($i)] = '';
}
}
static $iconv = null;
if ($iconv === null) $iconv = function_exists('iconv');
if ($iconv && !$force_php) {
// do the shortcut way
$str = @iconv('UTF-8', 'UTF-8//IGNORE', $str);
return strtr($str, $non_sgml_chars);
}
$mState = 0; // cached expected number of octets after the current octet
@@ -213,17 +220,7 @@ class HTMLPurifier_Encoder
) {
} elseif (0xFEFF != $mUcs4 && // omit BOM
// check for valid Char unicode codepoints
(
0x9 == $mUcs4 ||
0xA == $mUcs4 ||
0xD == $mUcs4 ||
(0x20 <= $mUcs4 && 0x7E >= $mUcs4) ||
// 7F-9F is not strictly prohibited by XML,
// but it is non-SGML, and thus we don't allow it
(0xA0 <= $mUcs4 && 0xD7FF >= $mUcs4) ||
(0x10000 <= $mUcs4 && 0x10FFFF >= $mUcs4)
)
!($mUcs4 >= 128 && $mUcs4 <= 159) // omit non-SGML
) {
$out .= $char;
}
@@ -274,7 +271,7 @@ class HTMLPurifier_Encoder
// | 00000000 | 00010000 | 11111111 | 11111111 | Defined upper limit of legal scalar codes
// +----------+----------+----------+----------+
function unichr($code) {
static function unichr($code) {
if($code > 1114111 or $code < 0 or
($code >= 55296 and $code <= 57343) ) {
// bits are set outside the "valid" range as defined
@@ -315,24 +312,15 @@ class HTMLPurifier_Encoder
* Converts a string to UTF-8 based on configuration.
* @static
*/
function convertToUTF8($str, $config, &$context) {
$encoding = $config->get('Core', 'Encoding');
if ($encoding === 'utf-8') return $str;
static function convertToUTF8($str, $config, &$context) {
static $iconv = null;
if ($iconv === null) $iconv = function_exists('iconv');
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
$encoding = $config->get('Core', 'Encoding');
if ($encoding === 'utf-8') return $str;
if ($iconv && !$config->get('Test', 'ForceNoIconv')) {
$str = iconv($encoding, 'utf-8//IGNORE', $str);
// If the string is bjorked by Shift_JIS or a similar encoding
// that doesn't support all of ASCII, convert the naughty
// characters to their true byte-wise ASCII/UTF-8 equivalents.
$str = strtr($str, HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding));
restore_error_handler();
return $str;
return @iconv($encoding, 'utf-8//IGNORE', $str);
} elseif ($encoding === 'iso-8859-1') {
$str = utf8_encode($str);
restore_error_handler();
return $str;
return @utf8_encode($str);
}
trigger_error('Encoding not supported', E_USER_ERROR);
}
@@ -343,32 +331,18 @@ class HTMLPurifier_Encoder
* @note Currently, this is a lossy conversion, with unexpressable
* characters being omitted.
*/
function convertFromUTF8($str, $config, &$context) {
$encoding = $config->get('Core', 'Encoding');
if ($encoding === 'utf-8') return $str;
static function convertFromUTF8($str, $config, &$context) {
static $iconv = null;
if ($iconv === null) $iconv = function_exists('iconv');
if ($escape = $config->get('Core', 'EscapeNonASCIICharacters')) {
$encoding = $config->get('Core', 'Encoding');
if ($encoding === 'utf-8') return $str;
if ($config->get('Core', 'EscapeNonASCIICharacters')) {
$str = HTMLPurifier_Encoder::convertToASCIIDumbLossless($str);
}
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
if ($iconv && !$config->get('Test', 'ForceNoIconv')) {
// Undo our previous fix in convertToUTF8, otherwise iconv will barf
$ascii_fix = HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding);
if (!$escape && !empty($ascii_fix)) {
$clear_fix = array();
foreach ($ascii_fix as $utf8 => $native) $clear_fix[$utf8] = '';
$str = strtr($str, $clear_fix);
}
$str = strtr($str, array_flip($ascii_fix));
// Normal stuff
$str = iconv('utf-8', $encoding . '//IGNORE', $str);
restore_error_handler();
return $str;
return @iconv('utf-8', $encoding . '//IGNORE', $str);
} elseif ($encoding === 'iso-8859-1') {
$str = utf8_decode($str);
restore_error_handler();
return $str;
return @utf8_decode($str);
}
trigger_error('Encoding not supported', E_USER_ERROR);
}
@@ -390,7 +364,7 @@ class HTMLPurifier_Encoder
* @note Sort of with cleanUTF8() but it assumes that $str is
* well-formed UTF-8
*/
function convertToASCIIDumbLossless($str) {
static function convertToASCIIDumbLossless($str) {
$bytesleft = 0;
$result = '';
$working = 0;
@@ -421,47 +395,6 @@ class HTMLPurifier_Encoder
return $result;
}
/**
* This expensive function tests whether or not a given character
* encoding supports ASCII. 7/8-bit encodings like Shift_JIS will
* fail this test, and require special processing. Variable width
* encodings shouldn't ever fail.
*
* @param string $encoding Encoding name to test, as per iconv format
* @param bool $bypass Whether or not to bypass the precompiled arrays.
* @return Array of UTF-8 characters to their corresponding ASCII,
* which can be used to "undo" any overzealous iconv action.
*/
function testEncodingSupportsASCII($encoding, $bypass = false) {
static $encodings = array();
if (!$bypass) {
if (isset($encodings[$encoding])) return $encodings[$encoding];
$lenc = strtolower($encoding);
switch ($lenc) {
case 'shift_jis':
return array("\xC2\xA5" => '\\', "\xE2\x80\xBE" => '~');
case 'johab':
return array("\xE2\x82\xA9" => '\\');
}
if (strpos($lenc, 'iso-8859-') === 0) return array();
}
$ret = array();
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
if (iconv('UTF-8', $encoding, 'a') === false) return false;
for ($i = 0x20; $i <= 0x7E; $i++) { // all printable ASCII chars
$c = chr($i);
if (iconv('UTF-8', "$encoding//IGNORE", $c) === '') {
// Reverse engineer: what's the UTF-8 equiv of this byte
// sequence? This assumes that there's no variable width
// encoding that doesn't support ASCII.
$ret[iconv($encoding, 'UTF-8//IGNORE', $c)] = $c;
}
}
restore_error_handler();
$encodings[$encoding] = $ret;
return $ret;
}
}

View File

@@ -29,7 +29,7 @@ class HTMLPurifier_EntityLookup {
* @static
* @param Optional prototype of custom lookup table to overload with.
*/
function instance($prototype = false) {
static function instance($prototype = false) {
// no references, since PHP doesn't copy unless modified
static $instance = null;
if ($prototype) {

View File

@@ -222,8 +222,6 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
/**
* Adds a custom attribute to a pre-existing element
* @note This is strictly convenience, and does not have a corresponding
* method in HTMLPurifier_HTMLModule
* @param $element_name String element name to add attribute to
* @param $attr_name String name of attribute
* @param $def Attribute definition, can be string or object, see
@@ -231,11 +229,7 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
*/
function addAttribute($element_name, $attr_name, $def) {
$module =& $this->getAnonymousModule();
if (!isset($module->info[$element_name])) {
$element =& $module->addBlankElement($element_name);
} else {
$element =& $module->info[$element_name];
}
$element->attr[$attr_name] = $def;
}

View File

@@ -219,14 +219,5 @@ class HTMLPurifier_HTMLModule
}
return $ret;
}
/**
* Lazy load construction of the module after determining whether
* or not it's needed, and also when a finalized configuration object
* is available.
* @param $config Instance of HTMLPurifier_Config
*/
function setup($config) {}
}

View File

@@ -15,7 +15,7 @@ class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule
'I18N' => array('dir' => false)
);
function setup($config) {
function HTMLPurifier_HTMLModule_Bdo() {
$bdo =& $this->addElement(
'bdo', true, 'Inline', 'Inline', array('Core', 'Lang'),
array(

View File

@@ -12,7 +12,7 @@ class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule
var $name = 'Edit';
function setup($config) {
function HTMLPurifier_HTMLModule_Edit() {
$contents = 'Chameleon: #PCDATA | Inline ! #PCDATA | Flow';
$attr = array(
'cite' => 'URI',

View File

@@ -11,7 +11,7 @@ class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
var $name = 'Hypertext';
function setup($config) {
function HTMLPurifier_HTMLModule_Hypertext() {
$a =& $this->addElement(
'a', true, 'Inline', 'Inline', 'Common',
array(

View File

@@ -5,18 +5,6 @@ require_once 'HTMLPurifier/HTMLModule.php';
require_once 'HTMLPurifier/AttrDef/URI.php';
require_once 'HTMLPurifier/AttrTransform/ImgRequired.php';
HTMLPurifier_ConfigSchema::define(
'HTML', 'MaxImgLength', 1200, 'int/null', '
<p>
This directive controls the maximum number of pixels in the width and
height attributes in <code>img</code> tags. This is
in place to prevent imagecrash attacks, disable with null at your own risk.
This directive is similar to %CSS.MaxImgLength, and both should be
concurrently edited, although there are
subtle differences in the input format (the HTML max is an integer).
</p>
');
/**
* XHTML 1.1 Image Module provides basic image embedding.
* @note There is specialized code for removing empty images in
@@ -27,26 +15,17 @@ class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
var $name = 'Image';
function setup($config) {
$max = $config->get('HTML', 'MaxImgLength');
function HTMLPurifier_HTMLModule_Image() {
$img =& $this->addElement(
'img', true, 'Inline', 'Empty', 'Common',
array(
'alt*' => 'Text',
// According to the spec, it's Length, but percents can
// be abused, so we allow only Pixels. A trusted module
// could overload this with the real value.
'height' => 'Pixels#' . $max,
'width' => 'Pixels#' . $max,
'height' => 'Length',
'longdesc' => 'URI',
'src*' => new HTMLPurifier_AttrDef_URI(true), // embedded
'width' => 'Length'
)
);
if ($max === null || $config->get('HTML', 'Trusted')) {
$img->attr['height'] =
$img->attr['width'] = 'Length';
}
// kind of strange, but splitting things up would be inefficient
$img->attr_transform_pre[] =
$img->attr_transform_post[] =

View File

@@ -25,7 +25,7 @@ class HTMLPurifier_HTMLModule_Legacy extends HTMLPurifier_HTMLModule
var $name = 'Legacy';
function setup($config) {
function HTMLPurifier_HTMLModule_Legacy() {
$this->addElement('basefont', true, 'Inline', 'Empty', false, array(
'color' => 'Color',

View File

@@ -21,7 +21,7 @@ class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule
var $content_sets = array('Flow' => 'List');
function setup($config) {
function HTMLPurifier_HTMLModule_List() {
$this->addElement('ol', true, 'List', 'Required: li', 'Common');
$this->addElement('ul', true, 'List', 'Required: li', 'Common');
$this->addElement('dl', true, 'List', 'Required: dt | dd', 'Common');

View File

@@ -12,7 +12,7 @@ class HTMLPurifier_HTMLModule_Object extends HTMLPurifier_HTMLModule
var $name = 'Object';
function setup($config) {
function HTMLPurifier_HTMLModule_Object() {
$this->addElement('object', false, 'Inline', 'Optional: #PCDATA | Flow | param', 'Common',
array(

View File

@@ -17,7 +17,7 @@ class HTMLPurifier_HTMLModule_Presentation extends HTMLPurifier_HTMLModule
var $name = 'Presentation';
function setup($config) {
function HTMLPurifier_HTMLModule_Presentation() {
$this->addElement('b', true, 'Inline', 'Inline', 'Common');
$this->addElement('big', true, 'Inline', 'Inline', 'Common');
$this->addElement('hr', true, 'Block', 'Empty', 'Common');

View File

@@ -11,7 +11,7 @@ class HTMLPurifier_HTMLModule_Ruby extends HTMLPurifier_HTMLModule
var $name = 'Ruby';
function setup($config) {
function HTMLPurifier_HTMLModule_Ruby() {
$this->addElement('ruby', true, 'Inline',
'Custom: ((rb, (rt | (rp, rt, rp))) | (rbc, rtc, rtc?))',
'Common');

View File

@@ -32,7 +32,7 @@ class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
var $elements = array('script', 'noscript');
var $content_sets = array('Block' => 'script | noscript', 'Inline' => 'script | noscript');
function setup($config) {
function HTMLPurifier_HTMLModule_Scripting() {
// TODO: create custom child-definition for noscript that
// auto-wraps stray #PCDATA in a similar manner to
// blockquote's custom definition (we would use it but

View File

@@ -18,7 +18,7 @@ class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule
'Core' => array(0 => array('Style'))
);
function setup($config) {
function HTMLPurifier_HTMLModule_StyleAttribute() {
$this->attr_collections['Style']['style'] = new HTMLPurifier_AttrDef_CSS();
}

View File

@@ -11,7 +11,7 @@ class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule
var $name = 'Tables';
function setup($config) {
function HTMLPurifier_HTMLModule_Tables() {
$this->addElement('caption', true, false, 'Inline', 'Common');

View File

@@ -10,7 +10,7 @@ class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule
var $name = 'Target';
function setup($config) {
function HTMLPurifier_HTMLModule_Target() {
$elements = array('a');
foreach ($elements as $name) {
$e =& $this->addBlankElement($name);

View File

@@ -22,7 +22,7 @@ class HTMLPurifier_HTMLModule_Text extends HTMLPurifier_HTMLModule
'Flow' => 'Heading | Block | Inline'
);
function setup($config) {
function HTMLPurifier_HTMLModule_Text() {
// Inline Phrasal -------------------------------------------------
$this->addElement('abbr', true, 'Inline', 'Inline', 'Common');

View File

@@ -70,7 +70,7 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
* @todo Wildcard matching and error reporting when an added or
* subtracted fix has no effect.
*/
function setup($config) {
function construct($config) {
// create fixes, initialize fixesForLevel
$fixes = $this->makeFixes();

View File

@@ -342,12 +342,13 @@ class HTMLPurifier_HTMLModuleManager
foreach ($modules as $module) {
$this->processModule($module);
$this->modules[$module]->setup($config);
}
foreach ($this->doctype->tidyModules as $module) {
$this->processModule($module);
$this->modules[$module]->setup($config);
if (method_exists($this->modules[$module], 'construct')) {
$this->modules[$module]->construct($config);
}
}
// setup lookup table based on all valid modules

View File

@@ -27,10 +27,10 @@ class HTMLPurifier_IDAccumulator
* @return Fully initialized HTMLPurifier_IDAccumulator
* @static
*/
function build($config, &$context) {
$acc = new HTMLPurifier_IDAccumulator();
$acc->load($config->get('Attr', 'IDBlacklist'));
return $acc;
static function build($config, &$context) {
$id_accumulator = new HTMLPurifier_IDAccumulator();
$id_accumulator->load($config->get('Attr', 'IDBlacklist'));
return $id_accumulator;
}
/**

View File

@@ -25,13 +25,6 @@ class HTMLPurifier_Language
*/
var $errorNames = array();
/**
* True if no message file was found for this language, so English
* is being used instead. Check this if you'd like to notify the
* user that they've used a non-supported language.
*/
var $error = false;
/**
* Has the language object been loaded yet?
* @private
@@ -120,7 +113,7 @@ class HTMLPurifier_Language
$generator = false;
foreach ($args as $i => $value) {
if (is_object($value)) {
if (is_a($value, 'HTMLPurifier_Token')) {
if ($value instanceof HTMLPurifier_Token) {
// factor this out some time
if (!$generator) $generator = $this->context->get('Generator');
if (isset($value->name)) $subst['$'.$i.'.Name'] = $value->name;

View File

@@ -1,11 +0,0 @@
<?php
// private language message file for unit testing purposes
// this language file has no class associated with it
$fallback = 'en';
$messages = array(
'HTMLPurifier' => 'HTML Purifier XNone'
);

View File

@@ -16,7 +16,6 @@ This directive has been available since 2.0.0.
* caching and fallbacks.
* @note Thanks to MediaWiki for the general logic, although this version
* has been entirely rewritten
* @todo Serialized cache for languages
*/
class HTMLPurifier_LanguageFactory
{
@@ -66,7 +65,7 @@ class HTMLPurifier_LanguageFactory
* @param $prototype Optional prototype to overload sole instance with,
* or bool true to reset to default factory.
*/
function &instance($prototype = null) {
static function &instance($prototype = null) {
static $instance = null;
if ($prototype !== null) {
$instance = $prototype;
@@ -90,42 +89,40 @@ class HTMLPurifier_LanguageFactory
* Creates a language object, handles class fallbacks
* @param $config Instance of HTMLPurifier_Config
* @param $context Instance of HTMLPurifier_Context
* @param $code Code to override configuration with. Private parameter.
*/
function create($config, &$context, $code = false) {
function create($config, &$context) {
// validate language code
if ($code === false) {
$code = $this->validator->validate(
$config->get('Core', 'Language'), $config, $context
);
} else {
$code = $this->validator->validate($code, $config, $context);
}
if ($code === false) $code = 'en'; // malformed code becomes English
$pcode = str_replace('-', '_', $code); // make valid PHP classname
static $depth = 0; // recursion protection
if ($code == 'en') {
$lang = new HTMLPurifier_Language($config, $context);
$class = 'HTMLPurifier_Language';
$file = $this->dir . '/Language.php';
} else {
$class = 'HTMLPurifier_Language_' . $pcode;
$file = $this->dir . '/Language/classes/' . $code . '.php';
if (file_exists($file)) {
include $file;
$lang = new $class($config, $context);
} else {
// Go fallback
$raw_fallback = $this->getFallbackFor($code);
$fallback = $raw_fallback ? $raw_fallback : 'en';
// PHP5/APC deps bug workaround can go here
// you can bypass the conditional include by loading the
// file yourself
if (file_exists($file) && !class_exists($class)) {
include_once $file;
}
}
if (!class_exists($class)) {
// go fallback
$fallback = HTMLPurifier_LanguageFactory::getFallbackFor($code);
$depth++;
$lang = $this->create($config, $context, $fallback);
if (!$raw_fallback) {
$lang->error = true;
}
$lang = HTMLPurifier_LanguageFactory::factory( $fallback );
$depth--;
}
} else {
$lang = new $class($config, $context);
}
$lang->code = $code;

View File

@@ -1,111 +0,0 @@
<?php
/**
* Represents a measurable length, with a string numeric magnitude
* and a unit. This object is immutable.
*/
class HTMLPurifier_Length
{
/**
* String numeric magnitude.
*/
var $n;
/**
* String unit. False is permitted if $n = 0.
*/
var $unit;
/**
* Whether or not this length is valid. Null if not calculated yet.
*/
var $isValid;
/*
* @param number $n Magnitude
* @param string $u Unit
*/
function HTMLPurifier_Length($n = '0', $u = false) {
$this->n = (string) $n;
$this->unit = $u !== false ? (string) $u : false;
}
/**
* @param string $s Unit string, like '2em' or '3.4in'
* @warning Does not perform validation.
*/
function make($s) {
if (is_a($s, 'HTMLPurifier_Length')) return $s;
$n_length = strspn($s, '1234567890.+-');
$n = substr($s, 0, $n_length);
$unit = substr($s, $n_length);
if ($unit === '') $unit = false;
return new HTMLPurifier_Length($n, $unit);
}
/**
* Validates the number and unit.
*/
function validate() {
// Special case:
static $allowedUnits = array(
'em' => true, 'ex' => true, 'px' => true, 'in' => true,
'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true
);
if ($this->n === '+0' || $this->n === '-0') $this->n = '0';
if ($this->n === '0' && $this->unit === false) return true;
if (!ctype_lower($this->unit)) $this->unit = strtolower($this->unit);
if (!isset($allowedUnits[$this->unit])) return false;
// Hack:
$def = new HTMLPurifier_AttrDef_CSS_Number();
$a = false; // hack hack
$result = $def->validate($this->n, $a, $a);
if ($result === false) return false;
$this->n = $result;
return true;
}
/**
* Returns string representation of number.
*/
function toString() {
if (!$this->isValid()) return false;
return $this->n . $this->unit;
}
/**
* Retrieves string numeric magnitude.
*/
function getN() {return $this->n;}
/**
* Retrieves string unit.
*/
function getUnit() {return $this->unit;}
/**
* Returns true if this length unit is valid.
*/
function isValid() {
if ($this->isValid === null) $this->isValid = $this->validate();
return $this->isValid;
}
/**
* Compares two lengths, and returns 1 if greater, -1 if less and 0 if equal.
* @warning If both values are too large or small, this calculation will
* not work properly
*/
function compareTo($l) {
if ($l === false) return false;
if ($l->unit !== $this->unit) {
$converter = new HTMLPurifier_UnitConverter();
$l = $converter->convert($l, $this->unit);
if ($l === false) return false;
}
return $this->n - $l->n;
}
}

View File

@@ -148,9 +148,9 @@ class HTMLPurifier_Lexer
* @param $prototype Optional prototype lexer or configuration object
* @return Concrete lexer.
*/
function create($config) {
static function create($config) {
if (!is_a($config, 'HTMLPurifier_Config')) {
if (!($config instanceof HTMLPurifier_Config)) {
$lexer = $config;
trigger_error("Passing a prototype to
HTMLPurifier_Lexer::create() is deprecated, please instead
@@ -278,7 +278,7 @@ class HTMLPurifier_Lexer
* @param $string HTML string to process.
* @returns HTML with CDATA sections escaped.
*/
function escapeCDATA($string) {
static function escapeCDATA($string) {
return preg_replace_callback(
'/<!\[CDATA\[(.+?)\]\]>/s',
array('HTMLPurifier_Lexer', 'CDATACallback'),
@@ -307,7 +307,7 @@ class HTMLPurifier_Lexer
* and 1 the inside of the CDATA section.
* @returns Escaped internals of the CDATA section.
*/
function CDATACallback($matches) {
static function CDATACallback($matches) {
// not exactly sure why the character set is needed, but whatever
return htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8');
}

View File

@@ -90,27 +90,10 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
$tokens[] = $this->factory->createText($node->data);
return;
} elseif ($node->nodeType === XML_CDATA_SECTION_NODE) {
// undo libxml's special treatment of <script> and <style> tags
$last = end($tokens);
$data = $node->data;
// (note $node->tagname is already normalized)
if ($last instanceof HTMLPurifier_Token_Start && $last->name == 'script') {
$new_data = trim($data);
if (substr($new_data, 0, 4) === '<!--') {
$data = substr($new_data, 4);
if (substr($data, -3) === '-->') {
$data = substr($data, 0, -3);
} else {
// Highly suspicious! Not sure what to do...
}
}
}
$tokens[] = $this->factory->createText($this->parseData($data));
// undo DOM's special treatment of <script> tags
$tokens[] = $this->factory->createText($this->parseData($node->data));
return;
} elseif ($node->nodeType === XML_COMMENT_NODE) {
// this is code is only invoked for comments in script/style in versions
// of libxml pre-2.6.28 (regular comments, of course, are still
// handled regularly)
$tokens[] = $this->factory->createComment($node->data);
return;
} elseif (
@@ -175,7 +158,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
* Callback function for undoing escaping of stray angled brackets
* in comments
*/
function callbackUndoCommentSubst($matches) {
static public function callbackUndoCommentSubst($matches) {
return '<!--' . strtr($matches[1], array('&amp;'=>'&','&lt;'=>'<')) . $matches[2];
}
@@ -183,7 +166,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
* Callback function that entity-izes ampersands in comments so that
* callbackUndoCommentSubst doesn't clobber them
*/
function callbackArmorCommentEntities($matches) {
static public function callbackArmorCommentEntities($matches) {
return '<!--' . str_replace('&', '&amp;', $matches[1]) . $matches[2];
}

View File

@@ -40,7 +40,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
* @param $matches, in form of array(opening tag, contents, closing tag)
* @static
*/
function scriptCallback($matches) {
static function scriptCallback($matches) {
return $matches[1] . htmlspecialchars($matches[2], ENT_COMPAT, 'UTF-8') . $matches[3];
}
@@ -168,7 +168,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
// Check if it's a comment
if (
strncmp('!--', $segment, 3) === 0
substr($segment, 0, 3) === '!--'
) {
// re-determine segment length, looking for -->
$position_comment_end = strpos($html, '-->', $cursor);
@@ -184,7 +184,12 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
}
$strlen_segment = $position_comment_end - $cursor;
$segment = substr($html, $cursor, $strlen_segment);
$token = new HTMLPurifier_Token_Comment(substr($segment, 3));
$token = new
HTMLPurifier_Token_Comment(
substr(
$segment, 3, $strlen_segment - 3
)
);
if ($maintain_line_numbers) {
$token->line = $current_line;
$current_line += $this->substrCount($html, $nl, $cursor, $strlen_segment);

View File

@@ -2,68 +2,12 @@
/**
* Class that handles operations involving percent-encoding in URIs.
*
* @warning
* Be careful when reusing instances of PercentEncoder. The object
* you use for normalize() SHOULD NOT be used for encode(), or
* vice-versa.
*/
class HTMLPurifier_PercentEncoder
{
/**
* Reserved characters to preserve when using encode().
*/
var $preserve = array();
/**
* String of characters that should be preserved while using encode().
*/
function HTMLPurifier_PercentEncoder($preserve = false) {
// unreserved letters, ought to const-ify
for ($i = 48; $i <= 57; $i++) $this->preserve[$i] = true; // digits
for ($i = 65; $i <= 90; $i++) $this->preserve[$i] = true; // upper-case
for ($i = 97; $i <= 122; $i++) $this->preserve[$i] = true; // lower-case
$this->preserve[45] = true; // Dash -
$this->preserve[46] = true; // Period .
$this->preserve[95] = true; // Underscore _
$this->preserve[126]= true; // Tilde ~
// extra letters not to escape
if ($preserve !== false) {
for ($i = 0, $c = strlen($preserve); $i < $c; $i++) {
$this->preserve[ord($preserve[$i])] = true;
}
}
}
/**
* Our replacement for urlencode, it encodes all non-reserved characters,
* as well as any extra characters that were instructed to be preserved.
* @note
* Assumes that the string has already been normalized, making any
* and all percent escape sequences valid. Percents will not be
* re-escaped, regardless of their status in $preserve
* @param $string String to be encoded
* @return Encoded string.
*/
function encode($string) {
$ret = '';
for ($i = 0, $c = strlen($string); $i < $c; $i++) {
if ($string[$i] !== '%' && !isset($this->preserve[$int = ord($string[$i])]) ) {
$ret .= '%' . sprintf('%02X', $int);
} else {
$ret .= $string[$i];
}
}
return $ret;
}
/**
* Fix up percent-encoding by decoding unreserved characters and normalizing.
* @warning This function is affected by $preserve, even though the
* usual desired behavior is for this not to preserve those
* characters. Be careful when reusing instances of PercentEncoder!
* Fix up percent-encoding by decoding unreserved characters and normalizing
* @param $string String to normalize
*/
function normalize($string) {
@@ -83,7 +27,12 @@ class HTMLPurifier_PercentEncoder
continue;
}
$int = hexdec($encoding);
if (isset($this->preserve[$int])) {
if (
($int >= 48 && $int <= 57) || // digits
($int >= 65 && $int <= 90) || // uppercase letters
($int >= 97 && $int <= 122) || // lowercase letters
$int == 126 || $int == 45 || $int == 46 || $int == 95 // ~-._
) {
$ret .= chr($int) . $text;
continue;
}

View File

@@ -158,9 +158,10 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
// the parent
if (!isset($parent_info->child->elements[$token->name])) {
if ($e) $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag auto closed', $parent);
// close the parent, then re-loop to reprocess token
// close the parent, then append the token
$result[] = new HTMLPurifier_Token_End($parent->name);
$this->inputIndex--;
$result[] = $token;
$this->currentNesting[] = $token;
continue;
}

View File

@@ -4,12 +4,7 @@ require_once 'HTMLPurifier/URIParser.php';
require_once 'HTMLPurifier/URIFilter.php';
/**
* HTML Purifier's internal representation of a URI.
* @note
* Internal data-structures are completely escaped. If the data needs
* to be used in a non-URI context (which is very unlikely), be sure
* to decode it first. The URI may not necessarily be well-formed until
* validate() is called.
* HTML Purifier's internal representation of a URI
*/
class HTMLPurifier_URI
{
@@ -57,27 +52,13 @@ class HTMLPurifier_URI
}
/**
* Generic validation method applicable for all schemes. May modify
* this URI in order to get it into a compliant form.
* Generic validation method applicable for all schemes
* @param $config Instance of HTMLPurifier_Config
* @param $context Instance of HTMLPurifier_Context
* @return True if validation/filtering succeeds, false if failure
*/
function validate($config, &$context) {
// ABNF definitions from RFC 3986
$chars_sub_delims = '!$&\'()*+,;=';
$chars_gen_delims = ':/?#[]@';
$chars_pchar = $chars_sub_delims . ':@';
// validate scheme (MUST BE FIRST!)
if (!is_null($this->scheme) && is_null($this->host)) {
$def = $config->getDefinition('URI');
if ($def->defaultScheme === $this->scheme) {
$this->scheme = null;
}
}
// validate host
if (!is_null($this->host)) {
$host_def = new HTMLPurifier_AttrDef_URI_Host();
@@ -85,62 +66,18 @@ class HTMLPurifier_URI
if ($this->host === false) $this->host = null;
}
// validate username
if (!is_null($this->userinfo)) {
$encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . ':');
$this->userinfo = $encoder->encode($this->userinfo);
}
// validate port
if (!is_null($this->port)) {
if ($this->port < 1 || $this->port > 65535) $this->port = null;
}
// validate path
$path_parts = array();
$segments_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/');
if (!is_null($this->host)) {
// path-abempty (hier and relative)
$this->path = $segments_encoder->encode($this->path);
} elseif ($this->path !== '' && $this->path[0] === '/') {
// path-absolute (hier and relative)
if (strlen($this->path) >= 2 && $this->path[1] === '/') {
// This shouldn't ever happen!
$this->path = '';
} else {
$this->path = $segments_encoder->encode($this->path);
}
} elseif (!is_null($this->scheme) && $this->path !== '') {
// path-rootless (hier)
// Short circuit evaluation means we don't need to check nz
$this->path = $segments_encoder->encode($this->path);
} elseif (is_null($this->scheme) && $this->path !== '') {
// path-noscheme (relative)
// (once again, not checking nz)
$segment_nc_encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . '@');
$c = strpos($this->path, '/');
if ($c !== false) {
$this->path =
$segment_nc_encoder->encode(substr($this->path, 0, $c)) .
$segments_encoder->encode(substr($this->path, $c));
} else {
$this->path = $segment_nc_encoder->encode($this->path);
}
} else {
// path-empty (hier and relative)
$this->path = ''; // just to be safe
}
// query and fragment are quite simple in terms of definition:
// *( pchar / "/" / "?" ), so define their validation routines
// when we start fixing percent encoding
// qf = query and fragment
$qf_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/?');
if (!is_null($this->query)) {
$this->query = $qf_encoder->encode($this->query);
}
if (!is_null($this->fragment)) {
$this->fragment = $qf_encoder->encode($this->fragment);
}
// path gets to be validated against a hodge-podge of rules depending
// on the status of authority and scheme, but it's not that important,
// esp. since it won't be applicable to everyone
return true;

View File

@@ -4,39 +4,24 @@ require_once 'HTMLPurifier/URI.php';
/**
* Parses a URI into the components and fragment identifier as specified
* by RFC 3986.
* by RFC 2396.
* @todo Replace regexps with a native PHP parser
*/
class HTMLPurifier_URIParser
{
/**
* Instance of HTMLPurifier_PercentEncoder to do normalization with.
*/
var $percentEncoder;
function HTMLPurifier_URIParser() {
$this->percentEncoder = new HTMLPurifier_PercentEncoder();
}
/**
* Parses a URI.
* Parses a URI
* @param $uri string URI to parse
* @return HTMLPurifier_URI representation of URI. This representation has
* not been validated yet and may not conform to RFC.
* @return HTMLPurifier_URI representation of URI
*/
function parse($uri) {
$uri = $this->percentEncoder->normalize($uri);
// Regexp is as per Appendix B.
// Note that ["<>] are an addition to the RFC's recommended
// characters, because they represent external delimeters.
$r_URI = '!'.
'(([^:/?#"<>]+):)?'. // 2. Scheme
'(//([^/?#"<>]*))?'. // 4. Authority
'([^?#"<>]*)'. // 5. Path
'(\?([^#"<>]*))?'. // 7. Query
'(#([^"<>]*))?'. // 8. Fragment
'(([^:/?#<>\'"]+):)?'. // 2. Scheme
'(//([^/?#<>\'"]*))?'. // 4. Authority
'([^?#<>\'"]*)'. // 5. Path
'(\?([^#<>\'"]*))?'. // 7. Query
'(#([^<>\'"]*))?'. // 8. Fragment
'!';
$matches = array();
@@ -53,7 +38,13 @@ class HTMLPurifier_URIParser
// further parse authority
if ($authority !== null) {
$r_authority = "/^((.+?)@)?(\[[^\]]+\]|[^:]*)(:(\d*))?/";
// ridiculously inefficient: it's a stacked regex!
$HEXDIG = '[A-Fa-f0-9]';
$unreserved = 'A-Za-z0-9-._~'; // make sure you wrap with []
$sub_delims = '!$&\'()'; // needs []
$pct_encoded = "%$HEXDIG$HEXDIG";
$r_userinfo = "(?:[$unreserved$sub_delims:]|$pct_encoded)*";
$r_authority = "/^(($r_userinfo)@)?(\[[^\]]+\]|[^:]*)(:(\d*))?/";
$matches = array();
preg_match($r_authority, $authority, $matches);
$userinfo = !empty($matches[1]) ? $matches[2] : null;

View File

@@ -44,7 +44,7 @@ class HTMLPurifier_URISchemeRegistry
* @note Pass a registry object $prototype with a compatible interface and
* the function will copy it and return it all further times.
*/
function &instance($prototype = null) {
static function &instance($prototype = null) {
static $instance = null;
if ($prototype !== null) {
$instance = $prototype;

View File

@@ -1,241 +0,0 @@
<?php
/**
* Class for converting between different unit-lengths as specified by
* CSS.
*/
class HTMLPurifier_UnitConverter
{
/**
* Minimum bcmath precision for output.
*/
var $outputPrecision;
/**
* Bcmath precision for internal calculations.
*/
var $internalPrecision;
/**
* Whether or not BCMath is available
*/
var $bcmath;
function HTMLPurifier_UnitConverter($output_precision = 4, $internal_precision = 10, $force_no_bcmath = false) {
$this->outputPrecision = $output_precision;
$this->internalPrecision = $internal_precision;
$this->bcmath = !$force_no_bcmath && function_exists('bcmul');
}
/**
* Converts a length object of one unit into another unit.
* @param HTMLPurifier_Length $length
* Instance of HTMLPurifier_Length to convert. You must validate()
* it before passing it here!
* @param string $to_unit
* Unit to convert to.
* @note
* About precision: This conversion function pays very special
* attention to the incoming precision of values and attempts
* to maintain a number of significant figure. Results are
* fairly accurate up to nine digits. Some caveats:
* - If a number is zero-padded as a result of this significant
* figure tracking, the zeroes will be eliminated.
* - If a number contains less than four sigfigs ($outputPrecision)
* and this causes some decimals to be excluded, those
* decimals will be added on.
*/
function convert($length, $to_unit) {
/**
* Units information array. Units are grouped into measuring systems
* (English, Metric), and are assigned an integer representing
* the conversion factor between that unit and the smallest unit in
* the system. Numeric indexes are actually magical constants that
* encode conversion data from one system to the next, with a O(n^2)
* constraint on memory (this is generally not a problem, since
* the number of measuring systems is small.)
*/
static $units = array(
1 => array(
'px' => 3, // This is as per CSS 2.1 and Firefox. Your mileage may vary
'pt' => 4,
'pc' => 48,
'in' => 288,
2 => array('pt', '0.352777778', 'mm'),
),
2 => array(
'mm' => 1,
'cm' => 10,
1 => array('mm', '2.83464567', 'pt'),
),
);
if (!$length->isValid()) return false;
$n = $length->getN();
$unit = $length->getUnit();
if ($n === '0' || $unit === false) {
return new HTMLPurifier_Length('0', false);
}
$state = $dest_state = false;
foreach ($units as $k => $x) {
if (isset($x[$unit])) $state = $k;
if (isset($x[$to_unit])) $dest_state = $k;
}
if (!$state || !$dest_state) return false;
// Some calculations about the initial precision of the number;
// this will be useful when we need to do final rounding.
$sigfigs = $this->getSigFigs($n);
if ($sigfigs < $this->outputPrecision) $sigfigs = $this->outputPrecision;
// Cleanup $n for PHP 4.3.9 and 4.3.10. See http://bugs.php.net/bug.php?id=30726
if (strncmp($n, '-.', 2) === 0) {
$n = '-0.' . substr($n, 2);
}
// BCMath's internal precision deals only with decimals. Use
// our default if the initial number has no decimals, or increase
// it by how ever many decimals, thus, the number of guard digits
// will always be greater than or equal to internalPrecision.
$log = (int) floor(log(abs($n), 10));
$cp = ($log < 0) ? $this->internalPrecision - $log : $this->internalPrecision; // internal precision
for ($i = 0; $i < 2; $i++) {
// Determine what unit IN THIS SYSTEM we need to convert to
if ($dest_state === $state) {
// Simple conversion
$dest_unit = $to_unit;
} else {
// Convert to the smallest unit, pending a system shift
$dest_unit = $units[$state][$dest_state][0];
}
// Do the conversion if necessary
if ($dest_unit !== $unit) {
$factor = $this->div($units[$state][$unit], $units[$state][$dest_unit], $cp);
$n = $this->mul($n, $factor, $cp);
$unit = $dest_unit;
}
// Output was zero, so bail out early. Shouldn't ever happen.
if ($n === '') {
$n = '0';
$unit = $to_unit;
break;
}
// It was a simple conversion, so bail out
if ($dest_state === $state) {
break;
}
if ($i !== 0) {
// Conversion failed! Apparently, the system we forwarded
// to didn't have this unit. This should never happen!
return false;
}
// Pre-condition: $i == 0
// Perform conversion to next system of units
$n = $this->mul($n, $units[$state][$dest_state][1], $cp);
$unit = $units[$state][$dest_state][2];
$state = $dest_state;
// One more loop around to convert the unit in the new system.
}
// Post-condition: $unit == $to_unit
if ($unit !== $to_unit) return false;
// Useful for debugging:
//echo "<pre>n";
//echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n</pre>\n";
$n = $this->round($n, $sigfigs);
if (strpos($n, '.') !== false) $n = rtrim($n, '0');
$n = rtrim($n, '.');
return new HTMLPurifier_Length($n, $unit);
}
/**
* Returns the number of significant figures in a string number.
* @param string $n Decimal number
* @return int number of sigfigs
*/
function getSigFigs($n) {
$n = ltrim($n, '0+-');
$dp = strpos($n, '.'); // decimal position
if ($dp === false) {
$sigfigs = strlen(rtrim($n, '0'));
} else {
$sigfigs = strlen(ltrim($n, '0.')); // eliminate extra decimal character
if ($dp !== 0) $sigfigs--;
}
return $sigfigs;
}
/**
* Adds two numbers, using arbitrary precision when available.
*/
function add($s1, $s2, $scale) {
if ($this->bcmath) return bcadd($s1, $s2, $scale);
else return $this->scale($s1 + $s2, $scale);
}
/**
* Multiples two numbers, using arbitrary precision when available.
*/
function mul($s1, $s2, $scale) {
if ($this->bcmath) return bcmul($s1, $s2, $scale);
else return $this->scale($s1 * $s2, $scale);
}
/**
* Divides two numbers, using arbitrary precision when available.
*/
function div($s1, $s2, $scale) {
if ($this->bcmath) return bcdiv($s1, $s2, $scale);
else return $this->scale($s1 / $s2, $scale);
}
/**
* Rounds a number according to the number of sigfigs it should have,
* using arbitrary precision when available.
*/
function round($n, $sigfigs) {
$new_log = (int) floor(log(abs($n), 10)); // Number of digits left of decimal - 1
$rp = $sigfigs - $new_log - 1; // Number of decimal places needed
$neg = $n < 0 ? '-' : ''; // Negative sign
if ($this->bcmath) {
if ($rp >= 0) {
$n = bcadd($n, $neg . '0.' . str_repeat('0', $rp) . '5', $rp + 1);
$n = bcdiv($n, '1', $rp);
} else {
// This algorithm partially depends on the standardized
// form of numbers that comes out of bcmath.
$n = bcadd($n, $neg . '5' . str_repeat('0', $new_log - $sigfigs), 0);
$n = substr($n, 0, $sigfigs + strlen($neg)) . str_repeat('0', $new_log - $sigfigs + 1);
}
return $n;
} else {
return $this->scale(round($n, $sigfigs - $new_log - 1), $rp + 1);
}
}
/**
* Scales a float to $scale digits right of decimal point, like BCMath.
*/
function scale($r, $scale) {
return sprintf('%.' . $scale . 'f', (float) $r);
}
}

View File

@@ -10,11 +10,11 @@ $pkg->setOptions(
array(
'baseinstalldir' => '/',
'packagefile' => 'package2.xml',
'packagedirectory' => realpath(dirname(__FILE__) . '/library'),
'packagedirectory' => dirname(__FILE__) . '/library',
'filelistgenerator' => 'file',
'include' => array('*'),
'dir_roles' => array('/' => 'php'), // hack to put .ser in the right place
'ignore' => array('HTMLPurifier.auto.php', 'HTMLPurifier.standalone.php', 'standalone/'),
'ignore' => array('HTMLPurifier.auto.php'),
)
);

View File

@@ -71,7 +71,7 @@ readmeinstallchangelog = README, INSTALL, NEWS, WYSIWYG, SLOW, LICENSE, CREDITS
;; legal values: directory paths separated by commas
;directory = /path1,/path2,.,..,subdirectory
;directory = /home/jeichorn/cvs/pear
directory = .
directory = ./
;; template base directory (the equivalent directory of <installdir>/phpDocumentor)
;templatebase = /path/to/my/templates
@@ -82,7 +82,7 @@ directory = .
;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
;; legal values: any wildcard strings separated by commas
;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
ignore = *tests*,*benchmarks*,*docs*,*test-settings.php,*configdoc*,*maintenance*,*smoketests*,*standalone*,*.svn*,*conf*
ignore = pear-*,templates/,Documentation/,test*.php,Lexer.inc
sourcecode = on

30
release2-strict.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
// Merges in changes from trunk to strict branch
// WORKING COPY MUST BE POINTED TO STRICT BRANCH
if (php_sapi_name() != 'cli') {
echo 'Release script cannot be called from web-browser.';
exit;
}
require 'svn.php';
$svn_info = svn_info('.');
$last_rev = (int) $svn_info['Last Changed Rev'];
$trunk_url = $svn_info['Repository Root'] . '/htmlpurifier/trunk';
echo "Last revision was $last_rev, merging from $last_rev to head.\n";
$merge_cmd = "svn merge -r $last_rev:HEAD $trunk_url .";
$out = explode("\n", shell_exec($merge_cmd));
echo "Conflicted files:\n";
foreach ($out as $line) {
if (empty($line)) continue;
if ($line{0} === 'C' || $line{1} === 'C') echo $line . "\n";
}
$version = trim(file_get_contents('VERSION'));
echo "Resolve conflicts and then commit as 'Release $version, merged in $last_rev to HEAD.'";

View File

@@ -1,20 +0,0 @@
<?php
// Tags releases
if (php_sapi_name() != 'cli') {
echo 'Release script cannot be called from web-browser.';
exit;
}
require 'svn.php';
$svn_info = my_svn_info('.');
$version = trim(file_get_contents('VERSION'));
$trunk_url = $svn_info['Repository Root'] . '/htmlpurifier/branches/php4';
$trunk_tag_url = $svn_info['Repository Root'] . '/htmlpurifier/tags/' . $version;
echo "Tagging php4 branch to tags/$version...";
passthru("svn copy --message \"Tag $version release.\" $trunk_url $trunk_tag_url");

25
release3-tag.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
// Tags releases
if (php_sapi_name() != 'cli') {
echo 'Release script cannot be called from web-browser.';
exit;
}
require 'svn.php';
$svn_info = svn_info('.');
$version = trim(file_get_contents('VERSION'));
$trunk_url = $svn_info['Repository Root'] . '/htmlpurifier/trunk';
$strict_url = $svn_info['Repository Root'] . '/htmlpurifier/branches/strict';
$trunk_tag_url = $svn_info['Repository Root'] . '/htmlpurifier/tags/' . $version;
$strict_tag_url = $svn_info['Repository Root'] . '/htmlpurifier/tags/' . $version . '-strict';
echo "Tagging trunk to tags/$version...";
passthru("svn copy --message \"Tag $version release.\" $trunk_url $trunk_tag_url");
echo "Tagging strict to tags/$version-strict...";
passthru("svn copy --message \"Tag $version-strict release.\" $strict_url $strict_tag_url");

View File

@@ -7,7 +7,7 @@ if (!isset($_GET['standalone'])) {
} else {
require_once '../library/HTMLPurifier.standalone.php';
}
error_reporting(E_ALL);
error_reporting(E_ALL | E_STRICT);
function escapeHTML($string) {
$string = HTMLPurifier_Encoder::cleanUTF8($string);

View File

@@ -1,6 +1,6 @@
<?php
function my_svn_info($dir) {
function svn_info($dir) {
$raw = explode("\n", shell_exec("svn info $dir"));
$svn_info = array();
foreach ($raw as $r) {

View File

@@ -86,7 +86,7 @@ class Debugger
/**
* @static
*/
function &instance() {
static function &instance() {
static $soleInstance = false;
if (!$soleInstance) $soleInstance = new Debugger();
return $soleInstance;

View File

@@ -2,11 +2,12 @@
require_once 'HTMLPurifier/AttrCollections.php';
Mock::generatePartial(
'HTMLPurifier_AttrCollections',
'HTMLPurifier_AttrCollections_TestForConstruct',
array('performInclusions', 'expandIdentifiers')
);
class HTMLPurifier_AttrCollectionsTest_NoConstructor extends HTMLPurifier_AttrCollections
{
function HTMLPurifier_AttrCollectionsTest_NoConstructor() {}
function expandIdentifiers(&$a, $b) {}
function performInclusions(&$a) {}
}
class HTMLPurifier_AttrCollectionsTest extends HTMLPurifier_Harness
{
@@ -15,7 +16,7 @@ class HTMLPurifier_AttrCollectionsTest extends HTMLPurifier_Harness
generate_mock_once('HTMLPurifier_AttrTypes');
$collections = new HTMLPurifier_AttrCollections_TestForConstruct();
$collections = new HTMLPurifier_AttrCollectionsTest_NoConstructor();
$types = new HTMLPurifier_AttrTypesMock();

View File

@@ -14,10 +14,6 @@ class HTMLPurifier_AttrDef_CSS_BackgroundTest extends HTMLPurifier_AttrDefHarnes
$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(
'rgb(34, 56, 33) url(chess.png) repeat fixed top',
'rgb(34,56,33) url(chess.png) repeat fixed top'
);
}

View File

@@ -14,7 +14,6 @@ class HTMLPurifier_AttrDef_CSS_BorderTest extends HTMLPurifier_AttrDefHarness
$this->assertDef('thick solid');
$this->assertDef('solid red', 'solid #FF0000');
$this->assertDef('1px solid #000');
$this->assertDef('1px solid rgb(0, 0, 0)', '1px solid rgb(0,0,0)');
}

View File

@@ -11,8 +11,6 @@ class HTMLPurifier_AttrDef_CSS_ColorTest extends HTMLPurifier_AttrDefHarness
$this->def = new HTMLPurifier_AttrDef_CSS_Color();
$this->assertDef('#F00');
$this->assertDef('#fff');
$this->assertDef('#eeeeee');
$this->assertDef('#808080');
$this->assertDef('rgb(255, 0, 0)', 'rgb(255,0,0)'); // rm spaces
$this->assertDef('rgb(100%,0%,0%)');
@@ -29,11 +27,6 @@ class HTMLPurifier_AttrDef_CSS_ColorTest extends HTMLPurifier_AttrDefHarness
// color keywords, of course
$this->assertDef('red', '#FF0000');
// malformed hex declaration
$this->assertDef('808080', '#808080');
$this->assertDef('000000', '#000000');
$this->assertDef('fed', '#fed');
// maybe hex transformations would be another nice feature
// at the very least transform rgb percent to rgb integer

View File

@@ -20,21 +20,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamilyTest extends HTMLPurifier_AttrDefHarnes
$this->assertDef("John's Font", $d);
$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("'\\000045'", "E");
$this->assertDef("','", false);
$this->assertDef("',' foobar','", "' foobar'");
$this->assertDef("'\\27'", "'\''");
$this->assertDef('"\\22"', "'\"'");
$this->assertDef('"\\""', "'\"'");
$this->assertDef('"\'"', "'\\''");
$this->assertDef("'\\000045a'", "Ea");
$this->assertDef("'\\00045 a'", "Ea");
$this->assertDef("'\\00045 a'", "'E a'");
$this->assertDef("'\\\nf'", "f");
}
}

View File

@@ -31,20 +31,12 @@ class HTMLPurifier_AttrDef_CSS_LengthTest extends HTMLPurifier_AttrDefHarness
function testNonNegative() {
$this->def = new HTMLPurifier_AttrDef_CSS_Length('0');
$this->def = new HTMLPurifier_AttrDef_CSS_Length(true);
$this->assertDef('3cm');
$this->assertDef('-3mm', false);
}
function testBounding() {
$this->def = new HTMLPurifier_AttrDef_CSS_Length('-1in', '1in');
$this->assertDef('1cm');
$this->assertDef('-1cm');
$this->assertDef('0');
$this->assertDef('1em', false);
}
}

View File

@@ -10,9 +10,6 @@ class HTMLPurifier_AttrDef_CSS_TextDecorationTest extends HTMLPurifier_AttrDefHa
$this->def = new HTMLPurifier_AttrDef_CSS_TextDecoration();
$this->assertDef('none');
$this->assertDef('none underline', 'underline');
$this->assertDef('underline');
$this->assertDef('overline');
$this->assertDef('line-through overline underline');

View File

@@ -29,6 +29,7 @@ class HTMLPurifier_AttrDef_CSS_URITest extends HTMLPurifier_AttrDefHarness
// escaping
$this->assertDef("url(http://www.example.com/foo,bar\))",
"url(http://www.example.com/foo\,bar\))");
}
}

View File

@@ -107,9 +107,6 @@ class HTMLPurifier_AttrDef_CSSTest extends HTMLPurifier_AttrDefHarness
$this->assertDef(' font-weight : bold; color : #ff0000',
'font-weight:bold;color:#ff0000;');
// case-insensitivity
$this->assertDef('FLOAT:LEFT;', 'float:left;');
}
}

View File

@@ -36,12 +36,5 @@ class HTMLPurifier_AttrDef_HTML_PixelsTest extends HTMLPurifier_AttrDefHarness
}
function test_make() {
$factory = new HTMLPurifier_AttrDef_HTML_Pixels();
$this->def = $factory->make('30');
$this->assertDef('25');
$this->assertDef('35', '30');
}
}

View File

@@ -1,34 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrDef/Switch.php';
class HTMLPurifier_AttrDef_SwitchTest extends HTMLPurifier_AttrDefHarness
{
var $with, $without;
function setUp() {
parent::setUp();
generate_mock_once('HTMLPurifier_AttrDef');
$this->with = new HTMLPurifier_AttrDefMock();
$this->without = new HTMLPurifier_AttrDefMock();
$this->def = new HTMLPurifier_AttrDef_Switch('tag', $this->with, $this->without);
}
function testWith() {
$token = new HTMLPurifier_Token_Start('tag');
$this->context->register('CurrentToken', $token);
$this->with->expectOnce('validate');
$this->with->setReturnValue('validate', 'foo');
$this->assertDef('bar', 'foo');
}
function testWithout() {
$token = new HTMLPurifier_Token_Start('other-tag');
$this->context->register('CurrentToken', $token);
$this->without->expectOnce('validate');
$this->without->setReturnValue('validate', 'foo');
$this->assertDef('bar', 'foo');
}
}

View File

@@ -17,27 +17,6 @@ class HTMLPurifier_AttrDef_URI_HostTest extends HTMLPurifier_AttrDefHarness
$this->assertDef('124.15.6.89'); // IPv4
$this->assertDef('www.google.com'); // reg-name
// more domain name tests
$this->assertDef('test.');
$this->assertDef('sub.test.');
$this->assertDef('.test', false);
$this->assertDef('ff');
$this->assertDef('1f', false);
$this->assertDef('-f', false);
$this->assertDef('f1');
$this->assertDef('f-', false);
$this->assertDef('sub.ff');
$this->assertDef('sub.1f', false);
$this->assertDef('sub.-f', false);
$this->assertDef('sub.f1');
$this->assertDef('sub.f-', false);
$this->assertDef('ff.top');
$this->assertDef('1f.top');
$this->assertDef('-f.top', false);
$this->assertDef('ff.top');
$this->assertDef('f1.top');
$this->assertDef('f-.top', false);
}
}

View File

@@ -33,19 +33,6 @@ class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
);
}
function testPercentEncoding() {
$this->assertDef(
'http:colon:mercenary',
'colon%3Amercenary'
);
}
function testPercentEncodingPreserve() {
$this->assertDef(
'http://www.example.com/abcABC123-_.!~*()\''
);
}
function testEmbeds() {
$this->def = new HTMLPurifier_AttrDef_URI(true);
$this->assertDef('http://sub.example.com/alas?foo=asd');

View File

@@ -12,7 +12,8 @@ class HTMLPurifier_AttrDefTest extends HTMLPurifier_Harness
$this->assertIdentical('', $def->parseCDATA(''));
$this->assertIdentical('', $def->parseCDATA("\t\n\r \t\t"));
$this->assertIdentical('foo', $def->parseCDATA("\t\n\r foo\t\t"));
$this->assertIdentical('translate to space', $def->parseCDATA("translate\nto\tspace"));
$this->assertIdentical('ignorelinefeeds', $def->parseCDATA("ignore\nline\nfeeds"));
$this->assertIdentical('translate to space', $def->parseCDATA("translate\rto\tspace"));
}

View File

@@ -5,14 +5,13 @@ require_once 'HTMLPurifier/DefinitionCacheFactory.php';
class HTMLPurifier_DefinitionCacheFactoryTest extends HTMLPurifier_Harness
{
var $factory;
var $newFactory;
var $oldFactory;
function setup() {
parent::setup();
$this->factory = new HTMLPurifier_DefinitionCacheFactory();
$new = new HTMLPurifier_DefinitionCacheFactory();
$this->oldFactory = HTMLPurifier_DefinitionCacheFactory::instance();
HTMLPurifier_DefinitionCacheFactory::instance($this->factory);
HTMLPurifier_DefinitionCacheFactory::instance($new);
}
function teardown() {
@@ -20,52 +19,46 @@ class HTMLPurifier_DefinitionCacheFactoryTest extends HTMLPurifier_Harness
}
function test_create() {
$cache = $this->factory->create('Test', $this->config);
$config = HTMLPurifier_Config::createDefault();
$factory = HTMLPurifier_DefinitionCacheFactory::instance();
$cache = $factory->create('Test', $config);
$this->assertEqual($cache, new HTMLPurifier_DefinitionCache_Serializer('Test'));
}
function test_create_withDecorator() {
$this->factory->addDecorator('Memory');
$cache = $this->factory->create('Test', $this->config);
$config = HTMLPurifier_Config::createDefault();
$factory =& HTMLPurifier_DefinitionCacheFactory::instance();
$factory->addDecorator('Memory');
$cache =& $factory->create('Test', $config);
$cache_real = new HTMLPurifier_DefinitionCache_Decorator_Memory();
$cache_real = $cache_real->decorate(new HTMLPurifier_DefinitionCache_Serializer('Test'));
$this->assertEqual($cache, $cache_real);
}
function test_create_withDecoratorObject() {
$this->factory->addDecorator(new HTMLPurifier_DefinitionCache_Decorator_Memory());
$cache = $this->factory->create('Test', $this->config);
$config = HTMLPurifier_Config::createDefault();
$factory =& HTMLPurifier_DefinitionCacheFactory::instance();
$factory->addDecorator(new HTMLPurifier_DefinitionCache_Decorator_Memory());
$cache =& $factory->create('Test', $config);
$cache_real = new HTMLPurifier_DefinitionCache_Decorator_Memory();
$cache_real = $cache_real->decorate(new HTMLPurifier_DefinitionCache_Serializer('Test'));
$this->assertEqual($cache, $cache_real);
}
function test_create_recycling() {
$cache =& $this->factory->create('Test', $this->config);
$cache2 =& $this->factory->create('Test', $this->config);
$config = HTMLPurifier_Config::createDefault();
$factory =& HTMLPurifier_DefinitionCacheFactory::instance();
$cache =& $factory->create('Test', $config);
$cache2 =& $factory->create('Test', $config);
$this->assertReference($cache, $cache2);
}
function test_create_invalid() {
$this->config->set('Core', 'DefinitionCache', 'Invalid');
$this->expectError('Unrecognized DefinitionCache Invalid, using Serializer instead');
$cache = $this->factory->create('Test', $this->config);
$this->assertIsA($cache, 'HTMLPurifier_DefinitionCache_Serializer');
}
function test_null() {
$this->config->set('Core', 'DefinitionCache', null);
$cache = $this->factory->create('Test', $this->config);
$config = HTMLPurifier_Config::create(array('Core.DefinitionCache' => null));
$factory =& HTMLPurifier_DefinitionCacheFactory::instance();
$cache =& $factory->create('Test', $config);
$this->assertEqual($cache, new HTMLPurifier_DefinitionCache_Null('Test'));
}
function test_register() {
generate_mock_once('HTMLPurifier_DefinitionCache');
$this->config->set('Core', 'DefinitionCache', 'TestCache');
$this->factory->register('TestCache', $class = 'HTMLPurifier_DefinitionCacheMock');
$cache = $this->factory->create('Test', $this->config);
$this->assertIsA($cache, $class);
}
}

View File

@@ -9,7 +9,6 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
function setUp() {
$this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
parent::setUp();
}
function assertCleanUTF8($string, $expect = null) {
@@ -27,90 +26,93 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
$this->assertCleanUTF8("\xC2\x80", ''); // two byte invalid SGML
$this->assertCleanUTF8("\xF3\xBF\xBF\xBF"); // valid four byte
$this->assertCleanUTF8("\xDF\xFF", ''); // malformed UTF8
// invalid codepoints
$this->assertCleanUTF8("\xED\xB0\x80", '');
}
function test_convertToUTF8_noConvert() {
function test_convertToUTF8() {
$config = HTMLPurifier_Config::createDefault();
$context = new HTMLPurifier_Context();
// UTF-8 means that we don't touch it
$this->assertIdentical(
HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
HTMLPurifier_Encoder::convertToUTF8("\xF6", $config, $context),
"\xF6" // this is invalid
);
}
$this->assertNoErrors();
function test_convertToUTF8_iso8859_1() {
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
$config = HTMLPurifier_Config::create(array(
'Core.Encoding' => 'ISO-8859-1'
));
// Now it gets converted
$this->assertIdentical(
HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
HTMLPurifier_Encoder::convertToUTF8("\xF6", $config, $context),
"\xC3\xB6"
);
}
function test_convertToUTF8_withoutIconv() {
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
$this->config->set('Test', 'ForceNoIconv', true);
$config = HTMLPurifier_Config::create(array(
'Core.Encoding' => 'ISO-8859-1',
'Test.ForceNoIconv' => true
));
$this->assertIdentical(
HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
HTMLPurifier_Encoder::convertToUTF8("\xF6", $config, $context),
"\xC3\xB6"
);
}
function getZhongWen() {
return "\xE4\xB8\xAD\xE6\x96\x87 (Chinese)";
}
function test_convertFromUTF8() {
$config = HTMLPurifier_Config::createDefault();
$context = new HTMLPurifier_Context();
// zhong-wen
$chinese = "\xE4\xB8\xAD\xE6\x96\x87 (Chinese)";
function test_convertFromUTF8_utf8() {
// UTF-8 means that we don't touch it
$this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $config, $context),
"\xC3\xB6"
);
}
function test_convertFromUTF8_iso8859_1() {
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
$config = HTMLPurifier_Config::create(array(
'Core.Encoding' => 'ISO-8859-1'
));
// Now it gets converted
$this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $config, $context),
"\xF6"
);
}
function test_convertFromUTF8_iconvNoChars() {
if (!function_exists('iconv')) return;
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
if (function_exists('iconv')) {
// iconv has it's own way
$this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
HTMLPurifier_Encoder::convertFromUTF8($chinese, $config, $context),
" (Chinese)"
);
}
function test_convertFromUTF8_phpNormal() {
// Plain PHP implementation has slightly different behavior
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
$this->config->set('Test', 'ForceNoIconv', true);
$config = HTMLPurifier_Config::create(array(
'Core.Encoding' => 'ISO-8859-1',
'Test.ForceNoIconv' => true
));
$this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $config, $context),
"\xF6"
);
}
function test_convertFromUTF8_phpNoChars() {
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
$this->config->set('Test', 'ForceNoIconv', true);
$this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
HTMLPurifier_Encoder::convertFromUTF8($chinese, $config, $context),
"?? (Chinese)"
);
}
function test_convertFromUTF8_withProtection() {
// Preserve the characters!
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
$this->config->set('Core', 'EscapeNonASCIICharacters', true);
$config = HTMLPurifier_Config::create(array(
'Core.Encoding' => 'ISO-8859-1',
'Core.EscapeNonASCIICharacters' => true
));
$this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
HTMLPurifier_Encoder::convertFromUTF8($chinese, $config, $context),
"&#20013;&#25991; (Chinese)"
);
@@ -137,39 +139,5 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
}
function assertASCIISupportCheck($enc, $ret) {
$test = HTMLPurifier_Encoder::testEncodingSupportsASCII($enc, true);
if ($test === false) return;
$this->assertIdentical(
HTMLPurifier_Encoder::testEncodingSupportsASCII($enc),
$ret
);
$this->assertIdentical(
HTMLPurifier_Encoder::testEncodingSupportsASCII($enc, true),
$ret
);
}
function test_testEncodingSupportsASCII() {
$this->assertASCIISupportCheck('Shift_JIS', array("\xC2\xA5" => '\\', "\xE2\x80\xBE" => '~'));
$this->assertASCIISupportCheck('JOHAB', array("\xE2\x82\xA9" => '\\'));
$this->assertASCIISupportCheck('ISO-8859-1', array());
$this->assertASCIISupportCheck('dontexist', array()); // canary
}
function testShiftJIS() {
if (!function_exists('iconv')) return;
$this->config->set('Core', 'Encoding', 'Shift_JIS');
// This actually looks like a Yen, but we're going to treat it differently
$this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8('\\~', $this->config, $this->context),
'\\~'
);
$this->assertIdentical(
HTMLPurifier_Encoder::convertToUTF8('\\~', $this->config, $this->context),
'\\~'
);
}
}

View File

@@ -25,7 +25,7 @@ class HTMLPurifier_ErrorCollectorEMock extends HTMLPurifier_ErrorCollectorMock
$this->_expected_context_at[$step][$key] = $value;
}
function send() {
function send($severity, $msg) {
// test for context
$context =& SimpleTest::getContext();
$test =& $context->getTest();

View File

@@ -205,9 +205,6 @@ class HTMLPurifier_GeneratorTest extends HTMLPurifier_ComplexHarness
// abort test if tidy isn't loaded
if (!extension_loaded('tidy')) return;
// just don't test; Tidy is exploding on me.
return;
$this->config = HTMLPurifier_Config::createDefault();
$this->config->set('Core', 'TidyFormat', true);
$this->config->set('Output', 'Newline', "\n");

View File

@@ -87,22 +87,6 @@ a[href|title]
}
function test_addAttribute_multiple() {
$config = HTMLPurifier_Config::create(array(
'HTML.DefinitionID' => 'HTMLPurifier_HTMLDefinitionTest->test_addAttribute_multiple'
));
$def =& $config->getHTMLDefinition(true);
$def->addAttribute('span', 'custom', 'Enum#attribute');
$def->addAttribute('span', 'foo', 'Text');
$purifier = new HTMLPurifier($config);
$input = '<span custom="attribute" foo="asdf">Custom!</span>';
$output = $purifier->purify($input);
$this->assertIdentical($input, $output);
}
function test_addElement() {
$config = HTMLPurifier_Config::create(array(

View File

@@ -1,57 +0,0 @@
<?php
require_once 'HTMLPurifier/HTMLModuleHarness.php';
require_once 'HTMLPurifier/HTMLModule/Image.php';
class HTMLPurifier_HTMLModule_ImageTest extends HTMLPurifier_HTMLModuleHarness
{
function testNormal() {
$this->assertResult('<img height="40" width="40" src="" alt="" />');
}
function testLengthTooLarge() {
$this->assertResult(
'<img height="40000" width="40000" src="" alt="" />',
'<img height="1200" width="1200" src="" alt="" />'
);
}
function testLengthPercentage() {
$this->assertResult(
'<img height="100%" width="100%" src="" alt="" />',
'<img src="" alt="" />'
);
}
function testLengthCustomMax() {
$this->config->set('HTML', 'MaxImgLength', 20);
$this->assertResult(
'<img height="30" width="30" src="" alt="" />',
'<img height="20" width="20" src="" alt="" />'
);
}
function testLengthCrashFixDisabled() {
$this->config->set('HTML', 'MaxImgLength', null);
$this->assertResult(
'<img height="100%" width="100%" src="" alt="" />'
);
$this->assertResult(
'<img height="40000" width="40000" src="" alt="" />'
);
}
function testLengthTrusted() {
$this->config->set('HTML', 'Trusted', true);
$this->assertResult(
'<img height="100%" width="100%" src="" alt="" />'
);
$this->assertResult(
'<img height="40000" width="40000" src="" alt="" />'
);
}
}

View File

@@ -40,7 +40,7 @@ class HTMLPurifier_HTMLModule_TidyTest extends HTMLPurifier_Harness
}
function test_setup() {
function test_construct() {
$i = 0; // counter, helps us isolate expectations
@@ -65,7 +65,7 @@ class HTMLPurifier_HTMLModule_TidyTest extends HTMLPurifier_Harness
'HTML.TidyLevel' => 'none'
));
$module->expectAt($i++, 'populate', array(array()));
$module->setup($config);
$module->construct($config);
// basic levels
@@ -76,7 +76,7 @@ class HTMLPurifier_HTMLModule_TidyTest extends HTMLPurifier_Harness
'light-fix-1' => $lf1,
'light-fix-2' => $lf2
)));
$module->setup($config);
$module->construct($config);
$config = HTMLPurifier_Config::create(array(
'HTML.TidyLevel' => 'heavy'
@@ -89,7 +89,7 @@ class HTMLPurifier_HTMLModule_TidyTest extends HTMLPurifier_Harness
'heavy-fix-1' => $hf1,
'heavy-fix-2' => $hf2
)));
$module->setup($config);
$module->construct($config);
// fine grained tuning
@@ -101,7 +101,7 @@ class HTMLPurifier_HTMLModule_TidyTest extends HTMLPurifier_Harness
'light-fix-1' => $lf1,
'medium-fix-1' => $mf1
)));
$module->setup($config);
$module->construct($config);
$config = HTMLPurifier_Config::create(array(
'HTML.TidyLevel' => 'medium',
@@ -111,7 +111,7 @@ class HTMLPurifier_HTMLModule_TidyTest extends HTMLPurifier_Harness
'light-fix-2' => $lf2,
'medium-fix-2' => $mf2
)));
$module->setup($config);
$module->construct($config);
// done

View File

@@ -12,24 +12,13 @@ class HTMLPurifier_Harness extends UnitTestCase
parent::UnitTestCase();
}
var $config, $context, $purifier;
var $config, $context;
/**
* Generates easily accessible default config/context, as well as
* a convenience purifier for integration testing.
* Generates easily accessible default config/context
*/
function setUp() {
list($this->config, $this->context) = $this->createCommon();
$this->purifier = new HTMLPurifier();
}
/**
* Asserts a purification. Good for integration testing.
*/
function assertPurification($input, $expect = null) {
if ($expect === null) $expect = $input;
$result = $this->purifier->purify($input, $this->config);
$this->assertIdentical($expect, $result);
}
/**

View File

@@ -32,10 +32,7 @@ class HTMLPurifier_IDAccumulatorTest extends HTMLPurifier_Harness
function testBuild() {
$this->config->set('Attr', 'IDBlacklist', array('foo'));
// For some reason, doing the static call here results in a segfault
// for early versions of PHP 5.0.x
$acc = new HTMLPurifier_IDAccumulator();
$accumulator = $acc->build($this->config, $this->context);
$accumulator = HTMLPurifier_IDAccumulator::build($this->config, $this->context);
$this->assertTrue( isset($accumulator->ids['foo']) );
}

View File

@@ -5,20 +5,13 @@ require_once 'HTMLPurifier/LanguageFactory.php';
class HTMLPurifier_LanguageFactoryTest extends HTMLPurifier_Harness
{
/**
* Protected reference of global factory we're testing.
*/
var $factory;
function setUp() {
$this->factory = HTMLPurifier_LanguageFactory::instance();
parent::setUp();
}
function test() {
$this->config->set('Core', 'Language', 'en');
$language = $this->factory->create($this->config, $this->context);
$factory = HTMLPurifier_LanguageFactory::instance();
$config = HTMLPurifier_Config::create(array('Core.Language' => 'en'));
$context = new HTMLPurifier_Context();
$language = $factory->create($config, $context);
$this->assertIsA($language, 'HTMLPurifier_Language');
$this->assertIdentical($language->code, 'en');
@@ -28,12 +21,18 @@ class HTMLPurifier_LanguageFactoryTest extends HTMLPurifier_Harness
$language->load();
$this->assertNotEqual(count($language->messages), 0);
// actual tests for content can be found in LanguageTest
}
function testFallback() {
$this->config->set('Core', 'Language', 'en-x-test');
$language = $this->factory->create($this->config, $this->context);
$factory = HTMLPurifier_LanguageFactory::instance();
$config = HTMLPurifier_Config::create(array('Core.Language' => 'en-x-test'));
$context = new HTMLPurifier_Context();
$language = $factory->create($config, $context);
$this->assertIsA($language, 'HTMLPurifier_Language_en_x_test');
$this->assertIdentical($language->code, 'en-x-test');
@@ -48,24 +47,5 @@ class HTMLPurifier_LanguageFactoryTest extends HTMLPurifier_Harness
}
function testFallbackWithNoClass() {
$this->config->set('Core', 'Language', 'en-x-testmini');
$language = $this->factory->create($this->config, $this->context);
$this->assertIsA($language, 'HTMLPurifier_Language');
$this->assertIdentical($language->code, 'en-x-testmini');
$language->load();
$this->assertIdentical($language->getMessage('HTMLPurifier'), 'HTML Purifier XNone');
$this->assertIdentical($language->getMessage('LanguageFactoryTest: Pizza'), 'Pizza');
$this->assertIdentical($language->error, false);
}
function testNoSuchLanguage() {
$this->config->set('Core', 'Language', 'en-x-testnone');
$language = $this->factory->create($this->config, $this->context);
$this->assertIsA($language, 'HTMLPurifier_Language');
$this->assertIdentical($language->code, 'en-x-testnone');
$this->assertIdentical($language->error, true);
}
}

View File

@@ -1,73 +0,0 @@
<?php
require_once 'HTMLPurifier/Length.php';
class HTMLPurifier_LengthTest extends HTMLPurifier_Harness
{
function testConstruct() {
$l = new HTMLPurifier_Length('23', 'in');
$this->assertIdentical($l->getN(), '23');
$this->assertIdentical($l->getUnit(), 'in');
}
function testMake() {
$l = HTMLPurifier_Length::make('+23.4in');
$this->assertIdentical($l->getN(), '+23.4');
$this->assertIdentical($l->getUnit(), 'in');
}
function testToString() {
$l = new HTMLPurifier_Length('23', 'in');
$this->assertIdentical($l->toString(), '23in');
}
function assertValidate($string, $expect = true) {
if ($expect === true) $expect = $string;
$l = HTMLPurifier_Length::make($string);
$result = $l->isValid();
if ($result === false) $this->assertIdentical($expect, false);
else $this->assertIdentical($l->toString(), $expect);
}
function testValidate() {
$this->assertValidate('0');
$this->assertValidate('+0', '0');
$this->assertValidate('-0', '0');
$this->assertValidate('0px');
$this->assertValidate('4.5px');
$this->assertValidate('-4.5px');
$this->assertValidate('3ex');
$this->assertValidate('3em');
$this->assertValidate('3in');
$this->assertValidate('3cm');
$this->assertValidate('3mm');
$this->assertValidate('3pt');
$this->assertValidate('3pc');
$this->assertValidate('3PX', '3px');
$this->assertValidate('3', false);
$this->assertValidate('3miles', false);
}
/**
* @param $s1 First string to compare
* @param $s2 Second string to compare
* @param $expect 0 for $s1 == $s2, 1 for $s1 > $s2 and -1 for $s1 < $s2
*/
function assertComparison($s1, $s2, $expect = 0) {
$l1 = HTMLPurifier_Length::make($s1);
$l2 = HTMLPurifier_Length::make($s2);
$r1 = $l1->compareTo($l2);
$r2 = $l2->compareTo($l1);
$this->assertIdentical($r1 == 0 ? 0 : ($r1 > 0 ? 1 : -1), $expect);
$this->assertIdentical($r2 == 0 ? 0 : ($r2 > 0 ? 1 : -1), - $expect);
}
function testCompareTo() {
$this->assertComparison('12in', '12in');
$this->assertComparison('12in', '12mm', 1);
$this->assertComparison('1px', '1mm', -1);
$this->assertComparison(str_repeat('2', 38) . 'in', '100px', 1);
}
}

View File

@@ -37,28 +37,5 @@ class HTMLPurifier_PercentEncoderTest extends HTMLPurifier_Harness
}
function assertEncode($string, $expect = true, $preserve = false) {
if ($expect === true) $expect = $string;
$encoder = new HTMLPurifier_PercentEncoder($preserve);
$result = $encoder->encode($string);
$this->assertIdentical($result, $expect);
}
function test_encode_noChange() {
$this->assertEncode('abc012-_~.');
}
function test_encode_encode() {
$this->assertEncode('>', '%3E');
}
function test_encode_preserve() {
$this->assertEncode('<>', '<%3E', '<');
}
function test_encode_low() {
$this->assertEncode("\1", '%01');
}
}

View File

@@ -82,12 +82,5 @@ class HTMLPurifier_Strategy_MakeWellFormedTest extends HTMLPurifier_StrategyHarn
);
}
function testAutoCloseMultiple() {
$this->assertResult(
'<span><span><div></div>',
'<span><span></span></span><div></div>'
);
}
}

View File

@@ -180,55 +180,6 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
);
}
function testKeepAbsoluteCSSWidthAndHeightOnImg() {
$this->assertResult(
'<img src="" alt="" style="width:10px;height:10px;border:1px solid #000;" />'
);
}
function testRemoveLargeCSSWidthAndHeightOnImg() {
$this->assertResult(
'<img src="" alt="" style="width:10000000px;height:10000000px;border:1px solid #000;" />',
'<img src="" alt="" style="border:1px solid #000;" />'
);
}
function testRemoveLargeCSSWidthAndHeightOnImgWithUserConf() {
$this->config->set('CSS', 'MaxImgLength', '1px');
$this->assertResult(
'<img src="" alt="" style="width:1mm;height:1mm;border:1px solid #000;" />',
'<img src="" alt="" style="border:1px solid #000;" />'
);
}
function testKeepLargeCSSWidthAndHeightOnImgWhenToldTo() {
$this->config->set('CSS', 'MaxImgLength', null);
$this->assertResult(
'<img src="" alt="" style="width:10000000px;height:10000000px;border:1px solid #000;" />'
);
}
function testKeepPercentCSSWidthAndHeightOnImgWhenToldTo() {
$this->config->set('CSS', 'MaxImgLength', null);
$this->assertResult(
'<img src="" alt="" style="width:100%;height:100%;border:1px solid #000;" />'
);
}
function testRemoveRelativeCSSWidthAndHeightOnImg() {
$this->assertResult(
'<img src="" alt="" style="width:10em;height:10em;border:1px solid #000;" />',
'<img src="" alt="" style="border:1px solid #000;" />'
);
}
function testRemovePercentCSSWidthAndHeightOnImg() {
$this->assertResult(
'<img src="" alt="" style="width:100%;height:100%;border:1px solid #000;" />',
'<img src="" alt="" style="border:1px solid #000;" />'
);
}
}

View File

@@ -16,13 +16,6 @@ class HTMLPurifier_URIParserTest extends HTMLPurifier_Harness
$this->assertEqual($result, $expect);
}
function testPercentNormalization() {
$this->assertParsing(
'%G',
null, null, null, null, '%25G', null, null
);
}
function testRegular() {
$this->assertParsing(
'http://www.example.com/webhp?q=foo#result2',
@@ -131,7 +124,7 @@ class HTMLPurifier_URIParserTest extends HTMLPurifier_Harness
function testMalformedTag() {
$this->assertParsing(
'http://www.example.com/>',
'http://www.example.com/\'>"',
'http', null, 'www.example.com', null, '/', null, null
);
}

View File

@@ -163,40 +163,4 @@ class HTMLPurifier_URITest extends HTMLPurifier_URIHarness
$this->assertValidation('http://[2001:0db8:85z3:08d3:1319:8a2e:0370:7334]', 'http:');
}
function test_validate_removeRedundantScheme() {
$this->assertValidation('http:foo:/:', 'foo%3A/:');
}
function test_validate_username() {
$this->assertValidation("http://user\xE3\x91\x94:@foo.com", 'http://user%E3%91%94:@foo.com');
}
function test_validate_path_abempty() {
$this->assertValidation("http://host/\xE3\x91\x94:", 'http://host/%E3%91%94:');
}
function test_validate_path_absolute() {
$this->assertValidation("/\xE3\x91\x94:", '/%E3%91%94:');
}
function test_validate_path_rootless() {
$this->assertValidation("mailto:\xE3\x91\x94:", 'mailto:%E3%91%94:');
}
function test_validate_path_noscheme() {
$this->assertValidation("\xE3\x91\x94", '%E3%91%94');
}
function test_validate_query() {
$this->assertValidation("?/\xE3\x91\x94", '?/%E3%91%94');
}
function test_validate_fragment() {
$this->assertValidation("#/\xE3\x91\x94", '#/%E3%91%94');
}
function test_validate_path_empty() {
$this->assertValidation('http://google.com');
}
}

Some files were not shown because too many files have changed in this diff Show More