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

Compare commits

...

3 Commits

Author SHA1 Message Date
Edward Z. Yang
48ce521572 Fix typo in NEWS item.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.1@477 48356398-32a2-884e-a903-53898d9a118a
2006-09-30 19:30:50 +00:00
Edward Z. Yang
728e6c5b44 Sync 1.1 branch as much as possible with trunk.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.1@476 48356398-32a2-884e-a903-53898d9a118a
2006-09-30 19:25:51 +00:00
Edward Z. Yang
8104145580 Merged 463:474 for 1.1.2 release.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.1@475 48356398-32a2-884e-a903-53898d9a118a
2006-09-30 19:10:07 +00:00
28 changed files with 712 additions and 426 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.0.0 PROJECT_NUMBER = 1.1.2
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
@@ -89,9 +89,12 @@ EXCLUDE =
EXCLUDE_SYMLINKS = NO EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */tests/* \ EXCLUDE_PATTERNS = */tests/* \
*/benchmarks/* \ */benchmarks/* \
*/docs/phpdoc/* \ */docs/* \
*/docs/doxygen/* \ */test-settings.php \
*/test-settings.php */configdoc/* \
*/test-settings.php \
*/maintenance/* \
*/smoketests/*
EXAMPLE_PATH = EXAMPLE_PATH =
EXAMPLE_PATTERNS = * EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO EXAMPLE_RECURSIVE = NO

184
INSTALL
View File

@@ -2,145 +2,183 @@
Install Install
How to install HTML Purifier How to install HTML Purifier
Being a library, there's no fancy GUI that will take you step-by-step through HTML Purifier is designed to run out of the box, so actually using the library
configuring database credentials and other mumbo-jumbo. HTML Purifier is is extremely easy. (Although, if you were looking for a step-by-step
designed to run "out of the box." Regardless, there are still a couple of installation GUI, you've come to the wrong place!) The impatient can scroll
things you should be mindful of. down to the bottom of this INSTALL document to see the code, but you really
should make sure a few things are properly done.
0. Compatibility 1. Compatibility
HTML Purifier works in both PHP 4 and PHP 5. I have run the test suite on HTML Purifier works in both PHP 4 and PHP 5, from PHP 4.3.9 and up. It has no
these versions: core dependencies with other libraries. (Whoopee!)
- 4.3.9, 4.3.11 Optional extensions are iconv (usually installed) and tidy (also common).
- 4.4.0, 4.4.4 If you use UTF-8 and don't plan on pretty-printing HTML, you can get away with
- 5.0.0, 5.0.4 not having either of these extensions.
- 5.1.0, 5.1.6
And can confidently say that HTML Purifier should work in all versions
between and afterwards. HTML Purifier definitely does not support PHP 4.2,
and PHP 4.3 branch support may go further back than that, but I haven't tested
any earlier versions.
I have been unable to get PHP 5.0.5 working on my computer, so if someone
wants to test that, be my guest. All tests were done on Windows XP Home,
but operating system should not be a major factor in the library.
1. Including the proper files 2. Including the library
The library/ directory must be added to your path: HTML Purifier will not be Simply use:
able to find the necessary includes otherwise. This is as simple as:
set_include_path('/path/to/htmlpurifier/library' . PATH_SEPARATOR . require_once '/path/to/library/HTMLPurifier.auto.php';
get_include_path() );
...replacing /path/to/htmlpurifier with the actual location of the folder. Don't ...and you're good to go. Since HTML Purifier's codebase is fairly
worry, HTML Purifier is namespaced so unless you have another file named large, I recommend only including HTML Purifier when you need it.
HTMLPurifier.php, the files won't collide with any of your includes.
Then, it's a simple matter of including the base file: If you don't like your include_path to be fiddled around with, simply set
HTML Purifier's library/ directory to the include path yourself and then:
require_once 'HTMLPurifier.php'; require_once 'HTMLPurifier.php';
...and you're good to go. The library/ folder contains all the files you need, Only the contents in the library/ folder are necessary, so you can remove
so you can get rid of most of everything else when using the library in a everything else when using HTML Purifier in a production environment.
production environment.
2. Preparing the proper environment 3. Preparing the proper output environment
While no configuration is necessary, you first should take precautions regarding HTML Purifier is all about web-standards, so accordingly your webpages should
the other output HTML that the filtered content will be going along with. Here be standards compliant. HTML Purifier can deal with these doctypes:
is a (short) checklist:
* Have I specified XHTML 1.0 Transitional as the doctype? * XHTML 1.0 Transitional (default)
* Have I specified UTF-8 as the character encoding? * HTML 4.01 Transitional
...and these character encodings:
* UTF-8 (default)
* Any encoding iconv supports (support is crippled for i18n though)
The defaults are there for a reason: they are best-practice choices that
should not be changed lightly. For those of you in the dark, you can determine
the doctype from this code in your HTML documents:
To find out what these are, browse to your website and view its source code.
You can figure out the doctype from the a declaration that looks like
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
or no doctype. You can figure out the character encoding by looking for
...and the character encoding from this code:
<meta http-equiv="Content-type" content="text/html;charset=ENCODING"> <meta http-equiv="Content-type" content="text/html;charset=ENCODING">
I cannot stress the importance of these two bullets enough. Omitting either For legacy codebases these declarations may be missing. If that is the case,
of them could have dire consequences not only for security but for plain STOP, and read up on character encodings and doctypes (in that order). Here
old usability. You can find a more in-depth discussion of why this is needed are some links:
in docs/security.txt, in the meantime, try to change your output so this is
the case. If you can't, well, we might be able to accomodate you (read * http://www.joelonsoftware.com/articles/Unicode.html
section 3). * http://alistapart.com/stories/doctype/
You may currently be vulnerable to XSS and other security threats, and HTML
Purifier won't be able to fix that.
3. Configuring HTML Purifier 4. Configuration
HTML Purifier is designed to run out-of-the-box, but occasionally HTML HTML Purifier is designed to run out-of-the-box, but occasionally HTML
Purifier needs to be told what to do. Purifier needs to be told what to do. If you answered no to any of these
questions, read on, otherwise, you can skip to the next section (or, if you're
into configuring things just for the heck of it, skip to 4.3).
If, for some reason, you are unable to switch to UTF-8 immediately, you can * Am I using UTF-8?
switch HTML Purifier's encoding. Note that the availability of encodings is * Am I using XHTML 1.0 Transitional?
dependent on iconv, and you'll be missing characters if the charset you
choose doesn't have them. If you answered yes to any of these questions, instantiate a configuration
object and read on:
$config = HTMLPurifier_Config::createDefault();
4.1. Setting a different character encoding
You really shouldn't use any other encoding except UTF-8, especially if you
plan to support multilingual websites (read section three for more details).
However, switching to UTF-8 is not always immediately feasible, so we can
adapt.
HTML Purifier uses iconv to support other character encodings, as such,
any encoding that iconv supports <http://www.gnu.org/software/libiconv/>
HTML Purifier supports with this code:
$config->set('Core', 'Encoding', /* put your encoding here */); $config->set('Core', 'Encoding', /* put your encoding here */);
An example usage for Latin-1 websites: An example usage for Latin-1 websites (the most common encoding for English
websites):
$config->set('Core', 'Encoding', 'ISO-8859-1'); $config->set('Core', 'Encoding', 'ISO-8859-1');
Note that HTML Purifier's support for non-Unicode encodings is crippled by the
fact that any character not supported by that encoding will be silently
dropped, EVEN if it is ampersand escaped. This is a current limitation of
HTML Purifier that we are NOT actively working to fix. Patches are welcome,
but there are so many other gotchas and problems in I18N for non-Unicode
encodings that this functionality is low priority. See
<http://ppewww.ph.gla.ac.uk/~flavell/charset/form-i18n.html> for a more
detailed lowdown on the topic.
4.2. Setting a different doctype
For those of you stuck using HTML 4.01 Transitional, you can disable For those of you stuck using HTML 4.01 Transitional, you can disable
XHTML output like this: XHTML output like this:
$config->set('Core', 'XHTML', false); $config->set('Core', 'XHTML', false);
However, I strongly recommend that you use XHTML. Currently, we can only I recommend that you use XHTML, although not as much as I recommend UTF-8. If
guarantee transitional-complaint output, future versions will also allow strict your HTML 4.01 page validates, good for you!
output. There are more configuration directives which can be read about
here: http://hp.jpsband.org/live/configdoc/plain.html Currently, we can only guarantee transitional-complaint output, future
versions will also allow strict-compliant output.
3. Using the code 4.3. Other settings
There are more configuration directives which can be read about
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
your code.
5. Using the code
The interface is mind-numbingly simple: The interface is mind-numbingly simple:
$purifier = new HTMLPurifier(); $purifier = new HTMLPurifier();
$clean_html = $purifier->purify($dirty_html); $clean_html = $purifier->purify( $dirty_html );
Or, if you're using the configuration object: ...or, if you're using the configuration object:
$purifier = new HTMLPurifier($config); $purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($dirty_html); $clean_html = $purifier->purify( $dirty_html );
That's it. For more examples, check out docs/examples/. Also, SLOW gives That's it! For more examples, check out docs/examples/ (they aren't very
advice on what to do if HTML Purifier is slowing down your application. different though). Also, SLOW gives advice on what to do if HTML Purifier
is slowing down your application.
4. Quick install 6. Quick install
If your website is in UTF-8 and XHTML Transitional, use this code: If your website is in UTF-8 and XHTML Transitional, use this code:
<?php <?php
set_include_path('/path/to/htmlpurifier/library' require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
. PATH_SEPARATOR . get_include_path() );
require_once 'HTMLPurifier.php';
$purifier = new HTMLPurifier();
$purifier = new HTMLPurifier();
$clean_html = $purifier->purify($dirty_html); $clean_html = $purifier->purify($dirty_html);
?> ?>
If your website is in a different encoding or doctype, use this code: If your website is in a different encoding or doctype, use this code:
<?php <?php
set_include_path('/path/to/htmlpurifier/library' require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
. PATH_SEPARATOR . get_include_path() );
require_once 'HTMLPurifier.php';
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$config->set('Core', 'Encoding', 'ISO-8859-1'); //replace with your encoding $config->set('Core', 'Encoding', 'ISO-8859-1'); //replace with your encoding

