mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-08-04 05:07:55 +02:00
Compare commits
47 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7015aaff46 | ||
|
1009bd41a6 | ||
|
511dfe2d4a | ||
|
463aa3a0fa | ||
|
7189ec2790 | ||
|
e901d832ab | ||
|
643ed1bddc | ||
|
41830cd902 | ||
|
261aa1aeaa | ||
|
486b401cf7 | ||
|
f2794e59c5 | ||
|
d702077d2e | ||
|
36bd06d53e | ||
|
13eb016e06 | ||
|
32025a12e1 | ||
|
7dae94c44b | ||
|
54cc691ba7 | ||
|
3af2ff8f98 | ||
|
36fb284d2f | ||
|
8d1f1e8e73 | ||
|
322288e6c0 | ||
|
3c4346cb1e | ||
|
14d934c7ca | ||
|
bb16d8eae5 | ||
|
10530d7f81 | ||
|
c7e172f660 | ||
|
917d2ea5ef | ||
|
895141e0b5 | ||
|
8ab30e24b7 | ||
|
9db891c3aa | ||
|
eb9f9bc7f6 | ||
|
fcebb7731d | ||
|
8d0d0d1a03 | ||
|
80f59206d7 | ||
|
af3f5190dc | ||
|
5620241165 | ||
|
c06727190e | ||
|
1a95852007 | ||
|
c3fab7200e | ||
|
6d7a17e9b6 | ||
|
64b5581bf2 | ||
|
d8da5ff406 | ||
|
fda310f1e7 | ||
|
fc7dbdbd33 | ||
|
02ac821503 | ||
|
16fa73afa0 | ||
|
32a6afa27c |
2
Doxyfile
2
Doxyfile
@@ -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 = 3.1.0
|
||||
PROJECT_NUMBER = 3.1.1
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
5
INSTALL
5
INSTALL
@@ -23,8 +23,9 @@ August 8, 2008.
|
||||
|
||||
These optional extensions can enhance the capabilities of HTML Purifier:
|
||||
|
||||
* iconv : Converts text to and from non-UTF-8 encodings
|
||||
* tidy : Used for pretty-printing HTML
|
||||
* iconv : Converts text to and from non-UTF-8 encodings
|
||||
* bcmath : Used for unit conversion and imagecrash protection
|
||||
* tidy : Used for pretty-printing HTML
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
76
NEWS
76
NEWS
@@ -9,6 +9,79 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
||||
. Internal change
|
||||
==========================
|
||||
|
||||
3.1.1, released 2008-06-19
|
||||
# %URI.Munge now, by default, does not munge resources (for example, <img src="">)
|
||||
In order to enable this again, please set %URI.MungeResources to true.
|
||||
! More robust imagecrash protection with height/width CSS with %CSS.MaxImgLength,
|
||||
and height/width HTML with %HTML.MaxImgLength.
|
||||
! %URI.MungeSecretKey for secure URI munging. Thanks Chris
|
||||
for sponsoring this feature. Check out the corresponding documentation
|
||||
for details. (Att Nightly testers: The API for this feature changed before
|
||||
the general release. Namely, rename your directives %URI.SecureMungeSecretKey =>
|
||||
%URI.MungeSecretKey and and %URI.SecureMunge => %URI.Munge)
|
||||
! Implemented post URI filtering. Set member variable $post to true to set
|
||||
a URIFilter as such.
|
||||
! Allow modules to define injectors via $info_injector. Injectors are
|
||||
automatically disabled if injector's needed elements are not found.
|
||||
! Support for "safe" objects added, use %HTML.SafeObject and %HTML.SafeEmbed.
|
||||
Thanks Chris for sponsoring. If you've been using ad hoc code from the
|
||||
forums, PLEASE use this instead.
|
||||
! Added substitutions for %e, %n, %a and %p in %URI.Munge (in order,
|
||||
embedded, tag name, attribute name, CSS property name). See %URI.Munge
|
||||
for more details. Requested by Jochem Blok.
|
||||
- Disable percent height/width attributes for img.
|
||||
- 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.
|
||||
This semantics change was requested by frank farmer.
|
||||
- Percent encoding checks enabled for URI query and fragment
|
||||
- Fix stray backslashes in font-family; CSS Unicode character escapes are
|
||||
now properly resolved (although *only* in font-family). Thanks Takeshi Terada
|
||||
for reporting.
|
||||
- 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. Thanks Takeshi Terada for reporting.
|
||||
- Fix missing configuration parameter in Generator calls. Thanks vs for the
|
||||
partial patch.
|
||||
- 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''. Thanks Jochem Blok
|
||||
for reporting.
|
||||
. 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').
|
||||
. 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.
|
||||
. ConfigSchema data-structure heavily optimized; on average it uses a third
|
||||
the memory it did previously. The interface has changed accordingly,
|
||||
consult changes to HTMLPurifier_Config for details.
|
||||
. Variable parsing types now are magic integers instead of strings
|
||||
. Added benchmark for ConfigSchema
|
||||
. HTMLPurifier_Generator requires $config and $context parameters. If you
|
||||
don't know what they should be, use HTMLPurifier_Config::createDefault()
|
||||
and new HTMLPurifier_Context().
|
||||
. Printers now properly distinguish between output configuration, and
|
||||
target configuration. This is not applicable to scripts using
|
||||
the Printers for HTML Purifier related tasks.
|
||||
. HTML/CSS Printers must be primed with prepareGenerator($gen_config), otherwise
|
||||
fatal errors will ensue.
|
||||
. URIFilter->prepare can return false in order to abort loading of the filter
|
||||
. Factory for AttrDef_URI implemented, URI#embedded to indicate URI that embeds
|
||||
an external resource.
|
||||
. %URI.Munge functionality factored out into a post-filter class.
|
||||
. Added CurrentCSSProperty context variable during CSS validation
|
||||
|
||||
3.1.0, released 2008-05-18
|
||||
# Unnecessary references to objects (vestiges of PHP4) removed from method
|
||||
signatures. The following methods do not need references when assigning from
|
||||
@@ -33,7 +106,8 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
||||
and allows for version numbers like "3.1.0-dev".
|
||||
! %HTML.Allowed deals gracefully with whitespace anywhere, anytime!
|
||||
! HTML Purifier's URI handling is a lot more robust, with much stricter
|
||||
validation checks and better percent encoding handling.
|
||||
validation checks and better percent encoding handling. Thanks Gareth Heyes
|
||||
for indicating security vulnerabilities from lax percent encoding.
|
||||
! Bootstrap autoloader deals more robustly with classes that don't exist,
|
||||
preventing class_exists($class, true) from barfing.
|
||||
- InterchangeBuilder now alphabetizes its lists
|
||||
|
11
TODO
11
TODO
@@ -11,18 +11,22 @@ If no interest is expressed for a feature that may require a considerable
|
||||
amount of effort to implement, it may get endlessly delayed. Do not be
|
||||
afraid to cast your vote for the next feature to be implemented!
|
||||
|
||||
- Implement validation for query and for fragment
|
||||
- Investigate how early internal structures can be accessed; this would
|
||||
prevent structures from being parsed and serialized multiple times.
|
||||
- Built-in support for target="_blank" on all external links
|
||||
- Gitify the repository
|
||||
|
||||
FUTURE VERSIONS
|
||||
---------------
|
||||
|
||||
3.2 release [It's All About Trust] (floating)
|
||||
# Implement untrusted, dangerous elements/attributes
|
||||
- Objects and Forms are especially wanted
|
||||
- Forms are especially wanted
|
||||
# Implement IDREF support (harder than it seems, since you cannot have
|
||||
IDREFs to non-existent IDs)
|
||||
# Frameset XHTML 1.0 and HTML 4.01 doctypes
|
||||
- Research and implement a "safe" version of the Object module
|
||||
- Implement <area>
|
||||
- Figure out how to simultaneously set %CSS.Trusted and %HTML.Trusted (?)
|
||||
|
||||
3.3 release [Error'ed]
|
||||
# Error logging for filtering/cleanup procedures
|
||||
@@ -104,6 +108,7 @@ Neat feature related
|
||||
- Full set of color keywords. Also, a way to add onto them without
|
||||
finalizing the configuration object.
|
||||
- Write a var_export and memcached DefinitionCache - Denis
|
||||
- Allow restriction of allowed class values
|
||||
|
||||
Maintenance related (slightly boring)
|
||||
# CHMOD install script for PEAR installs
|
||||
|
19
WHATSNEW
19
WHATSNEW
@@ -1,10 +1,9 @@
|
||||
HTML Purifier 3.1.0 is the second release series for HTML Purifier on PHP 5
|
||||
as well as a security update related to URIs. It shifts over to using
|
||||
autoload, and also includes support for the !important CSS modifier,
|
||||
display and visibility CSS properties with %CSS.AllowTricky, marquee with
|
||||
%HTML.Proprietary (had you scared for a moment, hmm?), a kses() wrapper,
|
||||
%CSS.AllowedProperties, %HTML.ForbiddenAttributes and
|
||||
%HTML.ForbiddenElements and a totally revamped ConfigDoc system. Since the
|
||||
release candidate, there have also been a number of stability fixes such as
|
||||
improved URI escaping, a change in serializer ID format, and a relaxed
|
||||
format for %HTML.Allowed. And as always, numerous bugfixes.
|
||||
HTML Purifier 3.1.1 is a security and bugfix release. This release addresses
|
||||
two security vulnerabilities, both related to CSS, and one of which only
|
||||
applies to users using Shift_JIS as their output encoding. There is also
|
||||
a security improvement regarding the imagecrash attack. There is a backwards
|
||||
incompatible change with %URI.Munge, in which resources are no longer munged
|
||||
by default; please enable using %URI.MungeResources. Besides this, there
|
||||
are numerous improvements to URI munging, esp. with the addition of
|
||||
%URI.MungeSecretKey, as well as an experimental implementation of
|
||||
%HTML.SafeObject and %HTML.SafeEmbed. There are also some memory optimizations.
|
||||
|
14
benchmarks/ConfigSchema.php
Normal file
14
benchmarks/ConfigSchema.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
chdir(dirname(__FILE__));
|
||||
|
||||
//require_once '../library/HTMLPurifier.path.php';
|
||||
shell_exec('php ../maintenance/generate-schema-cache.php');
|
||||
require_once '../library/HTMLPurifier.path.php';
|
||||
require_once 'HTMLPurifier.includes.php';
|
||||
|
||||
$begin = xdebug_memory_usage();
|
||||
|
||||
$schema = HTMLPurifier_ConfigSchema::makeFromSerial();
|
||||
|
||||
echo xdebug_memory_usage() - $begin;
|
@@ -19,7 +19,7 @@
|
||||
<xsl:variable name="usageLookup" select="document('../usage.xml')/usage" />
|
||||
|
||||
<!-- Twiddle this variable to get the columns as even as possible -->
|
||||
<xsl:variable name="maxNumberAdjust" select="1" />
|
||||
<xsl:variable name="maxNumberAdjust" select="2" />
|
||||
|
||||
<xsl:template match="/">
|
||||
<html lang="en" xml:lang="en">
|
||||
|
@@ -16,24 +16,29 @@
|
||||
<line>44</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.MaxImgLength">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>157</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.Proprietary">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>202</line>
|
||||
<line>214</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowTricky">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>206</line>
|
||||
<line>218</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowImportant">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>210</line>
|
||||
<line>222</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowedProperties">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>262</line>
|
||||
<line>274</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Cache.DefinitionImpl">
|
||||
@@ -63,19 +68,19 @@
|
||||
</directive>
|
||||
<directive id="Core.Encoding">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>281</line>
|
||||
<line>305</line>
|
||||
<line>267</line>
|
||||
<line>294</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Test.ForceNoIconv">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>283</line>
|
||||
<line>310</line>
|
||||
<line>272</line>
|
||||
<line>302</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EscapeNonASCIICharacters">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>307</line>
|
||||
<line>298</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.MaintainLineNumbers">
|
||||
@@ -91,52 +96,52 @@
|
||||
</directive>
|
||||
<directive id="Output.CommentScriptContents">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>41</line>
|
||||
<line>40</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.TidyFormat">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>70</line>
|
||||
<line>69</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.Newline">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>84</line>
|
||||
<line>83</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.BlockWrapper">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>213</line>
|
||||
<line>222</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Parent">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>221</line>
|
||||
<line>230</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedElements">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>238</line>
|
||||
<line>247</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedAttributes">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>239</line>
|
||||
<line>248</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Allowed">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>242</line>
|
||||
<line>251</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.ForbiddenElements">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>328</line>
|
||||
<line>337</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.ForbiddenAttributes">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>329</line>
|
||||
<line>338</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Trusted">
|
||||
@@ -146,6 +151,9 @@
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>238</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/Image.php">
|
||||
<line>27</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>34</line>
|
||||
</file>
|
||||
@@ -165,6 +173,16 @@
|
||||
<line>220</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.SafeObject">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>225</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.SafeEmbed">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>228</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDBlacklist">
|
||||
<file name="HTMLPurifier/IDAccumulator.php">
|
||||
<line>26</line>
|
||||
@@ -187,7 +205,7 @@
|
||||
</directive>
|
||||
<directive id="URI.Host">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>57</line>
|
||||
<line>64</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/URIFilter/DisableExternal.php">
|
||||
<line>8</line>
|
||||
@@ -195,12 +213,12 @@
|
||||
</directive>
|
||||
<directive id="URI.Base">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>58</line>
|
||||
<line>65</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.DefaultScheme">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>65</line>
|
||||
<line>72</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.AllowedSchemes">
|
||||
@@ -215,12 +233,7 @@
|
||||
</directive>
|
||||
<directive id="URI.Disable">
|
||||
<file name="HTMLPurifier/AttrDef/URI.php">
|
||||
<line>23</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Munge">
|
||||
<file name="HTMLPurifier/AttrDef/URI.php">
|
||||
<line>68</line>
|
||||
<line>28</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.ColorKeywords">
|
||||
@@ -305,6 +318,17 @@
|
||||
<line>123</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.MaxImgLength">
|
||||
<file name="HTMLPurifier/HTMLModule/Image.php">
|
||||
<line>14</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/SafeEmbed.php">
|
||||
<line>13</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/SafeObject.php">
|
||||
<line>19</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TidyLevel">
|
||||
<file name="HTMLPurifier/HTMLModule/Tidy.php">
|
||||
<line>45</line>
|
||||
@@ -358,4 +382,14 @@
|
||||
<line>8</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.MungeResources">
|
||||
<file name="HTMLPurifier/URIFilter/Munge.php">
|
||||
<line>14</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.MungeSecretKey">
|
||||
<file name="HTMLPurifier/URIFilter/Munge.php">
|
||||
<line>15</line>
|
||||
</file>
|
||||
</directive>
|
||||
</usage>
|
||||
|
@@ -130,30 +130,26 @@
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's suppose I wanted to write a filter that de-internationalized domain
|
||||
names by converting them to <a href="http://en.wikipedia.org/wiki/Punycode">Punycode</a>.
|
||||
Assuming that <code>punycode_encode($input)</code> converts <code>$input</code> to
|
||||
Punycode and returns <code>false</code> on failure:
|
||||
Let's suppose I wanted to write a filter that converted links with a
|
||||
custom <code>image</code> scheme to its corresponding real path on
|
||||
our website:
|
||||
</p>
|
||||
|
||||
<pre>class HTMLPurifier_URIFilter_ConvertIDNToPunycode extends HTMLPurifier_URIFilter
|
||||
<pre>class HTMLPurifier_URIFilter_TransformImageScheme extends HTMLPurifier_URIFilter
|
||||
{
|
||||
public $name = 'ConvertIDNToPunycode';
|
||||
public $name = 'TransformImageScheme';
|
||||
public function filter(&$uri, $config, $context) {
|
||||
if (is_null($uri->host)) return true;
|
||||
if ($uri->host == utf8_decode($uri->host)) {
|
||||
// is ASCII, abort
|
||||
return true;
|
||||
}
|
||||
$host = punycode_encode($uri->host);
|
||||
if ($host === false) return false;
|
||||
$uri->host = $host;
|
||||
if ($uri->scheme !== 'image') return true;
|
||||
$img_name = $uri->path;
|
||||
// Overwrite the previous URI object
|
||||
$uri = new HTMLPurifier_URI('http', null, null, null, '/img/' . $img_name . '.png', null, null);
|
||||
return true;
|
||||
}
|
||||
}</pre>
|
||||
|
||||
<p>
|
||||
Notice I did not <code>return $uri;</code>.
|
||||
Notice I did not <code>return $uri;</code>. This filter would turn
|
||||
<code>image:Foo</code> into <code>/img/Foo.png</code>.
|
||||
</p>
|
||||
|
||||
<h2>Activating your filter</h2>
|
||||
@@ -186,6 +182,25 @@ $uri->registerFilter(new HTMLPurifier_URIFilter_<strong>NameOfFilter</strong>())
|
||||
is set to true.
|
||||
</p>
|
||||
|
||||
<h2>Post-filter</h2>
|
||||
|
||||
<p>
|
||||
Remember our TransformImageScheme filter? That filter acted before we had
|
||||
performed scheme validation; otherwise, the URI would have been filtered
|
||||
out when it was discovered that there was no image scheme. Well, a post-filter
|
||||
is run after scheme specific validation, so it's ideal for bulk
|
||||
post-processing of URIs, including munging. To specify a URI as a post-filter,
|
||||
set the <code>$post</code> member variable to TRUE.
|
||||
</p>
|
||||
|
||||
<pre>class HTMLPurifier_URIFilter_MyPostFilter extends HTMLPurifier_URIFilter
|
||||
{
|
||||
public $name = 'MyPostFilter';
|
||||
public $post = true;
|
||||
// ... extra code here
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h2>Examples</h2>
|
||||
|
||||
<p>
|
||||
|
129
docs/specimens/jochem-blok-word.html
Normal file
129
docs/specimens/jochem-blok-word.html
Normal file
@@ -0,0 +1,129 @@
|
||||
<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
|
||||
|
||||
<head>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii">
|
||||
<meta name=Generator content="Microsoft Word 12 (filtered medium)">
|
||||
<!--[if !mso]>
|
||||
<style>
|
||||
v\:* {behavior:url(#default#VML);}
|
||||
o\:* {behavior:url(#default#VML);}
|
||||
w\:* {behavior:url(#default#VML);}
|
||||
..shape {behavior:url(#default#VML);}
|
||||
</style>
|
||||
<![endif]-->
|
||||
<style>
|
||||
<!--
|
||||
/* Font Definitions */
|
||||
@font-face
|
||||
{font-family:"Cambria Math";
|
||||
panose-1:2 4 5 3 5 4 6 3 2 4;}
|
||||
@font-face
|
||||
{font-family:Calibri;
|
||||
panose-1:2 15 5 2 2 2 4 3 2 4;}
|
||||
@font-face
|
||||
{font-family:Tahoma;
|
||||
panose-1:2 11 6 4 3 5 4 4 2 4;}
|
||||
@font-face
|
||||
{font-family:Verdana;
|
||||
panose-1:2 11 6 4 3 5 4 4 2 4;}
|
||||
/* Style Definitions */
|
||||
p.MsoNormal, li.MsoNormal, div.MsoNormal
|
||||
{margin:0cm;
|
||||
margin-bottom:.0001pt;
|
||||
font-size:10.0pt;
|
||||
font-family:"Verdana","sans-serif";}
|
||||
a:link, span.MsoHyperlink
|
||||
{mso-style-priority:99;
|
||||
color:blue;
|
||||
text-decoration:underline;}
|
||||
a:visited, span.MsoHyperlinkFollowed
|
||||
{mso-style-priority:99;
|
||||
color:purple;
|
||||
text-decoration:underline;}
|
||||
p.MsoAcetate, li.MsoAcetate, div.MsoAcetate
|
||||
{mso-style-priority:99;
|
||||
mso-style-link:"Balloon Text Char";
|
||||
margin:0cm;
|
||||
margin-bottom:.0001pt;
|
||||
font-size:8.0pt;
|
||||
font-family:"Tahoma","sans-serif";}
|
||||
span.EmailStyle17
|
||||
{mso-style-type:personal-compose;
|
||||
font-family:"Verdana","sans-serif";
|
||||
color:windowtext;}
|
||||
span.BalloonTextChar
|
||||
{mso-style-name:"Balloon Text Char";
|
||||
mso-style-priority:99;
|
||||
mso-style-link:"Balloon Text";
|
||||
font-family:"Tahoma","sans-serif";}
|
||||
..MsoChpDefault
|
||||
{mso-style-type:export-only;}
|
||||
@page Section1
|
||||
{size:612.0pt 792.0pt;
|
||||
margin:70.85pt 70.85pt 70.85pt 70.85pt;}
|
||||
div.Section1
|
||||
{page:Section1;}
|
||||
-->
|
||||
</style>
|
||||
<!--[if gte mso 9]><xml>
|
||||
<o:shapedefaults v:ext="edit" spidmax="2050" />
|
||||
</xml><![endif]--><!--[if gte mso 9]><xml>
|
||||
<o:shapelayout v:ext="edit">
|
||||
<o:idmap v:ext="edit" data="1" />
|
||||
</o:shapelayout></xml><![endif]-->
|
||||
</head>
|
||||
|
||||
<body lang=NL link=blue vlink=purple>
|
||||
|
||||
<div class=Section1>
|
||||
|
||||
<p class=MsoNormal><img width=1277 height=994 id="Picture_x0020_1"
|
||||
src="cid:image001.png@01C8CBDF.5D1BAEE0"><o:p></o:p></p>
|
||||
|
||||
<p class=MsoNormal><o:p> </o:p></p>
|
||||
|
||||
<p class=MsoNormal><b>Name<o:p></o:p></b></p>
|
||||
|
||||
<p class=MsoNormal>E-mail : <a href="mailto:mail@example.com"><span
|
||||
style='color:windowtext'>mail@example.com</span></a><o:p></o:p></p>
|
||||
|
||||
<p class=MsoNormal><o:p> </o:p></p>
|
||||
|
||||
<p class=MsoNormal><b>Company<o:p></o:p></b></p>
|
||||
|
||||
<p class=MsoNormal>Address 1<o:p></o:p></p>
|
||||
|
||||
<p class=MsoNormal>Address 2<o:p></o:p></p>
|
||||
|
||||
<p class=MsoNormal><o:p> </o:p></p>
|
||||
|
||||
<p class=MsoNormal>Telefoon : +xx xx xxx xxx xx <span style='color:black'><o:p></o:p></span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US style='color:black'>Fax : +xx xx xxx xx xx<o:p></o:p></span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US style='color:black'>Internet : </span><span
|
||||
style='color:black'><a href="http://www.example.com/"><span lang=EN-US
|
||||
style='color:black'>http://www.example.com</span></a></span><span
|
||||
lang=EN-US style='color:black'><o:p></o:p></span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US style='color:black'>Kamer van koophandel
|
||||
xxxxxxxxx<o:p></o:p></span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US style='color:black'><o:p> </o:p></span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US style='font-size:7.5pt;color:black'>Op deze
|
||||
e-mail is een disclaimer van toepassing, ga naar </span><span lang=EN-US
|
||||
style='font-size:7.5pt'><a
|
||||
href="http://www.example.com/disclaimer"><span
|
||||
style='color:black'>www.example.com/disclaimer</span></a><br>
|
||||
<span style='color:black'>A disclaimer is applicable to this email, please
|
||||
refer to </span><a href="http://www.example.com/disclaimer"><span
|
||||
style='color:black'>www.example.com/disclaimer</span></a><o:p></o:p></span></p>
|
||||
|
||||
<p class=MsoNormal><span lang=EN-US><o:p> </o:p></span></p>
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@@ -7,7 +7,7 @@
|
||||
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
|
||||
* FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* @version 3.1.0
|
||||
* @version 3.1.1
|
||||
*
|
||||
* @warning
|
||||
* You must *not* include any other HTML Purifier files before this file,
|
||||
@@ -29,7 +29,6 @@ require 'HTMLPurifier/Definition.php';
|
||||
require 'HTMLPurifier/CSSDefinition.php';
|
||||
require 'HTMLPurifier/ChildDef.php';
|
||||
require 'HTMLPurifier/Config.php';
|
||||
require 'HTMLPurifier/ConfigDef.php';
|
||||
require 'HTMLPurifier/ConfigSchema.php';
|
||||
require 'HTMLPurifier/ContentSets.php';
|
||||
require 'HTMLPurifier/Context.php';
|
||||
@@ -52,6 +51,7 @@ require 'HTMLPurifier/IDAccumulator.php';
|
||||
require 'HTMLPurifier/Injector.php';
|
||||
require 'HTMLPurifier/Language.php';
|
||||
require 'HTMLPurifier/LanguageFactory.php';
|
||||
require 'HTMLPurifier/Length.php';
|
||||
require 'HTMLPurifier/Lexer.php';
|
||||
require 'HTMLPurifier/PercentEncoder.php';
|
||||
require 'HTMLPurifier/Strategy.php';
|
||||
@@ -66,12 +66,14 @@ require 'HTMLPurifier/URIFilter.php';
|
||||
require 'HTMLPurifier/URIParser.php';
|
||||
require 'HTMLPurifier/URIScheme.php';
|
||||
require 'HTMLPurifier/URISchemeRegistry.php';
|
||||
require 'HTMLPurifier/UnitConverter.php';
|
||||
require 'HTMLPurifier/VarParser.php';
|
||||
require 'HTMLPurifier/VarParserException.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS.php';
|
||||
require 'HTMLPurifier/AttrDef/Enum.php';
|
||||
require 'HTMLPurifier/AttrDef/Integer.php';
|
||||
require 'HTMLPurifier/AttrDef/Lang.php';
|
||||
require 'HTMLPurifier/AttrDef/Switch.php';
|
||||
require 'HTMLPurifier/AttrDef/Text.php';
|
||||
require 'HTMLPurifier/AttrDef/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
@@ -116,6 +118,9 @@ require 'HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require 'HTMLPurifier/AttrTransform/Lang.php';
|
||||
require 'HTMLPurifier/AttrTransform/Length.php';
|
||||
require 'HTMLPurifier/AttrTransform/Name.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require 'HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require 'HTMLPurifier/ChildDef/Custom.php';
|
||||
@@ -124,9 +129,6 @@ require 'HTMLPurifier/ChildDef/Required.php';
|
||||
require 'HTMLPurifier/ChildDef/Optional.php';
|
||||
require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require 'HTMLPurifier/ChildDef/Table.php';
|
||||
require 'HTMLPurifier/ConfigDef/Directive.php';
|
||||
require 'HTMLPurifier/ConfigDef/DirectiveAlias.php';
|
||||
require 'HTMLPurifier/ConfigDef/Namespace.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Null.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
@@ -144,6 +146,8 @@ require 'HTMLPurifier/HTMLModule/Object.php';
|
||||
require 'HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require 'HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require 'HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tables.php';
|
||||
@@ -159,6 +163,7 @@ require 'HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require 'HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require 'HTMLPurifier/Injector/Linkify.php';
|
||||
require 'HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require 'HTMLPurifier/Injector/SafeObject.php';
|
||||
require 'HTMLPurifier/Lexer/DOMLex.php';
|
||||
require 'HTMLPurifier/Lexer/DirectLex.php';
|
||||
require 'HTMLPurifier/Strategy/Composite.php';
|
||||
@@ -179,6 +184,7 @@ require 'HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require 'HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require 'HTMLPurifier/URIFilter/Munge.php';
|
||||
require 'HTMLPurifier/URIScheme/ftp.php';
|
||||
require 'HTMLPurifier/URIScheme/http.php';
|
||||
require 'HTMLPurifier/URIScheme/https.php';
|
||||
|
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
HTML Purifier 3.1.0 - Standards Compliant HTML Filtering
|
||||
HTML Purifier 3.1.1 - Standards Compliant HTML Filtering
|
||||
Copyright (C) 2006-2008 Edward Z. Yang
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
@@ -55,10 +55,10 @@ class HTMLPurifier
|
||||
{
|
||||
|
||||
/** Version of HTML Purifier */
|
||||
public $version = '3.1.0';
|
||||
public $version = '3.1.1';
|
||||
|
||||
/** Constant with version of HTML Purifier */
|
||||
const VERSION = '3.1.0';
|
||||
const VERSION = '3.1.1';
|
||||
|
||||
/** Global configuration object */
|
||||
public $config;
|
||||
|
@@ -23,7 +23,6 @@ require_once $__dir . '/HTMLPurifier/Definition.php';
|
||||
require_once $__dir . '/HTMLPurifier/CSSDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/Config.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigSchema.php';
|
||||
require_once $__dir . '/HTMLPurifier/ContentSets.php';
|
||||
require_once $__dir . '/HTMLPurifier/Context.php';
|
||||
@@ -46,6 +45,7 @@ require_once $__dir . '/HTMLPurifier/IDAccumulator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector.php';
|
||||
require_once $__dir . '/HTMLPurifier/Language.php';
|
||||
require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer.php';
|
||||
require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy.php';
|
||||
@@ -60,12 +60,14 @@ require_once $__dir . '/HTMLPurifier/URIFilter.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme.php';
|
||||
require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/UnitConverter.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParserException.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Switch.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
@@ -110,6 +112,9 @@ require_once $__dir . '/HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
|
||||
@@ -118,9 +123,6 @@ require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Table.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef/Directive.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef/DirectiveAlias.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef/Namespace.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
@@ -138,6 +140,8 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
|
||||
@@ -153,6 +157,7 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/Linkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Composite.php';
|
||||
@@ -173,6 +178,7 @@ require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/Munge.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/http.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
|
||||
|
@@ -51,16 +51,13 @@ abstract 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. 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.
|
||||
* 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.
|
||||
*/
|
||||
public function parseCDATA($string) {
|
||||
$string = trim($string);
|
||||
$string = str_replace("\n", '', $string);
|
||||
$string = str_replace(array("\r", "\t"), ' ', $string);
|
||||
$string = str_replace(array("\n", "\t", "\r"), ' ', $string);
|
||||
return $string;
|
||||
}
|
||||
|
||||
|
@@ -29,6 +29,12 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
$declarations = explode(';', $css);
|
||||
$propvalues = array();
|
||||
|
||||
/**
|
||||
* Name of the current CSS property being validated.
|
||||
*/
|
||||
$property = false;
|
||||
$context->register('CurrentCSSProperty', $property);
|
||||
|
||||
foreach ($declarations as $declaration) {
|
||||
if (!$declaration) continue;
|
||||
if (!strpos($declaration, ':')) continue;
|
||||
@@ -61,6 +67,8 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
$propvalues[$property] = $result;
|
||||
}
|
||||
|
||||
$context->destroy('CurrentCSSProperty');
|
||||
|
||||
// procedure does not write the new CSS simultaneously, so it's
|
||||
// slightly inefficient, but it's the only way of getting rid of
|
||||
// duplicates. Perhaps config to optimize it, but not now.
|
||||
|
@@ -16,7 +16,6 @@ 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 = '';
|
||||
@@ -35,13 +34,40 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
$quote = $font[0];
|
||||
if ($font[$length - 1] !== $quote) continue;
|
||||
$font = substr($font, 1, $length - 2);
|
||||
// double-backslash processing is buggy
|
||||
$font = str_replace("\\$quote", $quote, $font); // de-escape quote
|
||||
$font = str_replace("\\\n", "\n", $font); // de-escape newlines
|
||||
|
||||
$new_font = '';
|
||||
for ($i = 0, $c = strlen($font); $i < $c; $i++) {
|
||||
if ($font[$i] === '\\') {
|
||||
$i++;
|
||||
if ($i >= $c) {
|
||||
$new_font .= '\\';
|
||||
break;
|
||||
}
|
||||
if (ctype_xdigit($font[$i])) {
|
||||
$code = $font[$i];
|
||||
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
|
||||
if (!ctype_xdigit($font[$i])) break;
|
||||
$code .= $font[$i];
|
||||
}
|
||||
// We have to be extremely careful when adding
|
||||
// new characters, to make sure we're not breaking
|
||||
// the encoding.
|
||||
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
|
||||
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
|
||||
$new_font .= $char;
|
||||
if ($i < $c && trim($font[$i]) !== '') $i--;
|
||||
continue;
|
||||
}
|
||||
if ($font[$i] === "\n") continue;
|
||||
}
|
||||
$new_font .= $font[$i];
|
||||
}
|
||||
|
||||
$font = $new_font;
|
||||
}
|
||||
// $font is a pure representation of the font name
|
||||
|
||||
if (ctype_alnum($font)) {
|
||||
if (ctype_alnum($font) && $font !== '') {
|
||||
// very simple font, allow it in unharmed
|
||||
$final .= $font . ', ';
|
||||
continue;
|
||||
@@ -50,8 +76,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, ', ');
|
||||
|
@@ -6,46 +6,40 @@
|
||||
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Valid unit lookup table.
|
||||
* @warning The code assumes all units are two characters long. Be careful
|
||||
* if we have to change this behavior!
|
||||
*/
|
||||
protected $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
|
||||
*/
|
||||
protected $number_def;
|
||||
protected $min, $max;
|
||||
|
||||
/**
|
||||
* @param $non_negative Bool indication whether or not negative values are
|
||||
* allowed.
|
||||
* @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.
|
||||
*/
|
||||
public function __construct($non_negative = false) {
|
||||
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
|
||||
public function __construct($min = null, $max = null) {
|
||||
$this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
|
||||
$this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
|
||||
}
|
||||
|
||||
public function validate($length, $config, $context) {
|
||||
public function validate($string, $config, $context) {
|
||||
$string = $this->parseCDATA($string);
|
||||
|
||||
$length = $this->parseCDATA($length);
|
||||
if ($length === '') return false;
|
||||
if ($length === '0') return '0';
|
||||
$strlen = strlen($length);
|
||||
if ($strlen === 1) return false; // impossible!
|
||||
// Optimizations
|
||||
if ($string === '') return false;
|
||||
if ($string === '0') return '0';
|
||||
if (strlen($string) === 1) 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);
|
||||
$length = HTMLPurifier_Length::make($string);
|
||||
if (!$length->isValid()) 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;
|
||||
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;
|
||||
}
|
||||
|
||||
return $length->toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -18,6 +18,10 @@ 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
|
||||
*/
|
||||
public function validate($number, $config, $context) {
|
||||
|
||||
$number = $this->parseCDATA($number);
|
||||
|
@@ -13,10 +13,13 @@ 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) {
|
||||
|
@@ -6,6 +6,12 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $max;
|
||||
|
||||
public function __construct($max = null) {
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
$string = trim($string);
|
||||
@@ -24,11 +30,18 @@ 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 ($int > 1200) return '1200';
|
||||
if ($this->max !== null && $int > $this->max) return (string) $this->max;
|
||||
|
||||
return (string) $int;
|
||||
|
||||
}
|
||||
|
||||
public function make($string) {
|
||||
if ($string === '') $max = null;
|
||||
else $max = (int) $string;
|
||||
$class = get_class($this);
|
||||
return new $class($max);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
32
library/HTMLPurifier/AttrDef/Switch.php
Normal file
32
library/HTMLPurifier/AttrDef/Switch.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Decorator that, depending on a token, switches between two definitions.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_Switch
|
||||
{
|
||||
|
||||
protected $tag;
|
||||
protected $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
|
||||
*/
|
||||
public function __construct($tag, $with_tag, $without_tag) {
|
||||
$this->tag = $tag;
|
||||
$this->withTag = $with_tag;
|
||||
$this->withoutTag = $without_tag;
|
||||
}
|
||||
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -18,6 +18,11 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
$this->embedsResource = (bool) $embeds_resource;
|
||||
}
|
||||
|
||||
public function make($string) {
|
||||
$embeds = (bool) $string;
|
||||
return new HTMLPurifier_AttrDef_URI($embeds);
|
||||
}
|
||||
|
||||
public function validate($uri, $config, $context) {
|
||||
|
||||
if ($config->get('URI', 'Disable')) return false;
|
||||
@@ -50,6 +55,10 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
$result = $scheme_obj->validate($uri, $config, $context);
|
||||
if (!$result) break;
|
||||
|
||||
// Post chained filtering
|
||||
$result = $uri_def->postFilter($uri, $config, $context);
|
||||
if (!$result) break;
|
||||
|
||||
// survived gauntlet
|
||||
$ok = true;
|
||||
|
||||
@@ -59,18 +68,7 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
if (!$ok) return false;
|
||||
|
||||
// back to string
|
||||
$result = $uri->toString();
|
||||
|
||||
// munge entire URI if necessary
|
||||
if (
|
||||
!is_null($uri->host) && // indicator for authority
|
||||
!empty($scheme_obj->browsable) &&
|
||||
!is_null($munge = $config->get('URI', 'Munge'))
|
||||
) {
|
||||
$result = str_replace('%s', rawurlencode($result), $munge);
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $uri->toString();
|
||||
|
||||
}
|
||||
|
||||
|
13
library/HTMLPurifier/AttrTransform/SafeEmbed.php
Normal file
13
library/HTMLPurifier/AttrTransform/SafeEmbed.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
class HTMLPurifier_AttrTransform_SafeEmbed extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
public $name = "SafeEmbed";
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
$attr['allowscriptaccess'] = 'never';
|
||||
$attr['allownetworking'] = 'internal';
|
||||
$attr['type'] = 'application/x-shockwave-flash';
|
||||
return $attr;
|
||||
}
|
||||
}
|
14
library/HTMLPurifier/AttrTransform/SafeObject.php
Normal file
14
library/HTMLPurifier/AttrTransform/SafeObject.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Writes default type for all objects. Currently only supports flash.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_SafeObject extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
public $name = "SafeObject";
|
||||
|
||||
function transform($attr, $config, $context) {
|
||||
if (!isset($attr['type'])) $attr['type'] = 'application/x-shockwave-flash';
|
||||
return $attr;
|
||||
}
|
||||
}
|
48
library/HTMLPurifier/AttrTransform/SafeParam.php
Normal file
48
library/HTMLPurifier/AttrTransform/SafeParam.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates name/value pairs in param tags to be used in safe objects. This
|
||||
* will only allow name values it recognizes, and pre-fill certain attributes
|
||||
* with required values.
|
||||
*
|
||||
* @note
|
||||
* This class only supports Flash. In the future, Quicktime support
|
||||
* may be added.
|
||||
*
|
||||
* @warning
|
||||
* This class expects an injector to add the necessary parameters tags.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_SafeParam extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
public $name = "SafeParam";
|
||||
private $uri;
|
||||
|
||||
public function __construct() {
|
||||
$this->uri = new HTMLPurifier_AttrDef_URI(true); // embedded
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
// If we add support for other objects, we'll need to alter the
|
||||
// transforms.
|
||||
switch ($attr['name']) {
|
||||
// application/x-shockwave-flash
|
||||
// Keep this synchronized with Injector/SafeObject.php
|
||||
case 'allowScriptAccess':
|
||||
$attr['value'] = 'never';
|
||||
break;
|
||||
case 'allowNetworking':
|
||||
$attr['value'] = 'internal';
|
||||
break;
|
||||
case 'wmode':
|
||||
$attr['value'] = 'window';
|
||||
break;
|
||||
case 'movie':
|
||||
$attr['value'] = $this->uri->validate($attr['value'], $config, $context);
|
||||
break;
|
||||
// add other cases to support other param name/value pairs
|
||||
default:
|
||||
$attr['name'] = $attr['value'] = null;
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
}
|
@@ -43,8 +43,8 @@ class HTMLPurifier_AttrValidator
|
||||
// DEFINITION CALL
|
||||
$d_defs = $definition->info_global_attr;
|
||||
|
||||
// reference attributes for easy manipulation
|
||||
$attr =& $token->attr;
|
||||
// don't update token until the very end, to ensure an atomic update
|
||||
$attr = $token->attr;
|
||||
|
||||
// do global transformations (pre)
|
||||
// nothing currently utilizes this
|
||||
@@ -139,6 +139,8 @@ 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');
|
||||
|
||||
|
@@ -90,7 +90,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(true) //disallow negative
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
|
||||
));
|
||||
|
||||
$this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
|
||||
@@ -116,7 +116,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(true),
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0'),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(true)
|
||||
));
|
||||
|
||||
@@ -138,7 +138,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(true),
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0'),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(true)
|
||||
));
|
||||
|
||||
@@ -149,14 +149,26 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage()
|
||||
));
|
||||
|
||||
$this->info['width'] =
|
||||
$this->info['height'] =
|
||||
new HTMLPurifier_AttrDef_CSS_DenyElementDecorator(
|
||||
new HTMLPurifier_AttrDef_CSS_Composite(array(
|
||||
new HTMLPurifier_AttrDef_CSS_Length(true),
|
||||
$trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(array(
|
||||
new HTMLPurifier_AttrDef_CSS_Length('0'),
|
||||
new HTMLPurifier_AttrDef_CSS_Percentage(true),
|
||||
new HTMLPurifier_AttrDef_Enum(array('auto'))
|
||||
)), 'img');
|
||||
));
|
||||
$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();
|
||||
|
||||
|
@@ -55,10 +55,7 @@ class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
|
||||
$escape_invalid_children = $config->get('Core', 'EscapeInvalidChildren');
|
||||
|
||||
// generator
|
||||
static $gen = null;
|
||||
if ($gen === null) {
|
||||
$gen = new HTMLPurifier_Generator();
|
||||
}
|
||||
$gen = new HTMLPurifier_Generator($config, $context);
|
||||
|
||||
foreach ($tokens_of_children as $token) {
|
||||
if (!empty($token->is_whitespace)) {
|
||||
@@ -83,7 +80,7 @@ class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
|
||||
$result[] = $token;
|
||||
} elseif ($pcdata_allowed && $escape_invalid_children) {
|
||||
$result[] = new HTMLPurifier_Token_Text(
|
||||
$gen->generateFromToken($token, $config)
|
||||
$gen->generateFromToken($token)
|
||||
);
|
||||
}
|
||||
continue;
|
||||
@@ -94,7 +91,7 @@ class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
|
||||
} elseif ($pcdata_allowed && $escape_invalid_children) {
|
||||
$result[] =
|
||||
new HTMLPurifier_Token_Text(
|
||||
$gen->generateFromToken( $token, $config )
|
||||
$gen->generateFromToken($token)
|
||||
);
|
||||
} else {
|
||||
// drop silently
|
||||
|
@@ -20,7 +20,7 @@ class HTMLPurifier_Config
|
||||
/**
|
||||
* HTML Purifier's version
|
||||
*/
|
||||
public $version = '3.1.0';
|
||||
public $version = '3.1.1';
|
||||
|
||||
/**
|
||||
* Bool indicator whether or not to automatically finalize
|
||||
@@ -125,7 +125,7 @@ class HTMLPurifier_Config
|
||||
E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
if ($this->def->info[$namespace][$key]->class == 'alias') {
|
||||
if (isset($this->def->info[$namespace][$key]->isAlias)) {
|
||||
$d = $this->def->info[$namespace][$key];
|
||||
trigger_error('Cannot get value from aliased directive, use real name ' . $d->namespace . '.' . $d->name,
|
||||
E_USER_ERROR);
|
||||
@@ -196,40 +196,48 @@ class HTMLPurifier_Config
|
||||
E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
if ($this->def->info[$namespace][$key]->class == 'alias') {
|
||||
$def = $this->def->info[$namespace][$key];
|
||||
|
||||
if (isset($def->isAlias)) {
|
||||
if ($from_alias) {
|
||||
trigger_error('Double-aliases not allowed, please fix '.
|
||||
'ConfigSchema bug with' . "$namespace.$key", E_USER_ERROR);
|
||||
return;
|
||||
}
|
||||
$this->set($new_ns = $this->def->info[$namespace][$key]->namespace,
|
||||
$new_dir = $this->def->info[$namespace][$key]->name,
|
||||
$this->set($new_ns = $def->namespace,
|
||||
$new_dir = $def->name,
|
||||
$value, true);
|
||||
trigger_error("$namespace.$key is an alias, preferred directive name is $new_ns.$new_dir", E_USER_NOTICE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Raw type might be negative when using the fully optimized form
|
||||
// of stdclass, which indicates allow_null == true
|
||||
$rtype = is_int($def) ? $def : $def->type;
|
||||
if ($rtype < 0) {
|
||||
$type = -$rtype;
|
||||
$allow_null = true;
|
||||
} else {
|
||||
$type = $rtype;
|
||||
$allow_null = isset($def->allow_null);
|
||||
}
|
||||
|
||||
try {
|
||||
$value = $this->parser->parse(
|
||||
$value,
|
||||
$type = $this->def->info[$namespace][$key]->type,
|
||||
$this->def->info[$namespace][$key]->allow_null
|
||||
);
|
||||
$value = $this->parser->parse($value, $type, $allow_null);
|
||||
} catch (HTMLPurifier_VarParserException $e) {
|
||||
trigger_error('Value for ' . "$namespace.$key" . ' is of invalid type, should be ' . $type, E_USER_WARNING);
|
||||
trigger_error('Value for ' . "$namespace.$key" . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
if (is_string($value)) {
|
||||
if (is_string($value) && is_object($def)) {
|
||||
// resolve value alias if defined
|
||||
if (isset($this->def->info[$namespace][$key]->aliases[$value])) {
|
||||
$value = $this->def->info[$namespace][$key]->aliases[$value];
|
||||
if (isset($def->aliases[$value])) {
|
||||
$value = $def->aliases[$value];
|
||||
}
|
||||
if ($this->def->info[$namespace][$key]->allowed !== true) {
|
||||
// check to see if the value is allowed
|
||||
if (!isset($this->def->info[$namespace][$key]->allowed[$value])) {
|
||||
trigger_error('Value not supported, valid values are: ' .
|
||||
$this->_listify($this->def->info[$namespace][$key]->allowed), E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
// check to see if the value is allowed
|
||||
if (isset($def->allowed) && !isset($def->allowed[$value])) {
|
||||
trigger_error('Value not supported, valid values are: ' .
|
||||
$this->_listify($def->allowed), E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->conf[$namespace][$key] = $value;
|
||||
@@ -386,7 +394,7 @@ class HTMLPurifier_Config
|
||||
if (isset($blacklisted_directives["$ns.$directive"])) continue;
|
||||
if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue;
|
||||
}
|
||||
if ($def->class == 'alias') continue;
|
||||
if (isset($def->isAlias)) continue;
|
||||
if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue;
|
||||
$ret[] = array($ns, $directive);
|
||||
}
|
||||
|
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Base class for configuration entity
|
||||
*/
|
||||
abstract class HTMLPurifier_ConfigDef {
|
||||
public $class = false;
|
||||
}
|
||||
|
@@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Structure object containing definition of a directive.
|
||||
* @note This structure does not contain default values
|
||||
*/
|
||||
class HTMLPurifier_ConfigDef_Directive extends HTMLPurifier_ConfigDef
|
||||
{
|
||||
|
||||
public $class = 'directive';
|
||||
|
||||
public function __construct(
|
||||
$type = null,
|
||||
$allow_null = null,
|
||||
$allowed = null,
|
||||
$aliases = null
|
||||
) {
|
||||
if ( $type !== null) $this->type = $type;
|
||||
if ( $allow_null !== null) $this->allow_null = $allow_null;
|
||||
if ( $allowed !== null) $this->allowed = $allowed;
|
||||
if ( $aliases !== null) $this->aliases = $aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed type of the directive. Values are:
|
||||
* - string
|
||||
* - istring (case insensitive string)
|
||||
* - int
|
||||
* - float
|
||||
* - bool
|
||||
* - lookup (array of value => true)
|
||||
* - list (regular numbered index array)
|
||||
* - hash (array of key => value)
|
||||
* - mixed (anything goes)
|
||||
*/
|
||||
public $type = 'mixed';
|
||||
|
||||
/**
|
||||
* Is null allowed? Has no effect for mixed type.
|
||||
* @bool
|
||||
*/
|
||||
public $allow_null = false;
|
||||
|
||||
/**
|
||||
* Lookup table of allowed values of the element, bool true if all allowed.
|
||||
*/
|
||||
public $allowed = true;
|
||||
|
||||
/**
|
||||
* Hash of value aliases, i.e. values that are equivalent.
|
||||
*/
|
||||
public $aliases = array();
|
||||
|
||||
}
|
||||
|
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Structure object describing a directive alias
|
||||
*/
|
||||
class HTMLPurifier_ConfigDef_DirectiveAlias extends HTMLPurifier_ConfigDef
|
||||
{
|
||||
public $class = 'alias';
|
||||
|
||||
/**
|
||||
* Namespace being aliased to
|
||||
*/
|
||||
public $namespace;
|
||||
/**
|
||||
* Directive being aliased to
|
||||
*/
|
||||
public $name;
|
||||
|
||||
public function __construct($namespace, $name) {
|
||||
$this->namespace = $namespace;
|
||||
$this->name = $name;
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Structure object describing of a namespace
|
||||
*/
|
||||
class HTMLPurifier_ConfigDef_Namespace extends HTMLPurifier_ConfigDef
|
||||
{
|
||||
public $class = 'namespace';
|
||||
}
|
||||
|
@@ -12,7 +12,33 @@ class HTMLPurifier_ConfigSchema {
|
||||
public $defaults = array();
|
||||
|
||||
/**
|
||||
* Definition of the directives.
|
||||
* Definition of the directives. The structure of this is:
|
||||
*
|
||||
* array(
|
||||
* 'Namespace' => array(
|
||||
* 'Directive' => new stdclass(),
|
||||
* )
|
||||
* )
|
||||
*
|
||||
* The stdclass may have the following properties:
|
||||
*
|
||||
* - If isAlias isn't set:
|
||||
* - type: Integer type of directive, see HTMLPurifier_VarParser for definitions
|
||||
* - allow_null: If set, this directive allows null values
|
||||
* - aliases: If set, an associative array of value aliases to real values
|
||||
* - allowed: If set, a lookup array of allowed (string) values
|
||||
* - If isAlias is set:
|
||||
* - namespace: Namespace this directive aliases to
|
||||
* - name: Directive name this directive aliases to
|
||||
*
|
||||
* In certain degenerate cases, stdclass will actually be an integer. In
|
||||
* that case, the value is equivalent to an stdclass with the type
|
||||
* property set to the integer. If the integer is negative, type is
|
||||
* equal to the absolute value of integer, and allow_null is true.
|
||||
*
|
||||
* This class is friendly with HTMLPurifier_Config. If you need introspection
|
||||
* about the schema, you're better of using the ConfigSchema_Interchange,
|
||||
* which uses more memory but has much richer information.
|
||||
*/
|
||||
public $info = array();
|
||||
|
||||
@@ -21,15 +47,6 @@ class HTMLPurifier_ConfigSchema {
|
||||
*/
|
||||
static protected $singleton;
|
||||
|
||||
/**
|
||||
* Variable parser.
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
public function __construct() {
|
||||
$this->parser = new HTMLPurifier_VarParser_Flexible();
|
||||
}
|
||||
|
||||
/**
|
||||
* Unserializes the default ConfigSchema.
|
||||
*/
|
||||
@@ -62,11 +79,11 @@ class HTMLPurifier_ConfigSchema {
|
||||
* @param $allow_null Whether or not to allow null values
|
||||
*/
|
||||
public function add($namespace, $name, $default, $type, $allow_null) {
|
||||
$default = $this->parser->parse($default, $type, $allow_null);
|
||||
$this->info[$namespace][$name] = new HTMLPurifier_ConfigDef_Directive();
|
||||
$this->info[$namespace][$name]->type = $type;
|
||||
$this->info[$namespace][$name]->allow_null = $allow_null;
|
||||
$this->defaults[$namespace][$name] = $default;
|
||||
$obj = new stdclass();
|
||||
$obj->type = is_int($type) ? $type : HTMLPurifier_VarParser::$types[$type];
|
||||
if ($allow_null) $obj->allow_null = true;
|
||||
$this->info[$namespace][$name] = $obj;
|
||||
$this->defaults[$namespace][$name] = $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,6 +107,9 @@ class HTMLPurifier_ConfigSchema {
|
||||
* @param $aliases Hash of aliased values to the real alias
|
||||
*/
|
||||
public function addValueAliases($namespace, $name, $aliases) {
|
||||
if (!isset($this->info[$namespace][$name]->aliases)) {
|
||||
$this->info[$namespace][$name]->aliases = array();
|
||||
}
|
||||
foreach ($aliases as $alias => $real) {
|
||||
$this->info[$namespace][$name]->aliases[$alias] = $real;
|
||||
}
|
||||
@@ -104,7 +124,6 @@ class HTMLPurifier_ConfigSchema {
|
||||
* @param $allowed Lookup array of allowed values
|
||||
*/
|
||||
public function addAllowedValues($namespace, $name, $allowed) {
|
||||
$type = $this->info[$namespace][$name]->type;
|
||||
$this->info[$namespace][$name]->allowed = $allowed;
|
||||
}
|
||||
|
||||
@@ -116,7 +135,26 @@ class HTMLPurifier_ConfigSchema {
|
||||
* @param $new_name Directive that the alias will be to
|
||||
*/
|
||||
public function addAlias($namespace, $name, $new_namespace, $new_name) {
|
||||
$this->info[$namespace][$name] = new HTMLPurifier_ConfigDef_DirectiveAlias($new_namespace, $new_name);
|
||||
$obj = new stdclass;
|
||||
$obj->namespace = $new_namespace;
|
||||
$obj->name = $new_name;
|
||||
$obj->isAlias = true;
|
||||
$this->info[$namespace][$name] = $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces any stdclass that only has the type property with type integer.
|
||||
*/
|
||||
public function postProcess() {
|
||||
foreach ($this->info as $namespace => $info) {
|
||||
foreach ($info as $directive => $v) {
|
||||
if (count((array) $v) == 1) {
|
||||
$this->info[$namespace][$directive] = $v->type;
|
||||
} elseif (count((array) $v) == 2 && isset($v->allow_null)) {
|
||||
$this->info[$namespace][$directive] = -$v->type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DEPRECATED METHODS
|
||||
@@ -124,7 +162,6 @@ class HTMLPurifier_ConfigSchema {
|
||||
/** @see HTMLPurifier_ConfigSchema->set() */
|
||||
public static function define($namespace, $name, $default, $type, $description) {
|
||||
HTMLPurifier_ConfigSchema::deprecated(__METHOD__);
|
||||
// process modifiers (OPTIMIZE!)
|
||||
$type_values = explode('/', $type, 2);
|
||||
$type = $type_values[0];
|
||||
$modifier = isset($type_values[1]) ? $type_values[1] : false;
|
||||
@@ -168,7 +205,8 @@ class HTMLPurifier_ConfigSchema {
|
||||
/** @deprecated, use HTMLPurifier_VarParser->parse() */
|
||||
public function validate($a, $b, $c = false) {
|
||||
trigger_error("HTMLPurifier_ConfigSchema->validate deprecated, use HTMLPurifier_VarParser->parse instead", E_USER_NOTICE);
|
||||
return $this->parser->parse($a, $b, $c);
|
||||
$parser = new HTMLPurifier_VarParser();
|
||||
return $parser->parse($a, $b, $c);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -43,6 +43,7 @@ class HTMLPurifier_ConfigSchema_Builder_ConfigSchema
|
||||
);
|
||||
}
|
||||
}
|
||||
$schema->postProcess();
|
||||
return $schema;
|
||||
}
|
||||
|
||||
|
@@ -111,7 +111,8 @@ class HTMLPurifier_ConfigSchema_Validator
|
||||
if (!is_null($d->allowed) || !empty($d->valueAliases)) {
|
||||
// allowed and valueAliases require that we be dealing with
|
||||
// strings, so check for that early.
|
||||
if (!isset(HTMLPurifier_VarParser::$stringTypes[$d->type])) {
|
||||
$d_int = HTMLPurifier_VarParser::$types[$d->type];
|
||||
if (!isset(HTMLPurifier_VarParser::$stringTypes[$d_int])) {
|
||||
$this->error('type', 'must be a string type when used with allowed or value aliases');
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@@ -0,0 +1,15 @@
|
||||
CSS.MaxImgLength
|
||||
TYPE: string/null
|
||||
DEFAULT: '1200px'
|
||||
VERSION: 3.1.1
|
||||
--DESCRIPTION--
|
||||
<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>
|
@@ -0,0 +1,13 @@
|
||||
HTML.MaxImgLength
|
||||
TYPE: int/null
|
||||
DEFAULT: 1200
|
||||
VERSION: 3.1.1
|
||||
--DESCRIPTION--
|
||||
<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>
|
13
library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt
Normal file
13
library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
HTML.SafeEmbed
|
||||
TYPE: bool
|
||||
VERSION: 3.1.1
|
||||
DEFAULT: false
|
||||
--DESCRIPTION--
|
||||
<p>
|
||||
Whether or not to permit embed tags in documents, with a number of extra
|
||||
security features added to prevent script execution. This is similar to
|
||||
what websites like MySpace do to embed tags. Embed is a proprietary
|
||||
element and will cause your website to stop validating. You probably want
|
||||
to enable this with %HTML.SafeObject.
|
||||
<strong>Highly experimental.</strong>
|
||||
</p>
|
13
library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt
Normal file
13
library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
HTML.SafeObject
|
||||
TYPE: bool
|
||||
VERSION: 3.1.1
|
||||
DEFAULT: false
|
||||
--DESCRIPTION--
|
||||
<p>
|
||||
Whether or not to permit object tags in documents, with a number of extra
|
||||
security features added to prevent script execution. This is similar to
|
||||
what websites like MySpace do to object tags. You may also want to
|
||||
enable %HTML.SafeEmbed for maximum interoperability with Internet Explorer,
|
||||
although embed tags will cause your website to stop validating.
|
||||
<strong>Highly experimental.</strong>
|
||||
</p>
|
@@ -6,7 +6,7 @@ DEFAULT: NULL
|
||||
|
||||
<p>
|
||||
Munges all browsable (usually http, https and ftp)
|
||||
absolute URI's into another URI, usually a URI redirection service.
|
||||
absolute URIs into another URI, usually a URI redirection service.
|
||||
This directive accepts a URI, formatted with a <code>%s</code> where
|
||||
the url-encoded original URI should be inserted (sample:
|
||||
<code>http://www.google.com/url?q=%s</code>).
|
||||
@@ -19,13 +19,64 @@ DEFAULT: NULL
|
||||
Prevent PageRank leaks, while being fairly transparent
|
||||
to users (you may also want to add some client side JavaScript to
|
||||
override the text in the statusbar). <strong>Notice</strong>:
|
||||
Many security experts believe that this form of protection does
|
||||
not deter spam-bots.
|
||||
Many security experts believe that this form of protection does not deter spam-bots.
|
||||
</li>
|
||||
<li>
|
||||
Redirect users to a splash page telling them they are leaving your
|
||||
website. While this is poor usability practice, it is often
|
||||
mandated
|
||||
website. While this is poor usability practice, it is often mandated
|
||||
in corporate environments.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Prior to HTML Purifier 3.1.1, this directive also enabled the munging
|
||||
of browsable external resources, which could break things if your redirection
|
||||
script was a splash page or used <code>meta</code> tags. To revert to
|
||||
previous behavior, please use %URI.MungeResources.
|
||||
</p>
|
||||
<p>
|
||||
You may want to also use %URI.MungeSecretKey along with this directive
|
||||
in order to enforce what URIs your redirector script allows. Open
|
||||
redirector scripts can be a security risk and negatively affect the
|
||||
reputation of your domain name.
|
||||
</p>
|
||||
<p>
|
||||
Starting with HTML Purifier 3.1.1, there is also these substitutions:
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Description</th>
|
||||
<th>Example <code><a href=""></code></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>%r</td>
|
||||
<td>1 - The URI embeds a resource<br />(blank) - The URI is merely a link</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>%n</td>
|
||||
<td>The name of the tag this URI came from</td>
|
||||
<td>a</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>%m</td>
|
||||
<td>The name of the attribute this URI came from</td>
|
||||
<td>href</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>%p</td>
|
||||
<td>The name of the CSS property this URI came from, or blank if irrelevant</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
Admittedly, these letters are somewhat arbitrary; the only stipulation
|
||||
was that they couldn't be a through f. r is for resource (I would have preferred
|
||||
e, but you take what you can get), n is for name, m
|
||||
was picked because it came after n (and I couldn't use a), p is for
|
||||
property.
|
||||
</p>
|
||||
|
@@ -0,0 +1,16 @@
|
||||
URI.MungeResources
|
||||
TYPE: bool
|
||||
VERSION: 3.1.1
|
||||
DEFAULT: false
|
||||
--DESCRIPTION--
|
||||
<p>
|
||||
If true, any URI munging directives like %URI.Munge
|
||||
will also apply to embedded resources, such as <code><img src=""></code>.
|
||||
Be careful enabling this directive if you have a redirector script
|
||||
that does not use the <code>Location</code> HTTP header; all of your images
|
||||
and other embedded resources will break.
|
||||
</p>
|
||||
<p>
|
||||
<strong>Warning:</strong> It is strongly advised you use this in conjunction
|
||||
%URI.MungeSecretKey to mitigate the security risk of an open redirector.
|
||||
</p>
|
@@ -0,0 +1,29 @@
|
||||
URI.MungeSecretKey
|
||||
TYPE: string/null
|
||||
VERSION: 3.1.1
|
||||
DEFAULT: NULL
|
||||
--DESCRIPTION--
|
||||
<p>
|
||||
This directive enables secure checksum generation along with %URI.Munge.
|
||||
It should be set to a secure key that is not shared with anyone else.
|
||||
The checksum can be placed in the URI using %t. Use of this checksum
|
||||
affords an additional level of protection by allowing a redirector
|
||||
to check if a URI has passed through HTML Purifier with this line:
|
||||
</p>
|
||||
|
||||
<pre>$checksum === sha1($secret_key . ':' . $url)</pre>
|
||||
|
||||
<p>
|
||||
If the output is TRUE, the redirector script should accept the URI.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Please note that it would still be possible for an attacker to procure
|
||||
secure hashes en-mass by abusing your website's Preview feature or the
|
||||
like, but this service affords an additional level of protection
|
||||
that should be combined with website blacklisting.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Remember this has no effect if %URI.Munge is not on.
|
||||
</p>
|
@@ -46,35 +46,13 @@ class HTMLPurifier_Encoder
|
||||
*/
|
||||
public static function cleanUTF8($str, $force_php = false) {
|
||||
|
||||
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');
|
||||
|
||||
// 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 iconv/php stuff. 99% of the time, this will be the case.
|
||||
if (preg_match('/^.{1}/us', $str)) {
|
||||
return strtr($str, $non_sgml_chars);
|
||||
}
|
||||
|
||||
if ($iconv && !$force_php) {
|
||||
// do the shortcut way
|
||||
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
|
||||
$str = iconv('UTF-8', 'UTF-8//IGNORE', $str);
|
||||
restore_error_handler();
|
||||
return strtr($str, $non_sgml_chars);
|
||||
// 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;
|
||||
}
|
||||
|
||||
$mState = 0; // cached expected number of octets after the current octet
|
||||
@@ -185,7 +163,17 @@ class HTMLPurifier_Encoder
|
||||
) {
|
||||
|
||||
} elseif (0xFEFF != $mUcs4 && // omit BOM
|
||||
!($mUcs4 >= 128 && $mUcs4 <= 159) // omit non-SGML
|
||||
// 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)
|
||||
)
|
||||
) {
|
||||
$out .= $char;
|
||||
}
|
||||
@@ -276,17 +264,20 @@ class HTMLPurifier_Encoder
|
||||
* Converts a string to UTF-8 based on configuration.
|
||||
*/
|
||||
public static function convertToUTF8($str, $config, $context) {
|
||||
static $iconv = null;
|
||||
if ($iconv === null) $iconv = function_exists('iconv');
|
||||
$encoding = $config->get('Core', 'Encoding');
|
||||
if ($encoding === 'utf-8') return $str;
|
||||
static $iconv = null;
|
||||
if ($iconv === null) $iconv = function_exists('iconv');
|
||||
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
|
||||
if ($iconv && !$config->get('Test', 'ForceNoIconv')) {
|
||||
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
|
||||
$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;
|
||||
} elseif ($encoding === 'iso-8859-1') {
|
||||
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
|
||||
$str = utf8_encode($str);
|
||||
restore_error_handler();
|
||||
return $str;
|
||||
@@ -300,20 +291,28 @@ class HTMLPurifier_Encoder
|
||||
* characters being omitted.
|
||||
*/
|
||||
public static function convertFromUTF8($str, $config, $context) {
|
||||
static $iconv = null;
|
||||
if ($iconv === null) $iconv = function_exists('iconv');
|
||||
$encoding = $config->get('Core', 'Encoding');
|
||||
if ($encoding === 'utf-8') return $str;
|
||||
if ($config->get('Core', 'EscapeNonASCIICharacters')) {
|
||||
static $iconv = null;
|
||||
if ($iconv === null) $iconv = function_exists('iconv');
|
||||
if ($escape = $config->get('Core', 'EscapeNonASCIICharacters')) {
|
||||
$str = HTMLPurifier_Encoder::convertToASCIIDumbLossless($str);
|
||||
}
|
||||
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
|
||||
if ($iconv && !$config->get('Test', 'ForceNoIconv')) {
|
||||
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
|
||||
// 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;
|
||||
} elseif ($encoding === 'iso-8859-1') {
|
||||
set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
|
||||
$str = utf8_decode($str);
|
||||
restore_error_handler();
|
||||
return $str;
|
||||
@@ -368,6 +367,47 @@ 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.
|
||||
*/
|
||||
public static 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -35,8 +35,7 @@ class HTMLPurifier_Generator
|
||||
* @param $config Instance of HTMLPurifier_Config
|
||||
* @param $context Instance of HTMLPurifier_Context
|
||||
*/
|
||||
public function __construct($config = null, $context = null) {
|
||||
if (!$config) $config = HTMLPurifier_Config::createDefault();
|
||||
public function __construct($config, $context) {
|
||||
$this->config = $config;
|
||||
$this->_scriptFix = $config->get('Output', 'CommentScriptContents');
|
||||
$this->_def = $config->getHTMLDefinition();
|
||||
|
@@ -76,6 +76,11 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
|
||||
*/
|
||||
public $info_content_sets = array();
|
||||
|
||||
/**
|
||||
* Indexed list of HTMLPurifier_Injector to be used.
|
||||
*/
|
||||
public $info_injector = array();
|
||||
|
||||
/**
|
||||
* Doctype object
|
||||
*/
|
||||
@@ -186,18 +191,22 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
|
||||
$this->doctype = $this->manager->doctype;
|
||||
|
||||
foreach ($this->manager->modules as $module) {
|
||||
foreach($module->info_tag_transform as $k => $v) {
|
||||
foreach($module->info_tag_transform as $k => $v) {
|
||||
if ($v === false) unset($this->info_tag_transform[$k]);
|
||||
else $this->info_tag_transform[$k] = $v;
|
||||
}
|
||||
foreach($module->info_attr_transform_pre as $k => $v) {
|
||||
foreach($module->info_attr_transform_pre as $k => $v) {
|
||||
if ($v === false) unset($this->info_attr_transform_pre[$k]);
|
||||
else $this->info_attr_transform_pre[$k] = $v;
|
||||
}
|
||||
foreach($module->info_attr_transform_post as $k => $v) {
|
||||
foreach($module->info_attr_transform_post as $k => $v) {
|
||||
if ($v === false) unset($this->info_attr_transform_post[$k]);
|
||||
else $this->info_attr_transform_post[$k] = $v;
|
||||
}
|
||||
foreach ($module->info_injector as $k => $v) {
|
||||
if ($v === false) unset($this->info_injector[$k]);
|
||||
else $this->info_injector[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
$this->info = $this->manager->getElements();
|
||||
@@ -356,6 +365,14 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
|
||||
}
|
||||
}
|
||||
|
||||
// setup injectors -----------------------------------------------------
|
||||
foreach ($this->info_injector as $i => $injector) {
|
||||
if ($injector->checkNeeded($config) !== false) {
|
||||
// remove injector that does not have it's required
|
||||
// elements/attributes present, and is thus not needed.
|
||||
unset($this->info_injector[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -71,6 +71,14 @@ class HTMLPurifier_HTMLModule
|
||||
*/
|
||||
public $info_attr_transform_post = array();
|
||||
|
||||
/**
|
||||
* List of HTMLPurifier_Injector to be performed during well-formedness fixing.
|
||||
* An injector will only be invoked if all of it's pre-requisites are met;
|
||||
* if an injector fails setup, there will be no error; it will simply be
|
||||
* silently disabled.
|
||||
*/
|
||||
public $info_injector = array();
|
||||
|
||||
/**
|
||||
* Boolean flag that indicates whether or not getChildDef is implemented.
|
||||
* For optimization reasons: may save a call to a function. Be sure
|
||||
@@ -222,5 +230,14 @@ 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
|
||||
*/
|
||||
public function setup($config) {}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -12,7 +12,7 @@ class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule
|
||||
'I18N' => array('dir' => false)
|
||||
);
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$bdo = $this->addElement(
|
||||
'bdo', 'Inline', 'Inline', array('Core', 'Lang'),
|
||||
array(
|
||||
|
@@ -9,7 +9,7 @@ class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Edit';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$contents = 'Chameleon: #PCDATA | Inline ! #PCDATA | Flow';
|
||||
$attr = array(
|
||||
'cite' => 'URI',
|
||||
|
@@ -8,7 +8,7 @@ class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Hypertext';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$a = $this->addElement(
|
||||
'a', 'Inline', 'Inline', 'Common',
|
||||
array(
|
||||
|
@@ -10,17 +10,25 @@ class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Image';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$max = $config->get('HTML', 'MaxImgLength');
|
||||
$img = $this->addElement(
|
||||
'img', 'Inline', 'Empty', 'Common',
|
||||
array(
|
||||
'alt*' => 'Text',
|
||||
'height' => 'Length',
|
||||
// According to the spec, it's Length, but percents can
|
||||
// be abused, so we allow only Pixels.
|
||||
'height' => 'Pixels#' . $max,
|
||||
'width' => 'Pixels#' . $max,
|
||||
'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[] =
|
||||
|
@@ -21,7 +21,7 @@ class HTMLPurifier_HTMLModule_Legacy extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Legacy';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
|
||||
$this->addElement('basefont', 'Inline', 'Empty', false, array(
|
||||
'color' => 'Color',
|
||||
|
@@ -19,7 +19,7 @@ class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $content_sets = array('Flow' => 'List');
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$this->addElement('ol', 'List', 'Required: li', 'Common');
|
||||
$this->addElement('ul', 'List', 'Required: li', 'Common');
|
||||
$this->addElement('dl', 'List', 'Required: dt | dd', 'Common');
|
||||
|
@@ -11,7 +11,7 @@ class HTMLPurifier_HTMLModule_Object extends HTMLPurifier_HTMLModule
|
||||
public $name = 'Object';
|
||||
public $safe = false;
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
|
||||
$this->addElement('object', 'Inline', 'Optional: #PCDATA | Flow | param', 'Common',
|
||||
array(
|
||||
|
@@ -15,7 +15,7 @@ class HTMLPurifier_HTMLModule_Presentation extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Presentation';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$this->addElement('b', 'Inline', 'Inline', 'Common');
|
||||
$this->addElement('big', 'Inline', 'Inline', 'Common');
|
||||
$this->addElement('hr', 'Block', 'Empty', 'Common');
|
||||
|
@@ -9,7 +9,7 @@ class HTMLPurifier_HTMLModule_Proprietary extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Proprietary';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
|
||||
$this->addElement('marquee', 'Inline', 'Flow', 'Common',
|
||||
array(
|
||||
|
@@ -9,7 +9,7 @@ class HTMLPurifier_HTMLModule_Ruby extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Ruby';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$this->addElement('ruby', 'Inline',
|
||||
'Custom: ((rb, (rt | (rp, rt, rp))) | (rbc, rtc, rtc?))',
|
||||
'Common');
|
||||
|
31
library/HTMLPurifier/HTMLModule/SafeEmbed.php
Normal file
31
library/HTMLPurifier/HTMLModule/SafeEmbed.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A "safe" embed module. See SafeObject. This is a proprietary element.
|
||||
*/
|
||||
class HTMLPurifier_HTMLModule_SafeEmbed extends HTMLPurifier_HTMLModule
|
||||
{
|
||||
|
||||
public $name = 'SafeEmbed';
|
||||
|
||||
public function setup($config) {
|
||||
|
||||
$max = $config->get('HTML', 'MaxImgLength');
|
||||
$embed = $this->addElement(
|
||||
'embed', 'Inline', 'Empty', 'Common',
|
||||
array(
|
||||
'src*' => 'URI#embedded',
|
||||
'type' => 'Enum#application/x-shockwave-flash',
|
||||
'width' => 'Pixels#' . $max,
|
||||
'height' => 'Pixels#' . $max,
|
||||
'allowscriptaccess' => 'Enum#never',
|
||||
'allownetworking' => 'Enum#internal',
|
||||
'wmode' => 'Enum#window',
|
||||
'name' => 'ID',
|
||||
)
|
||||
);
|
||||
$embed->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeEmbed();
|
||||
|
||||
}
|
||||
|
||||
}
|
48
library/HTMLPurifier/HTMLModule/SafeObject.php
Normal file
48
library/HTMLPurifier/HTMLModule/SafeObject.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* A "safe" object module. In theory, objects permitted by this module will
|
||||
* be safe, and untrusted users can be allowed to embed arbitrary flash objects
|
||||
* (maybe other types too, but only Flash is supported as of right now).
|
||||
* Highly experimental.
|
||||
*/
|
||||
class HTMLPurifier_HTMLModule_SafeObject extends HTMLPurifier_HTMLModule
|
||||
{
|
||||
|
||||
public $name = 'SafeObject';
|
||||
|
||||
public function setup($config) {
|
||||
|
||||
// These definitions are not intrinsically safe: the attribute transforms
|
||||
// are a vital part of ensuring safety.
|
||||
|
||||
$max = $config->get('HTML', 'MaxImgLength');
|
||||
$object = $this->addElement(
|
||||
'object',
|
||||
'Inline',
|
||||
'Optional: param | Flow | #PCDATA',
|
||||
'Common',
|
||||
array(
|
||||
// While technically not required by the spec, we're forcing
|
||||
// it to this value.
|
||||
'type' => 'Enum#application/x-shockwave-flash',
|
||||
'width' => 'Pixels#' . $max,
|
||||
'height' => 'Pixels#' . $max,
|
||||
'data' => 'URI#embedded'
|
||||
)
|
||||
);
|
||||
$object->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeObject();
|
||||
|
||||
$param = $this->addElement('param', false, 'Empty', false,
|
||||
array(
|
||||
'id' => 'ID',
|
||||
'name*' => 'Text',
|
||||
'value' => 'Text'
|
||||
)
|
||||
);
|
||||
$param->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeParam();
|
||||
$this->info_injector[] = 'SafeObject';
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -20,7 +20,7 @@ class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
|
||||
public $content_sets = array('Block' => 'script | noscript', 'Inline' => 'script | noscript');
|
||||
public $safe = false;
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
// 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
|
||||
|
@@ -15,7 +15,7 @@ class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule
|
||||
'Core' => array(0 => array('Style'))
|
||||
);
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$this->attr_collections['Style']['style'] = new HTMLPurifier_AttrDef_CSS();
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Tables';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
|
||||
$this->addElement('caption', false, 'Inline', 'Common');
|
||||
|
||||
|
@@ -8,7 +8,7 @@ class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule
|
||||
|
||||
public $name = 'Target';
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
$elements = array('a');
|
||||
foreach ($elements as $name) {
|
||||
$e = $this->addBlankElement($name);
|
||||
|
@@ -20,7 +20,7 @@ class HTMLPurifier_HTMLModule_Text extends HTMLPurifier_HTMLModule
|
||||
'Flow' => 'Heading | Block | Inline'
|
||||
);
|
||||
|
||||
public function __construct() {
|
||||
public function setup($config) {
|
||||
|
||||
// Inline Phrasal -------------------------------------------------
|
||||
$this->addElement('abbr', 'Inline', 'Inline', 'Common');
|
||||
|
@@ -35,7 +35,7 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
|
||||
* @todo Wildcard matching and error reporting when an added or
|
||||
* subtracted fix has no effect.
|
||||
*/
|
||||
public function construct($config) {
|
||||
public function setup($config) {
|
||||
|
||||
// create fixes, initialize fixesForLevel
|
||||
$fixes = $this->makeFixes();
|
||||
|
@@ -221,15 +221,35 @@ class HTMLPurifier_HTMLModuleManager
|
||||
$modules[] = 'Proprietary';
|
||||
}
|
||||
|
||||
// add SafeObject/Safeembed modules
|
||||
if ($config->get('HTML', 'SafeObject')) {
|
||||
$modules[] = 'SafeObject';
|
||||
}
|
||||
if ($config->get('HTML', 'SafeEmbed')) {
|
||||
$modules[] = 'SafeEmbed';
|
||||
}
|
||||
|
||||
foreach ($modules as $module) {
|
||||
$this->processModule($module);
|
||||
$this->modules[$module]->setup($config);
|
||||
}
|
||||
|
||||
foreach ($this->doctype->tidyModules as $module) {
|
||||
$this->processModule($module);
|
||||
if (method_exists($this->modules[$module], 'construct')) {
|
||||
$this->modules[$module]->construct($config);
|
||||
$this->modules[$module]->setup($config);
|
||||
}
|
||||
|
||||
// prepare any injectors
|
||||
foreach ($this->modules as $module) {
|
||||
$n = array();
|
||||
foreach ($module->info_injector as $i => $injector) {
|
||||
if (!is_object($injector)) {
|
||||
$class = "HTMLPurifier_Injector_$injector";
|
||||
$injector = new $class;
|
||||
}
|
||||
$n[$injector->name] = $injector;
|
||||
}
|
||||
$module->info_injector = $n;
|
||||
}
|
||||
|
||||
// setup lookup table based on all valid modules
|
||||
|
@@ -58,29 +58,45 @@ abstract class HTMLPurifier_Injector
|
||||
* Prepares the injector by giving it the config and context objects:
|
||||
* this allows references to important variables to be made within
|
||||
* the injector. This function also checks if the HTML environment
|
||||
* will work with the Injector: if p tags are not allowed, the
|
||||
* Auto-Paragraphing injector should not be enabled.
|
||||
* will work with the Injector (see checkNeeded()).
|
||||
* @param $config Instance of HTMLPurifier_Config
|
||||
* @param $context Instance of HTMLPurifier_Context
|
||||
* @return Boolean false if success, string of missing needed element/attribute if failure
|
||||
*/
|
||||
public function prepare($config, $context) {
|
||||
$this->htmlDefinition = $config->getHTMLDefinition();
|
||||
// perform $needed checks
|
||||
foreach ($this->needed as $element => $attributes) {
|
||||
if (is_int($element)) $element = $attributes;
|
||||
if (!isset($this->htmlDefinition->info[$element])) return $element;
|
||||
if (!is_array($attributes)) continue;
|
||||
foreach ($attributes as $name) {
|
||||
if (!isset($this->htmlDefinition->info[$element]->attr[$name])) return "$element.$name";
|
||||
}
|
||||
}
|
||||
// Even though this might fail, some unit tests ignore this and
|
||||
// still test checkNeeded, so be careful. Maybe get rid of that
|
||||
// dependency.
|
||||
$result = $this->checkNeeded($config);
|
||||
if ($result !== false) return $result;
|
||||
$this->currentNesting =& $context->get('CurrentNesting');
|
||||
$this->inputTokens =& $context->get('InputTokens');
|
||||
$this->inputIndex =& $context->get('InputIndex');
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function checks if the HTML environment
|
||||
* will work with the Injector: if p tags are not allowed, the
|
||||
* Auto-Paragraphing injector should not be enabled.
|
||||
* @param $config Instance of HTMLPurifier_Config
|
||||
* @param $context Instance of HTMLPurifier_Context
|
||||
* @return Boolean false if success, string of missing needed element/attribute if failure
|
||||
*/
|
||||
public function checkNeeded($config) {
|
||||
$def = $config->getHTMLDefinition();
|
||||
foreach ($this->needed as $element => $attributes) {
|
||||
if (is_int($element)) $element = $attributes;
|
||||
if (!isset($def->info[$element])) return $element;
|
||||
if (!is_array($attributes)) continue;
|
||||
foreach ($attributes as $name) {
|
||||
if (!isset($def->info[$element]->attr[$name])) return "$element.$name";
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the context node allows a certain element
|
||||
* @param $name Name of element to test for
|
||||
|
83
library/HTMLPurifier/Injector/SafeObject.php
Normal file
83
library/HTMLPurifier/Injector/SafeObject.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Adds important param elements to inside of object in order to make
|
||||
* things safe.
|
||||
*/
|
||||
class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
|
||||
{
|
||||
public $name = 'SafeObject';
|
||||
public $needed = array('object', 'param');
|
||||
|
||||
protected $objectStack = array();
|
||||
protected $paramStack = array();
|
||||
|
||||
// Keep this synchronized with AttrTransform/SafeParam.php
|
||||
protected $addParam = array(
|
||||
'allowScriptAccess' => 'never',
|
||||
'allowNetworking' => 'internal',
|
||||
);
|
||||
protected $allowedParam = array(
|
||||
'wmode' => true,
|
||||
'movie' => true,
|
||||
);
|
||||
|
||||
public function prepare($config, $context) {
|
||||
parent::prepare($config, $context);
|
||||
}
|
||||
|
||||
public function handleElement(&$token) {
|
||||
if ($token->name == 'object') {
|
||||
$this->objectStack[] = $token;
|
||||
$this->paramStack[] = array();
|
||||
$new = array($token);
|
||||
foreach ($this->addParam as $name => $value) {
|
||||
$new[] = new HTMLPurifier_Token_Empty('param', array('name' => $name, 'value' => $value));
|
||||
}
|
||||
$token = $new;
|
||||
} elseif ($token->name == 'param') {
|
||||
$nest = count($this->currentNesting) - 1;
|
||||
if ($nest >= 0 && $this->currentNesting[$nest]->name === 'object') {
|
||||
$i = count($this->objectStack) - 1;
|
||||
if (!isset($token->attr['name'])) {
|
||||
$token = false;
|
||||
return;
|
||||
}
|
||||
$n = $token->attr['name'];
|
||||
// We need this fix because YouTube doesn't supply a data
|
||||
// attribute, which we need if a type is specified. This is
|
||||
// *very* Flash specific.
|
||||
if (!isset($this->objectStack[$i]->attr['data']) && $token->attr['name'] == 'movie') {
|
||||
$this->objectStack[$i]->attr['data'] = $token->attr['value'];
|
||||
}
|
||||
// Check if the parameter is the correct value but has not
|
||||
// already been added
|
||||
if (
|
||||
!isset($this->paramStack[$i][$n]) &&
|
||||
isset($this->addParam[$n]) &&
|
||||
$token->attr['name'] === $this->addParam[$n]
|
||||
) {
|
||||
// keep token, and add to param stack
|
||||
$this->paramStack[$i][$n] = true;
|
||||
} elseif (isset($this->allowedParam[$n])) {
|
||||
// keep token, don't do anything to it
|
||||
// (could possibly check for duplicates here)
|
||||
} else {
|
||||
$token = false;
|
||||
}
|
||||
} else {
|
||||
// not directly inside an object, DENY!
|
||||
$token = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function notifyEnd($token) {
|
||||
if ($token->name == 'object') {
|
||||
array_pop($this->objectStack);
|
||||
array_pop($this->paramStack);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
113
library/HTMLPurifier/Length.php
Normal file
113
library/HTMLPurifier/Length.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Represents a measurable length, with a string numeric magnitude
|
||||
* and a unit. This object is immutable.
|
||||
*/
|
||||
class HTMLPurifier_Length
|
||||
{
|
||||
|
||||
/**
|
||||
* String numeric magnitude.
|
||||
*/
|
||||
protected $n;
|
||||
|
||||
/**
|
||||
* String unit. False is permitted if $n = 0.
|
||||
*/
|
||||
protected $unit;
|
||||
|
||||
/**
|
||||
* Whether or not this length is valid. Null if not calculated yet.
|
||||
*/
|
||||
protected $isValid;
|
||||
|
||||
/**
|
||||
* Lookup array of units recognized by CSS 2.1
|
||||
*/
|
||||
protected static $allowedUnits = array(
|
||||
'em' => true, 'ex' => true, 'px' => true, 'in' => true,
|
||||
'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true
|
||||
);
|
||||
|
||||
/**
|
||||
* @param number $n Magnitude
|
||||
* @param string $u Unit
|
||||
*/
|
||||
public function __construct($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.
|
||||
*/
|
||||
static public function make($s) {
|
||||
if ($s instanceof 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.
|
||||
*/
|
||||
protected function validate() {
|
||||
// Special case:
|
||||
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(HTMLPurifier_Length::$allowedUnits[$this->unit])) return false;
|
||||
// Hack:
|
||||
$def = new HTMLPurifier_AttrDef_CSS_Number();
|
||||
$result = $def->validate($this->n, false, false);
|
||||
if ($result === false) return false;
|
||||
$this->n = $result;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string representation of number.
|
||||
*/
|
||||
public function toString() {
|
||||
if (!$this->isValid()) return false;
|
||||
return $this->n . $this->unit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves string numeric magnitude.
|
||||
*/
|
||||
public function getN() {return $this->n;}
|
||||
|
||||
/**
|
||||
* Retrieves string unit.
|
||||
*/
|
||||
public function getUnit() {return $this->unit;}
|
||||
|
||||
/**
|
||||
* Returns true if this length unit is valid.
|
||||
*/
|
||||
public 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
|
||||
*/
|
||||
public 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;
|
||||
}
|
||||
|
||||
}
|
@@ -20,18 +20,15 @@ class HTMLPurifier_Printer
|
||||
* Initialize $generator.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->generator = new HTMLPurifier_Generator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Give generator necessary configuration if possible
|
||||
*/
|
||||
public function prepareGenerator($config) {
|
||||
// hack for smoketests/configForm.php
|
||||
$all = $config->getAll();
|
||||
if (empty($all['HTML'])) return;
|
||||
$context = new HTMLPurifier_Context();
|
||||
$this->generator->generateFromTokens(array(), $config, $context);
|
||||
$this->generator = new HTMLPurifier_Generator($config, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @todo Rewrite to use Interchange objects
|
||||
*/
|
||||
class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
|
||||
{
|
||||
|
||||
@@ -38,8 +41,8 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
|
||||
$this->name = $name;
|
||||
$this->compress = $compress;
|
||||
// initialize sub-printers
|
||||
$this->fields['default'] = new HTMLPurifier_Printer_ConfigForm_default();
|
||||
$this->fields['bool'] = new HTMLPurifier_Printer_ConfigForm_bool();
|
||||
$this->fields[0] = new HTMLPurifier_Printer_ConfigForm_default();
|
||||
$this->fields[HTMLPurifier_VarParser::BOOL] = new HTMLPurifier_Printer_ConfigForm_bool();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,14 +71,23 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
|
||||
|
||||
/**
|
||||
* Returns HTML output for a configuration form
|
||||
* @param $config Configuration object of current form state
|
||||
* @param $config Configuration object of current form state, or an array
|
||||
* where [0] has an HTML namespace and [1] is being rendered.
|
||||
* @param $allowed Optional namespace(s) and directives to restrict form to.
|
||||
*/
|
||||
public function render($config, $allowed = true, $render_controls = true) {
|
||||
$this->config = $config;
|
||||
$this->prepareGenerator($config);
|
||||
if (is_array($config) && isset($config[0])) {
|
||||
$gen_config = $config[0];
|
||||
$config = $config[1];
|
||||
} else {
|
||||
$gen_config = $config;
|
||||
}
|
||||
|
||||
$allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed);
|
||||
$this->config = $config;
|
||||
$this->genConfig = $gen_config;
|
||||
$this->prepareGenerator($gen_config);
|
||||
|
||||
$allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $config->def);
|
||||
$all = array();
|
||||
foreach ($allowed as $key) {
|
||||
list($ns, $directive) = $key;
|
||||
@@ -148,13 +160,19 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
|
||||
|
||||
$ret .= $this->start('td');
|
||||
$def = $this->config->def->info[$ns][$directive];
|
||||
$type = $def->type;
|
||||
if (!isset($this->fields[$type])) $type = 'default';
|
||||
if (is_int($def)) {
|
||||
$allow_null = $def < 0;
|
||||
$type = abs($def);
|
||||
} else {
|
||||
$type = $def->type;
|
||||
$allow_null = isset($def->allow_null);
|
||||
}
|
||||
if (!isset($this->fields[$type])) $type = 0; // default
|
||||
$type_obj = $this->fields[$type];
|
||||
if ($def->allow_null) {
|
||||
if ($allow_null) {
|
||||
$type_obj = new HTMLPurifier_Printer_ConfigForm_NullDecorator($type_obj);
|
||||
}
|
||||
$ret .= $type_obj->render($ns, $directive, $value, $this->name, $this->config);
|
||||
$ret .= $type_obj->render($ns, $directive, $value, $this->name, array($this->genConfig, $this->config));
|
||||
$ret .= $this->end('td');
|
||||
$ret .= $this->end('tr');
|
||||
}
|
||||
@@ -180,7 +198,14 @@ class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
|
||||
$this->obj = $obj;
|
||||
}
|
||||
public function render($ns, $directive, $value, $name, $config) {
|
||||
$this->prepareGenerator($config);
|
||||
if (is_array($config) && isset($config[0])) {
|
||||
$gen_config = $config[0];
|
||||
$config = $config[1];
|
||||
} else {
|
||||
$gen_config = $config;
|
||||
}
|
||||
$this->prepareGenerator($gen_config);
|
||||
|
||||
$ret = '';
|
||||
$ret .= $this->start('label', array('for' => "$name:Null_$ns.$directive"));
|
||||
$ret .= $this->element('span', "$ns.$directive:", array('class' => 'verbose'));
|
||||
@@ -202,7 +227,7 @@ class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
|
||||
$ret .= $this->elementEmpty('input', $attr);
|
||||
$ret .= $this->text(' or ');
|
||||
$ret .= $this->elementEmpty('br');
|
||||
$ret .= $this->obj->render($ns, $directive, $value, $name, $config);
|
||||
$ret .= $this->obj->render($ns, $directive, $value, $name, array($gen_config, $config));
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
@@ -214,22 +239,33 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
|
||||
public $cols = 18;
|
||||
public $rows = 5;
|
||||
public function render($ns, $directive, $value, $name, $config) {
|
||||
$this->prepareGenerator($config);
|
||||
if (is_array($config) && isset($config[0])) {
|
||||
$gen_config = $config[0];
|
||||
$config = $config[1];
|
||||
} else {
|
||||
$gen_config = $config;
|
||||
}
|
||||
$this->prepareGenerator($gen_config);
|
||||
// this should probably be split up a little
|
||||
$ret = '';
|
||||
$def = $config->def->info[$ns][$directive];
|
||||
if (is_int($def)) {
|
||||
$type = abs($def);
|
||||
} else {
|
||||
$type = $def->type;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
switch ($def->type) {
|
||||
case 'lookup':
|
||||
switch ($type) {
|
||||
case HTMLPurifier_VarParser::LOOKUP:
|
||||
$array = $value;
|
||||
$value = array();
|
||||
foreach ($array as $val => $b) {
|
||||
$value[] = $val;
|
||||
}
|
||||
case 'list':
|
||||
case HTMLPurifier_VarParser::ALIST:
|
||||
$value = implode(PHP_EOL, $value);
|
||||
break;
|
||||
case 'hash':
|
||||
case HTMLPurifier_VarParser::HASH:
|
||||
$nvalue = '';
|
||||
foreach ($value as $i => $v) {
|
||||
$nvalue .= "$i:$v" . PHP_EOL;
|
||||
@@ -240,7 +276,7 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
|
||||
$value = '';
|
||||
}
|
||||
}
|
||||
if ($def->type === 'mixed') {
|
||||
if ($type === HTMLPurifier_VarParser::MIXED) {
|
||||
return 'Not supported';
|
||||
$value = serialize($value);
|
||||
}
|
||||
@@ -249,7 +285,7 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
|
||||
'id' => "$name:$ns.$directive"
|
||||
);
|
||||
if ($value === null) $attr['disabled'] = 'disabled';
|
||||
if (is_array($def->allowed)) {
|
||||
if (isset($def->allowed)) {
|
||||
$ret .= $this->start('select', $attr);
|
||||
foreach ($def->allowed as $val => $b) {
|
||||
$attr = array();
|
||||
@@ -258,8 +294,11 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
|
||||
}
|
||||
$ret .= $this->end('select');
|
||||
} elseif (
|
||||
$def->type == 'text' || $def->type == 'itext' ||
|
||||
$def->type == 'list' || $def->type == 'hash' || $def->type == 'lookup'
|
||||
$type === HTMLPurifier_VarParser::TEXT ||
|
||||
$type === HTMLPurifier_VarParser::ITEXT ||
|
||||
$type === HTMLPurifier_VarParser::ALIST ||
|
||||
$type === HTMLPurifier_VarParser::HASH ||
|
||||
$type === HTMLPurifier_VarParser::LOOKUP
|
||||
) {
|
||||
$attr['cols'] = $this->cols;
|
||||
$attr['rows'] = $this->rows;
|
||||
@@ -280,7 +319,13 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
|
||||
*/
|
||||
class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer {
|
||||
public function render($ns, $directive, $value, $name, $config) {
|
||||
$this->prepareGenerator($config);
|
||||
if (is_array($config) && isset($config[0])) {
|
||||
$gen_config = $config[0];
|
||||
$config = $config[1];
|
||||
} else {
|
||||
$gen_config = $config;
|
||||
}
|
||||
$this->prepareGenerator($gen_config);
|
||||
$ret = '';
|
||||
$ret .= $this->start('div', array('id' => "$name:$ns.$directive"));
|
||||
|
||||
|
@@ -18,7 +18,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
||||
|
||||
// local variables
|
||||
$result = array();
|
||||
$generator = new HTMLPurifier_Generator();
|
||||
$generator = new HTMLPurifier_Generator($config, $context);
|
||||
$escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
|
||||
$e = $context->get('ErrorCollector', true);
|
||||
|
||||
@@ -38,6 +38,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
||||
$this->injectors = array();
|
||||
|
||||
$injectors = $config->getBatch('AutoFormat');
|
||||
$def_injectors = $definition->info_injector;
|
||||
$custom_injectors = $injectors['Custom'];
|
||||
unset($injectors['Custom']); // special case
|
||||
foreach ($injectors as $injector => $b) {
|
||||
@@ -45,6 +46,10 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
||||
if (!$b) continue;
|
||||
$this->injectors[] = new $injector;
|
||||
}
|
||||
foreach ($def_injectors as $injector) {
|
||||
// assumed to be objects
|
||||
$this->injectors[] = $injector;
|
||||
}
|
||||
foreach ($custom_injectors as $injector) {
|
||||
if (is_string($injector)) {
|
||||
$injector = "HTMLPurifier_Injector_$injector";
|
||||
@@ -169,7 +174,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
||||
if ($escape_invalid_tags) {
|
||||
if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag to text');
|
||||
$result[] = new HTMLPurifier_Token_Text(
|
||||
$generator->generateFromToken($token, $config, $context)
|
||||
$generator->generateFromToken($token)
|
||||
);
|
||||
} elseif ($e) {
|
||||
$e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag removed');
|
||||
@@ -209,7 +214,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
|
||||
if ($skipped_tags === false) {
|
||||
if ($escape_invalid_tags) {
|
||||
$result[] = new HTMLPurifier_Token_Text(
|
||||
$generator->generateFromToken($token, $config, $context)
|
||||
$generator->generateFromToken($token)
|
||||
);
|
||||
if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Stray end tag to text');
|
||||
} elseif ($e) {
|
||||
|
@@ -13,7 +13,7 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
|
||||
|
||||
public function execute($tokens, $config, $context) {
|
||||
$definition = $config->getHTMLDefinition();
|
||||
$generator = new HTMLPurifier_Generator();
|
||||
$generator = new HTMLPurifier_Generator($config, $context);
|
||||
$result = array();
|
||||
|
||||
$escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
|
||||
@@ -101,7 +101,7 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
|
||||
// invalid tag, generate HTML representation and insert in
|
||||
if ($e) $e->send(E_WARNING, 'Strategy_RemoveForeignElements: Foreign element to text');
|
||||
$token = new HTMLPurifier_Token_Text(
|
||||
$generator->generateFromToken($token, $config, $context)
|
||||
$generator->generateFromToken($token)
|
||||
);
|
||||
} else {
|
||||
// check if we need to destroy all of the tag's children
|
||||
|
@@ -4,7 +4,6 @@
|
||||
* Abstract base token class that all others inherit from.
|
||||
*/
|
||||
class HTMLPurifier_Token {
|
||||
public $type; /**< Type of node to bypass <tt>is_a()</tt>. */
|
||||
public $line; /**< Line number node was on in source document. Null if unknown. */
|
||||
|
||||
/**
|
||||
|
@@ -128,6 +128,17 @@ class HTMLPurifier_URI
|
||||
$this->path = ''; // just to be safe
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
|
||||
|
||||
public $type = 'URI';
|
||||
protected $filters = array();
|
||||
protected $postFilters = array();
|
||||
protected $registeredFilters = array();
|
||||
|
||||
/**
|
||||
@@ -27,6 +28,7 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
|
||||
$this->registerFilter(new HTMLPurifier_URIFilter_DisableExternalResources());
|
||||
$this->registerFilter(new HTMLPurifier_URIFilter_HostBlacklist());
|
||||
$this->registerFilter(new HTMLPurifier_URIFilter_MakeAbsolute());
|
||||
$this->registerFilter(new HTMLPurifier_URIFilter_Munge());
|
||||
}
|
||||
|
||||
public function registerFilter($filter) {
|
||||
@@ -34,8 +36,13 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
|
||||
}
|
||||
|
||||
public function addFilter($filter, $config) {
|
||||
$filter->prepare($config);
|
||||
$this->filters[$filter->name] = $filter;
|
||||
$r = $filter->prepare($config);
|
||||
if ($r === false) return; // null is ok, for backwards compat
|
||||
if ($filter->post) {
|
||||
$this->postFilters[$filter->name] = $filter;
|
||||
} else {
|
||||
$this->filters[$filter->name] = $filter;
|
||||
}
|
||||
}
|
||||
|
||||
protected function doSetup($config) {
|
||||
@@ -66,8 +73,16 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
|
||||
}
|
||||
|
||||
public function filter(&$uri, $config, $context) {
|
||||
foreach ($this->filters as $name => $x) {
|
||||
$result = $this->filters[$name]->filter($uri, $config, $context);
|
||||
foreach ($this->filters as $name => $f) {
|
||||
$result = $f->filter($uri, $config, $context);
|
||||
if (!$result) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function postFilter(&$uri, $config, $context) {
|
||||
foreach ($this->postFilters as $name => $f) {
|
||||
$result = $f->filter($uri, $config, $context);
|
||||
if (!$result) return false;
|
||||
}
|
||||
return true;
|
||||
|
@@ -19,10 +19,15 @@ abstract class HTMLPurifier_URIFilter
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* True if this filter should be run after scheme validation.
|
||||
*/
|
||||
public $post = false;
|
||||
|
||||
/**
|
||||
* Performs initialization for the filter
|
||||
*/
|
||||
public function prepare($config) {}
|
||||
public function prepare($config) {return true;}
|
||||
|
||||
/**
|
||||
* Filter a URI object
|
||||
|
@@ -6,6 +6,7 @@ class HTMLPurifier_URIFilter_HostBlacklist extends HTMLPurifier_URIFilter
|
||||
protected $blacklist = array();
|
||||
public function prepare($config) {
|
||||
$this->blacklist = $config->get('URI', 'HostBlacklist');
|
||||
return true;
|
||||
}
|
||||
public function filter(&$uri, $config, $context) {
|
||||
foreach($this->blacklist as $blacklisted_host_fragment) {
|
||||
|
@@ -11,14 +11,15 @@ class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
|
||||
$def = $config->getDefinition('URI');
|
||||
$this->base = $def->base;
|
||||
if (is_null($this->base)) {
|
||||
trigger_error('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration', E_USER_ERROR);
|
||||
return;
|
||||
trigger_error('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration', E_USER_WARNING);
|
||||
return false;
|
||||
}
|
||||
$this->base->fragment = null; // fragment is invalid for base URI
|
||||
$stack = explode('/', $this->base->path);
|
||||
array_pop($stack); // discard last segment
|
||||
$stack = $this->_collapseStack($stack); // do pre-parsing
|
||||
$this->basePathStack = $stack;
|
||||
return true;
|
||||
}
|
||||
public function filter(&$uri, $config, $context) {
|
||||
if (is_null($this->base)) return true; // abort early
|
||||
|
48
library/HTMLPurifier/URIFilter/Munge.php
Normal file
48
library/HTMLPurifier/URIFilter/Munge.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter
|
||||
{
|
||||
public $name = 'Munge';
|
||||
public $post = true;
|
||||
private $target, $parser, $doEmbed, $secretKey;
|
||||
|
||||
protected $replace = array();
|
||||
|
||||
public function prepare($config) {
|
||||
$this->target = $config->get('URI', $this->name);
|
||||
$this->parser = new HTMLPurifier_URIParser();
|
||||
$this->doEmbed = $config->get('URI', 'MungeResources');
|
||||
$this->secretKey = $config->get('URI', 'MungeSecretKey');
|
||||
return true;
|
||||
}
|
||||
public function filter(&$uri, $config, $context) {
|
||||
if ($context->get('EmbeddedURI', true) && !$this->doEmbed) return true;
|
||||
|
||||
$scheme_obj = $uri->getSchemeObj($config, $context);
|
||||
if (!$scheme_obj) return true; // ignore unknown schemes, maybe another postfilter did it
|
||||
if (is_null($uri->host) || empty($scheme_obj->browsable)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->makeReplace($uri, $config, $context);
|
||||
$this->replace = array_map('rawurlencode', $this->replace);
|
||||
|
||||
$new_uri = strtr($this->target, $this->replace);
|
||||
$uri = $this->parser->parse($new_uri); // overwrite
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function makeReplace($uri, $config, $context) {
|
||||
$string = $uri->toString();
|
||||
// always available
|
||||
$this->replace['%s'] = $string;
|
||||
$this->replace['%r'] = $context->get('EmbeddedURI', true);
|
||||
$token = $context->get('CurrentToken', true);
|
||||
$this->replace['%n'] = $token ? $token->name : null;
|
||||
$this->replace['%m'] = $context->get('CurrentAttr', true);
|
||||
$this->replace['%p'] = $context->get('CurrentCSSProperty', true);
|
||||
// not always available
|
||||
if ($this->secretKey) $this->replace['%t'] = sha1($this->secretKey . ':' . $string);
|
||||
}
|
||||
|
||||
}
|
240
library/HTMLPurifier/UnitConverter.php
Normal file
240
library/HTMLPurifier/UnitConverter.php
Normal file
@@ -0,0 +1,240 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Class for converting between different unit-lengths as specified by
|
||||
* CSS.
|
||||
*/
|
||||
class HTMLPurifier_UnitConverter
|
||||
{
|
||||
|
||||
const ENGLISH = 1;
|
||||
const METRIC = 2;
|
||||
const DIGITAL = 3;
|
||||
|
||||
/**
|
||||
* 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.)
|
||||
*/
|
||||
protected static $units = array(
|
||||
self::ENGLISH => array(
|
||||
'px' => 3, // This is as per CSS 2.1 and Firefox. Your mileage may vary
|
||||
'pt' => 4,
|
||||
'pc' => 48,
|
||||
'in' => 288,
|
||||
self::METRIC => array('pt', '0.352777778', 'mm'),
|
||||
),
|
||||
self::METRIC => array(
|
||||
'mm' => 1,
|
||||
'cm' => 10,
|
||||
self::ENGLISH => array('mm', '2.83464567', 'pt'),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Minimum bcmath precision for output.
|
||||
*/
|
||||
protected $outputPrecision;
|
||||
|
||||
/**
|
||||
* Bcmath precision for internal calculations.
|
||||
*/
|
||||
protected $internalPrecision;
|
||||
|
||||
/**
|
||||
* Whether or not BCMath is available
|
||||
*/
|
||||
private $bcmath;
|
||||
|
||||
public function __construct($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.
|
||||
*/
|
||||
public function convert($length, $to_unit) {
|
||||
|
||||
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 (self::$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;
|
||||
|
||||
// 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 = self::$units[$state][$dest_state][0];
|
||||
}
|
||||
|
||||
// Do the conversion if necessary
|
||||
if ($dest_unit !== $unit) {
|
||||
$factor = $this->div(self::$units[$state][$unit], self::$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, self::$units[$state][$dest_state][1], $cp);
|
||||
$unit = self::$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
|
||||
*/
|
||||
public 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.
|
||||
*/
|
||||
private 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.
|
||||
*/
|
||||
private 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.
|
||||
*/
|
||||
private 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.
|
||||
*/
|
||||
private 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.
|
||||
*/
|
||||
private function scale($r, $scale) {
|
||||
return sprintf('%.' . $scale . 'f', (float) $r);
|
||||
}
|
||||
|
||||
}
|
@@ -7,21 +7,34 @@
|
||||
class HTMLPurifier_VarParser
|
||||
{
|
||||
|
||||
const STRING = 1;
|
||||
const ISTRING = 2;
|
||||
const TEXT = 3;
|
||||
const ITEXT = 4;
|
||||
const INT = 5;
|
||||
const FLOAT = 6;
|
||||
const BOOL = 7;
|
||||
const LOOKUP = 8;
|
||||
const ALIST = 9;
|
||||
const HASH = 10;
|
||||
const MIXED = 11;
|
||||
|
||||
/**
|
||||
* Lookup table of allowed types.
|
||||
* Lookup table of allowed types. Mainly for backwards compatibility, but
|
||||
* also convenient for transforming string type names to the integer constants.
|
||||
*/
|
||||
static public $types = array(
|
||||
'string' => true,
|
||||
'istring' => true,
|
||||
'text' => true,
|
||||
'itext' => true,
|
||||
'int' => true,
|
||||
'float' => true,
|
||||
'bool' => true,
|
||||
'lookup' => true,
|
||||
'list' => true,
|
||||
'hash' => true,
|
||||
'mixed' => true
|
||||
'string' => self::STRING,
|
||||
'istring' => self::ISTRING,
|
||||
'text' => self::TEXT,
|
||||
'itext' => self::ITEXT,
|
||||
'int' => self::INT,
|
||||
'float' => self::FLOAT,
|
||||
'bool' => self::BOOL,
|
||||
'lookup' => self::LOOKUP,
|
||||
'list' => self::ALIST,
|
||||
'hash' => self::HASH,
|
||||
'mixed' => self::MIXED
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -29,10 +42,10 @@ class HTMLPurifier_VarParser
|
||||
* allowed value lists.
|
||||
*/
|
||||
static public $stringTypes = array(
|
||||
'string' => true,
|
||||
'istring' => true,
|
||||
'text' => true,
|
||||
'itext' => true,
|
||||
self::STRING => true,
|
||||
self::ISTRING => true,
|
||||
self::TEXT => true,
|
||||
self::ITEXT => true,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -46,42 +59,46 @@ class HTMLPurifier_VarParser
|
||||
* @return Validated and type-coerced variable
|
||||
*/
|
||||
final public function parse($var, $type, $allow_null = false) {
|
||||
if (!isset(HTMLPurifier_VarParser::$types[$type])) {
|
||||
throw new HTMLPurifier_VarParserException("Invalid type '$type'");
|
||||
if (is_string($type)) {
|
||||
if (!isset(HTMLPurifier_VarParser::$types[$type])) {
|
||||
throw new HTMLPurifier_VarParserException("Invalid type '$type'");
|
||||
} else {
|
||||
$type = HTMLPurifier_VarParser::$types[$type];
|
||||
}
|
||||
}
|
||||
$var = $this->parseImplementation($var, $type, $allow_null);
|
||||
if ($allow_null && $var === null) return null;
|
||||
// These are basic checks, to make sure nothing horribly wrong
|
||||
// happened in our implementations.
|
||||
switch ($type) {
|
||||
case 'string':
|
||||
case 'istring':
|
||||
case 'text':
|
||||
case 'itext':
|
||||
case (self::STRING):
|
||||
case (self::ISTRING):
|
||||
case (self::TEXT):
|
||||
case (self::ITEXT):
|
||||
if (!is_string($var)) break;
|
||||
if ($type[0] == 'i') $var = strtolower($var);
|
||||
if ($type == self::ISTRING || $type == self::ITEXT) $var = strtolower($var);
|
||||
return $var;
|
||||
case 'int':
|
||||
case (self::INT):
|
||||
if (!is_int($var)) break;
|
||||
return $var;
|
||||
case 'float':
|
||||
case (self::FLOAT):
|
||||
if (!is_float($var)) break;
|
||||
return $var;
|
||||
case 'bool':
|
||||
case (self::BOOL):
|
||||
if (!is_bool($var)) break;
|
||||
return $var;
|
||||
case 'lookup':
|
||||
case 'list':
|
||||
case 'hash':
|
||||
case (self::LOOKUP):
|
||||
case (self::ALIST):
|
||||
case (self::HASH):
|
||||
if (!is_array($var)) break;
|
||||
if ($type === 'lookup') {
|
||||
if ($type === self::LOOKUP) {
|
||||
foreach ($var as $k) if ($k !== true) $this->error('Lookup table contains value other than true');
|
||||
} elseif ($type === 'list') {
|
||||
} elseif ($type === self::ALIST) {
|
||||
$keys = array_keys($var);
|
||||
if (array_keys($keys) !== $keys) $this->error('Indices for list are not uniform');
|
||||
}
|
||||
return $var;
|
||||
case 'mixed':
|
||||
case (self::MIXED):
|
||||
return $var;
|
||||
default:
|
||||
$this->errorInconsistent(get_class($this), $type);
|
||||
@@ -111,7 +128,7 @@ class HTMLPurifier_VarParser
|
||||
* updating subclasses.
|
||||
*/
|
||||
protected function errorInconsistent($class, $type) {
|
||||
throw new HTMLPurifier_Exception("Inconsistency in $class: $type not implemented");
|
||||
throw new HTMLPurifier_Exception("Inconsistency in $class: ".HTMLPurifier_VarParser::getTypeName($type)." not implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +136,17 @@ class HTMLPurifier_VarParser
|
||||
*/
|
||||
protected function errorGeneric($var, $type) {
|
||||
$vtype = gettype($var);
|
||||
$this->error("Expected type $type, got $vtype");
|
||||
$this->error("Expected type ".HTMLPurifier_VarParser::getTypeName($type).", got $vtype");
|
||||
}
|
||||
|
||||
static public function getTypeName($type) {
|
||||
static $lookup;
|
||||
if (!$lookup) {
|
||||
// Lazy load the alternative lookup table
|
||||
$lookup = array_flip(HTMLPurifier_VarParser::$types);
|
||||
}
|
||||
if (!isset($lookup[$type])) return 'unknown';
|
||||
return $lookup[$type];
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -14,19 +14,19 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
|
||||
// Note: if code "breaks" from the switch, it triggers a generic
|
||||
// exception to be thrown. Specific errors can be specifically
|
||||
// done here.
|
||||
case 'mixed':
|
||||
case 'istring':
|
||||
case 'string':
|
||||
case 'text':
|
||||
case 'itext':
|
||||
case self::MIXED :
|
||||
case self::ISTRING :
|
||||
case self::STRING :
|
||||
case self::TEXT :
|
||||
case self::ITEXT :
|
||||
return $var;
|
||||
case 'int':
|
||||
case self::INT :
|
||||
if (is_string($var) && ctype_digit($var)) $var = (int) $var;
|
||||
return $var;
|
||||
case 'float':
|
||||
case self::FLOAT :
|
||||
if ((is_string($var) && is_numeric($var)) || is_int($var)) $var = (float) $var;
|
||||
return $var;
|
||||
case 'bool':
|
||||
case self::BOOL :
|
||||
if (is_int($var) && ($var === 0 || $var === 1)) {
|
||||
$var = (bool) $var;
|
||||
} elseif (is_string($var)) {
|
||||
@@ -39,9 +39,9 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
|
||||
}
|
||||
}
|
||||
return $var;
|
||||
case 'list':
|
||||
case 'hash':
|
||||
case 'lookup':
|
||||
case self::ALIST :
|
||||
case self::HASH :
|
||||
case self::LOOKUP :
|
||||
if (is_string($var)) {
|
||||
// special case: technically, this is an array with
|
||||
// a single empty string item, but having an empty
|
||||
@@ -56,7 +56,7 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
|
||||
}
|
||||
// remove spaces
|
||||
foreach ($var as $i => $j) $var[$i] = trim($j);
|
||||
if ($type === 'hash') {
|
||||
if ($type === self::HASH) {
|
||||
// key:value,key2:value2
|
||||
$nvar = array();
|
||||
foreach ($var as $keypair) {
|
||||
@@ -70,8 +70,8 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
|
||||
if (!is_array($var)) break;
|
||||
$keys = array_keys($var);
|
||||
if ($keys === array_keys($keys)) {
|
||||
if ($type == 'list') return $var;
|
||||
elseif ($type == 'lookup') {
|
||||
if ($type == self::ALIST) return $var;
|
||||
elseif ($type == self::LOOKUP) {
|
||||
$new = array();
|
||||
foreach ($var as $key) {
|
||||
$new[$key] = true;
|
||||
@@ -79,7 +79,7 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
|
||||
return $new;
|
||||
} else break;
|
||||
}
|
||||
if ($type === 'lookup') {
|
||||
if ($type === self::LOOKUP) {
|
||||
foreach ($var as $key => $value) {
|
||||
$var[$key] = true;
|
||||
}
|
||||
|
@@ -35,9 +35,7 @@ $e = &$modx->Event;
|
||||
if ($e->name == 'OnBeforeDocFormSave') {
|
||||
global $content;
|
||||
|
||||
set_include_path('../assets/plugins/htmlpurifier/library/'
|
||||
. PATH_SEPARATOR . get_include_path());
|
||||
include_once 'HTMLPurifier.php';
|
||||
include_once '../assets/plugins/htmlpurifier/library/HTMLPurifier.auto.php';
|
||||
$purifier = new HTMLPurifier();
|
||||
|
||||
static $magic_quotes = null;
|
||||
@@ -89,3 +87,24 @@ HTML Purifier properly like this:
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('Core', 'Encoding', 'ISO-8859-1'); // or whatever encoding
|
||||
$purifier = new HTMLPurifier($config);
|
||||
|
||||
|
||||
|
||||
5. Known Bugs
|
||||
|
||||
'rn' characters sometimes mysteriously appear after purification. We are
|
||||
currently investigating this issue. See: <http://htmlpurifier.org/phorum/read.php?3,1866>
|
||||
|
||||
|
||||
|
||||
6. See Also
|
||||
|
||||
A modified version of Jot 1.1.3 is available, which integrates with HTML
|
||||
Purifier. You can check it out here: <http://modxcms.com/forums/index.php/topic,25621.msg161970.html>
|
||||
|
||||
|
||||
X. Changelog
|
||||
|
||||
2008-06-16
|
||||
- Updated code to work with 3.1.0 and later
|
||||
- Add Known Bugs and See Also section
|
||||
|
@@ -58,11 +58,10 @@ style="float:right;">
|
||||
|
||||
$schema_builder = new HTMLPurifier_ConfigSchema_Builder_ConfigSchema();
|
||||
$schema = $schema_builder->build($interchange);
|
||||
HTMLPurifier_ConfigSchema::instance($schema);
|
||||
|
||||
$config = HTMLPurifier_Config::loadArrayFromForm($_GET, 'config');
|
||||
$config = HTMLPurifier_Config::loadArrayFromForm($_GET, 'config', true, true, $schema);
|
||||
$printer = new HTMLPurifier_Printer_ConfigForm('config', '?doc#%s');
|
||||
echo $printer->render($config);
|
||||
echo $printer->render(array(HTMLPurifier_Config::createDefault(), $config));
|
||||
|
||||
?>
|
||||
</form>
|
||||
|
@@ -13,8 +13,11 @@ if (file_exists('printDefinition.settings.php')) {
|
||||
include 'printDefinition.settings.php';
|
||||
}
|
||||
|
||||
$gen_config = HTMLPurifier_Config::createDefault();
|
||||
$printer_html_definition = new HTMLPurifier_Printer_HTMLDefinition();
|
||||
$printer_html_definition->prepareGenerator($gen_config);
|
||||
$printer_css_definition = new HTMLPurifier_Printer_CSSDefinition();
|
||||
$printer_css_definition->prepareGenerator($gen_config);
|
||||
|
||||
$printer_config_form = new HTMLPurifier_Printer_ConfigForm(
|
||||
'config',
|
||||
|
@@ -17,7 +17,21 @@ 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");
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -28,12 +28,20 @@ class HTMLPurifier_AttrDef_CSS_LengthTest extends HTMLPurifier_AttrDefHarness
|
||||
|
||||
function testNonNegative() {
|
||||
|
||||
$this->def = new HTMLPurifier_AttrDef_CSS_Length(true);
|
||||
$this->def = new HTMLPurifier_AttrDef_CSS_Length('0');
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -7,6 +7,9 @@ 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');
|
||||
|
@@ -26,7 +26,6 @@ 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\))");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -33,5 +33,12 @@ 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');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
32
tests/HTMLPurifier/AttrDef/SwitchTest.php
Normal file
32
tests/HTMLPurifier/AttrDef/SwitchTest.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
class HTMLPurifier_AttrDef_SwitchTest extends HTMLPurifier_AttrDefHarness
|
||||
{
|
||||
|
||||
protected $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');
|
||||
}
|
||||
|
||||
}
|
@@ -8,7 +8,7 @@ class HTMLPurifier_AttrDef_TextTest extends HTMLPurifier_AttrDefHarness
|
||||
$this->def = new HTMLPurifier_AttrDef_Text();
|
||||
|
||||
$this->assertDef('This is spiffy text!');
|
||||
$this->assertDef(" Casual\tCDATA parse\ncheck. ", 'Casual CDATA parsecheck.');
|
||||
$this->assertDef(" Casual\tCDATA parse\ncheck. ", 'Casual CDATA parse check.');
|
||||
|
||||
}
|
||||
|
||||
|
@@ -83,6 +83,8 @@ class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
|
||||
$uri_def = new HTMLPurifier_URIDefinitionMock();
|
||||
$uri_def->expectOnce('filter', array($uri, '*', '*'));
|
||||
$uri_def->setReturnValue('filter', true, array($uri, '*', '*'));
|
||||
$uri_def->expectOnce('postFilter', array($uri, '*', '*'));
|
||||
$uri_def->setReturnValue('postFilter', true, array($uri, '*', '*'));
|
||||
$uri_def->setup = true;
|
||||
|
||||
// Since definitions are no longer passed by reference, we need
|
||||
@@ -105,6 +107,17 @@ class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
|
||||
HTMLPurifier_DefinitionCacheFactory::instance($old);
|
||||
}
|
||||
|
||||
function test_make() {
|
||||
$factory = new HTMLPurifier_AttrDef_URI();
|
||||
$def = $factory->make('');
|
||||
$def2 = new HTMLPurifier_AttrDef_URI();
|
||||
$this->assertIdentical($def, $def2);
|
||||
|
||||
$def = $factory->make('embedded');
|
||||
$def2 = new HTMLPurifier_AttrDef_URI(true);
|
||||
$this->assertIdentical($def, $def2);
|
||||
}
|
||||
|
||||
/*
|
||||
function test_validate_configWhitelist() {
|
||||
|
||||
|
@@ -15,8 +15,7 @@ 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('ignorelinefeeds', $def->parseCDATA("ignore\nline\nfeeds"));
|
||||
$this->assertIdentical('translate to space', $def->parseCDATA("translate\rto\tspace"));
|
||||
$this->assertIdentical('translate to space', $def->parseCDATA("translate\nto\tspace"));
|
||||
|
||||
}
|
||||
|
||||
|
@@ -21,16 +21,12 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
|
||||
$this->schema->add('Car', 'Seats', 5, 'int', false);
|
||||
|
||||
$this->assertIdentical($this->schema->defaults['Car']['Seats'], 5);
|
||||
$this->assertIdentical($this->schema->info['Car']['Seats'],
|
||||
new HTMLPurifier_ConfigDef_Directive('int')
|
||||
);
|
||||
$this->assertIdentical($this->schema->info['Car']['Seats']->type, HTMLPurifier_VarParser::INT);
|
||||
|
||||
$this->schema->add('Car', 'Age', null, 'int', true);
|
||||
|
||||
$this->assertIdentical($this->schema->defaults['Car']['Age'], null);
|
||||
$this->assertIdentical($this->schema->info['Car']['Age'],
|
||||
new HTMLPurifier_ConfigDef_Directive('int', true)
|
||||
);
|
||||
$this->assertIdentical($this->schema->info['Car']['Age']->type, HTMLPurifier_VarParser::INT);
|
||||
|
||||
}
|
||||
|
||||
@@ -45,15 +41,13 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
|
||||
);
|
||||
|
||||
$this->assertIdentical($this->schema->defaults['QuantumNumber']['Difficulty'], null);
|
||||
$this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty'],
|
||||
new HTMLPurifier_ConfigDef_Directive(
|
||||
'string',
|
||||
true,
|
||||
array(
|
||||
'easy' => true,
|
||||
'medium' => true,
|
||||
'hard' => true
|
||||
)
|
||||
$this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty']->type, HTMLPurifier_VarParser::STRING);
|
||||
$this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty']->allow_null, true);
|
||||
$this->assertIdentical($this->schema->info['QuantumNumber']['Difficulty']->allowed,
|
||||
array(
|
||||
'easy' => true,
|
||||
'medium' => true,
|
||||
'hard' => true
|
||||
)
|
||||
);
|
||||
|
||||
@@ -82,20 +76,19 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
|
||||
);
|
||||
|
||||
$this->assertIdentical($this->schema->defaults['Abbrev']['HTH'], 'Happy to Help');
|
||||
$this->assertIdentical($this->schema->info['Abbrev']['HTH'],
|
||||
new HTMLPurifier_ConfigDef_Directive(
|
||||
'string',
|
||||
false,
|
||||
array(
|
||||
'Happy to Help' => true,
|
||||
'Hope that Helps' => true,
|
||||
'HAIL THE HAND!' => true
|
||||
),
|
||||
array(
|
||||
'happy' => 'Happy to Help',
|
||||
'hope' => 'Hope that Helps',
|
||||
'hail' => 'HAIL THE HAND!'
|
||||
)
|
||||
$this->assertIdentical($this->schema->info['Abbrev']['HTH']->type, HTMLPurifier_VarParser::STRING);
|
||||
$this->assertIdentical($this->schema->info['Abbrev']['HTH']->allowed,
|
||||
array(
|
||||
'Happy to Help' => true,
|
||||
'Hope that Helps' => true,
|
||||
'HAIL THE HAND!' => true
|
||||
)
|
||||
);
|
||||
$this->assertIdentical($this->schema->info['Abbrev']['HTH']->aliases,
|
||||
array(
|
||||
'happy' => 'Happy to Help',
|
||||
'hope' => 'Hope that Helps',
|
||||
'hail' => 'HAIL THE HAND!'
|
||||
)
|
||||
);
|
||||
|
||||
@@ -107,9 +100,9 @@ class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
|
||||
$this->schema->addAlias('Home', 'Carpet', 'Home', 'Rug');
|
||||
|
||||
$this->assertTrue(!isset($this->schema->defaults['Home']['Carpet']));
|
||||
$this->assertIdentical($this->schema->info['Home']['Carpet'],
|
||||
new HTMLPurifier_ConfigDef_DirectiveAlias('Home', 'Rug')
|
||||
);
|
||||
$this->assertIdentical($this->schema->info['Home']['Carpet']->namespace, 'Home');
|
||||
$this->assertIdentical($this->schema->info['Home']['Carpet']->name, 'Rug');
|
||||
$this->assertIdentical($this->schema->info['Home']['Carpet']->isAlias, true);
|
||||
|
||||
}
|
||||
|
||||
|
@@ -7,6 +7,7 @@ class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
|
||||
|
||||
function setUp() {
|
||||
$this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
function assertCleanUTF8($string, $expect = null) {
|
||||
@@ -24,95 +25,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() {
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$context = new HTMLPurifier_Context();
|
||||
|
||||
function test_convertToUTF8_noConvert() {
|
||||
// UTF-8 means that we don't touch it
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertToUTF8("\xF6", $config, $context),
|
||||
HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
|
||||
"\xF6", // this is invalid
|
||||
'Expected identical [Binary: F6]'
|
||||
);
|
||||
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'Core.Encoding' => 'ISO-8859-1'
|
||||
));
|
||||
|
||||
// Now it gets converted
|
||||
}
|
||||
|
||||
function test_convertToUTF8_iso8859_1() {
|
||||
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertToUTF8("\xF6", $config, $context),
|
||||
HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
|
||||
"\xC3\xB6"
|
||||
);
|
||||
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'Core.Encoding' => 'ISO-8859-1',
|
||||
'Test.ForceNoIconv' => true
|
||||
));
|
||||
}
|
||||
|
||||
function test_convertToUTF8_withoutIconv() {
|
||||
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
|
||||
$this->config->set('Test', 'ForceNoIconv', true);
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertToUTF8("\xF6", $config, $context),
|
||||
HTMLPurifier_Encoder::convertToUTF8("\xF6", $this->config, $this->context),
|
||||
"\xC3\xB6"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function test_convertFromUTF8() {
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$context = new HTMLPurifier_Context();
|
||||
|
||||
// zhong-wen
|
||||
$chinese = "\xE4\xB8\xAD\xE6\x96\x87 (Chinese)";
|
||||
|
||||
function getZhongWen() {
|
||||
return "\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", $config, $context),
|
||||
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
|
||||
"\xC3\xB6"
|
||||
);
|
||||
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'Core.Encoding' => 'ISO-8859-1'
|
||||
));
|
||||
|
||||
// Now it gets converted
|
||||
}
|
||||
|
||||
function test_convertFromUTF8_iso8859_1() {
|
||||
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $config, $context),
|
||||
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
|
||||
"\xF6",
|
||||
'Expected identical [Binary: F6]'
|
||||
);
|
||||
|
||||
if (function_exists('iconv')) {
|
||||
// iconv has it's own way
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertFromUTF8($chinese, $config, $context),
|
||||
" (Chinese)"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function test_convertFromUTF8_iconvNoChars() {
|
||||
if (!function_exists('iconv')) return;
|
||||
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
|
||||
" (Chinese)"
|
||||
);
|
||||
}
|
||||
|
||||
function test_convertFromUTF8_phpNormal() {
|
||||
// Plain PHP implementation has slightly different behavior
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'Core.Encoding' => 'ISO-8859-1',
|
||||
'Test.ForceNoIconv' => true
|
||||
));
|
||||
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
|
||||
$this->config->set('Test', 'ForceNoIconv', true);
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $config, $context),
|
||||
HTMLPurifier_Encoder::convertFromUTF8("\xC3\xB6", $this->config, $this->context),
|
||||
"\xF6",
|
||||
'Expected identical [Binary: F6]'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function test_convertFromUTF8_phpNoChars() {
|
||||
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
|
||||
$this->config->set('Test', 'ForceNoIconv', true);
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertFromUTF8($chinese, $config, $context),
|
||||
HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
|
||||
"?? (Chinese)"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function test_convertFromUTF8_withProtection() {
|
||||
// Preserve the characters!
|
||||
$config = HTMLPurifier_Config::create(array(
|
||||
'Core.Encoding' => 'ISO-8859-1',
|
||||
'Core.EscapeNonASCIICharacters' => true
|
||||
));
|
||||
$this->config->set('Core', 'Encoding', 'ISO-8859-1');
|
||||
$this->config->set('Core', 'EscapeNonASCIICharacters', true);
|
||||
$this->assertIdentical(
|
||||
HTMLPurifier_Encoder::convertFromUTF8($chinese, $config, $context),
|
||||
HTMLPurifier_Encoder::convertFromUTF8($this->getZhongWen(), $this->config, $this->context),
|
||||
"中文 (Chinese)"
|
||||
);
|
||||
|
||||
@@ -139,5 +138,39 @@ 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),
|
||||
'\\~'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@ class HTMLPurifier_ErrorCollectorTest extends HTMLPurifier_Harness
|
||||
public function setup() {
|
||||
generate_mock_once('HTMLPurifier_Language');
|
||||
generate_mock_once('HTMLPurifier_Generator');
|
||||
parent::setup();
|
||||
}
|
||||
|
||||
function test() {
|
||||
@@ -20,14 +21,13 @@ class HTMLPurifier_ErrorCollectorTest extends HTMLPurifier_Harness
|
||||
|
||||
$line = false;
|
||||
|
||||
$context = new HTMLPurifier_Context();
|
||||
$context->register('Locale', $language);
|
||||
$context->register('CurrentLine', $line);
|
||||
$this->context->register('Locale', $language);
|
||||
$this->context->register('CurrentLine', $line);
|
||||
|
||||
$generator = new HTMLPurifier_Generator();
|
||||
$context->register('Generator', $generator);
|
||||
$generator = new HTMLPurifier_Generator($this->config, $this->context);
|
||||
$this->context->register('Generator', $generator);
|
||||
|
||||
$collector = new HTMLPurifier_ErrorCollector($context);
|
||||
$collector = new HTMLPurifier_ErrorCollector($this->context);
|
||||
|
||||
$line = 23;
|
||||
$collector->send(E_ERROR, 'message-1');
|
||||
@@ -48,23 +48,21 @@ class HTMLPurifier_ErrorCollectorTest extends HTMLPurifier_Harness
|
||||
|
||||
$config = HTMLPurifier_Config::create(array('Core.MaintainLineNumbers' => true));
|
||||
|
||||
$this->assertIdentical($collector->getHTMLFormatted($config), $formatted_result);
|
||||
$this->assertIdentical($collector->getHTMLFormatted($this->config), $formatted_result);
|
||||
|
||||
}
|
||||
|
||||
function testNoErrors() {
|
||||
$language = new HTMLPurifier_LanguageMock();
|
||||
$language->setReturnValue('getMessage', 'No errors', array('ErrorCollector: No errors'));
|
||||
$context = new HTMLPurifier_Context();
|
||||
$context->register('Locale', $language);
|
||||
$this->context->register('Locale', $language);
|
||||
|
||||
$generator = new HTMLPurifier_Generator();
|
||||
$context->register('Generator', $generator);
|
||||
$generator = new HTMLPurifier_Generator($this->config, $this->context);
|
||||
$this->context->register('Generator', $generator);
|
||||
|
||||
$collector = new HTMLPurifier_ErrorCollector($context);
|
||||
$collector = new HTMLPurifier_ErrorCollector($this->context);
|
||||
$formatted_result = '<p>No errors</p>';
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$this->assertIdentical($collector->getHTMLFormatted($config), $formatted_result);
|
||||
$this->assertIdentical($collector->getHTMLFormatted($this->config), $formatted_result);
|
||||
}
|
||||
|
||||
function testNoLineNumbers() {
|
||||
@@ -72,13 +70,12 @@ class HTMLPurifier_ErrorCollectorTest extends HTMLPurifier_Harness
|
||||
$language->setReturnValue('getMessage', 'Message 1', array('message-1'));
|
||||
$language->setReturnValue('getMessage', 'Message 2', array('message-2'));
|
||||
$language->setReturnValue('getErrorName', 'Error', array(E_ERROR));
|
||||
$context = new HTMLPurifier_Context();
|
||||
$context->register('Locale', $language);
|
||||
$this->context->register('Locale', $language);
|
||||
|
||||
$generator = new HTMLPurifier_Generator();
|
||||
$context->register('Generator', $generator);
|
||||
$generator = new HTMLPurifier_Generator($this->config, $this->context);
|
||||
$this->context->register('Generator', $generator);
|
||||
|
||||
$collector = new HTMLPurifier_ErrorCollector($context);
|
||||
$collector = new HTMLPurifier_ErrorCollector($this->context);
|
||||
$collector->send(E_ERROR, 'message-1');
|
||||
$collector->send(E_ERROR, 'message-2');
|
||||
|
||||
@@ -91,23 +88,21 @@ class HTMLPurifier_ErrorCollectorTest extends HTMLPurifier_Harness
|
||||
$formatted_result =
|
||||
'<ul><li><strong>Error</strong>: Message 1</li>'.
|
||||
'<li><strong>Error</strong>: Message 2</li></ul>';
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$this->assertIdentical($collector->getHTMLFormatted($config), $formatted_result);
|
||||
$this->assertIdentical($collector->getHTMLFormatted($this->config), $formatted_result);
|
||||
}
|
||||
|
||||
function testContextSubstitutions() {
|
||||
|
||||
$language = new HTMLPurifier_LanguageMock();
|
||||
$context = new HTMLPurifier_Context();
|
||||
$context->register('Locale', $language);
|
||||
$this->context->register('Locale', $language);
|
||||
|
||||
$generator = new HTMLPurifier_Generator();
|
||||
$context->register('Generator', $generator);
|
||||
$generator = new HTMLPurifier_Generator($this->config, $this->context);
|
||||
$this->context->register('Generator', $generator);
|
||||
|
||||
$current_token = false;
|
||||
$context->register('CurrentToken', $current_token);
|
||||
$this->context->register('CurrentToken', $current_token);
|
||||
|
||||
$collector = new HTMLPurifier_ErrorCollector($context);
|
||||
$collector = new HTMLPurifier_ErrorCollector($this->context);
|
||||
|
||||
// 0
|
||||
$current_token = new HTMLPurifier_Token_Start('a', array('href' => 'http://example.com'), 32);
|
||||
@@ -123,7 +118,7 @@ class HTMLPurifier_ErrorCollectorTest extends HTMLPurifier_Harness
|
||||
$collector->send(E_NOTICE, 'message-attr'); // test when context isn't available
|
||||
|
||||
// 2
|
||||
$context->register('CurrentAttr', $current_attr);
|
||||
$this->context->register('CurrentAttr', $current_attr);
|
||||
$collector->send(E_NOTICE, 'message-attr');
|
||||
|
||||
$result = array(
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user