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

Compare commits

..

1 Commits

Author SHA1 Message Date
Edward Z. Yang
6bab867afb Tag 1.5.0-strict.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/tags/1.5.0-strict@872 48356398-32a2-884e-a903-53898d9a118a
2007-03-24 01:30:10 +00:00
99 changed files with 742 additions and 2817 deletions

View File

@@ -4,7 +4,7 @@
# Project related configuration options # Project related configuration options
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
PROJECT_NAME = HTML Purifier PROJECT_NAME = HTML Purifier
PROJECT_NUMBER = 1.6.1 PROJECT_NUMBER = 1.5.0
OUTPUT_DIRECTORY = "C:/Documents and Settings/Edward/My Documents/My Webs/htmlpurifier/docs/doxygen" OUTPUT_DIRECTORY = "C:/Documents and Settings/Edward/My Documents/My Webs/htmlpurifier/docs/doxygen"
CREATE_SUBDIRS = NO CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English OUTPUT_LANGUAGE = English

View File

@@ -47,9 +47,7 @@ HTML Purifier is all about web-standards, so accordingly your webpages should
be standards compliant. HTML Purifier can deal with these doctypes: be standards compliant. HTML Purifier can deal with these doctypes:
* XHTML 1.0 Transitional (default) * XHTML 1.0 Transitional (default)
* XHTML 1.0 Strict
* HTML 4.01 Transitional * HTML 4.01 Transitional
* HTML 4.01 Strict
...and these character encodings: ...and these character encodings:
@@ -89,7 +87,7 @@ into configuring things just for the heck of it, skip to 4.3).
* Am I using UTF-8? * Am I using UTF-8?
* Am I using XHTML 1.0 Transitional? * Am I using XHTML 1.0 Transitional?
If you answered no to any of these questions, instantiate a configuration If you answered yes to any of these questions, instantiate a configuration
object and read on: object and read on:
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
@@ -143,7 +141,7 @@ versions will also allow strict-compliant output.
4.3. Other settings 4.3. Other settings
There are more configuration directives which can be read about There are more configuration directives which can be read about
here: <http://htmlpurifier.org/live/configdoc/plain.html> They're a bit boring, here: <http://hp.jpsband.org/live/configdoc/plain.html> They're a bit boring,
but they can help out for those of you who like to exert maximum control over but they can help out for those of you who like to exert maximum control over
your code. your code.

View File

@@ -1,71 +0,0 @@

Installation
Comment installer HTML Purifier
Attention: Ce document a encode en UTF-8. Si les lettres avec les accents
est essoreuse, prenez un mieux editeur de texte.
À L'Aide: Je ne suis pas un diseur natif de français. Si vous trouvez une
erreur dans ce document, racontez-moi! Merci.
L'installation de HTML Purifier est trés simple, parce qu'il ne doit pas
la configuration. Dans le pied de de document, les utilisateurs
impatient peuvent trouver le code, mais je recommande que vous lisez
ce document pour quelques choses.
1. Compatibilité
HTML Purifier fonctionne dans PHP 4 et PHP 5. PHP 4.3.9 est le dernier
version que je le testais. Il ne dépend de les autre librairies.
Les extensions optionnel est iconv (en général déjà installer) et
tidy (répandu aussi). Si vous utilisez UTF-8 et ne voulez pas
l'indentation, vous pouvez utiliser HTML Purifier sans ces extensions.
2. Inclure la librarie
Utilisez:
require_once '/path/to/library/HTMLPurifier.auto.php';
...quand vous devez utiliser HTML Purifier (ne inclure pas quand vous
ne devez pas, parce que HTML Purifier est trés grand.)
Si vous n'aime pas que HTML Purifier change vos include_path, on peut
change vos include_path, et:
require_once 'HTMLPurifier.php';
Seuleument les contents dans library/ est essentiel; vous peut enlever
les autre fichiers quand vous est dans une atmosphère professionnel.
[En cours de construction]
6. Installation vite
Si votre site web est en UTF-8 et XHTML Transitional, utilisez:
<?php
require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
$purificateur = new HTMLPurifier();
$html_propre = $purificateur->purify($html_salle);
?>
Sinon, utilisez:
<?php
require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('Core', 'Encoding', 'ISO-8859-1'); //remplacez avec votre encoding
$config->set('Core', 'XHTML', true); //remplacez avec false si HTML 4.01
$purificateur = new HTMLPurifier($config);
$html_propre = $purificateur->purify($html_salle);
?>

56
NEWS
View File

@@ -9,62 +9,6 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Internal change . Internal change
========================== ==========================
1.7.0, unknown release date
1.6.1, released 2007-05-05
! Support for more deprecated attributes via transformations:
+ hspace and vspace in img
+ size and noshade in hr
+ nowrap in td
+ clear in br
+ align in caption, table, img and hr
+ type in ul, ol and li
! DirectLex now preserves text in which a < bracket is followed by
a non-alphanumeric character. This means that certain emoticons
are now preserved.
! %Core.RemoveInvalidImg is now operational, when set to false invalid
images will hang around with an empty src
! target attribute in a tag supported, use %Attr.AllowedFrameTargets
to enable
! CSS property white-space now allows nowrap (supported in all modern
browsers) but not others (which have spotty browser implementations)
! XHTML 1.1 mode now sort-of works without any fatal errors, and
lang is now moved over to xml:lang.
! Attribute transformation smoketest available at smoketests/attrTransform.php
! Transformation of font's size attribute now handles super-large numbers
- Possibly fatal bug with __autoload() fixed in module manager
- Invert HTMLModuleManager->addModule() processing order to check
prefixes first and then the literal module
- Empty strings get converted to empty arrays instead of arrays with
an empty string in them.
- Merging in attribute lists now works.
. Demo script removed: it has been added to the website's repository
. Basic.php script modified to work out of the box
. Refactor AttrTransform classes to reduce duplication
. AttrTransform_TextAlign axed in favor of a more general
AttrTransform_EnumToCSS, refer to HTMLModule/TransformToStrict.php to
see how the new equivalent is implemented
. Unit tests now use exclusively assertIdentical
1.6.0, released 2007-04-01
! Support for most common deprecated attributes via transformations:
+ bgcolor in td, th, tr and table
+ border in img
+ name in a and img
+ width in td, th and hr
+ height in td, th
! Support for CSS attribute 'height' added
! Support for rel and rev attributes in a tags added, use %Attr.AllowedRel
and %Attr.AllowedRev to activate
- You can define ID blacklists using regular expressions via
%Attr.IDBlacklistRegexp
- Error messages are emitted when you attempt to "allow" elements or
attributes that HTML Purifier does not support
1.5.1, unknown release date
- Fix segfault in unit test. The problem is not very reproduceable and
I don't know what causes it, but a six line patch fixed it.
1.5.0, released 2007-03-23 1.5.0, released 2007-03-23
! Added a rudimentary I18N and L10N system modeled off MediaWiki. It ! Added a rudimentary I18N and L10N system modeled off MediaWiki. It
doesn't actually do anything yet, but keep your eyes peeled. doesn't actually do anything yet, but keep your eyes peeled.

2
README
View File

@@ -19,4 +19,4 @@ Places to go:
an in-depth installation guide. an in-depth installation guide.
* See WYSIWYG for information on editors like TinyMCE and FCKeditor * See WYSIWYG for information on editors like TinyMCE and FCKeditor
HTML Purifier can be found on the web at: http://htmlpurifier.org/ HTML Purifier can be found on the web at: http://hp.jpsband.org/

54
TODO
View File

