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

Compare commits

..

7 Commits

Author SHA1 Message Date
Edward Z. Yang
374736ae44 Merged revisions 380:382 from trunk/ to branches/1.0/:
- Disambiguate between iconv and PHP test runs for cleanUTF8.
- Fixed rejection of inline style declarations that had lots of extra space in them.  This manifested in TinyMCE.

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.0@383 48356398-32a2-884e-a903-53898d9a118a
2006-09-04 23:12:32 +00:00
Edward Z. Yang
0c4a9c0479 Merged 359:260 from trunk/ to branches/1.0/
- Bump Doxyfile version number, add spaces in-between HTML Purifier.

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.0@373 48356398-32a2-884e-a903-53898d9a118a
2006-09-01 17:54:47 +00:00
Edward Z. Yang
06e8b022a4 Add integration test.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.0@372 48356398-32a2-884e-a903-53898d9a118a
2006-09-01 17:50:55 +00:00
Edward Z. Yang
81a03bd16c Merged 369:370 from trunk/ to branches/1.0
- Bump tested in version number.

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.0@371 48356398-32a2-884e-a903-53898d9a118a
2006-09-01 17:21:26 +00:00
Edward Z. Yang
5770001006 Merged revisions 366:367 from trunk/ to branches/1.0
- Fixed rejection of case-insensitive configuration values when there is a set of allowed values.  This manifested in %Core.Encoding.
- Added Test namespace

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.0@369 48356398-32a2-884e-a903-53898d9a118a
2006-09-01 16:58:29 +00:00
Edward Z. Yang
55974e5964 Merged revisions 363:365 from trunk/ to branches/1.0/
- Fixed slight bug in DOMLex's attribute parsing.

git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.0@366 48356398-32a2-884e-a903-53898d9a118a
2006-09-01 16:24:35 +00:00
Edward Z. Yang
e789bc69eb Create 1.0 branch for maintenance fixes.
git-svn-id: http://htmlpurifier.org/svnroot/htmlpurifier/branches/1.0@359 48356398-32a2-884e-a903-53898d9a118a
2006-09-01 15:07:58 +00:00
59 changed files with 800 additions and 1602 deletions

View File

@@ -4,7 +4,7 @@
# Project related configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = HTML Purifier
PROJECT_NUMBER = 1.1.2
PROJECT_NUMBER = 1.0.0
OUTPUT_DIRECTORY = "C:/Documents and Settings/Edward/My Documents/My Webs/htmlpurifier/docs/doxygen"
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
@@ -89,12 +89,9 @@ EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */tests/* \
*/benchmarks/* \
*/docs/* \
*/test-settings.php \
*/configdoc/* \
*/test-settings.php \
*/maintenance/* \
*/smoketests/*
*/docs/phpdoc/* \
*/docs/doxygen/* \
*/test-settings.php
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO

201
INSTALL
View File

@@ -2,188 +2,89 @@
Install
How to install HTML Purifier
HTML Purifier is designed to run out of the box, so actually using the library
is extremely easy. (Although, if you were looking for a step-by-step
installation GUI, you've come to the wrong place!) The impatient can scroll
down to the bottom of this INSTALL document to see the code, but you really
should make sure a few things are properly done.
Being a library, there's no fancy GUI that will take you step-by-step through
configuring database credentials and other mumbo-jumbo. HTML Purifier is
designed to run "out of the box." Regardless, there are still a couple of
things you should be mindful of.
1. Compatibility
0. Compatibility
HTML Purifier works in both PHP 4 and PHP 5, from PHP 4.3.9 and up. It has no
core dependencies with other libraries. (Whoopee!)
HTML Purifier works in both PHP 4 and PHP 5. I have run the test suite on
these versions:
Optional extensions are iconv (usually installed) and tidy (also common).
If you use UTF-8 and don't plan on pretty-printing HTML, you can get away with
not having either of these extensions.
- 4.3.9, 4.3.11
- 4.4.0, 4.4.4
- 5.0.0, 5.0.4
- 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 is quite irrelevant in this particular case.
2. Including the library
1. Including the proper files
Simply use:
The library/ directory must be added to your path: HTML Purifier will not be
able to find the necessary includes otherwise. This is as simple as:
require_once '/path/to/library/HTMLPurifier.auto.php';
set_include_path('/path/to/htmlpurifier/library' . PATH_SEPARATOR . get_include_path());
...and you're good to go. Since HTML Purifier's codebase is fairly
large, I recommend only including HTML Purifier when you need it.
...replacing /path/to/htmlpurifier with the actual location of the folder. Don't
worry, HTML Purifier is namespaced so unless you have another file named
HTMLPurifier.php, the files won't collide with any of your includes.
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:
Then, it's a simple matter of including the base file:
require_once 'HTMLPurifier.php';
require_once 'HTMLPurifier.php';
Only the contents in the library/ folder are necessary, so you can remove
everything else when using HTML Purifier in a production environment.
...and you're good to go.
3. Preparing the proper output environment
2. Preparing the proper environment
HTML Purifier is all about web-standards, so accordingly your webpages should
be standards compliant. HTML Purifier can deal with these doctypes:
While no configuration is necessary, you first should take precautions regarding
the other output HTML that the filtered content will be going along with. Here
is a (short) checklist:
* XHTML 1.0 Transitional (default)
* HTML 4.01 Transitional
* Have I specified XHTML 1.0 Transitional as the doctype?
* Have I specified UTF-8 as the character encoding?
...and these character encodings:
I cannot stress the importance of these two bullets enough. Omitting either
of them could have dire consequences not only for security but for plain
old usability. You can find a more in-depth discussion of why this is needed
in docs/security.txt, in the meantime, try to change your output so this is
the case.
* 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:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
...and the character encoding from this code:
<meta http-equiv="Content-type" content="text/html;charset=ENCODING">
For legacy codebases these declarations may be missing. If that is the case,
STOP, and read up on character encodings and doctypes (in that order). Here
are some links:
* http://www.joelonsoftware.com/articles/Unicode.html
* 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.
4. Configuration
HTML Purifier is designed to run out-of-the-box, but occasionally HTML
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).
* Am I using UTF-8?
* Am I using XHTML 1.0 Transitional?
If you answered yes to any of these questions, instantiate a configuration
object and read on:
If, for some reason, you are unable to switch to UTF-8 immediately, you can
switch HTML Purifier's encoding. Note that the availability of encodings is
dependent on iconv, and you'll be missing characters if the charset you
choose doesn't have them.
$config = HTMLPurifier_Config::createDefault();
$config->set('Core', 'Encoding', $encoding);
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 */);
An example usage for Latin-1 websites (the most common encoding for English
websites):
$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
XHTML output like this:
$config->set('Core', 'XHTML', false);
I recommend that you use XHTML, although not as much as I recommend UTF-8. If
your HTML 4.01 page validates, good for you!
Currently, we can only guarantee transitional-complaint output, future
versions will also allow strict-compliant output.
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
3. Using the code
The interface is mind-numbingly simple:
$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);
$clean_html = $purifier->purify( $dirty_html );
That's it! For more examples, check out docs/examples/ (they aren't very
different though). Also, SLOW gives advice on what to do if HTML Purifier
is slowing down your application.
6. Quick install
If your website is in UTF-8 and XHTML Transitional, use this code:
<?php
require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
$purifier = new HTMLPurifier();
$clean_html = $purifier->purify($dirty_html);
?>
If your website is in a different encoding or doctype, use this code:
<?php
require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
$config = HTMLPurifier_Config::createDefault();
$config->set('Core', 'Encoding', 'ISO-8859-1'); //replace with your encoding
$config->set('Core', 'XHTML', true); //replace with false if HTML 4.01
$purifier = new HTMLPurifier($config);
$clean_html = $purifier->purify($dirty_html);
?>
That's it. For more examples, check out docs/examples/. Also, SLOW gives
advice on what to do if HTML Purifier is slowing down your application.

64
NEWS
View File

@@ -1,49 +1,7 @@
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
! 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
- Fixed parse error in configuration documentation script
- Fixed fatal error in benchmark scripts, slightly augmented
- As far as possible, whitespace is preserved in-between table children
- Sample test-settings.php file included
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
quotes, apostrophes and less than or greater than signs.
- Enforce alphanumeric namespace and directive names for configuration.
- Table child definition made more flexible, will fix up poorly ordered elements
. Renamed ConfigDef to ConfigSchema
1.0.1, released 2006-09-04
1.0.1, unknown release date
- Fixed slight bug in DOMLex attribute parsing
- Fixed rejection of case-insensitive configuration values when there is a
set of allowed values. This manifested in %Core.Encoding.
@@ -51,17 +9,17 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
space in them. This manifested in TinyMCE.
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
- Malformed UTF-8 and non-SGML character detection and cleaning implemented
- API documentation completed
. (HTML|CSS)Definition de-singleton-ized
- Shorthand CSS properties implemented: font, border, background, list-style
- 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
! First public release, most functionality implemented. Notable omissions are:
+ Shorthand CSS properties
+ Table CSS properties
+ Deprecated attribute transformations
- First public release, most functionality implemented. Notable omissions are:
. Shorthand CSS properties
. Table CSS properties
. Deprecated attribute transformations

24
README
View File

@@ -1,13 +1,13 @@
README
All about HTMLPurifier
README
All about HTMLPurifier
HTMLPurifier is an HTML filtering solution. It uses a unique combination of
robust whitelists and agressive parsing to ensure that not only are XSS
attacks thwarted, but the resulting HTML is standards compliant.
See INSTALL on how to use the library. See docs/ for more developer-oriented
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/
HTMLPurifier is an HTML filtering solution. It uses a unique combination of
robust whitelists and agressive parsing to ensure that not only are XSS
attacks thwarted, but the resulting HTML is standards compliant.
See INSTALL on how to use the library. See docs/ for more developer-oriented
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/

13
SLOW
View File

@@ -17,23 +17,18 @@ second tacked on to the load time probably isn't going to be that huge of
a problem. Then, displaying the content is a simple a manner of outputting
it directly from your database/filesystem. The trouble with this method is
that your user loses the original text, and when doing edits, will be
handling the filtered text. While this may be a good thing, especially if
you're using a WYSIWYG editor, it can also result in data-loss if a user
expects a certain to be available but it doesn't.
handling the filtered text. Of course, maybe that's a good thing. If you
don't mind a little extra complexity, you can try...
2. Caching the filtered output - accept the submitted text and put it
unaltered into the database, but then also generate a filtered version and
stash that in the database. Serve the filtered version to readers, and the
unaltered version to editors. If need be, you can invalidate the cache and
have the cached filtered version be regenerated on the first page view. Pros?
Full data retention. Cons? It's more complicated, and opens other editors
up to XSS if they are using a WYSIWYG editor (to fix that, they'd have to
be able to get their hands on the *really* original text served in plaintext
mode).
Full data retention. Cons? It's more complicated.
In short, inbound filtering is almost as simple as outbound filtering, but
it has some drawbacks which cannot be fixed unless you save both the original
and the filtered versions.
There is a third option: profile and optimize HTMLPurifier yourself. Be sure
to tell me if you decide to do that! ;-)
There is a third option: profile and optimize HTMLPurifier yourself. ;-)

33
TODO
View File