55
NEWS
View File

@@ -1,24 +1,47 @@
NEWS ( CHANGELOG and HISTORY ) HTMLPurifier NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
= KEY ====================
! Feature
- Bugfix
+ Sub-comment
. Internal change
==========================
1.1.2, released 2006-09-30
! Add HTMLPurifier.auto.php stub file that configures include_path
- Documentation updated
+ INSTALL document rewritten
+ TODO added semi-lossy conversion
+ API Doxygen docs' file exclusions updated
+ Added notes on HTML versus XML attribute whitespace handling
+ Noted that HTMLPurifier_ChildDef_Custom isn't being used
+ Noted that config object's definitions are cached versions
- Fixed lack of attribute parsing in HTMLPurifier_Lexer_PEARSax3
- ftp:// URIs now have their typecodes checked
- Hooked up HTMLPurifier_ChildDef_Custom's unit tests (they weren't being run)
. Line endings standardized throughout project (svn:eol-style standardized)
. Refactored parseData() to general Lexer class
. Tester named "HTML Purifier" not "HTMLPurifier"
1.1.1, released 2006-09-24 1.1.1, released 2006-09-24
! Configuration option to optionally Tidy up output for indentation to make up
for dropped whitespace by DOMLex (pretty-printing for the entire application
should be done by a page-wide Tidy)
- Various documentation updates - Various documentation updates
- Fixed parse error in configuration documentation script - Fixed parse error in configuration documentation script
- Fixed fatal error in benchmark scripts, slightly augmented - Fixed fatal error in benchmark scripts, slightly augmented
- As far as possible, whitespace is preserved in-between table children - As far as possible, whitespace is preserved in-between table children
- Configuration option to optionally Tidy up output for indentation to make up
for dropped whitespace by DOMLex (pretty-printing for the entire application
should be done by a page-wide Tidy)
- Sample test-settings.php file included - Sample test-settings.php file included
1.1.0, released 2006-09-16 1.1.0, released 2006-09-16
! Directive documentation generation using XSLT
! XHTML can now be turned off, output becomes <br>
- Made URI validator more forgiving: will ignore leading and trailing - Made URI validator more forgiving: will ignore leading and trailing
quotes, apostrophes and less than or greater than signs. quotes, apostrophes and less than or greater than signs.
- Enforce alphanumeric namespace and directive names for configuration. - Enforce alphanumeric namespace and directive names for configuration.
- Directive documentation generation using XSLT
- Table child definition made more flexible, will fix up poorly ordered elements - Table child definition made more flexible, will fix up poorly ordered elements
- XHTML generation can now be turned off, allowing things like <br> . Renamed ConfigDef to ConfigSchema
- Renamed ConfigDef to ConfigSchema
1.0.1, released 2006-09-04 1.0.1, released 2006-09-04
- Fixed slight bug in DOMLex attribute parsing - Fixed slight bug in DOMLex attribute parsing
@@ -28,17 +51,17 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
space in them. This manifested in TinyMCE. space in them. This manifested in TinyMCE.
1.0.0, released 2006-09-01 1.0.0, released 2006-09-01
! Shorthand CSS properties implemented: font, border, background, list-style
! Basic color keywords translated into hexadecimal values
! Table CSS properties implemented
! Support for charsets other than UTF-8 (defined by iconv)
! Malformed UTF-8 and non-SGML character detection and cleaning implemented
- Fixed broken numeric entity conversion - Fixed broken numeric entity conversion
- Malformed UTF-8 and non-SGML character detection and cleaning implemented
- API documentation completed - API documentation completed
- Shorthand CSS properties implemented: font, border, background, list-style . (HTML|CSS)Definition de-singleton-ized
- Basic color keywords translated into hexadecimal values
- Table CSS properties implemented
- (HTML|CSS)Definition de-singleton-ized
- Support for charsets other than UTF-8 (defined by iconv)
1.0.0beta, released 2006-08-16 1.0.0beta, released 2006-08-16
- First public release, most functionality implemented. Notable omissions are: ! First public release, most functionality implemented. Notable omissions are:
. Shorthand CSS properties + Shorthand CSS properties
. Table CSS properties + Table CSS properties
. Deprecated attribute transformations + Deprecated attribute transformations

24
README
View File

@@ -1,13 +1,13 @@
README
All about HTMLPurifier
HTMLPurifier is an HTML filtering solution. It uses a unique combination of README
robust whitelists and agressive parsing to ensure that not only are XSS All about HTMLPurifier
attacks thwarted, but the resulting HTML is standards compliant.
HTMLPurifier is an HTML filtering solution. It uses a unique combination of
See INSTALL on how to use the library. See docs/ for more developer-oriented robust whitelists and agressive parsing to ensure that not only are XSS
documentation as well as some code examples. Users of TinyMCE or FCKeditor attacks thwarted, but the resulting HTML is standards compliant.
may be especially interested in WYSIWYG.
See INSTALL on how to use the library. See docs/ for more developer-oriented
HTMLPurifier can be found on the web at: http://hp.jpsband.org/ documentation as well as some code examples. Users of TinyMCE or FCKeditor
may be especially interested in WYSIWYG.
HTMLPurifier can be found on the web at: http://hp.jpsband.org/

