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

Compare commits

...

23 Commits

Author SHA1 Message Date
Edward Z. Yang
d516e2f8de Release 4.5.0
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2013-02-17 16:04:08 -08:00
Edward Z. Yang
631021733b Add %Core.DisableExcludes directive
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2013-02-17 15:47:38 -08:00
Michael Tibben
344e0640b6 Add required constant for composer autoloading
Signed-off-by: Michael Tibben <michael.tibben@99designs.com>
2012-12-21 16:16:16 +08:00
Edward Z. Yang
62d2550e16 Use SHA-1 instead of MD5.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-10-27 02:33:22 -07:00
Edward Z. Yang
087145a71b Blacklist more tags from RemoveEmpty.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-10-27 02:32:48 -07:00
Edward Z. Yang
a44187a5c1 Cleanup after data validation.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-10-27 02:30:58 -07:00
Edward Z. Yang
c0ad68108a Do checks against iconvAvailable because PHP 5.4 has botched iconv support.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-10-27 02:27:57 -07:00
Edward Z. Yang
83a574491e Comment for bug that needs to get fixed.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-10-11 11:40:02 -07:00
Edward Z. Yang
3b537365a4 CSS properties page-break-*
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-10-11 11:39:52 -07:00
Rob Loach
8a8b123d33 Autoloading support for Composer 2012-09-16 18:11:46 +02:00
Edward Z. Yang
72db575446 Fix bug with non-lower case color names in HTML.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-07-30 10:54:32 -04:00
Edward Z. Yang
d8bb73ce46 Permit underscores in font-families.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-07-27 18:28:29 -04:00
Edward Z. Yang
f90372f8ab More support for white-space.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-06-16 17:10:36 -04:00
Edward Z. Yang
f38fca32a9 Don't lower-case components of background.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-06-02 11:22:58 -04:00
Edward Z. Yang
5a23004652 Support for inline-block.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-05-25 23:55:48 -04:00
Edward Z. Yang
6705140082 Fix in AttrTransform_Nofollow
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-05-14 23:07:27 -04:00
Edward Z. Yang
cb7162a995 Use prepend for autoloading on PHP 5.3+
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-05-02 11:07:24 -04:00
Edward Z. Yang
2189a9430f Support for safe external scripts via explicit whitelist.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-04-27 17:44:49 -04:00
Edward Z. Yang
7291f19347 Fix problem where stacked AttrTransforms clobber each other.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-03-16 23:12:16 -04:00
Benjamin Steininger
9fcffd6533 Add composer.json file for easy install via composer.
Composer: http://getcomposer.org/

Since HTML Purifier is not completely psr-0 compatible (a classmap is
not enough for autoloading), the package-description does not contain
anything autoload-related. The user has to include the autoloader
himself.

This lets us create an entry on packagist which allows installing HTML
Purifier without the need to declare a repository in projects; it also
makes it easy to create libraries which want to use HTML Purifier using
composer.

Signed-off-by: Benjamin Steininger <robo47@robo47.net>
2012-03-16 01:05:02 -04:00
Edward Z. Yang
31dce298ea Actually make URI.DisableResources do something.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-03-02 13:25:00 -05:00
Edward Z. Yang
8c9d461a62 Bugfix: _blank not blank.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-02-18 11:28:01 -05:00
Edward Z. Yang
7291a9647e Update NEWS.
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2012-01-25 07:06:30 -05:00
48 changed files with 352 additions and 98 deletions

2
.gitignore vendored
View File