@@ -5,34 +5,33 @@ Ongoing
- Lots of profiling, make it faster!
- Plugins for major CMSes (very tricky issue)
1.1 release
- Directive documentation generation
- Rewrite table's child definition to be faster, smart, and regexp free
- Allow HTML 4.01 output (cosmetic changes to the generator)
1.2 release
- Additional support for poorly written HTML
- Implement all non-essential attribute transforms
- Microsoft Word HTML cleaning (i.e. MsoNormal)
1.3 release
- Make URI validation routines tighter (especially mailto)
- More extensive URI filtering schemes
- Allow for background-image and list-style-image (see above)
- Distinguish between different types of URIs, for instance, a mailto URI
in IMG SRC is nonsensical
- Error logging for filtering/cleanup procedures
1.3 release
- Add various "levels" of cleaning
- Related: Allow strict (X)HTML
1.4 release
- Additional support for poorly written HTML
- Implement all non-essential attribute transforms
- Microsoft Word HTML cleaning (i.e. MsoNormal)
2.0 release
- Formatters for plaintext
- Auto-paragraphing (be sure to leverage fact that we know when things
shouldn't be paragraphed, such as lists and tables).
- Linkify URLs
- Smileys
- Add various "levels" of cleaning
- Related: Allow strict (X)HTML
3.0 release
- Extended HTML capabilities based on namespacing and tag transforms
- Hooks for adding custom processors to custom namespaced tags and
attributes, offer default implementation
- Auto-paragraphing (be sure to leverage fact that we know when things
shouldn't be paragraphed, such as lists and tables).
- Lots of documentation and samples
Unknown release (on a scratch-an-itch basis)
@@ -43,11 +42,9 @@ Unknown release (on a scratch-an-itch basis)
- Fixes for Firefox's inability to handle COL alignment props (Bug 915)
- Automatically add non-breaking spaces to empty table cells when
empty-cells:show is applied to have compatibility with Internet Explorer
- Pretty-printing HTML (adds dependency of Generator to HTMLDefinition)
- Non-lossy dumb alternate character encoding transformations, achieved by
numerically encoding all non-ASCII characters
- Semi-lossy dumb alternate character encoding transformations, achieved by
encoding all characters that have string entity equivalents
Wontfix
- Non-lossy smart alternate character encoding transformations
- Pretty-printing HTML, users can use Tidy on the output on entire page

View File

@@ -1,6 +1,6 @@
WYSIWYG - What You See Is What You Get
HTML Purifier: A Pretty Good Fit for TinyMCE and FCKeditor
HTMLPurifier: A Pretty Good Fit for TinyMCE and FCKeditor
Javascript-based WYSIWYG editors, simply stated, are quite amazing. But I've
always been wary about using them due to security issues: they handle the
@@ -13,9 +13,6 @@ other markup languages still reign supreme. Put simply: filtering HTML is
hard work, and these WYSIWYG authors don't offer anything to alleviate that
trouble. Therein lies the solution:
HTML Purifier is perfect for filtering pure-HTML input from WYSIWYG editors.
HTMLPurifier is perfect for filtering pure-HTML input from WYSIWYG editors.
Enough said.
There is a proof-of-concept integration of HTML Purifier with the Mantis
bugtracker at http://hp.jpsband.org/mantis/

View File

@@ -3,24 +3,15 @@
// emulates inserting a dir called HTMLPurifier into your class dir
set_include_path(get_include_path() . PATH_SEPARATOR . '../library/');
@include_once '../test-settings.php';
require_once 'HTMLPurifier/ConfigSchema.php';
require_once 'HTMLPurifier/ConfigDef.php';
require_once 'HTMLPurifier/Config.php';
$LEXERS = array();
$RUNS = isset($GLOBALS['HTMLPurifierTest']['Runs'])
? $GLOBALS['HTMLPurifierTest']['Runs'] : 2;
require_once 'HTMLPurifier/Lexer/DirectLex.php';
$LEXERS['DirectLex'] = new HTMLPurifier_Lexer_DirectLex();
require_once 'HTMLPurifier/Lexer/PEARSax3.php';
if (!empty($GLOBALS['HTMLPurifierTest']['PEAR'])) {
require_once 'HTMLPurifier/Lexer/PEARSax3.php';
$LEXERS['PEARSax3'] = new HTMLPurifier_Lexer_PEARSax3();
} else {
exit('PEAR required to perform benchmark.');
}
$LEXERS = array(
'DirectLex' => new HTMLPurifier_Lexer_DirectLex(),
'PEARSax3' => new HTMLPurifier_Lexer_PEARSax3()
);
if (version_compare(PHP_VERSION, '5', '>=')) {
require_once 'HTMLPurifier/Lexer/DOMLex.php';
@@ -65,12 +56,9 @@ class RowTimer extends Benchmark_Timer
if ($standard == false) $standard = $v['diff'];
$perc = $v['diff'] * 100 / $standard;
$bad_run = ($v['diff'] < 0);
$out .= '<td align="right"'.
($bad_run ? ' style="color:#AAA;"' : '').
'>' . number_format($perc, 2, '.', '') .
'%</td><td>'.number_format($v['diff'],4,'.','').'</td>';
$out .= '<td align="right">' . number_format($perc, 2, '.', '') .
'%</td>';
}
@@ -91,13 +79,13 @@ function print_lexers() {
}
function do_benchmark($name, $document) {
global $LEXERS, $RUNS;
global $LEXERS;
$timer = new RowTimer($name);
$timer->start();
foreach($LEXERS as $key => $lexer) {
for ($i=0; $i<$RUNS; $i++) $tokens = $lexer->tokenizeHTML($document);
$tokens = $lexer->tokenizeHTML($document);
$timer->setMarker($key);
}
@@ -115,7 +103,7 @@ function do_benchmark($name, $document) {
<table border="1">
<tr><th>Case</th><?php
foreach ($LEXERS as $key => $value) {
echo '<th colspan="2">' . htmlspecialchars($key) . '</th>';
echo '<th>' . htmlspecialchars($key) . '</th>';
}
?></tr>
<?php

View File

@@ -2,7 +2,7 @@
set_include_path(get_include_path() . PATH_SEPARATOR . '../library/');
require_once 'HTMLPurifier/ConfigSchema.php';
require_once 'HTMLPurifier/ConfigDef.php';
require_once 'HTMLPurifier/Config.php';
require_once 'HTMLPurifier/Lexer/DirectLex.php';

View File

@@ -1,214 +0,0 @@
<?php
/**
* Generates XML and HTML documents describing configuration.
*/
/*
TODO:
- make XML format richer (see below)
- extend XSLT transformation (see the corresponding XSLT file)
- allow generation of packaged docs that can be easily moved
- multipage documentation
- determine how to multilingualize
- factor out code into classes
- generate a table of contents
*/
// ---------------------------------------------------------------------------
// Check and configure environment
if (version_compare('5', PHP_VERSION, '>')) exit('Requires PHP 5 or higher.');
error_reporting(E_ALL);
// ---------------------------------------------------------------------------
// Include HTML Purifier library
set_include_path('../library' . PATH_SEPARATOR . get_include_path());
require_once 'HTMLPurifier.php';
// ---------------------------------------------------------------------------
// Setup convenience functions
function appendHTMLDiv($document, $node, $html) {
global $purifier;
$html = $purifier->purify($html);
$dom_html = $document->createDocumentFragment();
$dom_html->appendXML($html);
$dom_div = $document->createElement('div');
$dom_div->setAttribute('xmlns', 'http://www.w3.org/1999/xhtml');
$dom_div->appendChild($dom_html);
$node->appendChild($dom_div);
}
// ---------------------------------------------------------------------------
// Load copies of HTMLPurifier_ConfigDef and HTMLPurifier
$schema = HTMLPurifier_ConfigSchema::instance();
$purifier = new HTMLPurifier();
// ---------------------------------------------------------------------------
// Generate types.xml, a document describing the constraint "type"
$types_document = new DOMDocument('1.0', 'UTF-8');
$types_root = $types_document->createElement('types');
$types_document->appendChild($types_root);
$types_document->formatOutput = true;
foreach ($schema->types as $name => $expanded_name) {
$types_type = $types_document->createElement('type', $expanded_name);
$types_type->setAttribute('id', $name);
$types_root->appendChild($types_type);
}
$types_document->save('types.xml');
// ---------------------------------------------------------------------------
// Generate configdoc.xml, a document documenting configuration directives
$dom_document = new DOMDocument('1.0', 'UTF-8');
$dom_root = $dom_document->createElement('configdoc');
$dom_document->appendChild($dom_root);
$dom_document->formatOutput = true;
// add the name of the application
$dom_root->appendChild($dom_document->createElement('title', 'HTML Purifier'));
/*
TODO for XML format:
- namespace descriptions
- enumerated values
- default values
- create a definition (DTD or other) once interface stabilizes
*/
foreach($schema->info as $namespace_name => $namespace_info) {
$dom_namespace = $dom_document->createElement('namespace');
$dom_root->appendChild($dom_namespace);
$dom_namespace->setAttribute('id', $namespace_name);
$dom_namespace->appendChild(
$dom_document->createElement('name', $namespace_name)
);
$dom_namespace_description = $dom_document->createElement('description');
$dom_namespace->appendChild($dom_namespace_description);
appendHTMLDiv($dom_document, $dom_namespace_description,
$schema->info_namespace[$namespace_name]->description);
foreach ($namespace_info as $name => $info) {
$dom_directive = $dom_document->createElement('directive');
$dom_namespace->appendChild($dom_directive);
$dom_directive->setAttribute('id', $namespace_name . '.' . $name);
$dom_directive->appendChild(
$dom_document->createElement('name', $name)
);
$dom_constraints = $dom_document->createElement('constraints');
$dom_directive->appendChild($dom_constraints);
$dom_constraints->appendChild(
$dom_document->createElement('type', $info->type)
);
if ($info->allowed !== true) {
$dom_allowed = $dom_document->createElement('allowed');
$dom_constraints->appendChild($dom_allowed);
foreach ($info->allowed as $allowed => $bool) {
$dom_allowed->appendChild(
$dom_document->createElement('value', $allowed)
);
}
}
$raw_default = $schema->defaults[$namespace_name][$name];
if (is_bool($raw_default)) {
$default = $raw_default ? 'true' : 'false';
} elseif (is_string($raw_default)) {
$default = "\"$raw_default\"";
} else {
$default = print_r(
$schema->defaults[$namespace_name][$name], true
);
}
$dom_constraints->appendChild(
$dom_document->createElement('default', $default)
);
$dom_descriptions = $dom_document->createElement('descriptions');
$dom_directive->appendChild($dom_descriptions);
foreach ($info->descriptions as $file => $file_descriptions) {
foreach ($file_descriptions as $line => $description) {
$dom_description = $dom_document->createElement('description');
$dom_description->setAttribute('file', $file);
$dom_description->setAttribute('line', $line);
appendHTMLDiv($dom_document, $dom_description, $description);
$dom_descriptions->appendChild($dom_description);
}
}
}
}
// print_r($dom_document->saveXML());
// save a copy of the raw XML
$dom_document->save('configdoc.xml');
// ---------------------------------------------------------------------------
// Generate final output using XSLT
// load the stylesheet
$xsl_stylesheet_name = 'plain';
$xsl_stylesheet = "styles/$xsl_stylesheet_name.xsl";
$xsl_dom_stylesheet = new DOMDocument();
$xsl_dom_stylesheet->load($xsl_stylesheet);
// setup the XSLT processor
$xsl_processor = new XSLTProcessor();
// perform the transformation
$xsl_processor->importStylesheet($xsl_dom_stylesheet);
$html_output = $xsl_processor->transformToXML($dom_document);
// some slight fudges to preserve backwards compatibility
$html_output = str_replace('/>', ' />', $html_output); // <br /> not <br>
$html_output = str_replace(' xmlns=""', '', $html_output); // rm unnecessary xmlns
if (class_exists('Tidy')) {
// cleanup output
$config = array(
'indent' => true,
'output-xhtml' => true,
'wrap' => 80
);
$tidy = new Tidy;
$tidy->parseString($html_output, $config, 'utf8');
$tidy->cleanRepair();
$html_output = (string) $tidy;
}
// write it to a file (todo: parse into seperate pages)
file_put_contents("$xsl_stylesheet_name.html", $html_output);
// ---------------------------------------------------------------------------
// Output for instant feedback
if (php_sapi_name() != 'cli') {
echo $html_output;
} else {
echo 'Files generated successfully.';
}
?>

View File

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

View File

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

View File

@@ -11,24 +11,25 @@ profiling.
Here we go:
AttrDef
Class - doesn't support Unicode characters (fringe); uses regular
expressions
Lang - code duplication; premature optimization; doesn't consult official
lists (fringe)
Length - easily mistaken for CSSLength
URI - multiple regular expressions; needs host validation routines factored
out for mailto scheme; missing validation for query; fragment and path,
Class - doesn't support Unicode characters, uses regular expressions
Lang - code duplication, premature optimization, doesn't consult official
lists
Pixels/Length/MultiLength - implemented according to HTML spec (excludes
code reuse in CSS)
URI - multiple regular expressions, needs host validation routines factored
out for mailto scheme, IPv6 validation is broken (fringe), unintuitive
variable overwriting, missing validation for query, fragment and path,
no percent-encode fixing
CSS - parser doesn't accept advanced CSS (fringe)
Number - constructor interface is inconsistent with Integer
AttrTransform - doesn't accept AttrContext
Config - "load configuration" hooks missing, rich set* accessors missing
ConfigSchema - redefinition is a mess
AttrTransform - doesn't accept AttrContext, non-validating
ChildDef - not-allowed nodes translated to text, likely invalid handling
Config - "load configuration" hooks missing, rich set* accessors missing,
needs redefined relationship with the definitions
Strategy
FixNesting - cannot bubble nodes out of structures
MakeWellFormed - insufficient automatic closing definitions (check HTML
spec for optional end tags, also, closing based on type (block/inline)
might be efficient).
spec for optional end tags).
RemoveForeignElements - should be run in parallel with MakeWellFormed
URIScheme - needs to have callable generic checks
ftp - missing typecode check

View File

@@ -1,23 +0,0 @@
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

@@ -17,9 +17,18 @@ are passed. These classes are: HTMLPurifier::*, Generator::generateFromTokens
and Lexer::tokenizeHTML. However, whenever a valid configuration object
is defined, that object should be used.
In relation to HTMLDefinition and CSSDefinition, there is a special class
of directives that influence the *construction* of the Definition object.
A standard call pattern would look like:
-- the following is projected changes to the configuration system --
In relation to HTMLDefinition and CSSDefinition, there are going to be some
major structural changes to enable the easy configuration of these objects.
Due to the intricacy of these objects, it's not feasible to ask an average
user to twiddle around with an element and its 20 other dependencies. However,
these objects are the only possible point where change could occur in the
context of configuration.
The solution is to introduce a special class of directives that influence the
*construction* of the Definition object. A standard call pattern would look
like:
1. Client calls Config->getHTMLDefinition()
2. Config calls HTMLDefinition->createNew(this)

View File

@@ -0,0 +1,272 @@
<!-- Transform %TextAlign to align:value in style -->
<!-- text alignment for p, div, h1-h6. The default is
align="left" for ltr headings, "right" for rtl
Move to style! -->
<!ENTITY % TextAlign "DEPRECATED align (left|center|right|justify) #IMPLIED">
<!-- type and start should have CSS equivalents, but they'll need to
be translated intelligently -->
<!ENTITY % ULStyle "(disc|square|circle)">
<!-- Ordered list numbering style
1 arabic numbers 1, 2, 3, ...
a lower alpha a, b, c, ...
A upper alpha A, B, C, ...
i lower roman i, ii, iii, ...
I upper roman I, II, III, ...
The style is applied to the sequence number which by default
is reset to 1 for the first list item in an ordered list.
-->
<!ENTITY % OLStyle "CDATA">
<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
<!ENTITY % LIStyle "CDATA">
<!ATTLIST ol
%attrs;
DEPRECATED type %OLStyle; #IMPLIED
DEPRECATED start %Number; #IMPLIED
>
<!ATTLIST li
%attrs;
DEPRECATED type %LIStyle; #IMPLIED
DEPRECATED value %Number; #IMPLIED
>
<!ATTLIST hr
%attrs;
DEPRECATED align (left|center|right) #IMPLIED
DEPRECATED size %Pixels; #IMPLIED
DEPRECATED width %Length; #IMPLIED
>
<!ATTLIST pre
%attrs;
DEPRECATED width %Number; #IMPLIED
>
<!ATTLIST blockquote
%attrs;
cite %URI; #IMPLIED
>
<!ATTLIST ins
%attrs;
cite %URI; #IMPLIED
datetime %Datetime; #IMPLIED
>
<!ATTLIST del
%attrs;
cite %URI; #IMPLIED
datetime %Datetime; #IMPLIED
>
<!ATTLIST a
%attrs;
name NMTOKEN #IMPLIED // ID
href %URI; #IMPLIED
rel %LinkTypes; #IMPLIED // needs policing
rev %LinkTypes; #IMPLIED // see rel
target %FrameTarget; #IMPLIED // usually not used, but might be
>
<!ATTLIST bdo
%coreattrs; // !#!
lang %LanguageCode; #IMPLIED
xml:lang %LanguageCode; #IMPLIED
dir (ltr|rtl) #REQUIRED
>
<!ATTLIST br
%coreattrs; // !#!
DEPRECATED clear (left|all|right|none) "none"
>
<!ELEMENT q %Inline;> <!-- inlined quote -->
<!ATTLIST q
%attrs;
cite %URI; #IMPLIED
>
<!ATTLIST img
%attrs;
src %URI; #REQUIRED
alt %Text; #REQUIRED
DEPRECATED name NMTOKEN #IMPLIED // ID
longdesc %URI; #IMPLIED
height %Length; #IMPLIED // dubious, but we'll allow
width %Length; #IMPLIED //
DEPRECATED align %ImgAlign; #IMPLIED
DEPRECATED border %Length; #IMPLIED
DEPRECATED hspace %Pixels; #IMPLIED // left/right margin
DEPRECATED vspace %Pixels; #IMPLIED // up/down margin
>
<!--
The border attribute sets the thickness of the frame around the
table. The default units are screen pixels.
The frame attribute specifies which parts of the frame around
the table should be rendered. The values are not the same as
CALS to avoid a name clash with the valign attribute.
-->
<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
<!--
The rules attribute defines which rules to draw between cells:
If rules is absent then assume:
"none" if border is absent or border="0" otherwise "all"
-->
<!ENTITY % TRules "(none | groups | rows | cols | all)">
<!-- horizontal placement of table relative to document -->
<!ENTITY % TAlign "(left|center|right)">
<!-- horizontal alignment attributes for cell contents
char alignment char, e.g. char=':'
charoff offset for alignment char
-->
<!ENTITY % cellhalign
"align (left|center|right|justify|char) #IMPLIED
char %Character; #IMPLIED
charoff %Length; #IMPLIED"
>
<!-- vertical alignment attributes for cell contents -->
<!ENTITY % cellvalign
"valign (top|middle|bottom|baseline) #IMPLIED"
>
<!-- we may want to convert some of these nonetheless -->
<!ATTLIST table
%attrs;
summary %Text; #IMPLIED
width %Length; #IMPLIED
border %Pixels; #IMPLIED
frame %TFrame; #IMPLIED
rules %TRules; #IMPLIED
cellspacing %Length; #IMPLIED
cellpadding %Length; #IMPLIED
DEPRECATED align %TAlign; #IMPLIED
DEPRECATED bgcolor %Color; #IMPLIED
>
<!ENTITY % CAlign "(top|bottom|left|right)">
<!ATTLIST caption
%attrs;
DEPRECATED align %CAlign; #IMPLIED // watch, it's a special set
>
<!--
colgroup groups a set of col elements. It allows you to group
several semantically related columns together.
-->
<!ATTLIST colgroup
%attrs;
span %Number; "1"
width %MultiLength; #IMPLIED
%cellhalign; // very interesting
%cellvalign;
>
<!--
col elements define the alignment properties for cells in
one or more columns.
The width attribute specifies the width of the columns, e.g.
width=64 width in screen pixels
width=0.5* relative width of 0.5
The span attribute causes the attributes of one
col element to apply to more than one column.
-->
<!ATTLIST col
%attrs;
span %Number; "1"
width %MultiLength; #IMPLIED
%cellhalign;
%cellvalign;
>
<!--
Use thead to duplicate headers when breaking table
across page boundaries, or for static headers when
tbody sections are rendered in scrolling panel.
Use tfoot to duplicate footers when breaking table
across page boundaries, or for static footers when
tbody sections are rendered in scrolling panel.
Use multiple tbody sections when rules are needed
between groups of table rows.
-->
<!ATTLIST thead
%attrs;
%cellhalign;
%cellvalign;
>
<!ATTLIST tfoot
%attrs;
%cellhalign;
%cellvalign;
>
<!ATTLIST tbody
%attrs;
%cellhalign;
%cellvalign;
>
<!ATTLIST tr
%attrs;
%cellhalign;
%cellvalign;
DEPRECATED bgcolor %Color; #IMPLIED
>
<!-- Scope is simpler than headers attribute for common tables -->
<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
<!-- th is for headers, td for data and for cells acting as both -->
<!ATTLIST th
%attrs;
abbr %Text; #IMPLIED
axis CDATA #IMPLIED
headers IDREFS #IMPLIED
scope %Scope; #IMPLIED
rowspan %Number; "1"
colspan %Number; "1"
%cellhalign;
%cellvalign;
DEPRECATED nowrap (nowrap) #IMPLIED
DEPRECATED bgcolor %Color; #IMPLIED
DEPRECATED width %Length; #IMPLIED
DEPRECATED height %Length; #IMPLIED
>
<!ATTLIST td
%attrs;
abbr %Text; #IMPLIED
axis CDATA #IMPLIED
headers IDREFS #IMPLIED
scope %Scope; #IMPLIED
rowspan %Number; "1"
colspan %Number; "1"
%cellhalign;
%cellvalign;
DEPRECATED nowrap (nowrap) #IMPLIED
DEPRECATED bgcolor %Color; #IMPLIED
DEPRECATED width %Length; #IMPLIED
DEPRECATED height %Length; #IMPLIED
>

View File

@@ -21,9 +21,7 @@ if (!empty($_POST['html'])) {
$html = get_magic_quotes_gpc() ? stripslashes($_POST['html']) : $_POST['html'];
$config = HTMLPurifier_Config::createDefault();
$config->set('Core', 'TidyFormat', !empty($_POST['tidy']));
$purifier = new HTMLPurifier($config);
$purifier = new HTMLPurifier();
$pure_html = $purifier->purify($html);
?>
@@ -67,8 +65,6 @@ if (isset($html)) {
HTMLPurifier_Encoder::cleanUTF8($html), ENT_COMPAT, 'UTF-8');
}
?></textarea>
<div>Nicely format output with Tidy? <input type="checkbox" value="1"
name="tidy"<?php if (!empty($_POST['tidy'])) echo ' checked="checked"'; ?> /></div>
<div>
<input type="submit" value="Submit" name="submit" class="button" />
</div>

View File

@@ -20,32 +20,15 @@ can further be customized using simpler configuration options.
Here are some fuzzy levels you could set:
1. Comments - Wordpress recommends a, abbr, acronym, b, blockquote, cite,
code, em, i, strike, strong; however, you could get away with only a, em and
p; also having blockquote and pre tags would be helpful.
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
code, em, i, strike, strong; however, you could get away with only a, b and
i; also having p and pre tags would be helpful.
2. Pages - As permissive as possible without allowing XSS. No protection
against bad design sense, unfortunantely. Suitable for wiki and page
environments.
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)
3. Lint - Accept everything in the spec, a Tidy wannabe.
One final note: when you start axing tags that are more commonly used, you
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
I've also decomposed tags into risk levels. An asterisk indicates that no one
really uses that tag, tilde indicates it's deprecated.
1 - blockquote, code, em, i, p, tt / strong, sub, sup
1* - abbr, acronym, bdo, cite, dfn, kbd, q, samp
@@ -55,76 +38,30 @@ Legend:
5 - a
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
Tables - caption, table, td, th, tr / col, colgroup, tbody, tfoot, thead
Forms - fieldset, form, input, lable, legend, optgroup, option, select, textarea
XSS - noscript, object, script ~ applet
Meta - base, basefont, body, head, html, link, meta, style, title
Frames - frame, frameset, iframe
And tag specific notes:
a - general problems involving linkspam
b - too much bold is bad, typographically speaking bold is discouraged
br - often misused
a - general problems involving linkspam
b - too much bold is bad, typographically speaking bold is discouraged
br - often misused
center - CSS, usually no legit use
del - only useful in editing context
div - little meaning in certain contexts i.e. blog comment
h1 - usually no legit use, as header is already set by application
h* - not needed in blog comments
hr - usually not necessary in blog comments
img - could be extremely undesirable if linking to external pics (CSRF, goatse)
h1 - usually no legit use, as header is already set by application
h* - not needed in blog comments
hr - usually not necessary in blog comments
img - could be extremely undesirable if linking to external pics
pre - could use formatting, only useful in code contexts
q - very little support
s - transform into span with styling or del?
q - very little support
s - transform into span with styling or del?
small - technically presentational
span - depends on attribute allowances
sub, sup - specialized
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.
u - little legit use, prefer class with text-decoration

View File

@@ -2,10 +2,9 @@
Optimization
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
that itch, put it here!
they turn out to be slow. Be sure not to prematurely optimize though!
- Make Tokens Flyweights (may prove problematic, probably not worth it)
- Make Tokens Flyweights
- Rewrite regexps into PHP code
- Serialize the Definition object
- Batch regexp validation (do as many per function call as possible)

View File

@@ -86,7 +86,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
Well-supported values are: disc, circle, square,
decimal, lower-roman, upper-roman, lower-alpha and upper-alpha. See also
CSS 3. Mostly IE lack of support.</td></tr>
<tr class="css1 impl-yes"><td>list-style</td><td>SHORTHAND</td></tr>
<tr class="css1 impl-yes"><td>list-style</td><td>SHORTHAND, target milestone 1.0</td></tr>
<tr class="css1 impl-yes"><td>margin</td><td>MULTIPLE</td></tr>
<tr class="css1 impl-yes"><td>margin-*</td><td>COMPOSITE(&lt;length&gt;,
&lt;percentage&gt;, auto)</td></tr>
@@ -134,7 +134,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
<tbody>
<tr><th colspan="2">Unknown</th></tr>
<tr class="danger css1"><td>background-image</td><td>Dangerous, target milestone 1.2</td></tr>
<tr class="danger css1"><td>background-image</td><td>Dangerous, target milestone 1.3</td></tr>
<tr class="css1"><td>background-attachment</td><td>ENUM(scroll, fixed),
Depends on background-image</td></tr>
<tr class="css1"><td>background-position</td><td>Depends on background-image</td></tr>
@@ -144,7 +144,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
inline-block has incomplete IE6 support and requires -moz-inline-box
for Mozilla. Unknown target milestone.</td></tr>
<tr><td class="css1">height</td><td>Interesting, why use it? Unknown target milestone.</td></tr>
<tr class="danger css1"><td>list-style-image</td><td>Dangerous? Target milestone 1.2</td></tr>
<tr class="danger css1"><td>list-style-image</td><td>Dangerous? Target milestone 1.3</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>max-width</td></tr>
@@ -254,7 +254,7 @@ Mozilla on inside and needs -moz-outline, no IE support.</td></tr>
</tbody>
<tbody>
<tr><th colspan="3">Transform, target milestone 1.4</th></tr>
<tr><th colspan="3">Transform, target milestone 1.2</th></tr>
<tr><td rowspan="5">align</td><td>CAPTION</td><td>Near-equiv style 'caption-side', drop left and right</td></tr>
<tr><td>IMG</td><td rowspan="2">Margin-left and margin-right = auto or parent div</td></tr>
<tr><td>TABLE</td></tr>

View File

@@ -6,43 +6,35 @@ through negligence of people. This class will do its job: no more, no less,
and it's up to you to provide it the proper information and proper context
to be effective. Things to remember:
1. Character Encoding: UTF-8.
Currently, the parser runs under the assumption that it is dealing
1. UTF-8. Currently, the parser runs under the assumption that it is dealing
with UTF-8. Not ISO-8859-1 or Windows-1252, UTF-8. And definitely not "no
character encoding explicitly stated" or UTF-7. If you're not using UTF-8 as
your character encoding, make sure you configure HTML Purifier or switch
to UTF-8. Now. Also, make sure any input is properly converted to UTF-8, or
the parser will mangle it badly (though it won't be a security risk if you're
outputting it as UTF-8 though). Character encoding is, in general, a knotty
issue, but do yourself a favor and learn about it:
<http://www.joelonsoftware.com/articles/Unicode.html>
your character encoding, you should switch. Now. Make sure any input is
properly converted to UTF-8, or the parser will mangle it badly
(though it won't be a security risk if you're outputting it as UTF-8 though).
We will be adding out-of-the-box support for the other major character
encodings shortly.
2. Doctype: XHTML 1.0 Transitional
This is what the parser is outputting. For the most
2. XHTML 1.0 Transitional. This is what the parser is outputting. For the most
part, it's compatible with HTML 4.01, but XHTML enforces some very nice things
that all web developers should use. Regardless, NO DOCTYPE is a NO. Quirks mode
has waaaay too many quirks for a little parser to handle. We did not select
strict in order to prevent ourselves from being too draconic on users, but
this may be configurable in the future. Do you want standards compliance?
The doctype is a good place to start.
this may be configurable in the future.
3. IDs
They need to be unique, but without some knowledge of the
3. IDs. They need to be unique, but without some knowledge of the
rest of the document, it's difficult to know what's unique. %Attr.IDBlacklist
needs to be set: we may want to consider disallowing IDs by default to
save lazy programmers.
4. [PROJECTED] Links
We're not going to try for spam protection (although
4. [PROJECTED] Links. We're not going to try for spam protection (although
some hooks for such a module might be nice) but we may offer the ability to
only accept relative URLs. Pick the one that's right for you.
5. CSS
While we can prevent the most flagrant cases from affecting your
5. CSS. While we can prevent the most flagrant cases from affecting your
layout (such as absolutely positioned elements), no amount of code is going
to protect your pages from being attacked by garish colors and plain old
bad taste. A neat feature would be the ability to define acceptable colors
in a document, but that's not likely to be implemented for a while. In the
meantime, be sure to make sure that floated elements (permitted, since they
can be quite useful) can't mess up your layout. Once again, we may want to
disable this by default to protect lazy developers.
can be quite useful) can't mess up your layout.