2
TODO
View File

@@ -45,6 +45,8 @@ Unknown release (on a scratch-an-itch basis)
empty-cells:show is applied to have compatibility with Internet Explorer empty-cells:show is applied to have compatibility with Internet Explorer
- Non-lossy dumb alternate character encoding transformations, achieved by - Non-lossy dumb alternate character encoding transformations, achieved by
numerically encoding all non-ASCII characters numerically encoding all non-ASCII characters
- Semi-lossy dumb alternate character encoding transformations, achieved by
encoding all characters that have string entity equivalents
Wontfix Wontfix
- Non-lossy smart alternate character encoding transformations - Non-lossy smart alternate character encoding transformations

View File

@@ -1,7 +1,7 @@
table {border-collapse:collapse;} table {border-collapse:collapse;}
table td, table th {padding:0.2em;} table td, table th {padding:0.2em;}
table.constraints {margin:0 0 1em;} table.constraints {margin:0 0 1em;}
table.constraints th {text-align:left;padding-left:0.4em;} table.constraints th {text-align:left;padding-left:0.4em;}
table.constraints td {padding-right:0.4em;} table.constraints td {padding-right:0.4em;}
table.constraints td pre {margin:0;} table.constraints td pre {margin:0;}

View File

@@ -1,105 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet <xsl:stylesheet
version = "1.0" version = "1.0"
xmlns = "http://www.w3.org/1999/xhtml" xmlns = "http://www.w3.org/1999/xhtml"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
> >
<xsl:output <xsl:output
method = "xml" method = "xml"
encoding = "UTF-8" encoding = "UTF-8"
doctype-public = "-//W3C//DTD XHTML 1.0 Transitional//EN" doctype-public = "-//W3C//DTD XHTML 1.0 Transitional//EN"
doctype-system = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-system = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
indent = "no" indent = "no"
media-type = "text/html" media-type = "text/html"
/> />
<xsl:variable name="typeLookup" select="document('../types.xml')" /> <xsl:variable name="typeLookup" select="document('../types.xml')" />
<xsl:template match="/"> <xsl:template match="/">
<html lang="en" xml:lang="en"> <html lang="en" xml:lang="en">
<head> <head>
<title><xsl:value-of select="/configdoc/title" /> Configuration Documentation</title> <title><xsl:value-of select="/configdoc/title" /> Configuration Documentation</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="styles/plain.css" /> <link rel="stylesheet" type="text/css" href="styles/plain.css" />
</head> </head>
<body> <body>
<xsl:apply-templates /> <xsl:apply-templates />
</body> </body>
</html> </html>
</xsl:template> </xsl:template>
<xsl:template match="title"> <xsl:template match="title">
<h1><xsl:value-of select="/configdoc/title" /> Configuration Documentation</h1> <h1><xsl:value-of select="/configdoc/title" /> Configuration Documentation</h1>
</xsl:template> </xsl:template>
<xsl:template match="namespace"> <xsl:template match="namespace">
<xsl:apply-templates /> <xsl:apply-templates />
<xsl:if test="count(child::directive)=0"> <xsl:if test="count(child::directive)=0">
<p>No configuration directives defined for this namespace.</p> <p>No configuration directives defined for this namespace.</p>
</xsl:if> </xsl:if>
</xsl:template> </xsl:template>
<xsl:template match="namespace/name"> <xsl:template match="namespace/name">
<h2 id="{../@id}"><xsl:value-of select="text()" /></h2> <h2 id="{../@id}"><xsl:value-of select="text()" /></h2>
</xsl:template> </xsl:template>
<xsl:template match="namespace/description"> <xsl:template match="namespace/description">
<div class="description"> <div class="description">
<xsl:copy-of select="div/node()" /> <xsl:copy-of select="div/node()" />
</div> </div>
</xsl:template> </xsl:template>
<xsl:template match="directive"> <xsl:template match="directive">
<xsl:apply-templates /> <xsl:apply-templates />
</xsl:template> </xsl:template>
<xsl:template match="directive/name"> <xsl:template match="directive/name">
<h3 id="{../@id}"><xsl:value-of select="text()" /></h3> <h3 id="{../@id}"><xsl:value-of select="text()" /></h3>
</xsl:template> </xsl:template>
<xsl:template match="directive/constraints"> <xsl:template match="directive/constraints">
<table class="constraints"> <table class="constraints">
<xsl:apply-templates /> <xsl:apply-templates />
<!-- Calculated other values --> <!-- Calculated other values -->
<tr> <tr>
<th>Used by:</th> <th>Used by:</th>
<td> <td>
<xsl:for-each select="../descriptions/description"> <xsl:for-each select="../descriptions/description">
<xsl:if test="position()&gt;1">, </xsl:if> <xsl:if test="position()&gt;1">, </xsl:if>
<xsl:value-of select="@file" /> <xsl:value-of select="@file" />
</xsl:for-each> </xsl:for-each>
</td> </td>
</tr> </tr>
</table> </table>
</xsl:template> </xsl:template>
<xsl:template match="directive//description"> <xsl:template match="directive//description">
<div class="description"> <div class="description">
<xsl:copy-of select="div/node()" /> <xsl:copy-of select="div/node()" />
</div> </div>
</xsl:template> </xsl:template>
<xsl:template match="constraints/type"> <xsl:template match="constraints/type">
<tr> <tr>
<th>Type:</th> <th>Type:</th>
<td> <td>
<xsl:variable name="type" select="text()" /> <xsl:variable name="type" select="text()" />
<xsl:attribute name="class">type type-<xsl:value-of select="$type" /></xsl:attribute> <xsl:attribute name="class">type type-<xsl:value-of select="$type" /></xsl:attribute>
<xsl:value-of select="$typeLookup/types/type[@id=$type]/text()" /> <xsl:value-of select="$typeLookup/types/type[@id=$type]/text()" />
</td> </td>
</tr> </tr>
</xsl:template> </xsl:template>
<xsl:template match="constraints/allowed"> <xsl:template match="constraints/allowed">
<tr> <tr>
<th>Allowed values:</th> <th>Allowed values:</th>
<td> <td>
<xsl:for-each select="value"><!-- <xsl:for-each select="value"><!--
--><xsl:if test="position()&gt;1">, </xsl:if> --><xsl:if test="position()&gt;1">, </xsl:if>
&quot;<xsl:value-of select="." />&quot;<!-- &quot;<xsl:value-of select="." />&quot;<!--
--></xsl:for-each> --></xsl:for-each>
</td> </td>
</tr> </tr>
</xsl:template> </xsl:template>
<xsl:template match="constraints/default"> <xsl:template match="constraints/default">
<tr> <tr>
<th>Default:</th> <th>Default:</th>
<td><pre><xsl:value-of select="." xml:space="preserve" /></pre></td> <td><pre><xsl:value-of select="." xml:space="preserve" /></pre></td>
</tr> </tr>
</xsl:template> </xsl:template>
</xsl:stylesheet> </xsl:stylesheet>

23
docs/colors.txt Normal file
View File