@@ -20,3 +20,5 @@ docs/doxygen*
*.htmlt.ini *.htmlt.ini
*.patch *.patch
/*.php /*.php
vendor
composer.lock

View File

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

2
FOCUS
View File

@@ -1,4 +1,4 @@
8 - Minor security fixes 4 - Minor feature enhancements
[ Appendix A: Release focus IDs ] [ Appendix A: Release focus IDs ]
0 - N/A 0 - N/A

26
NEWS
View File

@@ -9,6 +9,30 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Internal change . Internal change
========================== ==========================
4.5.0, released 2013-02-17
# Fix bug where stacked attribute transforms clobber each other;
this also means it's no longer possible to override attribute
transforms in later modules. No internal code was using this
but this may break some clients.
# We now use SHA-1 to identify cached definitions, instead of MD5.
! Support display:inline-block
! Support for more white-space CSS values.
! Permit underscores in font families
! Support for page-break-* CSS3 properties when proprietary properties
are enabled.
! New directive %Core.EnableExcludes; can be set to 'false' to turn off
SGML excludes checking. If HTML Purifier is removing too much text
and you don't care about full standards compliance, try setting this to
'false'.
- Use prepend for SPL autoloading on PHP 5.3 and later.
- Fix bug with nofollow transform when pre-existing rel exists.
- Fix bug where background:url() always gets lower-cased
(but not background-image:url())
- Fix bug with non lower-case color names in HTML
- Fix bug where data URI validation doesn't remove temporary files.
Thanks Javier Marín Ros <javiermarinros@gmail.com> for reporting.
- Don't remove certain empty tags on RemoveEmpty.
4.4.0, released 2012-01-18 4.4.0, released 2012-01-18
# Removed PEARSax3 handler. # Removed PEARSax3 handler.
# URI.Munge now munges URIs inside the same host that go from https # URI.Munge now munges URIs inside the same host that go from https
@@ -21,7 +45,7 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
:lang pseudoselector, and anything not in CSS2.1. Furthermore, :lang pseudoselector, and anything not in CSS2.1. Furthermore,
ID and class selectors now work properly with the relevant ID and class selectors now work properly with the relevant
configuration attributes. Also, mute errors when parsing CSS configuration attributes. Also, mute errors when parsing CSS
with CSS Tidy. with CSS Tidy. Reported by Mario Heiderich and Norman Hippert.
! Added support for 'scope' attribute on tables. ! Added support for 'scope' attribute on tables.
! Added %HTML.TargetBlank, which adds target="blank" to all outgoing links. ! Added %HTML.TargetBlank, which adds target="blank" to all outgoing links.
! Properly handle sub-lists directly nested inside of lists in ! Properly handle sub-lists directly nested inside of lists in

3
TODO
View File

@@ -13,6 +13,7 @@ afraid to cast your vote for the next feature to be implemented!
Things to do as soon as possible: Things to do as soon as possible:
- http://htmlpurifier.org/phorum/read.php?3,5560,6307#msg-6307
- Think about allowing explicit order of operations hooks for transforms - Think about allowing explicit order of operations hooks for transforms
- Fix "<.<" bug (trailing < is removed if not EOD) - Fix "<.<" bug (trailing < is removed if not EOD)
- Build in better internal state dumps and debugging tools for remote - Build in better internal state dumps and debugging tools for remote
@@ -31,7 +32,7 @@ Things to do as soon as possible:
FUTURE VERSIONS FUTURE VERSIONS
--------------- ---------------
4.5 release [OMG CONFIG PONIES] 4.6 release [OMG CONFIG PONIES]
! Fix Printer. It's from the old days when we didn't have decent XML classes ! Fix Printer. It's from the old days when we didn't have decent XML classes
! Factor demo.php into a set of Printer classes, and then create a stub ! Factor demo.php into a set of Printer classes, and then create a stub
file for users here (inside the actual HTML Purifier library) file for users here (inside the actual HTML Purifier library)

View File

@@ -1 +1 @@
4.4.0 4.5.0

View File

@@ -1,8 +1,6 @@
HTML Purifier 4.4.0 is a minor security release addressing a security HTML Purifier 4.5.0 is a minor bugfix and feature release, containing an
vulnerability associated with some optional functionality. It also accumulation of changes over a year. CSS support has been extended to
contains an accumulation of new features and bugfixes over half a year. support display:inline-block, white-space, underscores in font families,
New configuration options include %HTML.TargetBlank, page-break-* CSS3 properties (when proprietary is enabled.) We now use
%HTML.AllowedComments, %HTML.AllowedCommentsRegexp, %HTML.SafeIframe, SHA-1 to identify cached definitions, and the semantics of stacked
%URI.SafeIframeRegexp, %Core.EnableIDNA (requires PEAR Net_IDNA2 module and attribute transforms has changed slightly.
doesn't work for PHP 5.0.5). We also now support the 'scope' attribute on
tables.

22
composer.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "ezyang/htmlpurifier",
"description": "Standards compliant HTML filter written in PHP",
"type": "library",
"keywords": ["html"],
"homepage": "http://htmlpurifier.org/",
"license": "LGPL",
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"require": {
"php": ">=5.2"
},
"autoload": {
"psr-0": { "HTMLPurifier": "library/" },
"files": ["library/HTMLPurifier.composer.php"]
}
}

View File

@@ -24,32 +24,32 @@
</directive> </directive>
<directive id="CSS.Proprietary"> <directive id="CSS.Proprietary">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>214</line> <line>215</line>
</file> </file>
</directive> </directive>
<directive id="CSS.AllowTricky"> <directive id="CSS.AllowTricky">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>218</line> <line>219</line>
</file> </file>
</directive> </directive>
<directive id="CSS.Trusted"> <directive id="CSS.Trusted">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>222</line> <line>223</line>
</file> </file>
</directive> </directive>
<directive id="CSS.AllowImportant"> <directive id="CSS.AllowImportant">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>226</line> <line>227</line>
</file> </file>
</directive> </directive>
<directive id="CSS.AllowedProperties"> <directive id="CSS.AllowedProperties">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>296</line> <line>302</line>
</file> </file>
</directive> </directive>
<directive id="CSS.ForbiddenProperties"> <directive id="CSS.ForbiddenProperties">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>310</line> <line>316</line>
</file> </file>
</directive> </directive>
<directive id="Cache.DefinitionImpl"> <directive id="Cache.DefinitionImpl">
@@ -80,18 +80,18 @@
<directive id="Core.Encoding"> <directive id="Core.Encoding">
<file name="HTMLPurifier/Encoder.php"> <file name="HTMLPurifier/Encoder.php">
<line>337</line> <line>337</line>
<line>367</line> <line>372</line>
</file> </file>
</directive> </directive>
<directive id="Test.ForceNoIconv"> <directive id="Test.ForceNoIconv">
<file name="HTMLPurifier/Encoder.php"> <file name="HTMLPurifier/Encoder.php">
<line>341</line> <line>341</line>
<line>374</line> <line>379</line>
</file> </file>
</directive> </directive>
<directive id="Core.EscapeNonASCIICharacters"> <directive id="Core.EscapeNonASCIICharacters">
<file name="HTMLPurifier/Encoder.php"> <file name="HTMLPurifier/Encoder.php">
<line>368</line> <line>373</line>
</file> </file>
</directive> </directive>
<directive id="Output.CommentScriptContents"> <directive id="Output.CommentScriptContents">
@@ -209,14 +209,22 @@
<line>228</line> <line>228</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Nofollow"> <directive id="HTML.SafeScripting">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>231</line> <line>231</line>
</file> </file>
<file name="HTMLPurifier/HTMLModule/SafeScripting.php">
<line>17</line>
</file>
</directive>
<directive id="HTML.Nofollow">
<file name="HTMLPurifier/HTMLModuleManager.php">
<line>234</line>
</file>
</directive> </directive>
<directive id="HTML.TargetBlank"> <directive id="HTML.TargetBlank">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>234</line> <line>237</line>
</file> </file>
</directive> </directive>
<directive id="Attr.IDBlacklist"> <directive id="Attr.IDBlacklist">
@@ -254,7 +262,7 @@
</directive> </directive>
<directive id="URI."> <directive id="URI.">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>59</line> <line>60</line>
</file> </file>
<file name="HTMLPurifier/URIFilter/Munge.php"> <file name="HTMLPurifier/URIFilter/Munge.php">
<line>12</line> <line>12</line>
@@ -262,7 +270,7 @@
</directive> </directive>
<directive id="URI.Host"> <directive id="URI.Host">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>69</line> <line>70</line>
</file> </file>
<file name="HTMLPurifier/URIScheme.php"> <file name="HTMLPurifier/URIScheme.php">
<line>81</line> <line>81</line>
@@ -270,12 +278,12 @@
</directive> </directive>
<directive id="URI.Base"> <directive id="URI.Base">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>70</line> <line>71</line>
</file> </file>
</directive> </directive>
<directive id="URI.DefaultScheme"> <directive id="URI.DefaultScheme">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>77</line> <line>78</line>
</file> </file>
</directive> </directive>
<directive id="URI.AllowedSchemes"> <directive id="URI.AllowedSchemes">
@@ -411,17 +419,17 @@
</directive> </directive>
<directive id="Filter.ExtractStyleBlocks.TidyImpl"> <directive id="Filter.ExtractStyleBlocks.TidyImpl">
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php"> <file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
<line>54</line> <line>55</line>
</file> </file>
</directive> </directive>
<directive id="Filter.ExtractStyleBlocks.Scope"> <directive id="Filter.ExtractStyleBlocks.Scope">
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php"> <file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
<line>78</line> <line>79</line>
</file> </file>
</directive> </directive>
<directive id="Filter.ExtractStyleBlocks.Escaping"> <directive id="Filter.ExtractStyleBlocks.Escaping">
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php"> <file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
<line>276</line> <line>277</line>
</file> </file>
</directive> </directive>
<directive id="HTML.SafeIframe"> <directive id="HTML.SafeIframe">
@@ -465,12 +473,12 @@
</directive> </directive>
<directive id="AutoFormat.RemoveEmpty.RemoveNbsp"> <directive id="AutoFormat.RemoveEmpty.RemoveNbsp">
<file name="HTMLPurifier/Injector/RemoveEmpty.php"> <file name="HTMLPurifier/Injector/RemoveEmpty.php">
<line>12</line> <line>15</line>
</file> </file>
</directive> </directive>
<directive id="AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions"> <directive id="AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions">
<file name="HTMLPurifier/Injector/RemoveEmpty.php"> <file name="HTMLPurifier/Injector/RemoveEmpty.php">
<line>13</line> <line>16</line>
</file> </file>
</directive> </directive>
<directive id="Core.AggressivelyFixLt"> <directive id="Core.AggressivelyFixLt">
@@ -483,6 +491,11 @@
<line>70</line> <line>70</line>
</file> </file>
</directive> </directive>
<directive id="Core.DisableExcludes">
<file name="HTMLPurifier/Strategy/FixNesting.php">
<line>57</line>
</file>
</directive>
<directive id="Core.EscapeInvalidTags"> <directive id="Core.EscapeInvalidTags">
<file name="HTMLPurifier/Strategy/MakeWellFormed.php"> <file name="HTMLPurifier/Strategy/MakeWellFormed.php">
<line>53</line> <line>53</line>

View File

@@ -0,0 +1,4 @@
<?php
if (!defined('HTMLPURIFIER_PREFIX')) {
define('HTMLPURIFIER_PREFIX', __DIR__);
}

View File

@@ -7,7 +7,7 @@
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
* FILE, changes will be overwritten the next time the script is run. * FILE, changes will be overwritten the next time the script is run.
* *
* @version 4.4.0 * @version 4.5.0
* *
* @warning * @warning
* You must *not* include any other HTML Purifier files before this file, * You must *not* include any other HTML Purifier files before this file,
@@ -165,6 +165,7 @@ require 'HTMLPurifier/HTMLModule/Proprietary.php';
require 'HTMLPurifier/HTMLModule/Ruby.php'; require 'HTMLPurifier/HTMLModule/Ruby.php';
require 'HTMLPurifier/HTMLModule/SafeEmbed.php'; require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
require 'HTMLPurifier/HTMLModule/SafeObject.php'; require 'HTMLPurifier/HTMLModule/SafeObject.php';
require 'HTMLPurifier/HTMLModule/SafeScripting.php';
require 'HTMLPurifier/HTMLModule/Scripting.php'; require 'HTMLPurifier/HTMLModule/Scripting.php';
require 'HTMLPurifier/HTMLModule/StyleAttribute.php'; require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
require 'HTMLPurifier/HTMLModule/Tables.php'; require 'HTMLPurifier/HTMLModule/Tables.php';

View File

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

View File

@@ -159,6 +159,7 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeScripting.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';

View File

@@ -32,7 +32,7 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
$string = $this->mungeRgb($string); $string = $this->mungeRgb($string);
// assumes URI doesn't have spaces in it // assumes URI doesn't have spaces in it
$bits = explode(' ', strtolower($string)); // bits to process $bits = explode(' ', $string); // bits to process
$caught = array(); $caught = array();
$caught['color'] = false; $caught['color'] = false;

View File

@@ -9,7 +9,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
protected $mask = null; protected $mask = null;
public function __construct() { public function __construct() {
$this->mask = '- '; $this->mask = '_- ';
for ($c = 'a'; $c <= 'z'; $c++) $this->mask .= $c; for ($c = 'a'; $c <= 'z'; $c++) $this->mask .= $c;
for ($c = 'A'; $c <= 'Z'; $c++) $this->mask .= $c; for ($c = 'A'; $c <= 'Z'; $c++) $this->mask .= $c;
for ($c = '0'; $c <= '9'; $c++) $this->mask .= $c; // cast-y, but should be fine for ($c = '0'; $c <= '9'; $c++) $this->mask .= $c; // cast-y, but should be fine
@@ -165,7 +165,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
// extensive research, we may feel comfortable with dropping // extensive research, we may feel comfortable with dropping
// it down to edgy. // it down to edgy.
// Edgy: alphanumeric, spaces, dashes and Unicode. Use of // Edgy: alphanumeric, spaces, dashes, underscores and Unicode. Use of
// str(c)spn assumes that the string was already well formed // str(c)spn assumes that the string was already well formed
// Unicode (which of course it is). // Unicode (which of course it is).
if (strspn($font, $this->mask) !== strlen($font)) { if (strspn($font, $this->mask) !== strlen($font)) {

View File

@@ -14,7 +14,8 @@ class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
$string = trim($string); $string = trim($string);
if (empty($string)) return false; if (empty($string)) return false;
if (isset($colors[strtolower($string)])) return $colors[$string]; $lower = strtolower($string);
if (isset($colors[$lower])) return $colors[$lower];
if ($string[0] === '#') $hex = substr($string, 1); if ($string[0] === '#') $hex = substr($string, 1);
else $hex = $string; else $hex = $string;

View File

@@ -26,7 +26,7 @@ class HTMLPurifier_AttrTransform_Nofollow extends HTMLPurifier_AttrTransform
if ($scheme->browsable && !$url->isLocal($config, $context)) { if ($scheme->browsable && !$url->isLocal($config, $context)) {
if (isset($attr['rel'])) { if (isset($attr['rel'])) {
$rels = explode(' ', $attr); $rels = explode(' ', $attr['rel']);
if (!in_array('nofollow', $rels)) { if (!in_array('nofollow', $rels)) {
$rels[] = 'nofollow'; $rels[] = 'nofollow';
} }

View File

@@ -26,7 +26,7 @@ class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform
$scheme = $url->getSchemeObj($config, $context); $scheme = $url->getSchemeObj($config, $context);
if ($scheme->browsable && !$url->isBenign($config, $context)) { if ($scheme->browsable && !$url->isBenign($config, $context)) {
$attr['target'] = 'blank'; $attr['target'] = '_blank';
} }
return $attr; return $attr;

View File

@@ -70,32 +70,37 @@ class HTMLPurifier_Bootstrap
if ( ($funcs = spl_autoload_functions()) === false ) { if ( ($funcs = spl_autoload_functions()) === false ) {
spl_autoload_register($autoload); spl_autoload_register($autoload);
} elseif (function_exists('spl_autoload_unregister')) { } elseif (function_exists('spl_autoload_unregister')) {
$buggy = version_compare(PHP_VERSION, '5.2.11', '<'); if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
$compat = version_compare(PHP_VERSION, '5.1.2', '<=') && // prepend flag exists, no need for shenanigans
version_compare(PHP_VERSION, '5.1.0', '>='); spl_autoload_register($autoload, true, true);
foreach ($funcs as $func) { } else {
if ($buggy && is_array($func)) { $buggy = version_compare(PHP_VERSION, '5.2.11', '<');
// :TRICKY: There are some compatibility issues and some $compat = version_compare(PHP_VERSION, '5.1.2', '<=') &&
// places where we need to error out version_compare(PHP_VERSION, '5.1.0', '>=');
$reflector = new ReflectionMethod($func[0], $func[1]); foreach ($funcs as $func) {
if (!$reflector->isStatic()) { if ($buggy && is_array($func)) {
throw new Exception(' // :TRICKY: There are some compatibility issues and some
HTML Purifier autoloader registrar is not compatible // places where we need to error out
with non-static object methods due to PHP Bug #44144; $reflector = new ReflectionMethod($func[0], $func[1]);
Please do not use HTMLPurifier.autoload.php (or any if (!$reflector->isStatic()) {
file that includes this file); instead, place the code: throw new Exception('
spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\')) HTML Purifier autoloader registrar is not compatible
after your own autoloaders. with non-static object methods due to PHP Bug #44144;
'); Please do not use HTMLPurifier.autoload.php (or any
file that includes this file); instead, place the code:
spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\'))
after your own autoloaders.
');
}
// Suprisingly, spl_autoload_register supports the
// Class::staticMethod callback format, although call_user_func doesn't
if ($compat) $func = implode('::', $func);
} }
// Suprisingly, spl_autoload_register supports the spl_autoload_unregister($func);
// Class::staticMethod callback format, although call_user_func doesn't
if ($compat) $func = implode('::', $func);
} }
spl_autoload_unregister($func); spl_autoload_register($autoload);
foreach ($funcs as $func) spl_autoload_register($func);
} }
spl_autoload_register($autoload);
foreach ($funcs as $func) spl_autoload_register($func);
} }
} }

View File

@@ -208,8 +208,9 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
$this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2); $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2);
// partial support // These CSS properties don't work on many browsers, but we live
$this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap')); // in THE FUTURE!
$this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line'));
if ($config->get('CSS.Proprietary')) { if ($config->get('CSS.Proprietary')) {
$this->doSetupProprietary($config); $this->doSetupProprietary($config);
@@ -249,12 +250,17 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
// only opacity, for now // only opacity, for now
$this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter(); $this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter();
// more CSS3
$this->info['page-break-after'] =
$this->info['page-break-before'] = new HTMLPurifier_AttrDef_Enum(array('auto','always','avoid','left','right'));
$this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(array('auto','avoid'));
} }
protected function doSetupTricky($config) { protected function doSetupTricky($config) {
$this->info['display'] = new HTMLPurifier_AttrDef_Enum(array( $this->info['display'] = new HTMLPurifier_AttrDef_Enum(array(
'inline', 'block', 'list-item', 'run-in', 'compact', 'inline', 'block', 'list-item', 'run-in', 'compact',
'marker', 'table', 'inline-table', 'table-row-group', 'marker', 'table', 'inline-block', 'inline-table', 'table-row-group',
'table-header-group', 'table-footer-group', 'table-row', 'table-header-group', 'table-footer-group', 'table-row',
'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none' 'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none'
)); ));

View File

@@ -20,7 +20,7 @@ class HTMLPurifier_Config
/** /**
* HTML Purifier's version * HTML Purifier's version
*/ */
public $version = '4.4.0'; public $version = '4.5.0';
/** /**
* Bool indicator whether or not to automatically finalize * Bool indicator whether or not to automatically finalize
@@ -189,7 +189,7 @@ class HTMLPurifier_Config
} }
/** /**
* Returns a md5 signature of a segment of the configuration object * Returns a SHA-1 signature of a segment of the configuration object
* that uniquely identifies that particular configuration * that uniquely identifies that particular configuration
* @note Revision is handled specially and is removed from the batch * @note Revision is handled specially and is removed from the batch
* before processing! * before processing!
@@ -199,18 +199,18 @@ class HTMLPurifier_Config
if (empty($this->serials[$namespace])) { if (empty($this->serials[$namespace])) {
$batch = $this->getBatch($namespace); $batch = $this->getBatch($namespace);
unset($batch['DefinitionRev']); unset($batch['DefinitionRev']);
$this->serials[$namespace] = md5(serialize($batch)); $this->serials[$namespace] = sha1(serialize($batch));
} }
return $this->serials[$namespace]; return $this->serials[$namespace];
} }
/** /**
* Returns a md5 signature for the entire configuration object * Returns a SHA-1 signature for the entire configuration object
* that uniquely identifies that particular configuration * that uniquely identifies that particular configuration
*/ */
public function getSerial() { public function getSerial() {
if (empty($this->serial)) { if (empty($this->serial)) {
$this->serial = md5(serialize($this->getAll())); $this->serial = sha1(serialize($this->getAll()));
} }
return $this->serial; return $this->serial;
} }
@@ -682,6 +682,7 @@ class HTMLPurifier_Config
$trace = debug_backtrace(); $trace = debug_backtrace();
// zip(tail(trace), trace) -- but PHP is not Haskell har har // zip(tail(trace), trace) -- but PHP is not Haskell har har
for ($i = 0, $c = count($trace); $i < $c - 1; $i++) { for ($i = 0, $c = count($trace); $i < $c - 1; $i++) {
// XXX this is not correct on some versions of HTML Purifier
if ($trace[$i + 1]['class'] === 'HTMLPurifier_Config') { if ($trace[$i + 1]['class'] === 'HTMLPurifier_Config') {
continue; continue;
} }

View File

@@ -0,0 +1,14 @@
Core.DisableExcludes
TYPE: bool
DEFAULT: false
VERSION: 4.5.0
--DESCRIPTION--
<p>
This directive disables SGML-style exclusions, e.g. the exclusion of
<code>&lt;object&gt;</code> in any descendant of a
<code>&lt;pre&gt;</code> tag. Disabling excludes will allow some
invalid documents to pass through HTML Purifier, but HTML Purifier
will also be less likely to accidentally remove large documents during
processing.
</p>
--# vim: et sw=4 sts=4

View File

@@ -0,0 +1,10 @@
HTML.SafeScripting
TYPE: lookup
VERSION: 4.5.0
DEFAULT: array()
--DESCRIPTION--
<p>
Whether or not to permit script tags to external scripts in documents.
Inline scripting is not allowed, and the script must match an explicit whitelist.
</p>
--# vim: et sw=4 sts=4

View File

@@ -30,13 +30,25 @@ class HTMLPurifier_ElementDef
*/ */
public $attr = array(); public $attr = array();
// XXX: Design note: currently, it's not possible to override
// previously defined AttrTransforms without messing around with
// the final generated config. This is by design; a previous version
// used an associated list of attr_transform, but it was extremely
// easy to accidentally override other attribute transforms by
// forgetting to specify an index (and just using 0.) While we
// could check this by checking the index number and complaining,
// there is a second problem which is that it is not at all easy to
// tell when something is getting overridden. Combine this with a
// codebase where this isn't really being used, and it's perfect for
// nuking.
/** /**
* Indexed list of tag's HTMLPurifier_AttrTransform to be done before validation * List of tags HTMLPurifier_AttrTransform to be done before validation
*/ */
public $attr_transform_pre = array(); public $attr_transform_pre = array();
/** /**
* Indexed list of tag's HTMLPurifier_AttrTransform to be done after validation * List of tags HTMLPurifier_AttrTransform to be done after validation
*/ */
public $attr_transform_post = array(); public $attr_transform_post = array();
@@ -144,9 +156,9 @@ class HTMLPurifier_ElementDef
} }
$this->attr[$k] = $v; $this->attr[$k] = $v;
} }
$this->_mergeAssocArray($this->attr_transform_pre, $def->attr_transform_pre);
$this->_mergeAssocArray($this->attr_transform_post, $def->attr_transform_post);
$this->_mergeAssocArray($this->excludes, $def->excludes); $this->_mergeAssocArray($this->excludes, $def->excludes);
$this->attr_transform_pre = array_merge($this->attr_transform_pre, $def->attr_transform_pre);
$this->attr_transform_post = array_merge($this->attr_transform_post, $def->attr_transform_post);
if(!empty($def->content_model)) { if(!empty($def->content_model)) {
$this->content_model = $this->content_model =

View File

@@ -355,7 +355,12 @@ class HTMLPurifier_Encoder
$str = utf8_encode($str); $str = utf8_encode($str);
return $str; return $str;
} }
trigger_error('Encoding not supported, please install iconv', E_USER_ERROR); $bug = HTMLPurifier_Encoder::testIconvTruncateBug();
if ($bug == self::ICONV_OK) {
trigger_error('Encoding not supported, please install iconv', E_USER_ERROR);
} else {
trigger_error('You have a buggy version of iconv, see https://bugs.php.net/bug.php?id=48147 and http://sourceware.org/bugzilla/show_bug.cgi?id=13541', E_USER_ERROR);
}
} }
/** /**

View File

@@ -33,6 +33,7 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
public function __construct() { public function __construct() {
$this->_tidy = new csstidy(); $this->_tidy = new csstidy();
$this->_tidy->set_cfg('lowercase_s', false);
$this->_id_attrdef = new HTMLPurifier_AttrDef_HTML_ID(true); $this->_id_attrdef = new HTMLPurifier_AttrDef_HTML_ID(true);
$this->_class_attrdef = new HTMLPurifier_AttrDef_CSS_Ident(); $this->_class_attrdef = new HTMLPurifier_AttrDef_CSS_Ident();
$this->_enum_attrdef = new HTMLPurifier_AttrDef_Enum(array('first-child', 'link', 'visited', 'active', 'hover', 'focus')); $this->_enum_attrdef = new HTMLPurifier_AttrDef_Enum(array('first-child', 'link', 'visited', 'active', 'hover', 'focus'));

View File

@@ -21,7 +21,7 @@ class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule
// inclusions wrong for bdo: bdo allows Lang // inclusions wrong for bdo: bdo allows Lang
) )
); );
$bdo->attr_transform_post['required-dir'] = new HTMLPurifier_AttrTransform_BdoDir(); $bdo->attr_transform_post[] = new HTMLPurifier_AttrTransform_BdoDir();
$this->attr_collections['I18N']['dir'] = 'Enum#ltr,rtl'; $this->attr_collections['I18N']['dir'] = 'Enum#ltr,rtl';
} }

View File

@@ -11,7 +11,7 @@ class HTMLPurifier_HTMLModule_Name extends HTMLPurifier_HTMLModule
$element = $this->addBlankElement($name); $element = $this->addBlankElement($name);
$element->attr['name'] = 'CDATA'; $element->attr['name'] = 'CDATA';
if (!$config->get('HTML.Attr.Name.UseCDATA')) { if (!$config->get('HTML.Attr.Name.UseCDATA')) {
$element->attr_transform_post['NameSync'] = new HTMLPurifier_AttrTransform_NameSync(); $element->attr_transform_post[] = new HTMLPurifier_AttrTransform_NameSync();
} }
} }
} }

View File

@@ -0,0 +1,37 @@
<?php
/**
* A "safe" script module. No inline JS is allowed, and pointed to JS
* files must match whitelist.
*/
class HTMLPurifier_HTMLModule_SafeScripting extends HTMLPurifier_HTMLModule
{
public $name = 'SafeScripting';
public function setup($config) {
// These definitions are not intrinsically safe: the attribute transforms
// are a vital part of ensuring safety.
$allowed = $config->get('HTML.SafeScripting');
$script = $this->addElement(
'script',
'Inline',
'Empty',
null,
array(
// While technically not required by the spec, we're forcing
// it to this value.
'type' => 'Enum#text/javascript',
'src*' => new HTMLPurifier_AttrDef_Enum(array_keys($allowed))
)
);
$script->attr_transform_pre[] =
$script->attr_transform_post[] = new HTMLPurifier_AttrTransform_ScriptRequired();
}
}
// vim: et sw=4 sts=4