View File

@@ -54,4 +54,4 @@ HTML Purifier is best suited for documents that require a rich array of
HTML tags. Things like blog comments are, in all likelihood, most appropriately
written in an extremely restrictive set of markup that doesn't require
all this functionality (or not written in HTML at all), although this may
be changing in the future with the addition of levels of filtering.
be changing in the future.

View File

@@ -1,25 +0,0 @@
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

@@ -1,10 +0,0 @@
<?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
*
* HTML Purifier is an HTML filter that will take an arbitrary snippet of
* HTMLPurifier is an HTML filter that will take an arbitrary snippet of
* HTML and rigorously test, validate and filter it into a version that
* is safe for output onto webpages. It achieves this by:
*
@@ -18,11 +18,11 @@
* However, most users will only need to interface with the HTMLPurifier
* class, so this massive amount of infrastructure is usually concealed.
* If you plan on working with the internals, be sure to include
* HTMLPurifier_ConfigSchema and HTMLPurifier_Config.
* HTMLPurifier_ConfigDef and HTMLPurifier_Config.
*/
/*
HTML Purifier - Standards Compliant HTML Filtering
HTMLPurifier - Standards Compliant HTML Filtering
Copyright (C) 2006 Edward Z. Yang
This library is free software; you can redistribute it and/or
@@ -39,13 +39,11 @@
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// almost every class has an undocumented dependency to these, so make sure
// they get included
require_once 'HTMLPurifier/ConfigSchema.php';
require_once 'HTMLPurifier/ConfigDef.php';
require_once 'HTMLPurifier/Config.php';
require_once 'HTMLPurifier/Lexer.php';
require_once 'HTMLPurifier/HTMLDefinition.php';
require_once 'HTMLPurifier/Generator.php';
require_once 'HTMLPurifier/Strategy/Core.php';
require_once 'HTMLPurifier/Encoder.php';

View File

@@ -3,15 +3,15 @@
/**
* Internal data-structure used in attribute validation to accumulate state.
*
* This is a data-structure that holds objects that accumulate state, like
* HTMLPurifier_IDAccumulator. It's better than using globals!
* All it is is a data-structure that holds objects that accumulate state, like
* HTMLPurifier_IDAccumulator.
*
* @note Many functions that accept this object have it as a mandatory
* parameter, even when there is no use for it. Though this is
* for the same reasons as why HTMLPurifier_Config is a mandatory
* parameter, it is also because you cannot assign a default value
* to a parameter passed by reference (passing by reference is essential
* for context to work in PHP 4).
* @param Many functions that accept this object have it as a mandatory
* parameter, even when there is no use for it. Though this is
* for the same reasons as why HTMLPurifier_Config is a mandatory
* parameter, it is also because you cannot assign a default value
* to a parameter passed by reference (passing by reference is essential
* for context to work in PHP 4).
*/
class HTMLPurifier_AttrContext