@@ -0,0 +1,23 @@
Colors
Hammering some sense into those content-makers
Your website probably has a color-scheme. Green on white, purple on yellow,
whatever. When you give users the ability to style their content, you may
want them to keep in line with your styling. If you're website is all
about light colors, you don't want a user to come in and vandalize your
page with a deep maroon.
This is an extremely silly feature proposal, but I'm writing it down anyway.
What if the user could constrain the colors specified in inline styles? You
are only allowed to use these shades of dark green for text and these shades
of light yellow for the background. At the very least, you could ensure
that we did not have pale yellow on white text.
Implementation issues:
1. Requires the color attribute definition to know, currently, what the text
and background colors are. This becomes difficult when classes are thrown
into the mix.
2. The user still has to define the permissible colors, how does one do
something like that?

View File

@@ -20,15 +20,32 @@ can further be customized using simpler configuration options.
Here are some fuzzy levels you could set: Here are some fuzzy levels you could set:
1. Comments - Wordpress recommends a, abbr, acronym, b, blockquote, cite, 1. Comments - Wordpress recommends a, abbr, acronym, b, blockquote, cite,
code, em, i, strike, strong; however, you could get away with only a, b and code, em, i, strike, strong; however, you could get away with only a, em and
i; also having p and pre tags would be helpful. p; also having blockquote and pre tags would be helpful.
2. Pages - As permissive as possible without allowing XSS. No protection 2. BBCode - Emulate the usual tagset for forums: b, i, img, a, blockquote,
pre, div, span and h[2-6] (the last three are for specially formatted
posts, div and span require associated classes or inline styling enabled
to be useful)
3. Pages - As permissive as possible without allowing XSS. No protection
against bad design sense, unfortunantely. Suitable for wiki and page against bad design sense, unfortunantely. Suitable for wiki and page
environments. environments.
3. Lint - Accept everything in the spec, a Tidy wannabe. 4. Lint - Accept everything in the spec, a Tidy wannabe. (This probably won't
get implemented as it would require routines for things like <object>
and friends to be implemented, which is a lot of work for not a lot of
benefit)
I've also decomposed tags into risk levels. An asterisk indicates that no one One final note: when you start axing tags that are more commonly used, you
really uses that tag, tilde indicates it's deprecated. run the risk of accidentally destroying user data, especially if the data
is incoming from a WYSIWYG eidtor that hasn't been synced accordingly. This may
make forbidden element to text transformations desirable (for example, images).
== Element Risk Analysis ==
Legend:
[danger level] - regular tags / uncommon tags ~ deprecated tags
[danger level]* - rare tags
1 - blockquote, code, em, i, p, tt / strong, sub, sup 1 - blockquote, code, em, i, p, tt / strong, sub, sup
1* - abbr, acronym, bdo, cite, dfn, kbd, q, samp 1* - abbr, acronym, bdo, cite, dfn, kbd, q, samp
@@ -38,30 +55,76 @@ really uses that tag, tilde indicates it's deprecated.
5 - a 5 - a
7 - area, map 7 - area, map
These are special use tags, they should be enabled on a blanket basis.
Lists - dd, dl, dt, li, ol, ul ~ menu, dir Lists - dd, dl, dt, li, ol, ul ~ menu, dir
Tables - caption, table, td, th, tr / col, colgroup, tbody, tfoot, thead Tables - caption, table, td, th, tr / col, colgroup, tbody, tfoot, thead
Forms - fieldset, form, input, lable, legend, optgroup, option, select, textarea Forms - fieldset, form, input, lable, legend, optgroup, option, select, textarea
XSS - noscript, object, script ~ applet XSS - noscript, object, script ~ applet
Meta - base, basefont, body, head, html, link, meta, style, title Meta - base, basefont, body, head, html, link, meta, style, title
Frames - frame, frameset, iframe Frames - frame, frameset, iframe
And tag specific notes: And tag specific notes:
a - general problems involving linkspam a - general problems involving linkspam
b - too much bold is bad, typographically speaking bold is discouraged b - too much bold is bad, typographically speaking bold is discouraged
br - often misused br - often misused
center - CSS, usually no legit use center - CSS, usually no legit use
del - only useful in editing context del - only useful in editing context
div - little meaning in certain contexts i.e. blog comment div - little meaning in certain contexts i.e. blog comment
h1 - usually no legit use, as header is already set by application h1 - usually no legit use, as header is already set by application
h* - not needed in blog comments h* - not needed in blog comments
hr - usually not necessary in blog comments hr - usually not necessary in blog comments
img - could be extremely undesirable if linking to external pics img - could be extremely undesirable if linking to external pics (CSRF, goatse)
pre - could use formatting, only useful in code contexts pre - could use formatting, only useful in code contexts
q - very little support q - very little support
s - transform into span with styling or del? s - transform into span with styling or del?
small - technically presentational small - technically presentational
span - depends on attribute allowances span - depends on attribute allowances
sub, sup - specialized sub, sup - specialized
u - little legit use, prefer class with text-decoration u - little legit use, prefer class with text-decoration
Based on the riskiness of the items, we may want to offer %HTML.DisableImages
attribute and put URI filtering higher up on the priority list.
== Attribute Risk Analysis ==
We actually have a suprisingly small assortment of allowed attributes (the
rest are deprecated in strict, and thus we opted not to allow them, even
though our output is XHTML Transitional by default.)
Required URI - img.alt, img.src, a.href
Medium risk - *.class, *.dir
High risk - img.height, img.width, *.id, *.style
Table - colgroup/col.span, td/th.rowspan, td/th.colspan
Uncommon - *.title, *.lang, *.xml:lang
Rare - td/th.abbr, table.summary, {table}.charoff
Rare URI - del.cite, ins.cite, blockquote.cite, q.cite, img.longdesc
Presentational - {table}.align, {table}.valign, table.frame, table.rules,
table.border
Partially presentational - table.cellpadding, table.cellspacing,
table.width, col.width, colgroup.width
== CSS Risk Analysis ==
There are certain CSS elements that are extremely useful inline, but then
as you get to more presentation oriented styling it may not always be
appropriate to inline them.
Useful - clear, float, border-collapse, caption-side
These CSS properties can break layouts if used improperly. We have excluded
any CSS properties that are not currently implemented (such as position).
Dangerous, can go outside container - float
Easy to abuse - font-size, font-family (font), width
Colored - background-color (background), border-color (border), color
Dramatic - border, list-style-position (list-style), margin, padding,
text-align, text-indent, text-transform, vertical-align, line-height
Dramatic elements substnatially change the look of text in ways that should
probably have been reserved to other areas.

25
docs/strictness.txt Normal file
View File

@@ -0,0 +1,25 @@
Is HTML Purifier Strict or Transitional?
A little bit of helpful guidance
Despite the fact that HTML Purifier professes only to support transitional
HTML, it rejects a lot of attributes and elements that are actually, indeed,
valid. You can investigate progress.html to find out precisely what we
are doing to these *deprecated* attributes.
However, users have found that Strict HTML imposes some quite unreasonable
restrictions on certain things. The start and value attributes in ol and
li (respectively) perhaps are the most contested. There's is currently no
widely supported browser method short of JavaScript that can replace these
two deprecated elements. HTML Purifier does not currently support them, but
it might behoove us to do so while our output is still transitional.
Fortunantely, that's the only real bugger case. The others have near-perfect
CSS equivalents, and were presentational anyway. However, the other question
pops up: should we always convert these to the CSS forms when 1. the spec
allows them anyway and 2. older browsers support them better? After all, the
whole point about CSS is to seperate styling from content, so inline styling
doesn't solve that problem.
It's an icky question, and we'll have to deal with it as more and more
transforms get implemented.

View File