@@ -4,36 +4,33 @@ TODO List
= KEY ==================== = KEY ====================
# Flagship # Flagship
- Regular - Regular
? Maybe I'll Do It ? At-risk
========================== ==========================
1.7 release [Advanced API] 1.6 release
# Complete advanced API, and fully document it # Implement all non-essential attribute transforms, configurable
# Implement all edge-case attribute transforms
# Implement all deprecated tags and attributes
- Parse TinyMCE-style whitelist into our %HTML.Allow* whitelists (possibly
do this earlier)
? HTML interface for tweaking configuration to see changes
1.8 release [Refactor, refactor!]
# URI validation routines tighter (see docs/dev-code-quality.html) (COMPLEX) # URI validation routines tighter (see docs/dev-code-quality.html) (COMPLEX)
# Advanced URI filtering schemes (see docs/proposal-new-directives.txt) # Advanced URI filtering schemes (see docs/proposal-new-directives.txt)
- Configuration profiles: predefined directives set with one func call
- Implement IDREF support (harder than it seems, since you cannot have
IDREFs to non-existent IDs)
- Allow non-ASCII characters in font names
1.9 release [Error'ed]
# Error logging for filtering/cleanup procedures # Error logging for filtering/cleanup procedures
- Requires I18N facilities to be created first (COMPLEX) - Requires I18N facilities to be created first (COMPLEX)
? Configuration profiles: sets of directives that get set with one func call
- XSS-attempt detection - XSS-attempt detection
- Implement IDREF support
1.7 release
# Add pre-packaged "levels" of cleaning (custom behavior already done)
- More fine-grained control over escaping behavior - More fine-grained control over escaping behavior
- Silently drop content inbetween SCRIPT tags (can be generalized to allow - Silently drop content inbetween SCRIPT tags (can be generalized to allow
specification of elements that, when detected as foreign, trigger removal specification of elements that, when detected as foreign, trigger removal
of children, although unbalanced tags could wreck havoc (or at least of children, although unbalanced tags could wreck havoc (or at least
delete the rest of the document)). delete the rest of the document)).
- Allow specifying global attributes on a tag-by-tag basis in
%HTML.AllowAttributes
? More user-friendly warnings when %HTML.Allow* attempts to specify a
tag or attribute that is not supported
- Parse TinyMCE whitelist into our %HTML.Allow* whitelists
1.10 release [Do What I Mean, Not What I Say] 1.8 release
# Additional support for poorly written HTML # Additional support for poorly written HTML
- Microsoft Word HTML cleaning (i.e. MsoNormal, but research essential!) - Microsoft Word HTML cleaning (i.e. MsoNormal, but research essential!)
- Friendly strict handling of <address> (block -> <br>) - Friendly strict handling of <address> (block -> <br>)
@@ -48,7 +45,7 @@ TODO List
- Append something to duplicate IDs so they're still usable (impl. note: the - Append something to duplicate IDs so they're still usable (impl. note: the
dupe detector would also need to detect the suffix as well) dupe detector would also need to detect the suffix as well)
2.0 release [Beyond HTML] 2.0 release
# Legit token based CSS parsing (will require revamping almost every # Legit token based CSS parsing (will require revamping almost every
AttrDef class) AttrDef class)
# Formatters for plaintext (COMPLEX) # Formatters for plaintext (COMPLEX)
@@ -57,33 +54,32 @@ TODO List
- Linkify URLs - Linkify URLs
- Smileys - Smileys
- Linkification for HTML Purifier docs: notably configuration and classes - Linkification for HTML Purifier docs: notably configuration and classes
3.0 release
- Extended HTML capabilities based on namespacing and tag transforms (COMPLEX)
- Hooks for adding custom processors to custom namespaced tags and
attributes, offer default implementation
- Lots of documentation and samples
- Allow tags to be "armored", an internal flag that protects them - Allow tags to be "armored", an internal flag that protects them
from validation and passes them out unharmed from validation and passes them out unharmed
- XHTML 1.1 support
- Fixes for Firefox's inability to handle COL alignment props (Bug 915) - Fixes for Firefox's inability to handle COL alignment props (Bug 915)
- Automatically add non-breaking spaces to empty table cells when - Automatically add non-breaking spaces to empty table cells when
empty-cells:show is applied to have compatibility with Internet Explorer empty-cells:show is applied to have compatibility with Internet Explorer
- Convert RTL/LTR override characters to <bdo> tags, or vice versa on demand. - Convert RTL/LTR override characters to <bdo> tags, or vice versa on demand.
Also, enable disabling of directionality Also, enable disabling of directionality
3.0 release [To XML and Beyond]
- Extended HTML capabilities based on namespacing and tag transforms (COMPLEX)
- Hooks for adding custom processors to custom namespaced tags and
attributes, offer default implementation
- Lots of documentation and samples
- XHTML 1.1 support
Ongoing Ongoing
- Lots of profiling, make it faster! - Lots of profiling, make it faster!
- Plugins for major CMSes (COMPLEX) - Plugins for major CMSes (COMPLEX)
- WordPress (mostly written, needs beta-testing) - WordPress
- eFiction - eFiction
- more! (look for ones that use WYSIWYGs) - more! (look for ones that use WYSIWYGs)
Unknown release (on a scratch-an-itch basis) Unknown release (on a scratch-an-itch basis)
? Semi-lossy dumb alternate character encoding transfor - Have 'lang' attribute be checked against official lists
? Have 'lang' attribute be checked against official lists, achieved by ? Semi-lossy dumb alternate character encoding transformations, achieved by
encoding all characters that have string entity equivalents encoding all characters that have string entity equivalents
- Explain how to use HTML Purifier in non-PHP languages
Requested Requested
? Native content compression, whitespace stripping (don't rely on Tidy, make ? Native content compression, whitespace stripping (don't rely on Tidy, make

View File

@@ -1 +0,0 @@
1.6.1

View File

@@ -1,7 +0,0 @@
The 1.6.1 release, code-named 'Ach! We missed something! Run!', completes
HTML Purifier's roster of attribute transformations. It also implements
a number of minor features (such as better font transformations, smarter
HTML parsing, the CSS property 'white-space' and XHTML 1.1), a few bug
fixes (most notably fixed __autoload compatibility issues) and a ton
of refactoring. 1.6 was for things that absolutely could not wait: this
release, developed in a more leisurely pace, fills in the gaps.

View File

@@ -24,7 +24,8 @@ error_reporting(E_ALL);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Include HTML Purifier library // Include HTML Purifier library
require_once '../library/HTMLPurifier.auto.php'; set_include_path('../library' . PATH_SEPARATOR . get_include_path());
require_once 'HTMLPurifier.php';
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@@ -14,12 +14,11 @@
<div id="filing">Filed under Development</div> <div id="filing">Filed under Development</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>HTML Purifier currently natively supports only a subset of HTML's <p>It makes no sense to adopt a <q>one-size-fits-all</q> approach to
allowed elements, attributes, and behavior. This is by design, filtersets: therefore, users must be able to define their own sets of
but as the user is always right, they'll need some method to overload <q>allowed</q> elements, as well as switch in-between doctypes of HTML.</p>
these behaviors.</p>
<p>Our goals are to let the user:</p> <p>Our goals are to let the user:</p>
@@ -27,18 +26,20 @@ these behaviors.</p>
<dt>Select</dt> <dt>Select</dt>
<dd><ul> <dd><ul>
<li>Doctype</li> <li>Doctype</li>
<li>Filtersets: Rich / Plain / Full ...</li>
<li>Mode: Lenient / Correctional</li> <li>Mode: Lenient / Correctional</li>
<li>Elements / Attributes / Modules</li> <li>Collections (?): Safe / Unsafe</li>
<li>Filterset</li> <li>Modules / Tags / Attributes</li>
</ul></dd> </ul></dd>
<dt>Customize</dt> <dt>Customize</dt>
<dd><ul> <dd><ul>
<li>Attributes</li> <li>Tags / Attributes / Attribute Types</li>
<li>Elements</li> <li>Filtersets</li>
<li>Root Node</li>
</ul></dd> </ul></dd>
<dt>Internals</dt> <dt>Create</dt>
<dd><ul> <dd><ul>
<li>Modules / Elements / Attributes / Attribute Types</li> <li>Modules / Tags / Attributes / Attribute Types</li>
<li>Filtersets</li> <li>Filtersets</li>
<li>Doctype</li> <li>Doctype</li>
</ul></dd> </ul></dd>
@@ -46,14 +47,11 @@ these behaviors.</p>
<h2>Select</h2> <h2>Select</h2>
<p>For basic use, the user will have to specify some basic parameters. This
is not strictly necessary, as HTML Purifier's default setting will always
output safe code, but is required for standards-compliant output.</p>
<h3>Selecting a Doctype</h3> <h3>Selecting a Doctype</h3>
<p>The first thing to select is the <strong>doctype</strong>. This <p>By default, users will use a doctype-based, permissive but secure
is essential for standards-compliant output.</p> whitelist. They must define a <strong>doctype</strong>, and this serves
as the first method of determining a filterset.</p>
<p class="technical">This identifier is based <p class="technical">This identifier is based
on the name the W3C has given to the document type and <em>not</em> on the name the W3C has given to the document type and <em>not</em>
@@ -63,131 +61,117 @@ the DTD identifier.</p>
<pre>$config->set('HTML', 'Doctype', 'XHTML 1.0 Transitional');</pre> <pre>$config->set('HTML', 'Doctype', 'XHTML 1.0 Transitional');</pre>
<p>Due to historical reasons, the default doctype is XHTML 1.0 <h3>Selecting a Filterset</h3>
Transitional, however, we really shouldn't be guessing what the user's
doctype is. Fortunantely, people who can't be bothered to set this won't <p>However, selecting this doctype doesn't mean much, because if we
be bothered when their pages stop validating.</p> adhered exactly to the definition we would be letting XSS and other
nasties through. HTML Purifier must, in its filterset, allow a subset
of the doctype, which we shall call a <strong>filterset</strong>.</p>
<p>By default, HTML Purifier will use the <strong>Rich</strong>
filterset, which allows as many elements as possible with untrusted
sources. Other possible filtersets could be:</p>
<dl>
<dt>Full</dt>
<dd>Allows the full span of elements in the doctype, good if you want
HTML Purifier to work as a Tidy substitute but not to strip
anything out.</dd>
<dt>Plain</dt>
<dd>Provides a minimum set of tags for semantic markup of things
like blog comments.</dd>
</dl>
<p>Extension-authors would be able to define custom filtersets for
other users to use.</p>
<p>A possible call to select a filterset would be:</p>
<pre>$config->set('HTML', 'Filterset', 'Rich');</pre>
<h3>Selecting Mode</h3> <h3>Selecting Mode</h3>
<p>Within doctypes, there are various <strong>modes</strong> of operation. <p>Within filtersets, there are various <strong>modes</strong> of operation.
These indicate variant behaviors that, while not strictly changing the These indicate variant behaviors that, while not strictly changing the
allowed set of elements and attributes, definitely affect the output. allowed set of elements and attributes, will definitely affect the output.
Currently, we have two modes, which may be used together:</p> Currently, we have two modes, which may be used together:</p>
<dl> <dl>
<dt>Lenient</dt> <dt>Lenient</dt>
<dd> <dd>Deprecated elements and attributes will be transformed into
<p>Deprecated elements and attributes will be transformed into standards-compliant alternatives when explicitly disallowed. For
standards-compliant alternatives when explicitly disallowed.</p> example, in the XHTML 1.0 Strict doctype, a <code>center</code>
<p>For example, in the XHTML 1.0 Strict doctype, a <code>center</code> tag would be turned into a <code>div</code> with the CSS property
element would be turned into a <code>div</code> with the CSS property
<code>text-align:center;</code>, but in XHTML 1.0 Transitional <code>text-align:center;</code>, but in XHTML 1.0 Transitional
the element would be preserved.</p> the tag would be preserved. This mode is on by default.</dd>
<p>This mode is on by default.</p> <dt>Correctional</dt>
</dd> <dd>Deprecated elements and attributes will be transformed into
<dt>Correctional[items to correct]</dt> standards-compliant alternatives whenever possible. Referring
<dd> back to the previous example, the <code>center</code> tag would
<p>Deprecated elements and attributes will be transformed into be transformed in both cases. However, tags without a
standards-compliant alternatives whenever possible.
It may have various levels of operation.</p>
<p>Referring back to the previous example, the <code>center</code> element would
be transformed in both cases. However, elements without a
reasonable standards-compliant alternative will be preserved reasonable standards-compliant alternative will be preserved
in their form.</p> in their form. This mode is on by default. It may have
<p>A user may want to correct certain deprecated attributes, but various levels of operation.</dd>
not others. For example, the <code>bgcolor</code> attribute may be
acceptable, but the <code>center</code> element not; also, possibly,
an HTML Purifier transformation may be buggy, so the user wants
to forgo it. Thus, correctional accepts an array defining which
elements and attributes to cleanup, or no parameter at all, which
means everything gets corrected. This also means that each
correction needs to be given a unique ID that can be referenced
in this manner. (We may also allow globbing, like *.name or a.*
for mass-enabling correction, and subtractive mode, where things
specified stop correction.) This array gets passed into the
constructor of the mode's module.</p>
<p>This mode is on by default.</p>
</dd>
</dl> </dl>
<p>A possible call to select modes would be:</p> <p>A possible call to select modes would be:</p>
<pre>$config->set('HTML', 'Mode', array('correctional', 'lenient'));</pre> <pre>$config->set('HTML', 'Mode', array('correctional', 'lenient'));</pre>
<p>If modes have extra parameters, a hash is necessary:</p> <p>If modes have extra parameters, a hash might work well:</p>
<pre>$config->set('HTML', 'Mode', array( <pre>$config->set('HTML', 'Mode', array(
'correctional' => 'center,a.name', 'correctional' => 9, // strongest level
'lenient' => true // this one's just boolean 'lenient' => true // this one's just boolean
));</pre> ));</pre>
<p>Modes may be specified along with the doctype declaration (we may want <p>Modes may possibly be wrapped up with the filterset declaration:</p>
to get a better set of separator characters):</p>
<pre>$config->setDoctype('XHTML Transitional 1.0', '+correctional[center,a.name] -lenient');</pre> <pre>$config->set('HTML', 'Filterset', 'Rich: correctional, lenient');</pre>
<p> <p>Further investigation in this field is necessary.</p>
With regards to the various levels of operation conjectured in the
Correctional mode, this is prompted by the fact that a user may want to
correct certain problems but not others, for example, fix the <code>center</code>
element but not the <code>u</code> element, both of which are deprecated.
Having an integer <q>level</q> will not work very well for such fine
grained tweaking, but an array of specific settings might.</p>
<h3>Selecting Elements / Attributes / Modules</h3> <h3>Selecting Modules / Tags / Attributes</h3>
<p></p>
<p>If this cookie cutter approach doesn't appeal to a user, they may <p>If this cookie cutter approach doesn't appeal to a user, they may
decide to roll their own filterset by selecting modules, elements and decide to roll their own filterset by selecting modules, tags and
attributes to allow.</p> attributes to allow.</p>
<p class="technical">This would make use of the same facilities <p class="technical">This would make use of the same facilities
as a filterset author would use, except that it would go under an as a filterset author would use, except that it would go under an
<q>anonymous</q> filterset that would be auto-selected if any of the <q>anonymous</q> filterset that would be auto-selected if any of the
relevant module/elements/attribute selection configuration directives were relevant module/tag/attribute selection configuration directives were
non-null.</p> non-null.</p>
<p>In practice, this is the most commonly demanded feature. Most users are <p>On the highest level, a user will usually be most interested in
perfectly happy defining a filterset that looks like:</p> directly specifying which elements and attributes are desired. For
example:</p>
<pre>$config->setAllowedHTML('a[href,title];em;p;blockquote');</pre> <pre>$config->set('HTML', 'AllowedElements', 'a,b,em,p,blockquote,code,i');</pre>
<p class="technical">The directive %HTML.Allowed is a convenience function <p>Attribute declarations could be merged into this declaration as such:</p>
that may be fully expressed with the legacy interface, and thus is
given its own setter.</p>
<p>We currently support a separated interface, which also must be preserved:</p> <pre>$config->set('HTML', 'Allowed', 'a[href,title],b,em,p[class],blockquote[cite],code,i');</pre>
<pre>$config->set('HTML', 'AllowedElements', 'a,em,p,blockquote'); <p>...or be kept separate:</p>
$config->set('HTML', 'AllowedAttributes', 'a.href,a.title');</pre>
<p>A user may also choose to allow modules:</p> <pre>$config->set('HTML', 'AllowedAttributes', 'a.href,a.title,p.class,blockquote.cite');</pre>
<pre>$config->set('HTML', 'AllowedModules', 'Hypertext,Text,Lists'); // or
$config->setAllowedHTML('Hypertext,Text,Lists');</pre>
<p>But it is not expected that this feature will be widely used.</p>
<p class="fixme">The granularity of these modules is too coarse for
the average user (for example, the core module loads everything from
the essential <code>p</code> element to the not-so-safe <code>h1</code>
element). How do we make this still a viable solution? Possible answers
may be sub-modules or module parameters. This may not even be a problem,
considering that most people won't be selecting modules.</p>
<p class="technical">Modules are distinguished from regular elements by the
case of their first letter. While XML distinguishes between and allows
lower and uppercase letters in element names, most well-known XML
languages use only lower-case
element names for sake of consistency.</p>
<p class="technical">Considering that, internally speaking, as mandated by <p class="technical">Considering that, internally speaking, as mandated by
the XHTML 1.1 Modularization specification, we have organized our the XHTML 1.1 Modularization specification, we have organized our
elements around modules, considerable gymnastics will be needed to elements around modules, considerable gymnastics will be needed to
get this sort of functionality working.</p> get this sort of functionality working.</p>
<p>A user may also specify a module to load a class of elements and attributes
into their filterest:</p>
<pre>$config->set('HTML', 'Allowed', 'Hypertext,Core');</pre>
<p class="fixme">The granularity of these modules is too coarse for
the average user (for example, the core module loads everything from
the essential <code>p</code> tag to the not-so-safe <code>h1</code>
tag). How do we make this still a viable solution?</p>
<h3>Unified selector</h3> <h3>Unified selector</h3>
<p>Because selecting each and every one of these configuration options <p>Because selecting each and every one of these configuration options
@@ -199,89 +183,6 @@ for selecting a filterset. Possibility:</p>
<p>...which is simply a light wrapper over the individual configuration <p>...which is simply a light wrapper over the individual configuration
calls. A custom config file format or text format could also be adopted.</p> calls. A custom config file format or text format could also be adopted.</p>
<h2>Customize</h2>
<p>By reviewing topic posts in the support forum, we determined that
there were two primarily demanded customization features people wanted:
to add an attribute to an existing element, and to add an element.
Thus, we'll want to create convenience functions for these common
use-cases.</p>
<p>Note that the functions described here are only available if
a raw copy of <code>HTMLPurifier_HTMLDefinition</code> was retrieved.
<code>addAttribute</code> may work on a processed copy, but for
consistency's sake we will mandate this for everything.</p>
<h3>Attributes</h3>
<p>An attribute is bound to an element by a name and has a specific
<code>AttrDef</code> that validates it. Thus, the interface should
be:</p>
<pre>function addAttribute($element, $attribute, $attribute_def);</pre>
<p>With a use-case that looks like:</p>
<pre>$def->addAttribute('a', 'rel', new HTMLPurifier_AttrDef_Enum(array('nofollow')));</pre>
<p>The <code>$attribute_def</code> value can be a little flexible,
to make things simpler. We'll let it also be:</p>
<ul>
<li>Class name: We'll instantiate it for you</li>
<li>Function name: We'll create an <code>HTMLPurifier_AttrDef_Anonymous</code>
class with that function registered as a callback.</li>
<li>String attribute type: We'll use <code>HTMLPurifier_AttrTypes</code>
</li>
<li>String starting with <code>enum(</code>: We'll explode it and stuff it in an
<code>HTMLPurifier_AttrDef_Enum</code> for you.</li>
</ul>
<p>Making the previous example written as:</p>
<pre>$def->addAttribute('a', 'rel', 'enum(nofollow)');</pre>
<h3>Elements</h3>
<p>An element requires certain information as specified by
<code>HTMLPurifier_ElementDef</code>. However, not all of it is necessary,
the usual things required are:</p>
<ul>
<li>Attributes</li>
<li>Content model/type</li>
<li>Registration in a content set</li>
</ul>
<p>This suggests an API like this:</p>
<pre>function addElement($element, $type, $content_model, $attributes = array());</pre>
<p>Each parameter explained in depth:</p>
<dl>
<dt><code>$element</code></dt>
<dd>Element name, ex. 'label'</dd>
<dt><code>$type</code></dt>
<dd>Content set to register in, ex. 'Inline' or 'Flow'</dd>
<dt><code>$content_model</code></dt>
<dd>Description of allowed children. This is a merged form of
<code>HTMLPurifier_ElementDef</code>'s member variables
<code>$content_model</code> and <code>$content_model_type</code>,
where the form is <q>Type: Model</q>, ex. 'Optional: Inline'.</dd>
<dt><code>$attributes</code></dt>
<dd>Array of attribute names to attribute definitions, much like
the above-described attribute customization.</dd>
</dl>
<p>A possible usage:</p>
<pre>$def->addElement('font', 'Inline', 'Optional: Inline',
array(0 => array('Common'), 'color' => 'Color'));</pre>
<p>We may want to Common attribute collection inclusion to be added
by default.</p>
<div id="version">$Id$</div> <div id="version">$Id$</div>
</body></html> </body></html>

View File

@@ -1,16 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="description" content="Discusses code quality issues and places that need to be refactored in HTML Purifier." />
<link rel="stylesheet" type="text/css" href="./style.css" />
Code Quality Issues <title>Code Quality Issues - HTML Purifier</title>
Okay, face it. Programmers can get lazy, cut corners, or make mistakes. They </head><body>
<h1>Code Quality Issues</h1>
<div id="filing">Filed under Development</div>
<div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>Okay, face it. Programmers can get lazy, cut corners, or make mistakes. They
also can do quick prototypes, and then forget to rewrite them later. Well, also can do quick prototypes, and then forget to rewrite them later. Well,
while I can't list mistakes in here, I can list prototype-like segments while I can't list mistakes in here, I can list prototype-like segments
of code that should be aggressively refactored. This does not list of code that should be aggressively refactored. This does not list
optimization issues, that needs to be done after intense profiling. optimization issues, that needs to be done after intense profiling.</p>
<pre>
docs/examples/demo.php - ad hoc HTML/PHP soup to the extreme docs/examples/demo.php - ad hoc HTML/PHP soup to the extreme
AttrDef - a lot of duplication, more generic classes need to be created; AttrDef
a lot of strtolower() calls, no legit casing
Class - doesn't support Unicode characters (fringe); uses regular Class - doesn't support Unicode characters (fringe); uses regular
expressions expressions
Lang - code duplication; premature optimization Lang - code duplication; premature optimization
@@ -30,3 +45,8 @@ URIScheme - needs to have callable generic checks
mailto - doesn't validate emails, doesn't validate querystring mailto - doesn't validate emails, doesn't validate querystring
news - doesn't validate opaque path news - doesn't validate opaque path
nntp - doesn't constrain path nntp - doesn't constrain path
</pre>
<div id="version">$Id$</div>
</body></html>

View File

@@ -14,7 +14,7 @@
<div id="filing">Filed under Development</div> <div id="filing">Filed under Development</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>The classes in this library follow a few naming conventions, which may <p>The classes in this library follow a few naming conventions, which may
help you find the correct functionality more quickly. Here they are:</p> help you find the correct functionality more quickly. Here they are:</p>

View File

@@ -14,7 +14,7 @@
<div id="filing">Filed under Development</div> <div id="filing">Filed under Development</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>Here are some possible optimization techniques we can apply to code sections if <p>Here are some possible optimization techniques we can apply to code sections if
they turn out to be slow. Be sure not to prematurely optimize: if you get they turn out to be slow. Be sure not to prematurely optimize: if you get

View File

@@ -32,7 +32,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
<div id="filing">Filed under Development</div> <div id="filing">Filed under Development</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<h2>Key</h2> <h2>Key</h2>
@@ -142,7 +142,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
<tbody> <tbody>
<tr><th colspan="2">Unknown</th></tr> <tr><th colspan="2">Unknown</th></tr>
<tr class="danger css1 impl-yes"><td>background-image</td><td>Dangerous</td></tr> <tr class="danger css1 impl-yes"><td>background-image</td><td>Dangerous, target milestone 1.3</td></tr>
<tr class="css1 impl-yes"><td>background-attachment</td><td>ENUM(scroll, fixed), <tr class="css1 impl-yes"><td>background-attachment</td><td>ENUM(scroll, fixed),
Depends on background-image</td></tr> Depends on background-image</td></tr>
<tr class="css1 impl-yes"><td>background-position</td><td>Depends on background-image</td></tr> <tr class="css1 impl-yes"><td>background-position</td><td>Depends on background-image</td></tr>
@@ -151,7 +151,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
will not implement list-item, run-in (Opera only) or table (no IE); will not implement list-item, run-in (Opera only) or table (no IE);
inline-block has incomplete IE6 support and requires -moz-inline-box inline-block has incomplete IE6 support and requires -moz-inline-box
for Mozilla. Unknown target milestone.</td></tr> for Mozilla. Unknown target milestone.</td></tr>
<tr class="css1 impl-yes"><td>height</td><td>Interesting, why use it? Unknown target milestone.</td></tr> <tr class="css1"><td>height</td><td>Interesting, why use it? Unknown target milestone.</td></tr>
<tr class="danger css1 impl-yes"><td>list-style-image</td><td>Dangerous?</td></tr> <tr class="danger css1 impl-yes"><td>list-style-image</td><td>Dangerous?</td></tr>
<tr class="impl-no"><td>max-height</td><td rowspan="4">No IE 5/6</td></tr> <tr class="impl-no"><td>max-height</td><td rowspan="4">No IE 5/6</td></tr>
<tr class="impl-no"><td>min-height</td></tr> <tr class="impl-no"><td>min-height</td></tr>
@@ -168,9 +168,9 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
<tr class="impl-no"><td>quotes</td><td>May be dropped from CSS2, fairly useless for inline context</td></tr> <tr class="impl-no"><td>quotes</td><td>May be dropped from CSS2, fairly useless for inline context</td></tr>
<tr class="impl-no"><td>visibility</td><td>ENUM(visible, hidden, collapse), <tr class="impl-no"><td>visibility</td><td>ENUM(visible, hidden, collapse),
Dangerous</td></tr> Dangerous</td></tr>
<tr class="css1 feature impl-partial"><td>white-space</td><td>ENUM(normal, pre, nowrap, pre-wrap, <tr class="css1 feature"><td>white-space</td><td>ENUM(normal, pre, nowrap, pre-wrap,
pre-line), Spotty implementation: pre-line), Spotty implementation:
pre (no IE 5/6), <em>nowrap</em> (no IE 5, supported), pre (no IE 5/6), nowrap (no IE 5),
pre-wrap (only Opera), pre-line (no support). Fixable? Unknown target milestone.</td></tr> pre-wrap (only Opera), pre-line (no support). Fixable? Unknown target milestone.</td></tr>
</tbody> </tbody>
@@ -238,14 +238,14 @@ Mozilla on inside and needs -moz-outline, no IE support.</td></tr>
<tr><th colspan="3">Questionable</th></tr> <tr><th colspan="3">Questionable</th></tr>
<tr class="impl-no"><td>accesskey</td><td>A</td><td>May interfere with main interface</td></tr> <tr class="impl-no"><td>accesskey</td><td>A</td><td>May interfere with main interface</td></tr>
<tr class="impl-no"><td>tabindex</td><td>A</td><td>May interfere with main interface</td></tr> <tr class="impl-no"><td>tabindex</td><td>A</td><td>May interfere with main interface</td></tr>
<tr class="impl-yes"><td>target</td><td>A</td><td>Config enabled, only useful for frame layouts, disallowed in strict</td></tr> <tr><td>target</td><td>A</td><td>Config enabled, only useful for frame layouts, disallowed in strict</td></tr>
</tbody> </tbody>
<tbody> <tbody>
<tr><th colspan="3">Miscellaneous</th></tr> <tr><th colspan="3">Miscellaneous</th></tr>
<tr><td>datetime</td><td>DEL, INS</td><td>No visible effect, ISO format</td></tr> <tr><td>datetime</td><td>DEL, INS</td><td>No visible effect, ISO format</td></tr>
<tr class="impl-yes"><td>rel</td><td>A</td><td>Largely user-defined: nofollow, tag (see microformats)</td></tr> <tr><td>rel</td><td>A</td><td>Largely user-defined: nofollow, tag (see microformats)</td></tr>
<tr class="impl-yes"><td>rev</td><td>A</td><td>Largely user-defined: vote-*</td></tr> <tr><td>rev</td><td>A</td><td>Largely user-defined: vote-*</td></tr>
<tr class="feature"><td>axis</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr> <tr class="feature"><td>axis</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr>
<tr class="feature"><td>char</td><td>COL, COLGROUP, TBODY, TD, TFOOT, TH, THEAD, TR</td><td>W3C only: No browser implementation</td></tr> <tr class="feature"><td>char</td><td>COL, COLGROUP, TBODY, TD, TFOOT, TH, THEAD, TR</td><td>W3C only: No browser implementation</td></tr>
<tr class="feature"><td>headers</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr> <tr class="feature"><td>headers</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr>
@@ -262,37 +262,37 @@ Mozilla on inside and needs -moz-outline, no IE support.</td></tr>
</tbody> </tbody>
<tbody> <tbody>
<tr><th colspan="3">Transform</th></tr> <tr><th colspan="3">Transform, target milestone 1.4</th></tr>
<tr class="impl-yes"><td rowspan="5">align</td><td>CAPTION</td><td>'caption-side' for top/bottom, 'text-align' for left/right</td></tr> <tr><td rowspan="5">align</td><td>CAPTION</td><td>Near-equiv style 'caption-side', drop left and right</td></tr>
<tr class="impl-yes"><td>IMG</td><td rowspan="3">See specimens/html-align-to-css.html</td></tr> <tr><td>IMG</td><td rowspan="2">Margin-left and margin-right = auto or parent div</td></tr>
<tr class="impl-yes"><td>TABLE</td></tr> <tr><td>TABLE</td></tr>
<tr class="impl-yes"><td>HR</td></tr> <tr><td>HR</td><td>Near-equivalent style 'text-align' (Works for IE and Opera, but not Firefox). Also try <code>margin-right:auto; margin-left:0;</code> for left or <code>margin-right:0; margin-left:auto;</code> for right (optionally replacing 0 with the original margin for that side)</td></tr>
<tr class="impl-yes"><td>H1, H2, H3, H4, H5, H6, P</td><td>Equivalent style 'text-align'</td></tr> <tr class="impl-yes"><td>H1, H2, H3, H4, H5, H6, P</td><td>Equivalent style 'text-align'</td></tr>
<tr class="required impl-yes"><td>alt</td><td>IMG</td><td>Required, insert image filename if src is present or default invalid image text</td></tr> <tr class="required impl-yes"><td>alt</td><td>IMG</td><td>Required, insert image filename if src is present or default invalid image text</td></tr>
<tr class="impl-yes"><td rowspan="3">bgcolor</td><td>TABLE</td><td>Superset style 'background-color'</td></tr> <tr><td rowspan="3">bgcolor</td><td>TABLE</td><td>Equivalent style 'background-color'</td></tr>
<tr class="impl-yes"><td>TR</td><td>Superset style 'background-color'</td></tr> <tr><td>TR</td><td>Equivalent style 'background-color'</td></tr>
<tr class="impl-yes"><td>TD, TH</td><td>Superset style 'background-color'</td></tr> <tr><td>TD, TH</td><td>Equivalent style 'background-color'</td></tr>
<tr class="impl-yes"><td>border</td><td>IMG</td><td>Equivalent style <code>border:[number]px solid</code></td></tr> <tr><td>border</td><td>IMG</td><td>Near equivalent style 'border-width', as it only applies when link present</td></tr>
<tr class="impl-yes"><td>clear</td><td>BR</td><td>Near-equiv style 'clear', transform 'all' into 'both'</td></tr> <tr><td>clear</td><td>BR</td><td>Near-equiv style 'clear', transform 'all' into 'both'</td></tr>
<tr class="impl-no"><td>compact</td><td>DL, OL, UL</td><td>Boolean, needs custom CSS class; rarely used anyway</td></tr> <tr class="impl-no"><td>compact</td><td>DL, OL, UL</td><td>Boolean, needs custom CSS class; rarely used anyway</td></tr>
<tr class="required impl-yes"><td>dir</td><td>BDO</td><td>Required, insert ltr (or configuration value) if none</td></tr> <tr class="required impl-yes"><td>dir</td><td>BDO</td><td>Required, insert ltr (or configuration value) if none</td></tr>
<tr class="impl-yes"><td>height</td><td>TD, TH</td><td>Near-equiv style 'height', needs px suffix if original was in pixels</td></tr> <tr><td>height</td><td>TD, TH</td><td>Near-equiv style 'height', needs px suffix if original was in pixels</td></tr>
<tr class="impl-yes"><td>hspace</td><td>IMG</td><td>Near-equiv styles 'margin-top' and 'margin-bottom', needs px suffix</td></tr> <tr><td>hspace</td><td>IMG</td><td>Near-equiv styles 'margin-top' and 'margin-bottom', needs px suffix</td></tr>
<tr class="impl-yes"><td>lang</td><td>*</td><td>Copy value to xml:lang</td></tr> <tr class="impl-yes"><td>lang</td><td>*</td><td>Copy value to xml:lang</td></tr>
<tr class="impl-yes"><td rowspan="2">name</td><td>IMG</td><td>Turn into ID</td></tr> <tr><td rowspan="2">name</td><td>IMG</td><td>Turn into ID</td></tr>
<tr class="impl-yes"><td>A</td><td>Turn into ID</td></tr> <tr><td>A</td><td>Turn into ID? (not deprecated, though in which specs?)</td></tr>
<tr class="impl-yes"><td>noshade</td><td>HR</td><td>Boolean, style 'border-style:solid;'</td></tr> <tr><td>noshade</td><td>HR</td><td>Boolean, style 'border-style:solid;'</td></tr>
<tr class="impl-yes"><td>nowrap</td><td>TD, TH</td><td>Boolean, style 'white-space:nowrap;' (not compat with IE5)</td></tr> <tr><td>nowrap</td><td>TD, TH</td><td>Boolean, style 'white-space:nowrap;' (not compat with IE5)</td></tr>
<tr class="impl-yes"><td>size</td><td>HR</td><td>Near-equiv 'height', needs px suffix if original was pixels</td></tr> <tr><td>size</td><td>HR</td><td>Near-equiv 'width', needs px suffix if original was pixels</td></tr>
<tr class="required impl-yes"><td>src</td><td>IMG</td><td>Required, insert blank or default img if not set</td></tr> <tr class="required impl-yes"><td>src</td><td>IMG</td><td>Required, insert blank or default img if not set</td></tr>
<tr class="impl-yes"><td>start</td><td>OL</td><td>Poorly supported 'counter-reset', allowed in loose, dropped in strict</td></tr> <tr class="impl-yes"><td>start</td><td>OL</td><td>Poorly supported 'counter-reset', allowed in loose, dropped in strict</td></tr>
<tr class="impl-yes"><td rowspan="3">type</td><td>LI</td><td rowspan="3">Equivalent style 'list-style-type', different allowed values though. (needs testing)</td></tr> <tr><td rowspan="3">type</td><td>LI</td><td rowspan="3">Equivalent style 'list-style-type', different allowed values though. (needs testing)</td></tr>
<tr class="impl-yes"><td>OL</td></tr> <tr><td>OL</td></tr>
<tr class="impl-yes"><td>UL</td></tr> <tr><td>UL</td></tr>
<tr class="impl-yes"><td>value</td><td>LI</td><td>Poorly supported 'counter-reset', allowed in loose, dropped in strict</td></tr> <tr class="impl-yes"><td>value</td><td>LI</td><td>Poorly supported 'counter-reset', allowed in loose, dropped in strict</td></tr>
<tr class="impl-yes"><td>vspace</td><td>IMG</td><td>Near-equiv styles 'margin-left' and 'margin-right', needs px suffix, see hspace</td></tr> <tr><td>vspace</td><td>IMG</td><td>Near-equiv styles 'margin-left' and 'margin-right', needs px suffix, see hspace</td></tr>
<tr class="impl-yes"><td rowspan="2">width</td><td>HR</td><td rowspan="2">Near-equiv style 'width', needs px suffix if original was pixels</td></tr> <tr><td rowspan="2">width</td><td>HR</td><td rowspan="2">Near-equiv style 'width', needs px suffix if original was pixels</td></tr>
<tr class="impl-yes"><td>TD, TH</td></tr> <tr><td>TD, TH</td></tr>
</tbody> </tbody>
</table> </table>

View File

@@ -15,7 +15,7 @@
<div id="filing">Filed under End-User</div> <div id="filing">Filed under End-User</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>Prior to HTML Purifier 1.2.0, this library blithely accepted user input that <p>Prior to HTML Purifier 1.2.0, this library blithely accepted user input that
looked like this:</p> looked like this:</p>

View File

@@ -15,7 +15,7 @@
<div id="filing">Filed under End-User</div> <div id="filing">Filed under End-User</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>HTML Purifier is a very powerful library. But with power comes great <p>HTML Purifier is a very powerful library. But with power comes great
responsibility, in the form of longer execution times. Remember, this responsibility, in the form of longer execution times. Remember, this

View File

@@ -23,7 +23,7 @@ own advice for sake of portability. -->
<div id="filing">Filed under End-User</div> <div id="filing">Filed under End-User</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>Character encoding and character sets are not that <p>Character encoding and character sets are not that
difficult to understand, but so many people blithely stumble difficult to understand, but so many people blithely stumble
@@ -1003,11 +1003,7 @@ when dealing with Unicode text:</p>
</ul></li> </ul></li>
</ul> </ul>
<p>Note: this list applies to UTF-8 encoded text only: if you have <p>...and always think in bytes, not characters. If you use strpos()
a string that you are 100% sure is ASCII, be my guest and use
<code>strtolower</code> (HTML Purifier uses this function.)</p>
<p>Regardless, always think in bytes, not characters. If you use strpos()
to find the position of a character, it will be in bytes, but this to find the position of a character, it will be in bytes, but this
usually won't matter since substr() also operates with byte indices!</p> usually won't matter since substr() also operates with byte indices!</p>

View File

@@ -15,7 +15,7 @@
<div id="filing">Filed under End-User</div> <div id="filing">Filed under End-User</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>Clients like their YouTube videos. It gives them a warm fuzzy feeling when <p>Clients like their YouTube videos. It gives them a warm fuzzy feeling when
they see a neat little embedded video player on their websites that can play they see a neat little embedded video player on their websites that can play
@@ -70,7 +70,7 @@ into your documents. YouTube's code goes like this:</p>
class=&quot;embed-youtube&quot;&gt;AyPzM5WK8ys&lt;/span&gt;</code> your class=&quot;embed-youtube&quot;&gt;AyPzM5WK8ys&lt;/span&gt;</code> your
application can reconstruct the full object from this small snippet that application can reconstruct the full object from this small snippet that
passes through HTML Purifier <em>unharmed</em>. passes through HTML Purifier <em>unharmed</em>.
<a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/Filter/YouTube.php">Show me the code!</a></p> <a href="http://hp.jpsband.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/Filter/YouTube.php">Show me the code!</a></p>
<p>And the corresponding usage:</p> <p>And the corresponding usage:</p>

View File

@@ -1,23 +1,14 @@
<?php <?php exit;
// This file demonstrates basic usage of HTMLPurifier. // This file demonstrates basic usage of HTMLPurifier.
// replace this with the path to the HTML Purifier library require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
require_once '../../library/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault(); $purifier = new HTMLPurifier();
// configuration goes here:
$config->set('Core', 'Encoding', 'ISO-8859-1'); //replace with your encoding
$config->set('Core', 'XHTML', true); // set to false if HTML 4.01
$purifier = new HTMLPurifier($config);
// untrusted input HTML
$html = '<b>Simple and short'; $html = '<b>Simple and short';
$pure_html = $purifier->purify($html); $pure_html = $purifier->purify($html);
echo '<pre>' . htmlspecialchars($pure_html) . '</pre>'; echo $pure_html;
?> ?>

136
docs/examples/demo.php Normal file
View File

@@ -0,0 +1,136 @@
<?php
// using _REQUEST because we accept GET and POST requests
$content = empty($_REQUEST['xml']) ? 'text/html' : 'application/xhtml+xml';
header("Content-type:$content;charset=UTF-8");
// prevent PHP versions with shorttags from barfing
echo '<?xml version="1.0" encoding="UTF-8" ?>
';
function getFormMethod() {
return (isset($_REQUEST['post'])) ? 'post' : 'get';
}
if (empty($_REQUEST['strict'])) {
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<?php
} else {
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<?php
}
?>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>HTML Purifier Live Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>HTML Purifier Live Demo</h1>
<?php
require_once '../../library/HTMLPurifier.auto.php';
if (!empty($_REQUEST['html'])) { // start result
if (strlen($_REQUEST['html']) > 50000) {
?>
<p>Request exceeds maximum allowed text size of 50kb.</p>
<?php
} else { // start main processing
$html = get_magic_quotes_gpc() ? stripslashes($_REQUEST['html']) : $_REQUEST['html'];
$config = HTMLPurifier_Config::createDefault();
$config->set('Core', 'TidyFormat', !empty($_REQUEST['tidy']));
$config->set('HTML', 'Strict', !empty($_REQUEST['strict']));
$purifier = new HTMLPurifier($config);
$pure_html = $purifier->purify($html);
?>
<p>Here is your purified HTML:</p>
<div style="border:5px solid #CCC;margin:0 10%;padding:1em;">
<?php if(getFormMethod() == 'get') { ?>
<div style="float:right;">
<a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Transitional" height="31" width="88" style="border:0;" /></a>
</div>
<?php } ?>
<?php
echo $pure_html;
?>
<div style="clear:both;"></div>
</div>
<p>Here is the source code of the purified HTML:</p>
<pre><?php
echo htmlspecialchars($pure_html, ENT_COMPAT, 'UTF-8');
?></pre>
<?php
if (getFormMethod() == 'post') { // start POST validation notice
?>
<p>If you would like to validate the code with
<a href="http://validator.w3.org/#validate-by-input">W3C's
validator</a>, copy and paste the <em>entire</em> demo page's source.</p>
<?php
} // end POST validation notice
} // end main processing
// end result
} else {
?>
<p>Welcome to the live demo. Enter some HTML and see how HTML Purifier
will filter it.</p>
<?php
}
?>
<form id="filter" action="demo.php<?php
echo '?' . getFormMethod();
if (isset($_REQUEST['profile']) || isset($_REQUEST['XDEBUG_PROFILE'])) {
echo '&amp;XDEBUG_PROFILE=1';
} ?>" method="<?php echo getFormMethod(); ?>">
<fieldset>
<legend>HTML Purifier Input (<?php echo getFormMethod(); ?>)</legend>
<textarea name="html" cols="60" rows="15"><?php
if (isset($html)) {
echo htmlspecialchars(
HTMLPurifier_Encoder::cleanUTF8($html), ENT_COMPAT, 'UTF-8');
}
?></textarea>
<?php if (getFormMethod() == 'get') { ?>
<p><strong>Warning:</strong> GET request method can only hold
8129 characters (probably less depending on your browser).
If you need to test anything
larger than that, try the <a href="demo.php?post">POST form</a>.</p>
<?php } ?>
<?php if (extension_loaded('tidy')) { ?>
<div>Nicely format output with Tidy? <input type="checkbox" value="1"
name="tidy"<?php if (!empty($_REQUEST['tidy'])) echo ' checked="checked"'; ?> /></div>
<?php } ?>
<div>XHTML 1.0 Strict output? <input type="checkbox" value="1"
name="strict"<?php if (!empty($_REQUEST['strict'])) echo ' checked="checked"'; ?> /></div>
<div>Serve as application/xhtml+xml? (not for IE) <input type="checkbox" value="1"
name="xml"<?php if (!empty($_REQUEST['xml'])) echo ' checked="checked"'; ?> /></div>
<div>
<input type="submit" value="Submit" name="submit" class="button" />
</div>
</fieldset>
</form>
<p>Return to <a href="http://hp.jpsband.org/">HTML Purifier's home page</a>.
Try the form in <a href="demo.php?get">GET</a> and <a href="demo.php?post">POST</a> request
flavors (GET is easy to validate with W3C, but POST allows larger inputs).</p>
</body>
</html>

View File

@@ -13,7 +13,7 @@
<h1>Documentation</h1> <h1>Documentation</h1>
<p><strong><a href="http://htmlpurifier.org/">HTML Purifier</a></strong> has documentation for all types of people. <p><strong><a href="http://hp.jpsband.org/">HTML Purifier</a></strong> has documentation for all types of people.
Here is an index of all of them.</p> Here is an index of all of them.</p>
<h2>End-user</h2> <h2>End-user</h2>
@@ -42,6 +42,9 @@ conventions.</p>
<dl> <dl>
<dt><a href="dev-code-quality.html">Code Quality Issues</a></dt>
<dd>Discusses code quality issues and places that need to be refactored.</dd>
<dt><a href="dev-progress.html">Implementation Progress</a></dt> <dt><a href="dev-progress.html">Implementation Progress</a></dt>
<dd>Tables detailing HTML element and CSS property implementation coverage.</dd> <dd>Tables detailing HTML element and CSS property implementation coverage.</dd>
@@ -102,12 +105,6 @@ the code. They may be upgraded to HTML files or stay as TXT scratchpads.</p>
<td>Common security issues that may still arise (half-baked).</td> <td>Common security issues that may still arise (half-baked).</td>
</tr> </tr>
<tr>
<td>Development</td>
<td><a href="enduser-code-quality.txt">Code Quality Issues</a></td>
<td>Enumerates code quality issues and places that need to be refactored.</td>
</tr>
<tr> <tr>
<td>Proposal</td> <td>Proposal</td>
<td><a href="proposal-filter-levels.txt">Filter levels</a></td> <td><a href="proposal-filter-levels.txt">Filter levels</a></td>

View File

@@ -15,7 +15,7 @@
<div id="filing">Filed under Proposals</div> <div id="filing">Filed under Proposals</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>Your website probably has a color-scheme. <p>Your website probably has a color-scheme.
<span style="color:#090; background:#FFF;">Green on white</span>, <span style="color:#090; background:#FFF;">Green on white</span>,

View File

@@ -15,7 +15,7 @@
<div id="filing">Filed under Reference</div> <div id="filing">Filed under Reference</div>
<div id="index">Return to the <a href="index.html">index</a>.</div> <div id="index">Return to the <a href="index.html">index</a>.</div>
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div> <div id="home"><a href="http://hp.jpsband.org/">HTML Purifier</a> End-User Documentation</div>
<p>Many thanks to the DevNetwork community for answering questions, <p>Many thanks to the DevNetwork community for answering questions,
theorizing about design, and offering encouragement during theorizing about design, and offering encouragement during

View File

@@ -1,8 +0,0 @@
Licensing of Specimens
Some files in this directory have different licenses:
windows-live-mail-desktop-beta.html - donated by laacz, public domain
img.png - LGPL, from <http://commons.wikimedia.org/wiki/Image:Pastille_chrome.png>
All other files are by me, and are licensed under LGPL.

View File

@@ -1,165 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>HTML align attribute to CSS - HTML Purifier Specimen</title>
<style type="text/css">
div.container {position:relative;height:110px;}
div.container.legend .test {text-align:center;line-height:100px;}
div.test {width:100px;height:100px;border:1px solid black;
position:absolute;top:10px;}
div.test.html {left:10px;}
div.test.css {left:140px;}
table {background:#F00;}
img {border:1px solid #000;}
hr {width:50px;}
div.segment {width:250px; float:left; margin-top:1em;}
</style>
</head>
<body>
<h1>HTML align attribute to CSS</h1>
<p>Inspect source for methodology.</p>
<div class="container legend">
<div class="test html">
HTML
</div>
<div class="test css">
CSS
</div>
</div>
<div class="segment">
<h2>table.align</h2>
<h3>left</h3>
<div class="container">
<div class="test html">
a<table align="left"><tr><td>O</td></tr></table>a
</div>
<div class="test css">
a<table style="float:left;"><tr><td>O</td></tr></table>a
</div>
</div>
<h3>center</h3>
<div class="container">
<div class="test html">
a<table align="center"><tr><td>O</td></tr></table>a
</div>
<div class="test css">
a<table style="margin-left:auto; margin-right:auto;"><tr><td>O</td></tr></table>a
</div>
</div>
<h3>right</h3>
<div class="container">
<div class="test html">
a<table align="right"><tr><td>O</td></tr></table>a
</div>
<div class="test css">
a<table style="float:right;"><tr><td>O</td></tr></table>a
</div>
</div>
</div>
<!-- ################################################################## -->
<div class="segment">
<h2>img.align</h2>
<h3>left</h3>
<div class="container">
<div class="test html">
a<img src="img.png" align="left">a
</div>
<div class="test css">
a<img src="img.png" style="float:left;">a
</div>
</div>
<h3>right</h3>
<div class="container">
<div class="test html">
a<img src="img.png" align="right">a
</div>
<div class="test css">
a<img src="img.png" style="float:right;">a
</div>
</div>
<h3>bottom</h3>
<div class="container">
<div class="test html">
a<img src="img.png" align="bottom">a
</div>
<div class="test css">
a<img src="img.png" style="vertical-align:baseline;">a
</div>
</div>
<h3>middle</h3>
<div class="container">
<div class="test html">
a<img src="img.png" align="middle">a
</div>
<div class="test css">
a<img src="img.png" style="vertical-align:middle;">a
</div>
</div>
<h3>top</h3>
<div class="container">
<div class="test html">
a<img src="img.png" align="top">a
</div>
<div class="test css">
a<img src="img.png" style="vertical-align:top;">a
</div>
</div>
</div>
<!-- ################################################################## -->
<div class="segment">
<h2>hr.align</h2>
<h3>left</h3>
<div class="container">
<div class="test html">
<hr align="left" />
</div>
<div class="test css">
<hr style="margin-right:auto; margin-left:0; text-align:left;" />
</div>
</div>
<h3>center</h3>
<div class="container">
<div class="test html">
<hr align="center" />
</div>
<div class="test css">
<hr style="margin-right:auto; margin-left:auto; text-align:center;" />
</div>
</div>
<h3>right</h3>
<div class="container">
<div class="test html">
<hr align="right" />
</div>
<div class="test css">
<hr style="margin-right:0; margin-left:auto; text-align:right;" />
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1,74 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML ChildAreas="4" xmlns:canvas><HEAD>
<META http-equiv=Content-Type content=text/html;charset=windows-1257>
<STYLE></STYLE>
<META content="MSHTML 6.00.6000.16414" name=GENERATOR></HEAD>
<BODY id=MailContainerBody
style="PADDING-RIGHT: 10px; PADDING-LEFT: 10px; FONT-SIZE: 10pt; COLOR: #000000; PADDING-TOP: 15px; FONT-FAMILY: Arial"
bgColor=#ff6600 leftMargin=0 background="" topMargin=0
name="Compose message area" acc_role="text" CanvasTabStop="false">
<DIV
style="BORDER-TOP: #dddddd 1px solid; FONT-SIZE: 10pt; WIDTH: 100%; MARGIN-RIGHT: 10px; PADDING-TOP: 5px; BORDER-BOTTOM: #dddddd 1px solid; FONT-FAMILY: Verdana; HEIGHT: 25px; BACKGROUND-COLOR: #ffffff"><NOBR><SPAN
title="View a slideshow of the pictures in this e-mail message."
style="PADDING-RIGHT: 20px"><A style="COLOR: #0088e4"
href="http://g.msn.com/5meen_us/171?path=/photomail/{6fc0065f-ffdd-4ca6-9a4c-cc5a93dc122f}&amp;image=47D7B182CFEFB10!127&amp;imagehi=47D7B182CFEFB10!125&amp;CID=323550092004883216">Play
slideshow </A></SPAN><SPAN style="COLOR: #909090"><SPAN>|</SPAN><SPAN
style="PADDING-LEFT: 20px"> Download the highest quality version of a picture by
clicking the + above it </SPAN></SPAN></NOBR></DIV>
<DIV
style="PADDING-RIGHT: 5px; PADDING-LEFT: 7px; PADDING-BOTTOM: 2px; WIDTH: 100%; PADDING-TOP: 2px">
<OL>
<LI><IMG title="Angry smile emoticon"
style="FLOAT: none; MARGIN: 0px; POSITION: static" tabIndex=-1
alt="Angry smile emoticon" src="cid:49F0C856199E4D688D2D740680733D74@wc"
MSNNonUserImageOrEmoticon="true">Un ka <FONT style="BACKGROUND-COLOR: #800000"
color=#cc99ff><STRONG>Tev</STRONG></FONT> iet, un ko tu dari?
<LI>Aha!</LI></OL>
<UL>
<LI>Buletets
<LI>
<DIV align=justify><A title=http://laacz.lv/blog/
href="http://laacz.lv/blog/">http://laacz.lv/blog/</A> un <A
title=http://google.com/ href="http://google.com/">gugle</A></DIV>
<LI>Sarakstucitis</LI></UL></DIV><SPAN><SPAN xmlns:canvas="canvas-namespace-id"
layoutEmptyTextWellFont="Tahoma"><SPAN
style="MARGIN-BOTTOM: 15px; OVERFLOW: visible; HEIGHT: 16px"></SPAN><SPAN
style="MARGIN-BOTTOM: 25px; VERTICAL-ALIGN: top; OVERFLOW: visible; MARGIN-RIGHT: 25px; HEIGHT: 234px">
<TABLE style="DISPLAY: inline">
<TBODY>
<TR>
<TD>
<DIV
style="FONT-WEIGHT: bold; FONT-SIZE: 12pt; FONT-FAMILY: arial; TEXT-ALIGN: center"><A
id=HiresARef
title="Click here to view or download a high resolution version of this picture"
style="COLOR: #0088e4; TEXT-DECORATION: none"
href="http://byfiles.storage.msn.com/x1pMvt0I80jTgT6DuaCpEMbprX3nk3jNv_vjigxV_EYVSMyM_PKgEvDEUtuNhQC-F-23mTTcKyqx6eGaeK2e_wMJ0ikwpDdFntk4SY7pfJUv2g2Ck6R2S2vAA?download">+</A></DIV>
<DIV
title="Click here to view the full image using the online photo viewer."
style="DISPLAY: inline; OVERFLOW: hidden; WIDTH: 140px; HEIGHT: 140px"><A
href="http://g.msn.com/5meen_us/171?path=/photomail/{6fc0065f-ffdd-4ca6-9a4c-cc5a93dc122f}&amp;image=47D7B182CFEFB10!127&amp;imagehi=47D7B182CFEFB10!125&amp;CID=323550092004883216"
border="0"><IMG
style="MARGIN-TOP: 15px; DISPLAY: inline-block; MARGIN-LEFT: 0px"
height=109 src="cid:006A71303B80404E9FB6184E55D6A446@wc" width=140
border=0></A></DIV></TD></TR>
<TR>
<TD>
<DIV
style="FONT-SIZE: 10pt; WIDTH: 140px; FONT-FAMILY: verdana; TEXT-ALIGN: center"><EM><STRONG>This
<U>is </U></STRONG><U>tit</U>le</EM> fo<STRONG>r <FONT
face="Arial Black">t<FONT color=#800000 size=7>h<U>i</U></FONT>s
</FONT>picture</STRONG></DIV></TD></TR></TBODY></TABLE></SPAN></SPAN></SPAN>
<DIV
style="PADDING-RIGHT: 5px; PADDING-LEFT: 7px; PADDING-BOTTOM: 2px; WIDTH: 100%; PADDING-TOP: 2px; HEIGHT: 50px">
<DIV>&nbsp;</DIV></DIV>
<DIV
style="BORDER-TOP: #dddddd 1px solid; FONT-SIZE: 10pt; MARGIN-BOTTOM: 10px; WIDTH: 100%; COLOR: #909090; MARGIN-RIGHT: 10px; PADDING-TOP: 9px; FONT-FAMILY: Verdana; HEIGHT: 42px; BACKGROUND-COLOR: #ffffff"><NOBR><SPAN
title="Join Windows Live to share photos using Windows Live Photo E-mail.">Online
pictures are available for 30 days. <A style="COLOR: #0088e4"
href="http://g.msn.com/5meen_us/175">Get Windows Live Mail desktop to create
your own photo e-mails. </A></SPAN></NOBR></DIV></BODY></HTML>

View File

@@ -22,7 +22,7 @@
*/ */
/* /*
HTML Purifier 1.6.1 - Standards Compliant HTML Filtering HTML Purifier 1.4.1 - Standards Compliant HTML Filtering
Copyright (C) 2006 Edward Z. Yang Copyright (C) 2006 Edward Z. Yang
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
@@ -64,7 +64,7 @@ require_once 'HTMLPurifier/Encoder.php';
class HTMLPurifier class HTMLPurifier
{ {
var $version = '1.6.1'; var $version = '1.4.1';
var $config; var $config;
var $filters; var $filters;

View File

@@ -5,9 +5,6 @@ require_once 'HTMLPurifier/AttrDef.php';
// Enum = Enumerated // Enum = Enumerated
/** /**
* Validates a keyword against a list of valid values. * Validates a keyword against a list of valid values.
* @warning The case-insensitive compare of this function uses PHP's
* built-in strtolower and ctype_lower functions, which may
* cause problems with international comparisons
*/ */
class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
{ {
@@ -37,7 +34,6 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
function validate($string, $config, &$context) { function validate($string, $config, &$context) {
$string = trim($string); $string = trim($string);
if (!$this->case_sensitive) { if (!$this->case_sensitive) {
// we may want to do full case-insensitive libraries
$string = ctype_lower($string) ? $string : strtolower($string); $string = ctype_lower($string) ? $string : strtolower($string);
} }
$result = isset($this->valid_values[$string]); $result = isset($this->valid_values[$string]);

View File

@@ -1,34 +0,0 @@
<?php
HTMLPurifier_ConfigSchema::define(
'Attr', 'AllowedFrameTargets', array(), 'lookup',
'Lookup table of all allowed link frame targets. Some commonly used '.
'link targets include _blank, _self, _parent and _top. Values should '.
'be lowercase, as validation will be done in a case-sensitive manner '.
'despite W3C\'s recommendation. XHTML 1.0 Strict does not permit '.
'the target attribute so this directive will have no effect in that '.
'doctype. XHTML 1.1 does not enable the Target module by default, you '.
'will have to manually enable it (see the module documentation for more details.)'
);
require_once 'HTMLPurifier/AttrDef/Enum.php';
/**
* Special-case enum attribute definition that lazy loads allowed frame targets
*/
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
{
var $valid_values = false; // uninitialized value
var $case_sensitive = false;
function HTMLPurifier_AttrDef_HTML_FrameTarget() {}
function validate($string, $config, &$context) {
if ($this->valid_values === false) $this->valid_values = $config->get('Attr', 'AllowedFrameTargets');
return parent::validate($string, $config, $context);
}
}
?>

View File

@@ -43,14 +43,6 @@ HTMLPurifier_ConfigSchema::define(
'is set to a non-empty value! This directive was available since 1.2.0.' 'is set to a non-empty value! This directive was available since 1.2.0.'
); );
HTMLPurifier_ConfigSchema::define(
'Attr', 'IDBlacklistRegexp', null, 'string/null',
'PCRE regular expression to be matched against all IDs. If the expression '.
'is matches, the ID is rejected. Use this with care: may cause '.
'significant degradation. ID matching is done after all other '.
'validation. This directive was available since 1.6.0.'
);
/** /**
* Validates the HTML attribute ID. * Validates the HTML attribute ID.
* @warning Even though this is the id processor, it * @warning Even though this is the id processor, it
@@ -102,11 +94,6 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
$result = ($trim === ''); $result = ($trim === '');
} }
$regexp = $config->get('Attr', 'IDBlacklistRegexp');
if ($regexp && preg_match($regexp, $id)) {
return false;
}
if (/*!$this->ref && */$result) $id_accumulator->add($id); if (/*!$this->ref && */$result) $id_accumulator->add($id);
// if no change was made to the ID, return the result // if no change was made to the ID, return the result

View File

@@ -1,75 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrDef.php';
HTMLPurifier_ConfigSchema::define(
'Attr', 'AllowedRel', array(), 'lookup',
'List of allowed forward document relationships in the rel attribute. '.
'Common values may be nofollow or print. By default, this is empty, '.
'meaning that no document relationships are allowed. This directive '.
'was available since 1.6.0.'
);
HTMLPurifier_ConfigSchema::define(
'Attr', 'AllowedRev', array(), 'lookup',
'List of allowed reverse document relationships in the rev attribute. '.
'This attribute is a bit of an edge-case; if you don\'t know what it '.
'is for, stay away. This directive was available since 1.6.0.'
);
/**
* Validates a rel/rev link attribute against a directive of allowed values
* @note We cannot use Enum because link types allow multiple
* values.
* @note Assumes link types are ASCII text
*/
class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
{
/** Lookup array of attribute names to configuration name */
var $configLookup = array(
'rel' => 'AllowedRel',
'rev' => 'AllowedRev'
);
/** Name config attribute to pull. */
var $name;
function HTMLPurifier_AttrDef_HTML_LinkTypes($name) {
if (!isset($this->configLookup[$name])) {
trigger_error('Unrecognized attribute name for link '.
'relationship.', E_USER_ERROR);
return;
}
$this->name = $this->configLookup[$name];
}
function validate($string, $config, &$context) {
$allowed = $config->get('Attr', $this->name);
if (empty($allowed)) return false;
$string = $this->parseCDATA($string);
$parts = explode(' ', $string);
// lookup to prevent duplicates
$ret_lookup = array();
foreach ($parts as $part) {
$part = strtolower(trim($part));
if (!isset($allowed[$part])) continue;
$ret_lookup[$part] = true;
}
if (empty($ret_lookup)) return false;
$ret_array = array();
foreach ($ret_lookup as $part => $bool) $ret_array[] = $part;
$string = implode(' ', $ret_array);
return $string;
}
}
?>

View File

@@ -29,30 +29,6 @@ class HTMLPurifier_AttrTransform
function transform($attr, $config, &$context) { function transform($attr, $config, &$context) {
trigger_error('Cannot call abstract function', E_USER_ERROR); trigger_error('Cannot call abstract function', E_USER_ERROR);
} }
/**
* Prepends CSS properties to the style attribute, creating the
* attribute if it doesn't exist.
* @param $attr Attribute array to process (passed by reference)
* @param $css CSS to prepend
*/
function prependCSS(&$attr, $css) {
$attr['style'] = isset($attr['style']) ? $attr['style'] : '';
$attr['style'] = $css . $attr['style'];
}
/**
* Retrieves and removes an attribute
* @param $attr Attribute array to process (passed by reference)
* @param $key Key of attribute to confiscate
*/
function confiscateAttr(&$attr, $key) {
if (!isset($attr[$key])) return null;
$value = $attr[$key];
unset($attr[$key]);
return $value;
}
} }
?> ?>

View File

@@ -1,26 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Pre-transform that changes deprecated bgcolor attribute to CSS.
*/
class HTMLPurifier_AttrTransform_BgColor
extends HTMLPurifier_AttrTransform {
function transform($attr, $config, &$context) {
if (!isset($attr['bgcolor'])) return $attr;
$bgcolor = $this->confiscateAttr($attr, 'bgcolor');
// some validation should happen here
$this->prependCSS($attr, "background-color:$bgcolor;");
return $attr;
}
}
?>

View File

@@ -1,39 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Pre-transform that changes converts a boolean attribute to fixed CSS
*/
class HTMLPurifier_AttrTransform_BoolToCSS
extends HTMLPurifier_AttrTransform {
/**
* Name of boolean attribute that is trigger
*/
var $attr;
/**
* CSS declarations to add to style, needs trailing semicolon
*/
var $css;
/**
* @param $attr string attribute name to convert from
* @param $css string CSS declarations to add to style (needs semicolon)
*/
function HTMLPurifier_AttrTransform_BoolToCSS($attr, $css) {
$this->attr = $attr;
$this->css = $css;
}
function transform($attr, $config, &$context) {
if (!isset($attr[$this->attr])) return $attr;
unset($attr[$this->attr]);
$this->prependCSS($attr, $this->css);
return $attr;
}
}
?>

View File

@@ -1,20 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Pre-transform that changes deprecated border attribute to CSS.
*/
class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform {
function transform($attr, $config, &$context) {
if (!isset($attr['border'])) return $attr;
$border_width = $this->confiscateAttr($attr, 'border');
// some validation should happen here
$this->prependCSS($attr, "border:{$border_width}px solid;");
return $attr;
}
}
?>

View File

@@ -1,60 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Generic pre-transform that converts an attribute with a fixed number of
* values (enumerated) to CSS.
*/
class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform {
/**
* Name of attribute to transform from
*/
var $attr;
/**
* Lookup array of attribute values to CSS
*/
var $enumToCSS = array();
/**
* Case sensitivity of the matching
* @warning Currently can only be guaranteed to work with ASCII
* values.
*/
var $caseSensitive = false;
/**
* @param $attr String attribute name to transform from
* @param $enumToCSS Lookup array of attribute values to CSS
* @param $case_sensitive Boolean case sensitivity indicator, default false
*/
function HTMLPurifier_AttrTransform_EnumToCSS($attr, $enum_to_css, $case_sensitive = false) {
$this->attr = $attr;
$this->enumToCSS = $enum_to_css;
$this->caseSensitive = (bool) $case_sensitive;
}
function transform($attr, $config, &$context) {
if (!isset($attr[$this->attr])) return $attr;
$value = trim($attr[$this->attr]);
unset($attr[$this->attr]);
if (!$this->caseSensitive) $value = strtolower($value);
if (!isset($this->enumToCSS[$value])) {
return $attr;
}
$this->prependCSS($attr, $this->enumToCSS[$value]);
return $attr;
}
}
?>

View File

@@ -1,47 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Pre-transform that changes deprecated hspace and vspace attributes to CSS
*/
class HTMLPurifier_AttrTransform_ImgSpace
extends HTMLPurifier_AttrTransform {
var $attr;
var $css = array(
'hspace' => array('left', 'right'),
'vspace' => array('top', 'bottom')
);
function HTMLPurifier_AttrTransform_ImgSpace($attr) {
$this->attr = $attr;
if (!isset($this->css[$attr])) {
trigger_error(htmlspecialchars($attr) . ' is not valid space attribute');
}
}
function transform($attr, $config, &$context) {
if (!isset($attr[$this->attr])) return $attr;
$width = $this->confiscateAttr($attr, $this->attr);
// some validation could happen here
if (!isset($this->css[$this->attr])) return $attr;
$style = '';
foreach ($this->css[$this->attr] as $suffix) {
$property = "margin-$suffix";
$style .= "$property:{$width}px;";
}
$this->prependCSS($attr, $style);
return $attr;
}
}
?>

View File

@@ -1,29 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Class for handling width/height length attribute transformations to CSS
*/
class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
{
var $name;
var $cssName;
function HTMLPurifier_AttrTransform_Length($name, $css_name = null) {
$this->name = $name;
$this->cssName = $css_name ? $css_name : $name;
}
function transform($attr, $config, &$context) {
if (!isset($attr[$this->name])) return $attr;
$length = $this->confiscateAttr($attr, $this->name);
if(ctype_digit($length)) $length .= 'px';
$this->prependCSS($attr, $this->cssName . ":$length;");
return $attr;
}
}
?>

View File

@@ -1,21 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Pre-transform that changes deprecated name attribute to ID if necessary
*/
class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
{
function transform($attr, $config, &$context) {
if (!isset($attr['name'])) return $attr;
$id = $this->confiscateAttr($attr, 'name');
if ( isset($attr['id'])) return $attr;
$attr['id'] = $id;
return $attr;
}
}
?>

View File

@@ -0,0 +1,36 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
/**
* Pre-transform that changes deprecated align attribute to text-align.
*/
class HTMLPurifier_AttrTransform_TextAlign
extends HTMLPurifier_AttrTransform {
function transform($attr, $config, &$context) {
if (!isset($attr['align'])) return $attr;
$align = strtolower(trim($attr['align']));
unset($attr['align']);
$values = array('left' => 1,
'right' => 1,
'center' => 1,
'justify' => 1);
if (!isset($values[$align])) {
return $attr;
}
$attr['style'] = isset($attr['style']) ? $attr['style'] : '';
$attr['style'] = "text-align:$align;" . $attr['style'];
return $attr;
}
}
?>

View File

@@ -162,9 +162,7 @@ class HTMLPurifier_CSSDefinition
new HTMLPurifier_AttrDef_CSS_Percentage() new HTMLPurifier_AttrDef_CSS_Percentage()
)); ));
$this->info['width'] = $this->info['width'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
$this->info['height'] =
new HTMLPurifier_AttrDef_CSS_Composite(array(
new HTMLPurifier_AttrDef_CSS_Length(true), new HTMLPurifier_AttrDef_CSS_Length(true),
new HTMLPurifier_AttrDef_CSS_Percentage(true), new HTMLPurifier_AttrDef_CSS_Percentage(true),
new HTMLPurifier_AttrDef_Enum(array('auto')) new HTMLPurifier_AttrDef_Enum(array('auto'))
@@ -206,9 +204,6 @@ class HTMLPurifier_CSSDefinition
new HTMLPurifier_AttrDef_CSS_Percentage() new HTMLPurifier_AttrDef_CSS_Percentage()
)); ));
// partial support
$this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
} }
} }