View File

@@ -15,12 +15,6 @@ require_once 'HTMLPurifier/AttrContext.php';
class HTMLPurifier_AttrDef
{
/**
* Tells us whether or not an HTML attribute is minimized. Only the
* boolean attribute vapourware would use this.
*/
var $minimized = false;
/**
* Abstract function defined for functions that validate and clean strings.
*
@@ -48,16 +42,7 @@ class HTMLPurifier_AttrDef
*
* @note This method is not entirely standards compliant, as trim() removes
* more types of whitespace than specified in the spec. In practice,
* 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.
* this is rarely a problem.
*
* @public
*/

View File

@@ -11,14 +11,9 @@ class HTMLPurifier_AttrDef_Host extends HTMLPurifier_AttrDef
{
/**
* Instance of HTMLPurifier_AttrDef_IPv4 sub-validator
* Instances of HTMLPurifier_AttrDef_IPv4 and HTMLPurifier_AttrDef_IPv6
*/
var $ipv4;
/**
* Instance of HTMLPurifier_AttrDef_IPv6 sub-validator
*/
var $ipv6;
var $ipv4, $ipv6;
function HTMLPurifier_AttrDef_Host() {
$this->ipv4 = new HTMLPurifier_AttrDef_IPv4();

View File

@@ -5,7 +5,7 @@ require_once 'HTMLPurifier/URIScheme.php';
require_once 'HTMLPurifier/URISchemeRegistry.php';
require_once 'HTMLPurifier/AttrDef/Host.php';
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'URI', 'DefaultScheme', 'http', 'string',
'Defines through what scheme the output will be served, in order to '.
'select the proper object validator when no scheme information is present.'
@@ -36,13 +36,13 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
// for HTTP and thus won't work for our generic URI parsing
// according to the RFC... (but this cuts corners, i.e. non-validating)
$r_URI = '!'.
'(([^:/?#<>\'"]+):)?'. // 2. Scheme
'(//([^/?#<>\'"]*))?'. // 4. Authority
'([^?#<>\'"]*)'. // 5. Path
'(\?([^#<>\'"]*))?'. // 7. Query
'(#([^<>\'"]*))?'. // 8. Fragment
'!';
$r_URI = '!^'.
'(([^:/?#<>]+):)?'. // 2. Scheme
'(//([^/?#<>]*))?'. // 4. Authority
'([^?#<>]*)'. // 5. Path
'(\?([^#<>]*))?'. // 7. Query
'(#([^<>]*))?'. // 8. Fragment
'$!';
$matches = array();
$result = preg_match($r_URI, $uri, $matches);

View File

@@ -4,13 +4,13 @@ require_once 'HTMLPurifier/AttrTransform.php';
// this MUST be placed in post, as it assumes that any value in dir is valid
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Attr', 'DefaultTextDir', 'ltr', 'string',
'Defines the default text direction (ltr or rtl) of the document '.
'being parsed. This generally is the same as the value of the dir '.
'attribute in HTML, or ltr if that is not specified.'
);
HTMLPurifier_ConfigSchema::defineAllowedValues(
HTMLPurifier_ConfigDef::defineAllowedValues(
'Attr', 'DefaultTextDir', array( 'ltr', 'rtl' )
);

View File

@@ -4,7 +4,7 @@ require_once 'HTMLPurifier/AttrTransform.php';
// must be called POST validation
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Attr', 'DefaultInvalidImage', '', 'string',
'This is the default image an img tag will be pointed to if it does '.
'not have a valid src attribute. In future versions, we may allow the '.
@@ -12,7 +12,7 @@ HTMLPurifier_ConfigSchema::define(
'not possible right now.'
);
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Attr', 'DefaultInvalidImageAlt', 'Invalid image', 'string',
'This is the content of the alt tag of an invalid image if the user '.
'had not previously specified an alt attribute. It has no effect when the '.

View File

@@ -5,7 +5,14 @@
// false = delete parent node and all children
// array(...) = replace children nodes with these
HTMLPurifier_ConfigSchema::define(
// this is the hardest one to implement. We'll use fancy regexp tricks
// right now, we only expect it to return TRUE or FALSE (it won't attempt
// to fix the tree)
// we may end up writing custom code for each HTML case
// in order to make it self correcting
HTMLPurifier_ConfigDef::define(
'Core', 'EscapeInvalidChildren', false, 'bool',
'When true, a child is found that is not allowed in the context of the '.
'parent element will be transformed into text as if it were ASCII. When '.
@@ -55,9 +62,9 @@ class HTMLPurifier_ChildDef
* Custom validation class, accepts DTD child definitions
*
* @warning Currently this class is an all or nothing proposition, that is,
* it will only give a bool return value.
* @note This class is currently not used by any code, although it is unit
* tested.
* it will only give a bool return value. Table is the only
* child definition that uses this class, and we ought to give
* it a dedicated one.
*/
class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef
{
@@ -300,141 +307,4 @@ class HTMLPurifier_ChildDef_Chameleon extends HTMLPurifier_ChildDef
}
}
/**
* Definition for tables
*/
class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef
{
var $allow_empty = false;
var $type = 'table';
function HTMLPurifier_ChildDef_Table() {}
function validateChildren($tokens_of_children, $config, $context) {
if (empty($tokens_of_children)) return false;
// this ensures that the loop gets run one last time before closing
// up. It's a little bit of a hack, but it works! Just make sure you
// get rid of the token later.
$tokens_of_children[] = false;
// only one of these elements is allowed in a table
$caption = false;
$thead = false;
$tfoot = false;
// as many of these as you want
$cols = array();
$content = array();
$nesting = 0; // current depth so we can determine nodes
$is_collecting = false; // are we globbing together tokens to package
// into one of the collectors?
$collection = array(); // collected nodes
$tag_index = 0; // the first node might be whitespace,
// so this tells us where the start tag is
foreach ($tokens_of_children as $token) {
$is_child = ($nesting == 0);
if ($token === false) {
// terminating sequence started
} elseif ($token->type == 'start') {
$nesting++;
} elseif ($token->type == 'end') {
$nesting--;
}
// handle node collection
if ($is_collecting) {
if ($is_child) {
// okay, let's stash the tokens away
// first token tells us the type of the collection
switch ($collection[$tag_index]->name) {
case 'tr':
case 'tbody':
$content[] = $collection;
break;
case 'caption':
if ($caption !== false) break;
$caption = $collection;
break;
case 'thead':
case 'tfoot':
// access the appropriate variable, $thead or $tfoot
$var = $collection[$tag_index]->name;
if ($$var === false) {
$$var = $collection;
} else {
// transmutate the first and less entries into
// tbody tags, and then put into content
$collection[$tag_index]->name = 'tbody';
$collection[count($collection)-1]->name = 'tbody';
$content[] = $collection;
}
break;
case 'colgroup':
$cols[] = $collection;
break;
}
$collection = array();
$is_collecting = false;
$tag_index = 0;
} else {
// add the node to the collection
$collection[] = $token;
}
}
// terminate
if ($token === false) break;
if ($is_child) {
// determine what we're dealing with
if ($token->name == 'col') {
// the only empty tag in the possie, we can handle it
// immediately
$cols[] = array_merge($collection, array($token));
$collection = array();
$tag_index = 0;
continue;
}
switch($token->name) {
case 'caption':
case 'colgroup':
case 'thead':
case 'tfoot':
case 'tbody':
case 'tr':
$is_collecting = true;
$collection[] = $token;
continue;
default:
if ($token->type == 'text' && $token->is_whitespace) {
$collection[] = $token;
$tag_index++;
}
continue;
}
}
}
if (empty($content)) return false;
$ret = array();
if ($caption !== false) $ret = array_merge($ret, $caption);
if ($cols !== false) foreach ($cols as $token_array) $ret = array_merge($ret, $token_array);
if ($thead !== false) $ret = array_merge($ret, $thead);
if ($tfoot !== false) $ret = array_merge($ret, $tfoot);
foreach ($content as $token_array) $ret = array_merge($ret, $token_array);
if (!empty($collection) && $is_collecting == false){
// grab the trailing space
$ret = array_merge($ret, $collection);
}
array_pop($tokens_of_children); // remove phantom token
return ($ret === $tokens_of_children) ? true : $ret;
}
}
?>
?>

View File

@@ -21,22 +21,22 @@ class HTMLPurifier_Config
var $conf;
/**
* Reference HTMLPurifier_ConfigSchema for value checking
* Reference HTMLPurifier_ConfigDef for value checking
*/
var $def;
/**
* Cached instance of HTMLPurifier_HTMLDefinition
* Instance of HTMLPurifier_HTMLDefinition
*/
var $html_definition;
/**
* Cached instance of HTMLPurifier_CSSDefinition
* Instance of HTMLPurifier_CSSDefinition
*/
var $css_definition;
/**
* @param $definition HTMLPurifier_ConfigSchema that defines what directives
* @param $definition HTMLPurifier_ConfigDef that defines what directives
* are allowed.
*/
function HTMLPurifier_Config(&$definition) {
@@ -49,7 +49,7 @@ class HTMLPurifier_Config
* @return Default HTMLPurifier_Config object.
*/
function createDefault() {
$definition =& HTMLPurifier_ConfigSchema::instance();
$definition =& HTMLPurifier_ConfigDef::instance();
$config = new HTMLPurifier_Config($definition);
return $config;
}

View File

@@ -2,23 +2,9 @@
/**
* Configuration definition, defines directives and their defaults.
* @todo The ability to define things multiple times is confusing and should
* be factored out to its own function named registerDependency() or
* addNote(), where only the namespace.name and an extra descriptions
* documenting the nature of the dependency are needed. Since it's
* possible that the dependency is registered before the configuration
* is defined, deferring it to some sort of cache until it actually
* gets defined would be wise, keeping it opaque until it does get
* defined. We could add a finalize() method which would cause it to
* error out if we get a dangling dependency. It's difficult, however,
* to know whether or not it's a dependency, or a codependency, that is
* neither of them fully depends on it. Where does the configuration go
* then? This could be partially resolved by allowing blanket definitions
* and then splitting them up into finer-grained versions, however, there
* might be implementation difficulties in ini files regarding order of
* execution.
* @todo Build documentation generation capabilities.
*/
class HTMLPurifier_ConfigSchema {
class HTMLPurifier_ConfigDef {
/**
* Defaults of the directives and namespaces.
@@ -40,15 +26,15 @@ class HTMLPurifier_ConfigSchema {
* Lookup table of allowed types.
*/
var $types = array(
'string' => 'String',
'istring' => 'Case-insensitive string',
'int' => 'Integer',
'float' => 'Float',
'bool' => 'Boolean',
'lookup' => 'Lookup array',
'list' => 'Array list',
'hash' => 'Associative array',
'mixed' => 'Mixed'
'string' => true,
'istring' => true,
'int' => true,
'float' => true,
'bool' => true,
'lookup' => true,
'list' => true,
'hash' => true,
'mixed' => true
);
/**
@@ -60,7 +46,7 @@ class HTMLPurifier_ConfigSchema {
$this->defineNamespace('URI', 'Features regarding Uniform Resource Identifiers.');
$this->defineNamespace('HTML', 'Configuration regarding allowed HTML.');
$this->defineNamespace('CSS', 'Configuration regarding allowed CSS.');
$this->defineNamespace('Test', 'Developer testing configuration for our unit tests.');
$this->defineNamespace('Test', 'Testing configuration for our unit tests.');
}
/**
@@ -71,7 +57,7 @@ class HTMLPurifier_ConfigSchema {
if ($prototype !== null) {
$instance = $prototype;
} elseif ($instance === null || $prototype === true) {
$instance = new HTMLPurifier_ConfigSchema();
$instance = new HTMLPurifier_ConfigDef();
$instance->initialize();
}
return $instance;
@@ -80,6 +66,9 @@ class HTMLPurifier_ConfigSchema {
/**
* Defines a directive for configuration
* @warning Will fail of directive's namespace is defined
* @todo Collect information on description and allow redefinition
* so that multiple files can register a dependency on a
* configuration directive.
* @param $namespace Namespace the directive is in
* @param $name Key of directive
* @param $default Default value of directive
@@ -91,17 +80,12 @@ class HTMLPurifier_ConfigSchema {
$namespace, $name, $default, $type,
$description
) {
$def =& HTMLPurifier_ConfigSchema::instance();
$def =& HTMLPurifier_ConfigDef::instance();
if (!isset($def->info[$namespace])) {
trigger_error('Cannot define directive for undefined namespace',
E_USER_ERROR);
return;
}
if (!ctype_alnum($name)) {
trigger_error('Directive name must be alphanumeric',
E_USER_ERROR);
return;
}
if (isset($def->info[$namespace][$name])) {
if (
$def->info[$namespace][$name]->type !== $type ||
@@ -138,19 +122,17 @@ class HTMLPurifier_ConfigSchema {
* @param $description Description of the namespace
*/
function defineNamespace($namespace, $description) {
$def =& HTMLPurifier_ConfigSchema::instance();
$def =& HTMLPurifier_ConfigDef::instance();
if (isset($def->info[$namespace])) {
trigger_error('Cannot redefine namespace', E_USER_ERROR);
return;
}
if (!ctype_alnum($namespace)) {
trigger_error('Namespace name must be alphanumeric',
E_USER_ERROR);
return;
}
$def->info[$namespace] = array();
$def->info_namespace[$namespace] = new HTMLPurifier_ConfigEntity_Namespace();
$def->info_namespace[$namespace]->description = $description;
$backtrace = debug_backtrace();
$file = $def->mungeFilename($backtrace[0]['file']);
$line = $backtrace[0]['line'];
$def->info_namespace[$namespace]->addDescription($file,$line,$description);
$def->defaults[$namespace] = array();
}
@@ -165,7 +147,7 @@ class HTMLPurifier_ConfigSchema {
* @param $real Value aliased value will be converted into
*/
function defineValueAliases($namespace, $name, $aliases) {
$def =& HTMLPurifier_ConfigSchema::instance();
$def =& HTMLPurifier_ConfigDef::instance();
if (!isset($def->info[$namespace][$name])) {
trigger_error('Cannot set value alias for non-existant directive',
E_USER_ERROR);
@@ -195,7 +177,7 @@ class HTMLPurifier_ConfigSchema {
* @param $allowed_values Arraylist of allowed values
*/
function defineAllowedValues($namespace, $name, $allowed_values) {
$def =& HTMLPurifier_ConfigSchema::instance();
$def =& HTMLPurifier_ConfigDef::instance();
if (!isset($def->info[$namespace][$name])) {
trigger_error('Cannot define allowed values for undefined directive',
E_USER_ERROR);
@@ -274,19 +256,27 @@ class HTMLPurifier_ConfigSchema {
/**
* Base class for configuration entity
*/
class HTMLPurifier_ConfigEntity {}
class HTMLPurifier_ConfigEntity
{
/**
* Plaintext descriptions of the configuration entity is. Organized by
* file and line number, so multiple descriptions are allowed.
*/
var $descriptions = array();
/**
* Adds a description to the array
*/
function addDescription($file, $line, $description) {
if (!isset($this->descriptions[$file])) $this->descriptions[$file] = array();
$this->descriptions[$file][$line] = $description;
}
}
/**
* Structure object describing of a namespace
*/
class HTMLPurifier_ConfigEntity_Namespace extends HTMLPurifier_ConfigEntity {
/**
* String description of what kinds of directives go in this namespace.
*/
var $description;
}
class HTMLPurifier_ConfigEntity_Namespace extends HTMLPurifier_ConfigEntity {}
/**
* Structure object containing definition of a directive.
@@ -318,19 +308,6 @@ class HTMLPurifier_ConfigEntity_Directive extends HTMLPurifier_ConfigEntity
* - mixed (anything goes)
*/
var $type = 'mixed';
/**
* Plaintext descriptions of the configuration entity is. Organized by
* file and line number, so multiple descriptions are allowed.
*/
var $descriptions = array();
/**
* Adds a description to the array
*/
function addDescription($file, $line, $description) {
if (!isset($this->descriptions[$file])) $this->descriptions[$file] = array();
$this->descriptions[$file][$line] = $description;
}
}

View File

@@ -2,7 +2,7 @@
require_once 'HTMLPurifier/EntityLookup.php';
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Encoding', 'utf-8', 'istring',
'If for some reason you are unable to convert all webpages to UTF-8, '.
'you can use this directive as a stop-gap compatibility change to '.
@@ -17,20 +17,20 @@ HTMLPurifier_ConfigSchema::define(
if ( !function_exists('iconv') ) {
// only encodings with native PHP support
HTMLPurifier_ConfigSchema::defineAllowedValues(
HTMLPurifier_ConfigDef::defineAllowedValues(
'Core', 'Encoding', array(
'utf-8',
'iso-8859-1'
)
);
HTMLPurifier_ConfigSchema::defineValueAliases(
HTMLPurifier_ConfigDef::defineValueAliases(
'Core', 'Encoding', array(
'iso8859-1' => 'iso-8859-1'
)
);
}
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Test', 'ForceNoIconv', false, 'bool',
'When set to true, HTMLPurifier_Encoder will act as if iconv does not '.
'exist and use only pure PHP implementations.'
@@ -88,7 +88,7 @@ class HTMLPurifier_Encoder
if ($iconv && !$force_php) {
// do the shortcut way
$str = @iconv('UTF-8', 'UTF-8//IGNORE', $str);
return strtr($str, $non_sgml_chars);
return strtr($str, $non_sgml_chars);;
}
$mState = 0; // cached expected number of octets after the current octet

View File

@@ -88,6 +88,7 @@ class HTMLPurifier_EntityParser
* either index 1, 2 or 3 set with a hex value, dec value,
* or string (respectively).
* @returns Replacement string.
* @todo Implement string translations
*/
// +----------+----------+----------+----------+

View File

@@ -4,7 +4,7 @@
require_once 'HTMLPurifier/Lexer.php';
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'CleanUTF8DuringGeneration', false, 'bool',
'When true, HTMLPurifier_Generator will also check all strings it '.
'escapes for UTF-8 well-formedness as a defense in depth measure. '.
@@ -15,29 +15,6 @@ HTMLPurifier_ConfigSchema::define(
'generateFromTokens.'
);
HTMLPurifier_ConfigSchema::define(
'Core', 'XHTML', true, 'bool',
'Determines whether or not output is XHTML or not. When disabled, HTML '.
'Purifier goes into HTML 4.01 removes XHTML-specific markup constructs, '.
'such as boolean attribute expansion and trailing slashes in empty tags. '.
'This directive was available since 1.1.'
);
// extension constraints could be factored into ConfigSchema
HTMLPurifier_ConfigSchema::define(
'Core', 'TidyFormat', false, 'bool',
'<p>Determines whether or not to run Tidy on the final output for pretty '.
'formatting reasons, such as indentation and wrap.</p><p>This can greatly '.
'improve readability for editors who are hand-editing the HTML, but is '.
'by no means necessary as HTML Purifier has already fixed all major '.
'errors the HTML may have had. Tidy is a non-default extension, and this directive '.
'will silently fail if Tidy is not available.</p><p>If you are looking to make '.
'the overall look of your page\'s source better, I recommend running Tidy '.
'on the entire page rather than just user-content (after all, the '.
'indentation relative to the containing blocks will be incorrect).</p><p>This '.
'directive was available since 1.1.1.</p>'
);
/**
* Generates HTML from tokens.
*/
@@ -45,16 +22,11 @@ class HTMLPurifier_Generator
{
/**
* Bool cache of %Core.CleanUTF8DuringGeneration
* Bool cache of the CleanUTF8DuringGeneration directive.
* @private
*/
var $_clean_utf8 = false;
/**
* Bool cache of %Core.XHTML
*/
var $_xhtml = true;
/**
* Generates HTML from an array of tokens.
* @param $tokens Array of HTMLPurifier_Token
@@ -66,35 +38,10 @@ class HTMLPurifier_Generator
$html = '';
if (!$config) $config = HTMLPurifier_Config::createDefault();
$this->_clean_utf8 = $config->get('Core', 'CleanUTF8DuringGeneration');
$this->_xhtml = $config->get('Core', 'XHTML');
if (!$tokens) return '';
foreach ($tokens as $token) {
$html .= $this->generateFromToken($token);
}
if ($config->get('Core', 'TidyFormat') && extension_loaded('tidy')) {
$tidy_options = array(
'indent'=> true,
'output-xhtml' => $this->_xhtml,
'show-body-only' => true,
'indent-spaces' => 2,
'wrap' => 68,
);
if (version_compare(PHP_VERSION, '5', '<')) {
tidy_set_encoding('utf8');
foreach ($tidy_options as $key => $value) {
tidy_setopt($key, $value);
}
tidy_parse_string($html);
tidy_clean_repair();
$html = tidy_get_output();
} else {
$tidy = new Tidy;
$tidy->parseString($html, $tidy_options, 'utf8');
$tidy->cleanRepair();
$html = (string) $tidy;
}
}
return $html;
}
@@ -114,9 +61,7 @@ class HTMLPurifier_Generator
} elseif ($token->type == 'empty') {
$attr = $this->generateAttributes($token->attributes);
return '<' . $token->name . ($attr ? ' ' : '') . $attr .
( $this->_xhtml ? ' /': '' )
. '>';
return '<' . $token->name . ($attr ? ' ' : '') . $attr . ' />';
} elseif ($token->type == 'text') {
return $this->escape($token->data);
@@ -135,11 +80,6 @@ class HTMLPurifier_Generator
function generateAttributes($assoc_array_of_attributes) {
$html = '';
foreach ($assoc_array_of_attributes as $key => $value) {
if (!$this->_xhtml) {
// remove namespaced attributes
if (strpos($key, ':') !== false) continue;
// also needed: check for attribute minimization
}
$html .= $key.'="'.$this->escape($value).'" ';
}
return rtrim($html);

View File

@@ -56,7 +56,6 @@ class HTMLPurifier_HTMLDefinition
/**
* String name of parent element HTML will be going into.
* @todo Allow this to be overloaded by user config
* @public
*/
var $info_parent = 'div';
@@ -112,19 +111,12 @@ class HTMLPurifier_HTMLDefinition
//////////////////////////////////////////////////////////////////////
// info[]->child : defines allowed children for elements
// entities: prefixed with e_ and _ replaces . from DTD
// double underlines are entities we made up
// entities: prefixed with e_ and _ replaces .
// we don't use an array because that complicates interpolation
// strings are used instead of arrays because if you use arrays,
// 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_basic = 'br | span | bdo';
$e_special = "$e_special_basic | $e_special_extra";
@@ -150,18 +142,16 @@ class HTMLPurifier_HTMLDefinition
$e_block = "p | $e_heading | div | $e_lists | $e_blocktext | table";
$e__flow = "#PCDATA | $e_block | $e_inline | $e_misc";
$e_Flow = new HTMLPurifier_ChildDef_Optional($e__flow);
$e_a_content = new HTMLPurifier_ChildDef_Optional("#PCDATA".
" | $e_special | $e_fontstyle | $e_phrase | $e_inline_forms".
" | $e_misc_inline");
$e_a_content = new HTMLPurifier_ChildDef_Optional("#PCDATA | $e_special".
" | $e_fontstyle | $e_phrase | $e_inline_forms | $e_misc_inline");
$e_pre_content = new HTMLPurifier_ChildDef_Optional("#PCDATA | a".
" | $e_special_basic | $e_fontstyle_basic | $e_phrase_basic".
" | $e_inline_forms | $e_misc_inline");
$e_form_content = new HTMLPurifier_ChildDef_Optional('');//unused
$e_form_button_content = new HTMLPurifier_ChildDef_Optional('');//unused
$e_form_content = new HTMLPurifier_ChildDef_Optional(''); //unused
$e_form_button_content = new HTMLPurifier_ChildDef_Optional(''); // unused
$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['dd']->child =
@@ -219,7 +209,8 @@ class HTMLPurifier_HTMLDefinition
$this->info['a']->child = $e_a_content;
$this->info['table']->child = new HTMLPurifier_ChildDef_Table();
$this->info['table']->child = new HTMLPurifier_ChildDef_Custom(
'(caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))');
// not a real entity, watch the double underscore
$e__row = new HTMLPurifier_ChildDef_Required('tr');
@@ -235,7 +226,7 @@ class HTMLPurifier_HTMLDefinition
//////////////////////////////////////////////////////////////////////
// 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) {
$this->info[$name]->type = 'inline';
@@ -253,7 +244,7 @@ class HTMLPurifier_HTMLDefinition
$this->info['a']->excludes = array('a' => true);
$this->info['pre']->excludes = array_flip(array('img', 'big', 'small',
// technically useless, but good to be indepth
// technically in spec, but we don't allow em anyway
'object', 'applet', 'font', 'basefont'));
//////////////////////////////////////////////////////////////////////
@@ -263,8 +254,6 @@ class HTMLPurifier_HTMLDefinition
// by the transform classes. It will, however, do simple and slightly
// complex attribute value substitution
// the question of varying allowed attributes is more entangling.
$e_Text = new HTMLPurifier_AttrDef_Text();
// attrs, included in almost every single one except for a few,
@@ -309,8 +298,7 @@ class HTMLPurifier_HTMLDefinition
$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();
$this->info['table']->attr['cellpadding'] =
@@ -342,7 +330,7 @@ class HTMLPurifier_HTMLDefinition
$this->info['q']->attr['cite'] = $e_URI;
//////////////////////////////////////////////////////////////////////
// info_tag_transform : transformations of tags
// UNIMP : info_tag_transform : transformations of tags
$this->info_tag_transform['font'] = new HTMLPurifier_TagTransform_Font();
$this->info_tag_transform['menu'] = new HTMLPurifier_TagTransform_Simple('ul');
@@ -352,9 +340,6 @@ class HTMLPurifier_HTMLDefinition
//////////////////////////////////////////////////////////////////////
// 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()
// these are all block elements: blocks aren't allowed in P

View File

@@ -4,11 +4,12 @@ require_once 'HTMLPurifier/Token.php';
require_once 'HTMLPurifier/Encoder.php';
require_once 'HTMLPurifier/EntityParser.php';
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'AcceptFullDocuments', true, 'bool',
'This parameter determines whether or not the filter should accept full '.
'HTML documents, not just HTML fragments. When on, it will '.
'drop all sections except the content between body.'
'drop all sections except the content between body. Depending on '.
'the implementation in use, this may speed up document parse times.'
);
/**
@@ -60,60 +61,6 @@ class HTMLPurifier_Lexer
$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;
/**

View File

@@ -12,19 +12,15 @@ require_once 'HTMLPurifier/TokenFactory.php';
* documents, it performs twenty times faster than
* HTMLPurifier_Lexer_DirectLex,and is the default choice for PHP 5.
*
* @note Any empty elements will have empty tokens associated with them, even if
* @notice
* Any empty elements will have empty tokens associated with them, even if
* this is prohibited by the spec. This is cannot be fixed until the spec
* comes into play.
*
* @note PHP's DOM extension does not actually parse any entities, we use
* our own function to do that.
*
* @warning DOM tends to drop whitespace, which may wreak havoc on indenting.
* If this is a huge problem, due to the fact that HTML is hand
* edited and youa re unable to get a parser cache that caches the
* the output of HTML Purifier while keeping the original HTML lying
* around, you may want to run Tidy on the resulting output or use
* HTMLPurifier_DirectLex
* @todo Determine DOM's entity parsing behavior, point to local entity files
* if necessary.
* @todo Make div access less fragile, and refrain from preprocessing when
* HTML tag and friends are already present.
*/
class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer

View File

@@ -12,12 +12,64 @@ require_once 'HTMLPurifier/Lexer.php';
* completely eventually.
*
* @todo Reread XML spec and document differences.
*
* @todo Determine correct behavior in transforming comment data. (preserve dashes?)
* @todo Add support for CDATA sections.
* @todo Determine correct behavior in outputting 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
{
/**
* 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.
* @protected

View File

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

View File

@@ -8,7 +8,7 @@
* features, such as custom tags, custom parsing of text, etc.
*/
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'EscapeInvalidTags', false, 'bool',
'When true, invalid tags will be written back to the document as plain '.
'text. Otherwise, they are silently dropped.'

View File

@@ -187,7 +187,6 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
if (!$parent_def->child->allow_empty) {
// we need to do a double-check
$i = $parent_index;
array_pop($stack);
}
// PROJECTED OPTIMIZATION: Process all children elements before
@@ -256,4 +255,4 @@ class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
}
?>
?>

View File

@@ -3,10 +3,10 @@
require_once 'HTMLPurifier/Strategy.php';
require_once 'HTMLPurifier/HTMLDefinition.php';
require_once 'HTMLPurifier/IDAccumulator.php';
require_once 'HTMLPurifier/ConfigSchema.php';
require_once 'HTMLPurifier/ConfigDef.php';
require_once 'HTMLPurifier/AttrContext.php';
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Attr', 'IDBlacklist', array(), 'list',
'Array of IDs not allowed in the document.');

View File

@@ -4,6 +4,7 @@ require_once 'HTMLPurifier/URIScheme.php';
/**
* Validates ftp (File Transfer Protocol) URIs as defined by generic RFC 1738.
* @todo Typecode check on path
*/
class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme {
@@ -15,27 +16,7 @@ class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme {
list($userinfo, $host, $port, $path, $query) =
parent::validateComponents(
$userinfo, $host, $port, $path, $query, $config );
$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;
}
// typecode check needed on path
return array($userinfo, $host, $port, $path, null);
}

View File

@@ -1,6 +1,6 @@
<?php
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'URI', 'AllowedSchemes', array(
'http' => true, // "Hypertext Transfer Protocol", nuf' said
'https' => true, // HTTP over SSL (Secure Socket Layer)
@@ -16,7 +16,7 @@ HTMLPurifier_ConfigSchema::define(
'prevents XSS attacks from using pseudo-schemes like javascript or mocha.'
);
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'URI', 'OverrideAllowedSchemes', true, 'bool',
'If this is set to true (which it is by default), you can override '.
'%URI.AllowedSchemes by simply registering a HTMLPurifier_URIScheme '.

View File

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

View File

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

View File

@@ -1,17 +0,0 @@
<?php
// This file is necessary to run the unit tests and profiling
// scripts.
// Is PEAR available on your system? If it isn't, set to false. If PEAR
// is not part of the default include_path, add it.
$GLOBALS['HTMLPurifierTest']['PEAR'] = true;
// How many times should profiling scripts iterate over the function? More runs
// means more accurate results, but they'll take longer to perform.
$GLOBALS['HTMLPurifierTest']['Runs'] = 2;
// Where is SimpleTest located?
$simpletest_location = '/path/to/simpletest/';
?>

View File

@@ -158,15 +158,9 @@ class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
$uri[18] = '/a/b';
$components[18] = array(null, null, null, '/a/b', null);
// result of malformed tag, gracefully handle error
$uri[19] = 'http://www.google.com/\'>"';
$components[19] = array(null, 'www.google.com', null, '/', null);
$expect_uri[19] = 'http://www.google.com/';
// test empty
$uri[20] = '';
$components[20] = array(null, null, null, '', null);
$expect_uri[20] = '';
// it's not allowed, so generic URI should get it
$uri[19] = '<';
$expect_uri[19] = false;
foreach ($uri as $i => $value) {

View File

@@ -1,7 +1,7 @@
<?php
require_once 'HTMLPurifier/ChildDef.php';
require_once 'HTMLPurifier/Lexer/DirectLex.php';
require_once 'HTMLPurifier/Lexer.php';
require_once 'HTMLPurifier/Generator.php';
class HTMLPurifier_ChildDefTest extends UnitTestCase
@@ -12,8 +12,7 @@ class HTMLPurifier_ChildDefTest extends UnitTestCase
var $gen;
function HTMLPurifier_ChildDefTest() {
// it is vital that the tags be treated as literally as possible
$this->lex = new HTMLPurifier_Lexer_DirectLex();
$this->lex = HTMLPurifier_Lexer::create();
$this->gen = new HTMLPurifier_Generator();
parent::UnitTestCase();
}
@@ -43,75 +42,28 @@ class HTMLPurifier_ChildDefTest extends UnitTestCase
function test_custom() {
$this->def = new HTMLPurifier_ChildDef_Custom(
'(a, b?, c*, d+, (a, b)*)');
$inputs = array();
$expect = array();
$config = array();
$inputs[0] = '';
$expect[0] = false;
$inputs[1] = '<a /><b /><c /><d /><a /><b />';
$expect[1] = true;
$inputs[2] = '<a /><d>Dob</d><a /><b>foo</b><a href="moo" /><b>foo</b>';
$expect[2] = true;
$inputs[3] = '<a /><a />';
$expect[3] = false;
$this->assertSeries($inputs, $expect, $config);
}
function test_table() {
// currently inactive, awaiting augmentation
// the table definition
$this->def = new HTMLPurifier_ChildDef_Table();
$this->def = new HTMLPurifier_ChildDef_Custom(
'(caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))');
$inputs = $expect = $config = array();
$inputs[0] = '';
$expect[0] = false;
// we're using empty tags to compact the tests: under real circumstances
// there would be contents in them
$inputs[1] = '<tr />';
// we really don't care what's inside, because if it turns out
// this tr is illegal, we'll end up re-evaluating the parent node
// anyway.
$inputs[1] = '<tr></tr>';
$expect[1] = true;
$inputs[2] = '<caption /><col /><thead /><tfoot /><tbody>'.
'<tr><td>asdf</td></tr></tbody>';
$inputs[2] = '<caption></caption><col></col><thead></thead>' .
'<tfoot></tfoot><tbody></tbody>';
$expect[2] = true;
$inputs[3] = '<col /><col /><col /><tr />';
$inputs[3] = '<col></col><col></col><col></col><tr></tr>';
$expect[3] = true;
// mixed up order
$inputs[4] = '<col /><colgroup /><tbody /><tfoot /><thead /><tr>1</tr><caption /><tr />';
$expect[4] = '<caption /><col /><colgroup /><thead /><tfoot /><tbody /><tr>1</tr><tr />';
// duplicates of singles
// - first caption serves
// - trailing tfoots/theads get turned into tbodys
$inputs[5] = '<caption>1</caption><caption /><tbody /><tbody /><tfoot>1</tfoot><tfoot />';
$expect[5] = '<caption>1</caption><tfoot>1</tfoot><tbody /><tbody /><tbody />';
// errant text dropped (until bubbling is implemented)
$inputs[6] = 'foo';
$expect[6] = false;
// whitespace sticks to the previous element, last whitespace is
// stationary
$inputs[7] = "\n <tr />\n <tr />\n ";
$expect[7] = true;
$inputs[8] = "\n\t<tbody />\n\t\t<tfoot />\n\t\t\t";
$expect[8] = "\n\t\t<tfoot />\n\t<tbody />\n\t\t\t";
$this->assertSeries($inputs, $expect, $config);
}
@@ -223,4 +175,4 @@ class HTMLPurifier_ChildDefTest extends UnitTestCase
}
?>
?>

View File

@@ -1,8 +1,8 @@
<?php
require_once 'HTMLPurifier/ConfigSchema.php';
require_once 'HTMLPurifier/ConfigDef.php';
class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
class HTMLPurifier_ConfigDefTest extends UnitTestCase
{
var $old_copy;
@@ -13,16 +13,16 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// you pay for using Singletons. Good thing we can overload it.
// first, let's get a clean copy to do tests
$our_copy = new HTMLPurifier_ConfigSchema();
$our_copy = new HTMLPurifier_ConfigDef();
// get the old copy
$this->old_copy = HTMLPurifier_ConfigSchema::instance();
$this->old_copy = HTMLPurifier_ConfigDef::instance();
// put in our copy, and reassign to the REAL reference
$this->our_copy =& HTMLPurifier_ConfigSchema::instance($our_copy);
$this->our_copy =& HTMLPurifier_ConfigDef::instance($our_copy);
}
function tearDown() {
// testing is done, restore the old copy
HTMLPurifier_ConfigSchema::instance($this->old_copy);
HTMLPurifier_ConfigDef::instance($this->old_copy);
}
function testNormal() {
@@ -31,9 +31,9 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// define a namespace
$description = 'Configuration that is always available.';
HTMLPurifier_ConfigSchema::defineNamespace(
HTMLPurifier_ConfigDef::defineNamespace(
'Core', $description
);
); $line = __LINE__;
$this->assertIdentical($this->our_copy->defaults, array(
'Core' => array()
));
@@ -41,7 +41,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
'Core' => array()
));
$namespace = new HTMLPurifier_ConfigEntity_Namespace();
$namespace->description = $description;
$namespace->addDescription($file, $line, $description);
$this->assertIdentical($this->our_copy->info_namespace, array(
'Core' => $namespace
));
@@ -50,7 +50,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// define a directive
$description = 'This is a description of the directive.';
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Name', 'default value', 'string',
$description
); $line = __LINE__;
@@ -71,7 +71,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// define a directive in an undefined namespace
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Extension', 'Name', false, 'bool',
'This is for an extension, but we have not defined its namespace!'
);
@@ -83,7 +83,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// redefine a value in a valid manner
$description = 'Alternative configuration definition';
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Name', 'default value', 'string',
$description
); $line = __LINE__;
@@ -98,7 +98,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// redefine a directive in an invalid manner
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Name', 'different default', 'string',
'Inconsistent default or type, cannot redefine'
);
@@ -109,7 +109,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// make an enumeration
HTMLPurifier_ConfigSchema::defineAllowedValues(
HTMLPurifier_ConfigDef::defineAllowedValues(
'Core', 'Name', array(
'Real Value',
'Real Value 2'
@@ -128,7 +128,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// redefinition of enumeration is cumulative
HTMLPurifier_ConfigSchema::defineAllowedValues(
HTMLPurifier_ConfigDef::defineAllowedValues(
'Core', 'Name', array(
'Real Value 3',
)
@@ -143,7 +143,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// cannot define enumeration for undefined directive
HTMLPurifier_ConfigSchema::defineAllowedValues(
HTMLPurifier_ConfigDef::defineAllowedValues(
'Core', 'Foobar', array(
'Real Value 9',
)
@@ -155,7 +155,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// test defining value aliases for an enumerated value
HTMLPurifier_ConfigSchema::defineValueAliases(
HTMLPurifier_ConfigDef::defineValueAliases(
'Core', 'Name', array(
'Aliased Value' => 'Real Value'
)
@@ -170,7 +170,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// redefine should be cumulative
HTMLPurifier_ConfigSchema::defineValueAliases(
HTMLPurifier_ConfigDef::defineValueAliases(
'Core', 'Name', array(
'Aliased Value 2' => 'Real Value 2'
)
@@ -185,7 +185,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// cannot create alias to not-allowed value
HTMLPurifier_ConfigSchema::defineValueAliases(
HTMLPurifier_ConfigDef::defineValueAliases(
'Core', 'Name', array(
'Aliased Value 3' => 'Invalid Value'
)
@@ -197,7 +197,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// cannot create alias for already allowed value
HTMLPurifier_ConfigSchema::defineValueAliases(
HTMLPurifier_ConfigDef::defineValueAliases(
'Core', 'Name', array(
'Real Value' => 'Real Value 2'
)
@@ -209,7 +209,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// define a directive with an invalid type
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Foobar', false, 'omen',
'Omen is not a valid type, so we reject this.'
);
@@ -221,7 +221,7 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
// define a directive with inconsistent type
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Foobaz', 10, 'string',
'If we say string, we should mean it, not integer 10.'
);
@@ -231,24 +231,6 @@ class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
$this->swallowErrors();
// define a directive with bad characters
HTMLPurifier_ConfigSchema::define(
'Core', 'Core.Attr', 10, 'int',
'No periods! >:-('
);
$this->assertError('Directive name must be alphanumeric');
$this->assertNoErrors();
$this->swallowErrors();
// define a namespace with bad characters
HTMLPurifier_ConfigSchema::defineNamespace(
'Foobar&Gromit', $description
);
$this->assertError('Namespace name must be alphanumeric');
$this->assertNoErrors();
$this->swallowErrors();
}

View File

@@ -8,42 +8,41 @@ class HTMLPurifier_ConfigTest extends UnitTestCase
var $our_copy, $old_copy;
function setUp() {
// set up a dummy schema object for testing
$our_copy = new HTMLPurifier_ConfigSchema();
$this->old_copy = HTMLPurifier_ConfigSchema::instance();
$this->our_copy =& HTMLPurifier_ConfigSchema::instance($our_copy);
$our_copy = new HTMLPurifier_ConfigDef();
$this->old_copy = HTMLPurifier_ConfigDef::instance();
$this->our_copy =& HTMLPurifier_ConfigDef::instance($our_copy);
}
function tearDown() {
HTMLPurifier_ConfigSchema::instance($this->old_copy);
HTMLPurifier_ConfigDef::instance($this->old_copy);
}
function test() {
HTMLPurifier_ConfigSchema::defineNamespace('Core', 'Corestuff');
HTMLPurifier_ConfigSchema::defineNamespace('Attr', 'Attributes');
HTMLPurifier_ConfigSchema::defineNamespace('Extension', 'Extensible');
HTMLPurifier_ConfigDef::defineNamespace('Core', 'Corestuff');
HTMLPurifier_ConfigDef::defineNamespace('Attr', 'Attributes');
HTMLPurifier_ConfigDef::defineNamespace('Extension', 'Extensible');
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Key', false, 'bool', 'A boolean directive.'
);
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Attr', 'Key', 42, 'int', 'An integer directive.'
);
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Extension', 'Pert', 'foo', 'string', 'A string directive.'
);
HTMLPurifier_ConfigSchema::define(
HTMLPurifier_ConfigDef::define(
'Core', 'Encoding', 'utf-8', 'istring', 'Case insensitivity!'
);
HTMLPurifier_ConfigSchema::defineAllowedValues(
HTMLPurifier_ConfigDef::defineAllowedValues(
'Extension', 'Pert', array('foo', 'moo')
);
HTMLPurifier_ConfigSchema::defineValueAliases(
HTMLPurifier_ConfigDef::defineValueAliases(
'Extension', 'Pert', array('cow' => 'moo')
);
HTMLPurifier_ConfigSchema::defineAllowedValues(
HTMLPurifier_ConfigDef::defineAllowedValues(
'Core', 'Encoding', array('utf-8', 'iso-8859-1')
);
@@ -94,17 +93,6 @@ 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

@@ -52,8 +52,10 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
$inputs[7] = new HTMLPurifier_Token_Text($theta_char);
$expect[7] = $theta_char;
$default_config = HTMLPurifier_Config::createDefault();
foreach ($inputs as $i => $input) {
$result = $this->gen->generateFromToken($input);
if (!isset($config[$i])) $config[$i] = $default_config;
$result = $this->gen->generateFromToken($input, $config[$i]);
$this->assertEqual($result, $expect[$i]);
paintIf($result, $result != $expect[$i]);
}
@@ -120,56 +122,6 @@ class HTMLPurifier_GeneratorTest extends UnitTestCase
}
var $config;
function assertGeneration($tokens, $expect) {
$result = $this->gen->generateFromTokens($tokens, $this->config);
// normalized newlines, this probably should be put somewhere else
$result = str_replace("\r\n", "\n", $result);
$result = str_replace("\r", "\n", $result);
$this->assertEqual($expect, $result);
}
function test_generateFromTokens_XHTMLoff() {
$this->config = HTMLPurifier_Config::createDefault();
$this->config->set('Core', 'XHTML', false);
// omit trailing slash
$this->assertGeneration(
array( new HTMLPurifier_Token_Empty('br') ),
'<br>'
);
// there should be a test for attribute minimization, but it is
// impossible for something like that to happen due to our current
// definitions! fix it later
// namespaced attributes must be dropped
$this->assertGeneration(
array( new HTMLPurifier_Token_Start('p', array('xml:lang'=>'fr')) ),
'<p>'
);
}
function test_generateFromTokens_TidyFormat() {
// abort test if tidy isn't loaded
if (!extension_loaded('tidy')) return;
$this->config = HTMLPurifier_Config::createDefault();
$this->config->set('Core', 'TidyFormat', true);
// nice wrapping please
$this->assertGeneration(
array(
new HTMLPurifier_Token_Start('div'),
new HTMLPurifier_Token_Text('Text'),
new HTMLPurifier_Token_End('div')
),
"<div>\n Text\n</div>\n"
);
}
}
?>

View File

@@ -11,6 +11,24 @@ class HTMLPurifier_Lexer_DirectLexTest extends UnitTestCase
$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
function test_parseAttributeString() {

View File

@@ -38,25 +38,6 @@ class HTMLPurifier_LexerTest extends UnitTestCase
$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() {
$this->assertExtractBody('<b>Bold</b>');
$this->assertExtractBody('<html><body><b>Bold</b></body></html>', '<b>Bold</b>');
@@ -268,16 +249,13 @@ class HTMLPurifier_LexerTest extends UnitTestCase
,new HTMLPurifier_Token_Text('Link')
,new HTMLPurifier_Token_End('a')
);
$sax_expect[16] = false; // PEARSax doesn't support it!
// test that UTF-8 is preserved
$char_hearts = $this->_entity_lookup->table['hearts'];
$input[17] = $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();
foreach($input as $i => $discard) {
if (!isset($config[$i])) $config[$i] = $default_config;

View File

@@ -54,34 +54,12 @@ class HTMLPurifier_URISchemeTest extends UnitTestCase
$scheme = new HTMLPurifier_URIScheme_ftp();
$config = HTMLPurifier_Config::createDefault();
$this->assertIdentical(
$scheme->validateComponents(
'user', 'www.example.com', 21, '/', 's=foobar', $config),
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() {

View File

@@ -40,7 +40,7 @@ require_once 'HTMLPurifier.php';
// define callable test files
$test_files = array();
$test_files[] = 'ConfigTest.php';
$test_files[] = 'ConfigSchemaTest.php';
$test_files[] = 'ConfigDefTest.php';
$test_files[] = 'LexerTest.php';
$test_files[] = 'Lexer/DirectLexTest.php';
$test_files[] = 'TokenTest.php';
@@ -114,14 +114,14 @@ if (isset($_GET['file']) && isset($test_file_lookup[$_GET['file']])) {
// execute only one test
$test_file = $_GET['file'];
$test = new GroupTest('HTML Purifier - ' . $test_file);
$test = new GroupTest('HTMLPurifier - ' . $test_file);
$path = 'HTMLPurifier/' . $test_file;
require_once $path;
$test->addTestClass(htmlpurifier_path2class($path));
} else {
$test = new GroupTest('HTML Purifier');
$test = new GroupTest('HTMLPurifier');
foreach ($test_files as $test_file) {
$path = 'HTMLPurifier/' . $test_file;