mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-08-06 22:26:31 +02:00
Compare commits
335 Commits
v2.1.0-str
...
v2.0.1
Author | SHA1 | Date | |
---|---|---|---|
|
45748500ec | ||
|
e99520ab96 | ||
|
1e2abb7f8f | ||
|
362c802191 | ||
|
3a1d505b3d | ||
|
a005da8a4c | ||
|
9a66394abb | ||
|
62c0575468 | ||
|
6a95d91a1a | ||
|
275932ec05 | ||
|
ae90bb919d | ||
|
3c734b4c72 | ||
|
3d02a2a7d4 | ||
|
0bfa42f9b7 | ||
|
7a8edc88f9 | ||
|
98b4e70a93 | ||
|
6f5592ae60 | ||
|
9f996b125a | ||
|
96b571d236 | ||
|
0e9904a9ba | ||
|
e66a98c396 | ||
|
728088f2ba | ||
|
8ae2604440 | ||
|
7b087c7bbe | ||
|
58064592ff | ||
|
b19fc32a5a | ||
|
b15cbbb42a | ||
|
5f0663cad7 | ||
|
75e52a12a6 | ||
|
269268b843 | ||
|
62c6d93b6d | ||
|
31704c92f6 | ||
|
291fa4cb29 | ||
|
389fcc9a5d | ||
|
e5191b3ada | ||
|
5d0a992579 | ||
|
ae83bebc98 | ||
|
9191877740 | ||
|
3066ca357a | ||
|
53fd096641 | ||
|
2166246b7e | ||
|
49bb6ec35d | ||
|
401612dc3a | ||
|
dc0fb7d2b4 | ||
|
eee45fed37 | ||
|
03657ad51a | ||
|
dda4038446 | ||
|
996ccdbdda | ||
|
008348db21 | ||
|
b10a380ff4 | ||
|
bf0d659c47 | ||
|
e55551ecdd | ||
|
e9f3fef47b | ||
|
840f9f7434 | ||
|
10c970760d | ||
|
69996acc9e | ||
|
8bbb73e47d | ||
|
cf7a50163c | ||
|
da2ea348fd | ||
|
ab3ebcba6d | ||
|
d399abba50 | ||
|
0b0a505c30 | ||
|
6aa3dfc116 | ||
|
c3094275ef | ||
|
220c150e0a | ||
|
32d30a9181 | ||
|
0e5491b20c | ||
|
7699efd593 | ||
|
4bf15de536 | ||
|
70bcccf54c | ||
|
bf6ce67fc1 | ||
|
bd44105ca9 | ||
|
d1f43636e5 | ||
|
9c7483166c | ||
|
e840564228 | ||
|
7d4b532d6b | ||
|
58f00105c8 | ||
|
8d15d1ce13 | ||
|
9c60eeed04 | ||
|
2e089477a5 | ||
|
b442d09ea6 | ||
|
12f73605a3 | ||
|
e2a951420f | ||
|
002395de09 | ||
|
d1187ed331 | ||
|
426fbd1f97 | ||
|
9c5f01a0cf | ||
|
f985d3cd96 | ||
|
0cb1d85822 | ||
|
073ddb0cb2 | ||
|
889ccb1a92 | ||
|
aec84dc3f6 | ||
|
dea62ffdab | ||
|
8913239b7f | ||
|
e06929c218 | ||
|
aaf4839c34 | ||
|
c113f43440 | ||
|
bd8ecdd268 | ||
|
ef51f8681a | ||
|
ee61ffc0d9 | ||
|
f758f7c534 | ||
|
95499e34da | ||
|
de23201cbb | ||
|
21ab12a6a8 | ||
|
69666e977f | ||
|
fa05319e30 | ||
|
ea46d79b0a | ||
|
a62f8971e4 | ||
|
7a3e06d4d0 | ||
|
e180b7689e | ||
|
7579932948 | ||
|
818d0d7a23 | ||
|
797d3e0393 | ||
|
ff7eec7424 | ||
|
0ea04db559 | ||
|
831db14c79 | ||
|
a470fc5621 | ||
|
2945f6a930 | ||
|
71326abec1 | ||
|
23ef535043 | ||
|
fda2043ace | ||
|
3f06d8316c | ||
|
e4b621eec2 | ||
|
9728be4a52 | ||
|
f1ec05afd0 | ||
|
7481d349d3 | ||
|
086dc9177b | ||
|
4d38c02932 | ||
|
83a50465dc | ||
|
dd62a303eb | ||
|
e4e981b6f1 | ||
|
a846f4e70b | ||
|
a5136b65e4 | ||
|
2d035483dd | ||
|
831a09d455 | ||
|
2cbb3be602 | ||
|
f7eccc0038 | ||
|
65252d6fbd | ||
|
6b9c5ec603 | ||
|
e7b15068c2 | ||
|
53c19552d2 | ||
|
048242004e | ||
|
05e1aca2fa | ||
|
23feb457f2 | ||
|
8f6380d63a | ||
|
3b1c40b2fc | ||
|
da92cb9ff4 | ||
|
bda9167423 | ||
|
cb9c96a2b0 | ||
|
e0cf214c44 | ||
|
ed73fdd5b8 | ||
|
eaea42f827 | ||
|
7f39e1e2c3 | ||
|
b81fb0af90 | ||
|
47fe34ad81 | ||
|
ac50d333a5 | ||
|
ce013e2962 | ||
|
67fab710bf | ||
|
b3a599e8c2 | ||
|
f4e4c1556d | ||
|
c5e33416d3 | ||
|
6c08ca4c16 | ||
|
b1822bb04f | ||
|
893e962890 | ||
|
bd6071cb3b | ||
|
92ea74cba2 | ||
|
a01459c87a | ||
|
fd35c43643 | ||
|
0426985c81 | ||
|
bbea02f55c | ||
|
4e77a1adbd | ||
|
bd58a7ba77 | ||
|
a3ed9196b9 | ||
|
2646f5ea57 | ||
|
424c7ad2e3 | ||
|
234b3085d7 | ||
|
3d978c961d | ||
|
72254cd77a | ||
|
d8a6361244 | ||
|
968dfa2feb | ||
|
114d6841ab | ||
|
1c68d769b5 | ||
|
ac0ca3f15c | ||
|
2d5498b8aa | ||
|
71ccae1a3a | ||
|
cb186dddc4 | ||
|
2ceccc0969 | ||
|
93aa98ad01 | ||
|
c0b38bab85 | ||
|
d6c4473a12 | ||
|
fc06f221d5 | ||
|
ac3ab2a556 | ||
|
2c330cac73 | ||
|
a0d6543b84 | ||
|
e223490a78 | ||
|
2666f067cc | ||
|
826a57a04a | ||
|
e08b5aaa70 | ||
|
b15e8c344e | ||
|
2c9e041b4c | ||
|
e2c3394d70 | ||
|
1532fe703a | ||
|
058f1eba7d | ||
|
1102dc6e27 | ||
|
85374d330f | ||
|
a16d6c4342 | ||
|
9b5e2978ad | ||
|
06468a4157 | ||
|
0167f8aa84 | ||
|
f1a90e684b | ||
|
14d98413fd | ||
|
97a4ec7598 | ||
|
71ed725c5c | ||
|
d4bf41288a | ||
|
365bd78c20 | ||
|
52fa958fb2 | ||
|
17d32bac7f | ||
|
e2babe5308 | ||
|
5f1a6b883f | ||
|
c5e3796202 | ||
|
72f1984229 | ||
|
918081b372 | ||
|
6c56dd070f | ||
|
299f93f8f0 | ||
|
4169846c57 | ||
|
aff4957531 | ||
|
e4bdf472a6 | ||
|
9a99750474 | ||
|
7eb751b5f5 | ||
|
0d0173eb6e | ||
|
556ed4ea90 | ||
|
cf445a6107 | ||
|
243ad45e59 | ||
|
31d0c621f5 | ||
|
0870974a25 | ||
|
5c4a0a6785 | ||
|
e55babdc53 | ||
|
6e1b540d99 | ||
|
edf20018f0 | ||
|
c09432e171 | ||
|
9c031b5c1e | ||
|
a827cbc3ba | ||
|
c05eebee15 | ||
|
93a69d020a | ||
|
f3fa9c01ba | ||
|
bae5b0c022 | ||
|
67befbc8a8 | ||
|
cac22f01cf | ||
|
94d2dbaa74 | ||
|
6add828bc8 | ||
|
800b67ed65 | ||
|
71e4ddd222 | ||
|
54a68a1713 | ||
|
bd544ad038 | ||
|
d5491da77f | ||
|
591fc0ae28 | ||
|
dac7ac1eae | ||
|
64ee756b7a | ||
|
e2103ce0f2 | ||
|
219902ebff | ||
|
21116373a7 | ||
|
5ed88809f3 | ||
|
bb8b38b1e0 | ||
|
236159242f | ||
|
9d8f839bf2 | ||
|
882148f9ad | ||
|
a863f62489 | ||
|
6478c7c2df | ||
|
129a4ea506 | ||
|
a122243a89 | ||
|
315c55eeb1 | ||
|
cfe50ff8ae | ||
|
d0018a2696 | ||
|
77d9e05a07 | ||
|
80243f377c | ||
|
43b157cf4d | ||
|
f6b50d4bfd | ||
|
806901cfd2 | ||
|
f90eef7f1f | ||
|
06867e14b6 | ||
|
bda2615b30 | ||
|
e1a5d10e75 | ||
|
98fd6b7d82 | ||
|
be264a4b20 | ||
|
01c85b71d2 | ||
|
2d22c0aa55 | ||
|
6e061f5184 | ||
|
44b988f1f6 | ||
|
0ead9558b4 | ||
|
159a1cced1 | ||
|
6871a54d64 | ||
|
96ac7e8797 | ||
|
2d49299621 | ||
|
ab5c782c77 | ||
|
8893b87e04 | ||
|
aeef746060 | ||
|
da13c6ac87 | ||
|
ccae73c25a | ||
|
8d6bfa4037 | ||
|
712d81ebea | ||
|
f7f6fed86a | ||
|
2293c67eec | ||
|
108df87824 | ||
|
5e366b25f8 | ||
|
2e16c4a968 | ||
|
a8db22dfff | ||
|
fbe2c25f8a | ||
|
158be61def | ||
|
d693c4ea09 | ||
|
c24916e1d6 | ||
|
a68b6afda1 | ||
|
78cf7db82e | ||
|
9b375fdfb8 | ||
|
0dd866cc15 | ||
|
ad1169c711 | ||
|
2816ae535f | ||
|
462d3ab72f | ||
|
cf1d868782 | ||
|
c705e17a58 | ||
|
1cce367950 | ||
|
61f852d429 | ||
|
3a73c2cf04 | ||
|
e75b676656 | ||
|
b53370efbf | ||
|
d60f345cab | ||
|
aefda60696 | ||
|
2ffa5d3135 | ||
|
23d3490d49 | ||
|
582ffc4143 | ||
|
d52189a19d | ||
|
02006d6e64 | ||
|
dcaa374dae | ||
|
e2cc37724b | ||
|
3ad6239dc3 | ||
|
663fb4e1b2 |
2
Doxyfile
2
Doxyfile
@@ -4,7 +4,7 @@
|
|||||||
# Project related configuration options
|
# Project related configuration options
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
PROJECT_NAME = HTML Purifier
|
PROJECT_NAME = HTML Purifier
|
||||||
PROJECT_NUMBER = 2.1.0
|
PROJECT_NUMBER = 2.0.1
|
||||||
OUTPUT_DIRECTORY = "C:/Documents and Settings/Edward/My Documents/My Webs/htmlpurifier/docs/doxygen"
|
OUTPUT_DIRECTORY = "C:/Documents and Settings/Edward/My Documents/My Webs/htmlpurifier/docs/doxygen"
|
||||||
CREATE_SUBDIRS = NO
|
CREATE_SUBDIRS = NO
|
||||||
OUTPUT_LANGUAGE = English
|
OUTPUT_LANGUAGE = English
|
||||||
|
12
INSTALL
12
INSTALL
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
Install
|
Install
|
||||||
How to install HTML Purifier
|
How to install HTML Purifier
|
||||||
|
|
||||||
@@ -8,8 +9,6 @@ down to the bottom of this INSTALL document to see the code, but you really
|
|||||||
should make sure a few things are properly done.
|
should make sure a few things are properly done.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
1. Compatibility
|
1. Compatibility
|
||||||
|
|
||||||
HTML Purifier works in both PHP 4 and PHP 5, from PHP 4.3.2 and up. It has no
|
HTML Purifier works in both PHP 4 and PHP 5, from PHP 4.3.2 and up. It has no
|
||||||
@@ -70,10 +69,6 @@ the doctype from this code in your HTML documents:
|
|||||||
For legacy codebases these declarations may be missing. If that is the case,
|
For legacy codebases these declarations may be missing. If that is the case,
|
||||||
STOP, and read docs/enduser-utf8.html
|
STOP, and read docs/enduser-utf8.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
You may currently be vulnerable to XSS and other security threats, and HTML
|
You may currently be vulnerable to XSS and other security threats, and HTML
|
||||||
Purifier won't be able to fix that.
|
Purifier won't be able to fix that.
|
||||||
|
|
||||||
@@ -123,9 +118,6 @@ reason, I do not include the solution in this document).
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
4.2. Setting a different doctype
|
4.2. Setting a different doctype
|
||||||
|
|
||||||
For those of you using HTML 4.01 Transitional, you can disable
|
For those of you using HTML 4.01 Transitional, you can disable
|
||||||
@@ -135,7 +127,6 @@ XHTML output like this:
|
|||||||
|
|
||||||
Other supported doctypes include:
|
Other supported doctypes include:
|
||||||
|
|
||||||
|
|
||||||
* HTML 4.01 Strict
|
* HTML 4.01 Strict
|
||||||
* HTML 4.01 Transitional
|
* HTML 4.01 Transitional
|
||||||
* XHTML 1.0 Strict
|
* XHTML 1.0 Strict
|
||||||
@@ -236,3 +227,4 @@ hit):
|
|||||||
Or move the cache directory somewhere else (no trailing slash):
|
Or move the cache directory somewhere else (no trailing slash):
|
||||||
|
|
||||||
$config->set('Cache', 'SerializerPath', '/home/user/absolute/path');
|
$config->set('Cache', 'SerializerPath', '/home/user/absolute/path');
|
||||||
|
|
||||||
|
4
NEWS
4
NEWS
@@ -159,8 +159,6 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
|||||||
%Attr.IDBlacklistRegexp
|
%Attr.IDBlacklistRegexp
|
||||||
- Error messages are emitted when you attempt to "allow" elements or
|
- Error messages are emitted when you attempt to "allow" elements or
|
||||||
attributes that HTML Purifier does not support
|
attributes that HTML Purifier does not support
|
||||||
|
|
||||||
|
|
||||||
- Fix segfault in unit test. The problem is not very reproduceable and
|
- 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.
|
I don't know what causes it, but a six line patch fixed it.
|
||||||
|
|
||||||
@@ -359,4 +357,4 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
|||||||
! First public release, most functionality implemented. Notable omissions are:
|
! First public release, most functionality implemented. Notable omissions are:
|
||||||
+ Shorthand CSS properties
|
+ Shorthand CSS properties
|
||||||
+ Table CSS properties
|
+ Table CSS properties
|
||||||
+ Deprecated attribute transformations
|
+ Deprecated attribute transformations
|
||||||
|
1
TODO
1
TODO
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
TODO List
|
TODO List
|
||||||
|
|
||||||
= KEY ====================
|
= KEY ====================
|
||||||
|
20
WHATSNEW
20
WHATSNEW
@@ -1,8 +1,12 @@
|
|||||||
In version 2.1, HTML Purifier's URI validation and filtering handling
|
The 2.0.1 release introduces a number of stability and usability fixes,
|
||||||
system has been revamped with a new, extensible URIFilter system. Also
|
as well as a number of (disabled by default) experimental features. The
|
||||||
notable features include preservation of emoticons in PHP5 with
|
security-minded should note that a reflected XSS vulnerability was patched
|
||||||
%Core.AggressivelyFixLt, standalone and lite download versions,
|
in smoketests/configForm.php; if you cannot upgrade immediately, please
|
||||||
transforming relative URIs to absolute URIs, Ruby in XHTML 1.1, a Phorum
|
delete that file (if that directory is not publically accessible, there
|
||||||
mod, and UTF-8 font names. Notable bug-fixes include refinement of
|
is no security risk). The maintenance changes include more helpful file
|
||||||
the auto-paragraphing algorithm (no longer experimental), better XHTML
|
permissions errors, internal newline normalization, reordered includes
|
||||||
1.1 support and the removal of the contents of <style> elements.
|
to prevent a missing class definition in some setups, and better cache
|
||||||
|
revision and id handling. The two experimental features are auto-formatting
|
||||||
|
(auto-paragraphing and linkification) and error collection, these can
|
||||||
|
be enabled with %AutoFormat.AutoParagraph, %AutoFormat.Linkify and
|
||||||
|
%Core.CollectErrors respectively.
|
||||||
|
@@ -18,8 +18,6 @@ TODO:
|
|||||||
if (version_compare('5', PHP_VERSION, '>')) exit('Requires PHP 5 or higher.');
|
if (version_compare('5', PHP_VERSION, '>')) exit('Requires PHP 5 or higher.');
|
||||||
error_reporting(E_ALL); // probably not possible to use E_STRICT
|
error_reporting(E_ALL); // probably not possible to use E_STRICT
|
||||||
|
|
||||||
define('HTMLPURIFIER_SCHEMA_STRICT', true); // description data needs to be collected
|
|
||||||
|
|
||||||
// load dual-libraries
|
// load dual-libraries
|
||||||
require_once '../library/HTMLPurifier.auto.php';
|
require_once '../library/HTMLPurifier.auto.php';
|
||||||
require_once 'library/ConfigDoc.auto.php';
|
require_once 'library/ConfigDoc.auto.php';
|
||||||
|
@@ -11,7 +11,8 @@ docs/examples/demo.php - ad hoc HTML/PHP soup to the extreme
|
|||||||
|
|
||||||
AttrDef - a lot of duplication, more generic classes need to be created;
|
AttrDef - a lot of duplication, more generic classes need to be created;
|
||||||
a lot of strtolower() calls, no legit casing
|
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
|
Lang - code duplication; premature optimization
|
||||||
Length - easily mistaken for CSSLength
|
Length - easily mistaken for CSSLength
|
||||||
URI - multiple regular expressions; missing validation for parts (?)
|
URI - multiple regular expressions; missing validation for parts (?)
|
||||||
@@ -21,6 +22,9 @@ ConfigSchema - redefinition is a mess
|
|||||||
Strategy
|
Strategy
|
||||||
FixNesting - cannot bubble nodes out of structures, duplicated checks
|
FixNesting - cannot bubble nodes out of structures, duplicated checks
|
||||||
for special-case parent node
|
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
|
RemoveForeignElements - should be run in parallel with MakeWellFormed
|
||||||
URIScheme - needs to have callable generic checks
|
URIScheme - needs to have callable generic checks
|
||||||
mailto - doesn't validate emails, doesn't validate querystring
|
mailto - doesn't validate emails, doesn't validate querystring
|
||||||
|
@@ -10,7 +10,9 @@ to be effective. Things to remember:
|
|||||||
|
|
||||||
2. IDs: see enduser-id.html for more info
|
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
|
4. CSS: document pending
|
||||||
Explain which CSS styles we blocked and why.
|
Explain which CSS styles we blocked and why.
|
||||||
|
@@ -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
|
|
||||||
{
|
|
||||||
var $name = '<strong>NameOfFilter</strong>';
|
|
||||||
function prepare($config) {}
|
|
||||||
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
|
|
||||||
{
|
|
||||||
var $scheme, $userinfo, $host, $port, $path, $query, $fragment;
|
|
||||||
function HTMLPurifier_URI($scheme, $userinfo, $host, $port, $path, $query, $fragment);
|
|
||||||
function toString();
|
|
||||||
function copy();
|
|
||||||
function getSchemeObj($config, &$context);
|
|
||||||
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
|
|
||||||
{
|
|
||||||
var $name = 'ConvertIDNToPunycode';
|
|
||||||
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>
|
|
@@ -40,9 +40,6 @@ information for casual developers using HTML Purifier.</p>
|
|||||||
<dt><a href="enduser-customize.html">Customize</a></dt>
|
<dt><a href="enduser-customize.html">Customize</a></dt>
|
||||||
<dd>Tutorial for customizing HTML Purifier's tag and attribute sets.</dd>
|
<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>
|
</dl>
|
||||||
|
|
||||||
<h2>Development</h2>
|
<h2>Development</h2>
|
||||||
|
@@ -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
|
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
|
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).
|
make forbidden element to text transformations desirable (for example, images).
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2,8 +2,7 @@
|
|||||||
Configuration Ideas
|
Configuration Ideas
|
||||||
|
|
||||||
Here are some theoretical configuration ideas that we could implement some
|
Here are some theoretical configuration ideas that we could implement some
|
||||||
time. Note the naming convention: %Namespace.Directive. If you want one
|
time. Note the naming convention: %Namespace.Directive
|
||||||
implemented, give us a ring, and we'll move it up the priority chain.
|
|
||||||
|
|
||||||
%Attr.RewriteFragments - if there's %Attr.IDPrefix we may want to transparently
|
%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
|
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
|
%URI.AddRelNofollow - will add rel="nofollow" to all links, preventing the
|
||||||
spread of ill-gotten pagerank
|
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.HostBlacklistRegex - regexes that if matching the host are disallowed
|
||||||
%URI.HostWhitelist - domain names that are excluded from the host blacklist
|
%URI.HostWhitelist - domain names that are excluded from the host blacklist
|
||||||
%URI.HostPolicy - determines whether or not its reject all and then whitelist
|
%URI.HostPolicy - determines whether or not its reject all and then whitelist
|
||||||
|
@@ -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 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;}
|
.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 */
|
/* Category of the file */
|
||||||
#filing {font-weight:bold; font-size:smaller; }
|
#filing {font-weight:bold; font-size:smaller; }
|
||||||
|
|
||||||
|
@@ -93,8 +93,11 @@ class HTMLPurifier_Config
|
|||||||
* or a string filename of an ini file.
|
* or a string filename of an ini file.
|
||||||
* @return Configured HTMLPurifier_Config object
|
* @return Configured HTMLPurifier_Config object
|
||||||
*/
|
*/
|
||||||
static function create($config) {
|
function create($config) {
|
||||||
if ($config instanceof HTMLPurifier_Config) return $config;
|
if (is_a($config, 'HTMLPurifier_Config')) {
|
||||||
|
// pass-through
|
||||||
|
return $config;
|
||||||
|
}
|
||||||
$ret = HTMLPurifier_Config::createDefault();
|
$ret = HTMLPurifier_Config::createDefault();
|
||||||
if (is_string($config)) $ret->loadIni($config);
|
if (is_string($config)) $ret->loadIni($config);
|
||||||
elseif (is_array($config)) $ret->loadArray($config);
|
elseif (is_array($config)) $ret->loadArray($config);
|
||||||
@@ -107,7 +110,7 @@ class HTMLPurifier_Config
|
|||||||
* @static
|
* @static
|
||||||
* @return Default HTMLPurifier_Config object.
|
* @return Default HTMLPurifier_Config object.
|
||||||
*/
|
*/
|
||||||
static function createDefault() {
|
function createDefault() {
|
||||||
$definition =& HTMLPurifier_ConfigSchema::instance();
|
$definition =& HTMLPurifier_ConfigSchema::instance();
|
||||||
$config = new HTMLPurifier_Config($definition);
|
$config = new HTMLPurifier_Config($definition);
|
||||||
return $config;
|
return $config;
|
||||||
@@ -347,7 +350,7 @@ class HTMLPurifier_Config
|
|||||||
* @param $allowed List of allowed namespaces/directives
|
* @param $allowed List of allowed namespaces/directives
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function getAllowedDirectivesForForm($allowed) {
|
function getAllowedDirectivesForForm($allowed) {
|
||||||
$schema = HTMLPurifier_ConfigSchema::instance();
|
$schema = HTMLPurifier_ConfigSchema::instance();
|
||||||
if ($allowed !== true) {
|
if ($allowed !== true) {
|
||||||
if (is_string($allowed)) $allowed = array($allowed);
|
if (is_string($allowed)) $allowed = array($allowed);
|
||||||
@@ -392,7 +395,7 @@ class HTMLPurifier_Config
|
|||||||
* @param $mq_fix Boolean whether or not to enable magic quotes fix
|
* @param $mq_fix Boolean whether or not to enable magic quotes fix
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function loadArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
|
function loadArrayFromForm($array, $index, $allowed = true, $mq_fix = true) {
|
||||||
$array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
|
$array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
|
||||||
$mq = get_magic_quotes_gpc() && $mq_fix;
|
$mq = get_magic_quotes_gpc() && $mq_fix;
|
||||||
|
|
||||||
|
@@ -78,7 +78,7 @@ class HTMLPurifier_ConfigSchema {
|
|||||||
* Retrieves an instance of the application-wide configuration definition.
|
* Retrieves an instance of the application-wide configuration definition.
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function &instance($prototype = null) {
|
function &instance($prototype = null) {
|
||||||
static $instance;
|
static $instance;
|
||||||
if ($prototype !== null) {
|
if ($prototype !== null) {
|
||||||
$instance = $prototype;
|
$instance = $prototype;
|
||||||
@@ -100,7 +100,7 @@ class HTMLPurifier_ConfigSchema {
|
|||||||
* HTMLPurifier_DirectiveDef::$type for allowed values
|
* HTMLPurifier_DirectiveDef::$type for allowed values
|
||||||
* @param $description Description of directive for documentation
|
* @param $description Description of directive for documentation
|
||||||
*/
|
*/
|
||||||
static function define(
|
function define(
|
||||||
$namespace, $name, $default, $type,
|
$namespace, $name, $default, $type,
|
||||||
$description
|
$description
|
||||||
) {
|
) {
|
||||||
@@ -164,7 +164,7 @@ class HTMLPurifier_ConfigSchema {
|
|||||||
* @param $namespace Namespace's name
|
* @param $namespace Namespace's name
|
||||||
* @param $description Description of the namespace
|
* @param $description Description of the namespace
|
||||||
*/
|
*/
|
||||||
static function defineNamespace($namespace, $description) {
|
function defineNamespace($namespace, $description) {
|
||||||
$def =& HTMLPurifier_ConfigSchema::instance();
|
$def =& HTMLPurifier_ConfigSchema::instance();
|
||||||
if (isset($def->info[$namespace])) {
|
if (isset($def->info[$namespace])) {
|
||||||
trigger_error('Cannot redefine namespace', E_USER_ERROR);
|
trigger_error('Cannot redefine namespace', E_USER_ERROR);
|
||||||
@@ -197,7 +197,7 @@ class HTMLPurifier_ConfigSchema {
|
|||||||
* @param $alias Name of aliased value
|
* @param $alias Name of aliased value
|
||||||
* @param $real Value aliased value will be converted into
|
* @param $real Value aliased value will be converted into
|
||||||
*/
|
*/
|
||||||
static function defineValueAliases($namespace, $name, $aliases) {
|
function defineValueAliases($namespace, $name, $aliases) {
|
||||||
$def =& HTMLPurifier_ConfigSchema::instance();
|
$def =& HTMLPurifier_ConfigSchema::instance();
|
||||||
if (!isset($def->info[$namespace][$name])) {
|
if (!isset($def->info[$namespace][$name])) {
|
||||||
trigger_error('Cannot set value alias for non-existant directive',
|
trigger_error('Cannot set value alias for non-existant directive',
|
||||||
@@ -228,7 +228,7 @@ class HTMLPurifier_ConfigSchema {
|
|||||||
* @param $name Name of directive
|
* @param $name Name of directive
|
||||||
* @param $allowed_values Arraylist of allowed values
|
* @param $allowed_values Arraylist of allowed values
|
||||||
*/
|
*/
|
||||||
static function defineAllowedValues($namespace, $name, $allowed_values) {
|
function defineAllowedValues($namespace, $name, $allowed_values) {
|
||||||
$def =& HTMLPurifier_ConfigSchema::instance();
|
$def =& HTMLPurifier_ConfigSchema::instance();
|
||||||
if (!isset($def->info[$namespace][$name])) {
|
if (!isset($def->info[$namespace][$name])) {
|
||||||
trigger_error('Cannot define allowed values for undefined directive',
|
trigger_error('Cannot define allowed values for undefined directive',
|
||||||
@@ -265,7 +265,7 @@ class HTMLPurifier_ConfigSchema {
|
|||||||
* @param $new_namespace
|
* @param $new_namespace
|
||||||
* @param $new_name Directive that the alias will be to
|
* @param $new_name Directive that the alias will be to
|
||||||
*/
|
*/
|
||||||
static function defineAlias($namespace, $name, $new_namespace, $new_name) {
|
function defineAlias($namespace, $name, $new_namespace, $new_name) {
|
||||||
$def =& HTMLPurifier_ConfigSchema::instance();
|
$def =& HTMLPurifier_ConfigSchema::instance();
|
||||||
if (!isset($def->info[$namespace])) {
|
if (!isset($def->info[$namespace])) {
|
||||||
trigger_error('Cannot define directive alias in undefined namespace',
|
trigger_error('Cannot define directive alias in undefined namespace',
|
||||||
@@ -399,7 +399,7 @@ class HTMLPurifier_ConfigSchema {
|
|||||||
*/
|
*/
|
||||||
function isError($var) {
|
function isError($var) {
|
||||||
if (!is_object($var)) return false;
|
if (!is_object($var)) return false;
|
||||||
if (!($var instanceof HTMLPurifier_Error)) return false;
|
if (!is_a($var, 'HTMLPurifier_Error')) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,7 +24,7 @@ class HTMLPurifier_DefinitionCache_Null extends HTMLPurifier_DefinitionCache
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function flush($config) {
|
function flush() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,7 +40,7 @@ class HTMLPurifier_DefinitionCacheFactory
|
|||||||
* Retrieves an instance of global definition cache factory.
|
* Retrieves an instance of global definition cache factory.
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function &instance($prototype = null) {
|
function &instance($prototype = null) {
|
||||||
static $instance;
|
static $instance;
|
||||||
if ($prototype !== null) {
|
if ($prototype !== null) {
|
||||||
$instance = $prototype;
|
$instance = $prototype;
|
||||||
|
@@ -110,7 +110,7 @@ class HTMLPurifier_ElementDef
|
|||||||
* Low-level factory constructor for creating new standalone element defs
|
* Low-level factory constructor for creating new standalone element defs
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function create($safe, $content_model, $content_model_type, $attr) {
|
function create($safe, $content_model, $content_model_type, $attr) {
|
||||||
$def = new HTMLPurifier_ElementDef();
|
$def = new HTMLPurifier_ElementDef();
|
||||||
$def->safe = (bool) $safe;
|
$def->safe = (bool) $safe;
|
||||||
$def->content_model = $content_model;
|
$def->content_model = $content_model;
|
||||||
|
@@ -88,7 +88,7 @@ class HTMLPurifier_Encoder
|
|||||||
* would need that, and I'm probably not going to implement them.
|
* would need that, and I'm probably not going to implement them.
|
||||||
* Once again, PHP 6 should solve all our problems.
|
* Once again, PHP 6 should solve all our problems.
|
||||||
*/
|
*/
|
||||||
static function cleanUTF8($str, $force_php = false) {
|
function cleanUTF8($str, $force_php = false) {
|
||||||
|
|
||||||
static $non_sgml_chars = array();
|
static $non_sgml_chars = array();
|
||||||
if (empty($non_sgml_chars)) {
|
if (empty($non_sgml_chars)) {
|
||||||
@@ -271,7 +271,7 @@ class HTMLPurifier_Encoder
|
|||||||
// | 00000000 | 00010000 | 11111111 | 11111111 | Defined upper limit of legal scalar codes
|
// | 00000000 | 00010000 | 11111111 | 11111111 | Defined upper limit of legal scalar codes
|
||||||
// +----------+----------+----------+----------+
|
// +----------+----------+----------+----------+
|
||||||
|
|
||||||
static function unichr($code) {
|
function unichr($code) {
|
||||||
if($code > 1114111 or $code < 0 or
|
if($code > 1114111 or $code < 0 or
|
||||||
($code >= 55296 and $code <= 57343) ) {
|
($code >= 55296 and $code <= 57343) ) {
|
||||||
// bits are set outside the "valid" range as defined
|
// bits are set outside the "valid" range as defined
|
||||||
@@ -312,7 +312,7 @@ class HTMLPurifier_Encoder
|
|||||||
* Converts a string to UTF-8 based on configuration.
|
* Converts a string to UTF-8 based on configuration.
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function convertToUTF8($str, $config, &$context) {
|
function convertToUTF8($str, $config, &$context) {
|
||||||
static $iconv = null;
|
static $iconv = null;
|
||||||
if ($iconv === null) $iconv = function_exists('iconv');
|
if ($iconv === null) $iconv = function_exists('iconv');
|
||||||
$encoding = $config->get('Core', 'Encoding');
|
$encoding = $config->get('Core', 'Encoding');
|
||||||
@@ -331,7 +331,7 @@ class HTMLPurifier_Encoder
|
|||||||
* @note Currently, this is a lossy conversion, with unexpressable
|
* @note Currently, this is a lossy conversion, with unexpressable
|
||||||
* characters being omitted.
|
* characters being omitted.
|
||||||
*/
|
*/
|
||||||
static function convertFromUTF8($str, $config, &$context) {
|
function convertFromUTF8($str, $config, &$context) {
|
||||||
static $iconv = null;
|
static $iconv = null;
|
||||||
if ($iconv === null) $iconv = function_exists('iconv');
|
if ($iconv === null) $iconv = function_exists('iconv');
|
||||||
$encoding = $config->get('Core', 'Encoding');
|
$encoding = $config->get('Core', 'Encoding');
|
||||||
@@ -364,7 +364,7 @@ class HTMLPurifier_Encoder
|
|||||||
* @note Sort of with cleanUTF8() but it assumes that $str is
|
* @note Sort of with cleanUTF8() but it assumes that $str is
|
||||||
* well-formed UTF-8
|
* well-formed UTF-8
|
||||||
*/
|
*/
|
||||||
static function convertToASCIIDumbLossless($str) {
|
function convertToASCIIDumbLossless($str) {
|
||||||
$bytesleft = 0;
|
$bytesleft = 0;
|
||||||
$result = '';
|
$result = '';
|
||||||
$working = 0;
|
$working = 0;
|
||||||
|
@@ -29,7 +29,7 @@ class HTMLPurifier_EntityLookup {
|
|||||||
* @static
|
* @static
|
||||||
* @param Optional prototype of custom lookup table to overload with.
|
* @param Optional prototype of custom lookup table to overload with.
|
||||||
*/
|
*/
|
||||||
static function instance($prototype = false) {
|
function instance($prototype = false) {
|
||||||
// no references, since PHP doesn't copy unless modified
|
// no references, since PHP doesn't copy unless modified
|
||||||
static $instance = null;
|
static $instance = null;
|
||||||
if ($prototype) {
|
if ($prototype) {
|
||||||
|
@@ -74,12 +74,12 @@ class HTMLPurifier_Injector
|
|||||||
/**
|
/**
|
||||||
* Handler that is called when a text token is processed
|
* Handler that is called when a text token is processed
|
||||||
*/
|
*/
|
||||||
function handleText(&$token, $config, &$context) {}
|
function handleText(&$token) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler that is called when a start token is processed
|
* Handler that is called when a start token is processed
|
||||||
*/
|
*/
|
||||||
function handleStart(&$token, $config, &$context) {}
|
function handleStart(&$token) {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
|
|||||||
return $par;
|
return $par;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleText(&$token, $config, &$context) {
|
function handleText(&$token) {
|
||||||
$text = $token->data;
|
$text = $token->data;
|
||||||
if (empty($this->currentNesting)) {
|
if (empty($this->currentNesting)) {
|
||||||
if (!$this->allowsElement('p')) return;
|
if (!$this->allowsElement('p')) return;
|
||||||
@@ -79,7 +79,7 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleStart(&$token, $config, &$context) {
|
function handleStart(&$token) {
|
||||||
// check if we're inside a tag already
|
// check if we're inside a tag already
|
||||||
if (!empty($this->currentNesting)) {
|
if (!empty($this->currentNesting)) {
|
||||||
if ($this->allowsElement('p')) {
|
if ($this->allowsElement('p')) {
|
||||||
|
@@ -113,7 +113,7 @@ class HTMLPurifier_Language
|
|||||||
$generator = false;
|
$generator = false;
|
||||||
foreach ($args as $i => $value) {
|
foreach ($args as $i => $value) {
|
||||||
if (is_object($value)) {
|
if (is_object($value)) {
|
||||||
if ($value instanceof HTMLPurifier_Token) {
|
if (is_a($value, 'HTMLPurifier_Token')) {
|
||||||
// factor this out some time
|
// factor this out some time
|
||||||
if (!$generator) $generator = $this->context->get('Generator');
|
if (!$generator) $generator = $this->context->get('Generator');
|
||||||
if (isset($value->name)) $subst['$'.$i.'.Name'] = $value->name;
|
if (isset($value->name)) $subst['$'.$i.'.Name'] = $value->name;
|
||||||
|
@@ -65,7 +65,7 @@ class HTMLPurifier_LanguageFactory
|
|||||||
* @param $prototype Optional prototype to overload sole instance with,
|
* @param $prototype Optional prototype to overload sole instance with,
|
||||||
* or bool true to reset to default factory.
|
* or bool true to reset to default factory.
|
||||||
*/
|
*/
|
||||||
static function &instance($prototype = null) {
|
function &instance($prototype = null) {
|
||||||
static $instance = null;
|
static $instance = null;
|
||||||
if ($prototype !== null) {
|
if ($prototype !== null) {
|
||||||
$instance = $prototype;
|
$instance = $prototype;
|
||||||
|
@@ -135,9 +135,9 @@ class HTMLPurifier_Lexer
|
|||||||
* @param $prototype Optional prototype lexer or configuration object
|
* @param $prototype Optional prototype lexer or configuration object
|
||||||
* @return Concrete lexer.
|
* @return Concrete lexer.
|
||||||
*/
|
*/
|
||||||
static function create($config) {
|
function create($config) {
|
||||||
|
|
||||||
if (!($config instanceof HTMLPurifier_Config)) {
|
if (!is_a($config, 'HTMLPurifier_Config')) {
|
||||||
$lexer = $config;
|
$lexer = $config;
|
||||||
trigger_error("Passing a prototype to
|
trigger_error("Passing a prototype to
|
||||||
HTMLPurifier_Lexer::create() is deprecated, please instead
|
HTMLPurifier_Lexer::create() is deprecated, please instead
|
||||||
@@ -262,7 +262,7 @@ class HTMLPurifier_Lexer
|
|||||||
* @param $string HTML string to process.
|
* @param $string HTML string to process.
|
||||||
* @returns HTML with CDATA sections escaped.
|
* @returns HTML with CDATA sections escaped.
|
||||||
*/
|
*/
|
||||||
static function escapeCDATA($string) {
|
function escapeCDATA($string) {
|
||||||
return preg_replace_callback(
|
return preg_replace_callback(
|
||||||
'/<!\[CDATA\[(.+?)\]\]>/s',
|
'/<!\[CDATA\[(.+?)\]\]>/s',
|
||||||
array('HTMLPurifier_Lexer', 'CDATACallback'),
|
array('HTMLPurifier_Lexer', 'CDATACallback'),
|
||||||
@@ -291,7 +291,7 @@ class HTMLPurifier_Lexer
|
|||||||
* and 1 the inside of the CDATA section.
|
* and 1 the inside of the CDATA section.
|
||||||
* @returns Escaped internals of the CDATA section.
|
* @returns Escaped internals of the CDATA section.
|
||||||
*/
|
*/
|
||||||
static function CDATACallback($matches) {
|
function CDATACallback($matches) {
|
||||||
// not exactly sure why the character set is needed, but whatever
|
// not exactly sure why the character set is needed, but whatever
|
||||||
return htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8');
|
return htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
@@ -40,7 +40,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
|
|||||||
* @param $matches, in form of array(opening tag, contents, closing tag)
|
* @param $matches, in form of array(opening tag, contents, closing tag)
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function scriptCallback($matches) {
|
function scriptCallback($matches) {
|
||||||
return $matches[1] . htmlspecialchars($matches[2], ENT_COMPAT, 'UTF-8') . $matches[3];
|
return $matches[1] . htmlspecialchars($matches[2], ENT_COMPAT, 'UTF-8') . $matches[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,7 +38,7 @@ class HTMLPurifier_URISchemeRegistry
|
|||||||
* @note Pass a registry object $prototype with a compatible interface and
|
* @note Pass a registry object $prototype with a compatible interface and
|
||||||
* the function will copy it and return it all further times.
|
* the function will copy it and return it all further times.
|
||||||
*/
|
*/
|
||||||
static function &instance($prototype = null) {
|
function &instance($prototype = null) {
|
||||||
static $instance = null;
|
static $instance = null;
|
||||||
if ($prototype !== null) {
|
if ($prototype !== null) {
|
||||||
$instance = $prototype;
|
$instance = $prototype;
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
function assertCli() {
|
|
||||||
if (php_sapi_name() != 'cli' && !getenv('PHP_IS_CLI')) {
|
|
||||||
echo 'Script cannot be called from web-browser (if you are calling via cli,
|
|
||||||
set environment variable PHP_IS_CLI to work around this).';
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once 'common.php';
|
|
||||||
assertCli();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Flushes the default HTMLDefinition serial cache
|
|
||||||
* @param Accepts one argument, cache type to flush; otherwise flushes all
|
|
||||||
* the caches.
|
|
||||||
*/
|
|
||||||
|
|
||||||
echo "Flushing cache... \n";
|
|
||||||
|
|
||||||
require_once(dirname(__FILE__) . '/../library/HTMLPurifier.auto.php');
|
|
||||||
|
|
||||||
$config = HTMLPurifier_Config::createDefault();
|
|
||||||
|
|
||||||
$names = array('HTML', 'CSS', 'URI', 'Test');
|
|
||||||
if (isset($argv[1])) {
|
|
||||||
if (in_array($argv[1], $names)) {
|
|
||||||
$names = array($argv[1]);
|
|
||||||
} else {
|
|
||||||
echo "Did not recognized cache parameter {$argv[1]} as valid cache, aborting.\n";
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($names as $name) {
|
|
||||||
echo " - Flushing $name\n";
|
|
||||||
$cache = new HTMLPurifier_DefinitionCache_Serializer($name);
|
|
||||||
$cache->flush($config);
|
|
||||||
}
|
|
||||||
|
|
||||||
echo 'Cache flushed successfully.';
|
|
||||||
|
|
23
maintenance/flush-htmldefinition-cache.php
Normal file
23
maintenance/flush-htmldefinition-cache.php
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flushes the default HTMLDefinition serial cache
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (php_sapi_name() != 'cli') {
|
||||||
|
echo 'Script cannot be called from web-browser.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'Flushing cache... ';
|
||||||
|
|
||||||
|
require_once(dirname(__FILE__) . '/../library/HTMLPurifier.auto.php');
|
||||||
|
|
||||||
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
|
|
||||||
|
$cache = new HTMLPurifier_DefinitionCache_Serializer('HTML');
|
||||||
|
$cache->flush($config);
|
||||||
|
|
||||||
|
echo 'Cache flushed successfully.';
|
||||||
|
|
8
maintenance/generate-entity-file.php
Executable file → Normal file
8
maintenance/generate-entity-file.php
Executable file → Normal file
@@ -1,14 +1,16 @@
|
|||||||
#!/usr/bin/php
|
#!/usr/bin/php
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once 'common.php';
|
|
||||||
assertCli();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses *.ent files into an entity lookup table, and then serializes and
|
* Parses *.ent files into an entity lookup table, and then serializes and
|
||||||
* writes the whole kaboodle to a file. The resulting file should be versioned.
|
* writes the whole kaboodle to a file. The resulting file should be versioned.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (php_sapi_name() != 'cli') {
|
||||||
|
echo 'Script cannot be called from web-browser.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
chdir( dirname(__FILE__) );
|
chdir( dirname(__FILE__) );
|
||||||
|
|
||||||
// here's where the entity files are located, assuming working directory
|
// here's where the entity files are located, assuming working directory
|
||||||
|
@@ -1,198 +0,0 @@
|
|||||||
#!/usr/bin/php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once 'common.php';
|
|
||||||
assertCli();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles all of HTML Purifier's library files into one big file
|
|
||||||
* named HTMLPurifier.standalone.php. Operates recursively, and will
|
|
||||||
* barf if there are conditional includes.
|
|
||||||
*
|
|
||||||
* Details: also creates blank "include" files in the test/blank directory
|
|
||||||
* in order to simulate require_once's inside the test files.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Global array that tracks already loaded includes
|
|
||||||
*/
|
|
||||||
$GLOBALS['loaded'] = array('HTMLPurifier.php' => true);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $text Text to replace includes from
|
|
||||||
*/
|
|
||||||
function replace_includes($text) {
|
|
||||||
return preg_replace_callback(
|
|
||||||
"/require_once ['\"]([^'\"]+)['\"];/",
|
|
||||||
'replace_includes_callback',
|
|
||||||
$text
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes leading PHP tags from included files. Assumes that there is
|
|
||||||
* no trailing tag.
|
|
||||||
*/
|
|
||||||
function remove_php_tags($text) {
|
|
||||||
return substr($text, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an appropriate blank file, recursively generating directories
|
|
||||||
* if necessary
|
|
||||||
*/
|
|
||||||
function create_blank($file) {
|
|
||||||
$dir = dirname($file);
|
|
||||||
$base = realpath('../tests/blanks/') . DIRECTORY_SEPARATOR ;
|
|
||||||
if ($dir != '.') mkdir_deep($base . $dir);
|
|
||||||
file_put_contents($base . $file, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively creates a directory
|
|
||||||
* @note Adapted from the PHP manual comment 76612
|
|
||||||
*/
|
|
||||||
function mkdir_deep($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)){
|
|
||||||
mkdir($base);
|
|
||||||
}
|
|
||||||
$base .= DIRECTORY_SEPARATOR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copy a file, or recursively copy a folder and its contents
|
|
||||||
*
|
|
||||||
* @author Aidan Lister <aidan@php.net>
|
|
||||||
* @version 1.0.1
|
|
||||||
* @link http://aidanlister.com/repos/v/function.copyr.php
|
|
||||||
* @param string $source Source path
|
|
||||||
* @param string $dest Destination path
|
|
||||||
* @return bool Returns TRUE on success, FALSE on failure
|
|
||||||
*/
|
|
||||||
function copyr($source, $dest) {
|
|
||||||
// Simple copy for a file
|
|
||||||
if (is_file($source)) {
|
|
||||||
return copy($source, $dest);
|
|
||||||
}
|
|
||||||
// Make destination directory
|
|
||||||
if (!is_dir($dest)) {
|
|
||||||
mkdir($dest);
|
|
||||||
}
|
|
||||||
// Loop through the folder
|
|
||||||
$dir = dir($source);
|
|
||||||
while (false !== $entry = $dir->read()) {
|
|
||||||
// Skip pointers
|
|
||||||
if ($entry == '.' || $entry == '..') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Skip hidden files
|
|
||||||
if ($entry[0] == '.') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Deep copy directories
|
|
||||||
if ($dest !== "$source/$entry") {
|
|
||||||
copyr("$source/$entry", "$dest/$entry");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Clean up
|
|
||||||
$dir->close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a file, or a folder and its contents
|
|
||||||
*
|
|
||||||
* @author Aidan Lister <aidan@php.net>
|
|
||||||
* @version 1.0.3
|
|
||||||
* @link http://aidanlister.com/repos/v/function.rmdirr.php
|
|
||||||
* @param string $dirname Directory to delete
|
|
||||||
* @return bool Returns TRUE on success, FALSE on failure
|
|
||||||
*/
|
|
||||||
function rmdirr($dirname)
|
|
||||||
{
|
|
||||||
// Sanity check
|
|
||||||
if (!file_exists($dirname)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple delete for a file
|
|
||||||
if (is_file($dirname) || is_link($dirname)) {
|
|
||||||
return unlink($dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop through the folder
|
|
||||||
$dir = dir($dirname);
|
|
||||||
while (false !== $entry = $dir->read()) {
|
|
||||||
// Skip pointers
|
|
||||||
if ($entry == '.' || $entry == '..') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Recurse
|
|
||||||
rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up
|
|
||||||
$dir->close();
|
|
||||||
return rmdir($dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies the contents of a directory to the standalone directory
|
|
||||||
*/
|
|
||||||
function make_dir_standalone($dir) {
|
|
||||||
return copyr($dir, 'standalone/' . $dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
function make_file_standalone($file) {
|
|
||||||
mkdir_deep('standalone/' . dirname($file));
|
|
||||||
return copy($file, 'standalone/' . $file);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $matches preg_replace_callback matches array, where index 1
|
|
||||||
* is the filename to include
|
|
||||||
*/
|
|
||||||
function replace_includes_callback($matches) {
|
|
||||||
$file = $matches[1];
|
|
||||||
if (isset($GLOBALS['loaded'][$file])) return '';
|
|
||||||
$GLOBALS['loaded'][$file] = true;
|
|
||||||
create_blank($file);
|
|
||||||
return replace_includes(remove_php_tags(file_get_contents($file)));
|
|
||||||
}
|
|
||||||
|
|
||||||
chdir(dirname(__FILE__) . '/../library/');
|
|
||||||
create_blank('HTMLPurifier.php');
|
|
||||||
|
|
||||||
echo 'Creating full file...';
|
|
||||||
$contents = replace_includes(file_get_contents('HTMLPurifier.php'));
|
|
||||||
$contents = str_replace(
|
|
||||||
"define('HTMLPURIFIER_PREFIX', dirname(__FILE__));",
|
|
||||||
"define('HTMLPURIFIER_PREFIX', dirname(__FILE__) . '/standalone');",
|
|
||||||
$contents
|
|
||||||
);
|
|
||||||
file_put_contents('HTMLPurifier.standalone.php', $contents);
|
|
||||||
echo ' done!' . PHP_EOL;
|
|
||||||
|
|
||||||
echo 'Creating standalone directory...';
|
|
||||||
rmdirr('standalone'); // ensure a clean copy
|
|
||||||
mkdir_deep('standalone/HTMLPurifier/DefinitionCache/Serializer');
|
|
||||||
make_dir_standalone('HTMLPurifier/EntityLookup');
|
|
||||||
make_dir_standalone('HTMLPurifier/Language');
|
|
||||||
make_file_standalone('HTMLPurifier/Printer/ConfigForm.js');
|
|
||||||
make_file_standalone('HTMLPurifier/Printer/ConfigForm.css');
|
|
||||||
make_dir_standalone('HTMLPurifier/URIScheme');
|
|
||||||
echo ' done!' . PHP_EOL;
|
|
||||||
|
|
@@ -3,7 +3,7 @@
|
|||||||
header('Content-type: text/html; charset=UTF-8');
|
header('Content-type: text/html; charset=UTF-8');
|
||||||
|
|
||||||
require_once '../library/HTMLPurifier.auto.php';
|
require_once '../library/HTMLPurifier.auto.php';
|
||||||
error_reporting(E_ALL | E_STRICT);
|
error_reporting(E_ALL);
|
||||||
|
|
||||||
function escapeHTML($string) {
|
function escapeHTML($string) {
|
||||||
$string = HTMLPurifier_Encoder::cleanUTF8($string);
|
$string = HTMLPurifier_Encoder::cleanUTF8($string);
|
||||||
|
@@ -86,7 +86,7 @@ class Debugger
|
|||||||
/**
|
/**
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
static function &instance() {
|
function &instance() {
|
||||||
static $soleInstance = false;
|
static $soleInstance = false;
|
||||||
if (!$soleInstance) $soleInstance = new Debugger();
|
if (!$soleInstance) $soleInstance = new Debugger();
|
||||||
return $soleInstance;
|
return $soleInstance;
|
||||||
|
@@ -2,21 +2,20 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/AttrCollections.php';
|
require_once 'HTMLPurifier/AttrCollections.php';
|
||||||
|
|
||||||
class HTMLPurifier_AttrCollectionsTest_NoConstructor extends HTMLPurifier_AttrCollections
|
Mock::generatePartial(
|
||||||
{
|
'HTMLPurifier_AttrCollections',
|
||||||
function HTMLPurifier_AttrCollectionsTest_NoConstructor() {}
|
'HTMLPurifier_AttrCollections_TestForConstruct',
|
||||||
function expandIdentifiers(&$a, $b) {}
|
array('performInclusions', 'expandIdentifiers')
|
||||||
function performInclusions(&$a) {}
|
);
|
||||||
}
|
|
||||||
|
|
||||||
class HTMLPurifier_AttrCollectionsTest extends HTMLPurifier_Harness
|
class HTMLPurifier_AttrCollectionsTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function testConstruction() {
|
function testConstruction() {
|
||||||
|
|
||||||
generate_mock_once('HTMLPurifier_AttrTypes');
|
generate_mock_once('HTMLPurifier_AttrTypes');
|
||||||
|
|
||||||
$collections = new HTMLPurifier_AttrCollectionsTest_NoConstructor();
|
$collections = new HTMLPurifier_AttrCollections_TestForConstruct();
|
||||||
|
|
||||||
$types = new HTMLPurifier_AttrTypesMock();
|
$types = new HTMLPurifier_AttrTypesMock();
|
||||||
|
|
||||||
|
@@ -16,10 +16,6 @@ class HTMLPurifier_AttrDef_CSS_FontFamilyTest extends HTMLPurifier_AttrDefHarnes
|
|||||||
$this->assertDef('01234');
|
$this->assertDef('01234');
|
||||||
$this->assertDef(',', false);
|
$this->assertDef(',', false);
|
||||||
$this->assertDef('Times New Roman, serif', '\'Times New Roman\', serif');
|
$this->assertDef('Times New Roman, serif', '\'Times New Roman\', serif');
|
||||||
$this->assertDef($d = "'John\\'s Font'");
|
|
||||||
$this->assertDef("John's Font", $d);
|
|
||||||
$this->assertDef($d = "'\xE5\xAE\x8B\xE4\xBD\x93'");
|
|
||||||
$this->assertDef("\xE5\xAE\x8B\xE4\xBD\x93", $d);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,86 +2,317 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/AttrDefHarness.php';
|
require_once 'HTMLPurifier/AttrDefHarness.php';
|
||||||
require_once 'HTMLPurifier/AttrDef/URI.php';
|
require_once 'HTMLPurifier/AttrDef/URI.php';
|
||||||
require_once 'HTMLPurifier/URIParser.php';
|
|
||||||
|
|
||||||
/**
|
// WARNING: INCOMPLETE UNIT TESTS!
|
||||||
* @todo Aim for complete code coverage with mocks
|
// we also need to test all the configuration directives defined by this class
|
||||||
*/
|
|
||||||
|
// http: is returned quite often when a URL is invalid. We have to change
|
||||||
|
// this behavior to just a plain old "FALSE"!
|
||||||
|
|
||||||
class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
|
class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
|
||||||
{
|
{
|
||||||
|
|
||||||
function setUp() {
|
var $scheme, $components, $return_components;
|
||||||
|
|
||||||
|
function testGenericURI() {
|
||||||
|
|
||||||
|
generate_mock_once('HTMLPurifier_URIScheme');
|
||||||
|
generate_mock_once('HTMLPurifier_URISchemeRegistry');
|
||||||
|
|
||||||
|
$old_registry = HTMLPurifier_URISchemeRegistry::instance();
|
||||||
|
|
||||||
|
// finally, lets get a copy of the actual class
|
||||||
$this->def = new HTMLPurifier_AttrDef_URI();
|
$this->def = new HTMLPurifier_AttrDef_URI();
|
||||||
parent::setUp();
|
|
||||||
|
// initialize test inputs
|
||||||
|
$uri = // input URI
|
||||||
|
$components = // what components the URI should be parsed to
|
||||||
|
$return_components = // return components
|
||||||
|
$expect_uri = array(); // what reassembled URI to expect
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// test a regular instance, return identical URI
|
||||||
|
$uri[0] = 'http://www.example.com/webhp?q=foo#result2';
|
||||||
|
$components[0] = array(
|
||||||
|
null, // userinfo
|
||||||
|
'www.example.com', // host
|
||||||
|
null, // port
|
||||||
|
'/webhp', // path
|
||||||
|
'q=foo' // query
|
||||||
|
);
|
||||||
|
|
||||||
|
// test an amended URI (the actual logic is irrelevant)
|
||||||
|
// test that user and port get parsed correctly (3.2.1 and 3.2.3)
|
||||||
|
$uri[1] = 'http://user@authority.part:80/now/the/path?query#fragment';
|
||||||
|
$components[1] = array(
|
||||||
|
'user', 'authority.part', 80,
|
||||||
|
'/now/the/path', 'query'
|
||||||
|
);
|
||||||
|
$return_components[1] = array( // removed port (it's standard)
|
||||||
|
'user', 'authority.part', null, '/now/the/path', 'query'
|
||||||
|
);
|
||||||
|
$expect_uri[1] = 'http://user@authority.part/now/the/path?query#fragment';
|
||||||
|
|
||||||
|
// percent encoded characters are not resolved during generic URI
|
||||||
|
// parsing even though RFC 3986 defines this notation
|
||||||
|
// also test what happens when query/fragment are missing
|
||||||
|
$uri[2] = 'http://en.wikipedia.org/wiki/Clich%C3%A9';
|
||||||
|
$components[2] = array(
|
||||||
|
null, 'en.wikipedia.org', null, '/wiki/Clich%C3%A9', null
|
||||||
|
);
|
||||||
|
|
||||||
|
// test distinction between empty query and undefined query (above)
|
||||||
|
$uri[3] = 'http://www.example.com/?#';
|
||||||
|
$components[3] = array(null, 'www.example.com', null, '/', '');
|
||||||
|
|
||||||
|
// path is always defined, even if empty
|
||||||
|
$uri[4] = 'http://www.example.com';
|
||||||
|
$components[4] = array(null, 'www.example.com', null, '', null);
|
||||||
|
|
||||||
|
// test parsing of an opaque URI
|
||||||
|
$uri[5] = 'mailto:bob@example.com';
|
||||||
|
$components[5] = array(null, null, null, 'bob@example.com', null);
|
||||||
|
|
||||||
|
// even though we don't resolve percent entities, we have to fix
|
||||||
|
// improper percent-encodes. Taken one at a time:
|
||||||
|
// %56 - V, which is an unreserved character
|
||||||
|
// %fc - u with an umlaut, normalize to uppercase
|
||||||
|
// %GJ - invalid characters in entity, encode %
|
||||||
|
// %5 - prematurely terminated, encode %
|
||||||
|
// %FC - u with umlaut, correct
|
||||||
|
// note that Apache doesn't do such fixing, rather, it just claims
|
||||||
|
// that the browser sent a "Bad Request". See PercentEncoder.php
|
||||||
|
// for more details
|
||||||
|
$uri[6] = 'http://www.example.com/%56%fc%GJ%5%FC';
|
||||||
|
$components[6] = array(null, 'www.example.com', null, '/V%FC%25GJ%255%FC', null);
|
||||||
|
$expect_uri[6] = 'http://www.example.com/V%FC%25GJ%255%FC';
|
||||||
|
|
||||||
|
// test IPv4 address (behavior may vary with configuration)
|
||||||
|
$uri[7] = 'http://192.0.34.166/';
|
||||||
|
$components[7] = array(null, '192.0.34.166', null, '/', null);
|
||||||
|
|
||||||
|
// while it may look like an IPv4 address, it's really a reg-name.
|
||||||
|
// don't destroy it
|
||||||
|
$uri[8] = 'http://333.123.32.123/';
|
||||||
|
$components[8] = array(null, '333.123.32.123', null, '/', null);
|
||||||
|
|
||||||
|
// test IPv6 address, using amended form of RFC's example
|
||||||
|
$uri[9] = 'http://[2001:db8::7]/c=GB?objectClass?one';
|
||||||
|
$components[9] = array(null, '[2001:db8::7]', null, '/c=GB',
|
||||||
|
'objectClass?one');
|
||||||
|
|
||||||
|
// We will not implement punycode encoding, that's up to the browsers
|
||||||
|
// We also will not implement percent to IDNA encoding transformations:
|
||||||
|
// if you need to use an international domain in a link, make sure that
|
||||||
|
// you've got it in UTF-8 and send it in raw (no encoding).
|
||||||
|
|
||||||
|
// break the RFC a little and allow international characters
|
||||||
|
// WARNING: UTF-8 encoded!
|
||||||
|
$uri[10] = 'http://tūdaliņ.lv';
|
||||||
|
$components[10] = array(null, 'tūdaliņ.lv', null, '', null);
|
||||||
|
|
||||||
|
// test invalid IPv6 address and invalid reg-name
|
||||||
|
$uri[11] = 'http://[2001:0db8:85z3:08d3:1319:8a2e:0370:7334]';
|
||||||
|
$components[11] = array(null, null, null, '', null);
|
||||||
|
$expect_uri[11] = 'http:';
|
||||||
|
|
||||||
|
// test invalid port
|
||||||
|
$uri[12] = 'http://example.com:foobar';
|
||||||
|
$components[12] = array(null, 'example.com', null, '', null);
|
||||||
|
$expect_uri[12] = 'http://example.com';
|
||||||
|
|
||||||
|
// test overlarge port (max is 65535, although this isn't official)
|
||||||
|
$uri[13] = 'http://example.com:65536';
|
||||||
|
$components[13] = array(null, 'example.com', null, '', null);
|
||||||
|
$expect_uri[13] = 'http://example.com';
|
||||||
|
|
||||||
|
// some spec abnf tests
|
||||||
|
|
||||||
|
// "authority . path-abempty" omitted, it is a trivial case
|
||||||
|
|
||||||
|
// "path-absolute", note this is different from path-rootless
|
||||||
|
$uri[14] = 'http:/this/is/path';
|
||||||
|
$components[14] = array(null, null, null, '/this/is/path', null);
|
||||||
|
$expect_uri[14] = 'http:/this/is/path'; // do not munge scheme off
|
||||||
|
|
||||||
|
// scheme munging is not being tested yet, it's an extra feature
|
||||||
|
|
||||||
|
// "path-rootless" - this should not be used but is allowed
|
||||||
|
$uri[15] = 'http:this/is/path';
|
||||||
|
$components[15] = array(null, null, null, 'this/is/path', null);
|
||||||
|
//$expect_uri[15] = 'this/is/path'; // munge scheme off
|
||||||
|
|
||||||
|
// "path-empty" - a rather interesting case, remove the scheme
|
||||||
|
$uri[16] = 'http:';
|
||||||
|
$components[16] = array(null, null, null, '', null);
|
||||||
|
//$expect_uri[16] = ''; // munge scheme off
|
||||||
|
|
||||||
|
// test invalid scheme, components shouldn't be passed
|
||||||
|
$uri[17] = 'javascript:alert("moo");';
|
||||||
|
$expect_uri[17] = false;
|
||||||
|
|
||||||
|
// relative URIs - basic case
|
||||||
|
$uri[18] = '/a/b';
|
||||||
|
$components[18] = array(null, null, null, '/a/b', null);
|
||||||
|
|
||||||
|
// result of malformed tag, gracefully handle error
|
||||||
|
$uri[19] = 'http://www.google.com/\'>"';
|
||||||
|
$components[19] = array(null, 'www.google.com', null, '/', null);
|
||||||
|
$expect_uri[19] = 'http://www.google.com/';
|
||||||
|
|
||||||
|
// test empty
|
||||||
|
$uri[20] = '';
|
||||||
|
$components[20] = array(null, null, null, '', null);
|
||||||
|
$expect_uri[20] = '';
|
||||||
|
|
||||||
|
foreach ($uri as $i => $value) {
|
||||||
|
|
||||||
|
// the read in values
|
||||||
|
$this->config = isset($config[$i]) ? $config[$i] : HTMLPurifier_Config::createDefault();
|
||||||
|
$this->context = isset($context[$i]) ? $context[$i] : new HTMLPurifier_Context();
|
||||||
|
|
||||||
|
// setUpAssertDef
|
||||||
|
if ( isset($components[$i]) ) {
|
||||||
|
$this->components = $components[$i];
|
||||||
|
} else {
|
||||||
|
$this->components = false;
|
||||||
|
}
|
||||||
|
if ( isset($return_components[$i]) ) {
|
||||||
|
$this->return_components = $return_components[$i];
|
||||||
|
} else {
|
||||||
|
$this->return_components = $this->components;
|
||||||
|
}
|
||||||
|
|
||||||
|
// parameters
|
||||||
|
if (!isset($expect_uri[$i])) {
|
||||||
|
$expect_uri[$i] = $value; // untouched
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertDef($value, $expect_uri[$i], true, "Test $i: %s");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset to regular implementation
|
||||||
|
HTMLPurifier_URISchemeRegistry::instance($old_registry);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function setUpAssertDef() {
|
||||||
|
// $fake_registry isn't the real mock, because due to PHP 4 weirdness
|
||||||
|
// I cannot set a default value to function parameters that are passed
|
||||||
|
// by reference. So we use the value instance() returns.
|
||||||
|
$fake_registry = new HTMLPurifier_URISchemeRegistryMock();
|
||||||
|
$registry =& HTMLPurifier_URISchemeRegistry::instance($fake_registry);
|
||||||
|
|
||||||
|
// now, let's add a pseudo-scheme to the registry
|
||||||
|
$this->scheme = new HTMLPurifier_URISchemeMock();
|
||||||
|
|
||||||
|
// here are the schemes we will support with overloaded mocks
|
||||||
|
$registry->setReturnReference('getScheme', $this->scheme, array('http', '*', '*'));
|
||||||
|
$registry->setReturnReference('getScheme', $this->scheme, array('mailto', '*', '*'));
|
||||||
|
|
||||||
|
// default return value is false (meaning no scheme defined: reject)
|
||||||
|
$registry->setReturnValue('getScheme', false, array('*', '*', '*'));
|
||||||
|
|
||||||
|
if ($this->components === false) {
|
||||||
|
$this->scheme->expectNever('validateComponents');
|
||||||
|
} else {
|
||||||
|
$this->components[] = '*'; // append the configuration
|
||||||
|
$this->components[] = '*'; // append context
|
||||||
|
$this->scheme->setReturnValue(
|
||||||
|
'validateComponents', $this->return_components, $this->components);
|
||||||
|
$this->scheme->expectOnce('validateComponents', $this->components);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function tearDownAssertDef() {
|
||||||
|
$this->scheme->tally();
|
||||||
}
|
}
|
||||||
|
|
||||||
function testIntegration() {
|
function testIntegration() {
|
||||||
|
|
||||||
|
$this->def = new HTMLPurifier_AttrDef_URI();
|
||||||
|
|
||||||
$this->assertDef('http://www.google.com/');
|
$this->assertDef('http://www.google.com/');
|
||||||
$this->assertDef('http:', '');
|
|
||||||
$this->assertDef('http:/foo', '/foo');
|
|
||||||
$this->assertDef('javascript:bad_stuff();', false);
|
$this->assertDef('javascript:bad_stuff();', false);
|
||||||
$this->assertDef('ftp://www.example.com/');
|
$this->assertDef('ftp://www.example.com/');
|
||||||
$this->assertDef('news:rec.alt');
|
$this->assertDef('news:rec.alt');
|
||||||
$this->assertDef('nntp://news.example.com/324234');
|
$this->assertDef('nntp://news.example.com/324234');
|
||||||
$this->assertDef('mailto:bob@example.com');
|
$this->assertDef('mailto:bob@example.com');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testIntegrationWithPercentEncoder() {
|
function testDisableExternal() {
|
||||||
$this->assertDef(
|
|
||||||
'http://www.example.com/%56%fc%GJ%5%FC',
|
$this->def = new HTMLPurifier_AttrDef_URI();
|
||||||
'http://www.example.com/V%FC%25GJ%255%FC'
|
$this->config->set('URI', 'DisableExternal', true);
|
||||||
);
|
$this->config->set('URI', 'Host', 'sub.example.com');
|
||||||
|
|
||||||
|
$this->assertDef('/foobar.txt');
|
||||||
|
$this->assertDef('http://google.com/', false);
|
||||||
|
$this->assertDef('http://sub.example.com/alas?foo=asd');
|
||||||
|
$this->assertDef('http://example.com/teehee', false);
|
||||||
|
$this->assertDef('http://www.example.com/#man', false);
|
||||||
|
$this->assertDef('http://go.sub.example.com/perhaps?p=foo');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testEmbeds() {
|
function testEmbeds() {
|
||||||
|
|
||||||
|
// embedded URI
|
||||||
$this->def = new HTMLPurifier_AttrDef_URI(true);
|
$this->def = new HTMLPurifier_AttrDef_URI(true);
|
||||||
|
|
||||||
$this->assertDef('http://sub.example.com/alas?foo=asd');
|
$this->assertDef('http://sub.example.com/alas?foo=asd');
|
||||||
$this->assertDef('mailto:foo@example.com', false);
|
$this->assertDef('mailto:foo@example.com', false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testConfigMunge() {
|
function testDisableExternalResources() {
|
||||||
|
|
||||||
|
$this->config->set('URI', 'DisableExternalResources', true);
|
||||||
|
|
||||||
|
$this->def = new HTMLPurifier_AttrDef_URI();
|
||||||
|
$this->assertDef('http://sub.example.com/alas?foo=asd');
|
||||||
|
$this->assertDef('/img.png');
|
||||||
|
|
||||||
|
$this->def = new HTMLPurifier_AttrDef_URI(true);
|
||||||
|
$this->assertDef('http://sub.example.com/alas?foo=asd', false);
|
||||||
|
$this->assertDef('/img.png');
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function testMunge() {
|
||||||
|
|
||||||
$this->config->set('URI', 'Munge', 'http://www.google.com/url?q=%s');
|
$this->config->set('URI', 'Munge', 'http://www.google.com/url?q=%s');
|
||||||
|
$this->def = new HTMLPurifier_AttrDef_URI();
|
||||||
|
|
||||||
$this->assertDef(
|
$this->assertDef(
|
||||||
'http://www.example.com/',
|
'http://www.example.com/',
|
||||||
'http://www.google.com/url?q=http%3A%2F%2Fwww.example.com%2F'
|
'http://www.google.com/url?q=http%3A%2F%2Fwww.example.com%2F'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertDef('index.html');
|
$this->assertDef('index.html');
|
||||||
$this->assertDef('javascript:foobar();', false);
|
$this->assertDef('javascript:foobar();', false);
|
||||||
}
|
|
||||||
|
|
||||||
function testDefaultSchemeRemovedInBlank() {
|
|
||||||
$this->assertDef('http:', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testDefaultSchemeRemovedInRelativeURI() {
|
|
||||||
$this->assertDef('http:/foo/bar', '/foo/bar');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testDefaultSchemeNotRemovedInAbsoluteURI() {
|
|
||||||
$this->assertDef('http://example.com/foo/bar');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testAltSchemeNotRemoved() {
|
|
||||||
$this->assertDef('mailto:this-looks-like-a-path@example.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testURIDefinitionValidation() {
|
|
||||||
$parser = new HTMLPurifier_URIParser();
|
|
||||||
$uri = $parser->parse('http://example.com');
|
|
||||||
$this->config->set('URI', 'DefinitionID', 'HTMLPurifier_AttrDef_URITest->testURIDefinitionValidation');
|
|
||||||
$uri_def =& $this->config->getDefinition('URI');
|
|
||||||
// overload with mock
|
|
||||||
generate_mock_once('HTMLPurifier_URIDefinition');
|
|
||||||
$uri_def = new HTMLPurifier_URIDefinitionMock();
|
|
||||||
$uri_def->expectOnce('filter', array($uri, '*', '*'));
|
|
||||||
$uri_def->setReturnValue('filter', true, array($uri, '*', '*'));
|
|
||||||
$uri_def->setup = true;
|
|
||||||
$this->assertDef('http://example.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
function test_validate_configWhitelist() {
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function testBlacklist() {
|
||||||
|
|
||||||
|
$this->config->set('URI', 'HostBlacklist', array('example.com', 'moo'));
|
||||||
|
|
||||||
|
$this->assertDef('foo.txt');
|
||||||
|
$this->assertDef('http://www.google.com/example.com/moo');
|
||||||
|
|
||||||
|
$this->assertDef('http://example.com/#23', false);
|
||||||
|
$this->assertDef('https://sub.domain.example.com/foobar', false);
|
||||||
|
$this->assertDef('http://example.com.example.net/?whoo=foo', false);
|
||||||
|
$this->assertDef('ftp://moo-moo.net/foo/foo/', false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function testWhitelist() {
|
||||||
|
/*
|
||||||
$this->config->set('URI', 'HostPolicy', 'DenyAll');
|
$this->config->set('URI', 'HostPolicy', 'DenyAll');
|
||||||
$this->config->set('URI', 'HostWhitelist', array(null, 'google.com'));
|
$this->config->set('URI', 'HostWhitelist', array(null, 'google.com'));
|
||||||
|
|
||||||
@@ -89,9 +320,8 @@ class HTMLPurifier_AttrDef_URITest extends HTMLPurifier_AttrDefHarness
|
|||||||
$this->assertDef('server.txt');
|
$this->assertDef('server.txt');
|
||||||
$this->assertDef('ftp://www.google.com/?t=a');
|
$this->assertDef('ftp://www.google.com/?t=a');
|
||||||
$this->assertDef('http://google.com.tricky.spamsite.net', false);
|
$this->assertDef('http://google.com.tricky.spamsite.net', false);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class HTMLPurifier_AttrDefHarness extends HTMLPurifier_Harness
|
class HTMLPurifier_AttrDefHarness extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $def;
|
var $def;
|
||||||
var $context, $config;
|
var $context;
|
||||||
|
var $config;
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
$this->config = HTMLPurifier_Config::createDefault();
|
$this->config = HTMLPurifier_Config::createDefault();
|
||||||
@@ -12,15 +13,20 @@ class HTMLPurifier_AttrDefHarness extends HTMLPurifier_Harness
|
|||||||
}
|
}
|
||||||
|
|
||||||
// cannot be used for accumulator
|
// cannot be used for accumulator
|
||||||
function assertDef($string, $expect = true) {
|
function assertDef($string, $expect = true, $ini = false, $message = '%s') {
|
||||||
// $expect can be a string or bool
|
// $expect can be a string or bool
|
||||||
|
if ($ini) $this->setUpAssertDef();
|
||||||
$result = $this->def->validate($string, $this->config, $this->context);
|
$result = $this->def->validate($string, $this->config, $this->context);
|
||||||
if ($expect === true) {
|
if ($expect === true) {
|
||||||
$this->assertIdentical($string, $result);
|
$this->assertIdentical($string, $result, $message);
|
||||||
} else {
|
} else {
|
||||||
$this->assertIdentical($expect, $result);
|
$this->assertIdentical($expect, $result, $message);
|
||||||
}
|
}
|
||||||
|
if ($ini) $this->tearDownAssertDef();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setUpAssertDef() {}
|
||||||
|
function tearDownAssertDef() {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/AttrDef.php';
|
require_once 'HTMLPurifier/AttrDef.php';
|
||||||
|
|
||||||
class HTMLPurifier_AttrDefTest extends HTMLPurifier_Harness
|
class HTMLPurifier_AttrDefTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_parseCDATA() {
|
function test_parseCDATA() {
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once 'HTMLPurifier/ComplexHarness.php';
|
require_once 'HTMLPurifier/Harness.php';
|
||||||
|
|
||||||
class HTMLPurifier_AttrTransformHarness extends HTMLPurifier_ComplexHarness
|
class HTMLPurifier_AttrTransformHarness extends HTMLPurifier_Harness
|
||||||
{
|
{
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/AttrTransform.php';
|
require_once 'HTMLPurifier/AttrTransform.php';
|
||||||
|
|
||||||
class HTMLPurifier_AttrTransformTest extends HTMLPurifier_Harness
|
class HTMLPurifier_AttrTransformTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_prependCSS() {
|
function test_prependCSS() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/AttrTypes.php';
|
require_once 'HTMLPurifier/AttrTypes.php';
|
||||||
|
|
||||||
class HTMLPurifier_AttrTypesTest extends HTMLPurifier_Harness
|
class HTMLPurifier_AttrTypesTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_get() {
|
function test_get() {
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once 'HTMLPurifier/ComplexHarness.php';
|
require_once 'HTMLPurifier/Harness.php';
|
||||||
require_once 'HTMLPurifier/ChildDef.php';
|
require_once 'HTMLPurifier/ChildDef.php';
|
||||||
|
|
||||||
class HTMLPurifier_ChildDefHarness extends HTMLPurifier_ComplexHarness
|
class HTMLPurifier_ChildDefHarness extends HTMLPurifier_Harness
|
||||||
{
|
{
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
|
@@ -1,129 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General-purpose test-harness that makes testing functions that require
|
|
||||||
* configuration and context objects easier when those two parameters are
|
|
||||||
* meaningless. See HTMLPurifier_ChildDefTest for a good example of usage.
|
|
||||||
*/
|
|
||||||
class HTMLPurifier_ComplexHarness extends HTMLPurifier_Harness
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance of the object that will execute the method
|
|
||||||
*/
|
|
||||||
var $obj;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the function to be executed
|
|
||||||
*/
|
|
||||||
var $func;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not the method deals in tokens. If set to true, assertResult()
|
|
||||||
* will transparently convert HTML to and back from tokens.
|
|
||||||
*/
|
|
||||||
var $to_tokens = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not to convert tokens back into HTML before performing
|
|
||||||
* equality check, has no effect on bools.
|
|
||||||
*/
|
|
||||||
var $to_html = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance of an HTMLPurifier_Lexer implementation.
|
|
||||||
*/
|
|
||||||
var $lexer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instance of HTMLPurifier_Generator
|
|
||||||
*/
|
|
||||||
var $generator;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default config to fall back on if no config is available
|
|
||||||
*/
|
|
||||||
var $config;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default context to fall back on if no context is available
|
|
||||||
*/
|
|
||||||
var $context;
|
|
||||||
|
|
||||||
function HTMLPurifier_ComplexHarness() {
|
|
||||||
$this->lexer = new HTMLPurifier_Lexer_DirectLex();
|
|
||||||
$this->generator = new HTMLPurifier_Generator();
|
|
||||||
parent::HTMLPurifier_Harness();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asserts a specific result from a one parameter + config/context function
|
|
||||||
* @param $input Input parameter
|
|
||||||
* @param $expect Expectation
|
|
||||||
* @param $config Configuration array in form of Ns.Directive => Value.
|
|
||||||
* Has no effect if $this->config is set.
|
|
||||||
* @param $context_array Context array in form of Key => Value or an actual
|
|
||||||
* context object.
|
|
||||||
*/
|
|
||||||
function assertResult($input, $expect = true,
|
|
||||||
$config_array = array(), $context_array = array()
|
|
||||||
) {
|
|
||||||
|
|
||||||
// setup config
|
|
||||||
if ($this->config) {
|
|
||||||
$config = HTMLPurifier_Config::create($this->config);
|
|
||||||
$config->autoFinalize = false;
|
|
||||||
$config->loadArray($config_array);
|
|
||||||
} else {
|
|
||||||
$config = HTMLPurifier_Config::create($config_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup context object. Note that we are operating on a copy of it!
|
|
||||||
// When necessary, extend the test harness to allow post-tests
|
|
||||||
// on the context object
|
|
||||||
if (empty($this->context)) {
|
|
||||||
$context = new HTMLPurifier_Context();
|
|
||||||
$context->loadArray($context_array);
|
|
||||||
} else {
|
|
||||||
$context =& $this->context;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->to_tokens && is_string($input)) {
|
|
||||||
// $func may cause $input to change, so "clone" another copy
|
|
||||||
// to sacrifice
|
|
||||||
$input = $this->lexer->tokenizeHTML($s = $input, $config, $context);
|
|
||||||
$input_c = $this->lexer->tokenizeHTML($s, $config, $context);
|
|
||||||
} else {
|
|
||||||
$input_c = $input;
|
|
||||||
}
|
|
||||||
|
|
||||||
// call the function
|
|
||||||
$func = $this->func;
|
|
||||||
$result = $this->obj->$func($input_c, $config, $context);
|
|
||||||
|
|
||||||
// test a bool result
|
|
||||||
if (is_bool($result)) {
|
|
||||||
$this->assertIdentical($expect, $result);
|
|
||||||
return;
|
|
||||||
} elseif (is_bool($expect)) {
|
|
||||||
$expect = $input;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->to_html) {
|
|
||||||
$result = $this->generator->
|
|
||||||
generateFromTokens($result, $config, $context);
|
|
||||||
if (is_array($expect)) {
|
|
||||||
$expect = $this->generator->
|
|
||||||
generateFromTokens($expect, $config, $context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->assertIdentical($expect, $result);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@@ -6,7 +6,7 @@ if (!class_exists('CS')) {
|
|||||||
class CS extends HTMLPurifier_ConfigSchema {}
|
class CS extends HTMLPurifier_ConfigSchema {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HTMLPurifier_ConfigSchemaTest extends HTMLPurifier_Harness
|
class HTMLPurifier_ConfigSchemaTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -6,7 +6,7 @@ if (!class_exists('CS')) {
|
|||||||
class CS extends HTMLPurifier_ConfigSchema {}
|
class CS extends HTMLPurifier_ConfigSchema {}
|
||||||
}
|
}
|
||||||
|
|
||||||
class HTMLPurifier_ConfigTest extends HTMLPurifier_Harness
|
class HTMLPurifier_ConfigTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $our_copy, $old_copy;
|
var $our_copy, $old_copy;
|
||||||
|
@@ -5,7 +5,7 @@ require_once 'HTMLPurifier/Context.php';
|
|||||||
// mocks
|
// mocks
|
||||||
require_once 'HTMLPurifier/IDAccumulator.php';
|
require_once 'HTMLPurifier/IDAccumulator.php';
|
||||||
|
|
||||||
class HTMLPurifier_ContextTest extends HTMLPurifier_Harness
|
class HTMLPurifier_ContextTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $context;
|
var $context;
|
||||||
|
@@ -17,7 +17,8 @@ class HTMLPurifier_DefinitionCache_SerializerTest extends HTMLPurifier_Definitio
|
|||||||
$config_md5 = '1.0.0-serial-2';
|
$config_md5 = '1.0.0-serial-2';
|
||||||
|
|
||||||
$file = realpath(
|
$file = realpath(
|
||||||
$rel_file = HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer/Test/' .
|
$rel_file = dirname(__FILE__) .
|
||||||
|
'/../../../library/HTMLPurifier/DefinitionCache/Serializer/Test/' .
|
||||||
$config_md5 . '.ser'
|
$config_md5 . '.ser'
|
||||||
);
|
);
|
||||||
if($file && file_exists($file)) unlink($file); // prevent previous failures from causing problems
|
if($file && file_exists($file)) unlink($file); // prevent previous failures from causing problems
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/DefinitionCacheFactory.php';
|
require_once 'HTMLPurifier/DefinitionCacheFactory.php';
|
||||||
|
|
||||||
class HTMLPurifier_DefinitionCacheFactoryTest extends HTMLPurifier_Harness
|
class HTMLPurifier_DefinitionCacheFactoryTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $newFactory;
|
var $newFactory;
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
class HTMLPurifier_DefinitionCacheHarness extends HTMLPurifier_Harness
|
class HTMLPurifier_DefinitionCacheHarness extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/DefinitionCache.php';
|
require_once 'HTMLPurifier/DefinitionCache.php';
|
||||||
|
|
||||||
class HTMLPurifier_DefinitionCacheTest extends HTMLPurifier_Harness
|
class HTMLPurifier_DefinitionCacheTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_isOld() {
|
function test_isOld() {
|
||||||
|
@@ -7,7 +7,7 @@ Mock::generatePartial(
|
|||||||
'HTMLPurifier_Definition_Testable',
|
'HTMLPurifier_Definition_Testable',
|
||||||
array('doSetup'));
|
array('doSetup'));
|
||||||
|
|
||||||
class HTMLPurifier_DefinitionTest extends HTMLPurifier_Harness
|
class HTMLPurifier_DefinitionTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
function test_setup() {
|
function test_setup() {
|
||||||
$def = new HTMLPurifier_Definition_Testable();
|
$def = new HTMLPurifier_Definition_Testable();
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/DoctypeRegistry.php';
|
require_once 'HTMLPurifier/DoctypeRegistry.php';
|
||||||
|
|
||||||
class HTMLPurifier_DoctypeRegistryTest extends HTMLPurifier_Harness
|
class HTMLPurifier_DoctypeRegistryTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_register() {
|
function test_register() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/ElementDef.php';
|
require_once 'HTMLPurifier/ElementDef.php';
|
||||||
|
|
||||||
class HTMLPurifier_ElementDefTest extends HTMLPurifier_Harness
|
class HTMLPurifier_ElementDefTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_mergeIn() {
|
function test_mergeIn() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/Encoder.php';
|
require_once 'HTMLPurifier/Encoder.php';
|
||||||
|
|
||||||
class HTMLPurifier_EncoderTest extends HTMLPurifier_Harness
|
class HTMLPurifier_EncoderTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $_entity_lookup;
|
var $_entity_lookup;
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/EntityLookup.php';
|
require_once 'HTMLPurifier/EntityLookup.php';
|
||||||
|
|
||||||
class HTMLPurifier_EntityLookupTest extends HTMLPurifier_Harness
|
class HTMLPurifier_EntityLookupTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/EntityParser.php';
|
require_once 'HTMLPurifier/EntityParser.php';
|
||||||
|
|
||||||
class HTMLPurifier_EntityParserTest extends HTMLPurifier_Harness
|
class HTMLPurifier_EntityParserTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $EntityParser;
|
var $EntityParser;
|
||||||
|
@@ -25,7 +25,7 @@ class HTMLPurifier_ErrorCollectorEMock extends HTMLPurifier_ErrorCollectorMock
|
|||||||
$this->_expected_context_at[$step][$key] = $value;
|
$this->_expected_context_at[$step][$key] = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function send($severity, $msg) {
|
function send() {
|
||||||
// test for context
|
// test for context
|
||||||
$test = &$this->_getCurrentTestCase();
|
$test = &$this->_getCurrentTestCase();
|
||||||
foreach ($this->_expected_context as $key => $value) {
|
foreach ($this->_expected_context as $key => $value) {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/ErrorCollector.php';
|
require_once 'HTMLPurifier/ErrorCollector.php';
|
||||||
|
|
||||||
class HTMLPurifier_ErrorCollectorTest extends HTMLPurifier_Harness
|
class HTMLPurifier_ErrorCollectorTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function setup() {
|
function setup() {
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
require_once 'HTMLPurifier/ErrorCollectorEMock.php';
|
require_once 'HTMLPurifier/ErrorCollectorEMock.php';
|
||||||
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
||||||
|
|
||||||
class HTMLPurifier_ErrorsHarness extends HTMLPurifier_Harness
|
class HTMLPurifier_ErrorsHarness extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $config, $context;
|
var $config, $context;
|
||||||
|
@@ -3,16 +3,16 @@
|
|||||||
require_once 'HTMLPurifier/Generator.php';
|
require_once 'HTMLPurifier/Generator.php';
|
||||||
require_once 'HTMLPurifier/EntityLookup.php';
|
require_once 'HTMLPurifier/EntityLookup.php';
|
||||||
|
|
||||||
require_once 'HTMLPurifier/ComplexHarness.php';
|
require_once 'HTMLPurifier/Harness.php';
|
||||||
|
|
||||||
class HTMLPurifier_GeneratorTest extends HTMLPurifier_ComplexHarness
|
class HTMLPurifier_GeneratorTest extends HTMLPurifier_Harness
|
||||||
{
|
{
|
||||||
|
|
||||||
var $gen;
|
var $gen;
|
||||||
var $_entity_lookup;
|
var $_entity_lookup;
|
||||||
|
|
||||||
function HTMLPurifier_GeneratorTest() {
|
function HTMLPurifier_GeneratorTest() {
|
||||||
$this->HTMLPurifier_Harness();
|
$this->UnitTestCase();
|
||||||
$this->gen = new HTMLPurifier_Generator();
|
$this->gen = new HTMLPurifier_Generator();
|
||||||
$this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
|
$this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
|
||||||
}
|
}
|
||||||
|
@@ -2,18 +2,13 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/HTMLDefinition.php';
|
require_once 'HTMLPurifier/HTMLDefinition.php';
|
||||||
|
|
||||||
class HTMLPurifier_HTMLDefinitionTest extends HTMLPurifier_Harness
|
class HTMLPurifier_HTMLDefinitionTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_parseTinyMCEAllowedList() {
|
function test_parseTinyMCEAllowedList() {
|
||||||
|
|
||||||
$def = new HTMLPurifier_HTMLDefinition();
|
$def = new HTMLPurifier_HTMLDefinition();
|
||||||
|
|
||||||
$this->assertEqual(
|
|
||||||
$def->parseTinyMCEAllowedList(''),
|
|
||||||
array(array(), array())
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->assertEqual(
|
$this->assertEqual(
|
||||||
$def->parseTinyMCEAllowedList('a,b,c'),
|
$def->parseTinyMCEAllowedList('a,b,c'),
|
||||||
array(array('a' => true, 'b' => true, 'c' => true), array())
|
array(array('a' => true, 'b' => true, 'c' => true), array())
|
||||||
|
@@ -1,56 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/HTMLModuleHarness.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_HTMLModule_RubyTest extends HTMLPurifier_HTMLModuleHarness
|
|
||||||
{
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
$this->config->set('HTML', 'Doctype', 'XHTML 1.1');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testBasicUse() {
|
|
||||||
$this->assertResult(
|
|
||||||
'<ruby><rb>WWW</rb><rt>World Wide Web</rt></ruby>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRPUse() {
|
|
||||||
$this->assertResult(
|
|
||||||
'<ruby><rb>WWW</rb><rp>(</rp><rt>World Wide Web</rt><rp>)</rp></ruby>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testComplexUse() {
|
|
||||||
$this->assertResult(
|
|
||||||
'<ruby>
|
|
||||||
<rbc>
|
|
||||||
<rb>10</rb>
|
|
||||||
<rb>31</rb>
|
|
||||||
<rb>2002</rb>
|
|
||||||
</rbc>
|
|
||||||
<rtc>
|
|
||||||
<rt>Month</rt>
|
|
||||||
<rt>Day</rt>
|
|
||||||
<rt>Year</rt>
|
|
||||||
</rtc>
|
|
||||||
<rtc>
|
|
||||||
<rt rbspan="3">Expiration Date</rt>
|
|
||||||
</rtc>
|
|
||||||
</ruby>'
|
|
||||||
);
|
|
||||||
|
|
||||||
/* not implemented
|
|
||||||
function testBackwardsCompat() {
|
|
||||||
$this->assertResult(
|
|
||||||
'<ruby>A<rp>(</rp><rt>aaa</rt><rp>)</rp></ruby>',
|
|
||||||
'<ruby><rb>A</rb><rp>(</rp><rt>aaa</rt><rp>)</rp></ruby>'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@@ -8,7 +8,7 @@ Mock::generatePartial(
|
|||||||
array('makeFixes', 'makeFixesForLevel', 'populate')
|
array('makeFixes', 'makeFixesForLevel', 'populate')
|
||||||
);
|
);
|
||||||
|
|
||||||
class HTMLPurifier_HTMLModule_TidyTest extends HTMLPurifier_Harness
|
class HTMLPurifier_HTMLModule_TidyTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_getFixesForLevel() {
|
function test_getFixesForLevel() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/HTMLModuleManager.php';
|
require_once 'HTMLPurifier/HTMLModuleManager.php';
|
||||||
|
|
||||||
class HTMLPurifier_HTMLModuleManagerTest extends HTMLPurifier_Harness
|
class HTMLPurifier_HTMLModuleManagerTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_addModule() {
|
function test_addModule() {
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
require_once 'HTMLPurifier/HTMLModule.php';
|
require_once 'HTMLPurifier/HTMLModule.php';
|
||||||
require_once 'HTMLPurifier/AttrDef.php';
|
require_once 'HTMLPurifier/AttrDef.php';
|
||||||
|
|
||||||
class HTMLPurifier_HTMLModuleTest extends HTMLPurifier_Harness
|
class HTMLPurifier_HTMLModuleTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test_addElementToContentSet() {
|
function test_addElementToContentSet() {
|
||||||
|
@@ -1,59 +1,128 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIParser.php';
|
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All-use harness, use this rather than SimpleTest's
|
* General-purpose test-harness that makes testing functions that require
|
||||||
|
* configuration and context objects easier when those two parameters are
|
||||||
|
* meaningless. See HTMLPurifier_ChildDefTest for a good example of usage.
|
||||||
*/
|
*/
|
||||||
class HTMLPurifier_Harness extends UnitTestCase
|
class HTMLPurifier_Harness extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of the object that will execute the method
|
||||||
|
*/
|
||||||
|
var $obj;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the function to be executed
|
||||||
|
*/
|
||||||
|
var $func;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the method deals in tokens. If set to true, assertResult()
|
||||||
|
* will transparently convert HTML to and back from tokens.
|
||||||
|
*/
|
||||||
|
var $to_tokens = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to convert tokens back into HTML before performing
|
||||||
|
* equality check, has no effect on bools.
|
||||||
|
*/
|
||||||
|
var $to_html = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of an HTMLPurifier_Lexer implementation.
|
||||||
|
*/
|
||||||
|
var $lexer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance of HTMLPurifier_Generator
|
||||||
|
*/
|
||||||
|
var $generator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default config to fall back on if no config is available
|
||||||
|
*/
|
||||||
|
var $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default context to fall back on if no context is available
|
||||||
|
*/
|
||||||
|
var $context;
|
||||||
|
|
||||||
function HTMLPurifier_Harness() {
|
function HTMLPurifier_Harness() {
|
||||||
|
$this->lexer = new HTMLPurifier_Lexer_DirectLex();
|
||||||
|
$this->generator = new HTMLPurifier_Generator();
|
||||||
parent::UnitTestCase();
|
parent::UnitTestCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
var $config, $context;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates easily accessible default config/context
|
* Asserts a specific result from a one parameter + config/context function
|
||||||
|
* @param $input Input parameter
|
||||||
|
* @param $expect Expectation
|
||||||
|
* @param $config Configuration array in form of Ns.Directive => Value.
|
||||||
|
* Has no effect if $this->config is set.
|
||||||
|
* @param $context_array Context array in form of Key => Value or an actual
|
||||||
|
* context object.
|
||||||
*/
|
*/
|
||||||
function setUp() {
|
function assertResult($input, $expect = true,
|
||||||
list($this->config, $this->context) = $this->createCommon();
|
$config_array = array(), $context_array = array()
|
||||||
}
|
) {
|
||||||
|
|
||||||
/**
|
// setup config
|
||||||
* Accepts config and context and prepares them into a valid state
|
if ($this->config) {
|
||||||
* @param &$config Reference to config variable
|
$config = HTMLPurifier_Config::create($this->config);
|
||||||
* @param &$context Reference to context variable
|
$config->loadArray($config_array);
|
||||||
*/
|
|
||||||
function prepareCommon(&$config, &$context) {
|
|
||||||
$config = HTMLPurifier_Config::create($config);
|
|
||||||
if (!$context) $context = new HTMLPurifier_Context();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates default configuration and context objects
|
|
||||||
* @return Defaults in form of array($config, $context)
|
|
||||||
*/
|
|
||||||
function createCommon() {
|
|
||||||
return array(HTMLPurifier_Config::createDefault(), new HTMLPurifier_Context);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If $expect is false, ignore $result and check if status failed.
|
|
||||||
* Otherwise, check if $status if true and $result === $expect.
|
|
||||||
* @param $status Boolean status
|
|
||||||
* @param $result Mixed result from processing
|
|
||||||
* @param $expect Mixed expectation for result
|
|
||||||
*/
|
|
||||||
function assertEitherFailOrIdentical($status, $result, $expect) {
|
|
||||||
if ($expect === false) {
|
|
||||||
$this->assertFalse($status, 'Expected false result, got true');
|
|
||||||
} else {
|
} else {
|
||||||
$this->assertTrue($status, 'Expected true result, got false');
|
$config = HTMLPurifier_Config::create($config_array);
|
||||||
$this->assertIdentical($result, $expect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// setup context object. Note that we are operating on a copy of it!
|
||||||
|
// When necessary, extend the test harness to allow post-tests
|
||||||
|
// on the context object
|
||||||
|
if (empty($this->context)) {
|
||||||
|
$context = new HTMLPurifier_Context();
|
||||||
|
$context->loadArray($context_array);
|
||||||
|
} else {
|
||||||
|
$context =& $this->context;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->to_tokens && is_string($input)) {
|
||||||
|
// $func may cause $input to change, so "clone" another copy
|
||||||
|
// to sacrifice
|
||||||
|
$input = $this->lexer->tokenizeHTML($s = $input, $config, $context);
|
||||||
|
$input_c = $this->lexer->tokenizeHTML($s, $config, $context);
|
||||||
|
} else {
|
||||||
|
$input_c = $input;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call the function
|
||||||
|
$func = $this->func;
|
||||||
|
$result = $this->obj->$func($input_c, $config, $context);
|
||||||
|
|
||||||
|
// test a bool result
|
||||||
|
if (is_bool($result)) {
|
||||||
|
$this->assertIdentical($expect, $result);
|
||||||
|
return;
|
||||||
|
} elseif (is_bool($expect)) {
|
||||||
|
$expect = $input;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->to_html) {
|
||||||
|
$result = $this->generator->
|
||||||
|
generateFromTokens($result, $config, $context);
|
||||||
|
if (is_array($expect)) {
|
||||||
|
$expect = $this->generator->
|
||||||
|
generateFromTokens($expect, $config, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertIdentical($expect, $result);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/IDAccumulator.php';
|
require_once 'HTMLPurifier/IDAccumulator.php';
|
||||||
|
|
||||||
class HTMLPurifier_IDAccumulatorTest extends HTMLPurifier_Harness
|
class HTMLPurifier_IDAccumulatorTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/LanguageFactory.php';
|
require_once 'HTMLPurifier/LanguageFactory.php';
|
||||||
|
|
||||||
class HTMLPurifier_LanguageFactoryTest extends HTMLPurifier_Harness
|
class HTMLPurifier_LanguageFactoryTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/Language.php';
|
require_once 'HTMLPurifier/Language.php';
|
||||||
|
|
||||||
class HTMLPurifier_LanguageTest extends HTMLPurifier_Harness
|
class HTMLPurifier_LanguageTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $lang;
|
var $lang;
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
||||||
|
|
||||||
class HTMLPurifier_Lexer_DirectLexTest extends HTMLPurifier_Harness
|
class HTMLPurifier_Lexer_DirectLexTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $DirectLex;
|
var $DirectLex;
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
require_once 'HTMLPurifier/Lexer/DirectLex.php';
|
||||||
|
|
||||||
class HTMLPurifier_LexerTest extends HTMLPurifier_Harness
|
class HTMLPurifier_LexerTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $Lexer;
|
var $Lexer;
|
||||||
@@ -16,8 +16,9 @@ class HTMLPurifier_LexerTest extends HTMLPurifier_Harness
|
|||||||
|
|
||||||
$this->DirectLex = new HTMLPurifier_Lexer_DirectLex();
|
$this->DirectLex = new HTMLPurifier_Lexer_DirectLex();
|
||||||
|
|
||||||
|
// E_STRICT = 2048, int used for PHP4 compat
|
||||||
if ( $GLOBALS['HTMLPurifierTest']['PEAR'] &&
|
if ( $GLOBALS['HTMLPurifierTest']['PEAR'] &&
|
||||||
((error_reporting() & E_STRICT) != E_STRICT)
|
((error_reporting() & 2048) != 2048)
|
||||||
) {
|
) {
|
||||||
$this->_has_pear = true;
|
$this->_has_pear = true;
|
||||||
require_once 'HTMLPurifier/Lexer/PEARSax3.php';
|
require_once 'HTMLPurifier/Lexer/PEARSax3.php';
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/PercentEncoder.php';
|
require_once 'HTMLPurifier/PercentEncoder.php';
|
||||||
|
|
||||||
class HTMLPurifier_PercentEncoderTest extends HTMLPurifier_Harness
|
class HTMLPurifier_PercentEncoderTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
var $PercentEncoder;
|
var $PercentEncoder;
|
||||||
|
@@ -15,7 +15,7 @@ class HTMLPurifier_Strategy_Composite_Test
|
|||||||
}
|
}
|
||||||
|
|
||||||
// doesn't use Strategy harness
|
// doesn't use Strategy harness
|
||||||
class HTMLPurifier_Strategy_CompositeTest extends HTMLPurifier_Harness
|
class HTMLPurifier_Strategy_CompositeTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@@ -63,6 +63,12 @@ class HTMLPurifier_Strategy_FixNestingTest extends HTMLPurifier_StrategyHarness
|
|||||||
'<span><ins>Not allowed!</ins></span>'
|
'<span><ins>Not allowed!</ins></span>'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->assertResult( // alt config
|
||||||
|
'<span><ins><div>Not allowed!</div></ins></span>',
|
||||||
|
'<span><ins><div>Not allowed!</div></ins></span>',
|
||||||
|
array('Core.EscapeInvalidChildren' => true)
|
||||||
|
);
|
||||||
|
|
||||||
// test block element that has inline content
|
// test block element that has inline content
|
||||||
$this->assertResult(
|
$this->assertResult(
|
||||||
'<h1><ins><div>Not allowed!</div></ins></h1>',
|
'<h1><ins><div>Not allowed!</div></ins></h1>',
|
||||||
@@ -78,12 +84,6 @@ class HTMLPurifier_Strategy_FixNestingTest extends HTMLPurifier_StrategyHarness
|
|||||||
'<div><ins><del><div>Allowed!</div></del></ins></div>'
|
'<div><ins><del><div>Allowed!</div></del></ins></div>'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->assertResult( // alt config
|
|
||||||
'<span><ins><div>Not allowed!</div></ins></span>',
|
|
||||||
'<span><ins><div>Not allowed!</div></ins></span>',
|
|
||||||
array('Core.EscapeInvalidChildren' => true)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testExclusionsIntegration() {
|
function testExclusionsIntegration() {
|
||||||
|
@@ -49,7 +49,7 @@ class HTMLPurifier_Strategy_RemoveForeignElements_ErrorsTest extends HTMLPurifie
|
|||||||
}
|
}
|
||||||
|
|
||||||
function testScriptRemoved() {
|
function testScriptRemoved() {
|
||||||
$this->collector->expectAt(0, 'send', array(E_ERROR, 'Strategy_RemoveForeignElements: Foreign meta element removed'));
|
$this->collector->expectAt(0, 'send', array(E_ERROR, 'Strategy_RemoveForeignElements: Script removed'));
|
||||||
$this->collector->expectContextAt(0, 'CurrentToken', new HTMLPurifier_Token_Start('script', array(), 1));
|
$this->collector->expectContextAt(0, 'CurrentToken', new HTMLPurifier_Token_Start('script', array(), 1));
|
||||||
$this->collector->expectAt(1, 'send', array(E_ERROR, 'Strategy_RemoveForeignElements: Token removed to end', 'script'));
|
$this->collector->expectAt(1, 'send', array(E_ERROR, 'Strategy_RemoveForeignElements: Token removed to end', 'script'));
|
||||||
$this->invoke('<script>asdf');
|
$this->invoke('<script>asdf');
|
||||||
|
@@ -1,12 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once 'HTMLPurifier/ComplexHarness.php';
|
require_once 'HTMLPurifier/Harness.php';
|
||||||
|
|
||||||
class HTMLPurifier_StrategyHarness extends HTMLPurifier_ComplexHarness
|
class HTMLPurifier_StrategyHarness extends HTMLPurifier_Harness
|
||||||
{
|
{
|
||||||
|
|
||||||
function setUp() {
|
function setUp() {
|
||||||
parent::setUp();
|
|
||||||
$this->func = 'execute';
|
$this->func = 'execute';
|
||||||
$this->to_tokens = true;
|
$this->to_tokens = true;
|
||||||
$this->to_html = true;
|
$this->to_html = true;
|
||||||
|
@@ -6,7 +6,7 @@ require_once 'HTMLPurifier/TagTransform.php';
|
|||||||
require_once 'HTMLPurifier/TagTransform/Font.php';
|
require_once 'HTMLPurifier/TagTransform/Font.php';
|
||||||
require_once 'HTMLPurifier/TagTransform/Simple.php';
|
require_once 'HTMLPurifier/TagTransform/Simple.php';
|
||||||
|
|
||||||
class HTMLPurifier_TagTransformTest extends HTMLPurifier_Harness
|
class HTMLPurifier_TagTransformTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/TokenFactory.php';
|
require_once 'HTMLPurifier/TokenFactory.php';
|
||||||
|
|
||||||
class HTMLPurifier_TokenFactoryTest extends HTMLPurifier_Harness
|
class HTMLPurifier_TokenFactoryTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
public function test() {
|
public function test() {
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/Token.php';
|
require_once 'HTMLPurifier/Token.php';
|
||||||
|
|
||||||
class HTMLPurifier_TokenTest extends HTMLPurifier_Harness
|
class HTMLPurifier_TokenTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function assertTokenConstruction($name, $attr,
|
function assertTokenConstruction($name, $attr,
|
||||||
|
@@ -1,59 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIHarness.php';
|
|
||||||
require_once 'HTMLPurifier/URIDefinition.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIDefinitionTest extends HTMLPurifier_URIHarness
|
|
||||||
{
|
|
||||||
|
|
||||||
function createFilterMock($expect = true, $result = true) {
|
|
||||||
generate_mock_once('HTMLPurifier_URIFilter');
|
|
||||||
$mock = new HTMLPurifier_URIFilterMock();
|
|
||||||
if ($expect) $mock->expectOnce('filter');
|
|
||||||
else $mock->expectNever('filter');
|
|
||||||
$mock->setReturnValue('filter', $result);
|
|
||||||
return $mock;
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_filter() {
|
|
||||||
$def = new HTMLPurifier_URIDefinition();
|
|
||||||
$def->filters[] = $this->createFilterMock();
|
|
||||||
$def->filters[] = $this->createFilterMock();
|
|
||||||
$uri = $this->createURI('test');
|
|
||||||
$this->assertTrue($def->filter($uri, $this->config, $this->context));
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_filter_earlyAbortIfFail() {
|
|
||||||
$def = new HTMLPurifier_URIDefinition();
|
|
||||||
$def->filters[] = $this->createFilterMock(true, false);
|
|
||||||
$def->filters[] = $this->createFilterMock(false); // never called
|
|
||||||
$uri = $this->createURI('test');
|
|
||||||
$this->assertFalse($def->filter($uri, $this->config, $this->context));
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_setupMemberVariables_collisionPrecedenceIsHostBaseScheme() {
|
|
||||||
$this->config->set('URI', 'Host', $host = 'example.com');
|
|
||||||
$this->config->set('URI', 'Base', $base = 'http://sub.example.com/foo/bar.html');
|
|
||||||
$this->config->set('URI', 'DefaultScheme', 'ftp');
|
|
||||||
$def = new HTMLPurifier_URIDefinition();
|
|
||||||
$def->setupMemberVariables($this->config);
|
|
||||||
$this->assertIdentical($def->host, $host);
|
|
||||||
$this->assertIdentical($def->base, $this->createURI($base));
|
|
||||||
$this->assertIdentical($def->defaultScheme, 'http'); // not ftp!
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_setupMemberVariables_onlyScheme() {
|
|
||||||
$this->config->set('URI', 'DefaultScheme', 'ftp');
|
|
||||||
$def = new HTMLPurifier_URIDefinition();
|
|
||||||
$def->setupMemberVariables($this->config);
|
|
||||||
$this->assertIdentical($def->defaultScheme, 'ftp');
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_setupMemberVariables_onlyBase() {
|
|
||||||
$this->config->set('URI', 'Base', 'http://sub.example.com/foo/bar.html');
|
|
||||||
$def = new HTMLPurifier_URIDefinition();
|
|
||||||
$def->setupMemberVariables($this->config);
|
|
||||||
$this->assertIdentical($def->host, 'sub.example.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,24 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIFilter/DisableExternalTest.php';
|
|
||||||
require_once 'HTMLPurifier/URIFilter/DisableExternalResources.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIFilter_DisableExternalResourcesTest extends
|
|
||||||
HTMLPurifier_URIFilter_DisableExternalTest
|
|
||||||
{
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
$this->filter = new HTMLPurifier_URIFilter_DisableExternalResources();
|
|
||||||
$var = true;
|
|
||||||
$this->context->register('EmbeddedURI', $var);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPreserveWhenNotEmbedded() {
|
|
||||||
$this->context->destroy('EmbeddedURI'); // undo setUp
|
|
||||||
$this->assertFiltering(
|
|
||||||
'http://example.com'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,47 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIFilter/DisableExternal.php';
|
|
||||||
require_once 'HTMLPurifier/URIFilterHarness.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIFilter_DisableExternalTest extends HTMLPurifier_URIFilterHarness
|
|
||||||
{
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
$this->filter = new HTMLPurifier_URIFilter_DisableExternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRemoveExternal() {
|
|
||||||
$this->assertFiltering(
|
|
||||||
'http://example.com', false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPreserveInternal() {
|
|
||||||
$this->assertFiltering(
|
|
||||||
'/foo/bar'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPreserveOurHost() {
|
|
||||||
$this->config->set('URI', 'Host', 'example.com');
|
|
||||||
$this->assertFiltering(
|
|
||||||
'http://example.com'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPreserveOurSubdomain() {
|
|
||||||
$this->config->set('URI', 'Host', 'example.com');
|
|
||||||
$this->assertFiltering(
|
|
||||||
'http://www.example.com'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRemoveSuperdomain() {
|
|
||||||
$this->config->set('URI', 'Host', 'www.example.com');
|
|
||||||
$this->assertFiltering(
|
|
||||||
'http://example.com', false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,30 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIFilter/HostBlacklist.php';
|
|
||||||
require_once 'HTMLPurifier/URIFilterHarness.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIFilter_HostBlacklistTest extends HTMLPurifier_URIFilterHarness
|
|
||||||
{
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
$this->filter = new HTMLPurifier_URIFilter_HostBlacklist();
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRejectBlacklistedHost() {
|
|
||||||
$this->config->set('URI', 'HostBlacklist', 'example.com');
|
|
||||||
$this->assertFiltering('http://example.com', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRejectBlacklistedHostThoughNotTrue() {
|
|
||||||
// maybe this behavior should change
|
|
||||||
$this->config->set('URI', 'HostBlacklist', 'example.com');
|
|
||||||
$this->assertFiltering('http://example.comcast.com', false);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPreserveNonBlacklistedHost() {
|
|
||||||
$this->config->set('URI', 'HostBlacklist', 'example.com');
|
|
||||||
$this->assertFiltering('http://google.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,122 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIFilter/MakeAbsolute.php';
|
|
||||||
require_once 'HTMLPurifier/URIFilterHarness.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIFilter_MakeAbsoluteTest extends HTMLPurifier_URIFilterHarness
|
|
||||||
{
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
parent::setUp();
|
|
||||||
$this->filter = new HTMLPurifier_URIFilter_MakeAbsolute();
|
|
||||||
$this->setBase();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setBase($base = 'http://example.com/foo/bar.html?q=s#frag') {
|
|
||||||
$this->config->set('URI', 'Base', $base);
|
|
||||||
}
|
|
||||||
|
|
||||||
// corresponding to RFC 2396
|
|
||||||
|
|
||||||
function testPreserveAbsolute() {
|
|
||||||
$this->assertFiltering('http://example.com/foo.html');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterBlank() {
|
|
||||||
$this->assertFiltering('', 'http://example.com/foo/bar.html?q=s');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterEmptyPath() {
|
|
||||||
$this->assertFiltering('?q=s#frag', 'http://example.com/foo/bar.html?q=s#frag');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPreserveAltScheme() {
|
|
||||||
$this->assertFiltering('mailto:bob@example.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterIgnoreHTTPSpecialCase() {
|
|
||||||
$this->assertFiltering('http:/', 'http://example.com/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterAbsolutePath() {
|
|
||||||
$this->assertFiltering('/foo.txt', 'http://example.com/foo.txt');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePath() {
|
|
||||||
$this->assertFiltering('baz.txt', 'http://example.com/foo/baz.txt');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathWithInternalDot() {
|
|
||||||
$this->assertFiltering('./baz.txt', 'http://example.com/foo/baz.txt');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathWithEndingDot() {
|
|
||||||
$this->assertFiltering('baz/.', 'http://example.com/foo/baz/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathDot() {
|
|
||||||
$this->assertFiltering('.', 'http://example.com/foo/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathWithInternalDotDot() {
|
|
||||||
$this->assertFiltering('../baz.txt', 'http://example.com/baz.txt');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathWithEndingDotDot() {
|
|
||||||
$this->assertFiltering('..', 'http://example.com/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathTooManyDotDots() {
|
|
||||||
$this->assertFiltering('../../', 'http://example.com/');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterAppendingQueryAndFragment() {
|
|
||||||
$this->assertFiltering('/foo.php?q=s#frag', 'http://example.com/foo.php?q=s#frag');
|
|
||||||
}
|
|
||||||
|
|
||||||
// edge cases below
|
|
||||||
|
|
||||||
function testFilterAbsolutePathBase() {
|
|
||||||
$this->setBase('/foo/baz.txt');
|
|
||||||
$this->assertFiltering('test.php', '/foo/test.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterAbsolutePathBaseDirectory() {
|
|
||||||
$this->setBase('/foo/');
|
|
||||||
$this->assertFiltering('test.php', '/foo/test.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterAbsolutePathBaseBelow() {
|
|
||||||
$this->setBase('/foo/baz.txt');
|
|
||||||
$this->assertFiltering('../../test.php', '/test.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathBase() {
|
|
||||||
$this->setBase('foo/baz.html');
|
|
||||||
$this->assertFiltering('foo.php', 'foo/foo.php');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathBaseBelow() {
|
|
||||||
$this->setBase('../baz.html');
|
|
||||||
$this->assertFiltering('test/strike.html', '../test/strike.html');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathBaseWithAbsoluteURI() {
|
|
||||||
$this->setBase('../baz.html');
|
|
||||||
$this->assertFiltering('/test/strike.html');
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFilterRelativePathBaseWithDot() {
|
|
||||||
$this->setBase('../baz.html');
|
|
||||||
$this->assertFiltering('.', '../');
|
|
||||||
}
|
|
||||||
|
|
||||||
// error case
|
|
||||||
|
|
||||||
function testErrorNoBase() {
|
|
||||||
$this->setBase(null);
|
|
||||||
$this->expectError('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration');
|
|
||||||
$this->assertFiltering('foo/bar.txt');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,15 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIHarness.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIFilterHarness extends HTMLPurifier_URIHarness
|
|
||||||
{
|
|
||||||
|
|
||||||
function assertFiltering($uri, $expect_uri = true) {
|
|
||||||
$this->prepareURI($uri, $expect_uri);
|
|
||||||
$this->filter->prepare($this->config, $this->context);
|
|
||||||
$result = $this->filter->filter($uri, $this->config, $this->context);
|
|
||||||
$this->assertEitherFailOrIdentical($result, $uri, $expect_uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,31 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIParser.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIHarness extends HTMLPurifier_Harness
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepares two URIs into object form
|
|
||||||
* @param &$uri Reference to string input URI
|
|
||||||
* @param &$expect_uri Reference to string expectation URI
|
|
||||||
* @note If $expect_uri is false, it will stay false
|
|
||||||
*/
|
|
||||||
function prepareURI(&$uri, &$expect_uri) {
|
|
||||||
$parser = new HTMLPurifier_URIParser();
|
|
||||||
if ($expect_uri === true) $expect_uri = $uri;
|
|
||||||
$uri = $parser->parse($uri);
|
|
||||||
if ($expect_uri !== false) {
|
|
||||||
$expect_uri = $parser->parse($expect_uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a URI object from the corresponding string
|
|
||||||
*/
|
|
||||||
function createURI($uri) {
|
|
||||||
$parser = new HTMLPurifier_URIParser();
|
|
||||||
return $parser->parse($uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,140 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIParser.php';
|
|
||||||
require_once 'HTMLPurifier/URI.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URIParserTest extends HTMLPurifier_Harness
|
|
||||||
{
|
|
||||||
|
|
||||||
function assertParsing(
|
|
||||||
$uri, $scheme, $userinfo, $host, $port, $path, $query, $fragment, $config = null, $context = null
|
|
||||||
) {
|
|
||||||
$this->prepareCommon($config, $context);
|
|
||||||
$parser = new HTMLPurifier_URIParser();
|
|
||||||
$result = $parser->parse($uri, $config, $context);
|
|
||||||
$expect = new HTMLPurifier_URI($scheme, $userinfo, $host, $port, $path, $query, $fragment);
|
|
||||||
$this->assertEqual($result, $expect);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRegular() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://www.example.com/webhp?q=foo#result2',
|
|
||||||
'http', null, 'www.example.com', null, '/webhp', 'q=foo', 'result2'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPortAndUsername() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://user@authority.part:80/now/the/path?query#fragment',
|
|
||||||
'http', 'user', 'authority.part', 80, '/now/the/path', 'query', 'fragment'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPercentEncoding() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://en.wikipedia.org/wiki/Clich%C3%A9',
|
|
||||||
'http', null, 'en.wikipedia.org', null, '/wiki/Clich%C3%A9', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testEmptyQuery() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://www.example.com/?#',
|
|
||||||
'http', null, 'www.example.com', null, '/', '', null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testEmptyPath() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://www.example.com',
|
|
||||||
'http', null, 'www.example.com', null, '', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testOpaqueURI() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'mailto:bob@example.com',
|
|
||||||
'mailto', null, null, null, 'bob@example.com', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIPv4Address() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://192.0.34.166/',
|
|
||||||
'http', null, '192.0.34.166', null, '/', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testFakeIPv4Address() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://333.123.32.123/',
|
|
||||||
'http', null, '333.123.32.123', null, '/', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testIPv6Address() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://[2001:db8::7]/c=GB?objectClass?one',
|
|
||||||
'http', null, '[2001:db8::7]', null, '/c=GB', 'objectClass?one', null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testInternationalizedDomainName() {
|
|
||||||
$this->assertParsing(
|
|
||||||
"http://t\xC5\xABdali\xC5\x86.lv",
|
|
||||||
'http', null, "t\xC5\xABdali\xC5\x86.lv", null, '', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testInvalidPort() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://example.com:foobar',
|
|
||||||
'http', null, 'example.com', null, '', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPathAbsolute() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http:/this/is/path',
|
|
||||||
'http', null, null, null, '/this/is/path', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPathRootless() {
|
|
||||||
// this should not be used but is allowed
|
|
||||||
$this->assertParsing(
|
|
||||||
'http:this/is/path',
|
|
||||||
'http', null, null, null, 'this/is/path', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testPathEmpty() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http:',
|
|
||||||
'http', null, null, null, '', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testRelativeURI() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'/a/b',
|
|
||||||
null, null, null, null, '/a/b', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testMalformedTag() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'http://www.example.com/\'>"',
|
|
||||||
'http', null, 'www.example.com', null, '/', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function testEmpty() {
|
|
||||||
$this->assertParsing(
|
|
||||||
'',
|
|
||||||
null, null, null, null, '', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
require_once 'HTMLPurifier/URISchemeRegistry.php';
|
require_once 'HTMLPurifier/URISchemeRegistry.php';
|
||||||
|
|
||||||
class HTMLPurifier_URISchemeRegistryTest extends HTMLPurifier_Harness
|
class HTMLPurifier_URISchemeRegistryTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@@ -1,9 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URI.php';
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIScheme.php';
|
require_once 'HTMLPurifier/URIScheme.php';
|
||||||
require_once 'HTMLPurifier/URISchemeRegistry.php';
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URIScheme/http.php';
|
require_once 'HTMLPurifier/URIScheme/http.php';
|
||||||
require_once 'HTMLPurifier/URIScheme/ftp.php';
|
require_once 'HTMLPurifier/URIScheme/ftp.php';
|
||||||
@@ -15,133 +12,145 @@ require_once 'HTMLPurifier/URIScheme/nntp.php';
|
|||||||
// WARNING: All the URI schemes are far to relaxed, we need to tighten
|
// WARNING: All the URI schemes are far to relaxed, we need to tighten
|
||||||
// the checks.
|
// the checks.
|
||||||
|
|
||||||
class HTMLPurifier_URISchemeTest extends HTMLPurifier_URIHarness
|
class HTMLPurifier_URISchemeTest extends UnitTestCase
|
||||||
{
|
{
|
||||||
|
|
||||||
function assertValidation($uri, $expect_uri = true) {
|
function test_http() {
|
||||||
$this->prepareURI($uri, $expect_uri);
|
$scheme = new HTMLPurifier_URIScheme_http();
|
||||||
// convenience hack: the scheme should be explicitly specified
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
$scheme = $uri->getSchemeObj($this->config, $this->context);
|
$context = new HTMLPurifier_Context();
|
||||||
$result = $scheme->validate($uri, $this->config, $this->context);
|
|
||||||
$this->assertEitherFailOrIdentical($result, $uri, $expect_uri);
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, 'www.example.com', null, '/', 's=foobar', $config, $context),
|
||||||
|
array(null, 'www.example.com', null, '/', 's=foobar')
|
||||||
|
);
|
||||||
|
|
||||||
|
// absorb default port and userinfo
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
'user', 'www.example.com', 80, '/', 's=foobar', $config, $context),
|
||||||
|
array(null, 'www.example.com', null, '/', 's=foobar')
|
||||||
|
);
|
||||||
|
|
||||||
|
// do not absorb non-default port
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, 'www.example.com', 8080, '/', 's=foobar', $config, $context),
|
||||||
|
array(null, 'www.example.com', 8080, '/', 's=foobar')
|
||||||
|
);
|
||||||
|
|
||||||
|
// https is basically the same
|
||||||
|
|
||||||
|
$scheme = new HTMLPurifier_URIScheme_https();
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
'user', 'www.example.com', 443, '/', 's=foobar', $config, $context),
|
||||||
|
array(null, 'www.example.com', null, '/', 's=foobar')
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_http_regular() {
|
function test_ftp() {
|
||||||
$this->assertValidation(
|
|
||||||
'http://example.com/?s=q#fragment'
|
$scheme = new HTMLPurifier_URIScheme_ftp();
|
||||||
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
|
$context = new HTMLPurifier_Context();
|
||||||
|
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
'user', 'www.example.com', 21, '/', 's=foobar', $config, $context),
|
||||||
|
array('user', 'www.example.com', null, '/', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
// valid typecode
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, 'www.example.com', null, '/file.txt;type=a', null, $config, $context),
|
||||||
|
array(null, 'www.example.com', null, '/file.txt;type=a', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove invalid typecode
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, 'www.example.com', null, '/file.txt;type=z', null, $config, $context),
|
||||||
|
array(null, 'www.example.com', null, '/file.txt', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
// encode errant semicolons
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, 'www.example.com', null, '/too;many;semicolons=1', null, $config, $context),
|
||||||
|
array(null, 'www.example.com', null, '/too%3Bmany%3Bsemicolons=1', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_news() {
|
||||||
|
|
||||||
|
$scheme = new HTMLPurifier_URIScheme_news();
|
||||||
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
|
$context = new HTMLPurifier_Context();
|
||||||
|
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, null, null, 'gmane.science.linguistics', null, $config, $context),
|
||||||
|
array(null, null, null, 'gmane.science.linguistics', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, null, null, '642@eagle.ATT.COM', null, $config, $context),
|
||||||
|
array(null, null, null, '642@eagle.ATT.COM', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
// test invalid field removal
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
'user', 'www.google.com', 80, 'rec.music', 'path=foo', $config, $context),
|
||||||
|
array(null, null, null, 'rec.music', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_nntp() {
|
||||||
|
|
||||||
|
$scheme = new HTMLPurifier_URIScheme_nntp();
|
||||||
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
|
$context = new HTMLPurifier_Context();
|
||||||
|
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, 'news.example.com', null, '/alt.misc/12345', null, $config, $context),
|
||||||
|
array(null, 'news.example.com', null, '/alt.misc/12345', null)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
'user', 'news.example.com', 119, '/alt.misc/12345', 'foo=asdf', $config, $context),
|
||||||
|
array(null, 'news.example.com', null, '/alt.misc/12345', null)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function test_http_removeDefaultPort() {
|
function test_mailto() {
|
||||||
$this->assertValidation(
|
|
||||||
'http://example.com:80',
|
$scheme = new HTMLPurifier_URIScheme_mailto();
|
||||||
'http://example.com'
|
$config = HTMLPurifier_Config::createDefault();
|
||||||
|
$context = new HTMLPurifier_Context();
|
||||||
|
|
||||||
|
$this->assertIdentical(
|
||||||
|
$scheme->validateComponents(
|
||||||
|
null, null, null, 'bob@example.com', null, $config, $context),
|
||||||
|
array(null, null, null, 'bob@example.com', null)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
$this->assertIdentical(
|
||||||
function test_http_removeUserInfo() {
|
$scheme->validateComponents(
|
||||||
$this->assertValidation(
|
'user', 'example.com', 80, 'bob@example.com', 'subject=Foo!', $config, $context),
|
||||||
'http://bob@example.com',
|
array(null, null, null, 'bob@example.com', 'subject=Foo!')
|
||||||
'http://example.com'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_http_preserveNonDefaultPort() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'http://example.com:8080'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_https_regular() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'https://user@example.com:443/?s=q#frag',
|
|
||||||
'https://example.com/?s=q#frag'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_ftp_regular() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'ftp://user@example.com/path'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_ftp_removeDefaultPort() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'ftp://example.com:21',
|
|
||||||
'ftp://example.com'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_ftp_removeQueryString() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'ftp://example.com?s=q',
|
|
||||||
'ftp://example.com'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_ftp_preserveValidTypecode() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'ftp://example.com/file.txt;type=a'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_ftp_removeInvalidTypecode() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'ftp://example.com/file.txt;type=z',
|
|
||||||
'ftp://example.com/file.txt'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_ftp_encodeExtraSemicolons() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'ftp://example.com/too;many;semicolons=1',
|
|
||||||
'ftp://example.com/too%3Bmany%3Bsemicolons=1'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_news_regular() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'news:gmane.science.linguistics'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_news_explicit() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'news:642@eagle.ATT.COM'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_news_removeNonPathComponents() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'news://user@example.com:80/rec.music?path=foo#frag',
|
|
||||||
'news:/rec.music#frag'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_nntp_regular() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'nntp://news.example.com/alt.misc/42#frag'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_nntp_removalOfRedundantOrUselessComponents() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'nntp://user@news.example.com:119/alt.misc/42?s=q#frag',
|
|
||||||
'nntp://news.example.com/alt.misc/42#frag'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_mailto_regular() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'mailto:bob@example.com'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_mailto_removalOfRedundantOrUselessComponents() {
|
|
||||||
$this->assertValidation(
|
|
||||||
'mailto://user@example.com:80/bob@example.com?subject=Foo#frag',
|
|
||||||
'mailto:/bob@example.com?subject=Foo#frag'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -1,166 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once 'HTMLPurifier/URI.php';
|
|
||||||
require_once 'HTMLPurifier/URIParser.php';
|
|
||||||
|
|
||||||
class HTMLPurifier_URITest extends HTMLPurifier_URIHarness
|
|
||||||
{
|
|
||||||
|
|
||||||
function createURI($uri) {
|
|
||||||
$parser = new HTMLPurifier_URIParser();
|
|
||||||
return $parser->parse($uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_construct() {
|
|
||||||
$uri1 = new HTMLPurifier_URI('HTTP', 'bob', 'example.com', '23', '/foo', 'bar=2', 'slash');
|
|
||||||
$uri2 = new HTMLPurifier_URI('http', 'bob', 'example.com', 23, '/foo', 'bar=2', 'slash');
|
|
||||||
$this->assertIdentical($uri1, $uri2);
|
|
||||||
}
|
|
||||||
|
|
||||||
var $oldRegistry;
|
|
||||||
|
|
||||||
function &setUpSchemeRegistryMock() {
|
|
||||||
$this->oldRegistry = HTMLPurifier_URISchemeRegistry::instance();
|
|
||||||
generate_mock_once('HTMLPurifier_URIScheme');
|
|
||||||
generate_mock_once('HTMLPurifier_URISchemeRegistry');
|
|
||||||
$registry =& HTMLPurifier_URISchemeRegistry::instance(
|
|
||||||
new HTMLPurifier_URISchemeRegistryMock()
|
|
||||||
);
|
|
||||||
return $registry;
|
|
||||||
}
|
|
||||||
|
|
||||||
function &setUpSchemeMock($name) {
|
|
||||||
$registry =& $this->setUpSchemeRegistryMock();
|
|
||||||
$scheme_mock = new HTMLPurifier_URISchemeMock();
|
|
||||||
$registry->setReturnValue('getScheme', $scheme_mock, array($name, '*', '*'));
|
|
||||||
return $scheme_mock;
|
|
||||||
}
|
|
||||||
|
|
||||||
function setUpNoValidSchemes() {
|
|
||||||
$registry =& $this->setUpSchemeRegistryMock();
|
|
||||||
$registry->setReturnValue('getScheme', false, array('*', '*', '*'));
|
|
||||||
}
|
|
||||||
|
|
||||||
function tearDownSchemeRegistryMock() {
|
|
||||||
HTMLPurifier_URISchemeRegistry::instance($this->oldRegistry);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_getSchemeObj() {
|
|
||||||
$scheme_mock =& $this->setUpSchemeMock('http');
|
|
||||||
|
|
||||||
$uri = $this->createURI('http:');
|
|
||||||
$scheme_obj = $uri->getSchemeObj($this->config, $this->context);
|
|
||||||
$this->assertIdentical($scheme_obj, $scheme_mock);
|
|
||||||
|
|
||||||
$this->tearDownSchemeRegistryMock();
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_getSchemeObj_invalidScheme() {
|
|
||||||
$this->setUpNoValidSchemes();
|
|
||||||
|
|
||||||
$uri = $this->createURI('http:');
|
|
||||||
$result = $uri->getSchemeObj($this->config, $this->context);
|
|
||||||
$this->assertIdentical($result, false);
|
|
||||||
|
|
||||||
$this->tearDownSchemeRegistryMock();
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_getSchemaObj_defaultScheme() {
|
|
||||||
$scheme = 'foobar';
|
|
||||||
|
|
||||||
$scheme_mock =& $this->setUpSchemeMock($scheme);
|
|
||||||
$this->config->set('URI', 'DefaultScheme', $scheme);
|
|
||||||
|
|
||||||
$uri = $this->createURI('hmm');
|
|
||||||
$scheme_obj = $uri->getSchemeObj($this->config, $this->context);
|
|
||||||
$this->assertIdentical($scheme_obj, $scheme_mock);
|
|
||||||
|
|
||||||
$this->tearDownSchemeRegistryMock();
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_getSchemaObj_invalidDefaultScheme() {
|
|
||||||
$this->setUpNoValidSchemes();
|
|
||||||
$this->config->set('URI', 'DefaultScheme', 'foobar');
|
|
||||||
|
|
||||||
$uri = $this->createURI('hmm');
|
|
||||||
|
|
||||||
$this->expectError('Default scheme object "foobar" was not readable');
|
|
||||||
$result = $uri->getSchemeObj($this->config, $this->context);
|
|
||||||
$this->assertIdentical($result, false);
|
|
||||||
|
|
||||||
$this->tearDownSchemeRegistryMock();
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertToString($expect_uri, $scheme, $userinfo, $host, $port, $path, $query, $fragment) {
|
|
||||||
$uri = new HTMLPurifier_URI($scheme, $userinfo, $host, $port, $path, $query, $fragment);
|
|
||||||
$string = $uri->toString();
|
|
||||||
$this->assertIdentical($string, $expect_uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_toString_full() {
|
|
||||||
$this->assertToString(
|
|
||||||
'http://bob@example.com:300/foo?bar=baz#fragment',
|
|
||||||
'http', 'bob', 'example.com', 300, '/foo', 'bar=baz', 'fragment'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_toString_scheme() {
|
|
||||||
$this->assertToString(
|
|
||||||
'http:',
|
|
||||||
'http', null, null, null, '', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_toString_authority() {
|
|
||||||
$this->assertToString(
|
|
||||||
'//bob@example.com:8080',
|
|
||||||
null, 'bob', 'example.com', 8080, '', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_toString_path() {
|
|
||||||
$this->assertToString(
|
|
||||||
'/path/to',
|
|
||||||
null, null, null, null, '/path/to', null, null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_toString_query() {
|
|
||||||
$this->assertToString(
|
|
||||||
'?q=string',
|
|
||||||
null, null, null, null, '', 'q=string', null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_toString_fragment() {
|
|
||||||
$this->assertToString(
|
|
||||||
'#fragment',
|
|
||||||
null, null, null, null, '', null, 'fragment'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function assertValidation($uri, $expect_uri = true) {
|
|
||||||
if ($expect_uri === true) $expect_uri = $uri;
|
|
||||||
$uri = $this->createURI($uri);
|
|
||||||
$result = $uri->validate($this->config, $this->context);
|
|
||||||
if ($expect_uri === false) {
|
|
||||||
$this->assertFalse($result);
|
|
||||||
} else {
|
|
||||||
$this->assertTrue($result);
|
|
||||||
$this->assertIdentical($uri->toString(), $expect_uri);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_validate_overlongPort() {
|
|
||||||
$this->assertValidation('http://example.com:65536', 'http://example.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_validate_zeroPort() {
|
|
||||||
$this->assertValidation('http://example.com:00', 'http://example.com');
|
|
||||||
}
|
|
||||||
|
|
||||||
function test_validate_invalidHostThatLooksLikeIPv6() {
|
|
||||||
$this->assertValidation('http://[2001:0db8:85z3:08d3:1319:8a2e:0370:7334]', 'http:');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -3,7 +3,7 @@
|
|||||||
// call one file using /?f=FileTest.php , see $test_files array for
|
// call one file using /?f=FileTest.php , see $test_files array for
|
||||||
// valid values
|
// valid values
|
||||||
|
|
||||||
error_reporting(E_ALL | E_STRICT);
|
error_reporting(E_ALL);
|
||||||
define('HTMLPurifierTest', 1);
|
define('HTMLPurifierTest', 1);
|
||||||
|
|
||||||
// wishlist: automated calling of this file from multiple PHP versions so we
|
// wishlist: automated calling of this file from multiple PHP versions so we
|
||||||
|
@@ -79,7 +79,6 @@ $test_files[] = 'HTMLPurifier/GeneratorTest.php';
|
|||||||
$test_files[] = 'HTMLPurifier/HTMLDefinitionTest.php';
|
$test_files[] = 'HTMLPurifier/HTMLDefinitionTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/HTMLModuleManagerTest.php';
|
$test_files[] = 'HTMLPurifier/HTMLModuleManagerTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/HTMLModuleTest.php';
|
$test_files[] = 'HTMLPurifier/HTMLModuleTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/HTMLModule/RubyTest.php';
|
|
||||||
$test_files[] = 'HTMLPurifier/HTMLModule/ScriptingTest.php';
|
$test_files[] = 'HTMLPurifier/HTMLModule/ScriptingTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/HTMLModule/TidyTest.php';
|
$test_files[] = 'HTMLPurifier/HTMLModule/TidyTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/IDAccumulatorTest.php';
|
$test_files[] = 'HTMLPurifier/IDAccumulatorTest.php';
|
||||||
@@ -103,15 +102,8 @@ $test_files[] = 'HTMLPurifier/Strategy/RemoveForeignElements_ErrorsTest.php';
|
|||||||
$test_files[] = 'HTMLPurifier/Strategy/ValidateAttributesTest.php';
|
$test_files[] = 'HTMLPurifier/Strategy/ValidateAttributesTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/TagTransformTest.php';
|
$test_files[] = 'HTMLPurifier/TagTransformTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/TokenTest.php';
|
$test_files[] = 'HTMLPurifier/TokenTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/URIDefinitionTest.php';
|
|
||||||
$test_files[] = 'HTMLPurifier/URIFilter/DisableExternalTest.php';
|
|
||||||
$test_files[] = 'HTMLPurifier/URIFilter/DisableExternalResourcesTest.php';
|
|
||||||
$test_files[] = 'HTMLPurifier/URIFilter/HostBlacklistTest.php';
|
|
||||||
$test_files[] = 'HTMLPurifier/URIFilter/MakeAbsoluteTest.php';
|
|
||||||
$test_files[] = 'HTMLPurifier/URIParserTest.php';
|
|
||||||
$test_files[] = 'HTMLPurifier/URISchemeRegistryTest.php';
|
$test_files[] = 'HTMLPurifier/URISchemeRegistryTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/URISchemeTest.php';
|
$test_files[] = 'HTMLPurifier/URISchemeTest.php';
|
||||||
$test_files[] = 'HTMLPurifier/URITest.php';
|
|
||||||
$test_files[] = 'HTMLPurifierTest.php';
|
$test_files[] = 'HTMLPurifierTest.php';
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, '5', '>=')) {
|
if (version_compare(PHP_VERSION, '5', '>=')) {
|
||||||
|
Reference in New Issue
Block a user