View File

@@ -45,8 +45,8 @@ class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
); );
$this->info['script']->content_model = '#PCDATA'; $this->info['script']->content_model = '#PCDATA';
$this->info['script']->content_model_type = 'optional'; $this->info['script']->content_model_type = 'optional';
$this->info['script']->attr_transform_pre['type'] = $this->info['script']->attr_transform_pre[] =
$this->info['script']->attr_transform_post['type'] = $this->info['script']->attr_transform_post[] =
new HTMLPurifier_AttrTransform_ScriptRequired(); new HTMLPurifier_AttrTransform_ScriptRequired();
} }
} }

View File

@@ -228,6 +228,9 @@ class HTMLPurifier_HTMLModuleManager
if ($config->get('HTML.SafeEmbed')) { if ($config->get('HTML.SafeEmbed')) {
$modules[] = 'SafeEmbed'; $modules[] = 'SafeEmbed';
} }
if ($config->get('HTML.SafeScripting') !== array()) {
$modules[] = 'SafeScripting';
}
if ($config->get('HTML.Nofollow')) { if ($config->get('HTML.Nofollow')) {
$modules[] = 'Nofollow'; $modules[] = 'Nofollow';
} }

View File

@@ -5,6 +5,9 @@ class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
private $context, $config, $attrValidator, $removeNbsp, $removeNbspExceptions; private $context, $config, $attrValidator, $removeNbsp, $removeNbspExceptions;
// TODO: make me configurable
private $_exclude = array('colgroup' => 1, 'th' => 1, 'td' => 1, 'iframe' => 1);
public function prepare($config, $context) { public function prepare($config, $context) {
parent::prepare($config, $context); parent::prepare($config, $context);
$this->config = $config; $this->config = $config;
@@ -30,7 +33,7 @@ class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
break; break;
} }
if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) { if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) {
if ($token->name == 'colgroup') return; if (isset($this->_exclude[$token->name])) return;
$this->attrValidator->validateToken($token, $this->config, $this->context); $this->attrValidator->validateToken($token, $this->config, $this->context);
$token->armor['ValidateAttributes'] = true; $token->armor['ValidateAttributes'] = true;
if (isset($token->attr['id']) || isset($token->attr['name'])) return; if (isset($token->attr['id']) || isset($token->attr['name'])) return;

View File

@@ -26,6 +26,22 @@
* translated into text depends on the child definitions. * translated into text depends on the child definitions.
* *
* @todo Enable nodes to be bubbled out of the structure. * @todo Enable nodes to be bubbled out of the structure.
*
* @warning This algorithm (though it may be hard to see) proceeds from
* a top-down fashion. Thus, parents are processed before
* children. This is easy to implement and has a nice effiency
* benefit, in that if a node is removed, we never waste any
* time processing it, but it also means that if a child
* changes in a non-encapsulated way (e.g. it is removed), we
* need to go back and reprocess the parent to see if those
* changes resulted in problems for the parent. See
* [BACKTRACK] for an example of this. In the current
* implementation, this backtracking can only be triggered when
* a node is removed and if that node was the sole node, the
* parent would need to be removed. As such, it is easy to see
* that backtracking only incurs constant overhead. If more
* sophisticated backtracking is implemented, care must be
* taken to avoid nontermination or exponential blowup.
*/ */
class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
@@ -38,6 +54,8 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// get a copy of the HTML definition // get a copy of the HTML definition
$definition = $config->getHTMLDefinition(); $definition = $config->getHTMLDefinition();
$excludes_enabled = !$config->get('Core.DisableExcludes');
// insert implicit "parent" node, will be removed at end. // insert implicit "parent" node, will be removed at end.
// DEFINITION CALL // DEFINITION CALL
$parent_name = $definition->info_parent; $parent_name = $definition->info_parent;
@@ -147,7 +165,7 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// parent exclusions. The array should not be very large, two // parent exclusions. The array should not be very large, two
// elements at most. // elements at most.
$excluded = false; $excluded = false;
if (!empty($exclude_stack)) { if (!empty($exclude_stack) && $excludes_enabled) {
foreach ($exclude_stack as $lookup) { foreach ($exclude_stack as $lookup) {
if (isset($lookup[$tokens[$i]->name])) { if (isset($lookup[$tokens[$i]->name])) {
$excluded = true; $excluded = true;
@@ -235,7 +253,7 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
// our current implementation claims that that case would // our current implementation claims that that case would
// not allow empty, even if it did // not allow empty, even if it did
if (!$parent_def->child->allow_empty) { if (!$parent_def->child->allow_empty) {
// we need to do a double-check // we need to do a double-check [BACKTRACK]
$i = $parent_index; $i = $parent_index;
array_pop($stack); array_pop($stack);
} }

View File

@@ -26,6 +26,7 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
public function __construct() { public function __construct() {
$this->registerFilter(new HTMLPurifier_URIFilter_DisableExternal()); $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternal());
$this->registerFilter(new HTMLPurifier_URIFilter_DisableExternalResources()); $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternalResources());
$this->registerFilter(new HTMLPurifier_URIFilter_DisableResources());
$this->registerFilter(new HTMLPurifier_URIFilter_HostBlacklist()); $this->registerFilter(new HTMLPurifier_URIFilter_HostBlacklist());
$this->registerFilter(new HTMLPurifier_URIFilter_SafeIframe()); $this->registerFilter(new HTMLPurifier_URIFilter_SafeIframe());
$this->registerFilter(new HTMLPurifier_URIFilter_MakeAbsolute()); $this->registerFilter(new HTMLPurifier_URIFilter_MakeAbsolute());

View File

@@ -64,10 +64,12 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
file_put_contents($file, $raw_data); file_put_contents($file, $raw_data);
if (function_exists('exif_imagetype')) { if (function_exists('exif_imagetype')) {
$image_code = exif_imagetype($file); $image_code = exif_imagetype($file);
unlink($file);
} elseif (function_exists('getimagesize')) { } elseif (function_exists('getimagesize')) {
set_error_handler(array($this, 'muteErrorHandler')); set_error_handler(array($this, 'muteErrorHandler'));
$info = getimagesize($file); $info = getimagesize($file);
restore_error_handler(); restore_error_handler();
unlink($file);
if ($info == false) return false; if ($info == false) return false;
$image_code = $info[2]; $image_code = $info[2];
} else { } else {

View File

@@ -9,6 +9,7 @@ class HTMLPurifier_AttrDef_HTML_ColorTest extends HTMLPurifier_AttrDefHarness
$this->assertDef('foo', false); $this->assertDef('foo', false);
$this->assertDef('43', false); $this->assertDef('43', false);
$this->assertDef('red', '#FF0000'); $this->assertDef('red', '#FF0000');
$this->assertDef('RED', '#FF0000');
$this->assertDef('#FF0000'); $this->assertDef('#FF0000');
$this->assertDef('#453443'); $this->assertDef('#453443');
$this->assertDef('453443', '#453443'); $this->assertDef('453443', '#453443');

View File

@@ -22,12 +22,16 @@ class HTMLPurifier_ElementDefTest extends HTMLPurifier_Harness
'overloaded-attr' => $overloaded_old, 'overloaded-attr' => $overloaded_old,
'removed-attr' => $removed, 'removed-attr' => $removed,
); );
/*
$def1->attr_transform_pre = $def1->attr_transform_pre =
$def1->attr_transform_post = array( $def1->attr_transform_post = array(
'old-transform' => $old, 'old-transform' => $old,
'overloaded-transform' => $overloaded_old, 'overloaded-transform' => $overloaded_old,
'removed-transform' => $removed, 'removed-transform' => $removed,
); );
*/
$def1->attr_transform_pre[] = $old;
$def1->attr_transform_post[] = $old;
$def1->child = $overloaded_old; $def1->child = $overloaded_old;
$def1->content_model = 'old'; $def1->content_model = 'old';
$def1->content_model_type = $overloaded_old; $def1->content_model_type = $overloaded_old;
@@ -44,12 +48,16 @@ class HTMLPurifier_ElementDefTest extends HTMLPurifier_Harness
'overloaded-attr' => $overloaded_new, 'overloaded-attr' => $overloaded_new,
'removed-attr' => false, 'removed-attr' => false,
); );
/*
$def2->attr_transform_pre = $def2->attr_transform_pre =
$def2->attr_transform_post = array( $def2->attr_transform_post = array(
'new-transform' => $new, 'new-transform' => $new,
'overloaded-transform' => $overloaded_new, 'overloaded-transform' => $overloaded_new,
'removed-transform' => false, 'removed-transform' => false,
); );
*/
$def2->attr_transform_pre[] = $new;
$def2->attr_transform_post[] = $new;
$def2->child = $new; $def2->child = $new;
$def2->content_model = '#SUPER | new'; $def2->content_model = '#SUPER | new';
$def2->content_model_type = $overloaded_new; $def2->content_model_type = $overloaded_new;
@@ -70,11 +78,14 @@ class HTMLPurifier_ElementDefTest extends HTMLPurifier_Harness
'new-attr' => $new, 'new-attr' => $new,
)); ));
$this->assertIdentical($def1->attr_transform_pre, $def1->attr_transform_post); $this->assertIdentical($def1->attr_transform_pre, $def1->attr_transform_post);
$this->assertIdentical($def1->attr_transform_pre, array($old, $new));
/*
$this->assertIdentical($def1->attr_transform_pre, array( $this->assertIdentical($def1->attr_transform_pre, array(
'old-transform' => $old, 'old-transform' => $old,
'overloaded-transform' => $overloaded_new, 'overloaded-transform' => $overloaded_new,
'new-transform' => $new, 'new-transform' => $new,
)); ));
*/
$this->assertIdentical($def1->child, $new); $this->assertIdentical($def1->child, $new);
$this->assertIdentical($def1->content_model, 'old | new'); $this->assertIdentical($def1->content_model, 'old | new');
$this->assertIdentical($def1->content_model_type, $overloaded_new); $this->assertIdentical($def1->content_model_type, $overloaded_new);

View File

@@ -39,6 +39,7 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
} }
function test_convertToUTF8_spuriousEncoding() { function test_convertToUTF8_spuriousEncoding() {
if (!HTMLPurifier_Encoder::iconvAvailable()) return;
$this->config->set('Core.Encoding', 'utf99'); $this->config->set('Core.Encoding', 'utf99');
$this->expectError('Invalid encoding utf99'); $this->expectError('Invalid encoding utf99');
$this->assertIdentical( $this->assertIdentical(
@@ -87,7 +88,7 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
} }
function test_convertFromUTF8_iconvNoChars() { function test_convertFromUTF8_iconvNoChars() {
if (!function_exists('iconv')) return; if (!HTMLPurifier_Encoder::iconvAvailable()) return;
$this->config->set('Core.Encoding', 'ISO-8859-1'); $this->config->set('Core.Encoding', 'ISO-8859-1');
$this->assertIdentical( $this->assertIdentical(
HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context), HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
@@ -169,14 +170,16 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
} }
function test_testEncodingSupportsASCII() { function test_testEncodingSupportsASCII() {
$this->assertASCIISupportCheck('Shift_JIS', array("\xC2\xA5" => '\\', "\xE2\x80\xBE" => '~')); if (HTMLPurifier_Encoder::iconvAvailable()) {
$this->assertASCIISupportCheck('JOHAB', array("\xE2\x82\xA9" => '\\')); $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('ISO-8859-1', array());
$this->assertASCIISupportCheck('dontexist', array()); // canary $this->assertASCIISupportCheck('dontexist', array()); // canary
} }
function testShiftJIS() { function testShiftJIS() {
if (!function_exists('iconv')) return; if (!HTMLPurifier_Encoder::iconvAvailable()) return;
$this->config->set('Core.Encoding', 'Shift_JIS'); $this->config->set('Core.Encoding', 'Shift_JIS');
// This actually looks like a Yen, but we're going to treat it differently // This actually looks like a Yen, but we're going to treat it differently
$this->assertIdentical( $this->assertIdentical(
@@ -190,7 +193,7 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
} }
function testIconvTruncateBug() { function testIconvTruncateBug() {
if (!function_exists('iconv')) return; if (!HTMLPurifier_Encoder::iconvAvailable()) return;
if (HTMLPurifier_Encoder::testIconvTruncateBug() !== HTMLPurifier_Encoder::ICONV_TRUNCATES) return; if (HTMLPurifier_Encoder::testIconvTruncateBug() !== HTMLPurifier_Encoder::ICONV_TRUNCATES) return;
$this->config->set('Core.Encoding', 'ISO-8859-1'); $this->config->set('Core.Encoding', 'ISO-8859-1');
$this->assertIdentical( $this->assertIdentical(
@@ -200,7 +203,7 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
} }
function testIconvChunking() { function testIconvChunking() {
if (!function_exists('iconv')) return; if (!HTMLPurifier_Encoder::iconvAvailable()) return;
if (HTMLPurifier_Encoder::testIconvTruncateBug() !== HTMLPurifier_Encoder::ICONV_TRUNCATES) return; if (HTMLPurifier_Encoder::testIconvTruncateBug() !== HTMLPurifier_Encoder::ICONV_TRUNCATES) return;
$this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "a\xF3\xA0\x80\xA0b", 4), 'ab'); $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "a\xF3\xA0\x80\xA0b", 4), 'ab');
$this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aa\xE4\xB8\xADb", 4), 'aab'); $this->assertIdentical(HTMLPurifier_Encoder::iconv('utf-8', 'iso-8859-1//IGNORE', "aa\xE4\xB8\xADb", 4), 'aab');

View File

@@ -226,6 +226,10 @@ text-align:center;
$this->assertCleanCSS("doesnt-exist { text-align:center }", ""); $this->assertCleanCSS("doesnt-exist { text-align:center }", "");
} }
function test_cleanCSS_caseSensitive() {
$this->assertCleanCSS("a .foo #ID div.cl#foo {\nbackground:url(\"http://foo/BAR\");\n}");
}
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,18 +6,19 @@ class HTMLPurifier_HTMLModule_NofollowTest extends HTMLPurifier_HTMLModuleHarnes
function setUp() { function setUp() {
parent::setUp(); parent::setUp();
$this->config->set('HTML.Nofollow', true); $this->config->set('HTML.Nofollow', true);
$this->config->set('Attr.AllowedRel', array("nofollow", "blah"));
} }
function testNofollow() { function testNofollow() {
$this->assertResult( $this->assertResult(
'<a href="http://google.com">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>', '<a href="http://google.com">x</a><a href="http://google.com" rel="blah">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>',
'<a href="http://google.com" rel="nofollow">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>' '<a href="http://google.com" rel="nofollow">x</a><a href="http://google.com" rel="blah nofollow">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>'
); );
} }
function testNofollowDupe() { function testNofollowDupe() {
$this->assertResult( $this->assertResult(
'<a href="http://google.com" rel="nofollow">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>' '<a href="http://google.com" rel="nofollow">x</a><a href="http://google.com" rel="blah nofollow">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>'
); );
} }

View File

@@ -0,0 +1,33 @@
<?php
class HTMLPurifier_HTMLModule_SafeScriptingTest extends HTMLPurifier_HTMLModuleHarness
{
function setUp() {
parent::setUp();
$this->config->set('HTML.SafeScripting', array('http://localhost/foo.js'));
}
function testMinimal() {
$this->assertResult(
'<script></script>',
''
);
}
function testGood() {
$this->assertResult(
'<script type="text/javascript" src="http://localhost/foo.js" />'
);
}
function testBad() {
$this->assertResult(
'<script type="text/javascript" src="http://localhost/foobar.js" />',
''
);
}
}
// vim: et sw=4 sts=4

View File

@@ -11,7 +11,7 @@ class HTMLPurifier_HTMLModule_TargetBlankTest extends HTMLPurifier_HTMLModuleHar
function testTargetBlank() { function testTargetBlank() {
$this->assertResult( $this->assertResult(
'<a href="http://google.com">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>', '<a href="http://google.com">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>',
'<a href="http://google.com" target="blank">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>' '<a href="http://google.com" target="_blank">a</a><a href="/local">b</a><a href="mailto:foo@example.com">c</a>'
); );
} }

View File

@@ -1,5 +1,5 @@
--SKIPIF-- --SKIPIF--
if (!function_exists('iconv')) return true; if (!HTMLPurifier_Encoder::iconvAvailable()) return true;
--INI-- --INI--
Core.Encoding = "Shift_JIS" Core.Encoding = "Shift_JIS"
Core.EscapeNonASCIICharacters = true Core.EscapeNonASCIICharacters = true

View File

@@ -1,5 +1,5 @@
--SKIPIF-- --SKIPIF--
if (!function_exists('iconv')) return true; if (!HTMLPurifier_Encoder::iconvAvailable()) return true;
--INI-- --INI--
Core.Encoding = Shift_JIS Core.Encoding = Shift_JIS
--HTML-- --HTML--

View File

@@ -139,6 +139,11 @@ class HTMLPurifier_Strategy_FixNestingTest extends HTMLPurifier_StrategyHarness
$this->assertResult('<blockquote>text</blockquote>', '<blockquote><p>text</p></blockquote>'); $this->assertResult('<blockquote>text</blockquote>', '<blockquote><p>text</p></blockquote>');
} }
function testDisabledExcludes() {
$this->config->set('Core.DisableExcludes', true);
$this->assertResult('<pre><font><font></font></font></pre>');
}
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -33,6 +33,12 @@ class HTMLPurifier_URISchemeTest extends HTMLPurifier_URIHarness
); );
} }
function test_http_uppercase() {
$this->assertValidation(
'http://example.com/FOO'
);
}
function test_http_removeDefaultPort() { function test_http_removeDefaultPort() {
$this->assertValidation( $this->assertValidation(
'http://example.com:80', 'http://example.com:80',

View File

@@ -36,6 +36,11 @@ class HTMLPurifierTest extends HTMLPurifier_Harness
); );
} }
function testDisableResources() {
$this->config->set('URI.DisableResources', true);
$this->assertPurification('<img src="foo.jpg" />', '');
}
function test_addFilter_deprecated() { function test_addFilter_deprecated() {
$this->expectError('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom'); $this->expectError('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom');
generate_mock_once('HTMLPurifier_Filter'); generate_mock_once('HTMLPurifier_Filter');