@@ -0,0 +1,10 @@
<?php
/**
* This is a stub include that automatically configures the include path.
*/
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
require_once 'HTMLPurifier.php';
?>

View File

@@ -3,7 +3,7 @@
/*! /*!
* @mainpage * @mainpage
* *
* HTMLPurifier is an HTML filter that will take an arbitrary snippet of * HTML Purifier is an HTML filter that will take an arbitrary snippet of
* HTML and rigorously test, validate and filter it into a version that * HTML and rigorously test, validate and filter it into a version that
* is safe for output onto webpages. It achieves this by: * is safe for output onto webpages. It achieves this by:
* *
@@ -22,7 +22,7 @@
*/ */
/* /*
HTMLPurifier - Standards Compliant HTML Filtering HTML Purifier - 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

View File

@@ -48,7 +48,16 @@ class HTMLPurifier_AttrDef
* *
* @note This method is not entirely standards compliant, as trim() removes * @note This method is not entirely standards compliant, as trim() removes
* more types of whitespace than specified in the spec. In practice, * more types of whitespace than specified in the spec. In practice,
* this is rarely a problem. * this is rarely a problem, as those extra characters usually have
* already been removed by HTMLPurifier_Encoder.
*
* @warning This processing is inconsistent with XML's whitespace handling
* as specified by section 3.3.3 and referenced XHTML 1.0 section
* 4.7. Compliant processing requires all line breaks normalized
* to "\n", so the fix is not as simple as fixing it in this
* function. Trim and whitespace collapsing are supposed to only
* occur in NMTOKENs. However, note that we are NOT necessarily
* parsing XML, thus, this behavior may still be correct.
* *
* @public * @public
*/ */

View File