View File

@@ -334,10 +334,6 @@ class HTMLPurifier_ConfigSchema {
case 'hash': case 'hash':
case 'lookup': case 'lookup':
if (is_string($var)) { if (is_string($var)) {
// special case: technically, this is an array with
// a single empty string item, but having an empty
// array is more intuitive
if ($var == '') return array();
// simplistic string to array method that only works // simplistic string to array method that only works
// for simple lists of tag names or alphanumeric characters // for simple lists of tag names or alphanumeric characters
$var = explode(',',$var); $var = explode(',',$var);

View File

@@ -95,7 +95,7 @@ class HTMLPurifier_ElementDef
// later keys takes precedence // later keys takes precedence
foreach($def->attr as $k => $v) { foreach($def->attr as $k => $v) {
if ($k === 0) { if ($k == 0) {
// merge in the includes // merge in the includes
// sorry, no way to override an include // sorry, no way to override an include
foreach ($v as $v2) { foreach ($v as $v2) {

View File

@@ -1,290 +1,250 @@
<?php <?php
// components // components
require_once 'HTMLPurifier/HTMLModuleManager.php'; require_once 'HTMLPurifier/HTMLModuleManager.php';
// this definition and its modules MUST NOT define configuration directives // this definition and its modules MUST NOT define configuration directives
// outside of the HTML or Attr namespaces // outside of the HTML or Attr namespaces
// will be superceded by more accurate doctype declaration schemes // will be superceded by more accurate doctype declaration schemes
HTMLPurifier_ConfigSchema::define( HTMLPurifier_ConfigSchema::define(
'HTML', 'Strict', false, 'bool', 'HTML', 'Strict', false, 'bool',
'Determines whether or not to use Transitional (loose) or Strict rulesets. '. 'Determines whether or not to use Transitional (loose) or Strict rulesets. '.
'This directive has been available since 1.3.0.' 'This directive has been available since 1.3.0.'
); );
HTMLPurifier_ConfigSchema::define( HTMLPurifier_ConfigSchema::define(
'HTML', 'BlockWrapper', 'p', 'string', 'HTML', 'BlockWrapper', 'p', 'string',
'String name of element to wrap inline elements that are inside a block '. 'String name of element to wrap inline elements that are inside a block '.
'context. This only occurs in the children of blockquote in strict mode. '. 'context. This only occurs in the children of blockquote in strict mode. '.
'Example: by default value, <code>&lt;blockquote&gt;Foo&lt;/blockquote&gt;</code> '. 'Example: by default value, <code>&lt;blockquote&gt;Foo&lt;/blockquote&gt;</code> '.
'would become <code>&lt;blockquote&gt;&lt;p&gt;Foo&lt;/p&gt;&lt;/blockquote&gt;</code>. The '. 'would become <code>&lt;blockquote&gt;&lt;p&gt;Foo&lt;/p&gt;&lt;/blockquote&gt;</code>. The '.
'<code>&lt;p&gt;</code> tags can be replaced '. '<code>&lt;p&gt;</code> tags can be replaced '.
'with whatever you desire, as long as it is a block level element. '. 'with whatever you desire, as long as it is a block level element. '.
'This directive has been available since 1.3.0.' 'This directive has been available since 1.3.0.'
); );
HTMLPurifier_ConfigSchema::define( HTMLPurifier_ConfigSchema::define(
'HTML', 'Parent', 'div', 'string', 'HTML', 'Parent', 'div', 'string',
'String name of element that HTML fragment passed to library will be '. 'String name of element that HTML fragment passed to library will be '.
'inserted in. An interesting variation would be using span as the '. 'inserted in. An interesting variation would be using span as the '.
'parent element, meaning that only inline tags would be allowed. '. 'parent element, meaning that only inline tags would be allowed. '.
'This directive has been available since 1.3.0.' 'This directive has been available since 1.3.0.'
); );
HTMLPurifier_ConfigSchema::define( HTMLPurifier_ConfigSchema::define(
'HTML', 'AllowedElements', null, 'lookup/null', 'HTML', 'AllowedElements', null, 'lookup/null',
'If HTML Purifier\'s tag set is unsatisfactory for your needs, you '. 'If HTML Purifier\'s tag set is unsatisfactory for your needs, you '.
'can overload it with your own list of tags to allow. Note that this '. 'can overload it with your own list of tags to allow. Note that this '.
'method is subtractive: it does its job by taking away from HTML Purifier '. 'method is subtractive: it does its job by taking away from HTML Purifier '.
'usual feature set, so you cannot add a tag that HTML Purifier never '. 'usual feature set, so you cannot add a tag that HTML Purifier never '.
'supported in the first place (like embed, form or head). If you change this, you '. 'supported in the first place (like embed, form or head). If you change this, you '.
'probably also want to change %HTML.AllowedAttributes. '. 'probably also want to change %HTML.AllowedAttributes. '.
'<strong>Warning:</strong> If another directive conflicts with the '. '<strong>Warning:</strong> If another directive conflicts with the '.
'elements here, <em>that</em> directive will win and override. '. 'elements here, <em>that</em> directive will win and override. '.
'This directive has been available since 1.3.0.' 'This directive has been available since 1.3.0.'
); );
HTMLPurifier_ConfigSchema::define( HTMLPurifier_ConfigSchema::define(
'HTML', 'AllowedAttributes', null, 'lookup/null', 'HTML', 'AllowedAttributes', null, 'lookup/null',
'IF HTML Purifier\'s attribute set is unsatisfactory, overload it! '. 'IF HTML Purifier\'s attribute set is unsatisfactory, overload it! '.
'The syntax is \'tag.attr\' or \'*.attr\' for the global attributes '. 'The syntax is \'tag.attr\' or \'*.attr\' for the global attributes '.
'(style, id, class, dir, lang, xml:lang).'. '(style, id, class, dir, lang, xml:lang).'.
'<strong>Warning:</strong> If another directive conflicts with the '. '<strong>Warning:</strong> If another directive conflicts with the '.
'elements here, <em>that</em> directive will win and override. For '. 'elements here, <em>that</em> directive will win and override. For '.
'example, %HTML.EnableAttrID will take precedence over *.id in this '. 'example, %HTML.EnableAttrID will take precedence over *.id in this '.
'directive. You must set that directive to true before you can use '. 'directive. You must set that directive to true before you can use '.
'IDs at all. This directive has been available since 1.3.0.' 'IDs at all. This directive has been available since 1.3.0.'
); );
/** /**
* Definition of the purified HTML that describes allowed children, * Definition of the purified HTML that describes allowed children,
* attributes, and many other things. * attributes, and many other things.
* *
* Conventions: * Conventions:
* *
* All member variables that are prefixed with info * All member variables that are prefixed with info
* (including the main $info array) are used by HTML Purifier internals * (including the main $info array) are used by HTML Purifier internals
* and should not be directly edited when customizing the HTMLDefinition. * and should not be directly edited when customizing the HTMLDefinition.
* They can usually be set via configuration directives or custom * They can usually be set via configuration directives or custom
* modules. * modules.
* *
* On the other hand, member variables without the info prefix are used * On the other hand, member variables without the info prefix are used
* internally by the HTMLDefinition and MUST NOT be used by other HTML * internally by the HTMLDefinition and MUST NOT be used by other HTML
* Purifier internals. Many of them, however, are public, and may be * Purifier internals. Many of them, however, are public, and may be
* edited by userspace code to tweak the behavior of HTMLDefinition. * edited by userspace code to tweak the behavior of HTMLDefinition.
* *
* HTMLPurifier_Printer_HTMLDefinition is a notable exception to this * HTMLPurifier_Printer_HTMLDefinition is a notable exception to this
* rule: in the interest of comprehensiveness, it will sniff everything. * rule: in the interest of comprehensiveness, it will sniff everything.
*/ */
class HTMLPurifier_HTMLDefinition class HTMLPurifier_HTMLDefinition
{ {
/** FULLY-PUBLIC VARIABLES */ /** FULLY-PUBLIC VARIABLES */
/** /**
* Associative array of element names to HTMLPurifier_ElementDef * Associative array of element names to HTMLPurifier_ElementDef
* @public * @public
*/ */
var $info = array(); var $info = array();
/** /**
* Associative array of global attribute name to attribute definition. * Associative array of global attribute name to attribute definition.
* @public * @public
*/ */
var $info_global_attr = array(); var $info_global_attr = array();
/** /**
* String name of parent element HTML will be going into. * String name of parent element HTML will be going into.
* @public * @public
*/ */
var $info_parent = 'div'; var $info_parent = 'div';
/** /**
* Definition for parent element, allows parent element to be a * Definition for parent element, allows parent element to be a
* tag that's not allowed inside the HTML fragment. * tag that's not allowed inside the HTML fragment.
* @public * @public
*/ */
var $info_parent_def; var $info_parent_def;
/** /**
* String name of element used to wrap inline elements in block context * String name of element used to wrap inline elements in block context
* @note This is rarely used except for BLOCKQUOTEs in strict mode * @note This is rarely used except for BLOCKQUOTEs in strict mode
* @public * @public
*/ */
var $info_block_wrapper = 'p'; var $info_block_wrapper = 'p';
/** /**
* Associative array of deprecated tag name to HTMLPurifier_TagTransform * Associative array of deprecated tag name to HTMLPurifier_TagTransform
* @public * @public
*/ */
var $info_tag_transform = array(); var $info_tag_transform = array();
/** /**
* Indexed list of HTMLPurifier_AttrTransform to be performed before validation. * Indexed list of HTMLPurifier_AttrTransform to be performed before validation.
* @public * @public
*/ */
var $info_attr_transform_pre = array(); var $info_attr_transform_pre = array();
/** /**
* Indexed list of HTMLPurifier_AttrTransform to be performed after validation. * Indexed list of HTMLPurifier_AttrTransform to be performed after validation.
* @public * @public
*/ */
var $info_attr_transform_post = array(); var $info_attr_transform_post = array();
/** /**
* Nested lookup array of content set name (Block, Inline) to * Nested lookup array of content set name (Block, Inline) to
* element name to whether or not it belongs in that content set. * element name to whether or not it belongs in that content set.
* @public * @public
*/ */
var $info_content_sets = array(); var $info_content_sets = array();
/** PUBLIC BUT INTERNAL VARIABLES */ /** PUBLIC BUT INTERNAL VARIABLES */
var $setup = false; /**< Has setup() been called yet? */ var $setup = false; /**< Has setup() been called yet? */
var $config; /**< Temporary instance of HTMLPurifier_Config */ var $config; /**< Temporary instance of HTMLPurifier_Config */
var $manager; /**< Instance of HTMLPurifier_HTMLModuleManager */ var $manager; /**< Instance of HTMLPurifier_HTMLModuleManager */
/** /**
* Performs low-cost, preliminary initialization. * Performs low-cost, preliminary initialization.
* @param $config Instance of HTMLPurifier_Config * @param $config Instance of HTMLPurifier_Config
*/ */
function HTMLPurifier_HTMLDefinition(&$config) { function HTMLPurifier_HTMLDefinition(&$config) {
$this->config =& $config; $this->config =& $config;
$this->manager = new HTMLPurifier_HTMLModuleManager(); $this->manager = new HTMLPurifier_HTMLModuleManager();
} }
/** /**
* Processes internals into form usable by HTMLPurifier internals. * Processes internals into form usable by HTMLPurifier internals.
* Modifying the definition after calling this function should not * Modifying the definition after calling this function should not
* be done. * be done.
*/ */
function setup() { function setup() {
// multiple call guard // multiple call guard
if ($this->setup) {return;} else {$this->setup = true;} if ($this->setup) {return;} else {$this->setup = true;}
$this->processModules(); $this->processModules();
$this->setupConfigStuff(); $this->setupConfigStuff();
unset($this->config); unset($this->config);
unset($this->manager); unset($this->manager);
} }
/** /**
* Extract out the information from the manager * Extract out the information from the manager
*/ */
function processModules() { function processModules() {
$this->manager->setup($this->config); $this->manager->setup($this->config);
foreach ($this->manager->activeModules as $module) { foreach ($this->manager->activeModules as $module) {
foreach($module->info_tag_transform as $k => $v) { foreach($module->info_tag_transform as $k => $v) $this->info_tag_transform[$k] = $v;
if ($v === false) unset($this->info_tag_transform[$k]); foreach($module->info_attr_transform_pre as $k => $v) $this->info_attr_transform_pre[$k] = $v;
else $this->info_tag_transform[$k] = $v; foreach($module->info_attr_transform_post as $k => $v) $this->info_attr_transform_post[$k]= $v;
} }
foreach($module->info_attr_transform_pre as $k => $v) {
if ($v === false) unset($this->info_attr_transform_pre[$k]); $this->info = $this->manager->getElements($this->config);
else $this->info_attr_transform_pre[$k] = $v; $this->info_content_sets = $this->manager->contentSets->lookup;
}
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; /**
} * Sets up stuff based on config. We need a better way of doing this.
} */
function setupConfigStuff() {
$this->info = $this->manager->getElements($this->config);
$this->info_content_sets = $this->manager->contentSets->lookup; $block_wrapper = $this->config->get('HTML', 'BlockWrapper');
if (isset($this->info_content_sets['Block'][$block_wrapper])) {
} $this->info_block_wrapper = $block_wrapper;
} else {
/** trigger_error('Cannot use non-block element as block wrapper.',
* Sets up stuff based on config. We need a better way of doing this. E_USER_ERROR);
*/ }
function setupConfigStuff() {
$parent = $this->config->get('HTML', 'Parent');
$block_wrapper = $this->config->get('HTML', 'BlockWrapper'); $def = $this->manager->getElement($parent, $this->config);
if (isset($this->info_content_sets['Block'][$block_wrapper])) { if ($def) {
$this->info_block_wrapper = $block_wrapper; $this->info_parent = $parent;
} else { $this->info_parent_def = $def;
trigger_error('Cannot use non-block element as block wrapper.', } else {
E_USER_ERROR); trigger_error('Cannot use unrecognized element as parent.',
} E_USER_ERROR);
$this->info_parent_def = $this->manager->getElement(
$parent = $this->config->get('HTML', 'Parent'); $this->info_parent, $this->config);
$def = $this->manager->getElement($parent, $this->config); }
if ($def) {
$this->info_parent = $parent; // setup allowed elements, SubtractiveWhitelist module
$this->info_parent_def = $def; $allowed_elements = $this->config->get('HTML', 'AllowedElements');
} else { if (is_array($allowed_elements)) {
trigger_error('Cannot use unrecognized element as parent.', foreach ($this->info as $name => $d) {
E_USER_ERROR); if(!isset($allowed_elements[$name])) unset($this->info[$name]);
$this->info_parent_def = $this->manager->getElement( }
$this->info_parent, $this->config); }
} $allowed_attributes = $this->config->get('HTML', 'AllowedAttributes');
if (is_array($allowed_attributes)) {
// support template text foreach ($this->info_global_attr as $attr_key => $info) {
$support = "(for information on implementing this, see the ". if (!isset($allowed_attributes["*.$attr_key"])) {
"support forums) "; unset($this->info_global_attr[$attr_key]);
}
// setup allowed elements, SubtractiveWhitelist module }
$allowed_elements = $this->config->get('HTML', 'AllowedElements'); foreach ($this->info as $tag => $info) {
if (is_array($allowed_elements)) { foreach ($info->attr as $attr => $attr_info) {
foreach ($this->info as $name => $d) { if (!isset($allowed_attributes["$tag.$attr"]) &&
if(!isset($allowed_elements[$name])) unset($this->info[$name]); !isset($allowed_attributes["*.$attr"])) {
unset($allowed_elements[$name]); unset($this->info[$tag]->attr[$attr]);
} }
// emit errors }
foreach ($allowed_elements as $element => $d) { }
trigger_error("Element '$element' is not supported $support", E_USER_WARNING); }
}
} }
$allowed_attributes = $this->config->get('HTML', 'AllowedAttributes');
$allowed_attributes_mutable = $allowed_attributes; // by copy! }
if (is_array($allowed_attributes)) {
foreach ($this->info_global_attr as $attr_key => $info) { ?>
if (!isset($allowed_attributes["*.$attr_key"])) {
unset($this->info_global_attr[$attr_key]);
} elseif (isset($allowed_attributes_mutable["*.$attr_key"])) {
unset($allowed_attributes_mutable["*.$attr_key"]);
}
}
foreach ($this->info as $tag => $info) {
foreach ($info->attr as $attr => $attr_info) {
if (!isset($allowed_attributes["$tag.$attr"]) &&
!isset($allowed_attributes["*.$attr"])) {
unset($this->info[$tag]->attr[$attr]);
} else {
if (isset($allowed_attributes_mutable["$tag.$attr"])) {
unset($allowed_attributes_mutable["$tag.$attr"]);
} elseif (isset($allowed_attributes_mutable["*.$attr"])) {
unset($allowed_attributes_mutable["*.$attr"]);
}
}
}
}
// emit errors
foreach ($allowed_attributes_mutable as $elattr => $d) {
list($element, $attribute) = explode('.', $elattr);
if ($element == '*') {
trigger_error("Global attribute '$attribute' is not ".
"supported in any elements $support",
E_USER_WARNING);
} else {
trigger_error("Attribute '$attribute' in element '$element' not supported $support",
E_USER_WARNING);
}
}
}
}
}
?>

View File

@@ -12,6 +12,7 @@ class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule
var $name = 'Bdo'; var $name = 'Bdo';
var $elements = array('bdo'); var $elements = array('bdo');
var $info = array();
var $content_sets = array('Inline' => 'bdo'); var $content_sets = array('Inline' => 'bdo');
var $attr_collections = array( var $attr_collections = array(
'I18N' => array('dir' => false) 'I18N' => array('dir' => false)

View File

@@ -12,6 +12,7 @@ class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule
var $name = 'Edit'; var $name = 'Edit';
var $elements = array('del', 'ins'); var $elements = array('del', 'ins');
var $info = array();
var $content_sets = array('Inline' => 'del | ins'); var $content_sets = array('Inline' => 'del | ins');
function HTMLPurifier_HTMLModule_Edit() { function HTMLPurifier_HTMLModule_Edit() {

View File

@@ -1,7 +1,6 @@
<?php <?php
require_once 'HTMLPurifier/HTMLModule.php'; require_once 'HTMLPurifier/HTMLModule.php';
require_once 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
/** /**
* XHTML 1.1 Hypertext Module, defines hypertext links. Core Module. * XHTML 1.1 Hypertext Module, defines hypertext links. Core Module.
@@ -11,6 +10,7 @@ class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
var $name = 'Hypertext'; var $name = 'Hypertext';
var $elements = array('a'); var $elements = array('a');
var $info = array();
var $content_sets = array('Inline' => 'a'); var $content_sets = array('Inline' => 'a');
function HTMLPurifier_HTMLModule_Hypertext() { function HTMLPurifier_HTMLModule_Hypertext() {
@@ -21,8 +21,8 @@ class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
// 'charset' => 'Charset', // 'charset' => 'Charset',
'href' => 'URI', 'href' => 'URI',
//'hreflang' => 'LanguageCode', //'hreflang' => 'LanguageCode',
'rel' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rel'), //'rel' => 'LinkTypes',
'rev' => new HTMLPurifier_AttrDef_HTML_LinkTypes('rev'), //'rev' => 'LinkTypes',
//'tabindex' => 'Number', //'tabindex' => 'Number',
//'type' => 'ContentType', //'type' => 'ContentType',
); );

View File

@@ -15,6 +15,7 @@ class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
var $name = 'Image'; var $name = 'Image';
var $elements = array('img'); var $elements = array('img');
var $info = array();
var $content_sets = array('Inline' => 'img'); var $content_sets = array('Inline' => 'img');
function HTMLPurifier_HTMLModule_Image() { function HTMLPurifier_HTMLModule_Image() {

View File

@@ -10,7 +10,7 @@ class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule
var $name = 'List'; var $name = 'List';
var $elements = array('dl', 'dt', 'dd', 'ol', 'ul', 'li'); var $elements = array('dl', 'dt', 'dd', 'ol', 'ul', 'li');
var $info = array();
// According to the abstract schema, the List content set is a fully formed // According to the abstract schema, the List content set is a fully formed
// one or more expr, but it invariably occurs in an optional declaration // one or more expr, but it invariably occurs in an optional declaration
// so we're not going to do that subtlety. It might cause trouble // so we're not going to do that subtlety. It might cause trouble

View File

@@ -17,6 +17,7 @@ class HTMLPurifier_HTMLModule_Presentation extends HTMLPurifier_HTMLModule
var $name = 'Presentation'; var $name = 'Presentation';
var $elements = array('b', 'big', 'hr', 'i', 'small', 'sub', 'sup', 'tt'); var $elements = array('b', 'big', 'hr', 'i', 'small', 'sub', 'sup', 'tt');
var $info = array();
var $content_sets = array( var $content_sets = array(
'Block' => 'hr', 'Block' => 'hr',
'Inline' => 'b | big | i | small | sub | sup | tt' 'Inline' => 'b | big | i | small | sub | sup | tt'

View File

@@ -1,67 +0,0 @@
<?php
/*
WARNING: THIS MODULE IS EXTREMELY DANGEROUS AS IT ENABLES INLINE SCRIPTING
INSIDE HTML PURIFIER DOCUMENTS. USE ONLY WITH TRUSTED USER INPUT!!!
Usage:
require_once 'HTMLPurifier/HTMLModule/Scripting.php';
$def =& $config->getHTMLDefinition(true); // get the raw version
$def->manager->addModule('Scripting');
This must come before any other calls to getHTMLDefinition()
*/
/**
* Implements required attribute stipulation for <script>
*/
class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform
{
function transform($attr, $config, &$context) {
if (!isset($attr['type'])) {
$attr['type'] = 'text/javascript';
}
return $attr;
}
}
/**
* XHTML 1.1 Scripting module, defines elements that are used to contain
* information pertaining to executable scripts or the lack of support
* for executable scripts.
* @note This module does not contain inline scripting elements
*/
class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
{
var $name = 'Scripting';
var $elements = array('script', 'noscript');
var $content_sets = array('Block' => 'script | noscript', 'Inline' => 'script | noscript');
function HTMLPurifier_HTMLModule_Scripting() {
// TODO: create custom child-definition for noscript that
// auto-wraps stray #PCDATA in a similar manner to
// blockquote's custom definition (we would use it but
// blockquote's contents are optional while noscript's contents
// are required)
foreach ($this->elements as $element) {
$this->info[$element] = new HTMLPurifier_ElementDef();
}
$this->info['noscript']->attr = array( 0 => array('Common') );
$this->info['noscript']->content_model = 'Heading | List | Block';
$this->info['noscript']->content_model_type = 'required';
$this->info['script']->attr = array(
'defer' => new HTMLPurifier_AttrDef_Enum(array('defer')),
'src' => new HTMLPurifier_AttrDef_URI(true),
'type' => new HTMLPurifier_AttrDef_Enum(array('text/javascript'))
);
$this->info['script']->content_model = '#PCDATA';
$this->info['script']->content_model_type = 'optional';
$this->info['script']->attr_transform_post['type'] =
new HTMLPurifier_AttrTransform_ScriptRequired();
}
}
?>

View File

@@ -12,6 +12,7 @@ class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule
var $name = 'Tables'; var $name = 'Tables';
var $elements = array('caption', 'table', 'td', 'th', 'tr', 'col', var $elements = array('caption', 'table', 'td', 'th', 'tr', 'col',
'colgroup', 'tbody', 'thead', 'tfoot'); 'colgroup', 'tbody', 'thead', 'tfoot');
var $info = array();
var $content_sets = array('Block' => 'table'); var $content_sets = array('Block' => 'table');
function HTMLPurifier_HTMLModule_Tables() { function HTMLPurifier_HTMLModule_Tables() {

View File

@@ -1,26 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
/**
* XHTML 1.1 Target Module, defines target attribute in link elements.
*/
class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule
{
var $name = 'Target';
var $elements = array('a');
function HTMLPurifier_HTMLModule_Target() {
foreach ($this->elements as $e) {
$this->info[$e] = new HTMLPurifier_ElementDef();
$this->info[$e]->standalone = false;
$this->info[$e]->attr = array(
'target' => new HTMLPurifier_AttrDef_HTML_FrameTarget()
);
}
}
}
?>

View File

@@ -22,6 +22,8 @@ class HTMLPurifier_HTMLModule_Text extends HTMLPurifier_HTMLModule
'h4', 'h5', 'h6', 'kbd', 'p', 'pre', 'q', 'samp', 'span', 'strong', 'h4', 'h5', 'h6', 'kbd', 'p', 'pre', 'q', 'samp', 'span', 'strong',
'var'); 'var');
var $info = array();
var $content_sets = array( var $content_sets = array(
'Heading' => 'h1 | h2 | h3 | h4 | h5 | h6', 'Heading' => 'h1 | h2 | h3 | h4 | h5 | h6',
'Block' => 'address | blockquote | div | p | pre', 'Block' => 'address | blockquote | div | p | pre',

View File

@@ -7,13 +7,7 @@ require_once 'HTMLPurifier/TagTransform/Center.php';
require_once 'HTMLPurifier/TagTransform/Font.php'; require_once 'HTMLPurifier/TagTransform/Font.php';
require_once 'HTMLPurifier/AttrTransform/Lang.php'; require_once 'HTMLPurifier/AttrTransform/Lang.php';
require_once 'HTMLPurifier/AttrTransform/BgColor.php'; require_once 'HTMLPurifier/AttrTransform/TextAlign.php';
require_once 'HTMLPurifier/AttrTransform/BoolToCSS.php';
require_once 'HTMLPurifier/AttrTransform/Border.php';
require_once 'HTMLPurifier/AttrTransform/Name.php';
require_once 'HTMLPurifier/AttrTransform/Length.php';
require_once 'HTMLPurifier/AttrTransform/ImgSpace.php';
require_once 'HTMLPurifier/AttrTransform/EnumToCSS.php';
/** /**
* Proprietary module that transforms deprecated elements into Strict * Proprietary module that transforms deprecated elements into Strict
@@ -26,9 +20,7 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
var $name = 'TransformToStrict'; var $name = 'TransformToStrict';
// we're actually modifying these elements, not defining them // we're actually modifying these elements, not defining them
var $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', var $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'blockquote');
'blockquote', 'table', 'td', 'th', 'tr', 'img', 'a', 'hr', 'br',
'caption', 'ul', 'ol', 'li');
var $info_tag_transform = array( var $info_tag_transform = array(
// placeholders, see constructor for definitions // placeholders, see constructor for definitions
@@ -50,13 +42,6 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
function HTMLPurifier_HTMLModule_TransformToStrict() { function HTMLPurifier_HTMLModule_TransformToStrict() {
// behavior with transformations when there's another CSS property
// working on it is interesting: the CSS will *always* override
// the deprecated attribute, whereas an inline CSS declaration will
// override the corresponding declaration in, say, an external
// stylesheet. This behavior won't affect most people, but it
// does represent an operational difference we CANNOT fix.
// deprecated tag transforms // deprecated tag transforms
$this->info_tag_transform['font'] = new HTMLPurifier_TagTransform_Font(); $this->info_tag_transform['font'] = new HTMLPurifier_TagTransform_Font();
$this->info_tag_transform['menu'] = new HTMLPurifier_TagTransform_Simple('ul'); $this->info_tag_transform['menu'] = new HTMLPurifier_TagTransform_Simple('ul');
@@ -69,11 +54,6 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
} }
// deprecated attribute transforms // deprecated attribute transforms
// align battery
$align_lookup = array();
$align_values = array('left', 'right', 'center', 'justify');
foreach ($align_values as $v) $align_lookup[$v] = "text-align:$v;";
$this->info['h1']->attr_transform_pre['align'] = $this->info['h1']->attr_transform_pre['align'] =
$this->info['h2']->attr_transform_pre['align'] = $this->info['h2']->attr_transform_pre['align'] =
$this->info['h3']->attr_transform_pre['align'] = $this->info['h3']->attr_transform_pre['align'] =
@@ -81,7 +61,7 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
$this->info['h5']->attr_transform_pre['align'] = $this->info['h5']->attr_transform_pre['align'] =
$this->info['h6']->attr_transform_pre['align'] = $this->info['h6']->attr_transform_pre['align'] =
$this->info['p'] ->attr_transform_pre['align'] = $this->info['p'] ->attr_transform_pre['align'] =
new HTMLPurifier_AttrTransform_EnumToCSS('align', $align_lookup); new HTMLPurifier_AttrTransform_TextAlign();
// xml:lang <=> lang mirroring, implement in TransformToStrict, // xml:lang <=> lang mirroring, implement in TransformToStrict,
// this is overridden in TransformToXHTML11 // this is overridden in TransformToXHTML11
@@ -93,100 +73,6 @@ class HTMLPurifier_HTMLModule_TransformToStrict extends HTMLPurifier_HTMLModule
$this->info['blockquote']->content_model_type = 'strictblockquote'; $this->info['blockquote']->content_model_type = 'strictblockquote';
$this->info['blockquote']->child = false; // recalculate please! $this->info['blockquote']->child = false; // recalculate please!
$this->info['table']->attr_transform_pre['bgcolor'] =
$this->info['tr']->attr_transform_pre['bgcolor'] =
$this->info['td']->attr_transform_pre['bgcolor'] =
$this->info['th']->attr_transform_pre['bgcolor'] = new HTMLPurifier_AttrTransform_BgColor();
$this->info['img']->attr_transform_pre['border'] = new HTMLPurifier_AttrTransform_Border();
$this->info['img']->attr_transform_pre['name'] =
$this->info['a']->attr_transform_pre['name'] = new HTMLPurifier_AttrTransform_Name();
$this->info['td']->attr_transform_pre['width'] =
$this->info['th']->attr_transform_pre['width'] =
$this->info['hr']->attr_transform_pre['width'] = new HTMLPurifier_AttrTransform_Length('width');
$this->info['td']->attr_transform_pre['nowrap'] =
$this->info['th']->attr_transform_pre['nowrap'] = new HTMLPurifier_AttrTransform_BoolToCSS('nowrap', 'white-space:nowrap;');
$this->info['td']->attr_transform_pre['height'] =
$this->info['th']->attr_transform_pre['height'] = new HTMLPurifier_AttrTransform_Length('height');
$this->info['img']->attr_transform_pre['hspace'] = new HTMLPurifier_AttrTransform_ImgSpace('hspace');
$this->info['img']->attr_transform_pre['vspace'] = new HTMLPurifier_AttrTransform_ImgSpace('vspace');
$this->info['hr']->attr_transform_pre['size'] = new HTMLPurifier_AttrTransform_Length('size', 'height');
// this transformation is not precise but often good enough.
// different browsers use different styles to designate noshade
$this->info['hr']->attr_transform_pre['noshade'] = new HTMLPurifier_AttrTransform_BoolToCSS('noshade', 'color:#808080;background-color:#808080;border: 0;');
$this->info['br']->attr_transform_pre['clear'] =
new HTMLPurifier_AttrTransform_EnumToCSS('clear', array(
'left' => 'clear:left;',
'right' => 'clear:right;',
'all' => 'clear:both;',
'none' => 'clear:none;',
));
// this is a slightly unreasonable attribute
$this->info['caption']->attr_transform_pre['align'] =
new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
// we're following IE's behavior, not Firefox's, due
// to the fact that no one supports caption-side:right,
// W3C included (with CSS 2.1)
'left' => 'text-align:left;',
'right' => 'text-align:right;',
'top' => 'caption-side:top;',
'bottom' => 'caption-side:bottom;' // not supported by IE
));
$this->info['table']->attr_transform_pre['align'] =
new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'left' => 'float:left;',
'center' => 'margin-left:auto;margin-right:auto;',
'right' => 'float:right;'
));
$this->info['img']->attr_transform_pre['align'] =
new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'left' => 'float:left;',
'right' => 'float:right;',
'top' => 'vertical-align:top;',
'middle' => 'vertical-align:middle;',
'bottom' => 'vertical-align:baseline;',
));
$this->info['hr']->attr_transform_pre['align'] =
new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'left' => 'margin-left:0;margin-right:auto;text-align:left;',
'center' => 'margin-left:auto;margin-right:auto;text-align:center;',
'right' => 'margin-left:auto;margin-right:0;text-align:right;'
));
$ul_types = array(
'disc' => 'list-style-type:disc;',
'square' => 'list-style-type:square;',
'circle' => 'list-style-type:circle;'
);
$ol_types = array(
'1' => 'list-style-type:decimal;',
'i' => 'list-style-type:lower-roman;',
'I' => 'list-style-type:upper-roman;',
'a' => 'list-style-type:lower-alpha;',
'A' => 'list-style-type:upper-alpha;'
);
$li_types = $ul_types + $ol_types;
$this->info['ul']->attr_transform_pre['type'] =
new HTMLPurifier_AttrTransform_EnumToCSS('type', $ul_types);
$this->info['ol']->attr_transform_pre['type'] =
new HTMLPurifier_AttrTransform_EnumToCSS('type', $ol_types, true);
$this->info['li']->attr_transform_pre['type'] =
new HTMLPurifier_AttrTransform_EnumToCSS('type', $li_types, true);
} }
var $defines_child_def = true; var $defines_child_def = true;

View File

@@ -1,7 +1,5 @@
<?php <?php
require_once 'HTMLPurifier/AttrTransform/Lang.php';
/** /**
* Proprietary module that transforms XHTML 1.0 deprecated aspects into * Proprietary module that transforms XHTML 1.0 deprecated aspects into
* XHTML 1.1 compliant ones, when possible. For maximum effectiveness, * XHTML 1.1 compliant ones, when possible. For maximum effectiveness,
@@ -27,10 +25,6 @@ class HTMLPurifier_HTMLModule_TransformToXHTML11 extends HTMLPurifier_HTMLModule
'lang' => false // remove it 'lang' => false // remove it
); );
function HTMLPurifier_HTMLModule_TransformToXHTML11() {
$this->info_attr_transform_pre['lang'] = new HTMLPurifier_AttrTransform_Lang();
}
} }
?> ?>

View File

@@ -22,7 +22,6 @@ require_once 'HTMLPurifier/HTMLModule/Tables.php';
require_once 'HTMLPurifier/HTMLModule/Image.php'; require_once 'HTMLPurifier/HTMLModule/Image.php';
require_once 'HTMLPurifier/HTMLModule/StyleAttribute.php'; require_once 'HTMLPurifier/HTMLModule/StyleAttribute.php';
require_once 'HTMLPurifier/HTMLModule/Legacy.php'; require_once 'HTMLPurifier/HTMLModule/Legacy.php';
require_once 'HTMLPurifier/HTMLModule/Target.php';
// proprietary modules // proprietary modules
require_once 'HTMLPurifier/HTMLModule/TransformToStrict.php'; require_once 'HTMLPurifier/HTMLModule/TransformToStrict.php';
@@ -135,7 +134,6 @@ class HTMLPurifier_HTMLModuleManager
'CommonAttributes', 'CommonAttributes',
'Text', 'Hypertext', 'List', 'Presentation', 'Text', 'Hypertext', 'List', 'Presentation',
'Edit', 'Bdo', 'Tables', 'Image', 'StyleAttribute', 'Edit', 'Bdo', 'Tables', 'Image', 'StyleAttribute',
'Target',
// define-redefine // define-redefine
'Legacy', 'Legacy',
// redefine // redefine
@@ -157,7 +155,7 @@ class HTMLPurifier_HTMLModuleManager
'HTML 4.01 Transitional' => array(array('XHTML 1.0 Transitional')), 'HTML 4.01 Transitional' => array(array('XHTML 1.0 Transitional')),
'HTML 4.01 Strict' => array(array('XHTML 1.0 Strict')), 'HTML 4.01 Strict' => array(array('XHTML 1.0 Strict')),
// XHTML definitions // XHTML definitions
'XHTML 1.0 Transitional' => array( array('XHTML 1.0 Strict'), 'Legacy', 'Target' ), 'XHTML 1.0 Transitional' => array( array('XHTML 1.0 Strict'), 'Legacy' ),
'XHTML 1.0 Strict' => array(array('_Common')), 'XHTML 1.0 Strict' => array(array('_Common')),
'XHTML 1.1' => array(array('_Common')), 'XHTML 1.1' => array(array('_Common')),
); );
@@ -208,35 +206,20 @@ class HTMLPurifier_HTMLModuleManager
* @param $module Mixed: string module name, with or without * @param $module Mixed: string module name, with or without
* HTMLPurifier_HTMLModule prefix, or instance of * HTMLPurifier_HTMLModule prefix, or instance of
* subclass of HTMLPurifier_HTMLModule. * subclass of HTMLPurifier_HTMLModule.
* @note This function will not call autoload, you must instantiate
* (and thus invoke) autoload outside the method.
* @note If a string is passed as a module name, different variants
* will be tested in this order:
* - Check for HTMLPurifier_HTMLModule_$name
* - Check all prefixes with $name in order they were added
* - Check for literal object name
* - Throw fatal error
* If your object name collides with an internal class, specify
* your module manually.
*/ */
function addModule($module) { function addModule($module) {
if (is_string($module)) { if (is_string($module)) {
$original_module = $module; $original_module = $module;
$ok = false; if (!class_exists($module)) {
foreach ($this->prefixes as $prefix) { foreach ($this->prefixes as $prefix) {
$module = $prefix . $original_module; $module = $prefix . $original_module;
if ($this->_classExists($module)) { if (class_exists($module)) break;
$ok = true;
break;
} }
} }
if (!$ok) { if (!class_exists($module)) {
$module = $original_module; trigger_error($original_module . ' module does not exist',
if (!$this->_classExists($module)) { E_USER_ERROR);
trigger_error($original_module . ' module does not exist', return;
E_USER_ERROR);
return;
}
} }
$module = new $module(); $module = new $module();
} }
@@ -247,23 +230,6 @@ class HTMLPurifier_HTMLModuleManager
} }
} }
/**
* Safely tests for class existence without invoking __autoload in PHP5
* @param $name String class name to test
* @private
*/
function _classExists($name) {
static $is_php_4 = null;
if ($is_php_4 === null) {
$is_php_4 = version_compare(PHP_VERSION, '5', '<');
}
if ($is_php_4) {
return class_exists($name);
} else {
return class_exists($name, false);
}
}
/** /**
* Makes a collection active, while also making it valid if not * Makes a collection active, while also making it valid if not
* already done so. See $activeModules for the semantics of "active". * already done so. See $activeModules for the semantics of "active".
@@ -525,8 +491,7 @@ class HTMLPurifier_HTMLModuleManager
$elements = array(); $elements = array();
foreach ($this->activeModules as $module) { foreach ($this->activeModules as $module) {
foreach ($module->info as $name => $v) { foreach ($module->elements as $name) {
if (isset($elements[$name])) continue;
$elements[$name] = $this->getElement($name, $config); $elements[$name] = $this->getElement($name, $config);
} }
} }
@@ -590,4 +555,4 @@ class HTMLPurifier_HTMLModuleManager
} }
?> ?>

View File

@@ -110,23 +110,6 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
continue; continue;
} }
// Check leading character is alnum, if not, we may
// have accidently grabbed an emoticon. Translate into
// text and go our merry way
if (!ctype_alnum($segment[0])) {
$array[] = new
HTMLPurifier_Token_Text(
'<' .
$this->parseData(
$segment
) .
'>'
);
$cursor = $position_next_gt + 1;
$inside_tag = false;
continue;
}
// Check if it is explicitly self closing, if so, remove // Check if it is explicitly self closing, if so, remove
// trailing slash. Remember, we could have a tag like <br>, so // trailing slash. Remember, we could have a tag like <br>, so
// any later token processing scripts must convert improperly // any later token processing scripts must convert improperly

View File

@@ -29,7 +29,6 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
$generator = new HTMLPurifier_Generator(); $generator = new HTMLPurifier_Generator();
$result = array(); $result = array();
$escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags'); $escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
$remove_invalid_img = $config->get('Core', 'RemoveInvalidImg');
foreach($tokens as $token) { foreach($tokens as $token) {
if (!empty( $token->is_tag )) { if (!empty( $token->is_tag )) {
// DEFINITION CALL // DEFINITION CALL
@@ -38,7 +37,7 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
// hard-coded image special case, pre-emptively drop // hard-coded image special case, pre-emptively drop
// if not available. Probably not abstract-able // if not available. Probably not abstract-able
if ( $token->name == 'img' && $remove_invalid_img ) { if ( $token->name == 'img' ) {
if (!isset($token->attr['src'])) { if (!isset($token->attr['src'])) {
continue; continue;
} }

View File

@@ -20,7 +20,6 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
var $transform_to = 'span'; var $transform_to = 'span';
var $_size_lookup = array( var $_size_lookup = array(
'0' => 'xx-small',
'1' => 'xx-small', '1' => 'xx-small',
'2' => 'small', '2' => 'small',
'3' => 'medium', '3' => 'medium',
@@ -29,10 +28,9 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
'6' => 'xx-large', '6' => 'xx-large',
'7' => '300%', '7' => '300%',
'-1' => 'smaller', '-1' => 'smaller',
'-2' => '60%',
'+1' => 'larger', '+1' => 'larger',
'-2' => '60%',
'+2' => '150%', '+2' => '150%',
'+3' => '200%',
'+4' => '300%' '+4' => '300%'
); );
@@ -60,15 +58,6 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
// handle size transform // handle size transform
if (isset($attr['size'])) { if (isset($attr['size'])) {
// normalize large numbers
if ($attr['size']{0} == '+' || $attr['size']{0} == '-') {
$size = (int) $attr['size'];
if ($size < -2) $attr['size'] = '-2';
if ($size > 4) $attr['size'] = '+4';
} else {
$size = (int) $attr['size'];
if ($size > 7) $attr['size'] = '7';
}
if (isset($this->_size_lookup[$attr['size']])) { if (isset($this->_size_lookup[$attr['size']])) {
$prepend_style .= 'font-size:' . $prepend_style .= 'font-size:' .
$this->_size_lookup[$attr['size']] . ';'; $this->_size_lookup[$attr['size']] . ';';

View File

@@ -1,56 +0,0 @@
<?php
set_time_limit(0);
require_once 'PEAR/PackageFileManager2.php';
PEAR::setErrorHandling(PEAR_ERROR_PRINT);
$pkg = new PEAR_PackageFileManager2;
$pkg->setOptions(
array(
'baseinstalldir' => '/',
'packagefile' => 'package2.xml',
'packagedirectory' => dirname(__FILE__) . '/library',
'filelistgenerator' => 'file',
'include' => array('*'),
'dir_roles' => array('/' => 'php'), // hack to put .ser in the right place
'ignore' => array('HTMLPurifier.auto.php'),
)
);
$pkg->setPackage('HTMLPurifier');
$pkg->setLicense('LGPL', 'http://www.gnu.org/licenses/lgpl.html');
$pkg->setSummary('Standards-compliant HTML filter');
$pkg->setDescription(
'HTML Purifier is an HTML filter that will remove all malicious code
(better known as XSS) with a thoroughly audited, secure yet permissive
whitelist and will also make sure your documents are standards
compliant.'
);
$pkg->addMaintainer('lead', 'ezyang', 'Edward Z. Yang', 'admin@htmlpurifier.org', 'yes');
$version = file_get_contents('VERSION');
$api_version = substr($version, 0, strrpos($version, '.'));
$pkg->setChannel('htmlpurifier.org');
$pkg->setAPIVersion($api_version);
$pkg->setAPIStability('stable');
$pkg->setReleaseVersion($version);
$pkg->setReleaseStability('stable');
$pkg->addRelease();
$pkg->setNotes(file_get_contents('WHATSNEW'));
$pkg->setPackageType('php');
$pkg->setPhpDep('4.3.9');
$pkg->setPearinstallerDep('1.4.3');
$pkg->generateContents();
$compat =& $pkg->exportCompatiblePackageFile1();
$compat->writePackageFile();
$pkg->writePackageFile();
?>

View File

@@ -1,82 +0,0 @@
<?php
// release script
// PHP 5.0 only
if (php_sapi_name() != 'cli') {
echo 'Release script cannot be called from web-browser.';
exit;
}
if (!isset($argv[1])) {
echo
'php release.php [version]
HTML Purifier release script
';
exit;
}
$version = trim($argv[1]);
// Bump version numbers:
// ...in VERSION
file_put_contents('VERSION', $version);
// ...in NEWS
$date = date('Y-m-d');
$news_c = str_replace(
$l = "$version, unknown release date",
"$version, released $date",
file_get_contents('NEWS'),
$c
);
if (!$c) {
echo 'Could not update NEWS, missing ' . $l . PHP_EOL;
exit;
} elseif ($c > 1) {
echo 'More than one release declaration in NEWS replaced' . PHP_EOL;
exit;
}
file_put_contents('NEWS', $news_c);
// ...in Doxyfile
$doxyfile_c = preg_replace(
'/(?<=PROJECT_NUMBER {9}= )[^\s]+/m', // brittle
$version,
file_get_contents('Doxyfile'),
1, $c
);
if (!$c) {
echo 'Could not update Doxyfile, missing PROJECT_NUMBER.' . PHP_EOL;
exit;
}
file_put_contents('Doxyfile', $doxyfile_c);
// ...in HTMLPurifier.php
$htmlpurifier_c = file_get_contents('library/HTMLPurifier.php');
$htmlpurifier_c = preg_replace(
'/HTML Purifier .+? - /',
"HTML Purifier $version - ",
$htmlpurifier_c,
1, $c
);
if (!$c) {
echo 'Could not update HTMLPurifier.php, missing HTML Purifier [version] header.' . PHP_EOL;
exit;
}
$htmlpurifier_c = preg_replace(
'/var \$version = \'.+?\';/',
"var \$version = '$version';",
$htmlpurifier_c,
1, $c
);
if (!$c) {
echo 'Could not update HTMLPurifier.php, missing var $version.' . PHP_EOL;
exit;
}
file_put_contents('library/HTMLPurifier.php', $htmlpurifier_c);
echo "Review changes, write something in WHATSNEW, and then SVN commit with log 'Release $version.'" . PHP_EOL;
?>

View File

@@ -1,68 +0,0 @@
<?php
require 'common.php';
?><!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>HTML Purifier Attribute Transformation Smoketest</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
div.container {position:relative;height:120px;border:1px solid #CCC;
margin-bottom:1em; width:225px; float:left; margin-top:1em;
margin-right:1em;}
h2 {clear:left;margin-bottom:0;}
div.container.legend .test {text-align:center;line-height:100px;}
div.test {width:100px;height:100px;border:1px solid black;
position:absolute;top:10px;overflow:auto;}
div.test.html {left:10px;border-right:none;background:#FCC;}
div.test.css {left:110px;background:#CFC;}
img.marked {border:1px solid #000;background:#FFF;}
table.bright {background-color:#F00;}
hr.short {width:50px;}
</style>
</head>
<body>
<h1>HTML Purifier Attribute Transformation Smoketest</h1>
<div class="container legend">
<div class="test html">
HTML
</div>
<div class="test css">
CSS
</div>
</div>
<?php
if (version_compare(PHP_VERSION, '5', '<')) exit('<p>Requires PHP 5.</p>');
$xml = simplexml_load_file('attrTransform.xml');
// attr transform enabled HTML Purifier
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
$title = isset($_GET['title']) ? $_GET['title'] : true;
foreach ($xml->group as $group) {
echo '<h2>' . $group['title'] . '</h2>';
foreach ($group->sample as $sample) {
$sample = (string) $sample;
?>
<div class="container">
<div class="test html">
<?php echo $sample; ?>
</div>
<div class="test css">
<?php echo $purifier->purify($sample); ?>
</div>
</div>
<?php
}
}
?>
</body>
</html>

View File

@@ -1,189 +0,0 @@
<?xml version="1.0"?>
<samples>
<group title="menu,dir">
<sample><![CDATA[<menu><li>menu</li></menu>]]></sample>
<sample><![CDATA[<dir><li>dir</li></dir>]]></sample>
</group>
<group title="font">
<sample><![CDATA[<font color="red">Red</font>]]></sample>
<sample><![CDATA[<font color="#0000FF">#0000FF</font>]]></sample>
<sample><![CDATA[<font face="Arial">Arial</font>]]></sample>
</group>
<group title="font.size">
<sample><![CDATA[<font size="-2">-2</font>]]></sample>
<sample><![CDATA[<font size="-1">-1</font>]]></sample>
<sample><![CDATA[<font size="0">0</font>]]></sample>
<sample><![CDATA[<font size="1">1</font>]]></sample>
<sample><![CDATA[<font size="2">2</font>]]></sample>
<sample><![CDATA[<font size="3">3</font>]]></sample>
<sample><![CDATA[<font size="4">4</font>]]></sample>
<sample><![CDATA[<font size="5">5</font>]]></sample>
<sample><![CDATA[<font size="6">6</font>]]></sample>
<sample><![CDATA[<font size="7">7</font>]]></sample>
<sample><![CDATA[<font size="8">8</font>]]></sample>
<sample><![CDATA[<font size="+1">+1</font>]]></sample>
<sample><![CDATA[<font size="+2">+2</font>]]></sample>
<sample><![CDATA[<font size="+3">+3</font>]]></sample>
<sample><![CDATA[<font size="+4">+4</font>]]></sample>
<sample><![CDATA[<font size="+5">+5</font>]]></sample>
</group>
<group title="center">
<sample><![CDATA[<center>Centered</center>]]></sample>
</group>
<group title="p.align">
<sample><![CDATA[<p align="left">Left</p>]]></sample>
<sample><![CDATA[<p align="center">Center</p>]]></sample>
<sample><![CDATA[<p align="right">Right</p>]]></sample>
</group>
<group title="table.bgcolor">
<sample><![CDATA[
<table bgcolor="black" cellspacing="2" cellpadding="2" border="1">
<tr bgcolor="red">
<th bgcolor="green">To</th>
<td bgcolor="blue">Be</td>
</tr>
<tr>
<th bgcolor="green">Or</th>
<td>Not</td>
</tr>
<tr bgcolor="red">
<th>To</th>
<td>Be</td>
</tr>
</table>
]]></sample>
<sample><![CDATA[
<table class="bright" bgcolor="black" cellspacing="2" cellpadding="2" border="1">
<tr>
<th bgcolor="green">Or</th>
<td>Not</td>
</tr>
<tr bgcolor="blue">
<th bgcolor="green">To</th>
<td>Be</td>
</tr>
</table>
]]></sample>
</group>
<group title="img.border">
<sample><![CDATA[<img src="img.png" alt="I" border="2" />]]></sample>
<sample><![CDATA[<a href="http://example.com/"><img src="img.png" alt="I" border="2" /></a>]]></sample>
</group>
<group title="td,th,hr.width">
<sample><![CDATA[
<table border="1">
<tr>
<th width="20">x1</th>
<td width="40">x2</td>
</tr>
</table>
]]></sample>
<sample><![CDATA[
<table border="1">
<tr>
<th width="33%">x1</th>
<td width="67%">x2</td>
</tr>
</table>
]]></sample>
<sample><![CDATA[<hr width="70%" /><hr width="30" />]]></sample>
</group>
<group title="td,th.nowrap">
<sample><![CDATA[
<table border="1">
<tr>
<th>This wants to wrap</th>
<td>really badly yes it does</td>
</tr>
</table>
]]></sample>
<sample><![CDATA[
<table border="1">
<tr>
<th nowrap>This wants to wrap</th>
<td nowrap>really badly yes it does</td>
</tr>
</table>
]]></sample>
</group>
<group title="td,th.height">
<sample><![CDATA[<table border="1"><tr><td height="60">tall</td></tr></table>]]></sample>
</group>
<group title="img.vspace,hspace">
<sample><![CDATA[a<img src="img.png" alt="I" class="marked" hspace="7" />a]]></sample>
<sample><![CDATA[<img src="img.png" alt="I" class="marked" vspace="7" /><br />o]]></sample>
</group>
<group title="hr">
<sample><![CDATA[<hr size="4" />]]></sample>
<sample><![CDATA[<hr size="50" noshade />]]></sample>
</group>
<group title="br.clear">
<sample><![CDATA[<img src="img.png" alt="I" align="right" />B<br />A]]></sample>
<sample><![CDATA[<img src="img.png" alt="I" align="right" />B<br clear="right" />A]]></sample>
<sample><![CDATA[<img src="img.png" alt="I" align="right" /><img src="img.png" alt="I" align="left" />B<br />A]]></sample>
<sample><![CDATA[<img src="img.png" alt="I" align="right" /><img src="img.png" alt="I" align="left" />B<br clear="all" />A]]></sample>
</group>
<group title="caption.align">
<sample><![CDATA[
<table border="1">
<caption align="left">Left</caption>
<tr><td>1.1</td><td>1.2</td></tr>
</table>
]]></sample>
<sample><![CDATA[
<table border="1">
<caption align="right">Right</caption>
<tr><td>1.1</td><td>1.2</td></tr>
</table>
]]></sample>
<sample><![CDATA[
<table border="1">
<caption align="top">Top</caption>
<tr><td>1.1</td><td>1.2</td></tr>
</table>
]]></sample>
<sample><![CDATA[
<table border="1">
<caption align="bottom">Bottom</caption>
<tr><td>1.1</td><td>1.2</td></tr>
</table>
]]></sample>
</group>
<group title="img.align">
<sample><![CDATA[left<img src="img.png" alt="I" class="marked" align="left" />]]></sample>
<sample><![CDATA[right<img src="img.png" alt="I" class="marked" align="right" />]]></sample>
<sample><![CDATA[o<img src="img.png" alt="I" class="marked" align="top" /> top]]></sample>
<sample><![CDATA[o<img src="img.png" alt="I" class="marked" align="bottom" /> bottom]]></sample>
<sample><![CDATA[o<img src="img.png" alt="I" class="marked" align="middle" /> middle]]></sample>
</group>
<group title="table.align">
<sample><![CDATA[a<table align="left" class="bright"><tr><td>left</td></tr></table>a]]></sample>
<sample><![CDATA[a<table align="center" class="bright"><tr><td>center</td></tr></table>a]]></sample>
<sample><![CDATA[a<table align="right" class="bright"><tr><td>right</td></tr></table>a]]></sample>
</group>
<group title="hr.align">
<sample><![CDATA[<hr align="left" class="short" />left]]></sample>
<sample><![CDATA[<hr align="center" class="short" />center]]></sample>
<sample><![CDATA[<hr align="right" class="short" />right]]></sample>
</group>
<group title="ul,ol,li.type">
<sample><![CDATA[<ul type="disc"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ul type="square"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ul type="circle"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ol type="a"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ol type="A"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ol type="i"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ol type="I"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ol type="1"><li>1</li><li>2</li></ul>]]></sample>
<sample><![CDATA[<ol><li type="a">1</li><li type="I">2</li></ul>]]></sample>
</group>
<!-- sample
<group title="">
<sample><![CDATA[]]></sample>
<sample><![CDATA[]]></sample>
<sample><![CDATA[]]></sample>
</group>
-->
</samples>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -105,7 +105,7 @@ transformation into a real array list or a lookup table).</p>
?> ?>
<tr> <tr>
<th> <th>
<a href="http://htmlpurifier.org/live/configdoc/plain.html#<?php echo $directive ?>"> <a href="http://hp.jpsband.org/live/configdoc/plain.html#<?php echo $directive ?>">
<label for="<?php echo $directive; ?>">%<?php echo $directive; ?></label> <label for="<?php echo $directive; ?>">%<?php echo $directive; ?></label>
</a> </a>
</th> </th>

View File

@@ -40,8 +40,8 @@ class HTMLPurifier_AttrDef_CSS_CompositeTest extends HTMLPurifier_AttrDefHarness
$def1->setReturnValue('validate', $output, $def1_params); $def1->setReturnValue('validate', $output, $def1_params);
$def2->expectNever('validate'); $def2->expectNever('validate');
$result = $def->validate($input, $config, $context); $this->assertIdentical($output,
$this->assertIdentical($output, $result); $def->validate($input, $config, $context));
$def1->tally(); $def1->tally();
$def2->tally(); $def2->tally();
@@ -60,8 +60,8 @@ class HTMLPurifier_AttrDef_CSS_CompositeTest extends HTMLPurifier_AttrDefHarness
$def2->expectOnce('validate', $def_params); $def2->expectOnce('validate', $def_params);
$def2->setReturnValue('validate', $output, $def_params); $def2->setReturnValue('validate', $output, $def_params);
$result = $def->validate($input, $config, $context); $this->assertIdentical($output,
$this->assertIdentical($output, $result); $def->validate($input, $config, $context));
$def1->tally(); $def1->tally();
$def2->tally(); $def2->tally();
@@ -80,8 +80,8 @@ class HTMLPurifier_AttrDef_CSS_CompositeTest extends HTMLPurifier_AttrDefHarness
$def2->expectOnce('validate', $def_params); $def2->expectOnce('validate', $def_params);
$def2->setReturnValue('validate', false, $def_params); $def2->setReturnValue('validate', false, $def_params);
$result = $def->validate($input, $config, $context); $this->assertIdentical($output,
$this->assertIdentical($output, $result); $def->validate($input, $config, $context));
$def1->tally(); $def1->tally();
$def2->tally(); $def2->tally();

View File

@@ -1,31 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrDefHarness.php';
require_once 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
class HTMLPurifier_AttrDef_HTML_FrameTargetTest extends HTMLPurifier_AttrDefHarness
{
function setup() {
parent::setup();
$this->def = new HTMLPurifier_AttrDef_HTML_FrameTarget();
}
function testNoneAllowed() {
$this->assertDef('', false);
$this->assertDef('foo', false);
$this->assertDef('_blank', false);
$this->assertDef('baz', false);
}
function test() {
$this->config->set('Attr', 'AllowedFrameTargets', 'foo,_blank');
$this->assertDef('', false);
$this->assertDef('foo');
$this->assertDef('_blank');
$this->assertDef('baz', false);
}
}
?>

View File

@@ -95,15 +95,6 @@ class HTMLPurifier_AttrDef_HTML_IDTest extends HTMLPurifier_AttrDefHarness
} }
function testRegexp() {
$this->config->set('Attr', 'IDBlacklistRegexp', '/^g_/');
$this->assertDef('good_id');
$this->assertDef('g_bad_id', false);
}
} }
?> ?>

View File

@@ -1,24 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrDefHarness.php';
require_once 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
class HTMLPurifier_AttrDef_HTML_LinkTypesTest extends HTMLPurifier_AttrDefHarness
{
function testNull() {
$this->def = new HTMLPurifier_AttrDef_HTML_LinkTypes('rel');
$this->config->set('Attr', 'AllowedRel', array('nofollow', 'foo'));
$this->assertDef('', false);
$this->assertDef('nofollow', true);
$this->assertDef('nofollow foo', true);
$this->assertDef('nofollow bar', 'nofollow');
$this->assertDef('bar', false);
}
}
?>

View File

@@ -9,11 +9,11 @@ class HTMLPurifier_AttrDefTest extends UnitTestCase
$def = new HTMLPurifier_AttrDef(); $def = new HTMLPurifier_AttrDef();
$this->assertIdentical('', $def->parseCDATA('')); $this->assertEqual('', $def->parseCDATA(''));
$this->assertIdentical('', $def->parseCDATA("\t\n\r \t\t")); $this->assertEqual('', $def->parseCDATA("\t\n\r \t\t"));
$this->assertIdentical('foo', $def->parseCDATA("\t\n\r foo\t\t")); $this->assertEqual('foo', $def->parseCDATA("\t\n\r foo\t\t"));
$this->assertIdentical('ignorelinefeeds', $def->parseCDATA("ignore\nline\nfeeds")); $this->assertEqual('ignorelinefeeds', $def->parseCDATA("ignore\nline\nfeeds"));
$this->assertIdentical('translate to space', $def->parseCDATA("translate\rto\tspace")); $this->assertEqual('translate to space', $def->parseCDATA("translate\rto\tspace"));
} }

View File

@@ -1,43 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform/BgColor.php';
require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_BgColorTest extends HTMLPurifier_AttrTransformHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_BgColor();
}
function test() {
$this->assertResult( array() );
// we currently rely on the CSS validator to fix any problems.
// This means that this transform, strictly speaking, supports
// a superset of the functionality.
$this->assertResult(
array('bgcolor' => '#000000'),
array('style' => 'background-color:#000000;')
);
$this->assertResult(
array('bgcolor' => '#000000', 'style' => 'font-weight:bold'),
array('style' => 'background-color:#000000;font-weight:bold')
);
// this may change when we natively support the datatype and
// validate its contents before forwarding it on
$this->assertResult(
array('bgcolor' => '#F00'),
array('style' => 'background-color:#F00;')
);
}
}
?>

View File

@@ -1,39 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform/BoolToCSS.php';
require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_BoolToCSSTest extends HTMLPurifier_AttrTransformHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_BoolToCSS('foo', 'bar:3in;');
}
function test() {
$this->assertResult( array() );
$this->assertResult(
array('foo' => 'foo'),
array('style' => 'bar:3in;')
);
// boolean attribute just has to be set: we don't care about
// anything else
$this->assertResult(
array('foo' => 'no'),
array('style' => 'bar:3in;')
);
$this->assertResult(
array('foo' => 'foo', 'style' => 'background-color:#F00;'),
array('style' => 'bar:3in;background-color:#F00;')
);
}
}
?>

View File

@@ -1,40 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform/Border.php';
require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_BorderTest extends HTMLPurifier_AttrTransformHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_Border();
}
function test() {
$this->assertResult( array() );
$this->assertResult(
array('border' => '1'),
array('style' => 'border:1px solid;')
);
// once again, no validation done here, we expect CSS validator
// to catch it
$this->assertResult(
array('border' => '10%'),
array('style' => 'border:10%px solid;')
);
$this->assertResult(
array('border' => '23', 'style' => 'font-weight:bold;'),
array('style' => 'border:23px solid;font-weight:bold;')
);
}
}
?>

View File

@@ -34,7 +34,7 @@ class HTMLPurifier_AttrTransform_ImgRequiredTest extends HTMLPurifier_AttrTransf
$this->assertResult( $this->assertResult(
array('alt' => 'intrigue'), array('alt' => 'intrigue'),
array('alt' => 'intrigue', 'src' => '') array('src' => '', 'alt' => 'intrigue')
); );
} }

View File

@@ -1,57 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform/ImgSpace.php';
require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_ImgSpaceTest extends HTMLPurifier_AttrTransformHarness
{
function setUp() {
parent::setUp();
}
function testVertical() {
$this->obj = new HTMLPurifier_AttrTransform_ImgSpace('vspace');
$this->assertResult( array() );
$this->assertResult(
array('vspace' => '1'),
array('style' => 'margin-top:1px;margin-bottom:1px;')
);
// no validation done here, we expect CSS validator to catch it
$this->assertResult(
array('vspace' => '10%'),
array('style' => 'margin-top:10%px;margin-bottom:10%px;')
);
$this->assertResult(
array('vspace' => '23', 'style' => 'font-weight:bold;'),
array('style' => 'margin-top:23px;margin-bottom:23px;font-weight:bold;')
);
}
function testHorizontal() {
$this->obj = new HTMLPurifier_AttrTransform_ImgSpace('hspace');
$this->assertResult(
array('hspace' => '1'),
array('style' => 'margin-left:1px;margin-right:1px;')
);
}
function testInvalid() {
$this->expectError('ispace is not valid space attribute');
$this->obj = new HTMLPurifier_AttrTransform_ImgSpace('ispace');
$this->assertResult(
array('ispace' => '1'),
array()
);
}
}
?>

View File

@@ -33,7 +33,7 @@ class HTMLPurifier_AttrTransform_LangTest
// copy xml:lang to lang // copy xml:lang to lang
$this->assertResult( $this->assertResult(
array('xml:lang' => 'en'), array('xml:lang' => 'en'),
array('xml:lang' => 'en', 'lang' => 'en') array('lang' => 'en', 'xml:lang' => 'en')
); );
// both set, override lang with xml:lang // both set, override lang with xml:lang

View File

@@ -1,37 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform/Length.php';
require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_LengthTest extends HTMLPurifier_AttrTransformHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_Length('width');
}
function test() {
$this->assertResult( array() );
$this->assertResult(
array('width' => '10'),
array('style' => 'width:10px;')
);
$this->assertResult(
array('width' => '10%'),
array('style' => 'width:10%;')
);
$this->assertResult(
array('width' => '10%', 'style' => 'font-weight:bold'),
array('style' => 'width:10%;font-weight:bold')
);
// this behavior might change
$this->assertResult(
array('width' => 'asdf'),
array('style' => 'width:asdf;')
);
}
}
?>

View File

@@ -1,28 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform/Name.php';
require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_NameTest extends HTMLPurifier_AttrTransformHarness
{
function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_Name();
}
function test() {
$this->assertResult( array() );
$this->assertResult(
array('name' => 'free'),
array('id' => 'free')
);
$this->assertResult(
array('name' => 'tryit', 'id' => 'tobad'),
array('id' => 'tobad')
);
}
}
?>

View File

@@ -1,17 +1,17 @@
<?php <?php
require_once 'HTMLPurifier/AttrTransform/EnumToCSS.php'; require_once 'HTMLPurifier/AttrTransform/TextAlign.php';
require_once 'HTMLPurifier/AttrTransformHarness.php'; require_once 'HTMLPurifier/AttrTransformHarness.php';
class HTMLPurifier_AttrTransform_EnumToCSSTest extends HTMLPurifier_AttrTransformHarness class HTMLPurifier_AttrTransform_TextAlignTest extends HTMLPurifier_AttrTransformHarness
{ {
function testRegular() { function setUp() {
parent::setUp();
$this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array( $this->obj = new HTMLPurifier_AttrTransform_TextAlign();
'left' => 'text-align:left;', }
'right' => 'text-align:right;'
)); function test() {
// leave empty arrays alone // leave empty arrays alone
$this->assertResult( array() ); $this->assertResult( array() );
@@ -31,6 +31,16 @@ class HTMLPurifier_AttrTransform_EnumToCSSTest extends HTMLPurifier_AttrTransfor
array('style' => 'text-align:right;') array('style' => 'text-align:right;')
); );
$this->assertResult(
array('align' => 'center'),
array('style' => 'text-align:center;')
);
$this->assertResult(
array('align' => 'justify'),
array('style' => 'text-align:justify;')
);
// drop garbage value // drop garbage value
$this->assertResult( $this->assertResult(
array('align' => 'invalid'), array('align' => 'invalid'),
@@ -43,32 +53,10 @@ class HTMLPurifier_AttrTransform_EnumToCSSTest extends HTMLPurifier_AttrTransfor
array('style' => 'text-align:left;font-weight:bold;') array('style' => 'text-align:left;font-weight:bold;')
); );
}
function testCaseInsensitive() {
$this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'right' => 'text-align:right;'
));
// test case insensitivity // test case insensitivity
$this->assertResult( $this->assertResult(
array('align' => 'RIGHT'), array('align' => 'CENTER'),
array('style' => 'text-align:right;') array('style' => 'text-align:center;')
);
}
function testCaseSensitive() {
$this->obj = new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
'right' => 'text-align:right;'
), true);
// test case insensitivity
$this->assertResult(
array('align' => 'RIGHT'),
array()
); );
} }

View File

@@ -1,42 +0,0 @@
<?php
require_once 'HTMLPurifier/AttrTransform.php';
class HTMLPurifier_AttrTransformTest extends UnitTestCase
{
function test_prependCSS() {
$t = new HTMLPurifier_AttrTransform();
$attr = array();
$t->prependCSS($attr, 'style:new;');
$this->assertIdentical(array('style' => 'style:new;'), $attr);
$attr = array('style' => 'style:original;');
$t->prependCSS($attr, 'style:new;');
$this->assertIdentical(array('style' => 'style:new;style:original;'), $attr);
$attr = array('style' => 'style:original;', 'misc' => 'un-related');
$t->prependCSS($attr, 'style:new;');
$this->assertIdentical(array('style' => 'style:new;style:original;', 'misc' => 'un-related'), $attr);
}
function test_confiscateAttr() {
$t = new HTMLPurifier_AttrTransform();
$attr = array('flavor' => 'sweet');
$this->assertIdentical('sweet', $t->confiscateAttr($attr, 'flavor'));
$this->assertIdentical(array(), $attr);
$attr = array('flavor' => 'sweet');
$this->assertIdentical(null, $t->confiscateAttr($attr, 'color'));
$this->assertIdentical(array('flavor' => 'sweet'), $attr);
}
}
?>

View File

@@ -9,7 +9,7 @@ class HTMLPurifier_ChildDef_RequiredTest extends HTMLPurifier_ChildDefHarness
function testParsing() { function testParsing() {
$def = new HTMLPurifier_ChildDef_Required('foobar | bang |gizmo'); $def = new HTMLPurifier_ChildDef_Required('foobar | bang |gizmo');
$this->assertIdentical($def->elements, $this->assertEqual($def->elements,
array( array(
'foobar' => true 'foobar' => true
,'bang' => true ,'bang' => true
@@ -17,7 +17,7 @@ class HTMLPurifier_ChildDef_RequiredTest extends HTMLPurifier_ChildDefHarness
)); ));
$def = new HTMLPurifier_ChildDef_Required(array('href', 'src')); $def = new HTMLPurifier_ChildDef_Required(array('href', 'src'));
$this->assertIdentical($def->elements, $this->assertEqual($def->elements,
array( array(
'href' => true 'href' => true
,'src' => true ,'src' => true

View File

@@ -277,17 +277,14 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
$this->assertValid(array('1', '2', '3'), 'list'); $this->assertValid(array('1', '2', '3'), 'list');
$this->assertValid('foo,bar, cow', 'list', array('foo', 'bar', 'cow')); $this->assertValid('foo,bar, cow', 'list', array('foo', 'bar', 'cow'));
$this->assertValid('', 'list', array());
$this->assertValid(array('1' => true, '2' => true), 'lookup'); $this->assertValid(array('1' => true, '2' => true), 'lookup');
$this->assertValid(array('1', '2'), 'lookup', array('1' => true, '2' => true)); $this->assertValid(array('1', '2'), 'lookup', array('1' => true, '2' => true));
$this->assertValid('foo,bar', 'lookup', array('foo' => true, 'bar' => true)); $this->assertValid('foo,bar', 'lookup', array('foo' => true, 'bar' => true));
$this->assertValid('', 'lookup', array());
$this->assertValid(array('foo' => 'bar'), 'hash'); $this->assertValid(array('foo' => 'bar'), 'hash');
$this->assertValid(array(1 => 'moo'), 'hash'); $this->assertValid(array(1 => 'moo'), 'hash');
$this->assertInvalid(array(0 => 'moo'), 'hash'); $this->assertInvalid(array(0 => 'moo'), 'hash');
$this->assertValid('', 'hash', array());
$this->assertValid(23, 'mixed'); $this->assertValid(23, 'mixed');

View File

@@ -164,13 +164,13 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$this->assertIdentical($config->get('Home', 'Rug'), 3); $this->assertEqual($config->get('Home', 'Rug'), 3);
$this->expectError('Cannot get value from aliased directive, use real name'); $this->expectError('Cannot get value from aliased directive, use real name');
$config->get('Home', 'Carpet'); $config->get('Home', 'Carpet');
$config->set('Home', 'Carpet', 999); $config->set('Home', 'Carpet', 999);
$this->assertIdentical($config->get('Home', 'Rug'), 999); $this->assertEqual($config->get('Home', 'Rug'), 999);
} }
@@ -231,7 +231,7 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
$def = $config->getHTMLDefinition(); $def = $config->getHTMLDefinition();
$def2 = $config->getHTMLDefinition(); $def2 = $config->getHTMLDefinition();
$this->assertIsA($def, 'HTMLPurifier_HTMLDefinition'); $this->assertIsA($def, 'HTMLPurifier_HTMLDefinition');
$this->assertIdentical($def, $def2); $this->assertEqual($def, $def2);
$this->assertTrue($def->setup); $this->assertTrue($def->setup);
// test re-calculation if HTML changes // test re-calculation if HTML changes
@@ -298,8 +298,8 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
) )
)); ));
$this->assertIdentical($config_manual, $config_loadabbr); $this->assertEqual($config_manual, $config_loadabbr);
$this->assertIdentical($config_manual, $config_loadfull); $this->assertEqual($config_manual, $config_loadfull);
} }
@@ -314,15 +314,15 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
// test flat pass-through // test flat pass-through
$created_config = HTMLPurifier_Config::create($config); $created_config = HTMLPurifier_Config::create($config);
$this->assertIdentical($config, $created_config); $this->assertEqual($config, $created_config);
// test loadArray // test loadArray
$created_config = HTMLPurifier_Config::create(array('Cake.Sprinkles' => 42)); $created_config = HTMLPurifier_Config::create(array('Cake.Sprinkles' => 42));
$this->assertIdentical($config, $created_config); $this->assertEqual($config, $created_config);
// test loadIni // test loadIni
$created_config = HTMLPurifier_Config::create(dirname(__FILE__) . '/ConfigTest-create.ini'); $created_config = HTMLPurifier_Config::create(dirname(__FILE__) . '/ConfigTest-create.ini');
$this->assertIdentical($config, $created_config); $this->assertEqual($config, $created_config);
} }

View File

@@ -61,7 +61,7 @@ class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness
foreach ($inputs as $i => $input) { foreach ($inputs as $i => $input) {
$result = $this->obj->generateFromToken($input); $result = $this->obj->generateFromToken($input);
$this->assertIdentical($result, $expect[$i]); $this->assertEqual($result, $expect[$i]);
paintIf($result, $result != $expect[$i]); paintIf($result, $result != $expect[$i]);
} }
@@ -90,7 +90,7 @@ class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness
foreach ($inputs as $i => $input) { foreach ($inputs as $i => $input) {
$result = $this->obj->generateAttributes($input); $result = $this->obj->generateAttributes($input);
$this->assertIdentical($result, $expect[$i]); $this->assertEqual($result, $expect[$i]);
paintIf($result, $result != $expect[$i]); paintIf($result, $result != $expect[$i]);
} }
@@ -121,7 +121,7 @@ class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness
// normalized newlines, this probably should be put somewhere else // normalized newlines, this probably should be put somewhere else
$result = str_replace("\r\n", "\n", $result); $result = str_replace("\r\n", "\n", $result);
$result = str_replace("\r", "\n", $result); $result = str_replace("\r", "\n", $result);
$this->assertIdentical($expect, $result); $this->assertEqual($expect, $result);
} }
function test_generateFromTokens_XHTMLoff() { function test_generateFromTokens_XHTMLoff() {

View File

@@ -48,15 +48,15 @@ class HTMLPurifier_HTMLModuleManagerTest extends UnitTestCase
$this->manager->addModule($module); $this->manager->addModule($module);
$module_order = $this->manager->modules['Module']->order; $module_order = $this->manager->modules['Module']->order;
$module->order = $module_order; $module->order = $module_order;
$this->assertIdentical($module, $this->manager->modules['Module']); $this->assertEqual($module, $this->manager->modules['Module']);
$this->manager->addModule($module2); $this->manager->addModule($module2);
$module2_order = $this->manager->modules['Module2']->order; $module2_order = $this->manager->modules['Module2']->order;
$module2->order = $module2_order; $module2->order = $module2_order;
$this->assertIdentical($module2, $this->manager->modules['Module2']); $this->assertEqual($module2, $this->manager->modules['Module2']);
$this->assertIdentical($module_order + 1, $module2_order); $this->assertEqual($module_order + 1, $module2_order);
$this->assertIdentical( $this->assertEqual(
$this->manager->collections['Default']['Generic Document 0.1'], $this->manager->collections['Default']['Generic Document 0.1'],
array('Module', 'Module2') array('Module', 'Module2')
); );

View File

@@ -97,7 +97,7 @@ class HTMLPurifier_Harness extends UnitTestCase
} }
} }
$this->assertIdentical($expect, $result); $this->assertEqual($expect, $result);
} }

View File

@@ -12,10 +12,10 @@ class HTMLPurifier_LanguageFactoryTest extends UnitTestCase
$language = $factory->create('en'); $language = $factory->create('en');
$this->assertIsA($language, 'HTMLPurifier_Language'); $this->assertIsA($language, 'HTMLPurifier_Language');
$this->assertIdentical($language->code, 'en'); $this->assertEqual($language->code, 'en');
// lazy loading test // lazy loading test
$this->assertIdentical(count($language->messages), 0); $this->assertEqual(count($language->messages), 0);
$language->load(); $language->load();
$this->assertNotEqual(count($language->messages), 0); $this->assertNotEqual(count($language->messages), 0);
@@ -30,15 +30,15 @@ class HTMLPurifier_LanguageFactoryTest extends UnitTestCase
$language = $factory->create('en-x-test'); $language = $factory->create('en-x-test');
$this->assertIsA($language, 'HTMLPurifier_Language_en_x_test'); $this->assertIsA($language, 'HTMLPurifier_Language_en_x_test');
$this->assertIdentical($language->code, 'en-x-test'); $this->assertEqual($language->code, 'en-x-test');
$language->load(); $language->load();
// test overloaded message // test overloaded message
$this->assertIdentical($language->getMessage('htmlpurifier'), 'HTML Purifier X'); $this->assertEqual($language->getMessage('htmlpurifier'), 'HTML Purifier X');
// test inherited message // test inherited message
$this->assertIdentical($language->getMessage('pizza'), 'Pizza'); $this->assertEqual($language->getMessage('pizza'), 'Pizza');
} }

View File

@@ -58,7 +58,7 @@ class HTMLPurifier_Lexer_DirectLexTest extends UnitTestCase
$size = count($input); $size = count($input);
for($i = 0; $i < $size; $i++) { for($i = 0; $i < $size; $i++) {
$result = $this->DirectLex->parseAttributeString($input[$i], $config, $context); $result = $this->DirectLex->parseAttributeString($input[$i], $config, $context);
$this->assertIdentical($expect[$i], $result, 'Test ' . $i . ': %s'); $this->assertEqual($expect[$i], $result, 'Test ' . $i . ': %s');
paintIf($result, $expect[$i] != $result); paintIf($result, $expect[$i] != $result);
} }

View File

@@ -280,25 +280,13 @@ class HTMLPurifier_LexerTest extends UnitTestCase
$input[18] = '<br test="x &lt; 6" />'; $input[18] = '<br test="x &lt; 6" />';
$expect[18] = array( new HTMLPurifier_Token_Empty('br', array('test' => 'x < 6')) ); $expect[18] = array( new HTMLPurifier_Token_Empty('br', array('test' => 'x < 6')) );
// test emoticon protection
$input[19] = '<b>Whoa! >.< That\'s not good >.></b>';
$expect[19] = array(
new HTMLPurifier_Token_Start('b'),
new HTMLPurifier_Token_Text('Whoa! >.'),
new HTMLPurifier_Token_Text('< That\'s not good >'),
new HTMLPurifier_Token_Text('.>'),
new HTMLPurifier_Token_End('b'),
);
$sax_expect[19] = false; // SAX drops the < character
$dom_expect[19] = false; // DOM drops the entire pseudo-tag
$default_config = HTMLPurifier_Config::createDefault(); $default_config = HTMLPurifier_Config::createDefault();
$default_context = new HTMLPurifier_Context(); $default_context = new HTMLPurifier_Context();
foreach($input as $i => $discard) { foreach($input as $i => $discard) {
if (!isset($config[$i])) $config[$i] = $default_config; if (!isset($config[$i])) $config[$i] = $default_config;
$result = $this->DirectLex->tokenizeHTML($input[$i], $config[$i], $default_context); $result = $this->DirectLex->tokenizeHTML($input[$i], $config[$i], $default_context);
$this->assertIdentical($expect[$i], $result, 'DirectLexTest '.$i.': %s'); $this->assertEqual($expect[$i], $result, 'DirectLexTest '.$i.': %s');
paintIf($result, $expect[$i] != $result); paintIf($result, $expect[$i] != $result);
if ($this->_has_pear) { if ($this->_has_pear) {
@@ -306,14 +294,14 @@ class HTMLPurifier_LexerTest extends UnitTestCase
$sax_result = $this->PEARSax3->tokenizeHTML($input[$i], $config[$i], $default_context); $sax_result = $this->PEARSax3->tokenizeHTML($input[$i], $config[$i], $default_context);
if (!isset($sax_expect[$i])) { if (!isset($sax_expect[$i])) {
// by default, assert with normal result // by default, assert with normal result
$this->assertIdentical($expect[$i], $sax_result, 'PEARSax3Test '.$i.': %s'); $this->assertEqual($expect[$i], $sax_result, 'PEARSax3Test '.$i.': %s');
paintIf($sax_result, $expect[$i] != $sax_result); paintIf($sax_result, $expect[$i] != $sax_result);
} elseif ($sax_expect[$i] === false) { } elseif ($sax_expect[$i] === false) {
// assertions were turned off, optionally dump // assertions were turned off, optionally dump
// paintIf($sax_expect, $i == NUMBER); // paintIf($sax_expect, $i == NUMBER);
} else { } else {
// match with a custom SAX result array // match with a custom SAX result array
$this->assertIdentical($sax_expect[$i], $sax_result, 'PEARSax3Test (custom) '.$i.': %s'); $this->assertEqual($sax_expect[$i], $sax_result, 'PEARSax3Test (custom) '.$i.': %s');
paintIf($sax_result, $sax_expect[$i] != $sax_result); paintIf($sax_result, $sax_expect[$i] != $sax_result);
} }
} }
@@ -322,12 +310,12 @@ class HTMLPurifier_LexerTest extends UnitTestCase
$dom_result = $this->DOMLex->tokenizeHTML($input[$i], $config[$i], $default_context); $dom_result = $this->DOMLex->tokenizeHTML($input[$i], $config[$i], $default_context);
// same structure as SAX // same structure as SAX
if (!isset($dom_expect[$i])) { if (!isset($dom_expect[$i])) {
$this->assertIdentical($expect[$i], $dom_result, 'DOMLexTest '.$i.': %s'); $this->assertEqual($expect[$i], $dom_result, 'DOMLexTest '.$i.': %s');
paintIf($dom_result, $expect[$i] != $dom_result); paintIf($dom_result, $expect[$i] != $dom_result);
} elseif ($dom_expect[$i] === false) { } elseif ($dom_expect[$i] === false) {
// paintIf($dom_result, $i == NUMBER); // paintIf($dom_result, $i == NUMBER);
} else { } else {
$this->assertIdentical($dom_expect[$i], $dom_result, 'DOMLexTest (custom) '.$i.': %s'); $this->assertEqual($dom_expect[$i], $dom_result, 'DOMLexTest (custom) '.$i.': %s');
paintIf($dom_result, $dom_expect[$i] != $dom_result); paintIf($dom_result, $dom_expect[$i] != $dom_result);
} }
} }

View File

@@ -15,7 +15,7 @@ class HTMLPurifier_PercentEncoderTest extends UnitTestCase
function assertDecode($string, $expect = true) { function assertDecode($string, $expect = true) {
if ($expect === true) $expect = $string; if ($expect === true) $expect = $string;
$this->assertIdentical($this->PercentEncoder->{$this->func}($string), $expect); $this->assertEqual($this->PercentEncoder->{$this->func}($string), $expect);
} }
function test_normalize() { function test_normalize() {

View File

@@ -51,15 +51,6 @@ class HTMLPurifier_Strategy_RemoveForeignElementsTest
// test preservation of valid img tag // test preservation of valid img tag
$this->assertResult('<img src="foobar.gif" />'); $this->assertResult('<img src="foobar.gif" />');
// test preservation of invalid img tag when removal is disabled
$this->assertResult(
'<img />',
true,
array(
'Core.RemoveInvalidImg' => false
)
);
} }
} }

View File

@@ -13,11 +13,14 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
$this->obj = new HTMLPurifier_Strategy_ValidateAttributes(); $this->obj = new HTMLPurifier_Strategy_ValidateAttributes();
} }
function testEmpty() { function test() {
// attribute order is VERY fragile, perhaps we should define
// an ordering scheme!
$this->assertResult(''); $this->assertResult('');
}
// test ids
function testIDs() {
$this->assertResult( $this->assertResult(
'<div id="valid">Kill the ID.</div>', '<div id="valid">Kill the ID.</div>',
'<div>Kill the ID.</div>' '<div>Kill the ID.</div>'
@@ -68,68 +71,32 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
) )
); );
// name rewritten as id // test classes
$this->assertResult(
'<a name="foobar" />',
'<a id="foobar" />',
array('HTML.EnableAttrID' => true)
);
}
function testClasses() {
$this->assertResult('<div class="valid">Valid</div>'); $this->assertResult('<div class="valid">Valid</div>');
$this->assertResult( $this->assertResult(
'<div class="valid 0invalid">Keep valid.</div>', '<div class="valid 0invalid">Keep valid.</div>',
'<div class="valid">Keep valid.</div>' '<div class="valid">Keep valid.</div>'
); );
}
// test title
function testTitle() {
$this->assertResult( $this->assertResult(
'<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>' '<acronym title="PHP: Hypertext Preprocessor">PHP</acronym>'
); );
}
// test lang
function testLang() {
$this->assertResult( $this->assertResult(
'<span lang="fr">La soupe.</span>', '<span lang="fr">La soupe.</span>',
'<span lang="fr" xml:lang="fr">La soupe.</span>' '<span lang="fr" xml:lang="fr">La soupe.</span>'
); );
// test only xml:lang for XHTML 1.1 // test align
$this->assertResult(
'<b lang="en">asdf</b>',
'<b xml:lang="en">asdf</b>', array('HTML.Doctype' => 'XHTML 1.1')
);
}
function testAlign() {
$this->assertResult( $this->assertResult(
'<h1 align="center">Centered Headline</h1>', '<h1 align="center">Centered Headline</h1>',
'<h1 style="text-align:center;">Centered Headline</h1>' '<h1 style="text-align:center;">Centered Headline</h1>'
); );
$this->assertResult(
'<h1 align="right">Right-aligned Headline</h1>',
'<h1 style="text-align:right;">Right-aligned Headline</h1>'
);
$this->assertResult(
'<h1 align="left">Left-aligned Headline</h1>',
'<h1 style="text-align:left;">Left-aligned Headline</h1>'
);
$this->assertResult(
'<p align="justify">Justified Paragraph</p>',
'<p style="text-align:justify;">Justified Paragraph</p>'
);
$this->assertResult(
'<h1 align="invalid">Invalid Headline</h1>',
'<h1>Invalid Headline</h1>'
);
} // test table
function testTable() {
$this->assertResult( $this->assertResult(
'<table frame="above" rules="rows" summary="A test table" border="2" cellpadding="5%" cellspacing="3" width="100%"> '<table frame="above" rules="rows" summary="A test table" border="2" cellpadding="5%" cellspacing="3" width="100%">
<col align="right" width="4*" /> <col align="right" width="4*" />
@@ -148,64 +115,7 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
</table>' </table>'
); );
// test col.span is non-zero // test URI
$this->assertResult(
'<col span="0" />',
'<col />'
);
// lengths
$this->assertResult(
'<td height="10" width="5%" /><th height="5%" width="10" /><hr width="10" height="10" />',
'<td style="height:10px;width:5%;" /><th style="height:5%;width:10px;" /><hr style="width:10px;" />'
);
// td boolean transformation
$this->assertResult(
'<td nowrap />',
'<td style="white-space:nowrap;" />'
);
// caption align transformation
$this->assertResult(
'<caption align="left" />',
'<caption style="text-align:left;" />'
);
$this->assertResult(
'<caption align="right" />',
'<caption style="text-align:right;" />'
);
$this->assertResult(
'<caption align="top" />',
'<caption style="caption-side:top;" />'
);
$this->assertResult(
'<caption align="bottom" />',
'<caption style="caption-side:bottom;" />'
);
$this->assertResult(
'<caption align="nonsense" />',
'<caption />'
);
// align transformation
$this->assertResult(
'<table align="left" />',
'<table style="float:left;" />'
);
$this->assertResult(
'<table align="center" />',
'<table style="margin-left:auto;margin-right:auto;" />'
);
$this->assertResult(
'<table align="right" />',
'<table style="float:right;" />'
);
$this->assertResult(
'<table align="top" />',
'<table />'
);
}
function testURI() {
$this->assertResult('<a href="http://www.google.com/">Google</a>'); $this->assertResult('<a href="http://www.google.com/">Google</a>');
// test invalid URI // test invalid URI
@@ -213,9 +123,9 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
'<a href="javascript:badstuff();">Google</a>', '<a href="javascript:badstuff();">Google</a>',
'<a>Google</a>' '<a>Google</a>'
); );
}
// test required attributes for img
function testImg() {
// (this should never happen, as RemoveForeignElements // (this should never happen, as RemoveForeignElements
// should have removed the offending image tag) // should have removed the offending image tag)
$this->assertResult( $this->assertResult(
@@ -232,40 +142,7 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
'<img alt="pretty picture" />', '<img alt="pretty picture" />',
'<img alt="pretty picture" src="" />' '<img alt="pretty picture" src="" />'
); );
// mailto in image is not allowed
$this->assertResult(
'<img src="mailto:foo@example.com" />',
'<img src="" alt="Invalid image" />'
);
// align transformation
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="left" />',
'<img src="foobar.jpg" alt="foobar" style="float:left;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="right" />',
'<img src="foobar.jpg" alt="foobar" style="float:right;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="bottom" />',
'<img src="foobar.jpg" alt="foobar" style="vertical-align:baseline;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="middle" />',
'<img src="foobar.jpg" alt="foobar" style="vertical-align:middle;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="top" />',
'<img src="foobar.jpg" alt="foobar" style="vertical-align:top;" />'
);
$this->assertResult(
'<img src="foobar.jpg" alt="foobar" align="outerspace" />',
'<img src="foobar.jpg" alt="foobar" />'
);
}
function testBdo() {
// test required attributes for bdo // test required attributes for bdo
$this->assertResult( $this->assertResult(
'<bdo>Go left.</bdo>', '<bdo>Go left.</bdo>',
@@ -276,160 +153,23 @@ class HTMLPurifier_Strategy_ValidateAttributesTest extends
'<bdo dir="blahblah">Invalid value!</bdo>', '<bdo dir="blahblah">Invalid value!</bdo>',
'<bdo dir="ltr">Invalid value!</bdo>' '<bdo dir="ltr">Invalid value!</bdo>'
); );
}
// see above, behavior is subtly different
function testDir() {
// see testBdo, behavior is subtly different
$this->assertResult( $this->assertResult(
'<span dir="blahblah">Invalid value!</span>', '<span dir="blahblah">Invalid value!</span>',
'<span>Invalid value!</span>' '<span>Invalid value!</span>'
); );
}
function testLinks() { // test col.span is non-zero
// link types
$this->assertResult( $this->assertResult(
'<a href="foo" rel="nofollow" />', '<col span="0" />',
true, '<col />'
array('Attr.AllowedRel' => 'nofollow')
); );
// link targets
// mailto in image is not allowed
$this->assertResult( $this->assertResult(
'<a href="foo" target="_top" />', '<img src="mailto:foo@example.com" />',
true, '<img src="" alt="Invalid image" />'
array('Attr.AllowedFrameTargets' => '_top')
);
$this->assertResult(
'<a href="foo" target="_top" />',
'<a href="foo" />'
);
$this->assertResult(
'<a href="foo" target="_top" />',
'<a href="foo" />',
array('Attr.AllowedFrameTargets' => '_top', 'HTML.Strict' => true)
);
}
function testBorder() {
// border
$this->assertResult(
'<img src="foo" alt="foo" hspace="1" vspace="3" />',
'<img src="foo" alt="foo" style="margin-top:3px;margin-bottom:3px;margin-left:1px;margin-right:1px;" />',
array('Attr.AllowedRel' => 'nofollow')
);
}
function testHr() {
$this->assertResult(
'<hr size="3" />',
'<hr style="height:3px;" />'
);
$this->assertResult(
'<hr noshade />',
'<hr style="color:#808080;background-color:#808080;border:0;" />'
);
// align transformation
$this->assertResult(
'<hr align="left" />',
'<hr style="margin-left:0;margin-right:auto;text-align:left;" />'
);
$this->assertResult(
'<hr align="center" />',
'<hr style="margin-left:auto;margin-right:auto;text-align:center;" />'
);
$this->assertResult(
'<hr align="right" />',
'<hr style="margin-left:auto;margin-right:0;text-align:right;" />'
);
$this->assertResult(
'<hr align="bottom" />',
'<hr />'
);
}
function testBr() {
// br clear transformation
$this->assertResult(
'<br clear="left" />',
'<br style="clear:left;" />'
);
$this->assertResult(
'<br clear="right" />',
'<br style="clear:right;" />'
);
$this->assertResult( // test both?
'<br clear="all" />',
'<br style="clear:both;" />'
);
$this->assertResult(
'<br clear="none" />',
'<br style="clear:none;" />'
);
$this->assertResult(
'<br clear="foo" />',
'<br />'
);
}
function testListTypeTransform() {
// ul
$this->assertResult(
'<ul type="disc" />',
'<ul style="list-style-type:disc;" />'
);
$this->assertResult(
'<ul type="square" />',
'<ul style="list-style-type:square;" />'
);
$this->assertResult(
'<ul type="circle" />',
'<ul style="list-style-type:circle;" />'
);
$this->assertResult( // case insensitive
'<ul type="CIRCLE" />',
'<ul style="list-style-type:circle;" />'
);
$this->assertResult(
'<ul type="a" />',
'<ul />'
);
// ol
$this->assertResult(
'<ol type="1" />',
'<ol style="list-style-type:decimal;" />'
);
$this->assertResult(
'<ol type="i" />',
'<ol style="list-style-type:lower-roman;" />'
);
$this->assertResult(
'<ol type="I" />',
'<ol style="list-style-type:upper-roman;" />'
);
$this->assertResult(
'<ol type="a" />',
'<ol style="list-style-type:lower-alpha;" />'
);
$this->assertResult(
'<ol type="A" />',
'<ol style="list-style-type:upper-alpha;" />'
);
$this->assertResult(
'<ol type="disc" />',
'<ol />'
);
// li
$this->assertResult(
'<li type="circle" />',
'<li style="list-style-type:circle;" />'
);
$this->assertResult(
'<li type="A" />',
'<li style="list-style-type:upper-alpha;" />'
);
$this->assertResult( // case sensitive
'<li type="CIRCLE" />',
'<li />'
); );
} }

View File

@@ -49,14 +49,14 @@ class HTMLPurifier_TagTransformTest extends UnitTestCase
$context->loadArray($context_array); $context->loadArray($context_array);
// start tag transform // start tag transform
$this->assertIdentical( $this->assertEqual(
new HTMLPurifier_Token_Start($expect_name, $expect_added_attributes), new HTMLPurifier_Token_Start($expect_name, $expect_added_attributes),
$transformer->transform( $transformer->transform(
new HTMLPurifier_Token_Start($name), $config, $context) new HTMLPurifier_Token_Start($name), $config, $context)
); );
// start tag transform with attributes // start tag transform with attributes
$this->assertIdentical( $this->assertEqual(
new HTMLPurifier_Token_Start($expect_name, $expect_attributes), new HTMLPurifier_Token_Start($expect_name, $expect_attributes),
$transformer->transform( $transformer->transform(
new HTMLPurifier_Token_Start($name, $attributes), new HTMLPurifier_Token_Start($name, $attributes),
@@ -65,7 +65,7 @@ class HTMLPurifier_TagTransformTest extends UnitTestCase
); );
// end tag transform // end tag transform
$this->assertIdentical( $this->assertEqual(
new HTMLPurifier_Token_End($expect_name), new HTMLPurifier_Token_End($expect_name),
$transformer->transform( $transformer->transform(
new HTMLPurifier_Token_End($name), $config, $context new HTMLPurifier_Token_End($name), $config, $context
@@ -73,7 +73,7 @@ class HTMLPurifier_TagTransformTest extends UnitTestCase
); );
// empty tag transform // empty tag transform
$this->assertIdentical( $this->assertEqual(
new HTMLPurifier_Token_Empty($expect_name, $expect_added_attributes), new HTMLPurifier_Token_Empty($expect_name, $expect_added_attributes),
$transformer->transform( $transformer->transform(
new HTMLPurifier_Token_Empty($name), $config, $context new HTMLPurifier_Token_Empty($name), $config, $context
@@ -81,7 +81,7 @@ class HTMLPurifier_TagTransformTest extends UnitTestCase
); );
// empty tag transform with attributes // empty tag transform with attributes
$this->assertIdentical( $this->assertEqual(
new HTMLPurifier_Token_Empty($expect_name, $expect_attributes), new HTMLPurifier_Token_Empty($expect_name, $expect_attributes),
$transformer->transform( $transformer->transform(
new HTMLPurifier_Token_Empty($name, $attributes), new HTMLPurifier_Token_Empty($name, $attributes),
@@ -152,7 +152,6 @@ class HTMLPurifier_TagTransformTest extends UnitTestCase
); );
// test the size transforms // test the size transforms
$this->assertSizeToStyle($transformer, '0', 'xx-small');
$this->assertSizeToStyle($transformer, '1', 'xx-small'); $this->assertSizeToStyle($transformer, '1', 'xx-small');
$this->assertSizeToStyle($transformer, '2', 'small'); $this->assertSizeToStyle($transformer, '2', 'small');
$this->assertSizeToStyle($transformer, '3', 'medium'); $this->assertSizeToStyle($transformer, '3', 'medium');
@@ -161,13 +160,10 @@ class HTMLPurifier_TagTransformTest extends UnitTestCase
$this->assertSizeToStyle($transformer, '6', 'xx-large'); $this->assertSizeToStyle($transformer, '6', 'xx-large');
$this->assertSizeToStyle($transformer, '7', '300%'); $this->assertSizeToStyle($transformer, '7', '300%');
$this->assertSizeToStyle($transformer, '-1', 'smaller'); $this->assertSizeToStyle($transformer, '-1', 'smaller');
$this->assertSizeToStyle($transformer, '-2', '60%');
$this->assertSizeToStyle($transformer, '-3', '60%');
$this->assertSizeToStyle($transformer, '+1', 'larger'); $this->assertSizeToStyle($transformer, '+1', 'larger');
$this->assertSizeToStyle($transformer, '-2', '60%');
$this->assertSizeToStyle($transformer, '+2', '150%'); $this->assertSizeToStyle($transformer, '+2', '150%');
$this->assertSizeToStyle($transformer, '+3', '200%');
$this->assertSizeToStyle($transformer, '+4', '300%'); $this->assertSizeToStyle($transformer, '+4', '300%');
$this->assertSizeToStyle($transformer, '+5', '300%');
// test multiple transforms, the alphabetical ordering is important // test multiple transforms, the alphabetical ordering is important
$this->assertTransformation( $this->assertTransformation(

View File

@@ -72,7 +72,7 @@ class HTMLPurifier_Test extends UnitTestCase
$this->purifier = new HTMLPurifier(); $this->purifier = new HTMLPurifier();
$this->assertIdentical( $this->assertEqual(
$this->purifier->purifyArray( $this->purifier->purifyArray(
array('Good', '<b>Sketchy', 'foo' => '<script>bad</script>') array('Good', '<b>Sketchy', 'foo' => '<script>bad</script>')
), ),

View File

@@ -11,7 +11,7 @@ class HTMLPurifier_TokenFactoryTest extends UnitTestCase
$regular = new HTMLPurifier_Token_Start('a', array('href' => 'about:blank')); $regular = new HTMLPurifier_Token_Start('a', array('href' => 'about:blank'));
$generated = $factory->createStart('a', array('href' => 'about:blank')); $generated = $factory->createStart('a', array('href' => 'about:blank'));
$this->assertIdentical($regular, $generated); $this->assertEqual($regular, $generated);
} }
} }

View File

@@ -12,8 +12,8 @@ class HTMLPurifier_TokenTest extends UnitTestCase
if ($expect_attr === null) $expect_attr = $attr; if ($expect_attr === null) $expect_attr = $attr;
$token = new HTMLPurifier_Token_Start($name, $attr); $token = new HTMLPurifier_Token_Start($name, $attr);
$this->assertIdentical($expect_name, $token->name); $this->assertEqual($expect_name, $token->name);
$this->assertIdentical($expect_attr, $token->attr); $this->assertEqual($expect_attr, $token->attr);
} }
function testConstruct() { function testConstruct() {

View File

@@ -21,11 +21,9 @@ $test_files[] = 'AttrDef/CSSTest.php';
$test_files[] = 'AttrDef/EnumTest.php'; $test_files[] = 'AttrDef/EnumTest.php';
$test_files[] = 'AttrDef/HTML/IDTest.php'; $test_files[] = 'AttrDef/HTML/IDTest.php';
$test_files[] = 'AttrDef/HTML/LengthTest.php'; $test_files[] = 'AttrDef/HTML/LengthTest.php';
$test_files[] = 'AttrDef/HTML/FrameTargetTest.php';
$test_files[] = 'AttrDef/HTML/MultiLengthTest.php'; $test_files[] = 'AttrDef/HTML/MultiLengthTest.php';
$test_files[] = 'AttrDef/HTML/NmtokensTest.php'; $test_files[] = 'AttrDef/HTML/NmtokensTest.php';
$test_files[] = 'AttrDef/HTML/PixelsTest.php'; $test_files[] = 'AttrDef/HTML/PixelsTest.php';
$test_files[] = 'AttrDef/HTML/LinkTypesTest.php';
$test_files[] = 'AttrDef/IntegerTest.php'; $test_files[] = 'AttrDef/IntegerTest.php';
$test_files[] = 'AttrDef/LangTest.php'; $test_files[] = 'AttrDef/LangTest.php';
$test_files[] = 'AttrDef/TextTest.php'; $test_files[] = 'AttrDef/TextTest.php';
@@ -35,17 +33,10 @@ $test_files[] = 'AttrDef/URI/IPv4Test.php';
$test_files[] = 'AttrDef/URI/IPv6Test.php'; $test_files[] = 'AttrDef/URI/IPv6Test.php';
$test_files[] = 'AttrDef/URITest.php'; $test_files[] = 'AttrDef/URITest.php';
$test_files[] = 'AttrDefTest.php'; $test_files[] = 'AttrDefTest.php';
$test_files[] = 'AttrTransformTest.php';
$test_files[] = 'AttrTransform/BdoDirTest.php'; $test_files[] = 'AttrTransform/BdoDirTest.php';
$test_files[] = 'AttrTransform/BgColorTest.php';
$test_files[] = 'AttrTransform/BoolToCSSTest.php';
$test_files[] = 'AttrTransform/BorderTest.php';
$test_files[] = 'AttrTransform/EnumToCSSTest.php';
$test_files[] = 'AttrTransform/ImgRequiredTest.php'; $test_files[] = 'AttrTransform/ImgRequiredTest.php';
$test_files[] = 'AttrTransform/ImgSpaceTest.php';
$test_files[] = 'AttrTransform/LangTest.php'; $test_files[] = 'AttrTransform/LangTest.php';
$test_files[] = 'AttrTransform/LengthTest.php'; $test_files[] = 'AttrTransform/TextAlignTest.php';
$test_files[] = 'AttrTransform/NameTest.php';
$test_files[] = 'ChildDef/ChameleonTest.php'; $test_files[] = 'ChildDef/ChameleonTest.php';
$test_files[] = 'ChildDef/CustomTest.php'; $test_files[] = 'ChildDef/CustomTest.php';
$test_files[] = 'ChildDef/OptionalTest.php'; $test_files[] = 'ChildDef/OptionalTest.php';