mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-08-03 20:58:11 +02:00
Compare commits
14 Commits
v3.1.0rc1
...
v2.0.0-str
Author | SHA1 | Date | |
---|---|---|---|
|
42858ad594 | ||
|
5ecb11f19a | ||
|
0101311193 | ||
|
c35eb3e95f | ||
|
b829e76bbf | ||
|
e967680250 | ||
|
dd2fd06591 | ||
|
cec7a1c087 | ||
|
c2d3d5b859 | ||
|
9a84e11f34 | ||
|
37ea1673dd | ||
|
5395d8b4bd | ||
|
c980e76197 | ||
|
2bf912d528 |
312
INSTALL
312
INSTALL
@@ -1,57 +1,64 @@
|
||||
|
||||
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 downloaded the wrong software!)
|
||||
|
||||
While the impatient can get going immediately with some of the sample
|
||||
code at the bottom of this library, it's well worth reading this entire
|
||||
document--most of the other documentation assumes that you are familiar
|
||||
with these contents.
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
1. Compatibility
|
||||
|
||||
HTML Purifier is PHP 5 only, and is actively tested from PHP 5.0.5 and
|
||||
up. It has no core dependencies with other libraries. PHP
|
||||
4 support was deprecated on December 31, 2007 with HTML Purifier 3.0.0.
|
||||
Essential security fixes will be issued for the 2.1.x branch until
|
||||
August 8, 2008.
|
||||
HTML Purifier works in both PHP 4 and PHP 5, from PHP 4.3.2 and up. It has no
|
||||
core dependencies with other libraries.
|
||||
|
||||
These optional extensions can enhance the capabilities of HTML Purifier:
|
||||
|
||||
* iconv : Converts text to and from non-UTF-8 encodings
|
||||
* tidy : Used for pretty-printing HTML
|
||||
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.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
2. Reconnaissance
|
||||
|
||||
A big plus of HTML Purifier is its inerrant support of standards, so
|
||||
your web-pages should be standards-compliant. (They should also use
|
||||
semantic markup, but that's another issue altogether, one HTML Purifier
|
||||
cannot fix without reading your mind.)
|
||||
2. Including the library
|
||||
|
||||
HTML Purifier can process these doctypes:
|
||||
Simply use:
|
||||
|
||||
require_once '/path/to/library/HTMLPurifier.auto.php';
|
||||
|
||||
...and you're good to go. Since HTML Purifier's codebase is fairly
|
||||
large, I recommend only including HTML Purifier when you need it.
|
||||
|
||||
If you don't like your include_path to be fiddled around with, simply set
|
||||
HTML Purifier's library/ directory to the include path yourself and then:
|
||||
|
||||
require_once 'HTMLPurifier.php';
|
||||
|
||||
Only the contents in the library/ folder are necessary, so you can remove
|
||||
everything else when using HTML Purifier in a production environment.
|
||||
|
||||
|
||||
|
||||
3. Preparing the proper output environment
|
||||
|
||||
HTML Purifier is all about web-standards, so accordingly your webpages should
|
||||
be standards compliant. HTML Purifier can deal with these doctypes:
|
||||
|
||||
* XHTML 1.0 Transitional (default)
|
||||
* XHTML 1.0 Strict
|
||||
* HTML 4.01 Transitional
|
||||
* HTML 4.01 Strict
|
||||
* XHTML 1.1
|
||||
* XHTML 1.1 sans Ruby
|
||||
|
||||
...and these character encodings:
|
||||
|
||||
* UTF-8 (default)
|
||||
* Any encoding iconv supports (with crippled internationalization support)
|
||||
* Any encoding iconv supports (support is crippled for i18n though)
|
||||
|
||||
These defaults reflect what my choices would be if I were authoring an
|
||||
HTML document, however, what you choose depends on the nature of your
|
||||
codebase. If you don't know what doctype you are using, you can determine
|
||||
the doctype from this identifier at the top of your source code:
|
||||
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">
|
||||
@@ -60,156 +67,23 @@ the doctype from this identifier at the top of your source code:
|
||||
|
||||
<meta http-equiv="Content-type" content="text/html;charset=ENCODING">
|
||||
|
||||
If the character encoding declaration is missing, STOP NOW, and
|
||||
read 'docs/enduser-utf8.html' (web accessible at
|
||||
http://htmlpurifier.org/docs/enduser-utf8.html). In fact, even if it is
|
||||
present, read this document anyway, as many websites specify their
|
||||
document's character encoding incorrectly.
|
||||
For legacy codebases these declarations may be missing. If that is the case,
|
||||
STOP, and read docs/enduser-utf8.html
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
3. Including the library
|
||||
|
||||
The procedure is quite simple:
|
||||
|
||||
require_once '/path/to/library/HTMLPurifier.auto.php';
|
||||
|
||||
This will setup an autoloader, so the library's files are only included
|
||||
when you use them.
|
||||
|
||||
Only the contents in the library/ folder are necessary, so you can remove
|
||||
everything else when using HTML Purifier in a production environment.
|
||||
|
||||
If you installed HTML Purifier via PEAR, all you need to do is:
|
||||
|
||||
require_once 'HTMLPurifier.auto.php';
|
||||
|
||||
Please note that the usual PEAR practice of including just the classes you
|
||||
want will not work with HTML Purifier's autoloading scheme.
|
||||
|
||||
Advanced users, read on; other users can skip to section 4.
|
||||
|
||||
Autoload compatibility
|
||||
----------------------
|
||||
|
||||
HTML Purifier attempts to be as smart as possible when registering an
|
||||
autoloader, but there are some cases where you will need to change
|
||||
your own code to accomodate HTML Purifier. These are those cases:
|
||||
|
||||
PHP VERSION IS LESS THAN 5.1.2, AND YOU'VE DEFINED __autoload
|
||||
Because spl_autoload_register() doesn't exist in early versions
|
||||
of PHP 5, HTML Purifier has no way of adding itself to the autoload
|
||||
stack. Modify your __autoload function to test
|
||||
HTMLPurifier_Bootstrap::autoload($class)
|
||||
|
||||
For example, suppose your autoload function looks like this:
|
||||
|
||||
function __autoload($class) {
|
||||
require str_replace('_', '/', $class) . '.php';
|
||||
return true;
|
||||
}
|
||||
|
||||
A modified version with HTML Purifier would look like this:
|
||||
|
||||
function __autoload($class) {
|
||||
if (HTMLPurifier_Bootstrap::autoload($class)) return true;
|
||||
require str_replace('_', '/', $class) . '.php';
|
||||
return true;
|
||||
}
|
||||
|
||||
Note that there *is* some custom behavior in our autoloader; the
|
||||
original autoloader in our example would work for 99% of the time,
|
||||
but would fail when including language files.
|
||||
|
||||
AN __autoload FUNCTION IS DECLARED AFTER OUR AUTOLOADER IS REGISTERED
|
||||
spl_autoload_register() has the curious behavior of disabling
|
||||
the existing __autoload() handler. Users need to explicitly
|
||||
spl_autoload_register('__autoload'). Because we use SPL when it
|
||||
is available, __autoload() will ALWAYS be disabled. If __autoload()
|
||||
is declared before HTML Purifier is loaded, this is not a problem:
|
||||
HTML Purifier will register the function for you. But if it is
|
||||
declared afterwards, it will mysteriously not work. This
|
||||
snippet of code (after your autoloader is defined) will fix it:
|
||||
|
||||
spl_autoload_register('__autoload')
|
||||
|
||||
Users should also be on guard if they use a version of PHP previous
|
||||
to 5.1.2 without an autoloader--HTML Purifier will define __autoload()
|
||||
for you, which can collide with an autoloader that was added by *you*
|
||||
later.
|
||||
|
||||
|
||||
For better performance
|
||||
----------------------
|
||||
|
||||
Opcode caches, which greatly speed up PHP initialization for scripts
|
||||
with large amounts of code (HTML Purifier included), don't like
|
||||
autoloaders. We offer an include file that includes all of HTML Purifier's
|
||||
files in one go in an opcode cache friendly manner:
|
||||
|
||||
// If /path/to/library isn't already in your include path, uncomment
|
||||
// the below line:
|
||||
// require '/path/to/library/HTMLPurifier.path.php';
|
||||
|
||||
require 'HTMLPurifier.includes.php';
|
||||
|
||||
Optional components still need to be included--you'll know if you try to
|
||||
use a feature and you get a class doesn't exists error! The autoloader
|
||||
can be used in conjunction with this approach to catch classes that are
|
||||
missing. Simply add this afterwards:
|
||||
|
||||
require 'HTMLPurifier.autoload.php';
|
||||
|
||||
Standalone version
|
||||
------------------
|
||||
|
||||
HTML Purifier has a standalone distribution; you can also generate
|
||||
a standalone file from the full version by running the script
|
||||
maintenance/generate-standalone.php . The standalone version has the
|
||||
benefit of having most of its code in one file, so parsing is much
|
||||
faster and the library is easier to manage.
|
||||
|
||||
If HTMLPurifier.standalone.php exists in the library directory, you
|
||||
can use it like this:
|
||||
|
||||
require '/path/to/HTMLPurifier.standalone.php';
|
||||
|
||||
This is equivalent to including HTMLPurifier.includes.php, except that
|
||||
the contents of standalone/ will be added to your path. To override this
|
||||
behavior, specify a new HTMLPURIFIER_PREFIX where standalone files can
|
||||
be found (usually, this will be one directory up, the "true" library
|
||||
directory in full distributions). Don't forget to set your path too!
|
||||
|
||||
The autoloader can be added to the end to ensure the classes are
|
||||
loaded when necessary; otherwise you can manually include them.
|
||||
To use the autoloader, use this:
|
||||
|
||||
require 'HTMLPurifier.autoload.php';
|
||||
|
||||
For advanced users
|
||||
------------------
|
||||
|
||||
HTMLPurifier.auto.php performs a number of operations that can be done
|
||||
individually. These are:
|
||||
|
||||
HTMLPurifier.path.php
|
||||
Puts /path/to/library in the include path. For high performance,
|
||||
this should be done in php.ini.
|
||||
|
||||
HTMLPurifier.autoload.php
|
||||
Registers our autoload handler HTMLPurifier_Bootstrap::autoload($class).
|
||||
|
||||
You can do these operations by yourself--in fact, you must modify your own
|
||||
autoload handler if you are using a version of PHP earlier than PHP 5.1.2
|
||||
(See "Autoload compatibility" above).
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
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 answer no to any of these
|
||||
questions, read on; otherwise, you can skip to the next section (or, if you're
|
||||
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?
|
||||
@@ -221,6 +95,7 @@ object and read on:
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
|
||||
|
||||
|
||||
4.1. Setting a different character encoding
|
||||
|
||||
You really shouldn't use any other encoding except UTF-8, especially if you
|
||||
@@ -242,9 +117,12 @@ websites):
|
||||
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. If you want to work around
|
||||
this, you are welcome to read docs/enduser-utf8.html for a fix,
|
||||
but please be cognizant of the issues the "solution" creates (for this
|
||||
reason, I do not include the solution in this document).
|
||||
this, you are welcome to read docs/enduser-utf8.html for a workaround,
|
||||
but please be cognizant of the issues the "solution" creates.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4.2. Setting a different doctype
|
||||
@@ -256,6 +134,7 @@ XHTML output like this:
|
||||
|
||||
Other supported doctypes include:
|
||||
|
||||
|
||||
* HTML 4.01 Strict
|
||||
* HTML 4.01 Transitional
|
||||
* XHTML 1.0 Strict
|
||||
@@ -263,71 +142,17 @@ Other supported doctypes include:
|
||||
* XHTML 1.1
|
||||
|
||||
|
||||
|
||||
4.3. Other settings
|
||||
|
||||
There are more configuration directives which can be read about
|
||||
here: <http://htmlpurifier.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. Some of the more interesting ones are configurable at the
|
||||
demo <http://htmlpurifier.org/demo.php> and are well worth looking into
|
||||
for your own system.
|
||||
|
||||
For example, you can fine tune allowed elements and attributes, convert
|
||||
relative URLs to absolute ones, and even autoparagraph input text! These
|
||||
are, respectively, %HTML.Allowed, %URI.MakeAbsolute and %URI.Base, and
|
||||
%AutoFormat.AutoParagraph. The %Namespace.Directive naming convention
|
||||
translates to:
|
||||
|
||||
$config->set('Namespace', 'Directive', $value);
|
||||
|
||||
E.g.
|
||||
|
||||
$config->set('HTML', 'Allowed', 'p,b,a[href],i');
|
||||
$config->set('URI', 'Base', 'http://www.example.com');
|
||||
$config->set('URI', 'MakeAbsolute', true);
|
||||
$config->set('AutoFormat', 'AutoParagraph', true);
|
||||
your code.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
5. Caching
|
||||
|
||||
HTML Purifier generates some cache files (generally one or two) to speed up
|
||||
its execution. For maximum performance, make sure that
|
||||
library/HTMLPurifier/DefinitionCache/Serializer is writeable by the webserver.
|
||||
|
||||
If you are in the library/ folder of HTML Purifier, you can set the
|
||||
appropriate permissions using:
|
||||
|
||||
chmod -R 0755 HTMLPurifier/DefinitionCache/Serializer
|
||||
|
||||
If the above command doesn't work, you may need to assign write permissions
|
||||
to all. This may be necessary if your webserver runs as nobody, but is
|
||||
not recommended since it means any other user can write files in the
|
||||
directory. Use:
|
||||
|
||||
chmod -R 0777 HTMLPurifier/DefinitionCache/Serializer
|
||||
|
||||
You can also chmod files via your FTP client; this option
|
||||
is usually accessible by right clicking the corresponding directory and
|
||||
then selecting "chmod" or "file permissions".
|
||||
|
||||
Starting with 2.0.1, HTML Purifier will generate friendly error messages
|
||||
that will tell you exactly what you have to chmod the directory to, if in doubt,
|
||||
follow its advice.
|
||||
|
||||
If you are unable or unwilling to give write permissions to the cache
|
||||
directory, you can either disable the cache (and suffer a performance
|
||||
hit):
|
||||
|
||||
$config->set('Core', 'DefinitionCache', null);
|
||||
|
||||
Or move the cache directory somewhere else (no trailing slash):
|
||||
|
||||
$config->set('Cache', 'SerializerPath', '/home/user/absolute/path');
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
6. Using the code
|
||||
5. Using the code
|
||||
|
||||
The interface is mind-numbingly simple:
|
||||
|
||||
@@ -340,15 +165,13 @@ The interface is mind-numbingly simple:
|
||||
$clean_html = $purifier->purify( $dirty_html );
|
||||
|
||||
That's it! For more examples, check out docs/examples/ (they aren't very
|
||||
different though). Also, docs/enduser-slow.html gives advice on what to
|
||||
do if HTML Purifier is slowing down your application.
|
||||
different though). Also, SLOW gives advice on what to do if HTML Purifier
|
||||
is slowing down your application.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
7. Quick install
|
||||
|
||||
First, make sure library/HTMLPurifier/DefinitionCache/Serializer is
|
||||
writable by the webserver (see Section 5: Caching above for details).
|
||||
6. Quick install
|
||||
|
||||
If your website is in UTF-8 and XHTML Transitional, use this code:
|
||||
|
||||
<?php
|
||||
@@ -371,3 +194,10 @@ If your website is in a different encoding or doctype, use this code:
|
||||
$clean_html = $purifier->purify($dirty_html);
|
||||
?>
|
||||
|
||||
|
||||
|
||||
7. Caching
|
||||
|
||||
HTML Purifier generates some cache files to speed up its execution. For
|
||||
maximum performance, make sure that library/HTMLPurifier/DefinitionCache/Serializer
|
||||
is writeable by the webserver.
|
@@ -17,7 +17,7 @@ ce document pour quelques choses.
|
||||
|
||||
1. Compatibilité
|
||||
|
||||
HTML Purifier fonctionne dans PHP 5. PHP 5.0.0 est le dernier
|
||||
HTML Purifier fonctionne dans PHP 4 et PHP 5. PHP 4.3.2 est le dernier
|
||||
version que je le testais. Il ne dépend de les autre librairies.
|
||||
|
||||
Les extensions optionnel est iconv (en général déjà installer) et
|
||||
|
305
NEWS
305
NEWS
@@ -9,307 +9,6 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
||||
. Internal change
|
||||
==========================
|
||||
|
||||
3.1.0rc1, released 2008-04-22
|
||||
# Autoload support added. Internal require_once's removed in favor of an
|
||||
explicit require list or autoloading. To use HTML Purifier,
|
||||
you must now either use HTMLPurifier.auto.php
|
||||
or HTMLPurifier.includes.php; setting the include path and including
|
||||
HTMLPurifier.php is insufficient--in such cases include HTMLPurifier.autoload.php
|
||||
as well to register our autoload handler (or modify your autoload function
|
||||
to check HTMLPurifier_Bootstrap::getPath($class)). You can also use
|
||||
HTMLPurifier.safe-includes.php for a less performance friendly but more
|
||||
user-friendly library load.
|
||||
# HTMLPurifier_ConfigSchema static functions are officially deprecated. Schema
|
||||
information is stored in the ConfigSchema directory, and the
|
||||
maintenance/generate-schema-cache.php generates the schema.ser file, which
|
||||
is now instantiated. Support for userland schema changes coming soon!
|
||||
# HTMLPurifier_Config will now throw E_USER_NOTICE when you use a directive
|
||||
alias; to get rid of these errors just modify your configuration to use
|
||||
the new directive name.
|
||||
# HTMLPurifier->addFilter is deprecated; built-in filters can now be
|
||||
enabled using %Filter.$filter_name or by setting your own filters using
|
||||
%Filter.Custom
|
||||
# Directive-level safety properties superceded in favor of module-level
|
||||
safety. Internal method HTMLModule->addElement() has changed, although
|
||||
the externally visible HTMLDefinition->addElement has *not* changed.
|
||||
! Extra utility classes for testing and non-library operations can
|
||||
be found in extras/. Specifically, these are FSTools and ConfigDoc.
|
||||
You may find a use for these in your own project, but right now they
|
||||
are highly experimental and volatile.
|
||||
! Integration with PHPT allows for automated smoketests
|
||||
! Limited support for proprietary HTML elements, namely <marquee>, sponsored
|
||||
by Chris. You can enable them with %HTML.Proprietary if your client
|
||||
demands them.
|
||||
! Support for !important CSS cascade modifier. By default, this will be stripped
|
||||
from CSS, but you can enable it using %CSS.AllowImportant
|
||||
! Support for display and visibility CSS properties added, set %CSS.AllowTricky
|
||||
to true to use them.
|
||||
! HTML Purifier now has its own Exception hierarchy under HTMLPurifier_Exception.
|
||||
Developer error (not enduser error) can cause these to be triggered.
|
||||
! Experimental kses() wrapper introduced with HTMLPurifier.kses.php
|
||||
! Finally %CSS.AllowedProperties for tweaking allowed CSS properties without
|
||||
mucking around with HTMLPurifier_CSSDefinition
|
||||
! ConfigDoc output has been enhanced with version and deprecation info.
|
||||
! %HTML.ForbiddenAttributes and %HTML.ForbiddenElements implemented.
|
||||
- Autoclose now operates iteratively, i.e. <span><span><div> now has
|
||||
both span tags closed.
|
||||
- Various HTMLPurifier_Config convenience functions now accept another parameter
|
||||
$schema which defines what HTMLPurifier_ConfigSchema to use besides the
|
||||
global default.
|
||||
- Fix bug with trusted script handling in libxml versions later than 2.6.28.
|
||||
- Fix bug in ExtractStyleBlocks with comments in style tags
|
||||
- Fix bug in comment parsing for DirectLex
|
||||
- Flush output now displayed when in command line mode for unit tester
|
||||
- Fix bug with rgb(0, 1, 2) color syntax with spaces inside shorthand syntax
|
||||
- HTMLPurifier_HTMLDefinition->addAttribute can now be called multiple times
|
||||
on the same element without emitting errors.
|
||||
- Fixed fatal error in PH5P lexer with invalid tag names
|
||||
. Plugins now get their own changelogs according to project conventions.
|
||||
. Convert tokens to use instanceof, reducing memory footprint and
|
||||
improving comparison speed.
|
||||
. Dry runs now supported in SimpleTest; testing facilities improved
|
||||
. Bootstrap class added for handling autoloading functionality
|
||||
. Implemented recursive glob at FSTools->globr
|
||||
. ConfigSchema now has instance methods for all corresponding define*
|
||||
static methods.
|
||||
. A couple of new historical maintenance scripts were added.
|
||||
. HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php split into two files
|
||||
. tests/index.php can now be run from any directory.
|
||||
. HTMLPurifier_Token subclasses split into seperate files
|
||||
. HTMLPURIFIER_PREFIX now is defined in Bootstrap.php, NOT HTMLPurifier.php
|
||||
. HTMLPURIFIER_PREFIX can now be defined outside of HTML Purifier
|
||||
. New --php=php flag added, allows PHP executable to be specified (command
|
||||
line only!)
|
||||
. htmlpurifier_add_test() preferred method to translate test files in to
|
||||
classes, because it handles PHPT files too.
|
||||
. Debugger class is deprecated and will be removed soon.
|
||||
. Command line argument parsing for testing scripts revamped, now --opt value
|
||||
format is supported.
|
||||
. Smoketests now cleanup after magic quotes
|
||||
. Generator now can output comments (however, comments are still stripped
|
||||
from HTML Purifier output)
|
||||
. HTMLPurifier_ConfigSchema->validate() deprecated in favor of
|
||||
HTMLPurifier_VarParser->parse()
|
||||
. Integers auto-cast into float type by VarParser.
|
||||
. HTMLPURIFIER_STRICT removed; no validation is performed on runtime, only
|
||||
during cache generation
|
||||
. Reordered script calls in maintenance/flush.php
|
||||
. Command line scripts now honor exit codes
|
||||
. When --flush fails in unit testers, abort tests and print message
|
||||
. Improved documentation in docs/dev-flush.html about the maintenance scripts
|
||||
. copy() methods removed in favor of clone keyword
|
||||
|
||||
3.0.0, released 2008-01-06
|
||||
# HTML Purifier is PHP 5 only! The 2.1.x branch will be maintained
|
||||
until PHP 4 is completely deprecated, but no new features will be added
|
||||
to it.
|
||||
+ Visibility declarations added
|
||||
+ Constructor methods renamed to __construct()
|
||||
+ PHP4 reference cruft removed (in progress)
|
||||
! CSS properties are now case-insensitive
|
||||
! DefinitionCacheFactory now can register new implementations
|
||||
! New HTMLPurifier_Filter_ExtractStyleBlocks for extracting <style> from
|
||||
documents and cleaning their contents up. Requires the CSSTidy library
|
||||
<http://csstidy.sourceforge.net/>. You can access the blocks with the
|
||||
'StyleBlocks' Context variable ($purifier->context->get('StyleBlocks')).
|
||||
The output CSS can also be "scoped" for a specific element, use:
|
||||
%Filter.ExtractStyleBlocksScope
|
||||
! Experimental support for some proprietary CSS attributes allowed:
|
||||
opacity (and all of the browser-specific equivalents) and scrollbar colors.
|
||||
Enable by setting %CSS.Proprietary to true.
|
||||
- Colors missing # but in hex form will be corrected
|
||||
- CSS Number algorithm improved
|
||||
- Unit testing and multi-testing now on steroids: command lines,
|
||||
XML output, and other goodies now added.
|
||||
. Unit tests for Injector improved
|
||||
. New classes:
|
||||
+ HTMLPurifier_AttrDef_CSS_AlphaValue
|
||||
+ HTMLPurifier_AttrDef_CSS_Filter
|
||||
. Multitest now has a file docblock
|
||||
|
||||
2.1.3, released 2007-11-05
|
||||
! tests/multitest.php allows you to test multiple versions by running
|
||||
tests/index.php through multiple interpreters using `phpv` shell
|
||||
script (you must provide this script!)
|
||||
- Fixed poor include ordering for Email URI AttrDefs, causes fatal errors
|
||||
on some systems.
|
||||
- Injector algorithm further refined: off-by-one error regarding skip
|
||||
counts for dormant injectors fixed
|
||||
- Corrective blockquote definition now enabled for HTML 4.01 Strict
|
||||
- Fatal error when <img> tag (or any other element with required attributes)
|
||||
has 'id' attribute fixed, thanks NykO18 for reporting
|
||||
- Fix warning emitted when a non-supported URI scheme is passed to the
|
||||
MakeAbsolute URIFilter, thanks NykO18 (again)
|
||||
- Further refine AutoParagraph injector. Behavior inside of elements
|
||||
allowing paragraph tags clarified: only inline content delimeted by
|
||||
double newlines (not block elements) are paragraphed.
|
||||
- Buggy treatment of end tags of elements that have required attributes
|
||||
fixed (does not manifest on default tag-set)
|
||||
- Spurious internal content reorganization error suppressed
|
||||
- HTMLDefinition->addElement now returns a reference to the created
|
||||
element object, as implied by the documentation
|
||||
- Phorum mod's HTML Purifier help message expanded (unreleased elsewhere)
|
||||
- Fix a theoretical class of infinite loops from DirectLex reported
|
||||
by Nate Abele
|
||||
- Work around unnecessary DOMElement type-cast in PH5P that caused errors
|
||||
in PHP 5.1
|
||||
- Work around PHP 4 SimpleTest lack-of-error complaining for one-time-only
|
||||
HTMLDefinition errors, this may indicate problems with error-collecting
|
||||
facilities in PHP 5
|
||||
- Make ErrorCollectorEMock work in both PHP 4 and PHP 5
|
||||
- Make PH5P work with PHP 5.0 by removing unnecessary array parameter typedef
|
||||
. %Core.AcceptFullDocuments renamed to %Core.ConvertDocumentToFragment
|
||||
to better communicate its purpose
|
||||
. Error unit tests can now specify the expectation of no errors. Future
|
||||
iterations of the harness will be extremely strict about what errors
|
||||
are allowed
|
||||
. Extend Injector hooks to allow for more powerful injector routines
|
||||
. HTMLDefinition->addBlankElement created, as according to the HTMLModule
|
||||
method
|
||||
. Doxygen configuration file updated, with minor improvements
|
||||
. Test runner now checks for similarly named files in conf/ directory too.
|
||||
. Minor cosmetic change to flush-definition-cache.php: trailing newline is
|
||||
outputted
|
||||
. Maintenance script for generating PH5P patch added, original PH5P source
|
||||
file also added under version control
|
||||
. Full unit test runner script title made more descriptive with PHP version
|
||||
. Updated INSTALL file to state that 4.3.7 is the earliest version we
|
||||
are actively testing
|
||||
|
||||
2.1.2, released 2007-09-03
|
||||
! Implemented Object module for trusted users
|
||||
! Implemented experimental HTML5 parsing mode using PH5P. To use, add
|
||||
this to your code:
|
||||
require_once 'HTMLPurifier/Lexer/PH5P.php';
|
||||
$config->set('Core', 'LexerImpl', 'PH5P');
|
||||
Note that this Lexer introduces some classes not in the HTMLPurifier
|
||||
namespace. Also, this is PHP5 only.
|
||||
! CSS property border-spacing implemented
|
||||
- Fix non-visible parsing error in DirectLex with empty tags that have
|
||||
slashes inside attribute values.
|
||||
- Fix typo in CSS definition: border-collapse:seperate; was incorrectly
|
||||
accepted as valid CSS. Usually non-visible, because this styling is the
|
||||
default for tables in most browsers. Thanks Brett Zamir for pointing
|
||||
this out.
|
||||
- Fix validation errors in configuration form
|
||||
- Hammer out a bunch of edge-case bugs in the standalone distribution
|
||||
- Inclusion reflection removed from URISchemeRegistry; you must manually
|
||||
include any new schema files you wish to use
|
||||
- Numerous typo fixes in documentation thanks to Brett Zamir
|
||||
. Unit test refactoring for one logical test per test function
|
||||
. Config and context parameters in ComplexHarness deprecated: instead, edit
|
||||
the $config and $context member variables
|
||||
. HTML wrapper in DOMLex now takes DTD identifiers into account; doesn't
|
||||
really make a difference, but is good for completeness sake
|
||||
. merge-library.php script refactored for greater code reusability and
|
||||
PHP4 compatibility
|
||||
|
||||
2.1.1, released 2007-08-04
|
||||
- Fix show-stopper bug in %URI.MakeAbsolute functionality
|
||||
- Fix PHP4 syntax error in standalone version
|
||||
. Add prefix directory to include path for standalone, this prevents
|
||||
other installations from clobbering the standalone's URI schemes
|
||||
. Single test methods can be invoked by prefixing with __only
|
||||
|
||||
2.1.0, released 2007-08-02
|
||||
# flush-htmldefinition-cache.php superseded in favor of a generic
|
||||
flush-definition-cache.php script, you can clear a specific cache
|
||||
by passing its name as a parameter to the script
|
||||
! Phorum mod implemented for HTML Purifier
|
||||
! With %Core.AggressivelyFixLt, <3 and similar emoticons no longer
|
||||
trigger HTML removal in PHP5 (DOMLex). This directive is not necessary
|
||||
for PHP4 (DirectLex).
|
||||
! Standalone file now available, which greatly reduces the amount of
|
||||
includes (although there are still a few files that reside in the
|
||||
standalone folder)
|
||||
! Relative URIs can now be transformed into their absolute equivalents
|
||||
using %URI.Base and %URI.MakeAbsolute
|
||||
! Ruby implemented for XHTML 1.1
|
||||
! You can now define custom URI filtering behavior, see enduser-uri-filter.html
|
||||
for more details
|
||||
! UTF-8 font names now supported in CSS
|
||||
- AutoFormatters emit friendly error messages if tags or attributes they
|
||||
need are not allowed
|
||||
- ConfigForm's compactification of directive names is now configurable
|
||||
- AutoParagraph autoformatter algorithm refined after field-testing
|
||||
- XHTML 1.1 now applies XHTML 1.0 Strict cleanup routines, namely
|
||||
blockquote wrapping
|
||||
- Contents of <style> tags removed by default when tags are removed
|
||||
. HTMLPurifier_Config->getSerial() implemented, this is extremely useful
|
||||
for output cache invalidation
|
||||
. ConfigForm printer now can retrieve CSS and JS files as strings, in
|
||||
case HTML Purifier's directory is not publically accessible
|
||||
. Introduce new text/itext configuration directive values: these represent
|
||||
longer strings that would be more appropriately edited with a textarea
|
||||
. Allow newlines to act as separators for lists, hashes, lookups and
|
||||
%HTML.Allowed
|
||||
. ConfigForm generates textareas instead of text inputs for lists, hashes,
|
||||
lookups, text and itext fields
|
||||
. Hidden element content removal genericized: %Core.HiddenElements can
|
||||
be used to customize this behavior, by default <script> and <style> are
|
||||
hidden
|
||||
. Added HTMLPURIFIER_PREFIX constant, should be used instead of dirname(__FILE__)
|
||||
. Custom ChildDef added to default include list
|
||||
. URIScheme reflection improved: will not attempt to include file if class
|
||||
already exists. May clobber autoload, so I need to keep an eye on it
|
||||
. ConfigSchema heavily optimized, will only collect information and validate
|
||||
definitions when HTMLPURIFIER_SCHEMA_STRICT is true.
|
||||
. AttrDef_URI unit tests and implementation refactored
|
||||
. benchmarks/ directory now protected from public view with .htaccess file;
|
||||
run the tests via command line
|
||||
. URI scheme is munged off if there is no authority and the scheme is the
|
||||
default one
|
||||
. All unit tests inherit from HTMLPurifier_Harness, not UnitTestCase
|
||||
. Interface for URIScheme changed
|
||||
. Generic URI object to hold components of URI added, most systems involved
|
||||
in URI validation have been migrated to use it
|
||||
. Custom filtering for URIs factored out to URIDefinition interface for
|
||||
maximum extensibility
|
||||
|
||||
2.0.1, released 2007-06-27
|
||||
! Tag auto-closing now based on a ChildDef heuristic rather than a
|
||||
manually set auto_close array; some behavior may change
|
||||
! Experimental AutoFormat functionality added: auto-paragraph and
|
||||
linkify your HTML input by setting %AutoFormat.AutoParagraph and
|
||||
%AutoFormat.Linkify to true
|
||||
! Newlines normalized internally, and then converted back to the
|
||||
value of PHP_EOL. If this is not desired, set your newline format
|
||||
using %Output.Newline.
|
||||
! Beta error collection, messages are implemented for the most generic
|
||||
cases involving Lexing or Strategies
|
||||
- Clean up special case code for <script> tags
|
||||
- Reorder includes for DefinitionCache decorators, fixes a possible
|
||||
missing class error
|
||||
- Fixed bug where manually modified definitions were not saved via cache
|
||||
(mostly harmless, except for the fact that it would be a little slower)
|
||||
- Configuration objects with different serials do not clobber each
|
||||
others when revision numbers are unequal
|
||||
- Improve Serializer DefinitionCache directory permissions checks
|
||||
- DefinitionCache no longer throws errors when it encounters old
|
||||
serial files that do not conform to the current style
|
||||
- Stray xmlns attributes removed from configuration documentation
|
||||
- configForm.php smoketest no longer has XSS vulnerability due to
|
||||
unescaped print_r output
|
||||
- Printer adheres to configuration's directives on output format
|
||||
- Fix improperly named form field in ConfigForm printer
|
||||
. Rewire some test-cases to swallow errors rather than expect them
|
||||
. HTMLDefinition printer updated with some of the new attributes
|
||||
. DefinitionCache keys reordered to reflect precedence: version number,
|
||||
hash, then revision number
|
||||
. %Core.DefinitionCache renamed to %Cache.DefinitionImpl
|
||||
. Interlinking in configuration documentation added using
|
||||
Injector_PurifierLinkify
|
||||
. Directives now keep track of aliases to themselves
|
||||
. Error collector now requires a severity to be passed, use PHP's internal
|
||||
error constants for this
|
||||
. HTMLPurifier_Config::getAllowedDirectivesForForm implemented, allows
|
||||
much easier selective embedding of configuration values
|
||||
. Doctype objects now accept public and system DTD identifiers
|
||||
. %HTML.Doctype is now constrained by specific values, to specify a custom
|
||||
doctype use new %HTML.CustomDoctype
|
||||
. ConfigForm truncates long directives to keep the form small, and does
|
||||
not re-output namespaces
|
||||
|
||||
2.0.0, released 2007-06-20
|
||||
# Completely refactored HTMLModuleManager, decentralizing safety
|
||||
information
|
||||
@@ -416,6 +115,8 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
||||
%Attr.IDBlacklistRegexp
|
||||
- Error messages are emitted when you attempt to "allow" elements or
|
||||
attributes that HTML Purifier does not support
|
||||
|
||||
|
||||
- Fix segfault in unit test. The problem is not very reproduceable and
|
||||
I don't know what causes it, but a six line patch fixed it.
|
||||
|
||||
@@ -614,4 +315,4 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
||||
! First public release, most functionality implemented. Notable omissions are:
|
||||
+ Shorthand CSS properties
|
||||
+ Table CSS properties
|
||||
+ Deprecated attribute transformations
|
||||
+ Deprecated attribute transformations
|
106
TODO
106
TODO
@@ -1,4 +1,3 @@
|
||||
|
||||
TODO List
|
||||
|
||||
= KEY ====================
|
||||
@@ -7,44 +6,34 @@ TODO List
|
||||
? Maybe I'll Do It
|
||||
==========================
|
||||
|
||||
If no interest is expressed for a feature that may required a considerable
|
||||
amount of effort to implement, it may get endlessly delayed. Do not be
|
||||
afraid to cast your vote for the next feature to be implemented!
|
||||
2.1 release [Refactor, refactor!]
|
||||
|
||||
|
||||
UPCOMING RELEASE
|
||||
----------------
|
||||
|
||||
IMPORTANT
|
||||
- Release candidate, because of the major changes
|
||||
|
||||
DOCUMENTATION
|
||||
- Update French translation of README
|
||||
|
||||
IMPORTANT FEATURES
|
||||
- Factor out command line parser into its own class, and unit test it
|
||||
|
||||
NICE FEATURES
|
||||
- Factor demo.php into a set of Printer classes, and then create a stub
|
||||
file for users here (inside the actual HTML Purifier library)
|
||||
- Support exporting configuration, so users can easily tweak settings
|
||||
in the demo, and then copy-paste into their own setup
|
||||
|
||||
BUGS
|
||||
- Style attribute height/width limiting for images
|
||||
- Easy way to blacklist elements and attributes
|
||||
- Investigate iconv error emitting
|
||||
- Investigate UTF-8 optimization <http://htmlpurifier.org/phorum/read.php?3,1496>
|
||||
- Figure out what to do about target="" and name="", since they show up so often
|
||||
|
||||
FUTURE VERSIONS
|
||||
---------------
|
||||
# URI validation routines tighter (see docs/dev-code-quality.html) (COMPLEX)
|
||||
# Advanced URI filtering schemes (see docs/proposal-new-directives.txt)
|
||||
- Configuration profiles: predefined directives set with one func call
|
||||
- Implement IDREF support (harder than it seems, since you cannot have
|
||||
IDREFs to non-existent IDs)
|
||||
- Allow non-ASCII characters in font names
|
||||
- Genericize special cases in RemoveForeignElements
|
||||
|
||||
3.2 release [Error'ed]
|
||||
2.2 release [Error'ed]
|
||||
# Error logging for filtering/cleanup procedures
|
||||
- Requires I18N facilities to be created first (COMPLEX)
|
||||
- XSS-attempt detection
|
||||
- More fine-grained control over escaping behavior
|
||||
|
||||
3.3 release [Do What I Mean, Not What I Say]
|
||||
|
||||
|
||||
|
||||
|
||||
2.3 release [Do What I Mean, Not What I Say]
|
||||
# Additional support for poorly written HTML
|
||||
- Microsoft Word HTML cleaning (i.e. MsoNormal, but research essential!)
|
||||
- Friendly strict handling of <address> (block -> <br>)
|
||||
@@ -58,73 +47,60 @@ FUTURE VERSIONS
|
||||
- Remove empty inline tags<i></i>
|
||||
- Append something to duplicate IDs so they're still usable (impl. note: the
|
||||
dupe detector would also need to detect the suffix as well)
|
||||
- Externalize inline CSS to promote clean HTML
|
||||
|
||||
3.4 release [It's All About Trust] (floating)
|
||||
2.4 release [It's All About Trust] (floating)
|
||||
# Implement untrusted, dangerous elements/attributes
|
||||
- Objects and Forms are especially wanted
|
||||
# Implement IDREF support (harder than it seems, since you cannot have
|
||||
IDREFs to non-existent IDs)
|
||||
# Frameset XHTML 1.0 and HTML 4.01 doctypes
|
||||
|
||||
4.0 release [Beyond HTML]
|
||||
3.0 release [Beyond HTML]
|
||||
# Legit token based CSS parsing (will require revamping almost every
|
||||
AttrDef class). Probably will use CSSTidy class
|
||||
AttrDef class)
|
||||
# More control over allowed CSS properties (maybe modularize it in the
|
||||
same fashion!)
|
||||
# HTML 5 support
|
||||
- Standardize token armor for all areas of processing
|
||||
# Formatters for plaintext (COMPLEX)
|
||||
- Auto-paragraphing (be sure to leverage fact that we know when things
|
||||
shouldn't be paragraphed, such as lists and tables).
|
||||
- Linkify URLs
|
||||
- Smileys
|
||||
- Linkification for HTML Purifier docs: notably configuration and classes
|
||||
- Allow tags to be "armored", an internal flag that protects them
|
||||
from validation and passes them out unharmed
|
||||
- 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
|
||||
- Convert RTL/LTR override characters to <bdo> tags, or vice versa on demand.
|
||||
Also, enable disabling of directionality
|
||||
- Table of Contents generation (XHTML Compiler might be reusable)
|
||||
|
||||
5.0 release [To XML and Beyond]
|
||||
4.0 release [To XML and Beyond]
|
||||
- Extended HTML capabilities based on namespacing and tag transforms (COMPLEX)
|
||||
- Hooks for adding custom processors to custom namespaced tags and
|
||||
attributes, offer default implementation
|
||||
- Lots of documentation and samples
|
||||
- XHTML 1.1 support
|
||||
|
||||
Ongoing
|
||||
- More refactoring to take advantage of PHP5's facilities
|
||||
- Lots of profiling, make it faster!
|
||||
- Plugins for major CMSes (COMPLEX)
|
||||
- phpBB
|
||||
- WordPress (mostly written, needs beta-testing)
|
||||
- eFiction
|
||||
- more! (look for ones that use WYSIWYGs)
|
||||
- Complete basic smoketests
|
||||
|
||||
AutoFormat
|
||||
- Smileys
|
||||
- Syntax highlighting with <pre> and possibly <?php
|
||||
- Look at http://drupal.org/project/Modules/category/63 for ideas
|
||||
|
||||
Unknown release (on a scratch-an-itch basis)
|
||||
# CHMOD install script for PEAR installs
|
||||
? Semi-lossy dumb alternate character encoding transfor
|
||||
? Have 'lang' attribute be checked against official lists, achieved by
|
||||
encoding all characters that have string entity equivalents
|
||||
- Explain how to use HTML Purifier in non-PHP languages
|
||||
- Abstract ChildDef_BlockQuote to work with all elements that only
|
||||
allow blocks in them, required or optional
|
||||
- Reorganize Unit Tests
|
||||
- Advanced URI filtering schemes (see docs/proposal-new-directives.txt)
|
||||
- Implement lenient <ruby> child validation
|
||||
- Explain how to use HTML Purifier in non-PHP languages / create
|
||||
a simple command line stub (or complicated?)
|
||||
- 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
|
||||
- Distinguish between default settings and explicitly set settings, so
|
||||
configurations can be merged
|
||||
- Nested configuration namespaces
|
||||
- Allow scoped="scoped" attribute in <style> tags; may be troublesome
|
||||
because regular CSS has no way of uniquely identifying nodes, so we'd
|
||||
have to generate IDs
|
||||
- Time PHPT tests
|
||||
- Refactor loop tests (esp. AttrDef_URI)
|
||||
- Reorganize configuration directives (Create more namespaces! Get messy!)
|
||||
|
||||
Requested
|
||||
? Native content compression, whitespace stripping (don't rely on Tidy, make
|
||||
sure we don't remove from <pre> or related tags)
|
||||
|
||||
Wontfix
|
||||
- Non-lossy smart alternate character encoding transformations (unless
|
||||
patch provided)
|
||||
- Pretty-printing HTML: users can use Tidy on the output on entire page
|
||||
- Native content compression, whitespace stripping (don't rely on Tidy, make
|
||||
sure we don't remove from <pre> or related tags): use gzip if this is
|
||||
really important
|
||||
- Pretty-printing HTML, users can use Tidy on the output on entire page
|
15
WHATSNEW
15
WHATSNEW
@@ -1,8 +1,7 @@
|
||||
Release 3.1.0rc1 is a release candidate aimed primarily at ironing out bugs
|
||||
in HTML Purifier's shiny new __autoload system. There are lots of new features,
|
||||
however; some notable ones include support for the !important CSS modifier,
|
||||
display and visibility CSS properties with %CSS.AllowTricky, marquee
|
||||
with %HTML.Proprietary (had you scared for a moment, hmm?), a kses() wrapper,
|
||||
%CSS.AllowedProperties, %HTML.ForbiddenAttributes and %HTML.ForbiddenElements
|
||||
and a totally revamped ConfigDoc system. And of course, the usual slew of
|
||||
bugfixes.
|
||||
HTML Purifier 2.0 is the culmination of two major architectural changes.
|
||||
The first is Tidy, which enables HTML Purifier to both natively support
|
||||
deprecated elements and also convert them to standards-compliant
|
||||
alternatives. The second is the Advanced API, which enables users to
|
||||
create new elements and attributes with ease. Keeping in line with a
|
||||
commitment to high quality, there are also five esoteric bug-fixes and a
|
||||
plethora of subtle improvements that enhance the library.
|
||||
|
BIN
art/100cases.png
BIN
art/100cases.png
Binary file not shown.
Before Width: | Height: | Size: 2.7 KiB |
@@ -1 +0,0 @@
|
||||
Deny from all
|
@@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
require_once '../library/HTMLPurifier.auto.php';
|
||||
// emulates inserting a dir called HTMLPurifier into your class dir
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . '../library/');
|
||||
|
||||
@include_once '../test-settings.php';
|
||||
|
||||
// PEAR
|
||||
require_once 'Benchmark/Timer.php'; // to do the timing
|
||||
require_once 'Text/Password.php'; // for generating random input
|
||||
require_once 'HTMLPurifier/ConfigSchema.php';
|
||||
require_once 'HTMLPurifier/Config.php';
|
||||
require_once 'HTMLPurifier/Context.php';
|
||||
|
||||
$LEXERS = array();
|
||||
$RUNS = isset($GLOBALS['HTMLPurifierTest']['Runs'])
|
||||
@@ -14,11 +16,22 @@ $RUNS = isset($GLOBALS['HTMLPurifierTest']['Runs'])
|
||||
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
||||
$LEXERS['DirectLex'] = new HTMLPurifier_Lexer_DirectLex();
|
||||
|
||||
if (!empty($GLOBALS['HTMLPurifierTest']['PEAR'])) {
|
||||
require_once 'HTMLPurifier/Lexer/PEARSax3.php';
|
||||
$LEXERS['PEARSax3'] = new HTMLPurifier_Lexer_PEARSax3();
|
||||
} else {
|
||||
exit('PEAR required to perform benchmark.');
|
||||
}
|
||||
|
||||
if (version_compare(PHP_VERSION, '5', '>=')) {
|
||||
require_once 'HTMLPurifier/Lexer/DOMLex.php';
|
||||
$LEXERS['DOMLex'] = new HTMLPurifier_Lexer_DOMLex();
|
||||
}
|
||||
|
||||
// PEAR
|
||||
require_once 'Benchmark/Timer.php'; // to do the timing
|
||||
require_once 'Text/Password.php'; // for generating random input
|
||||
|
||||
// custom class to aid unit testing
|
||||
class RowTimer extends Benchmark_Timer
|
||||
{
|
||||
@@ -152,4 +165,4 @@ echo '<div>Random input was: ' .
|
||||
?>
|
||||
|
||||
|
||||
</body></html>
|
||||
</body></html>
|
19
benchmarks/ProfileDirectLex.php
Normal file
19
benchmarks/ProfileDirectLex.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . '../library/');
|
||||
|
||||
require_once 'HTMLPurifier/ConfigSchema.php';
|
||||
require_once 'HTMLPurifier/Config.php';
|
||||
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
||||
require_once 'HTMLPurifier/Context.php';
|
||||
|
||||
$input = file_get_contents('samples/Lexer/4.html');
|
||||
$lexer = new HTMLPurifier_Lexer_DirectLex();
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$context = new HTMLPurifier_Context();
|
||||
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$tokens = $lexer->tokenizeHTML($input, $config, $context);
|
||||
}
|
||||
|
||||
?>
|
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
ini_set('xdebug.trace_format', 1);
|
||||
ini_set('xdebug.show_mem_delta', true);
|
||||
|
||||
if (file_exists('Trace.xt')) {
|
||||
echo "Previous trace Trace.xt must be removed before this script can be run.";
|
||||
exit;
|
||||
}
|
||||
|
||||
xdebug_start_trace(dirname(__FILE__) . '/Trace');
|
||||
require_once '../library/HTMLPurifier.auto.php';
|
||||
|
||||
$purifier = new HTMLPurifier();
|
||||
|
||||
$data = $purifier->purify(file_get_contents('samples/Lexer/4.html'));
|
||||
xdebug_stop_trace();
|
||||
|
||||
echo "Trace finished.";
|
@@ -2,12 +2,12 @@
|
||||
|
||||
/**
|
||||
* Generates XML and HTML documents describing configuration.
|
||||
* @note PHP 5.2+ only!
|
||||
* @note PHP 5 only!
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO:
|
||||
- make XML format richer
|
||||
- make XML format richer (see XMLSerializer_ConfigSchema)
|
||||
- extend XSLT transformation (see the corresponding XSLT file)
|
||||
- allow generation of packaged docs that can be easily moved
|
||||
- multipage documentation
|
||||
@@ -15,46 +15,26 @@ TODO:
|
||||
- add blurbs to ToC
|
||||
*/
|
||||
|
||||
if (version_compare(PHP_VERSION, '5.2.0', '<')) exit('PHP 5.2.0 or greater required.');
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
chdir(dirname(__FILE__));
|
||||
if (version_compare('5', PHP_VERSION, '>')) exit('Requires PHP 5 or higher.');
|
||||
error_reporting(E_ALL); // probably not possible to use E_STRICT
|
||||
|
||||
// load dual-libraries
|
||||
require_once '../extras/HTMLPurifierExtras.auto.php';
|
||||
require_once '../library/HTMLPurifier.auto.php';
|
||||
require_once 'library/ConfigDoc.auto.php';
|
||||
|
||||
// setup HTML Purifier singleton
|
||||
HTMLPurifier::getInstance(array(
|
||||
'AutoFormat.PurifierLinkify' => true
|
||||
));
|
||||
|
||||
$interchange = HTMLPurifier_ConfigSchema_InterchangeBuilder::buildFromDirectory();
|
||||
$interchange->validate();
|
||||
|
||||
$style = 'plain'; // use $_GET in the future, careful to validate!
|
||||
$configdoc_xml = 'configdoc.xml';
|
||||
|
||||
$xml_builder = new HTMLPurifier_ConfigSchema_Builder_Xml();
|
||||
$xml_builder->openURI($configdoc_xml);
|
||||
$xml_builder->build($interchange);
|
||||
|
||||
$xslt = new ConfigDoc_HTMLXSLTProcessor();
|
||||
$xslt->importStylesheet(dirname(__FILE__) . "/styles/$style.xsl");
|
||||
$output = $xslt->transformToHTML($configdoc_xml);
|
||||
|
||||
if (!$output) {
|
||||
echo "Error in generating files\n";
|
||||
exit(1);
|
||||
}
|
||||
$schema = HTMLPurifier_ConfigSchema::instance();
|
||||
$style = 'plain'; // use $_GET in the future
|
||||
$configdoc = new ConfigDoc();
|
||||
$output = $configdoc->generate($schema, $style);
|
||||
|
||||
// write out
|
||||
file_put_contents("$style.html", $output);
|
||||
|
||||
if (php_sapi_name() != 'cli') {
|
||||
// output (instant feedback if it's a browser)
|
||||
// output = instant feedback
|
||||
echo $output;
|
||||
} else {
|
||||
echo 'Files generated successfully.';
|
||||
}
|
||||
|
||||
?>
|
@@ -5,5 +5,6 @@
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||
require_once 'HTMLPurifierExtras.php';
|
||||
require_once 'HTMLPurifierExtras.autoload.php';
|
||||
require_once 'ConfigDoc.php';
|
||||
|
||||
?>
|
39
configdoc/library/ConfigDoc.php
Normal file
39
configdoc/library/ConfigDoc.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
require_once 'ConfigDoc/HTMLXSLTProcessor.php';
|
||||
require_once 'ConfigDoc/XMLSerializer/Types.php';
|
||||
require_once 'ConfigDoc/XMLSerializer/ConfigSchema.php';
|
||||
|
||||
class ConfigDoc
|
||||
{
|
||||
|
||||
function generate($schema, $xsl_stylesheet_name = 'plain', $parameters = array()) {
|
||||
// generate types document, describing type constraints
|
||||
$types_serializer = new ConfigDoc_XMLSerializer_Types();
|
||||
$types_document = $types_serializer->serialize($schema);
|
||||
$types_document->save(dirname(__FILE__) . '/../types.xml'); // only ONE
|
||||
|
||||
// generate configdoc.xml, documents configuration directives
|
||||
$schema_serializer = new ConfigDoc_XMLSerializer_ConfigSchema();
|
||||
$schema_document = $schema_serializer->serialize($schema);
|
||||
$schema_document->save('configdoc.xml');
|
||||
|
||||
// setup transformation
|
||||
$xsl_stylesheet = dirname(__FILE__) . "/../styles/$xsl_stylesheet_name.xsl";
|
||||
$xslt_processor = new ConfigDoc_HTMLXSLTProcessor();
|
||||
$xslt_processor->setParameters($parameters);
|
||||
$xslt_processor->importStylesheet($xsl_stylesheet);
|
||||
|
||||
return $xslt_processor->transformToHTML($schema_document);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any generated files
|
||||
*/
|
||||
function cleanup() {
|
||||
unlink('configdoc.xml');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,23 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Decorator/extender XSLT processor specifically for HTML documents.
|
||||
* Special XSLTProcessor specifically for HTML documents. Loosely
|
||||
* based off of XSLTProcessor, but not really
|
||||
*/
|
||||
class ConfigDoc_HTMLXSLTProcessor
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance of XSLTProcessor
|
||||
*/
|
||||
protected $xsltProcessor;
|
||||
|
||||
public function __construct($proc = false) {
|
||||
if ($proc === false) $proc = new XSLTProcessor();
|
||||
$this->xsltProcessor = $proc;
|
||||
public function __construct() {
|
||||
$this->xsltProcessor = new XSLTProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @note Allows a string $xsl filename to be passed
|
||||
* Imports stylesheet for processor to use
|
||||
* @param $xsl XSLT DOM tree, or filename of the XSL transformation
|
||||
*/
|
||||
public function importStylesheet($xsl) {
|
||||
if (is_string($xsl)) {
|
||||
@@ -29,25 +27,15 @@ class ConfigDoc_HTMLXSLTProcessor
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an XML file into compatible XHTML based on the stylesheet
|
||||
* @param $xml XML DOM tree, or string filename
|
||||
* @return string HTML output
|
||||
* @todo Rename to transformToXHTML, as transformToHTML is misleading
|
||||
* Transforms an XML file into HTML based on the stylesheet
|
||||
* @param $xml XML DOM tree
|
||||
*/
|
||||
public function transformToHTML($xml) {
|
||||
if (is_string($xml)) {
|
||||
$dom = new DOMDocument();
|
||||
$dom->load($xml);
|
||||
} else {
|
||||
$dom = $xml;
|
||||
}
|
||||
$out = $this->xsltProcessor->transformToXML($dom);
|
||||
$out = $this->xsltProcessor->transformToXML($xml);
|
||||
|
||||
// fudges for HTML backwards compatibility
|
||||
// assumes that document is XHTML
|
||||
$out = str_replace('/>', ' />', $out); // <br /> not <br/>
|
||||
$out = str_replace(' xmlns=""', '', $out); // rm unnecessary xmlns
|
||||
|
||||
if (class_exists('Tidy')) {
|
||||
// cleanup output
|
||||
$config = array(
|
||||
@@ -60,26 +48,15 @@ class ConfigDoc_HTMLXSLTProcessor
|
||||
$tidy->cleanRepair();
|
||||
$out = (string) $tidy;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk sets parameters for the XSL stylesheet
|
||||
* @param array $options Associative array of options to set
|
||||
*/
|
||||
public function setParameters($options) {
|
||||
foreach ($options as $name => $value) {
|
||||
$this->xsltProcessor->setParameter('', $name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward any other calls to the XSLT processor
|
||||
*/
|
||||
public function __call($name, $arguments) {
|
||||
call_user_func_array(array($this->xsltProcessor, $name), $arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
26
configdoc/library/ConfigDoc/XMLSerializer.php
Normal file
26
configdoc/library/ConfigDoc/XMLSerializer.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The XMLSerializer hierarchy of classes consist of classes that take
|
||||
* objects and serialize them into XML, specifically DOM, form; this
|
||||
* super-class contains convenience functions for those classes.
|
||||
*/
|
||||
class ConfigDoc_XMLSerializer
|
||||
{
|
||||
|
||||
protected function appendHTMLDiv($document, $node, $html) {
|
||||
$purifier = HTMLPurifier::getInstance();
|
||||
$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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
118
configdoc/library/ConfigDoc/XMLSerializer/ConfigSchema.php
Normal file
118
configdoc/library/ConfigDoc/XMLSerializer/ConfigSchema.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
require_once 'ConfigDoc/XMLSerializer.php';
|
||||
|
||||
class ConfigDoc_XMLSerializer_ConfigSchema extends ConfigDoc_XMLSerializer
|
||||
{
|
||||
|
||||
/**
|
||||
* Serializes a schema into DOM form
|
||||
* @todo Split into sub-serializers
|
||||
* @param $schema HTMLPurifier_ConfigSchema to serialize
|
||||
*/
|
||||
public function serialize($schema) {
|
||||
$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:
|
||||
- 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);
|
||||
$this->appendHTMLDiv($dom_document, $dom_namespace_description,
|
||||
$schema->info_namespace[$namespace_name]->description);
|
||||
|
||||
foreach ($namespace_info as $name => $info) {
|
||||
|
||||
if ($info->class == 'alias') continue;
|
||||
|
||||
$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_type = $dom_document->createElement('type', $info->type);
|
||||
if ($info->allow_null) {
|
||||
$dom_type->setAttribute('allow-null', 'yes');
|
||||
}
|
||||
$dom_constraints->appendChild($dom_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\"";
|
||||
} elseif (is_null($raw_default)) {
|
||||
$default = 'null';
|
||||
} else {
|
||||
$default = print_r(
|
||||
$schema->defaults[$namespace_name][$name], true
|
||||
);
|
||||
}
|
||||
|
||||
$dom_default = $dom_document->createElement('default', $default);
|
||||
|
||||
// remove this once we get a DTD
|
||||
$dom_default->setAttribute('xml:space', 'preserve');
|
||||
|
||||
$dom_constraints->appendChild($dom_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');
|
||||
// refuse to write $file if it's a full path
|
||||
if (str_replace('\\', '/', realpath($file)) != $file) {
|
||||
$dom_description->setAttribute('file', $file);
|
||||
$dom_description->setAttribute('line', $line);
|
||||
}
|
||||
$this->appendHTMLDiv($dom_document, $dom_description, $description);
|
||||
$dom_descriptions->appendChild($dom_description);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $dom_document;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
27
configdoc/library/ConfigDoc/XMLSerializer/Types.php
Normal file
27
configdoc/library/ConfigDoc/XMLSerializer/Types.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
require_once 'ConfigDoc/XMLSerializer.php';
|
||||
|
||||
class ConfigDoc_XMLSerializer_Types extends ConfigDoc_XMLSerializer
|
||||
{
|
||||
|
||||
/**
|
||||
* Serializes the types in a schema into DOM form
|
||||
* @param $schema HTMLPurifier_ConfigSchema owner of types to serialize
|
||||
*/
|
||||
public function serialize($schema) {
|
||||
$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);
|
||||
}
|
||||
return $types_document;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,30 +1,16 @@
|
||||
|
||||
body {margin:0;padding:0;}
|
||||
#content {
|
||||
margin:1em auto;
|
||||
max-width: 47em;
|
||||
width: expression(document.body.clientWidth >
|
||||
85 * parseInt(document.body.currentStyle.fontSize) ?
|
||||
"54em": "auto");
|
||||
}
|
||||
body {margin:1em 4em;}
|
||||
|
||||
table {border-collapse:collapse;}
|
||||
table td, table th {padding:0.2em;}
|
||||
|
||||
table.constraints {margin:0 0 1em;}
|
||||
table.constraints th {
|
||||
text-align:right;padding-left:0.4em;padding-right:0.4em;background:#EEE;
|
||||
width:8em;vertical-align:top;}
|
||||
table.constraints td {padding-right:0.4em; padding-left: 1em;}
|
||||
table.constraints td ul {padding:0; margin:0; list-style:none;}
|
||||
table.constraints th {text-align:left;padding-left:0.4em;}
|
||||
table.constraints td {padding-right:0.4em;}
|
||||
table.constraints td pre {margin:0;}
|
||||
|
||||
#tocContainer {position:relative;}
|
||||
#toc {list-style-type:none; font-weight:bold; font-size:1em; margin-bottom:1em;}
|
||||
#toc li {position:relative; line-height: 1.2em;}
|
||||
#toc .col-2 {margin-left:50%;}
|
||||
#toc .col-l {float:left;}
|
||||
#toc ul {list-style-type:disc; font-weight:normal; padding-bottom:1.2em;}
|
||||
#toc {list-style-type:none; font-weight:bold;}
|
||||
#toc ul {list-style-type:disc; font-weight:normal;}
|
||||
|
||||
.description p {margin-top:0;margin-bottom:1em;}
|
||||
|
||||
@@ -33,10 +19,6 @@ table.constraints td pre {margin:0;}
|
||||
#library {font-size:1em;}
|
||||
h1 {margin-top:0;}
|
||||
h2 {border-bottom:1px solid #CCC; font-family:sans-serif; font-weight:normal;
|
||||
font-size:1.3em; clear:both;}
|
||||
font-size:1.3em;}
|
||||
h3 {font-family:sans-serif; font-size:1.1em; font-weight:bold; }
|
||||
h4 {font-family:sans-serif; font-size:0.9em; font-weight:bold; }
|
||||
|
||||
.deprecated {color: #CCC;}
|
||||
.deprecated table.constraints th {background:#FFF;}
|
||||
.deprecated-notice {color: #000; text-align:center; margin-bottom: 1em;}
|
||||
|
@@ -15,11 +15,7 @@
|
||||
<xsl:param name="css" select="'styles/plain.css'"/>
|
||||
<xsl:param name="title" select="'Configuration Documentation'"/>
|
||||
|
||||
<xsl:variable name="typeLookup" select="document('../types.xml')/types" />
|
||||
<xsl:variable name="usageLookup" select="document('../usage.xml')/usage" />
|
||||
|
||||
<!-- Twiddle this variable to get the columns as even as possible -->
|
||||
<xsl:variable name="maxNumberAdjust" select="1" />
|
||||
<xsl:variable name="typeLookup" select="document('../types.xml')" />
|
||||
|
||||
<xsl:template match="/">
|
||||
<html lang="en" xml:lang="en">
|
||||
@@ -29,170 +25,85 @@
|
||||
<link rel="stylesheet" type="text/css" href="{$css}" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="content">
|
||||
<div id="library"><xsl:value-of select="/configdoc/title" /></div>
|
||||
<h1><xsl:value-of select="$title" /></h1>
|
||||
<div id="tocContainer">
|
||||
<h2>Table of Contents</h2>
|
||||
<ul id="toc">
|
||||
<xsl:apply-templates mode="toc">
|
||||
<xsl:with-param name="overflowNumber" select="round(count(/configdoc/namespace) div 2) + $maxNumberAdjust" />
|
||||
</xsl:apply-templates>
|
||||
</ul>
|
||||
</div>
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
<div id="library"><xsl:value-of select="/configdoc/title" /></div>
|
||||
<h1><xsl:value-of select="$title" /></h1>
|
||||
<h2>Table of Contents</h2>
|
||||
<ul id="toc">
|
||||
<xsl:apply-templates mode="toc" />
|
||||
</ul>
|
||||
<xsl:apply-templates />
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="title" mode="toc" />
|
||||
<xsl:template match="namespace" mode="toc">
|
||||
<xsl:param name="overflowNumber" />
|
||||
<xsl:variable name="number"><xsl:number level="single" /></xsl:variable>
|
||||
<xsl:variable name="directiveNumber"><xsl:number level="any" count="directive" /></xsl:variable>
|
||||
<xsl:if test="count(directive)>0">
|
||||
<li>
|
||||
<!-- BEGIN multicolumn code -->
|
||||
<xsl:if test="$number >= $overflowNumber">
|
||||
<xsl:attribute name="class">col-2</xsl:attribute>
|
||||
</xsl:if>
|
||||
<xsl:if test="$number = $overflowNumber">
|
||||
<xsl:attribute name="style">margin-top:-<xsl:value-of select="($number * 2 + $directiveNumber - 3) * 1.2" />em</xsl:attribute>
|
||||
</xsl:if>
|
||||
<!-- END multicolumn code -->
|
||||
<a href="#{@id}"><xsl:value-of select="name" /></a>
|
||||
<ul>
|
||||
<xsl:apply-templates select="directive" mode="toc">
|
||||
<xsl:with-param name="overflowNumber" select="$overflowNumber" />
|
||||
</xsl:apply-templates>
|
||||
<xsl:apply-templates select="directive" mode="toc" />
|
||||
</ul>
|
||||
<xsl:if test="$number + 1 = $overflowNumber">
|
||||
<div class="col-l" />
|
||||
</xsl:if>
|
||||
</li>
|
||||
</xsl:if>
|
||||
</xsl:template>
|
||||
<xsl:template match="directive" mode="toc">
|
||||
<xsl:variable name="number">
|
||||
<xsl:number level="any" count="directive|namespace" />
|
||||
</xsl:variable>
|
||||
<xsl:if test="not(deprecated)">
|
||||
<li>
|
||||
<a href="#{@id}"><xsl:value-of select="name" /></a>
|
||||
</li>
|
||||
</xsl:if>
|
||||
<li><a href="#{@id}"><xsl:value-of select="name" /></a></li>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="title" />
|
||||
|
||||
<xsl:template match="namespace">
|
||||
<div class="namespace">
|
||||
<xsl:apply-templates />
|
||||
<xsl:if test="count(directive)=0">
|
||||
<p>No configuration directives defined for this namespace.</p>
|
||||
</xsl:if>
|
||||
</div>
|
||||
<xsl:apply-templates />
|
||||
<xsl:if test="count(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="." /></h2>
|
||||
</xsl:template>
|
||||
<xsl:template match="namespace/description">
|
||||
<div class="description">
|
||||
<xsl:copy-of xmlns:xhtml="http://www.w3.org/1999/xhtml" select="xhtml:div/node()" />
|
||||
<xsl:copy-of select="div/node()" />
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="directive">
|
||||
<div>
|
||||
<xsl:attribute name="class"><!--
|
||||
-->directive<!--
|
||||
--><xsl:if test="deprecated"> deprecated</xsl:if><!--
|
||||
--></xsl:attribute>
|
||||
<xsl:apply-templates>
|
||||
<xsl:with-param name="id" select="@id" />
|
||||
</xsl:apply-templates>
|
||||
</div>
|
||||
<xsl:apply-templates />
|
||||
</xsl:template>
|
||||
<xsl:template match="directive/name">
|
||||
<xsl:param name="id" />
|
||||
<xsl:apply-templates select="../aliases/alias" mode="anchor" />
|
||||
<h3 id="{$id}"><xsl:value-of select="$id" /></h3>
|
||||
<h3 id="{../@id}"><xsl:value-of select="../@id" /></h3>
|
||||
</xsl:template>
|
||||
<xsl:template match="alias" mode="anchor">
|
||||
<a id="{.}"></a>
|
||||
</xsl:template>
|
||||
|
||||
<!-- Do not pass through -->
|
||||
<xsl:template match="alias"></xsl:template>
|
||||
|
||||
<xsl:template match="directive/constraints">
|
||||
<xsl:param name="id" />
|
||||
<table class="constraints">
|
||||
<xsl:apply-templates />
|
||||
<xsl:if test="../aliases/alias">
|
||||
<xsl:apply-templates select="../aliases" mode="constraints" />
|
||||
<!-- Calculated other values -->
|
||||
<xsl:if test="../descriptions/description[@file]">
|
||||
<tr>
|
||||
<th>Used by:</th>
|
||||
<td>
|
||||
<xsl:for-each select="../descriptions/description">
|
||||
<xsl:if test="position()>1">, </xsl:if>
|
||||
<xsl:value-of select="@file" />
|
||||
</xsl:for-each>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:if>
|
||||
<xsl:apply-templates select="$usageLookup/directive[@id=$id]" />
|
||||
</table>
|
||||
</xsl:template>
|
||||
<xsl:template match="directive/aliases" mode="constraints">
|
||||
<tr>
|
||||
<th>Aliases</th>
|
||||
<td>
|
||||
<xsl:for-each select="alias">
|
||||
<xsl:if test="position()>1">, </xsl:if>
|
||||
<xsl:value-of select="." />
|
||||
</xsl:for-each>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="directive/description">
|
||||
<xsl:template match="directive//description">
|
||||
<div class="description">
|
||||
<xsl:copy-of xmlns:xhtml="http://www.w3.org/1999/xhtml" select="xhtml:div/node()" />
|
||||
<xsl:copy-of select="div/node()" />
|
||||
</div>
|
||||
</xsl:template>
|
||||
<xsl:template match="directive/deprecated">
|
||||
<div class="deprecated-notice">
|
||||
<strong>Warning:</strong>
|
||||
This directive was deprecated in version <xsl:value-of select="version" />.
|
||||
<a href="#{use}">%<xsl:value-of select="use" /></a> should be used instead.
|
||||
</div>
|
||||
</xsl:template>
|
||||
<xsl:template match="usage/directive">
|
||||
<tr>
|
||||
<th>Used in</th>
|
||||
<td>
|
||||
<ul>
|
||||
<xsl:apply-templates />
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="usage/directive/file">
|
||||
<li>
|
||||
<em><xsl:value-of select="@name" /></em> on line<xsl:if test="count(line)>1">s</xsl:if>
|
||||
<xsl:text> </xsl:text>
|
||||
<xsl:for-each select="line">
|
||||
<xsl:if test="position()>1">, </xsl:if>
|
||||
<xsl:value-of select="." />
|
||||
</xsl:for-each>
|
||||
</li>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="constraints/version">
|
||||
<tr>
|
||||
<th>Version added</th>
|
||||
<td><xsl:value-of select="." /></td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="constraints/type">
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<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/type[@id=$type]/text()" />
|
||||
<xsl:value-of select="$typeLookup/types/type[@id=$type]/text()" />
|
||||
<xsl:if test="@allow-null='yes'">
|
||||
(or null)
|
||||
</xsl:if>
|
||||
@@ -201,7 +112,7 @@
|
||||
</xsl:template>
|
||||
<xsl:template match="constraints/allowed">
|
||||
<tr>
|
||||
<th>Allowed values</th>
|
||||
<th>Allowed values:</th>
|
||||
<td>
|
||||
<xsl:for-each select="value"><!--
|
||||
--><xsl:if test="position()>1">, </xsl:if>
|
||||
@@ -212,22 +123,9 @@
|
||||
</xsl:template>
|
||||
<xsl:template match="constraints/default">
|
||||
<tr>
|
||||
<th>Default</th>
|
||||
<th>Default:</th>
|
||||
<td><pre><xsl:value-of select="." xml:space="preserve" /></pre></td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="constraints/external">
|
||||
<tr>
|
||||
<th>External deps</th>
|
||||
<td>
|
||||
<ul>
|
||||
<xsl:apply-templates />
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
<xsl:template match="constraints/external/project">
|
||||
<xsl:value-of select="." />
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
</xsl:stylesheet>
|
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<types>
|
||||
<type id="string">String</type>
|
||||
<type id="istring">Case-insensitive string</type>
|
||||
<type id="text">Text</type>
|
||||
<type id="itext">Case-insensitive text</type>
|
||||
<type id="int">Integer</type>
|
||||
<type id="float">Float</type>
|
||||
<type id="bool">Boolean</type>
|
||||
<type id="lookup">Lookup array</type>
|
||||
<type id="list">Array list</type>
|
||||
<type id="hash">Associative array</type>
|
||||
<type id="mixed">Mixed</type>
|
||||
</types>
|
@@ -1,361 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<usage>
|
||||
<directive id="Core.CollectErrors">
|
||||
<file name="HTMLPurifier.php">
|
||||
<line>131</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>93</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>50</line>
|
||||
<line>62</line>
|
||||
<line>327</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>44</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.Proprietary">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>201</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowTricky">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>205</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowImportant">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>209</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowedProperties">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>261</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Cache.DefinitionImpl">
|
||||
<file name="HTMLPurifier/DefinitionCacheFactory.php">
|
||||
<line>49</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Doctype">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>83</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.CustomDoctype">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>85</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.XHTML">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>88</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Strict">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>93</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.Encoding">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>267</line>
|
||||
<line>285</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Test.ForceNoIconv">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>269</line>
|
||||
<line>290</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EscapeNonASCIICharacters">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>287</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.MaintainLineNumbers">
|
||||
<file name="HTMLPurifier/ErrorCollector.php">
|
||||
<line>81</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>90</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>45</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.CommentScriptContents">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>40</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.TidyFormat">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>61</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.Newline">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>86</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.BlockWrapper">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>213</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Parent">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>221</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedElements">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>238</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedAttributes">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>239</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Allowed">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>242</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.ForbiddenElements">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>303</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.ForbiddenAttributes">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>304</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Trusted">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>198</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>245</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>34</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedModules">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>205</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.CoreModules">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>206</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Proprietary">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>220</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDBlacklist">
|
||||
<file name="HTMLPurifier/IDAccumulator.php">
|
||||
<line>26</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.Language">
|
||||
<file name="HTMLPurifier/LanguageFactory.php">
|
||||
<line>85</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.LexerImpl">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>78</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.ConvertDocumentToFragment">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>237</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Host">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>57</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/URIFilter/DisableExternal.php">
|
||||
<line>8</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Base">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>58</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.DefaultScheme">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>65</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.AllowedSchemes">
|
||||
<file name="HTMLPurifier/URISchemeRegistry.php">
|
||||
<line>42</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.OverrideAllowedSchemes">
|
||||
<file name="HTMLPurifier/URISchemeRegistry.php">
|
||||
<line>43</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Disable">
|
||||
<file name="HTMLPurifier/AttrDef/URI.php">
|
||||
<line>24</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Munge">
|
||||
<file name="HTMLPurifier/AttrDef/URI.php">
|
||||
<line>78</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.ColorKeywords">
|
||||
<file name="HTMLPurifier/AttrDef/CSS/Color.php">
|
||||
<line>12</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/AttrDef/HTML/Color.php">
|
||||
<line>12</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.AllowedFrameTargets">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/FrameTarget.php">
|
||||
<line>15</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.EnableID">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>20</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDPrefix">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>26</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDPrefixLocal">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>28</line>
|
||||
<line>31</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDBlacklistRegexp">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>54</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.DefaultTextDir">
|
||||
<file name="HTMLPurifier/AttrTransform/BdoDir.php">
|
||||
<line>13</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.RemoveInvalidImg">
|
||||
<file name="HTMLPurifier/AttrTransform/ImgRequired.php">
|
||||
<line>18</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>20</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.DefaultInvalidImage">
|
||||
<file name="HTMLPurifier/AttrTransform/ImgRequired.php">
|
||||
<line>19</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.DefaultInvalidImageAlt">
|
||||
<file name="HTMLPurifier/AttrTransform/ImgRequired.php">
|
||||
<line>27</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EscapeInvalidChildren">
|
||||
<file name="HTMLPurifier/ChildDef/Required.php">
|
||||
<line>55</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Cache.SerializerPath">
|
||||
<file name="HTMLPurifier/DefinitionCache/Serializer.php">
|
||||
<line>91</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="FilterParam.ExtractStyleBlocksTidyImpl">
|
||||
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
|
||||
<line>41</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="FilterParam.ExtractStyleBlocksScope">
|
||||
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
|
||||
<line>65</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="FilterParam.ExtractStyleBlocksEscaping">
|
||||
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
|
||||
<line>123</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TidyLevel">
|
||||
<file name="HTMLPurifier/HTMLModule/Tidy.php">
|
||||
<line>45</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TidyAdd">
|
||||
<file name="HTMLPurifier/HTMLModule/Tidy.php">
|
||||
<line>49</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TidyRemove">
|
||||
<file name="HTMLPurifier/HTMLModule/Tidy.php">
|
||||
<line>50</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="AutoFormatParam.PurifierLinkifyDocURL">
|
||||
<file name="HTMLPurifier/Injector/PurifierLinkify.php">
|
||||
<line>15</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.AggressivelyFixLt">
|
||||
<file name="HTMLPurifier/Lexer/DOMLex.php">
|
||||
<line>44</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.DirectLexLineNumberSyncInterval">
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>59</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EscapeInvalidTags">
|
||||
<file name="HTMLPurifier/Strategy/MakeWellFormed.php">
|
||||
<line>22</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>19</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.RemoveScriptContents">
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>22</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.HiddenElements">
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>23</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.HostBlacklist">
|
||||
<file name="HTMLPurifier/URIFilter/HostBlacklist.php">
|
||||
<line>8</line>
|
||||
</file>
|
||||
</directive>
|
||||
</usage>
|
@@ -3,7 +3,7 @@
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="description" content="Specification for HTML Purifier's advanced API for defining custom filtering behavior." />
|
||||
<meta name="description" content="Functional specification for HTML Purifier's advanced API for defining custom filtering behavior." />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
|
||||
<title>Advanced API - HTML Purifier</title>
|
||||
@@ -16,11 +16,6 @@
|
||||
<div id="index">Return to the <a href="index.html">index</a>.</div>
|
||||
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div>
|
||||
|
||||
<p>
|
||||
<strong>Warning:</strong> This document may be out-of-date. When in doubt,
|
||||
consult the source code documentation.
|
||||
</p>
|
||||
|
||||
<p>HTML Purifier currently natively supports only a subset of HTML's
|
||||
allowed elements, attributes, and behavior; specifically, this subset
|
||||
is the set of elements that are safe for untrusted users to use.
|
||||
@@ -215,4 +210,4 @@ the usual things required are:</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body></html>
|
||||
</body></html>
|
@@ -11,15 +11,20 @@ docs/examples/demo.php - ad hoc HTML/PHP soup to the extreme
|
||||
|
||||
AttrDef - a lot of duplication, more generic classes need to be created;
|
||||
a lot of strtolower() calls, no legit casing
|
||||
Class - doesn't support Unicode characters (fringe); uses regular expressions
|
||||
Class - doesn't support Unicode characters (fringe); uses regular
|
||||
expressions
|
||||
Lang - code duplication; premature optimization
|
||||
Length - easily mistaken for CSSLength
|
||||
URI - multiple regular expressions; missing validation for parts (?)
|
||||
CSS - parser doesn't accept advanced CSS (fringe)
|
||||
Number - constructor interface inconsistent with Integer
|
||||
ConfigSchema - redefinition is a mess
|
||||
Strategy
|
||||
FixNesting - cannot bubble nodes out of structures, duplicated checks
|
||||
for special-case parent node
|
||||
MakeWellFormed - insufficient automatic closing definitions (check HTML
|
||||
spec for optional end tags, also, closing based on type (block/inline)
|
||||
might be efficient).
|
||||
RemoveForeignElements - should be run in parallel with MakeWellFormed
|
||||
URIScheme - needs to have callable generic checks
|
||||
mailto - doesn't validate emails, doesn't validate querystring
|
||||
|
@@ -1,376 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="description" content="Describes config schema framework in HTML Purifier." />
|
||||
<link rel="stylesheet" type="text/css" href="./style.css" />
|
||||
<title>Config Schema - HTML Purifier</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Config Schema</h1>
|
||||
|
||||
<div id="filing">Filed under Development</div>
|
||||
<div id="index">Return to the <a href="index.html">index</a>.</div>
|
||||
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div>
|
||||
|
||||
<p>
|
||||
HTML Purifier has a fairly complex system for configuration. Users
|
||||
interact with a <code>HTMLPurifier_Config</code> object to
|
||||
set configuration directives. The values they set are validated according
|
||||
to a configuration schema, <code>HTMLPurifier_ConfigSchema</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The schema is mostly transparent to end-users, but if you're doing development
|
||||
work for HTML Purifier and need to define a new configuration directive,
|
||||
you'll need to interact with it. We'll also talk about how to define
|
||||
userspace configuration directives at the very end.
|
||||
</p>
|
||||
|
||||
<h2>Write a directive file</h2>
|
||||
|
||||
<p>
|
||||
Directive files define configuration directives to be used by
|
||||
HTML Purifier. They are placed in <code>library/HTMLPurifier/ConfigSchema/schema/</code>
|
||||
in the form <code><em>Namespace</em>.<em>Directive</em>.txt</code> (I
|
||||
couldn't think of a more descriptive file extension.)
|
||||
Directive files are actually what we call <code>StringHash</code>es,
|
||||
i.e. associative arrays represented in a string form reminiscent of
|
||||
<a href="http://qa.php.net/write-test.php">PHPT</a> tests. Here's a
|
||||
sample directive file, <code>Test.Sample.txt</code>:
|
||||
</p>
|
||||
|
||||
<pre>Test.Sample
|
||||
TYPE: string/null
|
||||
DEFAULT: NULL
|
||||
ALLOWED: 'foo', 'bar'
|
||||
VALUE-ALIASES: 'baz' => 'bar'
|
||||
VERSION: 3.1.0
|
||||
--DESCRIPTION--
|
||||
This is a sample configuration directive for the purposes of the
|
||||
<code>dev-config-schema.html<code> documentation.
|
||||
--ALIASES--
|
||||
Test.Example</pre>
|
||||
|
||||
<p>
|
||||
Each of these segments has a specific meaning:
|
||||
</p>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Key</th>
|
||||
<th>Example</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>Test.Sample</td>
|
||||
<td>The name of the directive, in the form Namespace.Directive
|
||||
(implicitly the first line)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>TYPE</td>
|
||||
<td>string/null</td>
|
||||
<td>The type of variable this directive accepts. See below for
|
||||
details. You can also add <code>/null</code> to the end of
|
||||
any basic type to allow null values too.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DEFAULT</td>
|
||||
<td>NULL</td>
|
||||
<td>A parseable PHP expression of the default value.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DESCRIPTION</td>
|
||||
<td>This is a...</td>
|
||||
<td>An HTML description of what this directive does.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>VERSION</td>
|
||||
<td>3.1.0</td>
|
||||
<td><em>Recommended</em>. The version of HTML Purifier this directive was added.
|
||||
Directives that have been around since 1.0.0 don't have this,
|
||||
but any new ones should.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ALIASES</td>
|
||||
<td>Test.Example</td>
|
||||
<td><em>Optional</em>. A comma separated list of aliases for this directive.
|
||||
This is most useful for backwards compatibility and should
|
||||
not be used otherwise.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ALLOWED</td>
|
||||
<td>'foo', 'bar'</td>
|
||||
<td><em>Optional</em>. Set of allowed value for a directive,
|
||||
a comma separated list of parseable PHP expressions. This
|
||||
is only allowed string, istring, text and itext TYPEs.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>VALUE-ALIASES</td>
|
||||
<td>'baz' => 'bar'</td>
|
||||
<td><em>Optional</em>. Mapping of one value to another, and
|
||||
should be a comma separated list of keypair duples. This
|
||||
is only allowed string, istring, text and itext TYPEs.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DEPRECATED-VERSION</td>
|
||||
<td>3.1.0</td>
|
||||
<td><em>Not shown</em>. Indicates that the directive was
|
||||
deprecated this version.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DEPRECATED-USE</td>
|
||||
<td>Test.NewDirective</td>
|
||||
<td><em>Not shown</em>. Indicates what new directive should be
|
||||
used instead. Note that the directives will functionally be
|
||||
different, although they should offer the same functionality.
|
||||
If they are identical, use an alias instead.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>EXTERNAL</td>
|
||||
<td>CSSTidy</td>
|
||||
<td><em>Not shown</em>. Indicates if there is an external library
|
||||
the user will need to download and install to use this configuration
|
||||
directive. As of right now, this is merely a Google-able name; future
|
||||
versions may also provide links and instructions.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Some notes on format and style:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
Each of these keys can be expressed in the short format
|
||||
(<code>KEY: Value</code>) or the long format
|
||||
(<code>--KEY--</code> with value beneath). You must use the
|
||||
long format if multiple lines are needed, or if a long format
|
||||
has been used already (that's why <code>ALIASES</code> in our
|
||||
example is in the long format); otherwise, it's user preference.
|
||||
</li>
|
||||
<li>
|
||||
The HTML descriptions should be wrapped at about 80 columns; do
|
||||
not rely on editor word-wrapping.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Also, as promised, here is the set of possible types:
|
||||
</p>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Example</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>string</td>
|
||||
<td>'Foo'</td>
|
||||
<td><a href="http://docs.php.net/manual/en/language.types.string.php">String</a> without newlines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>istring</td>
|
||||
<td>'foo'</td>
|
||||
<td>Case insensitive ASCII string without newlines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>text</td>
|
||||
<td>"A<em>\n</em>b"</td>
|
||||
<td>String with newlines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>itext</td>
|
||||
<td>"a<em>\n</em>b"</td>
|
||||
<td>Case insensitive ASCII string without newlines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>int</td>
|
||||
<td>23</td>
|
||||
<td>Integer</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>float</td>
|
||||
<td>3.0</td>
|
||||
<td>Floating point number</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>bool</td>
|
||||
<td>true</td>
|
||||
<td>Boolean</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>lookup</td>
|
||||
<td>array('key' => true)</td>
|
||||
<td>Lookup array, used with <code>isset($var[$key])</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>list</td>
|
||||
<td>array('f', 'b')</td>
|
||||
<td>List array, with ordered numerical indexes</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>hash</td>
|
||||
<td>array('key' => 'val')</td>
|
||||
<td>Associative array of keys to values</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>mixed</td>
|
||||
<td>new stdclass</td>
|
||||
<td>Any PHP variable is fine</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
The examples represent what will be returned out of the configuration
|
||||
object; users have a little bit of leeway when setting configuration
|
||||
values (for example, a lookup value can be specified as a list;
|
||||
HTML Purifier will flip it as necessary.) These types are defined
|
||||
in <a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/VarParser.php">
|
||||
library/HTMLPurifier/VarParser.php</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For more information on what values are allowed, and how they are parsed,
|
||||
consult <a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php">
|
||||
library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php</a>, as well
|
||||
as <a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php">
|
||||
library/HTMLPurifier/ConfigSchema/Interchange/Directive.php</a> for
|
||||
the semantics of the parsed values.
|
||||
</p>
|
||||
|
||||
<h2>Refreshing the cache</h2>
|
||||
|
||||
<p>
|
||||
You may have noticed that your directive file isn't doing anything
|
||||
yet. That's because it hasn't been added to the runtime
|
||||
<code>HTMLPurifier_ConfigSchema</code> instance. Run
|
||||
<code>maintenance/generate-schema-cache.php</code> to fix this.
|
||||
If there were no errors, you're good to go! Don't forget to add
|
||||
some unit tests for your functionality!
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you ever make changes to your configuration directives, you
|
||||
will need to run this script again.
|
||||
</p>
|
||||
|
||||
<h2>Errors</h2>
|
||||
|
||||
<p>
|
||||
All directive files go through a rigorous validation process
|
||||
through <a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/ConfigSchema/">
|
||||
library/HTMLPurifier/ConfigSchema/Validator.php</a>, as well
|
||||
as some basic checks during building. While
|
||||
listing every error out here is out-of-scope for this document, we
|
||||
can give some general tips for interpreting error messages.
|
||||
There are two types of errors: builder errors and validation errors.
|
||||
</p>
|
||||
|
||||
<h3>Builder errors</h3>
|
||||
|
||||
<blockquote>
|
||||
<p>
|
||||
<strong>Exception:</strong> Expected type string, got
|
||||
integer in DEFAULT in directive hash 'Ns.Dir'
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
You can identify a builder error by the keyword "directive hash."
|
||||
These are the easiest to deal with, because they directly correspond
|
||||
with your directive file. Find the offending directive file (which
|
||||
is the directive hash plus the .txt extension), find the
|
||||
offending index ("in DEFAULT" means the DEFAULT key) and fix the error.
|
||||
This particular error would occur if your default value is not the same
|
||||
type as TYPE.
|
||||
</p>
|
||||
|
||||
<h3>Validation errors</h3>
|
||||
|
||||
<blockquote>
|
||||
<p>
|
||||
<strong>Exception:</strong> Alias 3 in valueAliases in directive
|
||||
'Ns.Dir' must be a string
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
<p>
|
||||
These are a little trickier, because we're not actually validating
|
||||
your directive file, or even the direct string hash representation.
|
||||
We're validating an Interchange object, and the error messages do
|
||||
not mention any string hash keys.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Nevertheless, it's not difficult to figure out what went wrong.
|
||||
Read the "context" statements in reverse:
|
||||
</p>
|
||||
|
||||
<dl>
|
||||
<dt>in directive 'Ns.Dir'</dt>
|
||||
<dd>This means we need to look at the directive file <code>Ns.Dir.txt</code></dd>
|
||||
<dt>in valueAliases</dt>
|
||||
<dd>There's no key actually called this, but there's one that's close:
|
||||
VALUE-ALIASES. Indeed, that's where to look.</dd>
|
||||
<dt>Alias 3</dt>
|
||||
<dd>The value alias that is equal to 3 is the culprit.</dd>
|
||||
</dl>
|
||||
|
||||
<p>
|
||||
In this particular case, you're not allowed to alias integers values to
|
||||
strings values.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The most difficult part is translating the Interchange member variable (valueAliases)
|
||||
into a directive file key (VALUE-ALIASES), but there's a one-to-one
|
||||
correspondence currently. If the two formats diverge, any discrepancies
|
||||
will be described in <a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php">
|
||||
library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php</a>.
|
||||
</p>
|
||||
|
||||
<h2>Internals</h2>
|
||||
|
||||
<p>
|
||||
Much of the configuration schema framework's codebase deals with
|
||||
shuffling data from one format to another, and doing validation on this
|
||||
data.
|
||||
The keystone of all of this is the <code>HTMLPurifier_ConfigSchema_Interchange</code>
|
||||
class, which represents the purest, parsed representation of the schema.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Hand-writing this data is unwieldy, however, so we write directive files.
|
||||
These directive files are parsed by <code>HTMLPurifier_StringHashParser</code>
|
||||
into <code>HTMLPurifier_StringHash</code>es, which then
|
||||
are run through <code>HTMLPurifier_ConfigSchema_InterchangeBuilder</code>
|
||||
to construct the interchange object.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
From the interchange object, the data can be siphoned into other forms
|
||||
using <code>HTMLPurifier_ConfigSchema_Builder</code> subclasses.
|
||||
For example, <code>HTMLPurifier_ConfigSchema_Builder_ConfigSchema</code>
|
||||
generates a runtime <code>HTMLPurifier_ConfigSchema</code> object,
|
||||
which <code>HTMLPurifier_Config</code> uses to validate its incoming
|
||||
data. There is also a planned documentation builder.
|
||||
</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@@ -1,67 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="description" content="Discusses when to flush HTML Purifier's various caches." />
|
||||
<link rel="stylesheet" type="text/css" href="./style.css" />
|
||||
<title>Flushing the Purifier - HTML Purifier</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Flushing the Purifier</h1>
|
||||
|
||||
<div id="filing">Filed under Development</div>
|
||||
<div id="index">Return to the <a href="index.html">index</a>.</div>
|
||||
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div>
|
||||
|
||||
<p>
|
||||
If you've been poking around the various folders in HTML Purifier,
|
||||
you may have noticed the <code>maintenance</code> directory. Almost
|
||||
all of these scripts are devoted to flushing out the various caches
|
||||
HTML Purifier uses. Normal users don't have to worry about this:
|
||||
regular library usage is transparent. However, when doing development
|
||||
work on HTML Purifier, you may find you have to flush one of the
|
||||
caches.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As a general rule of thumb, run <code>flush.php</code> whenever you make
|
||||
any <em>major</em> changes, or when tests start mysteriously failing.
|
||||
In more detail, run this script if:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
You added new source files to HTML Purifier's main library.
|
||||
(see <code>generate-includes.php</code>)
|
||||
</li>
|
||||
<li>
|
||||
You modified the configuration schema (see
|
||||
<code>generate-schema-cache.php</code>). This usually means
|
||||
adding or modifying files in <code>HTMLPurifier/ConfigSchema/schema/</code>,
|
||||
although in rare cases modifying <code>HTMLPurifier/ConfigSchema.php</code>
|
||||
will also require this.
|
||||
</li>
|
||||
<li>
|
||||
You modified a Definition, or its subsystems. The most usual candidate
|
||||
is <code>HTMLPurifier/HTMLDefinition.php</code>, which also encompasses
|
||||
the files in <code>HTMLPurifier/HTMLModule/</code> as well as if you've
|
||||
<a href="enduser-customize.html">customizing definitions</a> without
|
||||
the cache disabled. (see <code>flush-generation-cache.php</code>)
|
||||
</li>
|
||||
<li>
|
||||
You modified source files, and have been using the standalone
|
||||
version from the full installation. (see <code>generate-standalone.php</code>)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
You can check out the corresponding scripts for more information on what they
|
||||
do.
|
||||
</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body></html>
|
@@ -1,279 +0,0 @@
|
||||
|
||||
INCLUDES, AUTOLOAD, BYTECODE CACHES and OPTIMIZATION
|
||||
|
||||
The Problem
|
||||
-----------
|
||||
|
||||
HTML Purifier contains a number of extra components that are not used all
|
||||
of the time, only if the user explicitly specifies that we should use
|
||||
them.
|
||||
|
||||
Some of these optional components are optionally included (Filter,
|
||||
Language, Lexer, Printer), while others are included all the time
|
||||
(Injector, URIFilter, HTMLModule, URIScheme). We will stipulate that these
|
||||
are all developer specified: it is conceivable that certain Tokens are not
|
||||
used, but this is user-dependent and should not be trusted.
|
||||
|
||||
We should come up with a consistent way to handle these things and ensure
|
||||
that we get the maximum performance when there is bytecode caches and
|
||||
when there are not. Unfortunately, these two goals seem contrary to each
|
||||
other.
|
||||
|
||||
A peripheral issue is the performance of ConfigSchema, which has been
|
||||
shown take a large, constant amount of initialization time, and is
|
||||
intricately linked to the issue of includes due to its pervasive use
|
||||
in our plugin architecture.
|
||||
|
||||
Pros and Cons
|
||||
-------------
|
||||
|
||||
We will assume that user-based extensions will be included by them.
|
||||
|
||||
Conditional includes:
|
||||
Pros:
|
||||
- User management is simplified; only a single directive needs to be set
|
||||
- Only necessary code is included
|
||||
Cons:
|
||||
- Doesn't play nicely with opcode caches
|
||||
- Adds complexity to standalone version
|
||||
- Optional configuration directives are not exposed without a little
|
||||
extra coaxing (not implemented yet)
|
||||
|
||||
Include it all:
|
||||
Pros:
|
||||
- User management is still simple
|
||||
- Plays nicely with opcode caches and standalone version
|
||||
- All configuration directives are present
|
||||
Cons:
|
||||
- Lots of (how much?) extra code is included
|
||||
- Classes that inherit from external libraries will cause compile
|
||||
errors
|
||||
|
||||
Build an include stub (Let's do this!):
|
||||
Pros:
|
||||
- Only necessary code is included
|
||||
- Plays nicely with opcode caches and standalone version
|
||||
- require (without once) can be used, see above
|
||||
- Could further extend as a compilation to one file
|
||||
Cons:
|
||||
- Not implemented yet
|
||||
- Requires user intervention and use of a command line script
|
||||
- Standalone script must be chained to this
|
||||
- More complex and compiled-language-like
|
||||
- Requires a whole new class of system-wide configuration directives,
|
||||
as configuration objects can be reused
|
||||
- Determining what needs to be included can be complex (see above)
|
||||
- No way of autodetecting dynamically instantiated classes
|
||||
- Might be slow
|
||||
|
||||
Include stubs
|
||||
-------------
|
||||
|
||||
This solution may be "just right" for users who are heavily oriented
|
||||
towards performance. However, there are a number of picky implementation
|
||||
details to work out beforehand.
|
||||
|
||||
The number one concern is how to make the HTML Purifier files "work
|
||||
out of the box", while still being able to easily get them into a form
|
||||
that works with this setup. As the codebase stands right now, it would
|
||||
be necessary to strip out all of the require_once calls. The only way
|
||||
we could get rid of the require_once calls is to use __autoload or
|
||||
use the stub for all cases (which might not be a bad idea).
|
||||
|
||||
Aside
|
||||
-----
|
||||
An important thing to remember, however, is that these require_once's
|
||||
are valuable data about what classes a file needs. Unfortunately, there's
|
||||
no distinction between whether or not the file is needed all the time,
|
||||
or whether or not it is one of our "optional" files. Thus, it is
|
||||
effectively useless.
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
One of the things I'd like to do is have the code search for any classes
|
||||
that are explicitly mentioned in the code. If a class isn't mentioned, I
|
||||
get to assume that it is "optional," i.e. included via introspection.
|
||||
The choice is either to use PHP's tokenizer or use regexps; regexps would
|
||||
be faster but a tokenizer would be more correct. If this ends up being
|
||||
unfeasible, adding dependency comments isn't a bad idea. (This could
|
||||
even be done automatically by search/replacing require_once, although
|
||||
we'd have to manually inspect the results for the optional requires.)
|
||||
|
||||
NOTE: This ends up not being necessary, as we're going to make the user
|
||||
figure out all the extra classes they need, and only include the core
|
||||
which is predetermined.
|
||||
|
||||
Using the autoload framework with include stubs works nicely with
|
||||
introspective classes: instead of having to have require_once inside
|
||||
the function, we can let autoload do the work; we simply need to
|
||||
new $class or accept the object straight from the caller. Handling filters
|
||||
becomes a simple matter of ticking off configuration directives, and
|
||||
if ConfigSchema spits out errors, adding the necessary includes. We could
|
||||
also use the autoload framework as a fallback, in case the user forgets
|
||||
to make the include, but doesn't really care about performance.
|
||||
|
||||
Insight
|
||||
-------
|
||||
All of this talk is merely a natural extension of what our current
|
||||
standalone functionality does. However, instead of having our code
|
||||
perform the includes, or attempting to inline everything that possibly
|
||||
could be used, we boot the issue to the user, making them include
|
||||
everything or setup the fallback autoload handler.
|
||||
|
||||
Configuration Schema
|
||||
--------------------
|
||||
|
||||
A common deficiency for all of the conditional include setups (including
|
||||
the dynamically built include PHP stub) is that if one of this
|
||||
conditionally included files includes a configuration directive, it
|
||||
is not accessible to configdoc. A stopgap solution for this problem is
|
||||
to have it piggy-back off of the data in the merge-library.php script
|
||||
to figure out what extra files it needs to include, but if the file also
|
||||
inherits classes that don't exist, we're in big trouble.
|
||||
|
||||
I think it's high time we centralized the configuration documentation.
|
||||
However, the type checking has been a great boon for the library, and
|
||||
I'd like to keep that. The compromise is to use some other source, and
|
||||
then parse it into the ConfigSchema internal format (sans all of those
|
||||
nasty documentation strings which we really don't need at runtime) and
|
||||
serialize that for future use.
|
||||
|
||||
The next question is that of format. XML is very verbose, and the prospect
|
||||
of setting defaults in it gives me willies. However, this may be necessary.
|
||||
Splitting up the file into manageable chunks may alleviate this trouble,
|
||||
and we may be even want to create our own format optimized for specifying
|
||||
configuration. It might look like (based off the PHPT format, which is
|
||||
nicely compact yet unambiguous and human-readable):
|
||||
|
||||
Core.HiddenElements
|
||||
TYPE: lookup
|
||||
DEFAULT: array('script', 'style') // auto-converted during processing
|
||||
--ALIASES--
|
||||
Core.InvisibleElements, Core.StupidElements
|
||||
--DESCRIPTION--
|
||||
<p>
|
||||
Blah blah
|
||||
</p>
|
||||
|
||||
The first line is the directive name, the lines after that prior to the
|
||||
first --HEADER-- block are single-line values, and then after that
|
||||
the multiline values are there. No value is restricted to a particular
|
||||
format: DEFAULT could very well be multiline if that would be easier.
|
||||
This would make it insanely easy, also, to add arbitrary extra parameters,
|
||||
like:
|
||||
|
||||
VERSION: 3.0.0
|
||||
ALLOWED: 'none', 'light', 'medium', 'heavy' // this is wrapped in array()
|
||||
EXTERNAL: CSSTidy // this would be documented somewhere else with a URL
|
||||
|
||||
The final loss would be that you wouldn't know what file the directive
|
||||
was used in; with some clever regexps it should be possible to
|
||||
figure out where $config->get($ns, $d); occurs. Reflective calls to
|
||||
the configuration object is mitigated by the fact that getBatch is
|
||||
used, so we can simply talk about that in the namespace definition page.
|
||||
This might be slow, but it would only happen when we are creating
|
||||
the documentation for consumption, and is sugar.
|
||||
|
||||
We can put this in a schema/ directory, outside of HTML Purifier. The serialized
|
||||
data gets treated like entities.ser.
|
||||
|
||||
The final thing that needs to be handled is user defined configurations.
|
||||
They can be added at runtime using ConfigSchema::registerDirectory()
|
||||
which globs the directory and grabs all of the directives to be incorporated
|
||||
in. Then, the result is saved. We may want to take advantage of the
|
||||
DefinitionCache framework, although it is not altogether certain what
|
||||
configuration directives would be used to generate our key (meta-directives!)
|
||||
|
||||
Further thoughts
|
||||
----------------
|
||||
Our master configuration schema will only need to be updated once
|
||||
every new version, so it's easily versionable. User specified
|
||||
schema files are far more volatile, but it's far too expensive
|
||||
to check the filemtimes of all the files, so a DefinitionRev style
|
||||
mechanism works better. However, we can uniquely identify the
|
||||
schema based on the directories they loaded, so there's no need
|
||||
for a DefinitionId until we give them full programmatic control.
|
||||
|
||||
These variables should be directly incorporated into ConfigSchema,
|
||||
and ConfigSchema should handle serialization. Some refactoring will be
|
||||
necessary for the DefinitionCache classes, as they are built with
|
||||
Config in mind. If the user changes something, the cache file gets
|
||||
rebuilt. If the version changes, the cache file gets rebuilt. Since
|
||||
our unit tests flush the caches before we start, and the operation is
|
||||
pretty fast, this will not negatively impact unit testing.
|
||||
|
||||
One last thing: certain configuration directives require that files
|
||||
get added. They may even be specified dynamically. It is not a good idea
|
||||
for the HTMLPurifier_Config object to be used directly for such matters.
|
||||
Instead, the userland code should explicitly perform the includes. We may
|
||||
put in something like:
|
||||
|
||||
REQUIRES: HTMLPurifier_Filter_ExtractStyleBlocks
|
||||
|
||||
To indicate that if that class doesn't exist, and the user is attempting
|
||||
to use the directive, we should fatally error out. The stub includes the core files,
|
||||
and the user includes everything else. Any reflective things like new
|
||||
$class would be required to tie in with the configuration.
|
||||
|
||||
It would work very well with rarely used configuration options, but it
|
||||
wouldn't be so good for "core" parts that can be disabled. In such cases
|
||||
the core include file would need to be modified, and the only way
|
||||
to properly do this is use the configuration object. Once again, our
|
||||
ability to create cache keys saves the day again: we can create arbitrary
|
||||
stub files for arbitrary configurations and include those. They could
|
||||
even be the single file affairs. The only thing we'd need to include,
|
||||
then, would be HTMLPurifier_Config! Then, the configuration object would
|
||||
load the library.
|
||||
|
||||
An aside...
|
||||
-----------
|
||||
One questions, however, the wisdom of letting PHP files write other PHP
|
||||
files. It seems like a recipe for disaster, or at least lots of headaches
|
||||
in highly secured setups, where PHP does not have the ability to write
|
||||
to its root. In such cases, we could use sticky bits or tell the user
|
||||
to manually generate the file.
|
||||
|
||||
The other troublesome bit is actually doing the calculations necessary.
|
||||
For certain cases, it's simple (such as URIScheme), but for AttrDef
|
||||
and HTMLModule the dependency trees are very complex in relation to
|
||||
%HTML.Allowed and friends. I think that this idea should be shelved
|
||||
and looked at a later, less insane date.
|
||||
|
||||
An interesting dilemma presents itself when a configuration form is offered
|
||||
to the user. Normally, the configuration object is not accessible without
|
||||
editing PHP code; this facility changes thing. The sensible thing to do
|
||||
is stipulate that all classes required by the directives you allow must
|
||||
be included.
|
||||
|
||||
Unit testing
|
||||
------------
|
||||
|
||||
Setting up the parsing and translation into our existing format would not
|
||||
be difficult to do. It might represent a good time for us to rethink our
|
||||
tests for these facilities; as creative as they are, they are often hacky
|
||||
and require public visibility for things that ought to be protected.
|
||||
This is especially applicable for our DefinitionCache tests.
|
||||
|
||||
Migration
|
||||
---------
|
||||
|
||||
Because we are not *adding* anything essentially new, it should be trivial
|
||||
to write a script to take our existing data and dump it into the new format.
|
||||
Well, not trivial, but fairly easy to accomplish. Primary implementation
|
||||
difficulties would probably involve formatting the file nicely.
|
||||
|
||||
Backwards-compatibility
|
||||
-----------------------
|
||||
|
||||
I expect that the ConfigSchema methods should stick around for a little bit,
|
||||
but display E_USER_NOTICE warnings that they are deprecated. This will
|
||||
require documentation!
|
||||
|
||||
New stuff
|
||||
---------
|
||||
|
||||
VERSION: Version number directive was introduced
|
||||
DEPRECATED-VERSION: If the directive was deprecated, when was it deprecated?
|
||||
DEPRECATED-USE: If the directive was deprecated, what should the user use now?
|
||||
REQUIRES: What classes does this configuration directive require, but are
|
||||
not part of the HTML Purifier core?
|
@@ -79,4 +79,4 @@ help you find the correct functionality more quickly. Here they are:</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body></html>
|
||||
</body></html>
|
@@ -23,10 +23,11 @@ that itch, put it here!</p>
|
||||
<ul>
|
||||
<li>Make Tokens Flyweights (may prove problematic, probably not worth it)</li>
|
||||
<li>Rewrite regexps into PHP code</li>
|
||||
<li>Serialize the Definition object</li>
|
||||
<li>Batch regexp validation (do as many per function call as possible)</li>
|
||||
<li>Parallelize strategies</li>
|
||||
</ul>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body></html>
|
||||
</body></html>
|
@@ -34,17 +34,12 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
|
||||
<div id="index">Return to the <a href="index.html">index</a>.</div>
|
||||
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div>
|
||||
|
||||
<p>
|
||||
<strong>Warning:</strong> This table is kept for historical purposes and
|
||||
is not being actively updated.
|
||||
</p>
|
||||
|
||||
<h2>Key</h2>
|
||||
|
||||
<table cellspacing="0"><tbody>
|
||||
<tr><td class="impl-yes">Implemented</td></tr>
|
||||
<tr><td class="impl-partial">Partially implemented</td></tr>
|
||||
<tr><td class="impl-no">Not priority to implement</td></tr>
|
||||
<tr><td class="impl-no">Will not implement</td></tr>
|
||||
<tr><td class="danger">Dangerous attribute/property</td></tr>
|
||||
<tr><td class="css1">Present in CSS1</td></tr>
|
||||
<tr><td class="feature">Feature, requires extra work</td></tr>
|
||||
@@ -123,7 +118,6 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
|
||||
<tbody>
|
||||
<tr><th colspan="2">Table</th></tr>
|
||||
<tr class="impl-yes"><td>border-collapse</td><td>ENUM(collapse, seperate)</td></tr>
|
||||
<tr class="impl-yes"><td>border-space</td><td>MULTIPLE</td></tr>
|
||||
<tr class="impl-yes"><td>caption-side</td><td>ENUM(top, bottom)</td></tr>
|
||||
<tr class="feature"><td>empty-cells</td><td>ENUM(show, hide), No IE support makes this useless,
|
||||
possible fix with &nbsp;? Unknown release milestone.</td></tr>
|
||||
@@ -153,7 +147,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
|
||||
Depends on background-image</td></tr>
|
||||
<tr class="css1 impl-yes"><td>background-position</td><td>Depends on background-image</td></tr>
|
||||
<tr class="danger impl-no"><td>cursor</td><td>Dangerous but fluffy</td></tr>
|
||||
<tr class="danger impl-yes"><td>display</td><td>ENUM(...), Dangerous but interesting;
|
||||
<tr class="danger css1"><td>display</td><td>ENUM(...), Dangerous but interesting;
|
||||
will not implement list-item, run-in (Opera only) or table (no IE);
|
||||
inline-block has incomplete IE6 support and requires -moz-inline-box
|
||||
for Mozilla. Unknown target milestone.</td></tr>
|
||||
@@ -172,7 +166,7 @@ thead th {text-align:left;padding:0.1em;background-color:#EEE;}
|
||||
Mostly supported. Unknown target milestone.</td></tr>
|
||||
<tr><td>page-break-inside</td><td>ENUM(avoid, auto), Opera only. Unknown target milestone.</td></tr>
|
||||
<tr class="impl-no"><td>quotes</td><td>May be dropped from CSS2, fairly useless for inline context</td></tr>
|
||||
<tr class="danger impl-yes"><td>visibility</td><td>ENUM(visible, hidden, collapse),
|
||||
<tr class="impl-no"><td>visibility</td><td>ENUM(visible, hidden, collapse),
|
||||
Dangerous</td></tr>
|
||||
<tr class="css1 feature impl-partial"><td>white-space</td><td>ENUM(normal, pre, nowrap, pre-wrap,
|
||||
pre-line), Spotty implementation:
|
||||
@@ -305,4 +299,4 @@ Mozilla on inside and needs -moz-outline, no IE support.</td></tr>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body></html>
|
||||
</body></html>
|
@@ -17,6 +17,11 @@
|
||||
<div id="index">Return to the <a href="index.html">index</a>.</div>
|
||||
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div>
|
||||
|
||||
<div id="applicability">
|
||||
This document covers currently unreleased functionality and
|
||||
only applies to recent SVN checkouts.
|
||||
</div>
|
||||
|
||||
<p>
|
||||
You may have heard of the <a href="dev-advanced-api.html">Advanced API</a>.
|
||||
If you're interested in reading dry prose and boring functional
|
||||
@@ -32,7 +37,7 @@
|
||||
Before we even write any code, it is paramount to consider whether or
|
||||
not the code we're writing is necessary or not. HTML Purifier, by default,
|
||||
contains a large set of elements and attributes: large enough so that
|
||||
<em>any</em> element or attribute in XHTML 1.0 or 1.1 (and its HTML variants)
|
||||
<em>any</em> element or attribute in XHTML 1.0 (and its HTML variant)
|
||||
that can be safely used by the general public is implemented.
|
||||
</p>
|
||||
|
||||
@@ -76,12 +81,11 @@
|
||||
<h3>XHTML 1.1</h3>
|
||||
|
||||
<p>
|
||||
As of HTMLPurifier 2.1.0, we have implemented the
|
||||
We have not implemented the
|
||||
<a href="http://www.w3.org/TR/2001/REC-ruby-20010531/">Ruby module</a>,
|
||||
which defines a set of tags
|
||||
for publishing short annotations for text, used mostly in Japanese
|
||||
and Chinese school texts, but applicable for positioning any text (not
|
||||
limited to translations) above or below other corresponding text.
|
||||
and Chinese school texts.
|
||||
</p>
|
||||
|
||||
<h3>XHTML 2.0</h3>
|
||||
@@ -493,11 +497,10 @@ $def =& $config->getHTMLDefinition(true);
|
||||
<p>
|
||||
The <code>(%flow;)*</code> indicates the allowed children of the
|
||||
<code>li</code> tag: <code>li</code> allows any number of flow
|
||||
elements as its children. (The <code>- O</code> allows the closing tag to be
|
||||
omitted, though in XML this is not allowed.) In HTML Purifier,
|
||||
we'd write it like <code>Flow</code> (here's where the content sets
|
||||
we were discussing earlier come into play). There are three shorthand
|
||||
content models you can specify:
|
||||
elements as its children. In HTML Purifier, we'd write it like
|
||||
<code>Flow</code> (here's where the content sets we were
|
||||
discussing earlier come into play). There are three shorthand content models you
|
||||
can specify:
|
||||
</p>
|
||||
|
||||
<table class="table">
|
||||
@@ -670,22 +673,12 @@ $def =& $config->getHTMLDefinition(true);
|
||||
Common is a combination of the above-mentioned collections.
|
||||
</p>
|
||||
|
||||
<p class="aside">
|
||||
Readers familiar with the modularization may have noticed that the Core
|
||||
attribute collection differs from that specified by the <a
|
||||
href="http://www.w3.org/TR/xhtml-modularization/abstract_modules.html#s_commonatts">abstract
|
||||
modules of the XHTML Modularization 1.1</a>. We believe this section
|
||||
to be in error, as <code>br</code> permits the use of the <code>style</code>
|
||||
attribute even though it uses the <code>Core</code> collection, and
|
||||
the DTD and XML Schemas supplied by W3C support our interpretation.
|
||||
</p>
|
||||
|
||||
<h3>Attributes</h3>
|
||||
|
||||
<p>
|
||||
If you didn't read the <a href="#addAttribute">earlier section on
|
||||
If you didn't read the <a href="#addAttribute">previous section on
|
||||
adding attributes</a>, read it now. The last parameter is simply
|
||||
an array of attribute names to attribute implementations, in the exact
|
||||
array of attribute names to attribute implementations, in the exact
|
||||
same format as <code>addAttribute()</code>.
|
||||
</p>
|
||||
|
||||
@@ -795,4 +788,4 @@ $form->excludes = array('form' => true);</strong></pre>
|
||||
|
||||
<div id="version">$Id: enduser-tidy.html 1158 2007-06-18 19:26:29Z Edward $</div>
|
||||
|
||||
</body></html>
|
||||
</body></html>
|
@@ -58,7 +58,7 @@ appear elsewhere on the document. The method is simple:</p>
|
||||
|
||||
<pre>$config->set('HTML', 'EnableAttrID', true);
|
||||
$config->set('Attr', 'IDBlacklist' array(
|
||||
'list', 'of', 'attribute', 'values', 'that', 'are', 'forbidden'
|
||||
'list', 'of', 'attributes', 'that', 'are', 'forbidden'
|
||||
));</pre>
|
||||
|
||||
<p>That being said, there are some notable drawbacks. First of all, you have to
|
||||
@@ -71,9 +71,9 @@ to possible standards-compliance issues.</p>
|
||||
<p>Furthermore, this position becomes untenable when a single web page must hold
|
||||
multiple portions of user-submitted content. Since there's obviously no way
|
||||
to find out before-hand what IDs users will use, the blacklist is helpless.
|
||||
And since HTML Purifier validates each segment separately, perhaps doing
|
||||
And even since HTML Purifier validates each segment seperately, perhaps doing
|
||||
so at different times, it would be extremely difficult to dynamically update
|
||||
the blacklist in between runs.</p>
|
||||
the blacklist inbetween runs.</p>
|
||||
|
||||
<p>Finally, simply destroying the ID is extremely un-userfriendly behavior: after
|
||||
all, they might have simply specified a duplicate ID by accident.</p>
|
||||
@@ -144,4 +144,4 @@ anchors is beyond me.</p>
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@@ -10,7 +10,9 @@ to be effective. Things to remember:
|
||||
|
||||
2. IDs: see enduser-id.html for more info
|
||||
|
||||
3. URIs: see enduser-uri-filter.html
|
||||
3. Links: document pending feature completion
|
||||
Rudimentary blacklisting, we should also allow only relative URIs. We
|
||||
need a doc to explain the stuff.
|
||||
|
||||
4. CSS: document pending
|
||||
Explain which CSS styles we blocked and why.
|
||||
|
@@ -114,4 +114,4 @@ if you decide to do that! Especially if you port HTML Purifier to C++.
|
||||
<tt>;-)</tt></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@@ -16,13 +16,18 @@
|
||||
<div id="index">Return to the <a href="index.html">index</a>.</div>
|
||||
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div>
|
||||
|
||||
<div id="applicability">
|
||||
This document covers currently unreleased functionality and
|
||||
only applies to recent SVN checkouts.
|
||||
</div>
|
||||
|
||||
<p>You've probably heard of HTML Tidy, Dave Raggett's little piece
|
||||
of software that cleans up poorly written HTML. Let me say it straight
|
||||
out:</p>
|
||||
|
||||
<p class="emphasis">This ain't HTML Tidy!</p>
|
||||
|
||||
<p>Rather, Tidy stands for a cool set of Tidy-inspired features in HTML Purifier
|
||||
<p>Rather, Tidy stands for a cool set of Tidy-inspired in HTML Purifier
|
||||
that allows users to submit deprecated elements and attributes and get
|
||||
valid strict markup back. For example:</p>
|
||||
|
||||
@@ -33,8 +38,8 @@ valid strict markup back. For example:</p>
|
||||
<pre><div style="text-align:center;">Centered</div></pre>
|
||||
|
||||
<p>...when this particular fix is run on the HTML. This tutorial will give
|
||||
you the lowdown of what exactly HTML Purifier will do when Tidy
|
||||
is on, and how to fine-tune this behavior. Once again, <strong>you do
|
||||
you down the lowdown of what exactly HTML Purifier will do when Tidy
|
||||
is on, and how to fine tune this behavior. Once again, <strong>you do
|
||||
not need Tidy installed on your PHP to use these features!</strong></p>
|
||||
|
||||
<h2>What does it do?</h2>
|
||||
@@ -221,10 +226,10 @@ general syntax:</p>
|
||||
|
||||
<p>The lowdown is, quite frankly, HTML Purifier's default settings are
|
||||
probably good enough. The next step is to bump the level up to heavy,
|
||||
and if that still doesn't satisfy your appetite, do some fine-tuning.
|
||||
and if that still doesn't satisfy your appetite, do some fine tuning.
|
||||
Other than that, don't worry about it: this all works silently and
|
||||
effectively in the background.</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body></html>
|
||||
</body></html>
|
@@ -1,201 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="description" content="Tutorial for creating custom URI filters." />
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
|
||||
<title>URI Filters - HTML Purifier</title>
|
||||
|
||||
</head><body>
|
||||
|
||||
<h1>URI Filters</h1>
|
||||
|
||||
<div id="filing">Filed under End-User</div>
|
||||
<div id="index">Return to the <a href="index.html">index</a>.</div>
|
||||
<div id="home"><a href="http://htmlpurifier.org/">HTML Purifier</a> End-User Documentation</div>
|
||||
|
||||
<p>
|
||||
This is a quick and dirty document to get you on your way to writing
|
||||
custom URI filters for your own URL filtering needs. Why would you
|
||||
want to write a URI filter? If you need URIs your users put into
|
||||
HTML to magically change into a different URI, this is
|
||||
exactly what you need!
|
||||
</p>
|
||||
|
||||
<h2>Creating the class</h2>
|
||||
|
||||
<p>
|
||||
Any URI filter you make will be a subclass of <code>HTMLPurifier_URIFilter</code>.
|
||||
The scaffolding is thus:
|
||||
</p>
|
||||
|
||||
<pre>class HTMLPurifier_URIFilter_<strong>NameOfFilter</strong> extends HTMLPurifier_URIFilter
|
||||
{
|
||||
public $name = '<strong>NameOfFilter</strong>';
|
||||
public function prepare($config) {}
|
||||
public function filter(&$uri, $config, &$context) {}
|
||||
}</pre>
|
||||
|
||||
<p>
|
||||
Fill in the variable <code>$name</code> with the name of your filter, and
|
||||
take a look at the two methods. <code>prepare()</code> is an initialization
|
||||
method that is called only once, before any filtering has been done of the
|
||||
HTML. Use it to perform any costly setup work that only needs to be done
|
||||
once. <code>filter()</code> is the guts and innards of our filter:
|
||||
it takes the URI and does whatever needs to be done to it.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If you've worked with HTML Purifier, you'll recognize the <code>$config</code>
|
||||
and <code>$context</code> parameters. On the other hand, <code>$uri</code>
|
||||
is something unique to this section of the application: it's a
|
||||
<code>HTMLPurifier_URI</code> object. The interface is thus:
|
||||
</p>
|
||||
|
||||
<pre>class HTMLPurifier_URI
|
||||
{
|
||||
public $scheme, $userinfo, $host, $port, $path, $query, $fragment;
|
||||
public function HTMLPurifier_URI($scheme, $userinfo, $host, $port, $path, $query, $fragment);
|
||||
public function toString();
|
||||
public function copy();
|
||||
public function getSchemeObj($config, &$context);
|
||||
public function validate($config, &$context);
|
||||
}</pre>
|
||||
|
||||
<p>
|
||||
The first three methods are fairly self-explanatory: you have a constructor,
|
||||
a serializer, and a cloner. Generally, you won't be using them when
|
||||
you are manipulating the URI objects themselves.
|
||||
<code>getSchemeObj()</code> is a special purpose method that returns
|
||||
a <code>HTMLPurifier_URIScheme</code> object corresponding to the specific
|
||||
URI at hand. <code>validate()</code> performs general-purpose validation
|
||||
on the internal components of a URI. Once again, you don't need to
|
||||
worry about these: they've already been handled for you.
|
||||
</p>
|
||||
|
||||
<h2>URI format</h2>
|
||||
|
||||
<p>
|
||||
As a URIFilter, we're interested in the member variables of the URI object.
|
||||
</p>
|
||||
|
||||
<table class="quick"><tbody>
|
||||
<tr><th>Scheme</th> <td>The protocol for identifying (and possibly locating) a resource (http, ftp, https)</td></tr>
|
||||
<tr><th>Userinfo</th> <td>User information such as a username (bob)</td></tr>
|
||||
<tr><th>Host</th> <td>Domain name or IP address of the server (example.com, 127.0.0.1)</td></tr>
|
||||
<tr><th>Port</th> <td>Network port number for the server (80, 12345)</td></tr>
|
||||
<tr><th>Path</th> <td>Data that identifies the resource, possibly hierarchical (/path/to, ed@example.com)</td></tr>
|
||||
<tr><th>Query</th> <td>String of information to be interpreted by the resource (?q=search-term)</td></tr>
|
||||
<tr><th>Fragment</th> <td>Additional information for the resource after retrieval (#bookmark)</td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<p>
|
||||
Because the URI is presented to us in this form, and not
|
||||
<code>http://bob@example.com:8080/foo.php?q=string#hash</code>, it saves us
|
||||
a lot of trouble in having to parse the URI every time we want to filter
|
||||
it. For the record, the above URI has the following components:
|
||||
</p>
|
||||
|
||||
<table class="quick"><tbody>
|
||||
<tr><th>Scheme</th> <td>http</td></tr>
|
||||
<tr><th>Userinfo</th> <td>bob</td></tr>
|
||||
<tr><th>Host</th> <td>example.com</td></tr>
|
||||
<tr><th>Port</th> <td>8080</td></tr>
|
||||
<tr><th>Path</th> <td>/foo.php</td></tr>
|
||||
<tr><th>Query</th> <td>q=string</td></tr>
|
||||
<tr><th>Fragment</th> <td>hash</td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<p>
|
||||
Note that there is no question mark or octothorpe in the query or
|
||||
fragment: these get removed during parsing.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
With this information, you can get straight to implementing your
|
||||
<code>filter()</code> method. But one more thing...
|
||||
</p>
|
||||
|
||||
<h2>Return value: Boolean, not URI</h2>
|
||||
|
||||
<p>
|
||||
You may have noticed that the URI is being passed in by reference.
|
||||
This means that whatever changes you make to it, those changes will
|
||||
be reflected in the URI object the callee had. <strong>Do not
|
||||
return the URI object: it is unnecessary and will cause bugs.</strong>
|
||||
Instead, return a boolean value, true if the filtering was successful,
|
||||
or false if the URI is beyond repair and needs to be axed.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Let's suppose I wanted to write a filter that de-internationalized domain
|
||||
names by converting them to <a href="http://en.wikipedia.org/wiki/Punycode">Punycode</a>.
|
||||
Assuming that <code>punycode_encode($input)</code> converts <code>$input</code> to
|
||||
Punycode and returns <code>false</code> on failure:
|
||||
</p>
|
||||
|
||||
<pre>class HTMLPurifier_URIFilter_ConvertIDNToPunycode extends HTMLPurifier_URIFilter
|
||||
{
|
||||
public $name = 'ConvertIDNToPunycode';
|
||||
public function filter(&$uri, $config, &$context) {
|
||||
if (is_null($uri->host)) return true;
|
||||
if ($uri->host == utf8_decode($uri->host)) {
|
||||
// is ASCII, abort
|
||||
return true;
|
||||
}
|
||||
$host = punycode_encode($uri->host);
|
||||
if ($host === false) return false;
|
||||
$uri->host = $host;
|
||||
return true;
|
||||
}
|
||||
}</pre>
|
||||
|
||||
<p>
|
||||
Notice I did not <code>return $uri;</code>.
|
||||
</p>
|
||||
|
||||
<h2>Activating your filter</h2>
|
||||
|
||||
<p>
|
||||
Having a filter is all well and good, but you need to tell HTML Purifier
|
||||
to use it. Fortunately, this part's simple:
|
||||
</p>
|
||||
|
||||
<pre>$uri =& $config->getDefinition('URI');
|
||||
$uri->addFilter(new HTMLPurifier_URIFilter_<strong>NameOfFilter</strong>());</pre>
|
||||
|
||||
<p>
|
||||
If you want to be really fancy, you can define a configuration directive
|
||||
for your filter and have HTML Purifier automatically manage whether or
|
||||
not your filter gets loaded or not (this is how internal filters manage
|
||||
things):
|
||||
</p>
|
||||
|
||||
<pre>HTMLPurifier_ConfigSchema::define(
|
||||
'URI', '<strong>NameOfFilter</strong>', false, 'bool',
|
||||
'<strong>What your filter does.</strong>'
|
||||
);
|
||||
$uri =& $config->getDefinition('URI', true);
|
||||
$uri->registerFilter(new HTMLPurifier_URIFilter_<strong>NameOfFilter</strong>());
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Now, your filter will only be called when %URI.<strong>NameOfFilter</strong>
|
||||
is set to true.
|
||||
</p>
|
||||
|
||||
<h2>Examples</h2>
|
||||
|
||||
<p>
|
||||
Check the
|
||||
<a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/library/HTMLPurifier/URIFilter/">URIFilter</a>
|
||||
directory for more implementation examples, and see <a href="http://htmlpurifier.org/svnroot/htmlpurifier/trunk/docs/proposal-new-directives.txt">the
|
||||
new directives proposal document</a> for ideas on what could be implemented
|
||||
as a filter.
|
||||
</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
|
||||
</body></html>
|
@@ -5,6 +5,7 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="description" content="Describes the rationale for using UTF-8, the ramifications otherwise, and how to make the switch." />
|
||||
<link rel="stylesheet" type="text/css" href="./style.css" />
|
||||
<script defer="defer" type="text/javascript" src="./toc-gen.js"></script>
|
||||
<style type="text/css">
|
||||
.minor td {font-style:italic;}
|
||||
</style>
|
||||
@@ -95,7 +96,7 @@ which can be a rewarding (but difficult) task.</p>
|
||||
<h2 id="findcharset">Finding the real encoding</h2>
|
||||
|
||||
<p>In the beginning, there was ASCII, and things were simple. But they
|
||||
weren't good, for no one could write in Cyrillic or Thai. So there
|
||||
weren't good, for no one could write in Cryllic or Thai. So there
|
||||
exploded a proliferation of character encodings to remedy the problem
|
||||
by extending the characters ASCII could express. This ridiculously
|
||||
simplified version of the history of character encodings shows us that
|
||||
@@ -137,7 +138,7 @@ browser:</p>
|
||||
<dd>View > Encoding: bulleted item is unofficial name</dd>
|
||||
</dl>
|
||||
|
||||
<p>Internet Explorer won't give you the MIME (i.e. useful/real) name of the
|
||||
<p>Internet Explorer won't give you the mime (i.e. useful/real) name of the
|
||||
character encoding, so you'll have to look it up using their description.
|
||||
Some common ones:</p>
|
||||
|
||||
@@ -215,12 +216,6 @@ if your <code>META</code> tag claims that either:</p>
|
||||
|
||||
<h2 id="fixcharset">Fixing the encoding</h2>
|
||||
|
||||
<p class="aside">The advice given here is for pages being served as
|
||||
vanilla <code>text/html</code>. Different practices must be used
|
||||
for <code>application/xml</code> or <code>application/xml+xhtml</code>, see
|
||||
<a href="http://www.w3.org/TR/2002/NOTE-xhtml-media-types-20020430/">W3C's
|
||||
document on XHTML media types</a> for more information.</p>
|
||||
|
||||
<p>If your <code>META</code> encoding and your real encoding match,
|
||||
savvy! You can skip this section. If they don't...</p>
|
||||
|
||||
@@ -236,7 +231,7 @@ of your real encoding.</p>
|
||||
why the character encoding should be explicitly stated. When the
|
||||
browser isn't told what the character encoding of a text is, it
|
||||
has to guess: and sometimes the guess is wrong. Hackers can manipulate
|
||||
this guess in order to slip XSS past filters and then fool the
|
||||
this guess in order to slip XSS pass filters and then fool the
|
||||
browser into executing it as active code. A great example of this
|
||||
is the <a href="http://shiflett.org/archive/177">Google UTF-7
|
||||
exploit</a>.</p>
|
||||
@@ -307,8 +302,7 @@ languages</a>. The appropriate code is:</p>
|
||||
|
||||
<p>...replacing UTF-8 with whatever your embedded encoding is.
|
||||
This code must come before any output, so be careful about
|
||||
stray whitespace in your application (i.e., any whitespace before
|
||||
output excluding whitespace within <?php ?> tags).</p>
|
||||
stray whitespace in your application.</p>
|
||||
|
||||
<h4 id="fixcharset-server-phpini">PHP ini directive</h4>
|
||||
|
||||
@@ -319,8 +313,8 @@ header call: <code><a href="http://php.net/ini.core#ini.default-charset">default
|
||||
|
||||
<p>...will also do the trick. If PHP is running as an Apache module (and
|
||||
not as FastCGI, consult
|
||||
<a href="http://php.net/phpinfo">phpinfo</a>() for details), you can even use htaccess to apply this property
|
||||
across many PHP files:</p>
|
||||
<a href="http://php.net/phpinfo">phpinfo</a>() for details), you can even use htaccess do apply this property
|
||||
globally:</p>
|
||||
|
||||
<pre><a href="http://php.net/configuration.changes#configuration.changes.apache">php_value</a> default_charset "UTF-8"</pre>
|
||||
|
||||
@@ -366,11 +360,10 @@ to send anything at all:</p>
|
||||
|
||||
<pre><a href="http://httpd.apache.org/docs/1.3/mod/core.html#adddefaultcharset">AddDefaultCharset</a> Off</pre>
|
||||
|
||||
<p>...making your internal charset declaration (usually the <code>META</code> tags)
|
||||
the sole source of character encoding
|
||||
information. In these cases, it is <em>especially</em> important to make
|
||||
sure you have valid <code>META</code> tags on your pages and all the
|
||||
text before them is ASCII.</p>
|
||||
<p>...making your <code>META</code> tags the sole source of
|
||||
character encoding information. In these cases, it is
|
||||
<em>especially</em> important to make sure you have valid <code>META</code>
|
||||
tags on your pages and all the text before them is ASCII.</p>
|
||||
|
||||
<blockquote class="aside"><p>These directives can also be
|
||||
placed in httpd.conf file for Apache, but
|
||||
@@ -435,30 +428,28 @@ IIS to change character encodings, I'd be grateful.</p>
|
||||
|
||||
<p><code>META</code> tags are the most common source of embedded
|
||||
encodings, but they can also come from somewhere else: XML
|
||||
Declarations. They look like:</p>
|
||||
processing instructions. They look like:</p>
|
||||
|
||||
<pre><?xml version="1.0" encoding="UTF-8"?></pre>
|
||||
|
||||
<p>...and are most often found in XML documents (including XHTML).</p>
|
||||
|
||||
<p>For XHTML, this XML Declaration theoretically
|
||||
<p>For XHTML, this processing instruction theoretically
|
||||
overrides the <code>META</code> tag. In reality, this happens only when the
|
||||
XHTML is actually served as legit XML and not HTML, which is almost always
|
||||
never due to Internet Explorer's lack of support for
|
||||
<code>application/xhtml+xml</code> (even though doing so is often
|
||||
argued to be <a href="http://www.hixie.ch/advocacy/xhtml">good
|
||||
practice</a> and is required by the XHTML 1.1 specification).</p>
|
||||
argued to be <a href="http://www.hixie.ch/advocacy/xhtml">good practice</a>).</p>
|
||||
|
||||
<p>For XML, however, this XML Declaration is extremely important.
|
||||
<p>For XML, however, this processing instruction is extremely important.
|
||||
Since most webservers are not configured to send charsets for .xml files,
|
||||
this is the only thing a parser has to go on. Furthermore, the default
|
||||
for XML files is UTF-8, which often butts heads with more common
|
||||
ISO-8859-1 encoding (you see this in garbled RSS feeds).</p>
|
||||
|
||||
<p>In short, if you use XHTML and have gone through the
|
||||
trouble of adding the XML Declaration, make sure it jives
|
||||
with your <code>META</code> tags (which should only be present
|
||||
if served in text/html) and HTTP headers.</p>
|
||||
trouble of adding the XML header, make sure it jives
|
||||
with your <code>META</code> tags and HTTP headers.</p>
|
||||
|
||||
<h3 id="fixcharset-internals">Inside the process</h3>
|
||||
|
||||
@@ -515,7 +506,7 @@ usage in one language sometimes requires the occasional special character
|
||||
that, without surprise, is not available in your character set. Sometimes
|
||||
developers get around this by adding support for multiple encodings: when
|
||||
using Chinese, use Big5, when using Japanese, use Shift-JIS, when
|
||||
using Greek, etc. Other times, they use character references with great
|
||||
using Greek, etc. Other times, they use character entities with great
|
||||
zeal.</p>
|
||||
|
||||
<p>UTF-8, however, obviates the need for any of these complicated
|
||||
@@ -529,14 +520,14 @@ you don't have to use those user-unfriendly entities.</p>
|
||||
|
||||
<p>Websites encoded in Latin-1 (ISO-8859-1) which ocassionally need
|
||||
a special character outside of their scope often will use a character
|
||||
entity reference to achieve the desired effect. For instance, θ can be
|
||||
entity to achieve the desired effect. For instance, θ can be
|
||||
written <code>&theta;</code>, regardless of the character encoding's
|
||||
support of Greek letters.</p>
|
||||
|
||||
<p>This works nicely for limited use of special characters, but
|
||||
say you wanted this sentence of Chinese text: 激光,
|
||||
這兩個字是甚麼意思.
|
||||
The ampersand encoded version would look like this:</p>
|
||||
The entity-ized version would look like this:</p>
|
||||
|
||||
<pre>&#28608;&#20809;, &#36889;&#20841;&#20491;&#23383;&#26159;&#29978;&#40636;&#24847;&#24605;</pre>
|
||||
|
||||
@@ -554,7 +545,7 @@ an application that originally used ISO-8859-1 but switched to UTF-8
|
||||
when it became far to cumbersome to support foreign languages. Bots
|
||||
will now actually go through articles and convert character entities
|
||||
to their corresponding real characters for the sake of user-friendliness
|
||||
and searchability. See
|
||||
and searcheability. See
|
||||
<a href="http://meta.wikimedia.org/wiki/Help:Special_characters">Meta's
|
||||
page on special characters</a> for more details.
|
||||
</p></blockquote>
|
||||
@@ -576,11 +567,10 @@ which may be used by POST, and is required when you want to upload
|
||||
files.</p>
|
||||
|
||||
<p>The following is a summarization of notes from
|
||||
<a href="http://web.archive.org/web/20060427015200/ppewww.ph.gla.ac.uk/~flavell/charset/form-i18n.html">
|
||||
<a href="http://ppewww.physics.gla.ac.uk/~flavell/charset/form-i18n.html">
|
||||
<code>FORM</code> submission and i18n</a>. That document contains lots
|
||||
of useful information, but is written in a rambly manner, so
|
||||
here I try to get right to the point. (Note: the original has
|
||||
disappeared off the web, so I am linking to the Web Archive copy.)</p>
|
||||
here I try to get right to the point.</p>
|
||||
|
||||
<h4 id="whyutf8-forms-urlencoded"><code>application/x-www-form-urlencoded</code></h4>
|
||||
|
||||
@@ -602,7 +592,7 @@ browser you're using, they might:</p>
|
||||
<ul>
|
||||
<li>Replace the unsupported characters with useless question marks,</li>
|
||||
<li>Attempt to fix the characters (example: smart quotes to regular quotes),</li>
|
||||
<li>Replace the character with a character entity reference, or</li>
|
||||
<li>Replace the character with a character entity, or</li>
|
||||
<li>Send it anyway as a different character encoding mixed in
|
||||
with the original encoding (usually Windows-1252 rather than
|
||||
iso-8859-1 or UTF-8 interspersed in 8-bit)</li>
|
||||
@@ -618,7 +608,7 @@ since UTF-8 supports every character.</p>
|
||||
|
||||
<h4 id="whyutf8-forms-multipart"><code>multipart/form-data</code></h4>
|
||||
|
||||
<p>Multipart form submission takes away a lot of the ambiguity
|
||||
<p>Multipart form submission takes a way a lot of the ambiguity
|
||||
that percent-encoding had: the server now can explicitly ask for
|
||||
certain encodings, and the client can explicitly tell the server
|
||||
during the form submission what encoding the fields are in.</p>
|
||||
@@ -631,9 +621,9 @@ Each method has deficiencies, especially the former.</p>
|
||||
<p>If you tell the browser to send the form in the same encoding as
|
||||
the page, you still have the trouble of what to do with characters
|
||||
that are outside of the character encoding's range. The behavior, once
|
||||
again, varies: Firefox 2.0 converts them to character entity references
|
||||
while Internet Explorer 7.0 mangles them beyond intelligibility. For
|
||||
serious internationalization purposes, this is not an option.</p>
|
||||
again, varies: Firefox 2.0 entity-izes them while Internet Explorer
|
||||
7.0 mangles them beyond intelligibility. For serious internationalization purposes,
|
||||
this is not an option.</p>
|
||||
|
||||
<p>The other possibility is to set Accept-Encoding to UTF-8, which
|
||||
begs the question: Why aren't you using UTF-8 for everything then?
|
||||
@@ -673,12 +663,12 @@ it up to the module iconv to do the dirty work.</p>
|
||||
<p>This approach, however, is not perfect. iconv is blithely unaware
|
||||
of HTML character entities. HTML Purifier, in order to
|
||||
protect against sophisticated escaping schemes, normalizes all character
|
||||
and numeric entitie references before processing the text. This leads to
|
||||
and numeric entities before processing the text. This leads to
|
||||
one important ramification:</p>
|
||||
|
||||
<p><strong>Any character that is not supported by the target character
|
||||
set, regardless of whether or not it is in the form of a character
|
||||
entity reference or a raw character, will be silently ignored.</strong></p>
|
||||
entity or a raw character, will be silently ignored.</strong></p>
|
||||
|
||||
<p>Example of this principle at work: say you have <code>&theta;</code>
|
||||
in your HTML, but the output is in Latin-1 (which, understandably,
|
||||
@@ -687,7 +677,7 @@ set the encoding correctly using %Core.Encoding):</p>
|
||||
|
||||
<ul>
|
||||
<li>The <code>Encoder</code> will transform the text from ISO 8859-1 to UTF-8
|
||||
(note that theta is preserved here since it doesn't actually use
|
||||
(note that theta is preserved since it doesn't actually use
|
||||
any non-ASCII characters): <code>&theta;</code></li>
|
||||
<li>The <code>EntityParser</code> will transform all named and numeric
|
||||
character entities to their corresponding raw UTF-8 equivalents:
|
||||
@@ -710,7 +700,7 @@ Purifier has provided a slightly more palatable workaround using
|
||||
<li>The <code>EntityParser</code> transforms entities: <code>θ</code></li>
|
||||
<li>HTML Purifier processes the code: <code>θ</code></li>
|
||||
<li>The <code>Encoder</code> replaces all non-ASCII characters
|
||||
with numeric entity reference: <code>&#952;</code></li>
|
||||
with numeric entities: <code>&#952;</code></li>
|
||||
<li>For good measure, <code>Encoder</code> transforms encoding back to
|
||||
original (which is strictly unnecessary for 99% of encodings
|
||||
out there): <code>&#952;</code> (remember, it's all ASCII!)</li>
|
||||
@@ -720,19 +710,19 @@ Purifier has provided a slightly more palatable workaround using
|
||||
the land of Unicode characters, and is totally unacceptable for Chinese
|
||||
or Japanese texts. The even bigger kicker is that, supposing the
|
||||
input encoding was actually ISO-8859-7, which <em>does</em> support
|
||||
theta, the character would get converted into a character entity reference
|
||||
anyway! (The Encoder does not discriminate).</p>
|
||||
theta, the character would get entity-ized anyway! (The Encoder does
|
||||
not discriminate).</p>
|
||||
|
||||
<p>The current functionality is about where HTML Purifier will be for
|
||||
the rest of eternity. HTML Purifier could attempt to preserve the original
|
||||
form of the character references so that they could be substituted back in, only the
|
||||
form of the entities so that they could be substituted back in, only the
|
||||
DOM extension kills them off irreversibly. HTML Purifier could also attempt
|
||||
to be smart and only convert non-ASCII characters that weren't supported
|
||||
by the target encoding, but that would require reimplementing iconv
|
||||
with HTML awareness, something I will not do.</p>
|
||||
|
||||
<p>So there: either it's UTF-8 or crippled international support. Your pick! (and I'm
|
||||
not being sarcastic here: some people could care less about other languages).</p>
|
||||
not being sarcastic here: some people could care less about other languages)</p>
|
||||
|
||||
<h2 id="migrate">Migrate to UTF-8</h2>
|
||||
|
||||
@@ -994,7 +984,7 @@ and yes, it is variable width. Other traits:</p>
|
||||
in different ways. It is beyond the scope of this document to explain
|
||||
what precisely these implications are. PHPWact provides
|
||||
a very good <a href="http://www.phpwact.org/php/i18n/utf-8">reference document</a>
|
||||
on what to expect from each function, although coverage is spotty in
|
||||
on what to expect from each functions, although coverage is spotty in
|
||||
some areas. Their more general notes on
|
||||
<a href="http://www.phpwact.org/php/i18n/charsets">character sets</a>
|
||||
are also worth looking at for information on UTF-8. Some rules of thumb
|
||||
@@ -1008,7 +998,7 @@ when dealing with Unicode text:</p>
|
||||
<li>Think twice before using functions that:<ul>
|
||||
<li>...count characters (strlen will return bytes, not characters;
|
||||
str_split and word_wrap may corrupt)</li>
|
||||
<li>...convert characters to entity references (UTF-8 doesn't need entities)</li>
|
||||
<li>...entity-ize things (UTF-8 doesn't need entities)</li>
|
||||
<li>...do very complex string processing (*printf)</li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
@@ -1053,4 +1043,4 @@ a more in-depth look into character sets and encodings.</p>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@@ -149,4 +149,4 @@ like that, for that matter), send it over and it might get included
|
||||
with the core!</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@@ -20,3 +20,4 @@ $pure_html = $purifier->purify($html);
|
||||
|
||||
echo '<pre>' . htmlspecialchars($pure_html) . '</pre>';
|
||||
|
||||
?>
|
@@ -40,9 +40,6 @@ information for casual developers using HTML Purifier.</p>
|
||||
<dt><a href="enduser-customize.html">Customize</a></dt>
|
||||
<dd>Tutorial for customizing HTML Purifier's tag and attribute sets.</dd>
|
||||
|
||||
<dt><a href="enduser-uri-filter.html">URI Filters</a></dt>
|
||||
<dd>Tutorial for creating custom URI filters.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<h2>Development</h2>
|
||||
@@ -60,16 +57,10 @@ conventions.</p>
|
||||
<dt><a href="dev-optimization.html">Optimization</a></dt>
|
||||
<dd>Discusses possible methods of optimizing HTML Purifier.</dd>
|
||||
|
||||
<dt><a href="dev-flush.html">Flushing the Purifier</a></dt>
|
||||
<dd>Discusses when to flush HTML Purifier's various caches.</dd>
|
||||
|
||||
<dt><a href="dev-advanced-api.html">Advanced API</a></dt>
|
||||
<dd>Specification for HTML Purifier's advanced API for defining
|
||||
<dd>Functional specification for HTML Purifier's advanced API for defining
|
||||
custom filtering behavior.</dd>
|
||||
|
||||
<dt><a href="dev-config-schema.html">Config Schema</a></dt>
|
||||
<dd>Describes config schema framework in HTML Purifier.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<h2>Proposals</h2>
|
||||
@@ -119,7 +110,7 @@ the code. They may be upgraded to HTML files or stay as TXT scratchpads.</p>
|
||||
|
||||
<tr>
|
||||
<td>Development</td>
|
||||
<td><a href="dev-code-quality.txt">Code Quality Issues</a></td>
|
||||
<td><a href="enduser-code-quality.txt">Code Quality Issues</a></td>
|
||||
<td>Enumerates code quality issues and places that need to be refactored.</td>
|
||||
</tr>
|
||||
|
||||
@@ -141,12 +132,6 @@ the code. They may be upgraded to HTML files or stay as TXT scratchpads.</p>
|
||||
<td>Assorted configuration options that could be implemented.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Proposal</td>
|
||||
<td><a href="proposal-css-extraction.txt">CSS extraction</a></td>
|
||||
<td>Taking the inline CSS out of documents and into <code>style</code>.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>Reference</td>
|
||||
<td><a href="ref-content-models.txt">Handling Content Model Changes</a></td>
|
||||
@@ -177,4 +162,4 @@ the code. They may be upgraded to HTML files or stay as TXT scratchpads.</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@@ -1,32 +0,0 @@
|
||||
|
||||
Extracting inline CSS from HTML Purifier
|
||||
voodoofied: Assigning semantics to elements
|
||||
|
||||
Sander Tekelenburg brought to my attention the poor programming style of
|
||||
inline CSS in HTML documents. In an ideal world, we wouldn't be using inline
|
||||
CSS at all: everything would be assigned using semantic class attributes
|
||||
from an external stylesheet.
|
||||
|
||||
With ExtractStyleBlocks and CSSTidy, this is now possible (when allowed, users
|
||||
can specify a style element which gets extracted from the user-submitted HTML, which
|
||||
the application can place in the head of the HTML document). But there still
|
||||
is the issue of inline CSS that refuses to go away.
|
||||
|
||||
The basic idea behind this feature is assign every element a unique identifier,
|
||||
and then move all of the CSS data to a style-sheet. This HTML:
|
||||
|
||||
<div style="text-align:center">Big <span style="color:red;">things</span>!</div>
|
||||
|
||||
into
|
||||
|
||||
<div id="hp-12345">Big <span id="hp-12346">things</span>!</div>
|
||||
|
||||
and a stylesheet that is:
|
||||
|
||||
#hp-12345 {text-align:center;}
|
||||
#hp-12346 {color:red;}
|
||||
|
||||
Beyond that, HTML Purifier can magically merge common CSS values together,
|
||||
and a whole manner of other heuristic things. HTML Purifier should also
|
||||
make it easy for an admin to re-style the HTML semantically. Speed is not
|
||||
an issue. Also, better WYSIWYG editors are needed.
|
@@ -32,7 +32,7 @@ Here are some fuzzy levels you could set:
|
||||
|
||||
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 editor that hasn't been synced accordingly. This may
|
||||
is incoming from a WYSIWYG eidtor that hasn't been synced accordingly. This may
|
||||
make forbidden element to text transformations desirable (for example, images).
|
||||
|
||||
|
||||
|
@@ -2,8 +2,7 @@
|
||||
Configuration Ideas
|
||||
|
||||
Here are some theoretical configuration ideas that we could implement some
|
||||
time. Note the naming convention: %Namespace.Directive. If you want one
|
||||
implemented, give us a ring, and we'll move it up the priority chain.
|
||||
time. Note the naming convention: %Namespace.Directive
|
||||
|
||||
%Attr.RewriteFragments - if there's %Attr.IDPrefix we may want to transparently
|
||||
rewrite the URLs we parse too. However, we can only do it when it's a pure
|
||||
@@ -23,6 +22,8 @@ implemented, give us a ring, and we'll move it up the priority chain.
|
||||
%URI.AddRelNofollow - will add rel="nofollow" to all links, preventing the
|
||||
spread of ill-gotten pagerank
|
||||
|
||||
%URI.RelativeToAbsolute - transforms all relative URIs to absolute form
|
||||
|
||||
%URI.HostBlacklistRegex - regexes that if matching the host are disallowed
|
||||
%URI.HostWhitelist - domain names that are excluded from the host blacklist
|
||||
%URI.HostPolicy - determines whether or not its reject all and then whitelist
|
||||
|
@@ -1,28 +0,0 @@
|
||||
|
||||
CSS Length Reference
|
||||
To bound, or not to bound, that is the question
|
||||
|
||||
It's quite a reasonable request, really, and it's already been implemented
|
||||
for HTML. That is, length bounding. It makes little sense to let users
|
||||
define text blocks that have a font-size of 63,360 inches (that's a mile,
|
||||
by the way) or a width of forty-fold the parent container.
|
||||
|
||||
But it's a little more complicated then that. There are multiple units
|
||||
one can use, and we have to a little unit conversion to get things working.
|
||||
Here's what we have:
|
||||
|
||||
Absolute:
|
||||
1 in ~= 2.54 cm
|
||||
1 cm = 10 mm
|
||||
1 pt = 1/72 in
|
||||
1 pc = 12 pt
|
||||
|
||||
Relative:
|
||||
1 em ~= 10.0667 px
|
||||
1 ex ~= 0.5 em, though Mozilla Firefox says 1 ex = 6px
|
||||
1 px ~= 1 pt
|
||||
|
||||
Watch out: font-sizes can also be nested to get successively larger
|
||||
(although I do not relish having to keep track of context font-sizes,
|
||||
this may be necessary, especially for some of the more advanced features
|
||||
for preventing things like white on white).
|
@@ -42,4 +42,4 @@ the development of this library in these forum threads:</p>
|
||||
|
||||
<div id="version">$Id$</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@@ -1,8 +1,8 @@
|
||||
|
||||
The Modularization of HTMLDefinition in HTML Purifier
|
||||
|
||||
WARNING: This document was drafted before the implementation of this
|
||||
system, and some implementation details may have evolved over time.
|
||||
Todo for XHTML 1.1 support <http://www.w3.org/TR/xhtml11/changes.html>
|
||||
1. Support Ruby <http://www.w3.org/TR/2001/REC-ruby-20010531/>
|
||||
|
||||
HTML Purifier uses the modularization of XHTML
|
||||
<http://www.w3.org/TR/xhtml-modularization/> to organize the internals
|
||||
|
@@ -21,4 +21,4 @@ HTML Purifier context.
|
||||
<xmp>, monospace, replace with pre
|
||||
|
||||
These should be put into their own Tidy module, not loaded by default(?). These
|
||||
all qualify as "lenient" transforms.
|
||||
all qualify as "lenient" transforms.
|
@@ -33,9 +33,6 @@ blockquote .label {font-weight:bold; font-size:1em; margin:0 0 .1em;
|
||||
.table thead th:first-child {-moz-border-radius-topleft:1em;}
|
||||
.table tbody td {border-bottom:1px solid #CCC; padding-right:0.6em;padding-left:0.6em;}
|
||||
|
||||
/* A quick table*/
|
||||
table.quick tbody th {text-align:right; padding-right:1em;}
|
||||
|
||||
/* Category of the file */
|
||||
#filing {font-weight:bold; font-size:smaller; }
|
||||
|
||||
|
@@ -1,155 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Filesystem tools not provided by default; can recursively create, copy
|
||||
* and delete folders. Some template methods are provided for extensibility.
|
||||
*
|
||||
* @note This class must be instantiated to be used, although it does
|
||||
* not maintain state.
|
||||
*/
|
||||
class FSTools
|
||||
{
|
||||
|
||||
private static $singleton;
|
||||
|
||||
/**
|
||||
* Returns a global instance of FSTools
|
||||
*/
|
||||
static public function singleton() {
|
||||
if (empty(FSTools::$singleton)) FSTools::$singleton = new FSTools();
|
||||
return FSTools::$singleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets our global singleton to something else; useful for overloading
|
||||
* functions.
|
||||
*/
|
||||
static public function setSingleton($singleton) {
|
||||
FSTools::$singleton = $singleton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively creates a directory
|
||||
* @param string $folder Name of folder to create
|
||||
* @note Adapted from the PHP manual comment 76612
|
||||
*/
|
||||
public function mkdirr($folder) {
|
||||
$folders = preg_split("#[\\\\/]#", $folder);
|
||||
$base = '';
|
||||
for($i = 0, $c = count($folders); $i < $c; $i++) {
|
||||
if(empty($folders[$i])) {
|
||||
if (!$i) {
|
||||
// special case for root level
|
||||
$base .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$base .= $folders[$i];
|
||||
if(!is_dir($base)){
|
||||
$this->mkdir($base);
|
||||
}
|
||||
$base .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a file, or recursively copy a folder and its contents; modified
|
||||
* so that copied files, if PHP, have includes removed
|
||||
* @note Adapted from http://aidanlister.com/repos/v/function.copyr.php
|
||||
*/
|
||||
public function copyr($source, $dest) {
|
||||
// Simple copy for a file
|
||||
if (is_file($source)) {
|
||||
return $this->copy($source, $dest);
|
||||
}
|
||||
// Make destination directory
|
||||
if (!is_dir($dest)) {
|
||||
$this->mkdir($dest);
|
||||
}
|
||||
// Loop through the folder
|
||||
$dir = $this->dir($source);
|
||||
while ( false !== ($entry = $dir->read()) ) {
|
||||
// Skip pointers
|
||||
if ($entry == '.' || $entry == '..') {
|
||||
continue;
|
||||
}
|
||||
if (!$this->copyable($entry)) {
|
||||
continue;
|
||||
}
|
||||
// Deep copy directories
|
||||
if ($dest !== "$source/$entry") {
|
||||
$this->copyr("$source/$entry", "$dest/$entry");
|
||||
}
|
||||
}
|
||||
// Clean up
|
||||
$dir->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloadable function that tests a filename for copyability. By
|
||||
* default, everything should be copied; you can restrict things to
|
||||
* ignore hidden files, unreadable files, etc. This function
|
||||
* applies to copyr().
|
||||
*/
|
||||
public function copyable($file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a file, or a folder and its contents
|
||||
* @note Adapted from http://aidanlister.com/repos/v/function.rmdirr.php
|
||||
*/
|
||||
public function rmdirr($dirname)
|
||||
{
|
||||
// Sanity check
|
||||
if (!$this->file_exists($dirname)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Simple delete for a file
|
||||
if ($this->is_file($dirname) || $this->is_link($dirname)) {
|
||||
return $this->unlink($dirname);
|
||||
}
|
||||
|
||||
// Loop through the folder
|
||||
$dir = $this->dir($dirname);
|
||||
while (false !== $entry = $dir->read()) {
|
||||
// Skip pointers
|
||||
if ($entry == '.' || $entry == '..') {
|
||||
continue;
|
||||
}
|
||||
// Recurse
|
||||
$this->rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
$dir->close();
|
||||
return $this->rmdir($dirname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively globs a directory.
|
||||
*/
|
||||
public function globr($dir, $pattern, $flags = NULL) {
|
||||
$files = $this->glob("$dir/$pattern", $flags);
|
||||
if ($files === false) $files = array();
|
||||
$sub_dirs = $this->glob("$dir/*", GLOB_ONLYDIR);
|
||||
if ($sub_dirs === false) $sub_dirs = array();
|
||||
foreach ($sub_dirs as $sub_dir) {
|
||||
$sub_files = $this->globr($sub_dir, $pattern, $flags);
|
||||
$files = array_merge($files, $sub_files);
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows for PHP functions to be called and be stubbed.
|
||||
* @warning This function will not work for functions that need
|
||||
* to pass references; manually define a stub function for those.
|
||||
*/
|
||||
public function __call($name, $args) {
|
||||
return call_user_func_array($name, $args);
|
||||
}
|
||||
|
||||
}
|
@@ -1,124 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Represents a file in the filesystem
|
||||
*
|
||||
* @warning Be sure to distinguish between get() and write() versus
|
||||
* read() and put(), the former operates on the entire file, while
|
||||
* the latter operates on a handle.
|
||||
*/
|
||||
class FSTools_File
|
||||
{
|
||||
|
||||
/** Filename of file this object represents */
|
||||
protected $name;
|
||||
|
||||
/** Handle for the file */
|
||||
protected $handle = false;
|
||||
|
||||
/** Instance of FSTools for interfacing with filesystem */
|
||||
protected $fs;
|
||||
|
||||
/**
|
||||
* Filename of file you wish to instantiate.
|
||||
* @note This file need not exist
|
||||
*/
|
||||
public function __construct($name, $fs = false) {
|
||||
$this->name = $name;
|
||||
$this->fs = $fs ? $fs : FSTools::singleton();
|
||||
}
|
||||
|
||||
/** Returns the filename of the file. */
|
||||
public function getName() {return $this->name;}
|
||||
|
||||
/** Returns directory of the file without trailing slash */
|
||||
public function getDirectory() {return $this->fs->dirname($this->name);}
|
||||
|
||||
/**
|
||||
* Retrieves the contents of a file
|
||||
* @todo Throw an exception if file doesn't exist
|
||||
*/
|
||||
public function get() {
|
||||
return $this->fs->file_get_contents($this->name);
|
||||
}
|
||||
|
||||
/** Writes contents to a file, creates new file if necessary */
|
||||
public function write($contents) {
|
||||
return $this->fs->file_put_contents($this->name, $contents);
|
||||
}
|
||||
|
||||
/** Deletes the file */
|
||||
public function delete() {
|
||||
return $this->fs->unlink($this->name);
|
||||
}
|
||||
|
||||
/** Returns true if file exists and is a file. */
|
||||
public function exists() {
|
||||
return $this->fs->is_file($this->name);
|
||||
}
|
||||
|
||||
/** Returns last file modification time */
|
||||
public function getMTime() {
|
||||
return $this->fs->filemtime($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Chmod a file
|
||||
* @note We ignore errors because of some weird owner trickery due
|
||||
* to SVN duality
|
||||
*/
|
||||
public function chmod($octal_code) {
|
||||
return @$this->fs->chmod($this->name, $octal_code);
|
||||
}
|
||||
|
||||
/** Opens file's handle */
|
||||
public function open($mode) {
|
||||
if ($this->handle) $this->close();
|
||||
$this->handle = $this->fs->fopen($this->name, $mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Closes file's handle */
|
||||
public function close() {
|
||||
if (!$this->handle) return false;
|
||||
$status = $this->fs->fclose($this->handle);
|
||||
$this->handle = false;
|
||||
return $status;
|
||||
}
|
||||
|
||||
/** Retrieves a line from an open file, with optional max length $length */
|
||||
public function getLine($length = null) {
|
||||
if (!$this->handle) $this->open('r');
|
||||
if ($length === null) return $this->fs->fgets($this->handle);
|
||||
else return $this->fs->fgets($this->handle, $length);
|
||||
}
|
||||
|
||||
/** Retrieves a character from an open file */
|
||||
public function getChar() {
|
||||
if (!$this->handle) $this->open('r');
|
||||
return $this->fs->fgetc($this->handle);
|
||||
}
|
||||
|
||||
/** Retrieves an $length bytes of data from an open data */
|
||||
public function read($length) {
|
||||
if (!$this->handle) $this->open('r');
|
||||
return $this->fs->fread($this->handle, $length);
|
||||
}
|
||||
|
||||
/** Writes to an open file */
|
||||
public function put($string) {
|
||||
if (!$this->handle) $this->open('a');
|
||||
return $this->fs->fwrite($this->handle, $string);
|
||||
}
|
||||
|
||||
/** Returns TRUE if the end of the file has been reached */
|
||||
public function eof() {
|
||||
if (!$this->handle) return true;
|
||||
return $this->fs->feof($this->handle);
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
if ($this->handle) $this->close();
|
||||
}
|
||||
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Convenience file that registers autoload handler for HTML Purifier.
|
||||
*
|
||||
* @warning
|
||||
* This autoloader does not contain the compatibility code seen in
|
||||
* HTMLPurifier_Bootstrap; the user is expected to make any necessary
|
||||
* changes to use this library.
|
||||
*/
|
||||
|
||||
if (function_exists('spl_autoload_register')) {
|
||||
spl_autoload_register(array('HTMLPurifierExtras', 'autoload'));
|
||||
if (function_exists('__autoload')) {
|
||||
// Be polite and ensure that userland autoload gets retained
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
} elseif (!function_exists('__autoload')) {
|
||||
function __autoload($class) {
|
||||
return HTMLPurifierExtras::autoload($class);
|
||||
}
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Meta-class for HTML Purifier's extra class hierarchies, similar to
|
||||
* HTMLPurifier_Bootstrap.
|
||||
*/
|
||||
class HTMLPurifierExtras
|
||||
{
|
||||
|
||||
public static function autoload($class) {
|
||||
$path = HTMLPurifierExtras::getPath($class);
|
||||
if (!$path) return false;
|
||||
require $path;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getPath($class) {
|
||||
if (
|
||||
strncmp('FSTools', $class, 7) !== 0 &&
|
||||
strncmp('ConfigDoc', $class, 9) !== 0
|
||||
) return false;
|
||||
// Custom implementations can go here
|
||||
// Standard implementation:
|
||||
return str_replace('_', '/', $class) . '.php';
|
||||
}
|
||||
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
|
||||
HTML Purifier Extras
|
||||
The Method Behind The Madness!
|
||||
|
||||
The extras/ folder in HTML Purifier contains--you guessed it--extra things
|
||||
for HTML Purifier. Specifically, these are two extra libraries called
|
||||
FSTools and ConfigSchema. They're extra for a reason: you don't need them
|
||||
if you're using HTML Purifier for normal usage: filtering HTML. However,
|
||||
if you're a developer, and would like to test HTML Purifier, or need to
|
||||
use one of HTML Purifier's maintenance scripts, chances are they'll need
|
||||
these libraries. Who knows: maybe you'll find them useful too!
|
||||
|
||||
Here are the libraries:
|
||||
|
||||
|
||||
FSTools
|
||||
-------
|
||||
|
||||
Short for File System Tools, this is a poor-man's object-oriented wrapper for
|
||||
the filesystem. It currently consists of two classes:
|
||||
|
||||
- FSTools: This is a singleton that contains a manner of useful functions
|
||||
such as recursive glob, directory removal, etc, as well as the ability
|
||||
to call arbitrary native PHP functions through it like $FS->fopen(...).
|
||||
This makes it a lot simpler to mock these filesystem calls for unit testing.
|
||||
|
||||
- FSTools_File: This object represents a single file, and has almost any
|
||||
method imaginable one would need.
|
||||
|
||||
Check the files themselves for more information.
|
@@ -5,5 +5,6 @@
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
||||
require_once 'HTMLPurifier/Bootstrap.php';
|
||||
require_once 'HTMLPurifier.autoload.php';
|
||||
require_once 'HTMLPurifier.php';
|
||||
|
||||
?>
|
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Convenience file that registers autoload handler for HTML Purifier.
|
||||
*/
|
||||
|
||||
if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {
|
||||
// We need unregister for our pre-registering functionality
|
||||
HTMLPurifier_Bootstrap::registerAutoload();
|
||||
if (function_exists('__autoload')) {
|
||||
// Be polite and ensure that userland autoload gets retained
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
} elseif (!function_exists('__autoload')) {
|
||||
function __autoload($class) {
|
||||
return HTMLPurifier_Bootstrap::autoload($class);
|
||||
}
|
||||
}
|
@@ -1,22 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Defines a function wrapper for HTML Purifier for quick use.
|
||||
* Function wrapper for HTML Purifier for quick use.
|
||||
* @note This function only includes the library when it is called. While
|
||||
* this is efficient for instances when you only use HTML Purifier
|
||||
* on a few of your pages, it murders bytecode caching. You still
|
||||
* need to add HTML Purifier to your path.
|
||||
* @note ''HTMLPurifier()'' is NOT the same as ''new HTMLPurifier()''
|
||||
*/
|
||||
|
||||
/**
|
||||
* Purify HTML.
|
||||
* @param $html String HTML to purify
|
||||
* @param $config Configuration to use, can be any value accepted by
|
||||
* HTMLPurifier_Config::create()
|
||||
*/
|
||||
function HTMLPurifier($html, $config = null) {
|
||||
static $purifier = false;
|
||||
if (!$purifier) {
|
||||
require_once 'HTMLPurifier.php';
|
||||
$purifier = new HTMLPurifier();
|
||||
}
|
||||
return $purifier->purify($html, $config);
|
||||
}
|
||||
|
||||
?>
|
@@ -1,188 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file was auto-generated by generate-includes.php and includes all of
|
||||
* the core files required by HTML Purifier. Use this if performance is a
|
||||
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
|
||||
* FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* @version 3.0.0
|
||||
*
|
||||
* @warning
|
||||
* You must *not* include any other HTML Purifier files before this file,
|
||||
* because 'require' not 'require_once' is used.
|
||||
*
|
||||
* @warning
|
||||
* This file requires that the include path contains the HTML Purifier
|
||||
* library directory; this is not auto-set.
|
||||
*/
|
||||
|
||||
require 'HTMLPurifier.php';
|
||||
require 'HTMLPurifier/AttrCollections.php';
|
||||
require 'HTMLPurifier/AttrDef.php';
|
||||
require 'HTMLPurifier/AttrTransform.php';
|
||||
require 'HTMLPurifier/AttrTypes.php';
|
||||
require 'HTMLPurifier/AttrValidator.php';
|
||||
require 'HTMLPurifier/Bootstrap.php';
|
||||
require 'HTMLPurifier/Definition.php';
|
||||
require 'HTMLPurifier/CSSDefinition.php';
|
||||
require 'HTMLPurifier/ChildDef.php';
|
||||
require 'HTMLPurifier/Config.php';
|
||||
require 'HTMLPurifier/ConfigDef.php';
|
||||
require 'HTMLPurifier/ConfigSchema.php';
|
||||
require 'HTMLPurifier/ContentSets.php';
|
||||
require 'HTMLPurifier/Context.php';
|
||||
require 'HTMLPurifier/DefinitionCache.php';
|
||||
require 'HTMLPurifier/DefinitionCacheFactory.php';
|
||||
require 'HTMLPurifier/Doctype.php';
|
||||
require 'HTMLPurifier/DoctypeRegistry.php';
|
||||
require 'HTMLPurifier/ElementDef.php';
|
||||
require 'HTMLPurifier/Encoder.php';
|
||||
require 'HTMLPurifier/EntityLookup.php';
|
||||
require 'HTMLPurifier/EntityParser.php';
|
||||
require 'HTMLPurifier/Error.php';
|
||||
require 'HTMLPurifier/ErrorCollector.php';
|
||||
require 'HTMLPurifier/Exception.php';
|
||||
require 'HTMLPurifier/Filter.php';
|
||||
require 'HTMLPurifier/Generator.php';
|
||||
require 'HTMLPurifier/HTMLDefinition.php';
|
||||
require 'HTMLPurifier/HTMLModule.php';
|
||||
require 'HTMLPurifier/HTMLModuleManager.php';
|
||||
require 'HTMLPurifier/IDAccumulator.php';
|
||||
require 'HTMLPurifier/Injector.php';
|
||||
require 'HTMLPurifier/Language.php';
|
||||
require 'HTMLPurifier/LanguageFactory.php';
|
||||
require 'HTMLPurifier/Lexer.php';
|
||||
require 'HTMLPurifier/PercentEncoder.php';
|
||||
require 'HTMLPurifier/Strategy.php';
|
||||
require 'HTMLPurifier/StringHash.php';
|
||||
require 'HTMLPurifier/StringHashParser.php';
|
||||
require 'HTMLPurifier/TagTransform.php';
|
||||
require 'HTMLPurifier/Token.php';
|
||||
require 'HTMLPurifier/TokenFactory.php';
|
||||
require 'HTMLPurifier/URI.php';
|
||||
require 'HTMLPurifier/URIDefinition.php';
|
||||
require 'HTMLPurifier/URIFilter.php';
|
||||
require 'HTMLPurifier/URIParser.php';
|
||||
require 'HTMLPurifier/URIScheme.php';
|
||||
require 'HTMLPurifier/URISchemeRegistry.php';
|
||||
require 'HTMLPurifier/VarParser.php';
|
||||
require 'HTMLPurifier/VarParserException.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS.php';
|
||||
require 'HTMLPurifier/AttrDef/Enum.php';
|
||||
require 'HTMLPurifier/AttrDef/Integer.php';
|
||||
require 'HTMLPurifier/AttrDef/Lang.php';
|
||||
require 'HTMLPurifier/AttrDef/Text.php';
|
||||
require 'HTMLPurifier/AttrDef/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Background.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Border.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Color.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Color.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/ID.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Length.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||
require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Email.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Host.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||
require 'HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||
require 'HTMLPurifier/AttrTransform/BdoDir.php';
|
||||
require 'HTMLPurifier/AttrTransform/BgColor.php';
|
||||
require 'HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||
require 'HTMLPurifier/AttrTransform/Border.php';
|
||||
require 'HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||
require 'HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||
require 'HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require 'HTMLPurifier/AttrTransform/Lang.php';
|
||||
require 'HTMLPurifier/AttrTransform/Length.php';
|
||||
require 'HTMLPurifier/AttrTransform/Name.php';
|
||||
require 'HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require 'HTMLPurifier/ChildDef/Custom.php';
|
||||
require 'HTMLPurifier/ChildDef/Empty.php';
|
||||
require 'HTMLPurifier/ChildDef/Required.php';
|
||||
require 'HTMLPurifier/ChildDef/Optional.php';
|
||||
require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require 'HTMLPurifier/ChildDef/Table.php';
|
||||
require 'HTMLPurifier/ConfigDef/Directive.php';
|
||||
require 'HTMLPurifier/ConfigDef/DirectiveAlias.php';
|
||||
require 'HTMLPurifier/ConfigDef/Namespace.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Null.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||
require 'HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||
require 'HTMLPurifier/HTMLModule/Bdo.php';
|
||||
require 'HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Edit.php';
|
||||
require 'HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require 'HTMLPurifier/HTMLModule/Image.php';
|
||||
require 'HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require 'HTMLPurifier/HTMLModule/List.php';
|
||||
require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Object.php';
|
||||
require 'HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require 'HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require 'HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tables.php';
|
||||
require 'HTMLPurifier/HTMLModule/Target.php';
|
||||
require 'HTMLPurifier/HTMLModule/Text.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require 'HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require 'HTMLPurifier/Injector/Linkify.php';
|
||||
require 'HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require 'HTMLPurifier/Lexer/DOMLex.php';
|
||||
require 'HTMLPurifier/Lexer/DirectLex.php';
|
||||
require 'HTMLPurifier/Strategy/Composite.php';
|
||||
require 'HTMLPurifier/Strategy/Core.php';
|
||||
require 'HTMLPurifier/Strategy/FixNesting.php';
|
||||
require 'HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||
require 'HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||
require 'HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||
require 'HTMLPurifier/TagTransform/Font.php';
|
||||
require 'HTMLPurifier/TagTransform/Simple.php';
|
||||
require 'HTMLPurifier/Token/Comment.php';
|
||||
require 'HTMLPurifier/Token/Tag.php';
|
||||
require 'HTMLPurifier/Token/Empty.php';
|
||||
require 'HTMLPurifier/Token/End.php';
|
||||
require 'HTMLPurifier/Token/Start.php';
|
||||
require 'HTMLPurifier/Token/Text.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require 'HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require 'HTMLPurifier/URIScheme/ftp.php';
|
||||
require 'HTMLPurifier/URIScheme/http.php';
|
||||
require 'HTMLPurifier/URIScheme/https.php';
|
||||
require 'HTMLPurifier/URIScheme/mailto.php';
|
||||
require 'HTMLPurifier/URIScheme/news.php';
|
||||
require 'HTMLPurifier/URIScheme/nntp.php';
|
||||
require 'HTMLPurifier/VarParser/Flexible.php';
|
||||
require 'HTMLPurifier/VarParser/Native.php';
|
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Emulation layer for code that used kses(), substituting in HTML Purifier.
|
||||
*/
|
||||
|
||||
require_once dirname(__FILE__) . '/HTMLPurifier.auto.php';
|
||||
|
||||
function kses($string, $allowed_html, $allowed_protocols = null) {
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$allowed_elements = array();
|
||||
$allowed_attributes = array();
|
||||
foreach ($allowed_html as $element => $attributes) {
|
||||
$allowed_elements[$element] = true;
|
||||
foreach ($attributes as $attribute => $x) {
|
||||
$allowed_attributes["$element.$attribute"] = true;
|
||||
}
|
||||
}
|
||||
$config->set('HTML', 'AllowedElements', $allowed_elements);
|
||||
$config->set('HTML', 'AllowedAttributes', $allowed_attributes);
|
||||
$allowed_schemes = array();
|
||||
if ($allowed_protocols !== null) {
|
||||
$config->set('URI', 'AllowedSchemes', $allowed_protocols);
|
||||
}
|
||||
$purifier = new HTMLPurifier($config);
|
||||
return $purifier->purify($string);
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Convenience stub file that adds HTML Purifier's library file to the path
|
||||
* without any other side-effects.
|
||||
*/
|
||||
|
||||
set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
|
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
/*! @mainpage
|
||||
/*!
|
||||
* @mainpage
|
||||
*
|
||||
* HTML Purifier is an HTML filter that will take an arbitrary snippet of
|
||||
* HTML and rigorously test, validate and filter it into a version that
|
||||
@@ -21,8 +22,8 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
HTML Purifier 3.1.0rc1 - Standards Compliant HTML Filtering
|
||||
Copyright (C) 2006-2008 Edward Z. Yang
|
||||
HTML Purifier 2.0.0 - Standards Compliant HTML Filtering
|
||||
Copyright (C) 2006 Edward Z. Yang
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
@@ -39,42 +40,59 @@
|
||||
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'; // important
|
||||
require_once 'HTMLPurifier/Config.php';
|
||||
require_once 'HTMLPurifier/Context.php';
|
||||
|
||||
require_once 'HTMLPurifier/Lexer.php';
|
||||
require_once 'HTMLPurifier/Generator.php';
|
||||
require_once 'HTMLPurifier/Strategy/Core.php';
|
||||
require_once 'HTMLPurifier/Encoder.php';
|
||||
|
||||
require_once 'HTMLPurifier/LanguageFactory.php';
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Core', 'Language', 'en', 'string', '
|
||||
ISO 639 language code for localizable things in HTML Purifier to use,
|
||||
which is mainly error reporting. There is currently only an English (en)
|
||||
translation, so this directive is currently useless.
|
||||
This directive has been available since 2.0.0.
|
||||
');
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Core', 'CollectErrors', false, 'bool', '
|
||||
Whether or not to collect errors found while filtering the document. This
|
||||
is a useful way to give feedback to your users. CURRENTLY NOT IMPLEMENTED.
|
||||
This directive has been available since 2.0.0.
|
||||
');
|
||||
|
||||
/**
|
||||
* Facade that coordinates HTML Purifier's subsystems in order to purify HTML.
|
||||
* Main library execution class.
|
||||
*
|
||||
* @note There are several points in which configuration can be specified
|
||||
* for HTML Purifier. The precedence of these (from lowest to
|
||||
* highest) is as follows:
|
||||
* -# Instance: new HTMLPurifier($config)
|
||||
* -# Invocation: purify($html, $config)
|
||||
* These configurations are entirely independent of each other and
|
||||
* are *not* merged (this behavior may change in the future).
|
||||
* Facade that performs calls to the HTMLPurifier_Lexer,
|
||||
* HTMLPurifier_Strategy and HTMLPurifier_Generator subsystems in order to
|
||||
* purify HTML.
|
||||
*
|
||||
* @todo We need an easier way to inject strategies using the configuration
|
||||
* object.
|
||||
* @todo We need an easier way to inject strategies, it'll probably end
|
||||
* up getting done through config though.
|
||||
*/
|
||||
class HTMLPurifier
|
||||
{
|
||||
|
||||
/** Version of HTML Purifier */
|
||||
public $version = '3.1.0rc1';
|
||||
var $version = '2.0.0';
|
||||
|
||||
/** Global configuration object */
|
||||
public $config;
|
||||
var $config;
|
||||
var $filters;
|
||||
|
||||
/** Array of extra HTMLPurifier_Filter objects to run on HTML, for backwards compatibility */
|
||||
private $filters = array();
|
||||
|
||||
/** Single instance of HTML Purifier */
|
||||
private static $instance;
|
||||
|
||||
protected $strategy, $generator;
|
||||
var $strategy, $generator;
|
||||
|
||||
/**
|
||||
* Resultant HTMLPurifier_Context of last run purification. Is an array
|
||||
* of contexts if the last called method was purifyArray().
|
||||
* Final HTMLPurifier_Context of last run purification. Might be an array.
|
||||
* @public
|
||||
*/
|
||||
public $context;
|
||||
var $context;
|
||||
|
||||
/**
|
||||
* Initializes the purifier.
|
||||
@@ -84,7 +102,7 @@ class HTMLPurifier
|
||||
* The parameter can also be any type that
|
||||
* HTMLPurifier_Config::create() supports.
|
||||
*/
|
||||
public function __construct($config = null) {
|
||||
function HTMLPurifier($config = null) {
|
||||
|
||||
$this->config = HTMLPurifier_Config::create($config);
|
||||
|
||||
@@ -97,8 +115,7 @@ class HTMLPurifier
|
||||
* Adds a filter to process the output. First come first serve
|
||||
* @param $filter HTMLPurifier_Filter object
|
||||
*/
|
||||
public function addFilter($filter) {
|
||||
trigger_error('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom', E_USER_WARNING);
|
||||
function addFilter($filter) {
|
||||
$this->filters[] = $filter;
|
||||
}
|
||||
|
||||
@@ -112,9 +129,8 @@ class HTMLPurifier
|
||||
* that HTMLPurifier_Config::create() supports.
|
||||
* @return Purified HTML
|
||||
*/
|
||||
public function purify($html, $config = null) {
|
||||
function purify($html, $config = null) {
|
||||
|
||||
// :TODO: make the config merge in, instead of replace
|
||||
$config = $config ? HTMLPurifier_Config::create($config) : $this->config;
|
||||
|
||||
// implementation is partially environment dependant, partially
|
||||
@@ -123,47 +139,21 @@ class HTMLPurifier
|
||||
|
||||
$context = new HTMLPurifier_Context();
|
||||
|
||||
// our friendly neighborhood generator, all primed with configuration too!
|
||||
$this->generator->generateFromTokens(array(), $config, $context);
|
||||
$context->register('Generator', $this->generator);
|
||||
|
||||
// set up global context variables
|
||||
if ($config->get('Core', 'CollectErrors')) {
|
||||
// may get moved out if other facilities use it
|
||||
$language_factory = HTMLPurifier_LanguageFactory::instance();
|
||||
$language = $language_factory->create($config, $context);
|
||||
$language = $language_factory->create($config->get('Core', 'Language'));
|
||||
$context->register('Locale', $language);
|
||||
|
||||
$error_collector = new HTMLPurifier_ErrorCollector($context);
|
||||
$context->register('ErrorCollector', $error_collector);
|
||||
$error_collector = new HTMLPurifier_ErrorCollector();
|
||||
$context->register('ErrorCollector', $language);
|
||||
}
|
||||
|
||||
// setup id_accumulator context, necessary due to the fact that
|
||||
// AttrValidator can be called from many places
|
||||
$id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
|
||||
$context->register('IDAccumulator', $id_accumulator);
|
||||
|
||||
$html = HTMLPurifier_Encoder::convertToUTF8($html, $config, $context);
|
||||
|
||||
// setup filters
|
||||
$filter_flags = $config->getBatch('Filter');
|
||||
$custom_filters = $filter_flags['Custom'];
|
||||
unset($filter_flags['Custom']);
|
||||
$filters = array();
|
||||
foreach ($filter_flags as $filter => $flag) {
|
||||
if (!$flag) continue;
|
||||
$class = "HTMLPurifier_Filter_$filter";
|
||||
$filters[] = new $class;
|
||||
}
|
||||
foreach ($custom_filters as $filter) {
|
||||
// maybe "HTMLPurifier_Filter_$filter", but be consistent with AutoFormat
|
||||
$filters[] = $filter;
|
||||
}
|
||||
$filters = array_merge($filters, $this->filters);
|
||||
// maybe prepare(), but later
|
||||
|
||||
for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) {
|
||||
$html = $filters[$i]->preFilter($html, $config, $context);
|
||||
for ($i = 0, $size = count($this->filters); $i < $size; $i++) {
|
||||
$html = $this->filters[$i]->preFilter($html, $config, $context);
|
||||
}
|
||||
|
||||
// purified HTML
|
||||
@@ -181,8 +171,8 @@ class HTMLPurifier
|
||||
$config, $context
|
||||
);
|
||||
|
||||
for ($i = $filter_size - 1; $i >= 0; $i--) {
|
||||
$html = $filters[$i]->postFilter($html, $config, $context);
|
||||
for ($i = $size - 1; $i >= 0; $i--) {
|
||||
$html = $this->filters[$i]->postFilter($html, $config, $context);
|
||||
}
|
||||
|
||||
$html = HTMLPurifier_Encoder::convertFromUTF8($html, $config, $context);
|
||||
@@ -196,7 +186,7 @@ class HTMLPurifier
|
||||
* See HTMLPurifier::purify() for more details.
|
||||
* @return Array of purified HTML
|
||||
*/
|
||||
public function purifyArray($array_of_html, $config = null) {
|
||||
function purifyArray($array_of_html, $config = null) {
|
||||
$context_array = array();
|
||||
foreach ($array_of_html as $key => $html) {
|
||||
$array_of_html[$key] = $this->purify($html, $config);
|
||||
@@ -208,20 +198,22 @@ class HTMLPurifier
|
||||
|
||||
/**
|
||||
* Singleton for enforcing just one HTML Purifier in your system
|
||||
* @param $prototype Optional prototype HTMLPurifier instance to
|
||||
* overload singleton with.
|
||||
*/
|
||||
public static function getInstance($prototype = null) {
|
||||
if (!self::$instance || $prototype) {
|
||||
if ($prototype instanceof HTMLPurifier) {
|
||||
self::$instance = $prototype;
|
||||
function &getInstance($prototype = null) {
|
||||
static $htmlpurifier;
|
||||
if (!$htmlpurifier || $prototype) {
|
||||
if (is_a($prototype, 'HTMLPurifier')) {
|
||||
$htmlpurifier = $prototype;
|
||||
} elseif ($prototype) {
|
||||
self::$instance = new HTMLPurifier($prototype);
|
||||
$htmlpurifier = new HTMLPurifier(HTMLPurifier_Config::create($prototype));
|
||||
} else {
|
||||
self::$instance = new HTMLPurifier();
|
||||
$htmlpurifier = new HTMLPurifier();
|
||||
}
|
||||
}
|
||||
return self::$instance;
|
||||
return $htmlpurifier;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,182 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file was auto-generated by generate-includes.php and includes all of
|
||||
* the core files required by HTML Purifier. This is a convenience stub that
|
||||
* includes all files using dirname(__FILE__) and require_once. PLEASE DO NOT
|
||||
* EDIT THIS FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* Changes to include_path are not necessary.
|
||||
*/
|
||||
|
||||
$__dir = dirname(__FILE__);
|
||||
|
||||
require_once $__dir . '/HTMLPurifier.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrCollections.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTypes.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrValidator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Bootstrap.php';
|
||||
require_once $__dir . '/HTMLPurifier/Definition.php';
|
||||
require_once $__dir . '/HTMLPurifier/CSSDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/Config.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigSchema.php';
|
||||
require_once $__dir . '/HTMLPurifier/ContentSets.php';
|
||||
require_once $__dir . '/HTMLPurifier/Context.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCacheFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Doctype.php';
|
||||
require_once $__dir . '/HTMLPurifier/DoctypeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/ElementDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/Encoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/EntityLookup.php';
|
||||
require_once $__dir . '/HTMLPurifier/EntityParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/Error.php';
|
||||
require_once $__dir . '/HTMLPurifier/ErrorCollector.php';
|
||||
require_once $__dir . '/HTMLPurifier/Exception.php';
|
||||
require_once $__dir . '/HTMLPurifier/Filter.php';
|
||||
require_once $__dir . '/HTMLPurifier/Generator.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModuleManager.php';
|
||||
require_once $__dir . '/HTMLPurifier/IDAccumulator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector.php';
|
||||
require_once $__dir . '/HTMLPurifier/Language.php';
|
||||
require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer.php';
|
||||
require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHash.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHashParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token.php';
|
||||
require_once $__dir . '/HTMLPurifier/TokenFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIDefinition.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme.php';
|
||||
require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParserException.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/AlphaValue.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Background.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Border.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Color.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Composite.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BdoDir.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BgColor.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/BoolToCSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Border.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/EnumToCSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgRequired.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ImgSpace.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Empty.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Table.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef/Directive.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef/DirectiveAlias.php';
|
||||
require_once $__dir . '/HTMLPurifier/ConfigDef/Namespace.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Null.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Serializer.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php';
|
||||
require_once $__dir . '/HTMLPurifier/DefinitionCache/Decorator/Memory.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Bdo.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Edit.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Image.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/List.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Strict.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/Transitional.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy/XHTML.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/AutoParagraph.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/Linkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Composite.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Core.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/MakeWellFormed.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/RemoveForeignElements.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/ValidateAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform/Font.php';
|
||||
require_once $__dir . '/HTMLPurifier/TagTransform/Simple.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Comment.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Tag.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Empty.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/End.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Start.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/http.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/news.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/nntp.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Flexible.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Native.php';
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrTypes.php';
|
||||
|
||||
/**
|
||||
* Defines common attribute collections that modules reference
|
||||
*/
|
||||
@@ -10,7 +12,7 @@ class HTMLPurifier_AttrCollections
|
||||
/**
|
||||
* Associative array of attribute collections, indexed by name
|
||||
*/
|
||||
public $info = array();
|
||||
var $info = array();
|
||||
|
||||
/**
|
||||
* Performs all expansions on internal data for use by other inclusions
|
||||
@@ -19,7 +21,7 @@ class HTMLPurifier_AttrCollections
|
||||
* @param $attr_types HTMLPurifier_AttrTypes instance
|
||||
* @param $modules Hash array of HTMLPurifier_HTMLModule members
|
||||
*/
|
||||
public function __construct($attr_types, $modules) {
|
||||
function HTMLPurifier_AttrCollections($attr_types, $modules) {
|
||||
// load extensions from the modules
|
||||
foreach ($modules as $module) {
|
||||
foreach ($module->attr_collections as $coll_i => $coll) {
|
||||
@@ -51,7 +53,7 @@ class HTMLPurifier_AttrCollections
|
||||
* all inclusions specified by the zero index.
|
||||
* @param &$attr Reference to attribute array
|
||||
*/
|
||||
public function performInclusions(&$attr) {
|
||||
function performInclusions(&$attr) {
|
||||
if (!isset($attr[0])) return;
|
||||
$merge = $attr[0];
|
||||
$seen = array(); // recursion guard
|
||||
@@ -79,7 +81,7 @@ class HTMLPurifier_AttrCollections
|
||||
* @param &$attr Reference to attribute array
|
||||
* @param $attr_types HTMLPurifier_AttrTypes instance
|
||||
*/
|
||||
public function expandIdentifiers(&$attr, $attr_types) {
|
||||
function expandIdentifiers(&$attr, $attr_types) {
|
||||
|
||||
// because foreach will process new elements we add, make sure we
|
||||
// skip duplicates
|
||||
@@ -125,3 +127,4 @@ class HTMLPurifier_AttrCollections
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -10,29 +10,32 @@
|
||||
* subclasses are also responsible for cleaning the code if possible.
|
||||
*/
|
||||
|
||||
abstract class HTMLPurifier_AttrDef
|
||||
class HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is minimized. Has no
|
||||
* meaning in other contexts.
|
||||
*/
|
||||
public $minimized = false;
|
||||
var $minimized = false;
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is required. Has no
|
||||
* meaning in other contexts
|
||||
*/
|
||||
public $required = false;
|
||||
var $required = false;
|
||||
|
||||
/**
|
||||
* Validates and cleans passed string according to a definition.
|
||||
*
|
||||
* @public
|
||||
* @param $string String to be validated and cleaned.
|
||||
* @param $config Mandatory HTMLPurifier_Config object.
|
||||
* @param $context Mandatory HTMLPurifier_AttrContext object.
|
||||
*/
|
||||
abstract public function validate($string, $config, $context);
|
||||
function validate($string, $config, &$context) {
|
||||
trigger_error('Cannot call abstract function', E_USER_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that parses a string as if it were CDATA.
|
||||
@@ -56,8 +59,10 @@ abstract class HTMLPurifier_AttrDef
|
||||
* function. Trim and whitespace collapsing are supposed to only
|
||||
* occur in NMTOKENs. However, note that we are NOT necessarily
|
||||
* parsing XML, thus, this behavior may still be correct.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
public function parseCDATA($string) {
|
||||
function parseCDATA($string) {
|
||||
$string = trim($string);
|
||||
$string = str_replace("\n", '', $string);
|
||||
$string = str_replace(array("\r", "\t"), ' ', $string);
|
||||
@@ -68,21 +73,15 @@ abstract class HTMLPurifier_AttrDef
|
||||
* Factory method for creating this class from a string.
|
||||
* @param $string String construction info
|
||||
* @return Created AttrDef object corresponding to $string
|
||||
* @public
|
||||
*/
|
||||
public function make($string) {
|
||||
function make($string) {
|
||||
// default implementation, return flyweight of this object
|
||||
// if overloaded, it is *necessary* for you to clone the
|
||||
// object (usually by instantiating a new copy) and return that
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
|
||||
* properly. THIS IS A HACK!
|
||||
*/
|
||||
protected function mungeRgb($string) {
|
||||
return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/CSSDefinition.php';
|
||||
|
||||
/**
|
||||
* Validates the HTML attribute style, otherwise known as CSS.
|
||||
* @note We don't implement the whole CSS specification, so it might be
|
||||
@@ -14,7 +17,7 @@
|
||||
class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($css, $config, $context) {
|
||||
function validate($css, $config, &$context) {
|
||||
|
||||
$css = $this->parseCDATA($css);
|
||||
|
||||
@@ -35,20 +38,7 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
list($property, $value) = explode(':', $declaration, 2);
|
||||
$property = trim($property);
|
||||
$value = trim($value);
|
||||
$ok = false;
|
||||
do {
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
if (ctype_lower($property)) break;
|
||||
$property = strtolower($property);
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
if (!$ok) continue;
|
||||
if (!isset($definition->info[$property])) continue;
|
||||
// inefficient call, since the validator will do this again
|
||||
if (strtolower(trim($value)) !== 'inherit') {
|
||||
// inherit works for everything (but only on the base property)
|
||||
@@ -76,3 +66,4 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(false); // opacity is non-negative, but we will clamp it
|
||||
}
|
||||
|
||||
public function validate($number, $config, $context) {
|
||||
$result = parent::validate($number, $config, $context);
|
||||
if ($result === false) return $result;
|
||||
$float = (float) $result;
|
||||
if ($float < 0.0) $result = '0';
|
||||
if ($float > 1.0) $result = '1';
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/CSSDefinition.php';
|
||||
|
||||
/**
|
||||
* Validates shorthand CSS property background.
|
||||
* @warning Does not support url tokens that have internal spaces.
|
||||
@@ -11,9 +14,9 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
* Local copy of component validators.
|
||||
* @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
var $info;
|
||||
|
||||
public function __construct($config) {
|
||||
function HTMLPurifier_AttrDef_CSS_Background($config) {
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['background-color'] = $def->info['background-color'];
|
||||
$this->info['background-image'] = $def->info['background-image'];
|
||||
@@ -22,15 +25,12 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
$this->info['background-position'] = $def->info['background-position'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') return false;
|
||||
|
||||
// munge rgb() decl if necessary
|
||||
$string = $this->mungeRgb($string);
|
||||
|
||||
// assumes URI doesn't have spaces in it
|
||||
$bits = explode(' ', strtolower($string)); // bits to process
|
||||
|
||||
@@ -84,3 +84,4 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require_once 'HTMLPurifier/AttrDef/CSS/Percentage.php';
|
||||
|
||||
/* W3C says:
|
||||
[ // adjective and number must be in correct order, even if
|
||||
// you could switch them without introducing ambiguity.
|
||||
@@ -44,15 +48,15 @@
|
||||
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $length;
|
||||
protected $percentage;
|
||||
var $length;
|
||||
var $percentage;
|
||||
|
||||
public function __construct() {
|
||||
function HTMLPurifier_AttrDef_CSS_BackgroundPosition() {
|
||||
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
|
||||
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
$string = $this->parseCDATA($string);
|
||||
$bits = explode(' ', $string);
|
||||
|
||||
@@ -123,3 +127,4 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates the border property as defined by CSS.
|
||||
*/
|
||||
@@ -9,18 +11,18 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||
/**
|
||||
* Local copy of properties this property is shorthand for.
|
||||
*/
|
||||
protected $info = array();
|
||||
var $info = array();
|
||||
|
||||
public function __construct($config) {
|
||||
function HTMLPurifier_AttrDef_CSS_Border($config) {
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['border-width'] = $def->info['border-width'];
|
||||
$this->info['border-style'] = $def->info['border-style'];
|
||||
$this->info['border-top-color'] = $def->info['border-top-color'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
$string = $this->parseCDATA($string);
|
||||
$string = $this->mungeRgb($string);
|
||||
// we specifically will not support rgb() syntax with spaces
|
||||
$bits = explode(' ', $string);
|
||||
$done = array(); // segments we've finished
|
||||
$ret = ''; // return value
|
||||
@@ -40,3 +42,4 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,24 +1,58 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Core', 'ColorKeywords', array(
|
||||
'maroon' => '#800000',
|
||||
'red' => '#FF0000',
|
||||
'orange' => '#FFA500',
|
||||
'yellow' => '#FFFF00',
|
||||
'olive' => '#808000',
|
||||
'purple' => '#800080',
|
||||
'fuchsia' => '#FF00FF',
|
||||
'white' => '#FFFFFF',
|
||||
'lime' => '#00FF00',
|
||||
'green' => '#008000',
|
||||
'navy' => '#000080',
|
||||
'blue' => '#0000FF',
|
||||
'aqua' => '#00FFFF',
|
||||
'teal' => '#008080',
|
||||
'black' => '#000000',
|
||||
'silver' => '#C0C0C0',
|
||||
'gray' => '#808080'
|
||||
), 'hash', '
|
||||
Lookup array of color names to six digit hexadecimal number corresponding
|
||||
to color, with preceding hash mark. Used when parsing colors.
|
||||
This directive has been available since 2.0.0.
|
||||
');
|
||||
|
||||
/**
|
||||
* Validates Color as defined by CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($color, $config, $context) {
|
||||
function validate($color, $config, &$context) {
|
||||
|
||||
static $colors = null;
|
||||
if ($colors === null) $colors = $config->get('Core', 'ColorKeywords');
|
||||
|
||||
$color = trim($color);
|
||||
if ($color === '') return false;
|
||||
if (!$color) return false;
|
||||
|
||||
$lower = strtolower($color);
|
||||
if (isset($colors[$lower])) return $colors[$lower];
|
||||
|
||||
if (strpos($color, 'rgb(') !== false) {
|
||||
if ($color[0] === '#') {
|
||||
// hexadecimal handling
|
||||
$hex = substr($color, 1);
|
||||
$length = strlen($hex);
|
||||
if ($length !== 3 && $length !== 6) return false;
|
||||
if (!ctype_xdigit($hex)) return false;
|
||||
} else {
|
||||
// rgb literal handling
|
||||
if (strpos($color, 'rgb(')) return false;
|
||||
$length = strlen($color);
|
||||
if (strpos($color, ')') !== $length - 1) return false;
|
||||
$triad = substr($color, 4, $length - 4 - 1);
|
||||
@@ -56,17 +90,6 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||
}
|
||||
$new_triad = implode(',', $new_parts);
|
||||
$color = "rgb($new_triad)";
|
||||
} else {
|
||||
// hexadecimal handling
|
||||
if ($color[0] === '#') {
|
||||
$hex = substr($color, 1);
|
||||
} else {
|
||||
$hex = $color;
|
||||
$color = '#' . $color;
|
||||
}
|
||||
$length = strlen($hex);
|
||||
if ($length !== 3 && $length !== 6) return false;
|
||||
if (!ctype_xdigit($hex)) return false;
|
||||
}
|
||||
|
||||
return $color;
|
||||
@@ -75,3 +98,4 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -14,18 +14,18 @@ class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* List of HTMLPurifier_AttrDef objects that may process strings
|
||||
* @todo Make protected
|
||||
* @protected
|
||||
*/
|
||||
public $defs;
|
||||
var $defs;
|
||||
|
||||
/**
|
||||
* @param $defs List of HTMLPurifier_AttrDef objects
|
||||
*/
|
||||
public function __construct($defs) {
|
||||
function HTMLPurifier_AttrDef_CSS_Composite($defs) {
|
||||
$this->defs = $defs;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
foreach ($this->defs as $i => $def) {
|
||||
$result = $this->defs[$i]->validate($string, $config, $context);
|
||||
if ($result !== false) return $result;
|
||||
@@ -35,3 +35,4 @@ class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Microsoft's proprietary filter: CSS property
|
||||
* @note Currently supports the alpha filter. In the future, this will
|
||||
* probably need an extensible framework
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $intValidator;
|
||||
|
||||
public function __construct() {
|
||||
$this->intValidator = new HTMLPurifier_AttrDef_Integer();
|
||||
}
|
||||
|
||||
public function validate($value, $config, $context) {
|
||||
$value = $this->parseCDATA($value);
|
||||
if ($value === 'none') return $value;
|
||||
// if we looped this we could support multiple filters
|
||||
$function_length = strcspn($value, '(');
|
||||
$function = trim(substr($value, 0, $function_length));
|
||||
if ($function !== 'alpha' &&
|
||||
$function !== 'Alpha' &&
|
||||
$function !== 'progid:DXImageTransform.Microsoft.Alpha'
|
||||
) return false;
|
||||
$cursor = $function_length + 1;
|
||||
$parameters_length = strcspn($value, ')', $cursor);
|
||||
$parameters = substr($value, $cursor, $parameters_length);
|
||||
$params = explode(',', $parameters);
|
||||
$ret_params = array();
|
||||
$lookup = array();
|
||||
foreach ($params as $param) {
|
||||
list($key, $value) = explode('=', $param);
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
if (isset($lookup[$key])) continue;
|
||||
if ($key !== 'opacity') continue;
|
||||
$value = $this->intValidator->validate($value, $config, $context);
|
||||
if ($value === false) continue;
|
||||
$int = (int) $value;
|
||||
if ($int > 100) $value = '100';
|
||||
if ($int < 0) $value = '0';
|
||||
$ret_params[] = "$key=$value";
|
||||
$lookup[$key] = true;
|
||||
}
|
||||
$ret_parameters = implode(',', $ret_params);
|
||||
$ret_function = "$function($ret_parameters)";
|
||||
return $ret_function;
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates shorthand CSS property font.
|
||||
*/
|
||||
@@ -14,9 +16,9 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
* CSSDefinition, this wouldn't be necessary. We'd instantiate
|
||||
* our own copies.
|
||||
*/
|
||||
protected $info = array();
|
||||
var $info = array();
|
||||
|
||||
public function __construct($config) {
|
||||
function HTMLPurifier_AttrDef_CSS_Font($config) {
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['font-style'] = $def->info['font-style'];
|
||||
$this->info['font-variant'] = $def->info['font-variant'];
|
||||
@@ -26,7 +28,7 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
$this->info['font-family'] = $def->info['font-family'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
static $system_fonts = array(
|
||||
'caption' => true,
|
||||
@@ -146,3 +148,4 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,13 +1,16 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
// whitelisting allowed fonts would be nice
|
||||
|
||||
/**
|
||||
* Validates a font family list according to CSS spec
|
||||
* @todo whitelisting allowed fonts would be nice
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
static $generic_names = array(
|
||||
'serif' => true,
|
||||
'sans-serif' => true,
|
||||
@@ -35,24 +38,19 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
$quote = $font[0];
|
||||
if ($font[$length - 1] !== $quote) continue;
|
||||
$font = substr($font, 1, $length - 2);
|
||||
// double-backslash processing is buggy
|
||||
$font = str_replace("\\$quote", $quote, $font); // de-escape quote
|
||||
$font = str_replace("\\\n", "\n", $font); // de-escape newlines
|
||||
}
|
||||
// $font is a pure representation of the font name
|
||||
|
||||
// process font
|
||||
if (ctype_alnum($font)) {
|
||||
// very simple font, allow it in unharmed
|
||||
$final .= $font . ', ';
|
||||
continue;
|
||||
}
|
||||
|
||||
// complicated font, requires quoting
|
||||
|
||||
// armor single quotes and new lines
|
||||
$font = str_replace("'", "\\'", $font);
|
||||
$font = str_replace("\n", "\\\n", $font);
|
||||
$final .= "'$font', ";
|
||||
$nospace = str_replace(array(' ', '.', '!'), '', $font);
|
||||
if (ctype_alnum($nospace)) {
|
||||
// font with spaces in it
|
||||
$final .= "'$font', ";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$final = rtrim($final, ', ');
|
||||
if ($final === '') return false;
|
||||
@@ -61,3 +59,4 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Decorator which enables !important to be used in CSS values.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_ImportantDecorator
|
||||
{
|
||||
protected $def, $allow;
|
||||
|
||||
/**
|
||||
* @param $def Definition to wrap
|
||||
* @param $allow Whether or not to allow !important
|
||||
*/
|
||||
public function __construct($def, $allow = false) {
|
||||
$this->def = $def;
|
||||
$this->allow = $allow;
|
||||
}
|
||||
/**
|
||||
* Intercepts and removes !important if necessary
|
||||
*/
|
||||
public function validate($string, $config, $context) {
|
||||
// test for ! and important tokens
|
||||
$string = trim($string);
|
||||
$is_important = false;
|
||||
// :TODO: optimization: test directly for !important and ! important
|
||||
if (strlen($string) >= 9 && substr($string, -9) === 'important') {
|
||||
$temp = rtrim(substr($string, 0, -9));
|
||||
// use a temp, because we might want to restore important
|
||||
if (strlen($temp) >= 1 && substr($temp, -1) === '!') {
|
||||
$string = rtrim(substr($temp, 0, -1));
|
||||
$is_important = true;
|
||||
}
|
||||
}
|
||||
$string = $this->def->validate($string, $config, $context);
|
||||
if ($this->allow && $is_important) $string .= ' !important';
|
||||
return $string;
|
||||
}
|
||||
}
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
|
||||
/**
|
||||
* Represents a Length as defined by CSS.
|
||||
*/
|
||||
@@ -11,22 +14,22 @@ class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
|
||||
* @warning The code assumes all units are two characters long. Be careful
|
||||
* if we have to change this behavior!
|
||||
*/
|
||||
protected $units = array('em' => true, 'ex' => true, 'px' => true, 'in' => true,
|
||||
var $units = array('em' => true, 'ex' => true, 'px' => true, 'in' => true,
|
||||
'cm' => true, 'mm' => true, 'pt' => true, 'pc' => true);
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_Number to defer number validation to
|
||||
*/
|
||||
protected $number_def;
|
||||
var $number_def;
|
||||
|
||||
/**
|
||||
* @param $non_negative Bool indication whether or not negative values are
|
||||
* allowed.
|
||||
*/
|
||||
public function __construct($non_negative = false) {
|
||||
function HTMLPurifier_AttrDef_CSS_Length($non_negative = false) {
|
||||
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
|
||||
}
|
||||
|
||||
public function validate($length, $config, $context) {
|
||||
function validate($length, $config, &$context) {
|
||||
|
||||
$length = $this->parseCDATA($length);
|
||||
if ($length === '') return false;
|
||||
@@ -50,3 +53,4 @@ class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates shorthand CSS property list-style.
|
||||
* @warning Does not support url tokens that have internal spaces.
|
||||
@@ -11,16 +13,16 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
|
||||
* Local copy of component validators.
|
||||
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
var $info;
|
||||
|
||||
public function __construct($config) {
|
||||
function HTMLPurifier_AttrDef_CSS_ListStyle($config) {
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['list-style-type'] = $def->info['list-style-type'];
|
||||
$this->info['list-style-position'] = $def->info['list-style-position'];
|
||||
$this->info['list-style-image'] = $def->info['list-style-image'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
@@ -75,3 +77,4 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Framework class for strings that involve multiple values.
|
||||
*
|
||||
@@ -16,26 +18,24 @@ class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* Instance of component definition to defer validation to.
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $single;
|
||||
var $single;
|
||||
|
||||
/**
|
||||
* Max number of values allowed.
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $max;
|
||||
var $max;
|
||||
|
||||
/**
|
||||
* @param $single HTMLPurifier_AttrDef to multiply
|
||||
* @param $max Max number of values allowed (usually four)
|
||||
*/
|
||||
public function __construct($single, $max = 4) {
|
||||
function HTMLPurifier_AttrDef_CSS_Multiple($single, $max = 4) {
|
||||
$this->single = $single;
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') return false;
|
||||
$parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
|
||||
@@ -55,3 +55,4 @@ class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -9,21 +9,20 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
/**
|
||||
* Bool indicating whether or not only positive values allowed.
|
||||
*/
|
||||
protected $non_negative = false;
|
||||
var $non_negative = false;
|
||||
|
||||
/**
|
||||
* @param $non_negative Bool indicating whether negatives are forbidden
|
||||
*/
|
||||
public function __construct($non_negative = false) {
|
||||
function HTMLPurifier_AttrDef_CSS_Number($non_negative = false) {
|
||||
$this->non_negative = $non_negative;
|
||||
}
|
||||
|
||||
public function validate($number, $config, $context) {
|
||||
function validate($number, $config, &$context) {
|
||||
|
||||
$number = $this->parseCDATA($number);
|
||||
|
||||
if ($number === '') return false;
|
||||
if ($number === '0') return '0';
|
||||
|
||||
$sign = '';
|
||||
switch ($number[0]) {
|
||||
@@ -38,16 +37,13 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
$number = ltrim($number, '0');
|
||||
return $number ? $sign . $number : '0';
|
||||
}
|
||||
|
||||
// Period is the only non-numeric character allowed
|
||||
if (strpos($number, '.') === false) return false;
|
||||
if (!strpos($number, '.')) return false;
|
||||
|
||||
list($left, $right) = explode('.', $number, 2);
|
||||
|
||||
if ($left === '' && $right === '') return false;
|
||||
if ($left !== '' && !ctype_digit($left)) return false;
|
||||
if (!ctype_digit($left)) return false;
|
||||
$left = ltrim($left, '0');
|
||||
|
||||
$left = ltrim($left, '0');
|
||||
$right = rtrim($right, '0');
|
||||
|
||||
if ($right === '') {
|
||||
@@ -62,3 +58,4 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/AttrDef/CSS/Number.php';
|
||||
|
||||
/**
|
||||
* Validates a Percentage as defined by the CSS spec.
|
||||
*/
|
||||
@@ -9,16 +12,16 @@ class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_CSS_Number to defer number validation
|
||||
*/
|
||||
protected $number_def;
|
||||
var $number_def;
|
||||
|
||||
/**
|
||||
* @param Bool indicating whether to forbid negative values
|
||||
*/
|
||||
public function __construct($non_negative = false) {
|
||||
function HTMLPurifier_AttrDef_CSS_Percentage($non_negative = false) {
|
||||
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
$string = $this->parseCDATA($string);
|
||||
|
||||
@@ -37,3 +40,4 @@ class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates the value for the CSS property text-decoration
|
||||
* @note This class could be generalized into a version that acts sort of
|
||||
@@ -8,7 +10,7 @@
|
||||
class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
static $allowed_values = array(
|
||||
'line-through' => true,
|
||||
@@ -32,3 +34,4 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef/URI.php';
|
||||
|
||||
/**
|
||||
* Validates a URI in CSS syntax, which uses url('http://example.com')
|
||||
* @note While theoretically speaking a URI in a CSS document could
|
||||
@@ -12,11 +14,11 @@
|
||||
class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(true); // always embedded
|
||||
function HTMLPurifier_AttrDef_CSS_URI() {
|
||||
$this->HTMLPurifier_AttrDef_URI(true); // always embedded
|
||||
}
|
||||
|
||||
public function validate($uri_string, $config, $context) {
|
||||
function validate($uri_string, $config, &$context) {
|
||||
// parse the URI out of the string and then pass it onto
|
||||
// the parent object
|
||||
|
||||
@@ -53,3 +55,4 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
// Enum = Enumerated
|
||||
/**
|
||||
* Validates a keyword against a list of valid values.
|
||||
@@ -12,28 +14,27 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* Lookup table of valid values.
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $valid_values = array();
|
||||
var $valid_values = array();
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not enumeration is case sensitive.
|
||||
* @note In general this is always case insensitive.
|
||||
*/
|
||||
protected $case_sensitive = false; // values according to W3C spec
|
||||
var $case_sensitive = false; // values according to W3C spec
|
||||
|
||||
/**
|
||||
* @param $valid_values List of valid values
|
||||
* @param $case_sensitive Bool indicating whether or not case sensitive
|
||||
*/
|
||||
public function __construct(
|
||||
function HTMLPurifier_AttrDef_Enum(
|
||||
$valid_values = array(), $case_sensitive = false
|
||||
) {
|
||||
$this->valid_values = array_flip($valid_values);
|
||||
$this->case_sensitive = $case_sensitive;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
$string = trim($string);
|
||||
if (!$this->case_sensitive) {
|
||||
// we may want to do full case-insensitive libraries
|
||||
@@ -49,7 +50,7 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
* valid values. Example: "foo,bar,baz". Prepend "s:" to make
|
||||
* case sensitive
|
||||
*/
|
||||
public function make($string) {
|
||||
function make($string) {
|
||||
if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
|
||||
$string = substr($string, 2);
|
||||
$sensitive = true;
|
||||
@@ -62,3 +63,4 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,17 +1,19 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates a boolean attribute
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $name;
|
||||
public $minimized = true;
|
||||
var $name;
|
||||
var $minimized = true;
|
||||
|
||||
public function __construct($name = false) {$this->name = $name;}
|
||||
function HTMLPurifier_AttrDef_HTML_Bool($name = false) {$this->name = $name;}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
if (empty($string)) return false;
|
||||
return $this->name;
|
||||
}
|
||||
@@ -19,9 +21,10 @@ class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
|
||||
/**
|
||||
* @param $string Name of attribute
|
||||
*/
|
||||
public function make($string) {
|
||||
function make($string) {
|
||||
return new HTMLPurifier_AttrDef_HTML_Bool($string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,12 +1,15 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/AttrDef/CSS/Color.php'; // for %Core.ColorKeywords
|
||||
|
||||
/**
|
||||
* Validates a color according to the HTML spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
static $colors = null;
|
||||
if ($colors === null) $colors = $config->get('Core', 'ColorKeywords');
|
||||
@@ -29,3 +32,4 @@ class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,20 +1,34 @@
|
||||
<?php
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Attr', 'AllowedFrameTargets', array(), 'lookup',
|
||||
'Lookup table of all allowed link frame targets. Some commonly used '.
|
||||
'link targets include _blank, _self, _parent and _top. Values should '.
|
||||
'be lowercase, as validation will be done in a case-sensitive manner '.
|
||||
'despite W3C\'s recommendation. XHTML 1.0 Strict does not permit '.
|
||||
'the target attribute so this directive will have no effect in that '.
|
||||
'doctype. XHTML 1.1 does not enable the Target module by default, you '.
|
||||
'will have to manually enable it (see the module documentation for more details.)'
|
||||
);
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef/Enum.php';
|
||||
|
||||
/**
|
||||
* Special-case enum attribute definition that lazy loads allowed frame targets
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
|
||||
{
|
||||
|
||||
public $valid_values = false; // uninitialized value
|
||||
protected $case_sensitive = false;
|
||||
var $valid_values = false; // uninitialized value
|
||||
var $case_sensitive = false;
|
||||
|
||||
public function __construct() {}
|
||||
function HTMLPurifier_AttrDef_HTML_FrameTarget() {}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
if ($this->valid_values === false) $this->valid_values = $config->get('Attr', 'AllowedFrameTargets');
|
||||
return parent::validate($string, $config, $context);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,56 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/IDAccumulator.php';
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Attr', 'EnableID', false, 'bool',
|
||||
'Allows the ID attribute in HTML. This is disabled by default '.
|
||||
'due to the fact that without proper configuration user input can '.
|
||||
'easily break the validation of a webpage by specifying an ID that is '.
|
||||
'already on the surrounding HTML. If you don\'t mind throwing caution to '.
|
||||
'the wind, enable this directive, but I strongly recommend you also '.
|
||||
'consider blacklisting IDs you use (%Attr.IDBlacklist) or prefixing all '.
|
||||
'user supplied IDs (%Attr.IDPrefix). This directive has been available '.
|
||||
'since 1.2.0, and when set to true reverts to the behavior of pre-1.2.0 '.
|
||||
'versions.'
|
||||
);
|
||||
HTMLPurifier_ConfigSchema::defineAlias(
|
||||
'HTML', 'EnableAttrID', 'Attr', 'EnableID'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Attr', 'IDPrefix', '', 'string',
|
||||
'String to prefix to IDs. If you have no idea what IDs your pages '.
|
||||
'may use, you may opt to simply add a prefix to all user-submitted ID '.
|
||||
'attributes so that they are still usable, but will not conflict with '.
|
||||
'core page IDs. Example: setting the directive to \'user_\' will result in '.
|
||||
'a user submitted \'foo\' to become \'user_foo\' Be sure to set '.
|
||||
'%HTML.EnableAttrID to true before using '.
|
||||
'this. This directive was available since 1.2.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Attr', 'IDPrefixLocal', '', 'string',
|
||||
'Temporary prefix for IDs used in conjunction with %Attr.IDPrefix. If '.
|
||||
'you need to allow multiple sets of '.
|
||||
'user content on web page, you may need to have a seperate prefix that '.
|
||||
'changes with each iteration. This way, seperately submitted user content '.
|
||||
'displayed on the same page doesn\'t clobber each other. Ideal values '.
|
||||
'are unique identifiers for the content it represents (i.e. the id of '.
|
||||
'the row in the database). Be sure to add a seperator (like an underscore) '.
|
||||
'at the end. Warning: this directive will not work unless %Attr.IDPrefix '.
|
||||
'is set to a non-empty value! This directive was available since 1.2.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Attr', 'IDBlacklistRegexp', null, 'string/null',
|
||||
'PCRE regular expression to be matched against all IDs. If the expression '.
|
||||
'is matches, the ID is rejected. Use this with care: may cause '.
|
||||
'significant degradation. ID matching is done after all other '.
|
||||
'validation. This directive was available since 1.6.0.'
|
||||
);
|
||||
|
||||
/**
|
||||
* Validates the HTML attribute ID.
|
||||
* @warning Even though this is the id processor, it
|
||||
@@ -15,7 +66,7 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
|
||||
// ref functionality disabled, since we also have to verify
|
||||
// whether or not the ID it refers to exists
|
||||
|
||||
public function validate($id, $config, $context) {
|
||||
function validate($id, $config, &$context) {
|
||||
|
||||
if (!$config->get('Attr', 'EnableID')) return false;
|
||||
|
||||
@@ -67,3 +118,4 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/AttrDef/HTML/Pixels.php';
|
||||
|
||||
/**
|
||||
* Validates the HTML type length (not to be confused with CSS's length).
|
||||
*
|
||||
@@ -10,7 +13,7 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
$string = trim($string);
|
||||
if ($string === '') return false;
|
||||
@@ -38,3 +41,4 @@ class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,22 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Attr', 'AllowedRel', array(), 'lookup',
|
||||
'List of allowed forward document relationships in the rel attribute. '.
|
||||
'Common values may be nofollow or print. By default, this is empty, '.
|
||||
'meaning that no document relationships are allowed. This directive '.
|
||||
'was available since 1.6.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'Attr', 'AllowedRev', array(), 'lookup',
|
||||
'List of allowed reverse document relationships in the rev attribute. '.
|
||||
'This attribute is a bit of an edge-case; if you don\'t know what it '.
|
||||
'is for, stay away. This directive was available since 1.6.0.'
|
||||
);
|
||||
|
||||
/**
|
||||
* Validates a rel/rev link attribute against a directive of allowed values
|
||||
* @note We cannot use Enum because link types allow multiple
|
||||
@@ -10,9 +27,9 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/** Name config attribute to pull. */
|
||||
protected $name;
|
||||
var $name;
|
||||
|
||||
public function __construct($name) {
|
||||
function HTMLPurifier_AttrDef_HTML_LinkTypes($name) {
|
||||
$configLookup = array(
|
||||
'rel' => 'AllowedRel',
|
||||
'rev' => 'AllowedRev'
|
||||
@@ -25,7 +42,7 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
|
||||
$this->name = $configLookup[$name];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
$allowed = $config->get('Attr', $this->name);
|
||||
if (empty($allowed)) return false;
|
||||
@@ -53,3 +70,4 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/AttrDef/HTML/Length.php';
|
||||
|
||||
/**
|
||||
* Validates a MultiLength as defined by the HTML spec.
|
||||
*
|
||||
@@ -9,7 +12,7 @@
|
||||
class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
$string = trim($string);
|
||||
if ($string === '') return false;
|
||||
@@ -38,3 +41,4 @@ class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Le
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/Config.php';
|
||||
|
||||
/**
|
||||
* Validates contents based on NMTOKENS attribute type.
|
||||
* @note The only current use for this is the class attribute in HTML
|
||||
@@ -10,7 +13,7 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
$string = trim($string);
|
||||
|
||||
@@ -45,3 +48,4 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,12 +1,14 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates an integer representation of pixels according to the HTML spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
$string = trim($string);
|
||||
if ($string === '0') return $string;
|
||||
@@ -32,3 +34,4 @@ class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates an integer.
|
||||
* @note While this class was modeled off the CSS definition, no currently
|
||||
@@ -13,24 +15,24 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
|
||||
/**
|
||||
* Bool indicating whether or not negative values are allowed
|
||||
*/
|
||||
protected $negative = true;
|
||||
var $negative = true;
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not zero is allowed
|
||||
*/
|
||||
protected $zero = true;
|
||||
var $zero = true;
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not positive values are allowed
|
||||
*/
|
||||
protected $positive = true;
|
||||
var $positive = true;
|
||||
|
||||
/**
|
||||
* @param $negative Bool indicating whether or not negative values are allowed
|
||||
* @param $zero Bool indicating whether or not zero is allowed
|
||||
* @param $positive Bool indicating whether or not positive values are allowed
|
||||
*/
|
||||
public function __construct(
|
||||
function HTMLPurifier_AttrDef_Integer(
|
||||
$negative = true, $zero = true, $positive = true
|
||||
) {
|
||||
$this->negative = $negative;
|
||||
@@ -38,7 +40,7 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
|
||||
$this->positive = $positive;
|
||||
}
|
||||
|
||||
public function validate($integer, $config, $context) {
|
||||
function validate($integer, $config, &$context) {
|
||||
|
||||
$integer = $this->parseCDATA($integer);
|
||||
if ($integer === '') return false;
|
||||
@@ -70,3 +72,4 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates the HTML attribute lang, effectively a language code.
|
||||
* @note Built according to RFC 3066, which obsoleted RFC 1766
|
||||
@@ -7,7 +9,7 @@
|
||||
class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
|
||||
$string = trim($string);
|
||||
if (!$string) return false;
|
||||
@@ -70,3 +72,4 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,14 +1,17 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates arbitrary text according to the HTML spec.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
return $this->parseCDATA($string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,90 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/URIScheme.php';
|
||||
require_once 'HTMLPurifier/URISchemeRegistry.php';
|
||||
require_once 'HTMLPurifier/AttrDef/URI/Host.php';
|
||||
require_once 'HTMLPurifier/PercentEncoder.php';
|
||||
|
||||
HTMLPurifier_ConfigSchema::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.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'Host', null, 'string/null',
|
||||
'Defines the domain name of the server, so we can determine whether or '.
|
||||
'an absolute URI is from your website or not. Not strictly necessary, '.
|
||||
'as users should be using relative URIs to reference resources on your '.
|
||||
'website. It will, however, let you use absolute URIs to link to '.
|
||||
'subdomains of the domain you post here: i.e. example.com will allow '.
|
||||
'sub.example.com. However, higher up domains will still be excluded: '.
|
||||
'if you set %URI.Host to sub.example.com, example.com will be blocked. '.
|
||||
'This directive has been available since 1.2.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'DisableExternal', false, 'bool',
|
||||
'Disables links to external websites. This is a highly effective '.
|
||||
'anti-spam and anti-pagerank-leech measure, but comes at a hefty price: no'.
|
||||
'links or images outside of your domain will be allowed. Non-linkified '.
|
||||
'URIs will still be preserved. If you want to be able to link to '.
|
||||
'subdomains or use absolute URIs, specify %URI.Host for your website. '.
|
||||
'This directive has been available since 1.2.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'DisableExternalResources', false, 'bool',
|
||||
'Disables the embedding of external resources, preventing users from '.
|
||||
'embedding things like images from other hosts. This prevents '.
|
||||
'access tracking (good for email viewers), bandwidth leeching, '.
|
||||
'cross-site request forging, goatse.cx posting, and '.
|
||||
'other nasties, but also results in '.
|
||||
'a loss of end-user functionality (they can\'t directly post a pic '.
|
||||
'they posted from Flickr anymore). Use it if you don\'t have a '.
|
||||
'robust user-content moderation team. This directive has been '.
|
||||
'available since 1.3.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'DisableResources', false, 'bool',
|
||||
'Disables embedding resources, essentially meaning no pictures. You can '.
|
||||
'still link to them though. See %URI.DisableExternalResources for why '.
|
||||
'this might be a good idea. This directive has been available since 1.3.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'Munge', null, 'string/null',
|
||||
'Munges all browsable (usually http, https and ftp) URI\'s into some URL '.
|
||||
'redirection service. Pass this directive a URI, with %s inserted where '.
|
||||
'the url-encoded original URI should be inserted (sample: '.
|
||||
'<code>http://www.google.com/url?q=%s</code>). '.
|
||||
'This prevents PageRank leaks, while being as transparent as possible '.
|
||||
'to users (you may also want to add some client side JavaScript to '.
|
||||
'override the text in the statusbar). Warning: many security experts '.
|
||||
'believe that this form of protection does not deter spam-bots. '.
|
||||
'You can also use this directive to redirect users to a splash page '.
|
||||
'telling them they are leaving your website. '.
|
||||
'This directive has been available since 1.3.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'HostBlacklist', array(), 'list',
|
||||
'List of strings that are forbidden in the host of any URI. Use it to '.
|
||||
'kill domain names of spam, etc. Note that it will catch anything in '.
|
||||
'the domain, so <tt>moo.com</tt> will catch <tt>moo.com.example.com</tt>. '.
|
||||
'This directive has been available since 1.3.0.'
|
||||
);
|
||||
|
||||
HTMLPurifier_ConfigSchema::define(
|
||||
'URI', 'Disable', false, 'bool',
|
||||
'Disables all URIs in all forms. Not sure why you\'d want to do that '.
|
||||
'(after all, the Internet\'s founded on the notion of a hyperlink). '.
|
||||
'This directive has been available since 1.3.0.'
|
||||
);
|
||||
HTMLPurifier_ConfigSchema::defineAlias('Attr', 'DisableURI', 'URI', 'Disable');
|
||||
|
||||
/**
|
||||
* Validates a URI as defined by RFC 3986.
|
||||
* @note Scheme-specific mechanics deferred to HTMLPurifier_URIScheme
|
||||
@@ -7,83 +92,214 @@
|
||||
class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $parser, $percentEncoder;
|
||||
protected $embedsResource;
|
||||
var $host;
|
||||
var $embeds_resource;
|
||||
|
||||
/**
|
||||
* @param $embeds_resource_resource Does the URI here result in an extra HTTP request?
|
||||
*/
|
||||
public function __construct($embeds_resource = false) {
|
||||
$this->parser = new HTMLPurifier_URIParser();
|
||||
$this->percentEncoder = new HTMLPurifier_PercentEncoder();
|
||||
$this->embedsResource = (bool) $embeds_resource;
|
||||
function HTMLPurifier_AttrDef_URI($embeds_resource = false) {
|
||||
$this->host = new HTMLPurifier_AttrDef_URI_Host();
|
||||
$this->embeds_resource = (bool) $embeds_resource;
|
||||
}
|
||||
|
||||
public function validate($uri, $config, $context) {
|
||||
function validate($uri, $config, &$context) {
|
||||
|
||||
static $PercentEncoder = null;
|
||||
if ($PercentEncoder === null) $PercentEncoder = new HTMLPurifier_PercentEncoder();
|
||||
|
||||
// We'll write stack-based parsers later, for now, use regexps to
|
||||
// get things working as fast as possible (irony)
|
||||
|
||||
if ($config->get('URI', 'Disable')) return false;
|
||||
|
||||
// initial operations
|
||||
// parse as CDATA
|
||||
$uri = $this->parseCDATA($uri);
|
||||
$uri = $this->percentEncoder->normalize($uri);
|
||||
|
||||
// parse the URI
|
||||
$uri = $this->parser->parse($uri);
|
||||
if ($uri === false) return false;
|
||||
// fix up percent-encoding
|
||||
$uri = $PercentEncoder->normalize($uri);
|
||||
|
||||
// add embedded flag to context for validators
|
||||
$context->register('EmbeddedURI', $this->embedsResource);
|
||||
// while it would be nice to use parse_url(), that's specifically
|
||||
// for HTTP and thus won't work for our generic URI parsing
|
||||
|
||||
$ok = false;
|
||||
do {
|
||||
|
||||
// generic validation
|
||||
$result = $uri->validate($config, $context);
|
||||
if (!$result) break;
|
||||
|
||||
// chained filtering
|
||||
$uri_def =& $config->getDefinition('URI');
|
||||
$result = $uri_def->filter($uri, $config, $context);
|
||||
if (!$result) break;
|
||||
|
||||
// scheme-specific validation
|
||||
$scheme_obj = $uri->getSchemeObj($config, $context);
|
||||
if (!$scheme_obj) break;
|
||||
if ($this->embedsResource && !$scheme_obj->browsable) break;
|
||||
$result = $scheme_obj->validate($uri, $config, $context);
|
||||
if (!$result) break;
|
||||
|
||||
// survived gauntlet
|
||||
$ok = true;
|
||||
|
||||
} while (false);
|
||||
// according to the RFC... (but this cuts corners, i.e. non-validating)
|
||||
$r_URI = '!'.
|
||||
'(([^:/?#<>\'"]+):)?'. // 2. Scheme
|
||||
'(//([^/?#<>\'"]*))?'. // 4. Authority
|
||||
'([^?#<>\'"]*)'. // 5. Path
|
||||
'(\?([^#<>\'"]*))?'. // 7. Query
|
||||
'(#([^<>\'"]*))?'. // 8. Fragment
|
||||
'!';
|
||||
|
||||
$context->destroy('EmbeddedURI');
|
||||
if (!$ok) return false;
|
||||
$matches = array();
|
||||
$result = preg_match($r_URI, $uri, $matches);
|
||||
|
||||
// munge scheme off if necessary (this must be last)
|
||||
if (!is_null($uri->scheme) && is_null($uri->host)) {
|
||||
if ($uri_def->defaultScheme == $uri->scheme) {
|
||||
$uri->scheme = null;
|
||||
}
|
||||
if (!$result) return false; // invalid URI
|
||||
|
||||
// seperate out parts
|
||||
$scheme = !empty($matches[1]) ? $matches[2] : null;
|
||||
$authority = !empty($matches[3]) ? $matches[4] : null;
|
||||
$path = $matches[5]; // always present, can be empty
|
||||
$query = !empty($matches[6]) ? $matches[7] : null;
|
||||
$fragment = !empty($matches[8]) ? $matches[9] : null;
|
||||
|
||||
|
||||
|
||||
$registry =& HTMLPurifier_URISchemeRegistry::instance();
|
||||
if ($scheme !== null) {
|
||||
// no need to validate the scheme's fmt since we do that when we
|
||||
// retrieve the specific scheme object from the registry
|
||||
$scheme = ctype_lower($scheme) ? $scheme : strtolower($scheme);
|
||||
$scheme_obj = $registry->getScheme($scheme, $config, $context);
|
||||
if (!$scheme_obj) return false; // invalid scheme, clean it out
|
||||
} else {
|
||||
$scheme_obj = $registry->getScheme(
|
||||
$config->get('URI', 'DefaultScheme'), $config, $context
|
||||
);
|
||||
}
|
||||
|
||||
// back to string
|
||||
$result = $uri->toString();
|
||||
// something funky weird happened in the registry, abort!
|
||||
if (!$scheme_obj) {
|
||||
trigger_error(
|
||||
'Default scheme object "' . $config->get('URI', 'DefaultScheme') . '" was not readable',
|
||||
E_USER_WARNING
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// munge entire URI if necessary
|
||||
if (
|
||||
!is_null($uri->host) && // indicator for authority
|
||||
!empty($scheme_obj->browsable) &&
|
||||
!is_null($munge = $config->get('URI', 'Munge'))
|
||||
) {
|
||||
$result = str_replace('%s', rawurlencode($result), $munge);
|
||||
// the URI we're processing embeds_resource a resource in the page, but the URI
|
||||
// it references cannot be located
|
||||
if ($this->embeds_resource && !$scheme_obj->browsable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ($authority !== null) {
|
||||
|
||||
// remove URI if it's absolute and we disabled externals or
|
||||
// if it's absolute and embedded and we disabled external resources
|
||||
unset($our_host);
|
||||
if (
|
||||
$config->get('URI', 'DisableExternal') ||
|
||||
(
|
||||
$config->get('URI', 'DisableExternalResources') &&
|
||||
$this->embeds_resource
|
||||
)
|
||||
) {
|
||||
$our_host = $config->get('URI', 'Host');
|
||||
if ($our_host === null) return false;
|
||||
}
|
||||
|
||||
$HEXDIG = '[A-Fa-f0-9]';
|
||||
$unreserved = 'A-Za-z0-9-._~'; // make sure you wrap with []
|
||||
$sub_delims = '!$&\'()'; // needs []
|
||||
$pct_encoded = "%$HEXDIG$HEXDIG";
|
||||
$r_userinfo = "(?:[$unreserved$sub_delims:]|$pct_encoded)*";
|
||||
$r_authority = "/^(($r_userinfo)@)?(\[[^\]]+\]|[^:]*)(:(\d*))?/";
|
||||
$matches = array();
|
||||
preg_match($r_authority, $authority, $matches);
|
||||
// overloads regexp!
|
||||
$userinfo = !empty($matches[1]) ? $matches[2] : null;
|
||||
$host = !empty($matches[3]) ? $matches[3] : null;
|
||||
$port = !empty($matches[4]) ? $matches[5] : null;
|
||||
|
||||
// validate port
|
||||
if ($port !== null) {
|
||||
$port = (int) $port;
|
||||
if ($port < 1 || $port > 65535) $port = null;
|
||||
}
|
||||
|
||||
$host = $this->host->validate($host, $config, $context);
|
||||
if ($host === false) $host = null;
|
||||
|
||||
if ($this->checkBlacklist($host, $config, $context)) return false;
|
||||
|
||||
// more lenient absolute checking
|
||||
if (isset($our_host)) {
|
||||
$host_parts = array_reverse(explode('.', $host));
|
||||
// could be cached
|
||||
$our_host_parts = array_reverse(explode('.', $our_host));
|
||||
foreach ($our_host_parts as $i => $discard) {
|
||||
if (!isset($host_parts[$i])) return false;
|
||||
if ($host_parts[$i] != $our_host_parts[$i]) return false;
|
||||
}
|
||||
}
|
||||
|
||||
// userinfo and host are validated within the regexp
|
||||
|
||||
} else {
|
||||
$port = $host = $userinfo = null;
|
||||
}
|
||||
|
||||
|
||||
// query and fragment are quite simple in terms of definition:
|
||||
// *( pchar / "/" / "?" ), so define their validation routines
|
||||
// when we start fixing percent encoding
|
||||
|
||||
|
||||
|
||||
// path gets to be validated against a hodge-podge of rules depending
|
||||
// on the status of authority and scheme, but it's not that important,
|
||||
// esp. since it won't be applicable to everyone
|
||||
|
||||
|
||||
|
||||
// okay, now we defer execution to the subobject for more processing
|
||||
// note that $fragment is omitted
|
||||
list($userinfo, $host, $port, $path, $query) =
|
||||
$scheme_obj->validateComponents(
|
||||
$userinfo, $host, $port, $path, $query, $config, $context
|
||||
);
|
||||
|
||||
|
||||
// reconstruct authority
|
||||
$authority = null;
|
||||
if (!is_null($userinfo) || !is_null($host) || !is_null($port)) {
|
||||
$authority = '';
|
||||
if($userinfo !== null) $authority .= $userinfo . '@';
|
||||
$authority .= $host;
|
||||
if($port !== null) $authority .= ':' . $port;
|
||||
}
|
||||
|
||||
// reconstruct the result
|
||||
$result = '';
|
||||
if ($scheme !== null) $result .= "$scheme:";
|
||||
if ($authority !== null) $result .= "//$authority";
|
||||
$result .= $path;
|
||||
if ($query !== null) $result .= "?$query";
|
||||
if ($fragment !== null) $result .= "#$fragment";
|
||||
|
||||
// munge if necessary
|
||||
$munge = $config->get('URI', 'Munge');
|
||||
if (!empty($scheme_obj->browsable) && $munge !== null) {
|
||||
if ($authority !== null) {
|
||||
$result = str_replace('%s', rawurlencode($result), $munge);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a host against an array blacklist
|
||||
* @param $host Host to check
|
||||
* @param $config HTMLPurifier_Config instance
|
||||
* @param $context HTMLPurifier_Context instance
|
||||
* @return bool Is spam?
|
||||
*/
|
||||
function checkBlacklist($host, &$config, &$context) {
|
||||
$blacklist = $config->get('URI', 'HostBlacklist');
|
||||
if (!empty($blacklist)) {
|
||||
foreach($blacklist as $blacklisted_host_fragment) {
|
||||
if (strpos($host, $blacklisted_host_fragment) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
@@ -12,4 +14,4 @@ abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
// sub-implementations
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef/URI/Email.php';
|
||||
|
||||
/**
|
||||
* Primitive email validation class based on the regexp found at
|
||||
* http://www.regular-expressions.info/email.html
|
||||
@@ -7,7 +9,7 @@
|
||||
class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_URI_Email
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
// no support for named mailboxes i.e. "Bob <bob@example.com>"
|
||||
// that needs more percent encoding to be done
|
||||
if ($string == '') return false;
|
||||
@@ -18,3 +20,4 @@ class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_UR
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
require_once 'HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||
require_once 'HTMLPurifier/AttrDef/URI/IPv6.php';
|
||||
|
||||
/**
|
||||
* Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
|
||||
*/
|
||||
@@ -9,19 +13,19 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator
|
||||
*/
|
||||
protected $ipv4;
|
||||
var $ipv4;
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator
|
||||
*/
|
||||
protected $ipv6;
|
||||
var $ipv6;
|
||||
|
||||
public function __construct() {
|
||||
function HTMLPurifier_AttrDef_URI_Host() {
|
||||
$this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
|
||||
$this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
function validate($string, $config, &$context) {
|
||||
$length = strlen($string);
|
||||
if ($string === '') return '';
|
||||
if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
|
||||
@@ -47,3 +51,4 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
|
||||
|
||||
}
|
||||
|
||||
?>
|
@@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
require_once 'HTMLPurifier/AttrDef.php';
|
||||
|
||||
/**
|
||||
* Validates an IPv4 address
|
||||
* @author Feyd @ forums.devnetwork.net (public domain)
|
||||
@@ -9,10 +11,11 @@ class HTMLPurifier_AttrDef_URI_IPv4 extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* IPv4 regex, protected so that IPv6 can reuse it
|
||||
* @protected
|
||||
*/
|
||||
protected $ip4;
|
||||
var $ip4;
|
||||
|
||||
public function validate($aIP, $config, $context) {
|
||||
function validate($aIP, $config, &$context) {
|
||||
|
||||
if (!$this->ip4) $this->_loadRegex();
|
||||
|
||||
@@ -29,10 +32,11 @@ class HTMLPurifier_AttrDef_URI_IPv4 extends HTMLPurifier_AttrDef
|
||||
* Lazy load function to prevent regex from being stuffed in
|
||||
* cache.
|
||||
*/
|
||||
protected function _loadRegex() {
|
||||
function _loadRegex() {
|
||||
$oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255
|
||||
$this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user