@@ -56,6 +56,8 @@ class HTMLPurifier_ChildDef
* *
* @warning Currently this class is an all or nothing proposition, that is, * @warning Currently this class is an all or nothing proposition, that is,
* it will only give a bool return value. * it will only give a bool return value.
* @note This class is currently not used by any code, although it is unit
* tested.
*/ */
class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef
{ {

View File

@@ -26,12 +26,12 @@ class HTMLPurifier_Config
var $def; var $def;
/** /**
* Instance of HTMLPurifier_HTMLDefinition * Cached instance of HTMLPurifier_HTMLDefinition
*/ */
var $html_definition; var $html_definition;
/** /**
* Instance of HTMLPurifier_CSSDefinition * Cached instance of HTMLPurifier_CSSDefinition
*/ */
var $css_definition; var $css_definition;

View File

@@ -56,6 +56,7 @@ class HTMLPurifier_HTMLDefinition
/** /**
* String name of parent element HTML will be going into. * String name of parent element HTML will be going into.
* @todo Allow this to be overloaded by user config
* @public * @public
*/ */
var $info_parent = 'div'; var $info_parent = 'div';
@@ -111,12 +112,19 @@ class HTMLPurifier_HTMLDefinition
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// info[]->child : defines allowed children for elements // info[]->child : defines allowed children for elements
// entities: prefixed with e_ and _ replaces . // entities: prefixed with e_ and _ replaces . from DTD
// double underlines are entities we made up
// we don't use an array because that complicates interpolation // we don't use an array because that complicates interpolation
// strings are used instead of arrays because if you use arrays, // strings are used instead of arrays because if you use arrays,
// you have to do some hideous manipulation with array_merge() // you have to do some hideous manipulation with array_merge()
// todo: determine whether or not having allowed children
// that aren't allowed globally affects security (it shouldn't)
// if above works out, extend children definitions to include all
// possible elements (allowed elements will dictate which ones
// get dropped
$e_special_extra = 'img'; $e_special_extra = 'img';
$e_special_basic = 'br | span | bdo'; $e_special_basic = 'br | span | bdo';
$e_special = "$e_special_basic | $e_special_extra"; $e_special = "$e_special_basic | $e_special_extra";
@@ -142,16 +150,18 @@ class HTMLPurifier_HTMLDefinition
$e_block = "p | $e_heading | div | $e_lists | $e_blocktext | table"; $e_block = "p | $e_heading | div | $e_lists | $e_blocktext | table";
$e__flow = "#PCDATA | $e_block | $e_inline | $e_misc"; $e__flow = "#PCDATA | $e_block | $e_inline | $e_misc";
$e_Flow = new HTMLPurifier_ChildDef_Optional($e__flow); $e_Flow = new HTMLPurifier_ChildDef_Optional($e__flow);
$e_a_content = new HTMLPurifier_ChildDef_Optional("#PCDATA | $e_special". $e_a_content = new HTMLPurifier_ChildDef_Optional("#PCDATA".
" | $e_fontstyle | $e_phrase | $e_inline_forms | $e_misc_inline"); " | $e_special | $e_fontstyle | $e_phrase | $e_inline_forms".
" | $e_misc_inline");
$e_pre_content = new HTMLPurifier_ChildDef_Optional("#PCDATA | a". $e_pre_content = new HTMLPurifier_ChildDef_Optional("#PCDATA | a".
" | $e_special_basic | $e_fontstyle_basic | $e_phrase_basic". " | $e_special_basic | $e_fontstyle_basic | $e_phrase_basic".
" | $e_inline_forms | $e_misc_inline"); " | $e_inline_forms | $e_misc_inline");
$e_form_content = new HTMLPurifier_ChildDef_Optional(''); //unused $e_form_content = new HTMLPurifier_ChildDef_Optional('');//unused
$e_form_button_content = new HTMLPurifier_ChildDef_Optional(''); // unused $e_form_button_content = new HTMLPurifier_ChildDef_Optional('');//unused
$this->info['ins']->child = $this->info['ins']->child =
$this->info['del']->child = new HTMLPurifier_ChildDef_Chameleon($e__inline, $e__flow); $this->info['del']->child =
new HTMLPurifier_ChildDef_Chameleon($e__inline, $e__flow);
$this->info['blockquote']->child= $this->info['blockquote']->child=
$this->info['dd']->child = $this->info['dd']->child =
@@ -225,7 +235,7 @@ class HTMLPurifier_HTMLDefinition
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// info[]->type : defines the type of the element (block or inline) // info[]->type : defines the type of the element (block or inline)
// reuses $e_Inline and $e_block // reuses $e_Inline and $e_Block
foreach ($e_Inline->elements as $name) { foreach ($e_Inline->elements as $name) {
$this->info[$name]->type = 'inline'; $this->info[$name]->type = 'inline';
@@ -243,7 +253,7 @@ class HTMLPurifier_HTMLDefinition
$this->info['a']->excludes = array('a' => true); $this->info['a']->excludes = array('a' => true);
$this->info['pre']->excludes = array_flip(array('img', 'big', 'small', $this->info['pre']->excludes = array_flip(array('img', 'big', 'small',
// technically in spec, but we don't allow em anyway // technically useless, but good to be indepth
'object', 'applet', 'font', 'basefont')); 'object', 'applet', 'font', 'basefont'));
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@@ -253,6 +263,8 @@ class HTMLPurifier_HTMLDefinition
// by the transform classes. It will, however, do simple and slightly // by the transform classes. It will, however, do simple and slightly
// complex attribute value substitution // complex attribute value substitution
// the question of varying allowed attributes is more entangling.
$e_Text = new HTMLPurifier_AttrDef_Text(); $e_Text = new HTMLPurifier_AttrDef_Text();
// attrs, included in almost every single one except for a few, // attrs, included in almost every single one except for a few,
@@ -297,7 +309,8 @@ class HTMLPurifier_HTMLDefinition
$this->info['table']->attr['summary'] = $e_Text; $this->info['table']->attr['summary'] = $e_Text;
$this->info['table']->attr['border'] = new HTMLPurifier_AttrDef_Pixels(); $this->info['table']->attr['border'] =
new HTMLPurifier_AttrDef_Pixels();
$e_Length = new HTMLPurifier_AttrDef_Length(); $e_Length = new HTMLPurifier_AttrDef_Length();
$this->info['table']->attr['cellpadding'] = $this->info['table']->attr['cellpadding'] =
@@ -329,7 +342,7 @@ class HTMLPurifier_HTMLDefinition
$this->info['q']->attr['cite'] = $e_URI; $this->info['q']->attr['cite'] = $e_URI;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// UNIMP : info_tag_transform : transformations of tags // info_tag_transform : transformations of tags
$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');
@@ -339,6 +352,9 @@ class HTMLPurifier_HTMLDefinition
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// info[]->auto_close : tags that automatically close another // info[]->auto_close : tags that automatically close another
// todo: determine whether or not SGML-like modeling based on
// mandatory/optional end tags would be a better policy
// make sure you test using isset() not !empty() // make sure you test using isset() not !empty()
// these are all block elements: blocks aren't allowed in P // these are all block elements: blocks aren't allowed in P

View File

@@ -60,6 +60,60 @@ class HTMLPurifier_Lexer
$this->_entity_parser = new HTMLPurifier_EntityParser(); $this->_entity_parser = new HTMLPurifier_EntityParser();
} }
/**
* Most common entity to raw value conversion table for special entities.
* @protected
*/
var $_special_entity2str =
array(
'&quot;' => '"',
'&amp;' => '&',
'&lt;' => '<',
'&gt;' => '>',
'&#39;' => "'",
'&#039;' => "'",
'&#x27;' => "'"
);
/**
* Parses special entities into the proper characters.
*
* This string will translate escaped versions of the special characters
* into the correct ones.
*
* @warning
* You should be able to treat the output of this function as
* completely parsed, but that's only because all other entities should
* have been handled previously in substituteNonSpecialEntities()
*
* @param $string String character data to be parsed.
* @returns Parsed character data.
*/
function parseData($string) {
// following functions require at least one character
if ($string === '') return '';
// subtracts amps that cannot possibly be escaped
$num_amp = substr_count($string, '&') - substr_count($string, '& ') -
($string[strlen($string)-1] === '&' ? 1 : 0);
if (!$num_amp) return $string; // abort if no entities
$num_esc_amp = substr_count($string, '&amp;');
$string = strtr($string, $this->_special_entity2str);
// code duplication for sake of optimization, see above
$num_amp_2 = substr_count($string, '&') - substr_count($string, '& ') -
($string[strlen($string)-1] === '&' ? 1 : 0);
if ($num_amp_2 <= $num_esc_amp) return $string;
// hmm... now we have some uncommon entities. Use the callback.
$string = $this->_entity_parser->substituteSpecialEntities($string);
return $string;
}
var $_encoder; var $_encoder;
/** /**

View File

@@ -12,64 +12,12 @@ require_once 'HTMLPurifier/Lexer.php';
* completely eventually. * completely eventually.
* *
* @todo Reread XML spec and document differences. * @todo Reread XML spec and document differences.
* @todo Add support for CDATA sections. *
* @todo Determine correct behavior in outputting comment data. (preserve dashes?) * @todo Determine correct behavior in transforming comment data. (preserve dashes?)
* @todo Optimize main function tokenizeHTML().
* @todo Less than sign (<) being prohibited (even as entity) in attr-values?
*/ */
class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
{ {
/**
* Most common entity to raw value conversion table for special entities.
* @protected
*/
var $_special_entity2str =
array(
'&quot;' => '"',
'&amp;' => '&',
'&lt;' => '<',
'&gt;' => '>',
'&#39;' => "'",
'&#039;' => "'",
'&#x27;' => "'"
);
/**
* Parses special entities into the proper characters.
*
* This string will translate escaped versions of the special characters
* into the correct ones.
*
* @warning
* You should be able to treat the output of this function as
* completely parsed, but that's only because all other entities should
* have been handled previously in substituteNonSpecialEntities()
*
* @param $string String character data to be parsed.
* @returns Parsed character data.
*/
function parseData($string) {
// subtracts amps that cannot possibly be escaped
$num_amp = substr_count($string, '&') - substr_count($string, '& ') -
($string[strlen($string)-1] === '&' ? 1 : 0);
if (!$num_amp) return $string; // abort if no entities
$num_esc_amp = substr_count($string, '&amp;');
$string = strtr($string, $this->_special_entity2str);
// code duplication for sake of optimization, see above
$num_amp_2 = substr_count($string, '&') - substr_count($string, '& ') -
($string[strlen($string)-1] === '&' ? 1 : 0);
if ($num_amp_2 <= $num_esc_amp) return $string;
// hmm... now we have some uncommon entities. Use the callback.
$string = $this->_entity_parser->substituteSpecialEntities($string);
return $string;
}
/** /**
* Whitespace characters for str(c)spn. * Whitespace characters for str(c)spn.
* @protected * @protected

View File

@@ -18,6 +18,8 @@ require_once 'HTMLPurifier/Lexer.php';
* whatever it does for poorly formed HTML is up to it. * whatever it does for poorly formed HTML is up to it.
* *
* @todo Generalize so that XML_HTMLSax is also supported. * @todo Generalize so that XML_HTMLSax is also supported.
*
* @warning Entity-resolution inside attributes is broken.
*/ */
class HTMLPurifier_Lexer_PEARSax3 extends HTMLPurifier_Lexer class HTMLPurifier_Lexer_PEARSax3 extends HTMLPurifier_Lexer
@@ -41,6 +43,8 @@ class HTMLPurifier_Lexer_PEARSax3 extends HTMLPurifier_Lexer
$parser->set_element_handler('openHandler','closeHandler'); $parser->set_element_handler('openHandler','closeHandler');
$parser->set_data_handler('dataHandler'); $parser->set_data_handler('dataHandler');
$parser->set_escape_handler('escapeHandler'); $parser->set_escape_handler('escapeHandler');
// doesn't seem to work correctly for attributes
$parser->set_option('XML_OPTION_ENTITIES_PARSED', 1); $parser->set_option('XML_OPTION_ENTITIES_PARSED', 1);
$parser->parse($string); $parser->parse($string);
@@ -53,6 +57,10 @@ class HTMLPurifier_Lexer_PEARSax3 extends HTMLPurifier_Lexer
* Open tag event handler, interface is defined by PEAR package. * Open tag event handler, interface is defined by PEAR package.
*/ */
function openHandler(&$parser, $name, $attrs, $closed) { function openHandler(&$parser, $name, $attrs, $closed) {
// entities are not resolved in attrs
foreach ($attrs as $key => $attr) {
$attrs[$key] = $this->parseData($attr);
}
if ($closed) { if ($closed) {
$this->tokens[] = new HTMLPurifier_Token_Empty($name, $attrs); $this->tokens[] = new HTMLPurifier_Token_Empty($name, $attrs);
} else { } else {

View File

@@ -4,7 +4,6 @@ require_once 'HTMLPurifier/URIScheme.php';
/** /**
* Validates ftp (File Transfer Protocol) URIs as defined by generic RFC 1738. * Validates ftp (File Transfer Protocol) URIs as defined by generic RFC 1738.
* @todo Typecode check on path
*/ */
class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme { class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme {
@@ -16,7 +15,27 @@ class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme {
list($userinfo, $host, $port, $path, $query) = list($userinfo, $host, $port, $path, $query) =
parent::validateComponents( parent::validateComponents(
$userinfo, $host, $port, $path, $query, $config ); $userinfo, $host, $port, $path, $query, $config );
// typecode check needed on path $semicolon_pos = strrpos($path, ';'); // reverse
if ($semicolon_pos !== false) {
// typecode check
$type = substr($path, $semicolon_pos + 1); // no semicolon
$path = substr($path, 0, $semicolon_pos);
$type_ret = '';
if (strpos($type, '=') !== false) {
// figure out whether or not the declaration is correct
list($key, $typecode) = explode('=', $type, 2);
if ($key !== 'type') {
// invalid key, tack it back on encoded
$path .= '%3B' . $type;
} elseif ($typecode === 'a' || $typecode === 'i' || $typecode === 'd') {
$type_ret = ";type=$typecode";
}
} else {
$path .= '%3B' . $type;
}
$path = str_replace(';', '%3B', $path);
$path .= $type_ret;
}
return array($userinfo, $host, $port, $path, null); return array($userinfo, $host, $port, $path, null);
} }

View File

@@ -1 +1 @@
Deny from all Deny from all

View File

@@ -1,100 +1,100 @@
;; phpDocumentor parse configuration file ;; phpDocumentor parse configuration file
;; ;;
;; This file is designed to cut down on repetitive typing on the command-line or web interface ;; This file is designed to cut down on repetitive typing on the command-line or web interface
;; You can copy this file to create a number of configuration files that can be used with the ;; You can copy this file to create a number of configuration files that can be used with the
;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web ;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web
;; interface will automatically generate a list of .ini files that can be used. ;; interface will automatically generate a list of .ini files that can be used.
;; ;;
;; default.ini is used to generate the online manual at http://www.phpdoc.org/docs ;; default.ini is used to generate the online manual at http://www.phpdoc.org/docs
;; ;;
;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini ;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
;; ;;
;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net> ;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
;; ;;
;; WARNING: do not change the name of any command-line parameters, phpDocumentor will ignore them ;; WARNING: do not change the name of any command-line parameters, phpDocumentor will ignore them
[Parse Data] [Parse Data]
;; title of all the documentation ;; title of all the documentation
;; legal values: any string ;; legal values: any string
title = HTML Purifier API Documentation title = HTML Purifier API Documentation
;; parse files that start with a . like .bash_profile ;; parse files that start with a . like .bash_profile
;; legal values: true, false ;; legal values: true, false
hidden = false hidden = false
;; show elements marked @access private in documentation by setting this to on ;; show elements marked @access private in documentation by setting this to on
;; legal values: on, off ;; legal values: on, off
parseprivate = off parseprivate = off
;; parse with javadoc-like description (first sentence is always the short description) ;; parse with javadoc-like description (first sentence is always the short description)
;; legal values: on, off ;; legal values: on, off
javadocdesc = on javadocdesc = on
;; add any custom @tags separated by commas here ;; add any custom @tags separated by commas here
;; legal values: any legal tagname separated by commas. ;; legal values: any legal tagname separated by commas.
;customtags = mytag1,mytag2 ;customtags = mytag1,mytag2
;; This is only used by the XML:DocBook/peardoc2 converter ;; This is only used by the XML:DocBook/peardoc2 converter
defaultcategoryname = Documentation defaultcategoryname = Documentation
;; what is the main package? ;; what is the main package?
;; legal values: alphanumeric string plus - and _ ;; legal values: alphanumeric string plus - and _
defaultpackagename = HTMLPurifier defaultpackagename = HTMLPurifier
;; output any parsing information? set to on for cron jobs ;; output any parsing information? set to on for cron jobs
;; legal values: on ;; legal values: on
;quiet = on ;quiet = on
;; parse a PEAR-style repository. Do not turn this on if your project does ;; parse a PEAR-style repository. Do not turn this on if your project does
;; not have a parent directory named "pear" ;; not have a parent directory named "pear"
;; legal values: on/off ;; legal values: on/off
;pear = on ;pear = on
;; where should the documentation be written? ;; where should the documentation be written?
;; legal values: a legal path ;; legal values: a legal path
target = docs/phpdoc target = docs/phpdoc
;; Which files should be parsed out as special documentation files, such as README, ;; Which files should be parsed out as special documentation files, such as README,
;; INSTALL and CHANGELOG? This overrides the default files found in ;; INSTALL and CHANGELOG? This overrides the default files found in
;; phpDocumentor.ini (this file is not a user .ini file, but the global file) ;; phpDocumentor.ini (this file is not a user .ini file, but the global file)
readmeinstallchangelog = README, INSTALL, NEWS, WYSIWYG, SLOW, LICENSE, CREDITS readmeinstallchangelog = README, INSTALL, NEWS, WYSIWYG, SLOW, LICENSE, CREDITS
;; limit output to the specified packages, even if others are parsed ;; limit output to the specified packages, even if others are parsed
;; legal values: package names separated by commas ;; legal values: package names separated by commas
;packageoutput = package1,package2 ;packageoutput = package1,package2
;; comma-separated list of files to parse ;; comma-separated list of files to parse
;; legal values: paths separated by commas ;; legal values: paths separated by commas
;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory ;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
;; comma-separated list of directories to parse ;; comma-separated list of directories to parse
;; legal values: directory paths separated by commas ;; legal values: directory paths separated by commas
;directory = /path1,/path2,.,..,subdirectory ;directory = /path1,/path2,.,..,subdirectory
;directory = /home/jeichorn/cvs/pear ;directory = /home/jeichorn/cvs/pear
directory = ./ directory = ./
;; template base directory (the equivalent directory of <installdir>/phpDocumentor) ;; template base directory (the equivalent directory of <installdir>/phpDocumentor)
;templatebase = /path/to/my/templates ;templatebase = /path/to/my/templates
;; directory to find any example files in through @example and {@example} tags ;; directory to find any example files in through @example and {@example} tags
;examplesdir = /path/to/my/templates ;examplesdir = /path/to/my/templates
;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore ;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
;; legal values: any wildcard strings separated by commas ;; legal values: any wildcard strings separated by commas
;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/ ;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
ignore = pear-*,templates/,Documentation/,test*.php,Lexer.inc ignore = pear-*,templates/,Documentation/,test*.php,Lexer.inc
sourcecode = on sourcecode = on
;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format ;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib, ;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,
;; HTML:frames:earthli, ;; HTML:frames:earthli,
;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de, ;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,
;; HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli ;; HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli
;; HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS ;; HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS
;; PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default ;; PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default
output=HTML:frames:default output=HTML:frames:default
;; turn this option on if you want highlighted source code for every file ;; turn this option on if you want highlighted source code for every file
;; legal values: on/off ;; legal values: on/off
sourcecode = on sourcecode = on

View File

@@ -46,18 +46,23 @@ class HTMLPurifier_ChildDefTest extends UnitTestCase
$this->def = new HTMLPurifier_ChildDef_Custom( $this->def = new HTMLPurifier_ChildDef_Custom(
'(a, b?, c*, d+, (a, b)*)'); '(a, b?, c*, d+, (a, b)*)');
$inputs = array();
$expect = array();
$config = array();
$inputs[0] = ''; $inputs[0] = '';
$expect[0] = false; $expect[0] = false;
$inputs[1] = '<a /><b /><c /><d /><a /><b />'; $inputs[1] = '<a /><b /><c /><d /><a /><b />';
$expect[1] = true; $expect[1] = true;
$inputs[2] = '<a /><d>Dob</d><a /><b>foo</b><a href="moo"><b>foo</b>'; $inputs[2] = '<a /><d>Dob</d><a /><b>foo</b><a href="moo" /><b>foo</b>';
$expect[2] = true; $expect[2] = true;
$inputs[3] = '<a /><a />'; $inputs[3] = '<a /><a />';
$expect[3] = false; $expect[3] = false;
$this->assertSeries($inputs, $expect, $config);
} }
function test_table() { function test_table() {

View File

@@ -8,6 +8,7 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
var $our_copy, $old_copy; var $our_copy, $old_copy;
function setUp() { function setUp() {
// set up a dummy schema object for testing
$our_copy = new HTMLPurifier_ConfigSchema(); $our_copy = new HTMLPurifier_ConfigSchema();
$this->old_copy = HTMLPurifier_ConfigSchema::instance(); $this->old_copy = HTMLPurifier_ConfigSchema::instance();
$this->our_copy =& HTMLPurifier_ConfigSchema::instance($our_copy); $this->our_copy =& HTMLPurifier_ConfigSchema::instance($our_copy);
@@ -93,6 +94,17 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
} }
function test_getDefinition() {
$config = HTMLPurifier_Config::createDefault();
$def = $config->getHTMLDefinition();
$this->assertIsA($def, 'HTMLPurifier_HTMLDefinition');
$def = $config->getCSSDefinition();
$this->assertIsA($def, 'HTMLPurifier_CSSDefinition');
}
} }
?> ?>

View File

@@ -11,24 +11,6 @@ class HTMLPurifier_Lexer_DirectLexTest extends UnitTestCase
$this->DirectLex = new HTMLPurifier_Lexer_DirectLex(); $this->DirectLex = new HTMLPurifier_Lexer_DirectLex();
} }
function test_parseData() {
$HP =& $this->DirectLex;
$this->assertIdentical('asdf', $HP->parseData('asdf'));
$this->assertIdentical('&', $HP->parseData('&amp;'));
$this->assertIdentical('"', $HP->parseData('&quot;'));
$this->assertIdentical("'", $HP->parseData('&#039;'));
$this->assertIdentical("'", $HP->parseData('&#39;'));
$this->assertIdentical('&&&', $HP->parseData('&amp;&amp;&amp;'));
$this->assertIdentical('&&', $HP->parseData('&amp;&')); // [INVALID]
$this->assertIdentical('Procter & Gamble',
$HP->parseData('Procter & Gamble')); // [INVALID]
// This is not special, thus not converted. Test of fault tolerance,
// realistically speaking, this should never happen
$this->assertIdentical('&#x2D;', $HP->parseData('&#x2D;'));
}
// internals testing // internals testing
function test_parseAttributeString() { function test_parseAttributeString() {

View File

@@ -38,6 +38,25 @@ class HTMLPurifier_LexerTest extends UnitTestCase
$this->assertIdentical($extract, $result); $this->assertIdentical($extract, $result);
} }
function test_parseData() {
$HP =& $this->Lexer;
$this->assertIdentical('asdf', $HP->parseData('asdf'));
$this->assertIdentical('&', $HP->parseData('&amp;'));
$this->assertIdentical('"', $HP->parseData('&quot;'));
$this->assertIdentical("'", $HP->parseData('&#039;'));
$this->assertIdentical("'", $HP->parseData('&#39;'));
$this->assertIdentical('&&&', $HP->parseData('&amp;&amp;&amp;'));
$this->assertIdentical('&&', $HP->parseData('&amp;&')); // [INVALID]
$this->assertIdentical('Procter & Gamble',
$HP->parseData('Procter & Gamble')); // [INVALID]
// This is not special, thus not converted. Test of fault tolerance,
// realistically speaking, this should never happen
$this->assertIdentical('&#x2D;', $HP->parseData('&#x2D;'));
}
function test_extractBody() { function test_extractBody() {
$this->assertExtractBody('<b>Bold</b>'); $this->assertExtractBody('<b>Bold</b>');
$this->assertExtractBody('<html><body><b>Bold</b></body></html>', '<b>Bold</b>'); $this->assertExtractBody('<html><body><b>Bold</b></body></html>', '<b>Bold</b>');
@@ -249,13 +268,16 @@ class HTMLPurifier_LexerTest extends UnitTestCase
,new HTMLPurifier_Token_Text('Link') ,new HTMLPurifier_Token_Text('Link')
,new HTMLPurifier_Token_End('a') ,new HTMLPurifier_Token_End('a')
); );
$sax_expect[16] = false; // PEARSax doesn't support it!
// test that UTF-8 is preserved // test that UTF-8 is preserved
$char_hearts = $this->_entity_lookup->table['hearts']; $char_hearts = $this->_entity_lookup->table['hearts'];
$input[17] = $char_hearts; $input[17] = $char_hearts;
$expect[17] = array( new HTMLPurifier_Token_Text($char_hearts) ); $expect[17] = array( new HTMLPurifier_Token_Text($char_hearts) );
// test weird characters in attributes
$input[18] = '<br test="x &lt; 6" />';
$expect[18] = array( new HTMLPurifier_Token_Empty('br', array('test' => 'x < 6')) );
$default_config = HTMLPurifier_Config::createDefault(); $default_config = HTMLPurifier_Config::createDefault();
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;

View File

@@ -54,12 +54,34 @@ class HTMLPurifier_URISchemeTest extends UnitTestCase
$scheme = new HTMLPurifier_URIScheme_ftp(); $scheme = new HTMLPurifier_URIScheme_ftp();
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();
$this->assertIdentical( $this->assertIdentical(
$scheme->validateComponents( $scheme->validateComponents(
'user', 'www.example.com', 21, '/', 's=foobar', $config), 'user', 'www.example.com', 21, '/', 's=foobar', $config),
array('user', 'www.example.com', null, '/', null) array('user', 'www.example.com', null, '/', null)
); );
// valid typecode
$this->assertIdentical(
$scheme->validateComponents(
null, 'www.example.com', null, '/file.txt;type=a', null, $config),
array(null, 'www.example.com', null, '/file.txt;type=a', null)
);
// remove invalid typecode
$this->assertIdentical(
$scheme->validateComponents(
null, 'www.example.com', null, '/file.txt;type=z', null, $config),
array(null, 'www.example.com', null, '/file.txt', null)
);
// encode errant semicolons
$this->assertIdentical(
$scheme->validateComponents(
null, 'www.example.com', null, '/too;many;semicolons=1', null, $config),
array(null, 'www.example.com', null, '/too%3Bmany%3Bsemicolons=1', null)
);
} }
function test_news() { function test_news() {

View File

@@ -114,14 +114,14 @@ if (isset($_GET['file']) && isset($test_file_lookup[$_GET['file']])) {
// execute only one test // execute only one test
$test_file = $_GET['file']; $test_file = $_GET['file'];
$test = new GroupTest('HTMLPurifier - ' . $test_file); $test = new GroupTest('HTML Purifier - ' . $test_file);
$path = 'HTMLPurifier/' . $test_file; $path = 'HTMLPurifier/' . $test_file;
require_once $path; require_once $path;
$test->addTestClass(htmlpurifier_path2class($path)); $test->addTestClass(htmlpurifier_path2class($path));
} else { } else {
$test = new GroupTest('HTMLPurifier'); $test = new GroupTest('HTML Purifier');
foreach ($test_files as $test_file) { foreach ($test_files as $test_file) {
$path = 'HTMLPurifier/' . $test_file; $path = 'HTMLPurifier/' . $test_file;