mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2025-08-02 20:27:40 +02:00
Compare commits
268 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
6d50e5282a | ||
|
5bc7c72608 | ||
|
98984546d4 | ||
|
c7a2f6f0df | ||
|
fd24de69a3 | ||
|
5688656174 | ||
|
d728205767 | ||
|
8836ae05aa | ||
|
b90295deda | ||
|
de82f9845f | ||
|
9d2d75d8bc | ||
|
74f123a84c | ||
|
7e11c271b9 | ||
|
66bbae73a9 | ||
|
5886326cd0 | ||
|
564af61809 | ||
|
b19dcb0ba5 | ||
|
586abc63e4 | ||
|
5b6a3f55bf | ||
|
0c31b22240 | ||
|
5662efc936 | ||
|
353c96f156 | ||
|
4047a6230b | ||
|
9195cb7a2e | ||
|
39c4c359ad | ||
|
bb3f86e80a | ||
|
d16e73e63e | ||
|
f145f64bf4 | ||
|
5fdec87fe9 | ||
|
4462559459 | ||
|
12185143ef | ||
|
17a90a951a | ||
|
0bab4b9fd0 | ||
|
bd92f3531b | ||
|
0d5ab2fe13 | ||
|
d41a59e422 | ||
|
8e4cacf0a7 | ||
|
c82051c3e1 | ||
|
d4a96463ef | ||
|
1b7d684d07 | ||
|
5070404376 | ||
|
cef27f750d | ||
|
59463c5c39 | ||
|
d19d648a26 | ||
|
20b40a5441 | ||
|
34d252cbbc | ||
|
8b28e571fe | ||
|
3ae21ce511 | ||
|
3ba9133b21 | ||
|
dc8702160c | ||
|
4dc68aa920 | ||
|
08eee90e15 | ||
|
1ef4375dbb | ||
|
6a221a3045 | ||
|
246fc8946a | ||
|
1ce2fde400 | ||
|
1f982d279f | ||
|
8be8cee9b3 | ||
|
d0c392f77d | ||
|
d1c5d75027 | ||
|
3747cb7efb | ||
|
0166c3728b | ||
|
ed180f595d | ||
|
3e4deabbb3 | ||
|
44baee6a82 | ||
|
1675fc7caf | ||
|
cc35c8eb8c | ||
|
a11aeab4a6 | ||
|
43a9f052fd | ||
|
b4981c3395 | ||
|
f14076dc3e | ||
|
91fd55c857 | ||
|
096064dd0a | ||
|
845edf16e2 | ||
|
2c4f889ca4 | ||
|
b3856d2040 | ||
|
6e00b443cd | ||
|
7e49ff3dcd | ||
|
1f3e282fde | ||
|
753c830239 | ||
|
72123e23c9 | ||
|
45161b4fb1 | ||
|
25db9e1dd0 | ||
|
92aabf2b23 | ||
|
aebe1c02a2 | ||
|
913ac6955b | ||
|
958ba65595 | ||
|
ae1828d955 | ||
|
e34a858ca9 | ||
|
2c963dcc7f | ||
|
bfbf8a9da1 | ||
|
04cf6c8739 | ||
|
0d7328dbb2 | ||
|
7aeedd9071 | ||
|
c67e4c2f7e | ||
|
0c3e68dd03 | ||
|
b307f3d9ef | ||
|
cd60294ada | ||
|
39d3df1fd7 | ||
|
b8704535a3 | ||
|
4da38aca80 | ||
|
bf84df4f7d | ||
|
15d1a3003a | ||
|
80ebd4322e | ||
|
18b8a0e44a | ||
|
6f389f0f25 | ||
|
8cd08620dc | ||
|
0beecad78a | ||
|
54477c172b | ||
|
e52d1fe310 | ||
|
0767bbc12d | ||
|
b3640e1af6 | ||
|
be5769804a | ||
|
d6fbd7df22 | ||
|
804a06f01e | ||
|
8f401f769e | ||
|
82bcc62058 | ||
|
f17490f009 | ||
|
a5fc37d8c3 | ||
|
412bae13b5 | ||
|
cf44f399f8 | ||
|
fac747bdbd | ||
|
19eee14899 | ||
|
25d49f4ec0 | ||
|
53c2907706 | ||
|
af7107e830 | ||
|
107b3055a1 | ||
|
29a3c70370 | ||
|
75bd7abcc7 | ||
|
0680832d41 | ||
|
19360ddb36 | ||
|
3c903b7463 | ||
|
6e37ecd1c8 | ||
|
20eff0a3a0 | ||
|
d516e2f8de | ||
|
631021733b | ||
|
344e0640b6 | ||
|
62d2550e16 | ||
|
087145a71b | ||
|
a44187a5c1 | ||
|
c0ad68108a | ||
|
83a574491e | ||
|
3b537365a4 | ||
|
8a8b123d33 | ||
|
72db575446 | ||
|
d8bb73ce46 | ||
|
f90372f8ab | ||
|
f38fca32a9 | ||
|
5a23004652 | ||
|
6705140082 | ||
|
cb7162a995 | ||
|
2189a9430f | ||
|
7291f19347 | ||
|
9fcffd6533 | ||
|
31dce298ea | ||
|
8c9d461a62 | ||
|
7291a9647e | ||
|
17af0e4fc1 | ||
|
70028f83d6 | ||
|
5c5e3fe79f | ||
|
56a26cab14 | ||
|
1c7fedff5a | ||
|
9de0785448 | ||
|
974fe3f25e | ||
|
94468f3c24 | ||
|
e0354fecd9 | ||
|
1bbbc624dd | ||
|
49879d2cc6 | ||
|
5c9b5130c8 | ||
|
d2de8d976a | ||
|
4164b2eb2b | ||
|
1e5293d9fe | ||
|
6b643ede02 | ||
|
e41af46a8b | ||
|
3570c9985a | ||
|
8d572993b4 | ||
|
1bacbc0563 | ||
|
bfe2c10d07 | ||
|
9b10515fa4 | ||
|
1255d0f15d | ||
|
d45e11cc6b | ||
|
94c15d1f56 | ||
|
ce68cfe484 | ||
|
9f5f85952b | ||
|
dbb365155b | ||
|
32c0ffde0c | ||
|
856a5e5b89 | ||
|
820d6e9097 | ||
|
35b1fbce01 | ||
|
bcfbb8338c | ||
|
f51a6f7de9 | ||
|
f1439f0af5 | ||
|
0124605918 | ||
|
afb007d22f | ||
|
0dd9e4faf4 | ||
|
94ed3b1231 | ||
|
6a6c0ed5d7 | ||
|
e05b555448 | ||
|
ee9c70ab7f | ||
|
b4469f17aa | ||
|
e76f4b45d0 | ||
|
a32d5b52e1 | ||
|
a3d71fe606 | ||
|
77982bd61d | ||
|
78c4e62245 | ||
|
5803c06765 | ||
|
b63569ac22 | ||
|
f3d050c517 | ||
|
6dcc37cb55 | ||
|
cfc4ee1faf | ||
|
598c5b60c9 | ||
|
c9e7ffc172 | ||
|
feeffe6ed2 | ||
|
4754d407aa | ||
|
0b9db1f54b | ||
|
1d4a38d055 | ||
|
8c80349f9d | ||
|
d848c99b74 | ||
|
882ffed9ba | ||
|
86990a21f1 | ||
|
9573f0933d | ||
|
632bf2bbd4 | ||
|
ec86598446 | ||
|
b6c3f5e89b | ||
|
7c91104532 | ||
|
eac628f490 | ||
|
92913bc816 | ||
|
479d793562 | ||
|
e2c15f1c98 | ||
|
57ced3f361 | ||
|
c04a441b3e | ||
|
1bed8b6d5f | ||
|
33afd7d9e0 | ||
|
18e538317a | ||
|
96a4193fc9 | ||
|
00c66fa9cb | ||
|
d3abcb90e3 | ||
|
df3100b1b3 | ||
|
143e1ad718 | ||
|
875b0febde | ||
|
3166b8a10f | ||
|
1a70bffd5a | ||
|
f4c6e10ff7 | ||
|
c1cbd9e565 | ||
|
da94d3d6ac | ||
|
80793e925e | ||
|
8ef4fb22db | ||
|
70a7a3f5dd | ||
|
4d612d5a77 | ||
|
63a854ee5d | ||
|
0229458f8f | ||
|
baa477ac08 | ||
|
dc90e8e85b | ||
|
97125ed18b | ||
|
9a9036c689 | ||
|
aea7d02dfe | ||
|
b3ca1498c2 | ||
|
ac18672aba | ||
|
faf28682ad | ||
|
e2cd852bcf | ||
|
694583259c | ||
|
bde4de3c78 | ||
|
5b4e5c983e | ||
|
1ad8fd5ce9 | ||
|
6bdf161afd | ||
|
af45a6c191 | ||
|
2b72d0445f | ||
|
d7b3117678 |
14
.gitattributes
vendored
14
.gitattributes
vendored
@@ -1 +1,13 @@
|
||||
configdoc/usage.xml -crlf
|
||||
/.gitattributes export-ignore
|
||||
/.gitignore export-ignore
|
||||
/.travis.yml export-ignore
|
||||
/Doxyfile export-ignore
|
||||
/art/ export-ignore
|
||||
/benchmarks/ export-ignore
|
||||
/configdoc/ export-ignore
|
||||
/configdoc/usage.xml -crlf
|
||||
/docs/ export-ignore
|
||||
/phpdoc.ini
|
||||
/smoketests/ export-ignore
|
||||
/tests/* export-ignore
|
||||
/tests/path2class.func.php -export-ignore
|
||||
|
8
.gitignore
vendored
8
.gitignore
vendored
@@ -18,3 +18,11 @@ docs/doxygen*
|
||||
*.phpt.php
|
||||
*.phpt.skip.php
|
||||
*.htmlt.ini
|
||||
*.patch
|
||||
/*.php
|
||||
vendor
|
||||
composer.lock
|
||||
*.rej
|
||||
*.orig
|
||||
*.bak
|
||||
core
|
||||
|
13
.travis.yml
Normal file
13
.travis.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
language: php
|
||||
php:
|
||||
- '5.3'
|
||||
- '5.4'
|
||||
- '5.5'
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
before_script:
|
||||
- git clone --depth=50 https://github.com/ezyang/simpletest.git
|
||||
- cp test-settings.travis.php test-settings.php
|
||||
script:
|
||||
- php tests/index.php
|
2
Doxyfile
2
Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME = HTMLPurifier
|
||||
# This could be handy for archiving the generated documentation or
|
||||
# if some version control system is used.
|
||||
|
||||
PROJECT_NUMBER = 4.0.0
|
||||
PROJECT_NUMBER = 4.9.2
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
|
||||
# base path where the generated documentation will be put.
|
||||
|
13
FOCUS
13
FOCUS
@@ -1,13 +0,0 @@
|
||||
5 - Major feature enhancements
|
||||
|
||||
[ Appendix A: Release focus IDs ]
|
||||
0 - N/A
|
||||
1 - Initial freshmeat announcement
|
||||
2 - Documentation
|
||||
3 - Code cleanup
|
||||
4 - Minor feature enhancements
|
||||
5 - Major feature enhancements
|
||||
6 - Minor bugfixes
|
||||
7 - Major bugfixes
|
||||
8 - Minor security fixes
|
||||
9 - Major security fixes
|
26
INSTALL
26
INSTALL
@@ -15,9 +15,8 @@ with these contents.
|
||||
---------------------------------------------------------------------------
|
||||
1. Compatibility
|
||||
|
||||
HTML Purifier is PHP 5 only, and is actively tested from PHP 5.0.5 and
|
||||
up. It has no core dependencies with other libraries. PHP
|
||||
4 support was deprecated on December 31, 2007 with HTML Purifier 3.0.0.
|
||||
HTML Purifier is PHP 5 and PHP 7, and is actively tested from PHP 5.0.5
|
||||
and up. It has no core dependencies with other libraries.
|
||||
|
||||
These optional extensions can enhance the capabilities of HTML Purifier:
|
||||
|
||||
@@ -25,6 +24,13 @@ These optional extensions can enhance the capabilities of HTML Purifier:
|
||||
* bcmath : Used for unit conversion and imagecrash protection
|
||||
* tidy : Used for pretty-printing HTML
|
||||
|
||||
These optional libraries can enhance the capabilities of HTML Purifier:
|
||||
|
||||
* CSSTidy : Clean CSS stylesheets using %Core.ExtractStyleBlocks
|
||||
Note: You should use the modernized fork of CSSTidy available
|
||||
at https://github.com/Cerdic/CSSTidy
|
||||
* Net_IDNA2 (PEAR) : IRI support using %Core.EnableIDNA
|
||||
Note: This is not necessary for PHP 5.3 or later
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
2. Reconnaissance
|
||||
@@ -300,11 +306,9 @@ appropriate permissions using:
|
||||
chmod -R 0755 HTMLPurifier/DefinitionCache/Serializer
|
||||
|
||||
If the above command doesn't work, you may need to assign write permissions
|
||||
to all. This may be necessary if your webserver runs as nobody, but is
|
||||
not recommended since it means any other user can write files in the
|
||||
directory. Use:
|
||||
to group:
|
||||
|
||||
chmod -R 0777 HTMLPurifier/DefinitionCache/Serializer
|
||||
chmod -R 0775 HTMLPurifier/DefinitionCache/Serializer
|
||||
|
||||
You can also chmod files via your FTP client; this option
|
||||
is usually accessible by right clicking the corresponding directory and
|
||||
@@ -330,11 +334,6 @@ Or move the cache directory somewhere else (no trailing slash):
|
||||
|
||||
The interface is mind-numbingly simple:
|
||||
|
||||
$purifier = new HTMLPurifier();
|
||||
$clean_html = $purifier->purify( $dirty_html );
|
||||
|
||||
...or, if you're using the configuration object:
|
||||
|
||||
$purifier = new HTMLPurifier($config);
|
||||
$clean_html = $purifier->purify( $dirty_html );
|
||||
|
||||
@@ -353,7 +352,8 @@ If your website is in UTF-8 and XHTML Transitional, use this code:
|
||||
<?php
|
||||
require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
|
||||
|
||||
$purifier = new HTMLPurifier();
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$purifier = new HTMLPurifier($config);
|
||||
$clean_html = $purifier->purify($dirty_html);
|
||||
?>
|
||||
|
||||
|
@@ -1,69 +1,60 @@
|
||||
|
||||
|
||||
Installation
|
||||
Comment installer HTML Purifier
|
||||
|
||||
Attention: Ce document a encode en UTF-8. Si les lettres avec les accents
|
||||
est essoreuse, prenez un mieux editeur de texte.
|
||||
|
||||
À L'Aide: Je ne suis pas un diseur natif de français. Si vous trouvez une
|
||||
erreur dans ce document, racontez-moi! Merci.
|
||||
|
||||
|
||||
L'installation de HTML Purifier est trés simple, parce qu'il ne doit pas
|
||||
la configuration. Dans le pied de de document, les utilisateurs
|
||||
impatient peuvent trouver le code, mais je recommande que vous lisez
|
||||
ce document pour quelques choses.
|
||||
Attention : Ce document est encodé en UTF-8, si les lettres avec des accents
|
||||
ne s'affichent pas, prenez un meilleur éditeur de texte.
|
||||
|
||||
L'installation de HTML Purifier est très simple, parce qu'il n'a pas besoin
|
||||
de configuration. Pour les utilisateurs impatients, le code se trouve dans le
|
||||
pied de page, mais je recommande de lire le document.
|
||||
|
||||
1. Compatibilité
|
||||
|
||||
HTML Purifier fonctionne dans PHP 5. PHP 5.0.5 est le dernier
|
||||
version que je le testais. Il ne dépend de les autre librairies.
|
||||
HTML Purifier fonctionne avec PHP 5. PHP 5.0.5 est la dernière version testée.
|
||||
Il ne dépend pas d'autres librairies.
|
||||
|
||||
Les extensions optionnel est iconv (en général déjà installer) et
|
||||
tidy (répandu aussi). Si vous utilisez UTF-8 et ne voulez pas
|
||||
l'indentation, vous pouvez utiliser HTML Purifier sans ces extensions.
|
||||
Les extensions optionnelles sont iconv (généralement déjà installée) et tidy
|
||||
(répendue aussi). Si vous utilisez UTF-8 et que vous ne voulez pas l'indentation,
|
||||
vous pouvez utiliser HTML Purifier sans ces extensions.
|
||||
|
||||
|
||||
2. Inclure la librarie
|
||||
2. Inclure la librairie
|
||||
|
||||
Utilisez:
|
||||
Quand vous devez l'utilisez, incluez le :
|
||||
|
||||
require_once '/path/to/library/HTMLPurifier.auto.php';
|
||||
require_once('/path/to/library/HTMLPurifier.auto.php');
|
||||
|
||||
...quand vous devez utiliser HTML Purifier (ne inclure pas quand vous
|
||||
ne devez pas, parce que HTML Purifier est trés grand.)
|
||||
Ne pas l'inclure si ce n'est pas nécessaire, car HTML Purifier est lourd.
|
||||
|
||||
HTML Purifier utilise 'autoload'. Si vous avez définu la fonction
|
||||
__autoload, vous doivez ajoute cet programme:
|
||||
HTML Purifier utilise "autoload". Si vous avez défini la fonction __autoload,
|
||||
vous devez ajouter cette fonction :
|
||||
|
||||
spl_autoload_register('__autoload')
|
||||
|
||||
Plus d'information est dans le document 'INSTALL'.
|
||||
Plus d'informations dans le document "INSTALL".
|
||||
|
||||
3. Installation rapide
|
||||
|
||||
3. Installation vite
|
||||
|
||||
Si votre site web est en UTF-8 et XHTML Transitional, utilisez:
|
||||
Si votre site Web est en UTF-8 et XHTML Transitional, utilisez :
|
||||
|
||||
<?php
|
||||
require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
|
||||
|
||||
require_once('/path/to/htmlpurifier/library/HTMLPurifier.auto.php');
|
||||
$purificateur = new HTMLPurifier();
|
||||
$html_propre = $purificateur->purify($html_salle);
|
||||
$html_propre = $purificateur->purify($html_a_purifier);
|
||||
?>
|
||||
|
||||
Sinon, utilisez:
|
||||
Sinon, utilisez :
|
||||
|
||||
<?php
|
||||
require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
|
||||
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('Core', 'Encoding', 'ISO-8859-1'); //remplacez avec votre encoding
|
||||
$config->set('Core', 'XHTML', true); //remplacez avec false si HTML 4.01
|
||||
require_once('/path/to/html/purifier/library/HTMLPurifier.auto.load');
|
||||
$config = $HTMLPurifier_Config::createDefault();
|
||||
$config->set('Core', 'Encoding', 'ISO-8859-1'); //Remplacez par votre
|
||||
encodage
|
||||
$config->set('Core', 'XHTML', true); //Remplacer par false si HTML 4.01
|
||||
$purificateur = new HTMLPurifier($config);
|
||||
|
||||
$html_propre = $purificateur->purify($html_salle);
|
||||
$html_propre = $purificateur->purify($html_a_purifier);
|
||||
?>
|
||||
|
||||
|
||||
vim: et sw=4 sts=4
|
||||
|
276
NEWS
276
NEWS
@@ -9,6 +9,282 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
||||
. Internal change
|
||||
==========================
|
||||
|
||||
4.9.2, released 2017-03-12
|
||||
- Fixes PHP 5.3 compatibility
|
||||
- Fix breakage when decoding decimal entities. Thanks @rybakit (#129)
|
||||
|
||||
4.9.1, released 2017-03-08
|
||||
! %URI.DefaultScheme can now be set to null, in which case
|
||||
all relative paths are removed.
|
||||
! New CSS properties: min-width, max-width, min-height, max-height (#94)
|
||||
! Transparency (rgba) and hsl/hsla supported where color CSS is present.
|
||||
Thanks @fxbt for contributing the patch. (#118)
|
||||
- When idn_to_ascii is defined, we might accept malformed
|
||||
hostnames. Apply validation to the result in such cases.
|
||||
- Close directory when done in Serializer DefinitionCache (#100)
|
||||
- Deleted some asserts to avoid linters from choking (#97)
|
||||
- Rework Serializer cache behavior to avoid chmod'ing if possible (#32)
|
||||
- Embedded semicolons in strings in CSS are now handled correctly!
|
||||
- We accidentally dropped certain Unicode characters if there was
|
||||
one or more invalid characters. This has been fixed, thanks
|
||||
to mpyw <ryosuke_i_628@yahoo.co.jp>
|
||||
- Fix for "Don't truncate upon encountering </div> when using DOMLex"
|
||||
caused a regression with HTML 4.01 Strict parsing with libxml 2.9.1
|
||||
(and maybe later versions, but known OK with libxml 2.9.4). The
|
||||
fix is to go about handling truncation a bit more cleverly so that
|
||||
we can wrap with divs (sidestepping the bug) but slurping out the
|
||||
rest of the text in case it ran off the end. (#78)
|
||||
- Fix PREG_BACKTRACK_LIMIT_ERROR in HTMLPurifier_Filter_ExtractStyle.
|
||||
Thanks @breathbath for contributing the report and fix (#120)
|
||||
- Fix entity decoding algorithm to be more conservative about
|
||||
decoding entities that are missing trailing semicolon.
|
||||
To get old behavior, set %Core.LegacyEntityDecoder to true.
|
||||
(#119)
|
||||
- Workaround libxml bug when HTML tags are embedded inside
|
||||
script tags. To disable workaround set %Core.AggressivelyRemoveScript
|
||||
to false. (#83)
|
||||
# By default, when a link has a target attribute associated
|
||||
with it, we now also add rel="noopener" in order to
|
||||
prevent the new window from being able to overwrite
|
||||
the original frame. To disable this protection,
|
||||
set %HTML.TargetNoopener to FALSE.
|
||||
|
||||
4.9.0 was cut on Git but never properly released; when we did the
|
||||
real release we decided to skip this version number.
|
||||
|
||||
4.8.0, released 2016-07-16
|
||||
# By default, when a link has a target attribute associated
|
||||
with it, we now also add rel="noreferrer" in order to
|
||||
prevent the new window from being able to overwrite
|
||||
the original frame. To disable this protection,
|
||||
set %HTML.TargetNoreferrer to FALSE.
|
||||
! Full PHP 7 compatibility, the test suite is ALL GO.
|
||||
! %CSS.AllowDuplicates permits duplicate CSS properties.
|
||||
! Support for 'tel' URIs.
|
||||
! Partial support for 'border-radius' properties when %CSS.AllowProprietary is true.
|
||||
The slash syntax, i.e., 'border-radius: 2em 1em 4em / 0.5em 3em' is not
|
||||
yet supported.
|
||||
! %Attr.ID.HTML5 turns on HTML5-style ID handling.
|
||||
- alt truncation could result in malformed UTF-8 sequence. Don't
|
||||
truncate. Thanks Brandon Farber for reporting.
|
||||
- Linkify regex is smarter, based off of Gruber's regex.
|
||||
- IDNA supported natively on PHP 5.3 and later.
|
||||
- Non all-numeric top-level names (e.g., foo.1f, 1f) are now
|
||||
allowed.
|
||||
- Minor bounds error fix to squash a PHP 7 notice.
|
||||
- Support non-/tmp temporary directories for data:// validation
|
||||
- Give a better error message when a user attempts to allow
|
||||
ul/ol without allowing li.
|
||||
- On some versions of PHP, the Serializer DefinitionCache could
|
||||
infinite loop when the directory exists but is not listable. (#49)
|
||||
- Don't match for <body> inside comments with
|
||||
%Core.ConvertDocumentToFragment. (#67)
|
||||
- SafeObject is now less case sensitive. (#57)
|
||||
- AutoFormat.RemoveEmpty.Predicate now correctly renders in
|
||||
web form. (#85)
|
||||
|
||||
4.7.0, released 2015-08-04
|
||||
# opacity is now considered a "tricky" CSS property rather than a
|
||||
proprietary one.
|
||||
! %AutoFormat.RemoveEmpty.Predicate for specifying exactly when
|
||||
an element should be considered "empty" (maybe preserve if it
|
||||
has attributes), and modify iframe support so that the iframe
|
||||
is removed if it is missing a src attribute. Thanks meeva for
|
||||
reporting.
|
||||
- Don't truncate upon encountering </div> when using DOMLex. Thanks
|
||||
Myrto Christina for finally convincing me to fix this.
|
||||
- Update YouTube filter for new code.
|
||||
- Fix parsing of rgb() values with spaces in them for 'border'
|
||||
attribute.
|
||||
- Don't remove foo="" attributes if foo is a boolean attribute. Thanks
|
||||
valME for reporting.
|
||||
|
||||
4.6.0, released 2013-11-30
|
||||
# Secure URI munge hashing algorithm has changed to hash_hmac("sha256", $url, $secret).
|
||||
Please update any verification scripts you may have.
|
||||
# URI parsing algorithm was made more strict, so only prefixes which
|
||||
looks like schemes will actually be schemes. Thanks
|
||||
Michael Gusev <mgusev@sugarcrm.com> for fixing.
|
||||
# %Core.EscapeInvalidChildren is no longer supported, and no longer does
|
||||
anything.
|
||||
! New directive %Core.AllowHostnameUnderscore which allows underscores
|
||||
in hostnames.
|
||||
- Eliminate quadratic behavior in DOMLex by using a proper queue.
|
||||
Thanks Ole Laursen for noticing this.
|
||||
- Rewritten MakeWellFormed/FixNesting implementation eliminates quadratic
|
||||
behavior in the rest of the purificaiton pipeline. Thanks Chedburn
|
||||
Networks for sponsoring this work.
|
||||
- Made Linkify URL parser a bit less permissive, so that non-breaking
|
||||
spaces and commas are not included as part of URL. Thanks nAS for fixing.
|
||||
- Fix some bad interactions with %HTML.Allowed and injectors. Thanks
|
||||
David Hirtz for reporting.
|
||||
- Fix infinite loop in DirectLex. Thanks Ashar Javed (@soaj1664ashar)
|
||||
for reporting.
|
||||
|
||||
4.5.0, released 2013-02-17
|
||||
# Fix bug where stacked attribute transforms clobber each other;
|
||||
this also means it's no longer possible to override attribute
|
||||
transforms in later modules. No internal code was using this
|
||||
but this may break some clients.
|
||||
# We now use SHA-1 to identify cached definitions, instead of MD5.
|
||||
! Support display:inline-block
|
||||
! Support for more white-space CSS values.
|
||||
! Permit underscores in font families
|
||||
! Support for page-break-* CSS3 properties when proprietary properties
|
||||
are enabled.
|
||||
! New directive %Core.DisableExcludes; can be set to 'true' to turn off
|
||||
SGML excludes checking. If HTML Purifier is removing too much text
|
||||
and you don't care about full standards compliance, try setting this to
|
||||
'true'.
|
||||
- Use prepend for SPL autoloading on PHP 5.3 and later.
|
||||
- Fix bug with nofollow transform when pre-existing rel exists.
|
||||
- Fix bug where background:url() always gets lower-cased
|
||||
(but not background-image:url())
|
||||
- Fix bug with non lower-case color names in HTML
|
||||
- Fix bug where data URI validation doesn't remove temporary files.
|
||||
Thanks Javier Marín Ros <javiermarinros@gmail.com> for reporting.
|
||||
- Don't remove certain empty tags on RemoveEmpty.
|
||||
|
||||
4.4.0, released 2012-01-18
|
||||
# Removed PEARSax3 handler.
|
||||
# URI.Munge now munges URIs inside the same host that go from https
|
||||
to http. Reported by Neike Taika-Tessaro.
|
||||
# Core.EscapeNonASCIICharacters now always transforms entities to
|
||||
entities, even if target encoding is UTF-8.
|
||||
# Tighten up selector validation in ExtractStyleBlocks.
|
||||
Non-syntactically valid selectors are now rejected, along with
|
||||
some of the more obscure ones such as attribute selectors, the
|
||||
:lang pseudoselector, and anything not in CSS2.1. Furthermore,
|
||||
ID and class selectors now work properly with the relevant
|
||||
configuration attributes. Also, mute errors when parsing CSS
|
||||
with CSS Tidy. Reported by Mario Heiderich and Norman Hippert.
|
||||
! Added support for 'scope' attribute on tables.
|
||||
! Added %HTML.TargetBlank, which adds target="blank" to all outgoing links.
|
||||
! Properly handle sub-lists directly nested inside of lists in
|
||||
a standards compliant way, by moving them into the preceding <li>
|
||||
! Added %HTML.AllowedComments and %HTML.AllowedCommentsRegexp for
|
||||
limited allowed comments in untrusted situations.
|
||||
! Implement iframes, and allow them to be used in untrusted mode with
|
||||
%HTML.SafeIframe and %URI.SafeIframeRegexp. Thanks Bradley M. Froehle
|
||||
<brad.froehle@gmail.com> for submitting an initial version of the patch.
|
||||
! The Forms module now works properly for transitional doctypes.
|
||||
! Added support for internationalized domain names. You need the PEAR
|
||||
Net_IDNA2 module to be in your path; if it is installed, ensure the
|
||||
class can be loaded and then set %Core.EnableIDNA to true.
|
||||
- Color keywords are now case insensitive. Thanks Yzmir Ramirez
|
||||
<yramirez-htmlpurifier@adicio.com> for reporting.
|
||||
- Explicitly initialize anonModule variable to null.
|
||||
- Do not duplicate nofollow if already present. Thanks 178
|
||||
for reporting.
|
||||
- Do not add nofollow if hostname matches our current host. Thanks 178
|
||||
for reporting, and Neike Taika-Tessaro for helping diagnose.
|
||||
- Do not unset parser variable; this fixes intermittent serialization
|
||||
problems. Thanks Neike Taika-Tessaro for reporting, bill
|
||||
<10010tiger@gmail.com> for diagnosing.
|
||||
- Fix iconv truncation bug, where non-UTF-8 target encodings see
|
||||
output truncated after around 8000 characters. Thanks Jörg Ludwig
|
||||
<joerg.ludwig@iserv.eu> for reporting.
|
||||
- Fix broken table content model for XHTML1.1 (and also earlier
|
||||
versions, although the W3C validator doesn't catch those violations).
|
||||
Thanks GlitchMr <glitch.mr@gmail.com> for reporting.
|
||||
|
||||
4.3.0, released 2011-03-27
|
||||
# Fixed broken caching of customized raw definitions, but requires an
|
||||
API change. The old API still works but will emit a warning,
|
||||
see http://htmlpurifier.org/docs/enduser-customize.html#optimized
|
||||
for how to upgrade your code.
|
||||
# Protect against Internet Explorer innerHTML behavior by specially
|
||||
treating attributes with backticks but no angled brackets, quotes or
|
||||
spaces. This constitutes a slight semantic change, which can be
|
||||
reverted using %Output.FixInnerHTML. Reported by Neike Taika-Tessaro
|
||||
and Mario Heiderich.
|
||||
# Protect against cssText/innerHTML by restricting allowed characters
|
||||
used in fonts further than mandated by the specification and encoding
|
||||
some extra special characters in URLs. Reported by Neike
|
||||
Taika-Tessaro and Mario Heiderich.
|
||||
! Added %HTML.Nofollow to add rel="nofollow" to external links.
|
||||
! More types of SPL autoloaders allowed on later versions of PHP.
|
||||
! Implementations for position, top, left, right, bottom, z-index
|
||||
when %CSS.Trusted is on.
|
||||
! Add %Cache.SerializerPermissions option for custom serializer
|
||||
directory/file permissions
|
||||
! Fix longstanding bug in Flash support for non-IE browsers, and
|
||||
allow more wmode attributes.
|
||||
! Add %CSS.AllowedFonts to restrict permissible font names.
|
||||
- Switch to an iterative traversal of the DOM, which prevents us
|
||||
from running out of stack space for deeply nested documents.
|
||||
Thanks Maxim Krizhanovsky for contributing a patch.
|
||||
- Make removal of conditional IE comments ungreedy; thanks Bernd
|
||||
for reporting.
|
||||
- Escape CDATA before removing Internet Explorer comments.
|
||||
- Fix removal of id attributes under certain conditions by ensuring
|
||||
armor attributes are preserved when recreating tags.
|
||||
- Check if schema.ser was corrupted.
|
||||
- Check if zend.ze1_compatibility_mode is on, and error out if it is.
|
||||
This safety check is only done for HTMLPurifier.auto.php; if you
|
||||
are using standalone or the specialized includes files, you're
|
||||
expected to know what you're doing.
|
||||
- Stop repeatedly writing the cache file after I'm done customizing a
|
||||
raw definition. Reported by ajh.
|
||||
- Switch to using require_once in the Bootstrap to work around bad
|
||||
interaction with Zend Debugger and APC. Reported by Antonio Parraga.
|
||||
- Fix URI handling when hostname is missing but scheme is present.
|
||||
Reported by Neike Taika-Tessaro.
|
||||
- Fix missing numeric entities on DirectLex; thanks Neike Taika-Tessaro
|
||||
for reporting.
|
||||
- Fix harmless notice from indexing into empty string. Thanks Matthijs
|
||||
Kooijman <matthijs@stdin.nl> for reporting.
|
||||
- Don't autoclose no parent elements are able to support the element
|
||||
that triggered the autoclose. In particular fixes strange behavior
|
||||
of stray <li> tags. Thanks pkuliga@gmail.com for reporting and
|
||||
Neike Taika-Tessaro <pinkgothic@gmail.com> for debugging assistance.
|
||||
|
||||
4.2.0, released 2010-09-15
|
||||
! Added %Core.RemoveProcessingInstructions, which lets you remove
|
||||
<? ... ?> statements.
|
||||
! Added %URI.DisableResources functionality; the directive originally
|
||||
did nothing. Thanks David Rothstein for reporting.
|
||||
! Add documentation about configuration directive types.
|
||||
! Add %CSS.ForbiddenProperties configuration directive.
|
||||
! Add %HTML.FlashAllowFullScreen to permit embedded Flash objects
|
||||
to utilize full-screen mode.
|
||||
! Add optional support for the <code>file</code> URI scheme, enable
|
||||
by explicitly setting %URI.AllowedSchemes.
|
||||
! Add %Core.NormalizeNewlines options to allow turning off newline
|
||||
normalization.
|
||||
- Fix improper handling of Internet Explorer conditional comments
|
||||
by parser. Thanks zmonteca for reporting.
|
||||
- Fix missing attributes bug when running on Mac Snow Leopard and APC.
|
||||
Thanks sidepodcast for the fix.
|
||||
- Warn if an element is allowed, but an attribute it requires is
|
||||
not allowed.
|
||||
|
||||
4.1.1, released 2010-05-31
|
||||
- Fix undefined index warnings in maintenance scripts.
|
||||
- Fix bug in DirectLex for parsing elements with a single attribute
|
||||
with entities.
|
||||
- Rewrite CSS output logic for font-family and url(). Thanks Mario
|
||||
Heiderich <mario.heiderich@googlemail.com> for reporting and Takeshi
|
||||
Terada <t-terada@violet.plala.or.jp> for suggesting the fix.
|
||||
- Emit an error for CollectErrors if a body is extracted
|
||||
- Fix bug where in background-position for center keyword handling.
|
||||
- Fix infinite loop when a wrapper element is inserted in a context
|
||||
where it's not allowed. Thanks Lars <lars@renoz.dk> for reporting.
|
||||
- Remove +x bit and shebang from index.php; only supported mode is to
|
||||
explicitly call it with php.
|
||||
- Make test script less chatty when log_errors is on.
|
||||
|
||||
4.1.0, released 2010-04-26
|
||||
! Support proprietary height attribute on table element
|
||||
! Support YouTube slideshows that contain /cp/ in their URL.
|
||||
! Support for data: URI scheme; not enabled by default, add it using
|
||||
%URI.AllowedSchemes
|
||||
! Support flashvars when using %HTML.SafeObject and %HTML.SafeEmbed.
|
||||
! Support for Internet Explorer compatibility with %HTML.SafeObject
|
||||
using %Output.FlashCompat.
|
||||
! Handle <ol><ol> properly, by inserting the necessary <li> tag.
|
||||
- Always quote the insides of url(...) in CSS.
|
||||
|
||||
4.0.0, released 2009-07-07
|
||||
# APIs for ConfigSchema subsystem have substantially changed. See
|
||||
docs/dev-config-bcbreaks.txt for details; in essence, anything that
|
||||
|
@@ -1,6 +1,5 @@
|
||||
|
||||
README
|
||||
All about HTML Purifier
|
||||
HTML Purifier [](http://travis-ci.org/ezyang/htmlpurifier)
|
||||
=============
|
||||
|
||||
HTML Purifier is an HTML filtering solution that uses a unique combination
|
||||
of robust whitelists and agressive parsing to ensure that not only are
|
||||
@@ -19,6 +18,12 @@ Places to go:
|
||||
an in-depth installation guide.
|
||||
* See WYSIWYG for information on editors like TinyMCE and FCKeditor
|
||||
|
||||
HTML Purifier can be found on the web at: http://htmlpurifier.org/
|
||||
HTML Purifier can be found on the web at: [http://htmlpurifier.org/](http://htmlpurifier.org/)
|
||||
|
||||
vim: et sw=4 sts=4
|
||||
## Installation
|
||||
|
||||
Package available on [Composer](https://packagist.org/packages/ezyang/htmlpurifier).
|
||||
|
||||
If you're using Composer to manage dependencies, you can use
|
||||
|
||||
$ composer require "ezyang/htmlpurifier": "dev-master"
|
96
TODO
96
TODO
@@ -11,22 +11,43 @@ If no interest is expressed for a feature that may require a considerable
|
||||
amount of effort to implement, it may get endlessly delayed. Do not be
|
||||
afraid to cast your vote for the next feature to be implemented!
|
||||
|
||||
- Built-in support for target="_blank" on all external links
|
||||
- Incorporate data: support as implemented here:
|
||||
http://htmlpurifier.org/phorum/read.php?3,3491,3548
|
||||
- Fix ImgRequired to handle data correctly
|
||||
- Incorporate download and resize support as implemented here:
|
||||
http://htmlpurifier.org/phorum/read.php?3,2795,3628
|
||||
- Think about allowing explicit order of operations hooks for transforms
|
||||
- Add "register" field to config schemas to eliminate dependence on
|
||||
naming conventions
|
||||
- Add examples to everything (make built-in which also automatically
|
||||
gives output)
|
||||
Things to do as soon as possible:
|
||||
|
||||
- http://htmlpurifier.org/phorum/read.php?3,5560,6307#msg-6307
|
||||
- Think about allowing explicit order of operations hooks for transforms
|
||||
- Fix "<.<" bug (trailing < is removed if not EOD)
|
||||
- Build in better internal state dumps and debugging tools for remote
|
||||
debugging
|
||||
- Allowed/Allowed* have strange interactions when both set
|
||||
? Transform lone embeds into object tags
|
||||
- Deprecated config options that emit warnings when you set them (with'
|
||||
a way of muting the warning if you really want to)
|
||||
- Make HTML.Trusted work with Output.FlashCompat
|
||||
- HTML.Trusted and HTML.SafeObject have funny interaction; general
|
||||
problem is what to do when a module "supersedes" another
|
||||
(see also tables and basic tables.) This is a little dicier
|
||||
because HTML.SafeObject has some extra functionality that
|
||||
trusted might find useful. See http://htmlpurifier.org/phorum/read.php?3,5762,6100
|
||||
|
||||
FUTURE VERSIONS
|
||||
---------------
|
||||
|
||||
4.1 release [It's All About Trust] (floating)
|
||||
4.9 release [OMG CONFIG PONIES]
|
||||
! Fix Printer. It's from the old days when we didn't have decent XML classes
|
||||
! Factor demo.php into a set of Printer classes, and then create a stub
|
||||
file for users here (inside the actual HTML Purifier library)
|
||||
- Fix error handling with form construction
|
||||
- Do encoding validation in Printers, or at least, where user data comes in
|
||||
- Config: Add examples to everything (make built-in which also automatically
|
||||
gives output)
|
||||
- Add "register" field to config schemas to eliminate dependence on
|
||||
naming conventions (try to remember why we ultimately decided on tihs)
|
||||
|
||||
5.0 release [HTML 5]
|
||||
# Swap out code to use html5lib tokenizer and tree-builder
|
||||
! Allow turning off of FixNesting and required attribute insertion
|
||||
|
||||
5.1 release [It's All About Trust] (floating)
|
||||
# Implement untrusted, dangerous elements/attributes
|
||||
# Implement IDREF support (harder than it seems, since you cannot have
|
||||
IDREFs to non-existent IDs)
|
||||
@@ -35,36 +56,23 @@ FUTURE VERSIONS
|
||||
# Frameset XHTML 1.0 and HTML 4.01 doctypes
|
||||
- Figure out how to simultaneously set %CSS.Trusted and %HTML.Trusted (?)
|
||||
|
||||
4.2 release [Error'ed]
|
||||
5.2 release [Error'ed]
|
||||
# Error logging for filtering/cleanup procedures
|
||||
- XSS-attempt detection--certain errors are flagged XSS-like
|
||||
|
||||
4.3 release [Do What I Mean, Not What I Say]
|
||||
# Additional support for poorly written HTML
|
||||
- Microsoft Word HTML cleaning (i.e. MsoNormal, but research essential!)
|
||||
- Friendly strict handling of <address> (block -> <br>)
|
||||
? Remove redundant tags, ex. <u><u>Underlined</u></u>. Implementation notes:
|
||||
1. Analyzing which tags to remove duplicants
|
||||
2. Ensure attributes are merged into the parent tag
|
||||
3. Extend the tag exclusion system to specify whether or not the
|
||||
contents should be dropped or not (currently, there's code that could do
|
||||
something like this if it didn't drop the inner text too.)
|
||||
- Remove <span> tags that don't do anything (no attributes)
|
||||
- XSS-attempt detection--certain errors are flagged XSS-like
|
||||
- Append something to duplicate IDs so they're still usable (impl. note: the
|
||||
dupe detector would also need to detect the suffix as well)
|
||||
- Externalize inline CSS to promote clean HTML, proposed by Sander Tekelenburg
|
||||
|
||||
5.0 release [Beyond HTML]
|
||||
6.0 release [Beyond HTML]
|
||||
# Legit token based CSS parsing (will require revamping almost every
|
||||
AttrDef class). Probably will use CSSTidy class?
|
||||
AttrDef class). Probably will use CSSTidy
|
||||
# More control over allowed CSS properties using a modularization
|
||||
# HTML 5 support
|
||||
# IRI support (this includes IDN)
|
||||
- Standardize token armor for all areas of processing
|
||||
- Convert RTL/LTR override characters to <bdo> tags, or vice versa on demand.
|
||||
Also, enable disabling of directionality
|
||||
|
||||
6.0 release [To XML and Beyond]
|
||||
7.0 release [To XML and Beyond]
|
||||
- Extended HTML capabilities based on namespacing and tag transforms (COMPLEX)
|
||||
- Hooks for adding custom processors to custom namespaced tags and
|
||||
attributes, offer default implementation
|
||||
@@ -75,25 +83,14 @@ Ongoing
|
||||
- Refactor unit tests into lots of test methods
|
||||
- Plugins for major CMSes (COMPLEX)
|
||||
- phpBB
|
||||
- Drupal needs loving!
|
||||
- Phorum need loving!
|
||||
- more! (look for ones that use WYSIWYGs)
|
||||
- Also, maybe a FAQ for extension writers with HTML Purifier
|
||||
- Also, a FAQ for extension writers with HTML Purifier
|
||||
|
||||
AutoFormat
|
||||
- Smileys
|
||||
- Syntax highlighting (with GeSHi) with <pre> and possibly <?php
|
||||
- Look at http://drupal.org/project/Modules/category/63 for ideas
|
||||
|
||||
Optimizations
|
||||
- Reduce size of internal data-structures (esp. HTMLDefinition)
|
||||
- Get PH5P working with the latest versions of DOM, which have much more
|
||||
stringent error checking procedures. Maybe convert straight to tokens.
|
||||
- Get rid of set_include_path(). Save this for another major release.
|
||||
|
||||
Neat feature related
|
||||
! Factor demo.php into a set of Printer classes, and then create a stub
|
||||
file for users here (inside the actual HTML Purifier library)
|
||||
! Support exporting configuration, so users can easily tweak settings
|
||||
in the demo, and then copy-paste into their own setup
|
||||
- Advanced URI filtering schemes (see docs/proposal-new-directives.txt)
|
||||
@@ -110,10 +107,25 @@ Neat feature related
|
||||
- Full set of color keywords. Also, a way to add onto them without
|
||||
finalizing the configuration object.
|
||||
- Write a var_export and memcached DefinitionCache - Denis
|
||||
- Built-in support for target="_blank" on all external links
|
||||
- Convert RTL/LTR override characters to <bdo> tags, or vice versa on demand.
|
||||
Also, enable disabling of directionality
|
||||
? Externalize inline CSS to promote clean HTML, proposed by Sander Tekelenburg
|
||||
? Remove redundant tags, ex. <u><u>Underlined</u></u>. Implementation notes:
|
||||
1. Analyzing which tags to remove duplicants
|
||||
2. Ensure attributes are merged into the parent tag
|
||||
3. Extend the tag exclusion system to specify whether or not the
|
||||
contents should be dropped or not (currently, there's code that could do
|
||||
something like this if it didn't drop the inner text too.)
|
||||
? Make AutoParagraph also support paragraph-izing double <br> tags, and not
|
||||
just double newlines. This is kind of tough to do in the current framework,
|
||||
though, and might be reasonably approximated by search replacing double <br>s
|
||||
with newlines before running it through HTML Purifier.
|
||||
|
||||
Maintenance related (slightly boring)
|
||||
# CHMOD install script for PEAR installs
|
||||
! Factor out command line parser into its own class, and unit test it
|
||||
- Reduce size of internal data-structures (esp. HTMLDefinition)
|
||||
- Allow merging configurations. Thus,
|
||||
a -> b -> default
|
||||
c -> d -> default
|
||||
|
19
WHATSNEW
19
WHATSNEW
@@ -1,7 +1,12 @@
|
||||
HTML Purifier 4.0 is a major feature release focused on configuration
|
||||
It deprecates the $config->set('Ns', 'Directive', $value) syntax for
|
||||
$config->set('Ns.Directive', $value); both syntaxes work but the
|
||||
former will throw errors. There are also some new features: robust
|
||||
support for name/id, configuration inheritance, remove nbsp in
|
||||
the RemoveEmpty autoformatter, userland configuration directives
|
||||
and configuration serialization.
|
||||
HTML Purifier 4.9.x is a maintenance release, collecting a year
|
||||
of accumulated bug fixes plus a few new features. New features
|
||||
include support for min/max-width/height CSS, and rgba/hsl/hsla
|
||||
in color specifications. Major bugfixes include improvements
|
||||
in the Serializer cache to avoid chmod'ing directories, better
|
||||
entity decoding (we won't accidentally encode entities that occur
|
||||
in URLs) and rel="noopener" on links with target attributes,
|
||||
to prevent them from overwriting the original frame.
|
||||
|
||||
4.9.0 was skipped due to a packaging problem; 4.9.2 fixes two
|
||||
major regressions in PHP 5.3 support and entity decoding; no
|
||||
other functional changes were applied.
|
||||
|
@@ -23,15 +23,16 @@ if (version_compare(PHP_VERSION, '5', '>=')) {
|
||||
class RowTimer extends Benchmark_Timer
|
||||
{
|
||||
|
||||
var $name;
|
||||
public $name;
|
||||
|
||||
function RowTimer($name, $auto = false) {
|
||||
public function __construct($name, $auto = false)
|
||||
{
|
||||
$this->name = htmlentities($name);
|
||||
$this->Benchmark_Timer($auto);
|
||||
}
|
||||
|
||||
function getOutput() {
|
||||
|
||||
public function getOutput()
|
||||
{
|
||||
$total = $this->TimeElapsed();
|
||||
$result = $this->getProfiling();
|
||||
$dashes = '';
|
||||
@@ -68,7 +69,8 @@ class RowTimer extends Benchmark_Timer
|
||||
}
|
||||
}
|
||||
|
||||
function print_lexers() {
|
||||
function print_lexers()
|
||||
{
|
||||
global $LEXERS;
|
||||
$first = true;
|
||||
foreach ($LEXERS as $key => $value) {
|
||||
@@ -78,7 +80,8 @@ function print_lexers() {
|
||||
}
|
||||
}
|
||||
|
||||
function do_benchmark($name, $document) {
|
||||
function do_benchmark($name, $document)
|
||||
{
|
||||
global $LEXERS, $RUNS;
|
||||
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
|
25
composer.json
Normal file
25
composer.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"description": "Standards compliant HTML filter written in PHP",
|
||||
"type": "library",
|
||||
"keywords": ["html"],
|
||||
"homepage": "http://htmlpurifier.org/",
|
||||
"license": "LGPL",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Edward Z. Yang",
|
||||
"email": "admin@htmlpurifier.org",
|
||||
"homepage": "http://ezyang.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"simpletest/simpletest": "^1.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "HTMLPurifier": "library/" },
|
||||
"files": ["library/HTMLPurifier.composer.php"]
|
||||
}
|
||||
}
|
@@ -40,12 +40,26 @@
|
||||
</xsl:apply-templates>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="typesContainer">
|
||||
<h2>Types</h2>
|
||||
<xsl:apply-templates select="$typeLookup" mode="types" />
|
||||
</div>
|
||||
<xsl:apply-templates />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="type" mode="types">
|
||||
<div class="type-block">
|
||||
<xsl:attribute name="id">type-<xsl:value-of select="@id" /></xsl:attribute>
|
||||
<h3><code><xsl:value-of select="@id" /></code>: <xsl:value-of select="@name" /></h3>
|
||||
<div class="type-description">
|
||||
<xsl:copy-of xmlns:xhtml="http://www.w3.org/1999/xhtml" select="xhtml:div/node()" />
|
||||
</div>
|
||||
</div>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="title" mode="toc" />
|
||||
<xsl:template match="namespace" mode="toc">
|
||||
<xsl:param name="overflowNumber" />
|
||||
@@ -192,10 +206,13 @@
|
||||
<td>
|
||||
<xsl:variable name="type" select="text()" />
|
||||
<xsl:attribute name="class">type type-<xsl:value-of select="$type" /></xsl:attribute>
|
||||
<xsl:value-of select="$typeLookup/type[@id=$type]/text()" />
|
||||
<xsl:if test="@allow-null='yes'">
|
||||
(or null)
|
||||
</xsl:if>
|
||||
<a>
|
||||
<xsl:attribute name="href">#type-<xsl:value-of select="$type" /></xsl:attribute>
|
||||
<xsl:value-of select="$typeLookup/type[@id=$type]/@name" />
|
||||
<xsl:if test="@allow-null='yes'">
|
||||
(or null)
|
||||
</xsl:if>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</xsl:template>
|
||||
|
@@ -1,16 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<types>
|
||||
<type id="string">String</type>
|
||||
<type id="istring">Case-insensitive string</type>
|
||||
<type id="text">Text</type>
|
||||
<type id="itext">Case-insensitive text</type>
|
||||
<type id="int">Integer</type>
|
||||
<type id="float">Float</type>
|
||||
<type id="bool">Boolean</type>
|
||||
<type id="lookup">Lookup array</type>
|
||||
<type id="list">Array list</type>
|
||||
<type id="hash">Associative array</type>
|
||||
<type id="mixed">Mixed</type>
|
||||
<type id="string" name="String"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
A <a
|
||||
href="http://docs.php.net/manual/en/language.types.string.php">sequence
|
||||
of characters</a>.
|
||||
</div></type>
|
||||
<type id="istring" name="Case-insensitive string"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
A series of case-insensitive characters. Internally, upper-case
|
||||
ASCII characters will be converted to lower-case.
|
||||
</div></type>
|
||||
<type id="text" name="Text"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
A series of characters that may contain newlines. Text tends to
|
||||
indicate human-oriented text, as opposed to a machine format.
|
||||
</div></type>
|
||||
<type id="itext" name="Case-insensitive text"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
A series of case-insensitive characters that may contain newlines.
|
||||
</div></type>
|
||||
<type id="int" name="Integer"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
An <a
|
||||
href="http://docs.php.net/manual/en/language.types.integer.php">
|
||||
integer</a>. You are alternatively permitted to pass a string of
|
||||
digits instead, which will be cast to an integer using
|
||||
<code>(int)</code>.
|
||||
</div></type>
|
||||
<type id="float" name="Float"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
A <a href="http://docs.php.net/manual/en/language.types.float.php">
|
||||
floating point number</a>. You are alternatively permitted to
|
||||
pass a numeric string (as defined by <code>is_numeric()</code>),
|
||||
which will be cast to a float using <code>(float)</code>.
|
||||
</div></type>
|
||||
<type id="bool" name="Boolean"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
A <a
|
||||
href="http://docs.php.net/manual/en/language.types.boolean.php">boolean</a>.
|
||||
You are alternatively permitted to pass an integer <code>0</code> or
|
||||
<code>1</code> (other integers are not permitted) or a string
|
||||
<code>"on"</code>, <code>"true"</code> or <code>"1"</code> for
|
||||
<code>true</code>, and <code>"off"</code>, <code>"false"</code> or
|
||||
<code>"0"</code> for <code>false</code>.
|
||||
</div></type>
|
||||
<type id="lookup" name="Lookup array"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
An array whose values are <code>true</code>, e.g. <code>array('key'
|
||||
=> true, 'key2' => true)</code>. You are alternatively permitted
|
||||
to pass an array list of the keys <code>array('key', 'key2')</code>
|
||||
or a comma-separated string of keys <code>"key, key2"</code>. If
|
||||
you pass an array list of values, ensure that your values are
|
||||
strictly numerically indexed: <code>array('key1', 2 =>
|
||||
'key2')</code> will not do what you expect and emits a warning.
|
||||
</div></type>
|
||||
<type id="list" name="Array list"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
An array which has consecutive integer indexes, e.g.
|
||||
<code>array('val1', 'val2')</code>. You are alternatively permitted
|
||||
to pass a comma-separated string of keys <code>"val1, val2"</code>.
|
||||
If your array is not in this form, <code>array_values</code> is run
|
||||
on the array and a warning is emitted.
|
||||
</div></type>
|
||||
<type id="hash" name="Associative array"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
An array which is a mapping of keys to values, e.g.
|
||||
<code>array('key1' => 'val1', 'key2' => 'val2')</code>. You are
|
||||
alternatively permitted to pass a comma-separated string of
|
||||
key-colon-value strings, e.g. <code>"key1: val1, key2: val2"</code>.
|
||||
</div></type>
|
||||
<type id="mixed" name="Mixed"><div xmlns="http://www.w3.org/1999/xhtml">
|
||||
An arbitrary PHP value of any type.
|
||||
</div></type>
|
||||
</types>
|
||||
|
||||
<!-- vim: et sw=4 sts=4
|
||||
|
@@ -2,442 +2,589 @@
|
||||
<usage>
|
||||
<directive id="Core.CollectErrors">
|
||||
<file name="HTMLPurifier.php">
|
||||
<line>131</line>
|
||||
<line>162</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>81</line>
|
||||
<line>85</line>
|
||||
<line>326</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>53</line>
|
||||
<line>73</line>
|
||||
<line>348</line>
|
||||
<line>67</line>
|
||||
<line>87</line>
|
||||
<line>385</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>47</line>
|
||||
<line>57</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.MaxImgLength">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>157</line>
|
||||
<line>226</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.Proprietary">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>214</line>
|
||||
<line>323</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowTricky">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>218</line>
|
||||
<line>327</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.Trusted">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>331</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowImportant">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>222</line>
|
||||
<line>335</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowedProperties">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>275</line>
|
||||
<line>464</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.ForbiddenProperties">
|
||||
<file name="HTMLPurifier/CSSDefinition.php">
|
||||
<line>480</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Cache.DefinitionImpl">
|
||||
<file name="HTMLPurifier/DefinitionCacheFactory.php">
|
||||
<line>49</line>
|
||||
<line>66</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Doctype">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>83</line>
|
||||
<line>119</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.CustomDoctype">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>85</line>
|
||||
<line>123</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.XHTML">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>88</line>
|
||||
<line>128</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Strict">
|
||||
<file name="HTMLPurifier/DoctypeRegistry.php">
|
||||
<line>93</line>
|
||||
<line>133</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.Encoding">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>267</line>
|
||||
<line>300</line>
|
||||
<line>380</line>
|
||||
<line>428</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Test.ForceNoIconv">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>272</line>
|
||||
<line>308</line>
|
||||
<line>388</line>
|
||||
<line>439</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EscapeNonASCIICharacters">
|
||||
<file name="HTMLPurifier/Encoder.php">
|
||||
<line>304</line>
|
||||
<line>429</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.CommentScriptContents">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>45</line>
|
||||
<line>70</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.FixInnerHTML">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>71</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.SortAttr">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>46</line>
|
||||
<line>72</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.FlashCompat">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>73</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.TidyFormat">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>75</line>
|
||||
<line>104</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.NormalizeNewlines">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>122</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>308</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Output.Newline">
|
||||
<file name="HTMLPurifier/Generator.php">
|
||||
<line>89</line>
|
||||
<line>123</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.BlockWrapper">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>222</line>
|
||||
<line>263</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Parent">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>230</line>
|
||||
<line>273</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedElements">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>247</line>
|
||||
<line>291</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedAttributes">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>248</line>
|
||||
<line>292</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Allowed">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>251</line>
|
||||
<line>295</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.ForbiddenElements">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>337</line>
|
||||
<line>399</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.ForbiddenAttributes">
|
||||
<file name="HTMLPurifier/HTMLDefinition.php">
|
||||
<line>338</line>
|
||||
<line>400</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Trusted">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>202</line>
|
||||
<line>234</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>258</line>
|
||||
<line>313</line>
|
||||
<line>353</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/Image.php">
|
||||
<line>27</line>
|
||||
<line>37</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>36</line>
|
||||
<line>47</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>23</line>
|
||||
<line>30</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedModules">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>209</line>
|
||||
<line>241</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.CoreModules">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>210</line>
|
||||
<line>242</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Proprietary">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>221</line>
|
||||
<line>256</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.SafeObject">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>226</line>
|
||||
<line>259</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.SafeEmbed">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>229</line>
|
||||
<line>262</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.SafeScripting">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>265</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/SafeScripting.php">
|
||||
<line>22</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Nofollow">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>268</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TargetBlank">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>271</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TargetNoreferrer">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>276</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TargetNoopener">
|
||||
<file name="HTMLPurifier/HTMLModuleManager.php">
|
||||
<line>279</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDBlacklist">
|
||||
<file name="HTMLPurifier/IDAccumulator.php">
|
||||
<line>26</line>
|
||||
<line>27</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.Language">
|
||||
<file name="HTMLPurifier/LanguageFactory.php">
|
||||
<line>88</line>
|
||||
<line>93</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.LexerImpl">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>76</line>
|
||||
<line>80</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.MaintainLineNumbers">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>80</line>
|
||||
<line>84</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>48</line>
|
||||
<line>62</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.LegacyEntityDecoder">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>215</line>
|
||||
<line>337</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.ConvertDocumentToFragment">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>267</line>
|
||||
<line>324</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.RemoveProcessingInstructions">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>347</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.HiddenElements">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>351</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>36</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.AggressivelyRemoveScript">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>352</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.RemoveScriptContents">
|
||||
<file name="HTMLPurifier/Lexer.php">
|
||||
<line>353</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>35</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>55</line>
|
||||
<line>65</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/URIFilter/Munge.php">
|
||||
<line>12</line>
|
||||
<line>46</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Host">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>64</line>
|
||||
<line>76</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/URIScheme.php">
|
||||
<line>89</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Base">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>65</line>
|
||||
<line>77</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.DefaultScheme">
|
||||
<file name="HTMLPurifier/URIDefinition.php">
|
||||
<line>72</line>
|
||||
<line>84</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.AllowedSchemes">
|
||||
<file name="HTMLPurifier/URISchemeRegistry.php">
|
||||
<line>41</line>
|
||||
<line>48</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.OverrideAllowedSchemes">
|
||||
<file name="HTMLPurifier/URISchemeRegistry.php">
|
||||
<line>42</line>
|
||||
<line>49</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowDuplicates">
|
||||
<file name="HTMLPurifier/AttrDef/CSS.php">
|
||||
<line>28</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.Disable">
|
||||
<file name="HTMLPurifier/AttrDef/URI.php">
|
||||
<line>28</line>
|
||||
<line>47</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.ColorKeywords">
|
||||
<file name="HTMLPurifier/AttrDef/CSS/Color.php">
|
||||
<line>12</line>
|
||||
<line>29</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/AttrDef/HTML/Color.php">
|
||||
<line>12</line>
|
||||
<line>19</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="CSS.AllowedFonts">
|
||||
<file name="HTMLPurifier/AttrDef/CSS/FontFamily.php">
|
||||
<line>64</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.AllowedClasses">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/Class.php">
|
||||
<line>18</line>
|
||||
<line>33</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.ForbiddenClasses">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/Class.php">
|
||||
<line>19</line>
|
||||
<line>34</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.AllowedFrameTargets">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/FrameTarget.php">
|
||||
<line>15</line>
|
||||
<line>32</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.EnableID">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>20</line>
|
||||
<line>41</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDPrefix">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>26</line>
|
||||
<line>51</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDPrefixLocal">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>28</line>
|
||||
<line>31</line>
|
||||
<line>53</line>
|
||||
<line>58</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.ID.HTML5">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>75</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.IDBlacklistRegexp">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
|
||||
<line>54</line>
|
||||
<line>97</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.">
|
||||
<file name="HTMLPurifier/AttrDef/HTML/LinkTypes.php">
|
||||
<line>30</line>
|
||||
<line>46</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.AllowHostnameUnderscore">
|
||||
<file name="HTMLPurifier/AttrDef/URI/Host.php">
|
||||
<line>77</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EnableIDNA">
|
||||
<file name="HTMLPurifier/AttrDef/URI/Host.php">
|
||||
<line>105</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.DefaultTextDir">
|
||||
<file name="HTMLPurifier/AttrTransform/BdoDir.php">
|
||||
<line>13</line>
|
||||
<line>22</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.RemoveInvalidImg">
|
||||
<file name="HTMLPurifier/AttrTransform/ImgRequired.php">
|
||||
<line>18</line>
|
||||
<line>24</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>20</line>
|
||||
<line>27</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.DefaultInvalidImage">
|
||||
<file name="HTMLPurifier/AttrTransform/ImgRequired.php">
|
||||
<line>19</line>
|
||||
<line>27</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.DefaultImageAlt">
|
||||
<file name="HTMLPurifier/AttrTransform/ImgRequired.php">
|
||||
<line>25</line>
|
||||
<line>33</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Attr.DefaultInvalidImageAlt">
|
||||
<file name="HTMLPurifier/AttrTransform/ImgRequired.php">
|
||||
<line>32</line>
|
||||
<line>40</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.Attr.Name.UseCDATA">
|
||||
<file name="HTMLPurifier/AttrTransform/Name.php">
|
||||
<line>11</line>
|
||||
<line>18</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/Name.php">
|
||||
<line>13</line>
|
||||
<line>19</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EscapeInvalidChildren">
|
||||
<file name="HTMLPurifier/ChildDef/Required.php">
|
||||
<line>62</line>
|
||||
<directive id="HTML.FlashAllowFullScreen">
|
||||
<file name="HTMLPurifier/AttrTransform/SafeParam.php">
|
||||
<line>53</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Cache.SerializerPath">
|
||||
<file name="HTMLPurifier/DefinitionCache/Serializer.php">
|
||||
<line>91</line>
|
||||
<line>185</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Cache.SerializerPermissions">
|
||||
<file name="HTMLPurifier/DefinitionCache/Serializer.php">
|
||||
<line>202</line>
|
||||
<line>218</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Filter.ExtractStyleBlocks.TidyImpl">
|
||||
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
|
||||
<line>41</line>
|
||||
<line>94</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Filter.ExtractStyleBlocks.Scope">
|
||||
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
|
||||
<line>65</line>
|
||||
<line>125</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Filter.ExtractStyleBlocks.Escaping">
|
||||
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
|
||||
<line>123</line>
|
||||
<line>330</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.SafeIframe">
|
||||
<file name="HTMLPurifier/HTMLModule/Iframe.php">
|
||||
<line>28</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/URIFilter/SafeIframe.php">
|
||||
<line>48</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.MaxImgLength">
|
||||
<file name="HTMLPurifier/HTMLModule/Image.php">
|
||||
<line>14</line>
|
||||
<line>21</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/SafeEmbed.php">
|
||||
<line>13</line>
|
||||
<line>18</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/HTMLModule/SafeObject.php">
|
||||
<line>19</line>
|
||||
<line>24</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TidyLevel">
|
||||
<file name="HTMLPurifier/HTMLModule/Tidy.php">
|
||||
<line>45</line>
|
||||
<line>50</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TidyAdd">
|
||||
<file name="HTMLPurifier/HTMLModule/Tidy.php">
|
||||
<line>49</line>
|
||||
<line>54</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.TidyRemove">
|
||||
<file name="HTMLPurifier/HTMLModule/Tidy.php">
|
||||
<line>50</line>
|
||||
<line>55</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="AutoFormat.PurifierLinkify.DocURL">
|
||||
<file name="HTMLPurifier/Injector/PurifierLinkify.php">
|
||||
<line>15</line>
|
||||
<line>31</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="AutoFormat.RemoveEmpty.RemoveNbsp">
|
||||
<file name="HTMLPurifier/Injector/RemoveEmpty.php">
|
||||
<line>12</line>
|
||||
<line>46</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions">
|
||||
<file name="HTMLPurifier/Injector/RemoveEmpty.php">
|
||||
<line>13</line>
|
||||
<line>47</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="AutoFormat.RemoveEmpty.Predicate">
|
||||
<file name="HTMLPurifier/Injector/RemoveEmpty.php">
|
||||
<line>48</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.AggressivelyFixLt">
|
||||
<file name="HTMLPurifier/Lexer/DOMLex.php">
|
||||
<line>44</line>
|
||||
<line>54</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.DirectLexLineNumberSyncInterval">
|
||||
<file name="HTMLPurifier/Lexer/DirectLex.php">
|
||||
<line>70</line>
|
||||
<line>84</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.DisableExcludes">
|
||||
<file name="HTMLPurifier/Strategy/FixNesting.php">
|
||||
<line>54</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.EscapeInvalidTags">
|
||||
<file name="HTMLPurifier/Strategy/MakeWellFormed.php">
|
||||
<line>45</line>
|
||||
<line>72</line>
|
||||
</file>
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>19</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.RemoveScriptContents">
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>25</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="Core.HiddenElements">
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>26</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedComments">
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>31</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="HTML.AllowedCommentsRegexp">
|
||||
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
|
||||
<line>32</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.HostBlacklist">
|
||||
<file name="HTMLPurifier/URIFilter/HostBlacklist.php">
|
||||
<line>8</line>
|
||||
<line>25</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.MungeResources">
|
||||
<file name="HTMLPurifier/URIFilter/Munge.php">
|
||||
<line>14</line>
|
||||
<line>48</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.MungeSecretKey">
|
||||
<file name="HTMLPurifier/URIFilter/Munge.php">
|
||||
<line>15</line>
|
||||
<line>49</line>
|
||||
</file>
|
||||
</directive>
|
||||
<directive id="URI.SafeIframeRegexp">
|
||||
<file name="HTMLPurifier/URIFilter/SafeIframe.php">
|
||||
<line>35</line>
|
||||
</file>
|
||||
</directive>
|
||||
</usage>
|
||||
|
@@ -25,5 +25,6 @@ URIScheme - needs to have callable generic checks
|
||||
mailto - doesn't validate emails, doesn't validate querystring
|
||||
news - doesn't validate opaque path
|
||||
nntp - doesn't constrain path
|
||||
tel - doesn't validate phone numbers, only allows characters '+', '1-9', and 'x'
|
||||
|
||||
vim: et sw=4 sts=4
|
||||
|
@@ -255,7 +255,7 @@ Mozilla on inside and needs -moz-outline, no IE support.</td></tr>
|
||||
<tr class="feature"><td>axis</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr>
|
||||
<tr class="feature"><td>char</td><td>COL, COLGROUP, TBODY, TD, TFOOT, TH, THEAD, TR</td><td>W3C only: No browser implementation</td></tr>
|
||||
<tr class="feature"><td>headers</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr>
|
||||
<tr class="feature"><td>scope</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr>
|
||||
<tr class="impl-yes"><td>scope</td><td>TD, TH</td><td>W3C only: No browser implementation</td></tr>
|
||||
</tbody>
|
||||
|
||||
<tbody class="impl-yes">
|
||||
|
@@ -146,7 +146,9 @@
|
||||
<pre>$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('HTML.DefinitionID', 'enduser-customize.html tutorial');
|
||||
$config->set('HTML.DefinitionRev', 1);
|
||||
$def = $config->getHTMLDefinition(true);</pre>
|
||||
if ($def = $config->maybeGetRawHTMLDefinition()) {
|
||||
// our code will go here
|
||||
}</pre>
|
||||
|
||||
<p>
|
||||
Assuming that HTML Purifier has already been properly loaded (hint:
|
||||
@@ -174,23 +176,15 @@ $def = $config->getHTMLDefinition(true);</pre>
|
||||
</li>
|
||||
<li>
|
||||
The fourth line retrieves a raw <code>HTMLPurifier_HTMLDefinition</code>
|
||||
object that we will be tweaking. If the parameter was removed, we
|
||||
would be retrieving a fully formed definition object, which is somewhat
|
||||
useless for customization purposes.
|
||||
object that we will be tweaking. Interestingly enough, we have
|
||||
placed it in an if block: this is because
|
||||
<code>maybeGetRawHTMLDefinition</code>, as its name suggests, may
|
||||
return a NULL, in which case we should skip doing any
|
||||
initialization. This, in fact, will correspond to when our fully
|
||||
customized object is already in the cache.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3>Broken backwards-compatibility</h3>
|
||||
|
||||
<p>
|
||||
Those of you who have already been twiddling around with the raw
|
||||
HTML definition object, you'll be noticing that you're getting an error
|
||||
when you attempt to retrieve the raw definition object without specifying
|
||||
a DefinitionID. It is vital to caching (see below) that you make a unique
|
||||
name for your customized definition, so make up something right now and
|
||||
things will operate again.
|
||||
</p>
|
||||
|
||||
<h2>Turn off caching</h2>
|
||||
|
||||
<p>
|
||||
@@ -781,6 +775,75 @@ $form->excludes = array('form' => true);</strong></pre>
|
||||
<li><a href="http://repo.or.cz/w/htmlpurifier.git?a=blob;hb=HEAD;f=library/HTMLPurifier/ElementDef.php"><code>library/HTMLPurifier/ElementDef.php</code></a></li>
|
||||
</ul>
|
||||
|
||||
<h2 id="optimized">Notes for HTML Purifier 4.2.0 and earlier</h3>
|
||||
|
||||
<p>
|
||||
Previously, this tutorial gave some incorrect template code for
|
||||
editing raw definitions, and that template code will now produce the
|
||||
error <q>Due to a documentation error in previous version of HTML
|
||||
Purifier...</q> Here is how to mechanically transform old-style
|
||||
code into new-style code.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, identify all code that edits the raw definition object, and
|
||||
put it together. Ensure none of this code must be run on every
|
||||
request; if some sub-part needs to always be run, move it outside
|
||||
this block. Here is an example below, with the raw definition
|
||||
object code bolded.
|
||||
</p>
|
||||
|
||||
<pre>$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('HTML.DefinitionID', 'enduser-customize.html tutorial');
|
||||
$config->set('HTML.DefinitionRev', 1);
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
<strong>$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');</strong>
|
||||
$purifier = new HTMLPurifier($config);</pre>
|
||||
|
||||
<p>
|
||||
Next, replace the raw definition retrieval with a
|
||||
maybeGetRawHTMLDefinition method call inside an if conditional, and
|
||||
place the editing code inside that if block.
|
||||
</p>
|
||||
|
||||
<pre>$config = HTMLPurifier_Config::createDefault();
|
||||
$config->set('HTML.DefinitionID', 'enduser-customize.html tutorial');
|
||||
$config->set('HTML.DefinitionRev', 1);
|
||||
<strong>if ($def = $config->maybeGetRawHTMLDefinition()) {
|
||||
$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
|
||||
}</strong>
|
||||
$purifier = new HTMLPurifier($config);</pre>
|
||||
|
||||
<p>
|
||||
And you're done! Alternatively, if you're OK with not ever caching
|
||||
your code, the following will still work and not emit warnings.
|
||||
</p>
|
||||
|
||||
<pre>$config = HTMLPurifier_Config::createDefault();
|
||||
$def = $config->getHTMLDefinition(true);
|
||||
$def->addAttribute('a', 'target', 'Enum#_blank,_self,_target,_top');
|
||||
$purifier = new HTMLPurifier($config);</pre>
|
||||
|
||||
<p>
|
||||
A slightly less efficient version of this was what was going on with
|
||||
old versions of HTML Purifier.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<em>Technical notes:</em> ajh pointed out on <a
|
||||
href="http://htmlpurifier.org/phorum/read.php?5,5164,5169#msg-5169">in a forum topic</a> that
|
||||
HTML Purifier appeared to be repeatedly writing to the cache even
|
||||
when a cache entry already existed. Investigation lead to the
|
||||
discovery of the following infelicity: caching of customized
|
||||
definitions didn't actually work! The problem was that even though
|
||||
a cache file would be written out at the end of the process, there
|
||||
was no way for HTML Purifier to say, <q>Actually, I've already got a
|
||||
copy of your work, no need to reconfigure your
|
||||
customizations</q>. This required the API to change: placing
|
||||
all of the customizations to the raw definition object in a
|
||||
conditional which could be skipped.
|
||||
</p>
|
||||
|
||||
</body></html>
|
||||
|
||||
<!-- vim: et sw=4 sts=4
|
||||
|
@@ -561,7 +561,7 @@ page on special characters</a> for more details.
|
||||
<h3 id="whyutf8-forms">Forms</h3>
|
||||
|
||||
<p>While we're on the tack of users, how do non-UTF-8 web forms deal
|
||||
with characters that our outside of their character set? Rather than
|
||||
with characters that are outside of their character set? Rather than
|
||||
discuss what UTF-8 does right, we're going to show what could go wrong
|
||||
if you didn't use UTF-8 and people tried to use characters outside
|
||||
of your character encoding.</p>
|
||||
|
@@ -11,7 +11,8 @@ class ConfigDoc_HTMLXSLTProcessor
|
||||
*/
|
||||
protected $xsltProcessor;
|
||||
|
||||
public function __construct($proc = false) {
|
||||
public function __construct($proc = false)
|
||||
{
|
||||
if ($proc === false) $proc = new XSLTProcessor();
|
||||
$this->xsltProcessor = $proc;
|
||||
}
|
||||
@@ -19,7 +20,8 @@ class ConfigDoc_HTMLXSLTProcessor
|
||||
/**
|
||||
* @note Allows a string $xsl filename to be passed
|
||||
*/
|
||||
public function importStylesheet($xsl) {
|
||||
public function importStylesheet($xsl)
|
||||
{
|
||||
if (is_string($xsl)) {
|
||||
$xsl_file = $xsl;
|
||||
$xsl = new DOMDocument();
|
||||
@@ -34,7 +36,8 @@ class ConfigDoc_HTMLXSLTProcessor
|
||||
* @return string HTML output
|
||||
* @todo Rename to transformToXHTML, as transformToHTML is misleading
|
||||
*/
|
||||
public function transformToHTML($xml) {
|
||||
public function transformToHTML($xml)
|
||||
{
|
||||
if (is_string($xml)) {
|
||||
$dom = new DOMDocument();
|
||||
$dom->load($xml);
|
||||
@@ -68,7 +71,8 @@ class ConfigDoc_HTMLXSLTProcessor
|
||||
* Bulk sets parameters for the XSL stylesheet
|
||||
* @param array $options Associative array of options to set
|
||||
*/
|
||||
public function setParameters($options) {
|
||||
public function setParameters($options)
|
||||
{
|
||||
foreach ($options as $name => $value) {
|
||||
$this->xsltProcessor->setParameter('', $name, $value);
|
||||
}
|
||||
@@ -77,7 +81,8 @@ class ConfigDoc_HTMLXSLTProcessor
|
||||
/**
|
||||
* Forward any other calls to the XSLT processor
|
||||
*/
|
||||
public function __call($name, $arguments) {
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
call_user_func_array(array($this->xsltProcessor, $name), $arguments);
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,8 @@ class FSTools
|
||||
/**
|
||||
* Returns a global instance of FSTools
|
||||
*/
|
||||
static public function singleton() {
|
||||
public static function singleton()
|
||||
{
|
||||
if (empty(FSTools::$singleton)) FSTools::$singleton = new FSTools();
|
||||
return FSTools::$singleton;
|
||||
}
|
||||
@@ -24,7 +25,8 @@ class FSTools
|
||||
* Sets our global singleton to something else; useful for overloading
|
||||
* functions.
|
||||
*/
|
||||
static public function setSingleton($singleton) {
|
||||
public static function setSingleton($singleton)
|
||||
{
|
||||
FSTools::$singleton = $singleton;
|
||||
}
|
||||
|
||||
@@ -33,7 +35,8 @@ class FSTools
|
||||
* @param string $folder Name of folder to create
|
||||
* @note Adapted from the PHP manual comment 76612
|
||||
*/
|
||||
public function mkdirr($folder) {
|
||||
public function mkdirr($folder)
|
||||
{
|
||||
$folders = preg_split("#[\\\\/]#", $folder);
|
||||
$base = '';
|
||||
for($i = 0, $c = count($folders); $i < $c; $i++) {
|
||||
@@ -57,7 +60,8 @@ class FSTools
|
||||
* so that copied files, if PHP, have includes removed
|
||||
* @note Adapted from http://aidanlister.com/repos/v/function.copyr.php
|
||||
*/
|
||||
public function copyr($source, $dest) {
|
||||
public function copyr($source, $dest)
|
||||
{
|
||||
// Simple copy for a file
|
||||
if (is_file($source)) {
|
||||
return $this->copy($source, $dest);
|
||||
@@ -92,7 +96,8 @@ class FSTools
|
||||
* ignore hidden files, unreadable files, etc. This function
|
||||
* applies to copyr().
|
||||
*/
|
||||
public function copyable($file) {
|
||||
public function copyable($file)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -131,7 +136,8 @@ class FSTools
|
||||
/**
|
||||
* Recursively globs a directory.
|
||||
*/
|
||||
public function globr($dir, $pattern, $flags = NULL) {
|
||||
public function globr($dir, $pattern, $flags = NULL)
|
||||
{
|
||||
$files = $this->glob("$dir/$pattern", $flags);
|
||||
if ($files === false) $files = array();
|
||||
$sub_dirs = $this->glob("$dir/*", GLOB_ONLYDIR);
|
||||
@@ -148,7 +154,8 @@ class FSTools
|
||||
* @warning This function will not work for functions that need
|
||||
* to pass references; manually define a stub function for those.
|
||||
*/
|
||||
public function __call($name, $args) {
|
||||
public function __call($name, $args)
|
||||
{
|
||||
return call_user_func_array($name, $args);
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,8 @@ class FSTools_File
|
||||
* Filename of file you wish to instantiate.
|
||||
* @note This file need not exist
|
||||
*/
|
||||
public function __construct($name, $fs = false) {
|
||||
public function __construct($name, $fs = false)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->fs = $fs ? $fs : FSTools::singleton();
|
||||
}
|
||||
@@ -38,27 +39,32 @@ class FSTools_File
|
||||
* Retrieves the contents of a file
|
||||
* @todo Throw an exception if file doesn't exist
|
||||
*/
|
||||
public function get() {
|
||||
public function get()
|
||||
{
|
||||
return $this->fs->file_get_contents($this->name);
|
||||
}
|
||||
|
||||
/** Writes contents to a file, creates new file if necessary */
|
||||
public function write($contents) {
|
||||
public function write($contents)
|
||||
{
|
||||
return $this->fs->file_put_contents($this->name, $contents);
|
||||
}
|
||||
|
||||
/** Deletes the file */
|
||||
public function delete() {
|
||||
public function delete()
|
||||
{
|
||||
return $this->fs->unlink($this->name);
|
||||
}
|
||||
|
||||
/** Returns true if file exists and is a file. */
|
||||
public function exists() {
|
||||
public function exists()
|
||||
{
|
||||
return $this->fs->is_file($this->name);
|
||||
}
|
||||
|
||||
/** Returns last file modification time */
|
||||
public function getMTime() {
|
||||
public function getMTime()
|
||||
{
|
||||
return $this->fs->filemtime($this->name);
|
||||
}
|
||||
|
||||
@@ -67,19 +73,22 @@ class FSTools_File
|
||||
* @note We ignore errors because of some weird owner trickery due
|
||||
* to SVN duality
|
||||
*/
|
||||
public function chmod($octal_code) {
|
||||
public function chmod($octal_code)
|
||||
{
|
||||
return @$this->fs->chmod($this->name, $octal_code);
|
||||
}
|
||||
|
||||
/** Opens file's handle */
|
||||
public function open($mode) {
|
||||
public function open($mode)
|
||||
{
|
||||
if ($this->handle) $this->close();
|
||||
$this->handle = $this->fs->fopen($this->name, $mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Closes file's handle */
|
||||
public function close() {
|
||||
public function close()
|
||||
{
|
||||
if (!$this->handle) return false;
|
||||
$status = $this->fs->fclose($this->handle);
|
||||
$this->handle = false;
|
||||
@@ -87,37 +96,43 @@ class FSTools_File
|
||||
}
|
||||
|
||||
/** Retrieves a line from an open file, with optional max length $length */
|
||||
public function getLine($length = null) {
|
||||
public function getLine($length = null)
|
||||
{
|
||||
if (!$this->handle) $this->open('r');
|
||||
if ($length === null) return $this->fs->fgets($this->handle);
|
||||
else return $this->fs->fgets($this->handle, $length);
|
||||
}
|
||||
|
||||
/** Retrieves a character from an open file */
|
||||
public function getChar() {
|
||||
public function getChar()
|
||||
{
|
||||
if (!$this->handle) $this->open('r');
|
||||
return $this->fs->fgetc($this->handle);
|
||||
}
|
||||
|
||||
/** Retrieves an $length bytes of data from an open data */
|
||||
public function read($length) {
|
||||
public function read($length)
|
||||
{
|
||||
if (!$this->handle) $this->open('r');
|
||||
return $this->fs->fread($this->handle, $length);
|
||||
}
|
||||
|
||||
/** Writes to an open file */
|
||||
public function put($string) {
|
||||
public function put($string)
|
||||
{
|
||||
if (!$this->handle) $this->open('a');
|
||||
return $this->fs->fwrite($this->handle, $string);
|
||||
}
|
||||
|
||||
/** Returns TRUE if the end of the file has been reached */
|
||||
public function eof() {
|
||||
public function eof()
|
||||
{
|
||||
if (!$this->handle) return true;
|
||||
return $this->fs->feof($this->handle);
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->handle) $this->close();
|
||||
}
|
||||
|
||||
|
@@ -17,7 +17,8 @@ if (function_exists('spl_autoload_register')) {
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
} elseif (!function_exists('__autoload')) {
|
||||
function __autoload($class) {
|
||||
function __autoload($class)
|
||||
{
|
||||
return HTMLPurifierExtras::autoload($class);
|
||||
}
|
||||
}
|
||||
|
@@ -7,14 +7,16 @@
|
||||
class HTMLPurifierExtras
|
||||
{
|
||||
|
||||
public static function autoload($class) {
|
||||
public static function autoload($class)
|
||||
{
|
||||
$path = HTMLPurifierExtras::getPath($class);
|
||||
if (!$path) return false;
|
||||
require $path;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function getPath($class) {
|
||||
public static function getPath($class)
|
||||
{
|
||||
if (
|
||||
strncmp('FSTools', $class, 7) !== 0 &&
|
||||
strncmp('ConfigDoc', $class, 9) !== 0
|
||||
|
@@ -3,6 +3,7 @@
|
||||
/**
|
||||
* @file
|
||||
* Convenience file that registers autoload handler for HTML Purifier.
|
||||
* It also does some sanity checks.
|
||||
*/
|
||||
|
||||
if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {
|
||||
@@ -13,9 +14,14 @@ if (function_exists('spl_autoload_register') && function_exists('spl_autoload_un
|
||||
spl_autoload_register('__autoload');
|
||||
}
|
||||
} elseif (!function_exists('__autoload')) {
|
||||
function __autoload($class) {
|
||||
function __autoload($class)
|
||||
{
|
||||
return HTMLPurifier_Bootstrap::autoload($class);
|
||||
}
|
||||
}
|
||||
|
||||
if (ini_get('zend.ze1_compatibility_mode')) {
|
||||
trigger_error("HTML Purifier is not compatible with zend.ze1_compatibility_mode; please turn it off", E_USER_ERROR);
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
4
library/HTMLPurifier.composer.php
Normal file
4
library/HTMLPurifier.composer.php
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
if (!defined('HTMLPURIFIER_PREFIX')) {
|
||||
define('HTMLPURIFIER_PREFIX', dirname(__FILE__));
|
||||
}
|
@@ -8,11 +8,13 @@
|
||||
|
||||
/**
|
||||
* Purify HTML.
|
||||
* @param $html String HTML to purify
|
||||
* @param $config Configuration to use, can be any value accepted by
|
||||
* @param string $html String HTML to purify
|
||||
* @param mixed $config Configuration to use, can be any value accepted by
|
||||
* HTMLPurifier_Config::create()
|
||||
* @return string
|
||||
*/
|
||||
function HTMLPurifier($html, $config = null) {
|
||||
function HTMLPurifier($html, $config = null)
|
||||
{
|
||||
static $purifier = false;
|
||||
if (!$purifier) {
|
||||
$purifier = new HTMLPurifier();
|
||||
|
@@ -7,7 +7,7 @@
|
||||
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
|
||||
* FILE, changes will be overwritten the next time the script is run.
|
||||
*
|
||||
* @version 4.0.0
|
||||
* @version 4.9.2
|
||||
*
|
||||
* @warning
|
||||
* You must *not* include any other HTML Purifier files before this file,
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
require 'HTMLPurifier.php';
|
||||
require 'HTMLPurifier/Arborize.php';
|
||||
require 'HTMLPurifier/AttrCollections.php';
|
||||
require 'HTMLPurifier/AttrDef.php';
|
||||
require 'HTMLPurifier/AttrTransform.php';
|
||||
@@ -54,9 +55,11 @@ require 'HTMLPurifier/Language.php';
|
||||
require 'HTMLPurifier/LanguageFactory.php';
|
||||
require 'HTMLPurifier/Length.php';
|
||||
require 'HTMLPurifier/Lexer.php';
|
||||
require 'HTMLPurifier/Node.php';
|
||||
require 'HTMLPurifier/PercentEncoder.php';
|
||||
require 'HTMLPurifier/PropertyList.php';
|
||||
require 'HTMLPurifier/PropertyListIterator.php';
|
||||
require 'HTMLPurifier/Queue.php';
|
||||
require 'HTMLPurifier/Strategy.php';
|
||||
require 'HTMLPurifier/StringHash.php';
|
||||
require 'HTMLPurifier/StringHashParser.php';
|
||||
@@ -72,7 +75,9 @@ require 'HTMLPurifier/URISchemeRegistry.php';
|
||||
require 'HTMLPurifier/UnitConverter.php';
|
||||
require 'HTMLPurifier/VarParser.php';
|
||||
require 'HTMLPurifier/VarParserException.php';
|
||||
require 'HTMLPurifier/Zipper.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS.php';
|
||||
require 'HTMLPurifier/AttrDef/Clone.php';
|
||||
require 'HTMLPurifier/AttrDef/Enum.php';
|
||||
require 'HTMLPurifier/AttrDef/Integer.php';
|
||||
require 'HTMLPurifier/AttrDef/Lang.php';
|
||||
@@ -90,6 +95,7 @@ require 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
@@ -125,14 +131,19 @@ require 'HTMLPurifier/AttrTransform/Lang.php';
|
||||
require 'HTMLPurifier/AttrTransform/Length.php';
|
||||
require 'HTMLPurifier/AttrTransform/Name.php';
|
||||
require 'HTMLPurifier/AttrTransform/NameSync.php';
|
||||
require 'HTMLPurifier/AttrTransform/Nofollow.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require 'HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||
require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||
require 'HTMLPurifier/AttrTransform/Textarea.php';
|
||||
require 'HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require 'HTMLPurifier/ChildDef/Custom.php';
|
||||
require 'HTMLPurifier/ChildDef/Empty.php';
|
||||
require 'HTMLPurifier/ChildDef/List.php';
|
||||
require 'HTMLPurifier/ChildDef/Required.php';
|
||||
require 'HTMLPurifier/ChildDef/Optional.php';
|
||||
require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
@@ -147,10 +158,12 @@ require 'HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Edit.php';
|
||||
require 'HTMLPurifier/HTMLModule/Forms.php';
|
||||
require 'HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require 'HTMLPurifier/HTMLModule/Iframe.php';
|
||||
require 'HTMLPurifier/HTMLModule/Image.php';
|
||||
require 'HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require 'HTMLPurifier/HTMLModule/List.php';
|
||||
require 'HTMLPurifier/HTMLModule/Name.php';
|
||||
require 'HTMLPurifier/HTMLModule/Nofollow.php';
|
||||
require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require 'HTMLPurifier/HTMLModule/Object.php';
|
||||
require 'HTMLPurifier/HTMLModule/Presentation.php';
|
||||
@@ -158,10 +171,14 @@ require 'HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require 'HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require 'HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tables.php';
|
||||
require 'HTMLPurifier/HTMLModule/Target.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||
require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||
require 'HTMLPurifier/HTMLModule/Text.php';
|
||||
require 'HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
@@ -176,9 +193,13 @@ require 'HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||
require 'HTMLPurifier/Injector/Linkify.php';
|
||||
require 'HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require 'HTMLPurifier/Injector/RemoveEmpty.php';
|
||||
require 'HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||
require 'HTMLPurifier/Injector/SafeObject.php';
|
||||
require 'HTMLPurifier/Lexer/DOMLex.php';
|
||||
require 'HTMLPurifier/Lexer/DirectLex.php';
|
||||
require 'HTMLPurifier/Node/Comment.php';
|
||||
require 'HTMLPurifier/Node/Element.php';
|
||||
require 'HTMLPurifier/Node/Text.php';
|
||||
require 'HTMLPurifier/Strategy/Composite.php';
|
||||
require 'HTMLPurifier/Strategy/Core.php';
|
||||
require 'HTMLPurifier/Strategy/FixNesting.php';
|
||||
@@ -195,14 +216,19 @@ require 'HTMLPurifier/Token/Start.php';
|
||||
require 'HTMLPurifier/Token/Text.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require 'HTMLPurifier/URIFilter/DisableResources.php';
|
||||
require 'HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require 'HTMLPurifier/URIFilter/Munge.php';
|
||||
require 'HTMLPurifier/URIFilter/SafeIframe.php';
|
||||
require 'HTMLPurifier/URIScheme/data.php';
|
||||
require 'HTMLPurifier/URIScheme/file.php';
|
||||
require 'HTMLPurifier/URIScheme/ftp.php';
|
||||
require 'HTMLPurifier/URIScheme/http.php';
|
||||
require 'HTMLPurifier/URIScheme/https.php';
|
||||
require 'HTMLPurifier/URIScheme/mailto.php';
|
||||
require 'HTMLPurifier/URIScheme/news.php';
|
||||
require 'HTMLPurifier/URIScheme/nntp.php';
|
||||
require 'HTMLPurifier/URIScheme/tel.php';
|
||||
require 'HTMLPurifier/VarParser/Flexible.php';
|
||||
require 'HTMLPurifier/VarParser/Native.php';
|
||||
|
@@ -7,7 +7,8 @@
|
||||
|
||||
require_once dirname(__FILE__) . '/HTMLPurifier.auto.php';
|
||||
|
||||
function kses($string, $allowed_html, $allowed_protocols = null) {
|
||||
function kses($string, $allowed_html, $allowed_protocols = null)
|
||||
{
|
||||
$config = HTMLPurifier_Config::createDefault();
|
||||
$allowed_elements = array();
|
||||
$allowed_attributes = array();
|
||||
@@ -19,7 +20,6 @@ function kses($string, $allowed_html, $allowed_protocols = null) {
|
||||
}
|
||||
$config->set('HTML.AllowedElements', $allowed_elements);
|
||||
$config->set('HTML.AllowedAttributes', $allowed_attributes);
|
||||
$allowed_schemes = array();
|
||||
if ($allowed_protocols !== null) {
|
||||
$config->set('URI.AllowedSchemes', $allowed_protocols);
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
HTML Purifier 4.0.0 - Standards Compliant HTML Filtering
|
||||
HTML Purifier 4.9.2 - Standards Compliant HTML Filtering
|
||||
Copyright (C) 2006-2008 Edward Z. Yang
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
@@ -54,66 +54,97 @@
|
||||
class HTMLPurifier
|
||||
{
|
||||
|
||||
/** Version of HTML Purifier */
|
||||
public $version = '4.0.0';
|
||||
|
||||
/** Constant with version of HTML Purifier */
|
||||
const VERSION = '4.0.0';
|
||||
|
||||
/** Global configuration object */
|
||||
public $config;
|
||||
|
||||
/** Array of extra HTMLPurifier_Filter objects to run on HTML, for backwards compatibility */
|
||||
private $filters = array();
|
||||
|
||||
/** Single instance of HTML Purifier */
|
||||
private static $instance;
|
||||
|
||||
protected $strategy, $generator;
|
||||
/**
|
||||
* Version of HTML Purifier.
|
||||
* @type string
|
||||
*/
|
||||
public $version = '4.9.2';
|
||||
|
||||
/**
|
||||
* Resultant HTMLPurifier_Context of last run purification. Is an array
|
||||
* of contexts if the last called method was purifyArray().
|
||||
* Constant with version of HTML Purifier.
|
||||
*/
|
||||
const VERSION = '4.9.2';
|
||||
|
||||
/**
|
||||
* Global configuration object.
|
||||
* @type HTMLPurifier_Config
|
||||
*/
|
||||
public $config;
|
||||
|
||||
/**
|
||||
* Array of extra filter objects to run on HTML,
|
||||
* for backwards compatibility.
|
||||
* @type HTMLPurifier_Filter[]
|
||||
*/
|
||||
private $filters = array();
|
||||
|
||||
/**
|
||||
* Single instance of HTML Purifier.
|
||||
* @type HTMLPurifier
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Strategy_Core
|
||||
*/
|
||||
protected $strategy;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_Generator
|
||||
*/
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
* Resultant context of last run purification.
|
||||
* Is an array of contexts if the last called method was purifyArray().
|
||||
* @type HTMLPurifier_Context
|
||||
*/
|
||||
public $context;
|
||||
|
||||
/**
|
||||
* Initializes the purifier.
|
||||
* @param $config Optional HTMLPurifier_Config object for all instances of
|
||||
* the purifier, if omitted, a default configuration is
|
||||
* supplied (which can be overridden on a per-use basis).
|
||||
*
|
||||
* @param HTMLPurifier_Config|mixed $config Optional HTMLPurifier_Config object
|
||||
* for all instances of the purifier, if omitted, a default
|
||||
* configuration is supplied (which can be overridden on a
|
||||
* per-use basis).
|
||||
* The parameter can also be any type that
|
||||
* HTMLPurifier_Config::create() supports.
|
||||
*/
|
||||
public function __construct($config = null) {
|
||||
|
||||
public function __construct($config = null)
|
||||
{
|
||||
$this->config = HTMLPurifier_Config::create($config);
|
||||
|
||||
$this->strategy = new HTMLPurifier_Strategy_Core();
|
||||
|
||||
$this->strategy = new HTMLPurifier_Strategy_Core();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filter to process the output. First come first serve
|
||||
* @param $filter HTMLPurifier_Filter object
|
||||
*
|
||||
* @param HTMLPurifier_Filter $filter HTMLPurifier_Filter object
|
||||
*/
|
||||
public function addFilter($filter) {
|
||||
trigger_error('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom', E_USER_WARNING);
|
||||
public function addFilter($filter)
|
||||
{
|
||||
trigger_error(
|
||||
'HTMLPurifier->addFilter() is deprecated, use configuration directives' .
|
||||
' in the Filter namespace or Filter.Custom',
|
||||
E_USER_WARNING
|
||||
);
|
||||
$this->filters[] = $filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an HTML snippet/document to be XSS-free and standards-compliant.
|
||||
*
|
||||
* @param $html String of HTML to purify
|
||||
* @param $config HTMLPurifier_Config object for this operation, if omitted,
|
||||
* defaults to the config object specified during this
|
||||
* @param string $html String of HTML to purify
|
||||
* @param HTMLPurifier_Config $config Config object for this operation,
|
||||
* if omitted, defaults to the config object specified during this
|
||||
* object's construction. The parameter can also be any type
|
||||
* that HTMLPurifier_Config::create() supports.
|
||||
* @return Purified HTML
|
||||
*
|
||||
* @return string Purified HTML
|
||||
*/
|
||||
public function purify($html, $config = null) {
|
||||
|
||||
public function purify($html, $config = null)
|
||||
{
|
||||
// :TODO: make the config merge in, instead of replace
|
||||
$config = $config ? HTMLPurifier_Config::create($config) : $this->config;
|
||||
|
||||
@@ -151,8 +182,12 @@ class HTMLPurifier
|
||||
unset($filter_flags['Custom']);
|
||||
$filters = array();
|
||||
foreach ($filter_flags as $filter => $flag) {
|
||||
if (!$flag) continue;
|
||||
if (strpos($filter, '.') !== false) continue;
|
||||
if (!$flag) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($filter, '.') !== false) {
|
||||
continue;
|
||||
}
|
||||
$class = "HTMLPurifier_Filter_$filter";
|
||||
$filters[] = new $class;
|
||||
}
|
||||
@@ -175,9 +210,12 @@ class HTMLPurifier
|
||||
// list of un-purified tokens
|
||||
$lexer->tokenizeHTML(
|
||||
// un-purified HTML
|
||||
$html, $config, $context
|
||||
$html,
|
||||
$config,
|
||||
$context
|
||||
),
|
||||
$config, $context
|
||||
$config,
|
||||
$context
|
||||
)
|
||||
);
|
||||
|
||||
@@ -192,11 +230,15 @@ class HTMLPurifier
|
||||
|
||||
/**
|
||||
* Filters an array of HTML snippets
|
||||
* @param $config Optional HTMLPurifier_Config object for this operation.
|
||||
*
|
||||
* @param string[] $array_of_html Array of html snippets
|
||||
* @param HTMLPurifier_Config $config Optional config object for this operation.
|
||||
* See HTMLPurifier::purify() for more details.
|
||||
* @return Array of purified HTML
|
||||
*
|
||||
* @return string[] Array of purified HTML
|
||||
*/
|
||||
public function purifyArray($array_of_html, $config = null) {
|
||||
public function purifyArray($array_of_html, $config = null)
|
||||
{
|
||||
$context_array = array();
|
||||
foreach ($array_of_html as $key => $html) {
|
||||
$array_of_html[$key] = $this->purify($html, $config);
|
||||
@@ -208,11 +250,16 @@ class HTMLPurifier
|
||||
|
||||
/**
|
||||
* Singleton for enforcing just one HTML Purifier in your system
|
||||
* @param $prototype Optional prototype HTMLPurifier instance to
|
||||
* overload singleton with, or HTMLPurifier_Config
|
||||
* instance to configure the generated version with.
|
||||
*
|
||||
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||
* HTMLPurifier instance to overload singleton with,
|
||||
* or HTMLPurifier_Config instance to configure the
|
||||
* generated version with.
|
||||
*
|
||||
* @return HTMLPurifier
|
||||
*/
|
||||
public static function instance($prototype = null) {
|
||||
public static function instance($prototype = null)
|
||||
{
|
||||
if (!self::$instance || $prototype) {
|
||||
if ($prototype instanceof HTMLPurifier) {
|
||||
self::$instance = $prototype;
|
||||
@@ -226,12 +273,20 @@ class HTMLPurifier
|
||||
}
|
||||
|
||||
/**
|
||||
* Singleton for enforcing just one HTML Purifier in your system
|
||||
*
|
||||
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
|
||||
* HTMLPurifier instance to overload singleton with,
|
||||
* or HTMLPurifier_Config instance to configure the
|
||||
* generated version with.
|
||||
*
|
||||
* @return HTMLPurifier
|
||||
* @note Backwards compatibility, see instance()
|
||||
*/
|
||||
public static function getInstance($prototype = null) {
|
||||
public static function getInstance($prototype = null)
|
||||
{
|
||||
return HTMLPurifier::instance($prototype);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -13,6 +13,7 @@
|
||||
$__dir = dirname(__FILE__);
|
||||
|
||||
require_once $__dir . '/HTMLPurifier.php';
|
||||
require_once $__dir . '/HTMLPurifier/Arborize.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrCollections.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform.php';
|
||||
@@ -48,9 +49,11 @@ require_once $__dir . '/HTMLPurifier/Language.php';
|
||||
require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
|
||||
require_once $__dir . '/HTMLPurifier/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node.php';
|
||||
require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
|
||||
require_once $__dir . '/HTMLPurifier/PropertyList.php';
|
||||
require_once $__dir . '/HTMLPurifier/PropertyListIterator.php';
|
||||
require_once $__dir . '/HTMLPurifier/Queue.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHash.php';
|
||||
require_once $__dir . '/HTMLPurifier/StringHashParser.php';
|
||||
@@ -66,7 +69,9 @@ require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
|
||||
require_once $__dir . '/HTMLPurifier/UnitConverter.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParserException.php';
|
||||
require_once $__dir . '/HTMLPurifier/Zipper.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
|
||||
@@ -84,6 +89,7 @@ require_once $__dir . '/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Filter.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Font.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/FontFamily.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ident.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
|
||||
@@ -119,14 +125,19 @@ require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/NameSync.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Nofollow.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoopener.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoreferrer.php';
|
||||
require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Empty.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/List.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
|
||||
require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
|
||||
@@ -141,10 +152,12 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/CommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Edit.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Forms.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Hypertext.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Iframe.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Image.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Legacy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/List.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Name.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Nofollow.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php';
|
||||
@@ -152,10 +165,14 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/SafeScripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoopener.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoreferrer.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php';
|
||||
require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
|
||||
@@ -170,9 +187,13 @@ require_once $__dir . '/HTMLPurifier/Injector/DisplayLinkURI.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/Linkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/PurifierLinkify.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/RemoveEmpty.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
|
||||
require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Comment.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Element.php';
|
||||
require_once $__dir . '/HTMLPurifier/Node/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Composite.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/Core.php';
|
||||
require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php';
|
||||
@@ -189,14 +210,19 @@ require_once $__dir . '/HTMLPurifier/Token/Start.php';
|
||||
require_once $__dir . '/HTMLPurifier/Token/Text.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/DisableResources.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/Munge.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIFilter/SafeIframe.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/data.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/file.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/http.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/news.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/nntp.php';
|
||||
require_once $__dir . '/HTMLPurifier/URIScheme/tel.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Flexible.php';
|
||||
require_once $__dir . '/HTMLPurifier/VarParser/Native.php';
|
||||
|
71
library/HTMLPurifier/Arborize.php
Normal file
71
library/HTMLPurifier/Arborize.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Converts a stream of HTMLPurifier_Token into an HTMLPurifier_Node,
|
||||
* and back again.
|
||||
*
|
||||
* @note This transformation is not an equivalence. We mutate the input
|
||||
* token stream to make it so; see all [MUT] markers in code.
|
||||
*/
|
||||
class HTMLPurifier_Arborize
|
||||
{
|
||||
public static function arborize($tokens, $config, $context) {
|
||||
$definition = $config->getHTMLDefinition();
|
||||
$parent = new HTMLPurifier_Token_Start($definition->info_parent);
|
||||
$stack = array($parent->toNode());
|
||||
foreach ($tokens as $token) {
|
||||
$token->skip = null; // [MUT]
|
||||
$token->carryover = null; // [MUT]
|
||||
if ($token instanceof HTMLPurifier_Token_End) {
|
||||
$token->start = null; // [MUT]
|
||||
$r = array_pop($stack);
|
||||
//assert($r->name === $token->name);
|
||||
//assert(empty($token->attr));
|
||||
$r->endCol = $token->col;
|
||||
$r->endLine = $token->line;
|
||||
$r->endArmor = $token->armor;
|
||||
continue;
|
||||
}
|
||||
$node = $token->toNode();
|
||||
$stack[count($stack)-1]->children[] = $node;
|
||||
if ($token instanceof HTMLPurifier_Token_Start) {
|
||||
$stack[] = $node;
|
||||
}
|
||||
}
|
||||
//assert(count($stack) == 1);
|
||||
return $stack[0];
|
||||
}
|
||||
|
||||
public static function flatten($node, $config, $context) {
|
||||
$level = 0;
|
||||
$nodes = array($level => new HTMLPurifier_Queue(array($node)));
|
||||
$closingTokens = array();
|
||||
$tokens = array();
|
||||
do {
|
||||
while (!$nodes[$level]->isEmpty()) {
|
||||
$node = $nodes[$level]->shift(); // FIFO
|
||||
list($start, $end) = $node->toTokenPair();
|
||||
if ($level > 0) {
|
||||
$tokens[] = $start;
|
||||
}
|
||||
if ($end !== NULL) {
|
||||
$closingTokens[$level][] = $end;
|
||||
}
|
||||
if ($node instanceof HTMLPurifier_Node_Element) {
|
||||
$level++;
|
||||
$nodes[$level] = new HTMLPurifier_Queue();
|
||||
foreach ($node->children as $childNode) {
|
||||
$nodes[$level]->push($childNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
$level--;
|
||||
if ($level && isset($closingTokens[$level])) {
|
||||
while ($token = array_pop($closingTokens[$level])) {
|
||||
$tokens[] = $token;
|
||||
}
|
||||
}
|
||||
} while ($level > 0);
|
||||
return $tokens;
|
||||
}
|
||||
}
|
@@ -8,7 +8,8 @@ class HTMLPurifier_AttrCollections
|
||||
{
|
||||
|
||||
/**
|
||||
* Associative array of attribute collections, indexed by name
|
||||
* Associative array of attribute collections, indexed by name.
|
||||
* @type array
|
||||
*/
|
||||
public $info = array();
|
||||
|
||||
@@ -16,10 +17,16 @@ class HTMLPurifier_AttrCollections
|
||||
* Performs all expansions on internal data for use by other inclusions
|
||||
* It also collects all attribute collection extensions from
|
||||
* modules
|
||||
* @param $attr_types HTMLPurifier_AttrTypes instance
|
||||
* @param $modules Hash array of HTMLPurifier_HTMLModule members
|
||||
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||
* @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members
|
||||
*/
|
||||
public function __construct($attr_types, $modules) {
|
||||
public function __construct($attr_types, $modules)
|
||||
{
|
||||
$this->doConstruct($attr_types, $modules);
|
||||
}
|
||||
|
||||
public function doConstruct($attr_types, $modules)
|
||||
{
|
||||
// load extensions from the modules
|
||||
foreach ($modules as $module) {
|
||||
foreach ($module->attr_collections as $coll_i => $coll) {
|
||||
@@ -30,7 +37,9 @@ class HTMLPurifier_AttrCollections
|
||||
if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
|
||||
// merge in includes
|
||||
$this->info[$coll_i][$attr_i] = array_merge(
|
||||
$this->info[$coll_i][$attr_i], $attr);
|
||||
$this->info[$coll_i][$attr_i],
|
||||
$attr
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$this->info[$coll_i][$attr_i] = $attr;
|
||||
@@ -49,20 +58,29 @@ class HTMLPurifier_AttrCollections
|
||||
/**
|
||||
* Takes a reference to an attribute associative array and performs
|
||||
* all inclusions specified by the zero index.
|
||||
* @param &$attr Reference to attribute array
|
||||
* @param array &$attr Reference to attribute array
|
||||
*/
|
||||
public function performInclusions(&$attr) {
|
||||
if (!isset($attr[0])) return;
|
||||
public function performInclusions(&$attr)
|
||||
{
|
||||
if (!isset($attr[0])) {
|
||||
return;
|
||||
}
|
||||
$merge = $attr[0];
|
||||
$seen = array(); // recursion guard
|
||||
// loop through all the inclusions
|
||||
for ($i = 0; isset($merge[$i]); $i++) {
|
||||
if (isset($seen[$merge[$i]])) continue;
|
||||
if (isset($seen[$merge[$i]])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$merge[$i]] = true;
|
||||
// foreach attribute of the inclusion, copy it over
|
||||
if (!isset($this->info[$merge[$i]])) continue;
|
||||
if (!isset($this->info[$merge[$i]])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($this->info[$merge[$i]] as $key => $value) {
|
||||
if (isset($attr[$key])) continue; // also catches more inclusions
|
||||
if (isset($attr[$key])) {
|
||||
continue;
|
||||
} // also catches more inclusions
|
||||
$attr[$key] = $value;
|
||||
}
|
||||
if (isset($this->info[$merge[$i]][0])) {
|
||||
@@ -76,20 +94,24 @@ class HTMLPurifier_AttrCollections
|
||||
/**
|
||||
* Expands all string identifiers in an attribute array by replacing
|
||||
* them with the appropriate values inside HTMLPurifier_AttrTypes
|
||||
* @param &$attr Reference to attribute array
|
||||
* @param $attr_types HTMLPurifier_AttrTypes instance
|
||||
* @param array &$attr Reference to attribute array
|
||||
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
|
||||
*/
|
||||
public function expandIdentifiers(&$attr, $attr_types) {
|
||||
|
||||
public function expandIdentifiers(&$attr, $attr_types)
|
||||
{
|
||||
// because foreach will process new elements we add, make sure we
|
||||
// skip duplicates
|
||||
$processed = array();
|
||||
|
||||
foreach ($attr as $def_i => $def) {
|
||||
// skip inclusions
|
||||
if ($def_i === 0) continue;
|
||||
if ($def_i === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($processed[$def_i])) continue;
|
||||
if (isset($processed[$def_i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// determine whether or not attribute is required
|
||||
if ($required = (strpos($def_i, '*') !== false)) {
|
||||
@@ -120,9 +142,7 @@ class HTMLPurifier_AttrCollections
|
||||
unset($attr[$def_i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -14,23 +14,25 @@ abstract class HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is minimized. Has no
|
||||
* meaning in other contexts.
|
||||
* Tells us whether or not an HTML attribute is minimized.
|
||||
* Has no meaning in other contexts.
|
||||
* @type bool
|
||||
*/
|
||||
public $minimized = false;
|
||||
|
||||
/**
|
||||
* Tells us whether or not an HTML attribute is required. Has no
|
||||
* meaning in other contexts
|
||||
* Tells us whether or not an HTML attribute is required.
|
||||
* Has no meaning in other contexts
|
||||
* @type bool
|
||||
*/
|
||||
public $required = false;
|
||||
|
||||
/**
|
||||
* Validates and cleans passed string according to a definition.
|
||||
*
|
||||
* @param $string String to be validated and cleaned.
|
||||
* @param $config Mandatory HTMLPurifier_Config object.
|
||||
* @param $context Mandatory HTMLPurifier_AttrContext object.
|
||||
* @param string $string String to be validated and cleaned.
|
||||
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
|
||||
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object.
|
||||
*/
|
||||
abstract public function validate($string, $config, $context);
|
||||
|
||||
@@ -55,7 +57,8 @@ abstract class HTMLPurifier_AttrDef
|
||||
* parsing XML, thus, this behavior may still be correct. We
|
||||
* assume that newlines have been normalized.
|
||||
*/
|
||||
public function parseCDATA($string) {
|
||||
public function parseCDATA($string)
|
||||
{
|
||||
$string = trim($string);
|
||||
$string = str_replace(array("\n", "\t", "\r"), ' ', $string);
|
||||
return $string;
|
||||
@@ -63,10 +66,11 @@ abstract class HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* Factory method for creating this class from a string.
|
||||
* @param $string String construction info
|
||||
* @return Created AttrDef object corresponding to $string
|
||||
* @param string $string String construction info
|
||||
* @return HTMLPurifier_AttrDef Created AttrDef object corresponding to $string
|
||||
*/
|
||||
public function make($string) {
|
||||
public function make($string)
|
||||
{
|
||||
// default implementation, return a flyweight of this object.
|
||||
// If $string has an effect on the returned object (i.e. you
|
||||
// need to overload this method), it is best
|
||||
@@ -77,11 +81,64 @@ abstract class HTMLPurifier_AttrDef
|
||||
/**
|
||||
* Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
|
||||
* properly. THIS IS A HACK!
|
||||
* @param string $string a CSS colour definition
|
||||
* @return string
|
||||
*/
|
||||
protected function mungeRgb($string) {
|
||||
return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
|
||||
protected function mungeRgb($string)
|
||||
{
|
||||
$p = '\s*(\d+(\.\d+)?([%]?))\s*';
|
||||
|
||||
if (preg_match('/(rgba|hsla)\(/', $string)) {
|
||||
return preg_replace('/(rgba|hsla)\('.$p.','.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8,\11)', $string);
|
||||
}
|
||||
|
||||
return preg_replace('/(rgb|hsl)\('.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8)', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a possibly escaped CSS string and returns the "pure"
|
||||
* version of it.
|
||||
*/
|
||||
protected function expandCSSEscape($string)
|
||||
{
|
||||
// flexibly parse it
|
||||
$ret = '';
|
||||
for ($i = 0, $c = strlen($string); $i < $c; $i++) {
|
||||
if ($string[$i] === '\\') {
|
||||
$i++;
|
||||
if ($i >= $c) {
|
||||
$ret .= '\\';
|
||||
break;
|
||||
}
|
||||
if (ctype_xdigit($string[$i])) {
|
||||
$code = $string[$i];
|
||||
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
|
||||
if (!ctype_xdigit($string[$i])) {
|
||||
break;
|
||||
}
|
||||
$code .= $string[$i];
|
||||
}
|
||||
// We have to be extremely careful when adding
|
||||
// new characters, to make sure we're not breaking
|
||||
// the encoding.
|
||||
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
|
||||
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') {
|
||||
continue;
|
||||
}
|
||||
$ret .= $char;
|
||||
if ($i < $c && trim($string[$i]) !== '') {
|
||||
$i--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($string[$i] === "\n") {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$ret .= $string[$i];
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -14,20 +14,53 @@
|
||||
class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($css, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $css
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($css, $config, $context)
|
||||
{
|
||||
$css = $this->parseCDATA($css);
|
||||
|
||||
$definition = $config->getCSSDefinition();
|
||||
$allow_duplicates = $config->get("CSS.AllowDuplicates");
|
||||
|
||||
// we're going to break the spec and explode by semicolons.
|
||||
// This is because semicolon rarely appears in escaped form
|
||||
// Doing this is generally flaky but fast
|
||||
// IT MIGHT APPEAR IN URIs, see HTMLPurifier_AttrDef_CSSURI
|
||||
// for details
|
||||
|
||||
$declarations = explode(';', $css);
|
||||
// According to the CSS2.1 spec, the places where a
|
||||
// non-delimiting semicolon can appear are in strings
|
||||
// escape sequences. So here is some dumb hack to
|
||||
// handle quotes.
|
||||
$len = strlen($css);
|
||||
$accum = "";
|
||||
$declarations = array();
|
||||
$quoted = false;
|
||||
for ($i = 0; $i < $len; $i++) {
|
||||
$c = strcspn($css, ";'\"", $i);
|
||||
$accum .= substr($css, $i, $c);
|
||||
$i += $c;
|
||||
if ($i == $len) break;
|
||||
$d = $css[$i];
|
||||
if ($quoted) {
|
||||
$accum .= $d;
|
||||
if ($d == $quoted) {
|
||||
$quoted = false;
|
||||
}
|
||||
} else {
|
||||
if ($d == ";") {
|
||||
$declarations[] = $accum;
|
||||
$accum = "";
|
||||
} else {
|
||||
$accum .= $d;
|
||||
$quoted = $d;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($accum != "") $declarations[] = $accum;
|
||||
|
||||
$propvalues = array();
|
||||
$new_declarations = '';
|
||||
|
||||
/**
|
||||
* Name of the current CSS property being validated.
|
||||
@@ -36,35 +69,52 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
$context->register('CurrentCSSProperty', $property);
|
||||
|
||||
foreach ($declarations as $declaration) {
|
||||
if (!$declaration) continue;
|
||||
if (!strpos($declaration, ':')) continue;
|
||||
if (!$declaration) {
|
||||
continue;
|
||||
}
|
||||
if (!strpos($declaration, ':')) {
|
||||
continue;
|
||||
}
|
||||
list($property, $value) = explode(':', $declaration, 2);
|
||||
$property = trim($property);
|
||||
$value = trim($value);
|
||||
$value = trim($value);
|
||||
$ok = false;
|
||||
do {
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
if (ctype_lower($property)) break;
|
||||
if (ctype_lower($property)) {
|
||||
break;
|
||||
}
|
||||
$property = strtolower($property);
|
||||
if (isset($definition->info[$property])) {
|
||||
$ok = true;
|
||||
break;
|
||||
}
|
||||
} while(0);
|
||||
if (!$ok) continue;
|
||||
} while (0);
|
||||
if (!$ok) {
|
||||
continue;
|
||||
}
|
||||
// inefficient call, since the validator will do this again
|
||||
if (strtolower(trim($value)) !== 'inherit') {
|
||||
// inherit works for everything (but only on the base property)
|
||||
$result = $definition->info[$property]->validate(
|
||||
$value, $config, $context );
|
||||
$value,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
} else {
|
||||
$result = 'inherit';
|
||||
}
|
||||
if ($result === false) continue;
|
||||
$propvalues[$property] = $result;
|
||||
if ($result === false) {
|
||||
continue;
|
||||
}
|
||||
if ($allow_duplicates) {
|
||||
$new_declarations .= "$property:$result;";
|
||||
} else {
|
||||
$propvalues[$property] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
$context->destroy('CurrentCSSProperty');
|
||||
@@ -73,7 +123,6 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
|
||||
// slightly inefficient, but it's the only way of getting rid of
|
||||
// duplicates. Perhaps config to optimize it, but not now.
|
||||
|
||||
$new_declarations = '';
|
||||
foreach ($propvalues as $prop => $value) {
|
||||
$new_declarations .= "$prop:$value;";
|
||||
}
|
||||
|
@@ -3,19 +3,32 @@
|
||||
class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(false); // opacity is non-negative, but we will clamp it
|
||||
}
|
||||
|
||||
public function validate($number, $config, $context) {
|
||||
/**
|
||||
* @param string $number
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return string
|
||||
*/
|
||||
public function validate($number, $config, $context)
|
||||
{
|
||||
$result = parent::validate($number, $config, $context);
|
||||
if ($result === false) return $result;
|
||||
$float = (float) $result;
|
||||
if ($float < 0.0) $result = '0';
|
||||
if ($float > 1.0) $result = '1';
|
||||
if ($result === false) {
|
||||
return $result;
|
||||
}
|
||||
$float = (float)$result;
|
||||
if ($float < 0.0) {
|
||||
$result = '0';
|
||||
}
|
||||
if ($float > 1.0) {
|
||||
$result = '1';
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -9,11 +9,16 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* Local copy of component validators.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
|
||||
public function __construct($config) {
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['background-color'] = $def->info['background-color'];
|
||||
$this->info['background-image'] = $def->info['background-image'];
|
||||
@@ -22,40 +27,55 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
$this->info['background-position'] = $def->info['background-position'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') return false;
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// munge rgb() decl if necessary
|
||||
$string = $this->mungeRgb($string);
|
||||
|
||||
// assumes URI doesn't have spaces in it
|
||||
$bits = explode(' ', strtolower($string)); // bits to process
|
||||
$bits = explode(' ', $string); // bits to process
|
||||
|
||||
$caught = array();
|
||||
$caught['color'] = false;
|
||||
$caught['image'] = false;
|
||||
$caught['repeat'] = false;
|
||||
$caught['color'] = false;
|
||||
$caught['image'] = false;
|
||||
$caught['repeat'] = false;
|
||||
$caught['attachment'] = false;
|
||||
$caught['position'] = false;
|
||||
|
||||
$i = 0; // number of catches
|
||||
$none = false;
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
if ($bit === '') continue;
|
||||
if ($bit === '') {
|
||||
continue;
|
||||
}
|
||||
foreach ($caught as $key => $status) {
|
||||
if ($key != 'position') {
|
||||
if ($status !== false) continue;
|
||||
if ($status !== false) {
|
||||
continue;
|
||||
}
|
||||
$r = $this->info['background-' . $key]->validate($bit, $config, $context);
|
||||
} else {
|
||||
$r = $bit;
|
||||
}
|
||||
if ($r === false) continue;
|
||||
if ($r === false) {
|
||||
continue;
|
||||
}
|
||||
if ($key == 'position') {
|
||||
if ($caught[$key] === false) $caught[$key] = '';
|
||||
if ($caught[$key] === false) {
|
||||
$caught[$key] = '';
|
||||
}
|
||||
$caught[$key] .= $r . ' ';
|
||||
} else {
|
||||
$caught[$key] = $r;
|
||||
@@ -65,7 +85,9 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) return false;
|
||||
if (!$i) {
|
||||
return false;
|
||||
}
|
||||
if ($caught['position'] !== false) {
|
||||
$caught['position'] = $this->info['background-position']->
|
||||
validate($caught['position'], $config, $context);
|
||||
@@ -73,15 +95,17 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
|
||||
|
||||
$ret = array();
|
||||
foreach ($caught as $value) {
|
||||
if ($value === false) continue;
|
||||
if ($value === false) {
|
||||
continue;
|
||||
}
|
||||
$ret[] = $value;
|
||||
}
|
||||
|
||||
if (empty($ret)) return false;
|
||||
if (empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -44,22 +44,38 @@
|
||||
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_Length
|
||||
*/
|
||||
protected $length;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_Percentage
|
||||
*/
|
||||
protected $percentage;
|
||||
|
||||
public function __construct() {
|
||||
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
|
||||
public function __construct()
|
||||
{
|
||||
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
|
||||
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
$bits = explode(' ', $string);
|
||||
|
||||
$keywords = array();
|
||||
$keywords['h'] = false; // left, right
|
||||
$keywords['v'] = false; // top, bottom
|
||||
$keywords['c'] = false; // center
|
||||
$keywords['ch'] = false; // center (first word)
|
||||
$keywords['cv'] = false; // center (second word)
|
||||
$measures = array();
|
||||
|
||||
$i = 0;
|
||||
@@ -73,12 +89,21 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||
);
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
if ($bit === '') continue;
|
||||
if ($bit === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// test for keyword
|
||||
$lbit = ctype_lower($bit) ? $bit : strtolower($bit);
|
||||
if (isset($lookup[$lbit])) {
|
||||
$status = $lookup[$lbit];
|
||||
if ($status == 'c') {
|
||||
if ($i == 0) {
|
||||
$status = 'ch';
|
||||
} else {
|
||||
$status = 'cv';
|
||||
}
|
||||
}
|
||||
$keywords[$status] = $lbit;
|
||||
$i++;
|
||||
}
|
||||
@@ -96,31 +121,37 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
|
||||
$measures[] = $r;
|
||||
$i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!$i) return false; // no valid values were caught
|
||||
|
||||
if (!$i) {
|
||||
return false;
|
||||
} // no valid values were caught
|
||||
|
||||
$ret = array();
|
||||
|
||||
// first keyword
|
||||
if ($keywords['h']) $ret[] = $keywords['h'];
|
||||
elseif (count($measures)) $ret[] = array_shift($measures);
|
||||
elseif ($keywords['c']) {
|
||||
$ret[] = $keywords['c'];
|
||||
$keywords['c'] = false; // prevent re-use: center = center center
|
||||
if ($keywords['h']) {
|
||||
$ret[] = $keywords['h'];
|
||||
} elseif ($keywords['ch']) {
|
||||
$ret[] = $keywords['ch'];
|
||||
$keywords['cv'] = false; // prevent re-use: center = center center
|
||||
} elseif (count($measures)) {
|
||||
$ret[] = array_shift($measures);
|
||||
}
|
||||
|
||||
if ($keywords['v']) $ret[] = $keywords['v'];
|
||||
elseif (count($measures)) $ret[] = array_shift($measures);
|
||||
elseif ($keywords['c']) $ret[] = $keywords['c'];
|
||||
if ($keywords['v']) {
|
||||
$ret[] = $keywords['v'];
|
||||
} elseif ($keywords['cv']) {
|
||||
$ret[] = $keywords['cv'];
|
||||
} elseif (count($measures)) {
|
||||
$ret[] = array_shift($measures);
|
||||
}
|
||||
|
||||
if (empty($ret)) return false;
|
||||
if (empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -8,17 +8,29 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* Local copy of properties this property is shorthand for.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
*/
|
||||
protected $info = array();
|
||||
|
||||
public function __construct($config) {
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['border-width'] = $def->info['border-width'];
|
||||
$this->info['border-style'] = $def->info['border-style'];
|
||||
$this->info['border-top-color'] = $def->info['border-top-color'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
$string = $this->mungeRgb($string);
|
||||
$bits = explode(' ', $string);
|
||||
@@ -26,7 +38,9 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||
$ret = ''; // return value
|
||||
foreach ($bits as $bit) {
|
||||
foreach ($this->info as $propname => $validator) {
|
||||
if (isset($done[$propname])) continue;
|
||||
if (isset($done[$propname])) {
|
||||
continue;
|
||||
}
|
||||
$r = $validator->validate($bit, $config, $context);
|
||||
if ($r !== false) {
|
||||
$ret .= $r . ' ';
|
||||
@@ -37,7 +51,6 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
|
||||
}
|
||||
return rtrim($ret);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,56 +6,137 @@
|
||||
class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($color, $config, $context) {
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_CSS_AlphaValue
|
||||
*/
|
||||
protected $alpha;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $color
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($color, $config, $context)
|
||||
{
|
||||
static $colors = null;
|
||||
if ($colors === null) $colors = $config->get('Core.ColorKeywords');
|
||||
if ($colors === null) {
|
||||
$colors = $config->get('Core.ColorKeywords');
|
||||
}
|
||||
|
||||
$color = trim($color);
|
||||
if ($color === '') return false;
|
||||
if ($color === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$lower = strtolower($color);
|
||||
if (isset($colors[$lower])) return $colors[$lower];
|
||||
if (isset($colors[$lower])) {
|
||||
return $colors[$lower];
|
||||
}
|
||||
|
||||
if (strpos($color, 'rgb(') !== false) {
|
||||
// rgb literal handling
|
||||
if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
|
||||
$length = strlen($color);
|
||||
if (strpos($color, ')') !== $length - 1) return false;
|
||||
$triad = substr($color, 4, $length - 4 - 1);
|
||||
$parts = explode(',', $triad);
|
||||
if (count($parts) !== 3) return false;
|
||||
$type = false; // to ensure that they're all the same type
|
||||
if (strpos($color, ')') !== $length - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get used function : rgb, rgba, hsl or hsla
|
||||
$function = $matches[1];
|
||||
|
||||
$parameters_size = 3;
|
||||
$alpha_channel = false;
|
||||
if (substr($function, -1) === 'a') {
|
||||
$parameters_size = 4;
|
||||
$alpha_channel = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allowed types for values :
|
||||
* parameter_position => [type => max_value]
|
||||
*/
|
||||
$allowed_types = array(
|
||||
1 => array('percentage' => 100, 'integer' => 255),
|
||||
2 => array('percentage' => 100, 'integer' => 255),
|
||||
3 => array('percentage' => 100, 'integer' => 255),
|
||||
);
|
||||
$allow_different_types = false;
|
||||
|
||||
if (strpos($function, 'hsl') !== false) {
|
||||
$allowed_types = array(
|
||||
1 => array('integer' => 360),
|
||||
2 => array('percentage' => 100),
|
||||
3 => array('percentage' => 100),
|
||||
);
|
||||
$allow_different_types = true;
|
||||
}
|
||||
|
||||
$values = trim(str_replace($function, '', $color), ' ()');
|
||||
|
||||
$parts = explode(',', $values);
|
||||
if (count($parts) !== $parameters_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$type = false;
|
||||
$new_parts = array();
|
||||
$i = 0;
|
||||
|
||||
foreach ($parts as $part) {
|
||||
$i++;
|
||||
$part = trim($part);
|
||||
if ($part === '') return false;
|
||||
$length = strlen($part);
|
||||
if ($part[$length - 1] === '%') {
|
||||
// handle percents
|
||||
if (!$type) {
|
||||
$type = 'percentage';
|
||||
} elseif ($type !== 'percentage') {
|
||||
|
||||
if ($part === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// different check for alpha channel
|
||||
if ($alpha_channel === true && $i === count($parts)) {
|
||||
$result = $this->alpha->validate($part, $config, $context);
|
||||
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
$num = (float) substr($part, 0, $length - 1);
|
||||
if ($num < 0) $num = 0;
|
||||
if ($num > 100) $num = 100;
|
||||
$new_parts[] = "$num%";
|
||||
|
||||
$new_parts[] = (string)$result;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (substr($part, -1) === '%') {
|
||||
$current_type = 'percentage';
|
||||
} else {
|
||||
// handle integers
|
||||
if (!$type) {
|
||||
$type = 'integer';
|
||||
} elseif ($type !== 'integer') {
|
||||
return false;
|
||||
}
|
||||
$num = (int) $part;
|
||||
if ($num < 0) $num = 0;
|
||||
if ($num > 255) $num = 255;
|
||||
$new_parts[] = (string) $num;
|
||||
$current_type = 'integer';
|
||||
}
|
||||
|
||||
if (!array_key_exists($current_type, $allowed_types[$i])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$type) {
|
||||
$type = $current_type;
|
||||
}
|
||||
|
||||
if ($allow_different_types === false && $type != $current_type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$max_value = $allowed_types[$i][$current_type];
|
||||
|
||||
if ($current_type == 'integer') {
|
||||
// Return value between range 0 -> $max_value
|
||||
$new_parts[] = (int)max(min($part, $max_value), 0);
|
||||
} elseif ($current_type == 'percentage') {
|
||||
$new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
|
||||
}
|
||||
}
|
||||
$new_triad = implode(',', $new_parts);
|
||||
$color = "rgb($new_triad)";
|
||||
|
||||
$new_values = implode(',', $new_parts);
|
||||
|
||||
$color = $function . '(' . $new_values . ')';
|
||||
} else {
|
||||
// hexadecimal handling
|
||||
if ($color[0] === '#') {
|
||||
@@ -65,12 +146,14 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
|
||||
$color = '#' . $color;
|
||||
}
|
||||
$length = strlen($hex);
|
||||
if ($length !== 3 && $length !== 6) return false;
|
||||
if (!ctype_xdigit($hex)) return false;
|
||||
if ($length !== 3 && $length !== 6) {
|
||||
return false;
|
||||
}
|
||||
if (!ctype_xdigit($hex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $color;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -13,26 +13,36 @@ class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* List of HTMLPurifier_AttrDef objects that may process strings
|
||||
* List of objects that may process strings.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $defs;
|
||||
|
||||
/**
|
||||
* @param $defs List of HTMLPurifier_AttrDef objects
|
||||
* @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects
|
||||
*/
|
||||
public function __construct($defs) {
|
||||
public function __construct($defs)
|
||||
{
|
||||
$this->defs = $defs;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
foreach ($this->defs as $i => $def) {
|
||||
$result = $this->defs[$i]->validate($string, $config, $context);
|
||||
if ($result !== false) return $result;
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -5,22 +5,38 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
|
||||
{
|
||||
public $def, $element;
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
public $def;
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
public $element;
|
||||
|
||||
/**
|
||||
* @param $def Definition to wrap
|
||||
* @param $element Element to deny
|
||||
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||
* @param string $element Element to deny
|
||||
*/
|
||||
public function __construct($def, $element) {
|
||||
public function __construct($def, $element)
|
||||
{
|
||||
$this->def = $def;
|
||||
$this->element = $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if CurrentToken is set and equal to $this->element
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context) {
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$token = $context->get('CurrentToken', true);
|
||||
if ($token && $token->name == $this->element) return false;
|
||||
if ($token && $token->name == $this->element) {
|
||||
return false;
|
||||
}
|
||||
return $this->def->validate($string, $config, $context);
|
||||
}
|
||||
}
|
||||
|
@@ -7,23 +7,37 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_Integer
|
||||
*/
|
||||
protected $intValidator;
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
$this->intValidator = new HTMLPurifier_AttrDef_Integer();
|
||||
}
|
||||
|
||||
public function validate($value, $config, $context) {
|
||||
/**
|
||||
* @param string $value
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($value, $config, $context)
|
||||
{
|
||||
$value = $this->parseCDATA($value);
|
||||
if ($value === 'none') return $value;
|
||||
if ($value === 'none') {
|
||||
return $value;
|
||||
}
|
||||
// if we looped this we could support multiple filters
|
||||
$function_length = strcspn($value, '(');
|
||||
$function = trim(substr($value, 0, $function_length));
|
||||
if ($function !== 'alpha' &&
|
||||
$function !== 'Alpha' &&
|
||||
$function !== 'progid:DXImageTransform.Microsoft.Alpha'
|
||||
) return false;
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$cursor = $function_length + 1;
|
||||
$parameters_length = strcspn($value, ')', $cursor);
|
||||
$parameters = substr($value, $cursor, $parameters_length);
|
||||
@@ -32,15 +46,25 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
|
||||
$lookup = array();
|
||||
foreach ($params as $param) {
|
||||
list($key, $value) = explode('=', $param);
|
||||
$key = trim($key);
|
||||
$key = trim($key);
|
||||
$value = trim($value);
|
||||
if (isset($lookup[$key])) continue;
|
||||
if ($key !== 'opacity') continue;
|
||||
if (isset($lookup[$key])) {
|
||||
continue;
|
||||
}
|
||||
if ($key !== 'opacity') {
|
||||
continue;
|
||||
}
|
||||
$value = $this->intValidator->validate($value, $config, $context);
|
||||
if ($value === false) continue;
|
||||
$int = (int) $value;
|
||||
if ($int > 100) $value = '100';
|
||||
if ($int < 0) $value = '0';
|
||||
if ($value === false) {
|
||||
continue;
|
||||
}
|
||||
$int = (int)$value;
|
||||
if ($int > 100) {
|
||||
$value = '100';
|
||||
}
|
||||
if ($int < 0) {
|
||||
$value = '0';
|
||||
}
|
||||
$ret_params[] = "$key=$value";
|
||||
$lookup[$key] = true;
|
||||
}
|
||||
@@ -48,7 +72,6 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
|
||||
$ret_function = "$function($ret_parameters)";
|
||||
return $ret_function;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -7,8 +7,8 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of component validators.
|
||||
*
|
||||
* Local copy of validators
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note If we moved specific CSS property definitions to their own
|
||||
* classes instead of having them be assembled at run time by
|
||||
* CSSDefinition, this wouldn't be necessary. We'd instantiate
|
||||
@@ -16,18 +16,28 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
*/
|
||||
protected $info = array();
|
||||
|
||||
public function __construct($config) {
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['font-style'] = $def->info['font-style'];
|
||||
$this->info['font-style'] = $def->info['font-style'];
|
||||
$this->info['font-variant'] = $def->info['font-variant'];
|
||||
$this->info['font-weight'] = $def->info['font-weight'];
|
||||
$this->info['font-size'] = $def->info['font-size'];
|
||||
$this->info['line-height'] = $def->info['line-height'];
|
||||
$this->info['font-family'] = $def->info['font-family'];
|
||||
$this->info['font-weight'] = $def->info['font-weight'];
|
||||
$this->info['font-size'] = $def->info['font-size'];
|
||||
$this->info['line-height'] = $def->info['line-height'];
|
||||
$this->info['font-family'] = $def->info['font-family'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $system_fonts = array(
|
||||
'caption' => true,
|
||||
'icon' => true,
|
||||
@@ -39,7 +49,9 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') return false;
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if it's one of the keywords
|
||||
$lowercase_string = strtolower($string);
|
||||
@@ -54,15 +66,20 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
$final = ''; // output
|
||||
|
||||
for ($i = 0, $size = count($bits); $i < $size; $i++) {
|
||||
if ($bits[$i] === '') continue;
|
||||
if ($bits[$i] === '') {
|
||||
continue;
|
||||
}
|
||||
switch ($stage) {
|
||||
|
||||
// attempting to catch font-style, font-variant or font-weight
|
||||
case 0:
|
||||
case 0: // attempting to catch font-style, font-variant or font-weight
|
||||
foreach ($stage_1 as $validator_name) {
|
||||
if (isset($caught[$validator_name])) continue;
|
||||
if (isset($caught[$validator_name])) {
|
||||
continue;
|
||||
}
|
||||
$r = $this->info[$validator_name]->validate(
|
||||
$bits[$i], $config, $context);
|
||||
$bits[$i],
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r . ' ';
|
||||
$caught[$validator_name] = true;
|
||||
@@ -70,15 +87,17 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
}
|
||||
}
|
||||
// all three caught, continue on
|
||||
if (count($caught) >= 3) $stage = 1;
|
||||
if ($r !== false) break;
|
||||
|
||||
// attempting to catch font-size and perhaps line-height
|
||||
case 1:
|
||||
if (count($caught) >= 3) {
|
||||
$stage = 1;
|
||||
}
|
||||
if ($r !== false) {
|
||||
break;
|
||||
}
|
||||
case 1: // attempting to catch font-size and perhaps line-height
|
||||
$found_slash = false;
|
||||
if (strpos($bits[$i], '/') !== false) {
|
||||
list($font_size, $line_height) =
|
||||
explode('/', $bits[$i]);
|
||||
explode('/', $bits[$i]);
|
||||
if ($line_height === '') {
|
||||
// ooh, there's a space after the slash!
|
||||
$line_height = false;
|
||||
@@ -89,14 +108,19 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
$line_height = false;
|
||||
}
|
||||
$r = $this->info['font-size']->validate(
|
||||
$font_size, $config, $context);
|
||||
$font_size,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r;
|
||||
// attempt to catch line-height
|
||||
if ($line_height === false) {
|
||||
// we need to scroll forward
|
||||
for ($j = $i + 1; $j < $size; $j++) {
|
||||
if ($bits[$j] === '') continue;
|
||||
if ($bits[$j] === '') {
|
||||
continue;
|
||||
}
|
||||
if ($bits[$j] === '/') {
|
||||
if ($found_slash) {
|
||||
return false;
|
||||
@@ -116,7 +140,10 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
if ($found_slash) {
|
||||
$i = $j;
|
||||
$r = $this->info['line-height']->validate(
|
||||
$line_height, $config, $context);
|
||||
$line_height,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= '/' . $r;
|
||||
}
|
||||
@@ -126,13 +153,14 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
||||
// attempting to catch font-family
|
||||
case 2:
|
||||
case 2: // attempting to catch font-family
|
||||
$font_family =
|
||||
implode(' ', array_slice($bits, $i, $size - $i));
|
||||
$r = $this->info['font-family']->validate(
|
||||
$font_family, $config, $context);
|
||||
$font_family,
|
||||
$config,
|
||||
$context
|
||||
);
|
||||
if ($r !== false) {
|
||||
$final .= $r . ' ';
|
||||
// processing completed successfully
|
||||
@@ -143,7 +171,6 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -2,12 +2,58 @@
|
||||
|
||||
/**
|
||||
* Validates a font family list according to CSS spec
|
||||
* @todo whitelisting allowed fonts would be nice
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
protected $mask = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->mask = '_- ';
|
||||
for ($c = 'a'; $c <= 'z'; $c++) {
|
||||
$this->mask .= $c;
|
||||
}
|
||||
for ($c = 'A'; $c <= 'Z'; $c++) {
|
||||
$this->mask .= $c;
|
||||
}
|
||||
for ($c = '0'; $c <= '9'; $c++) {
|
||||
$this->mask .= $c;
|
||||
} // cast-y, but should be fine
|
||||
// special bytes used by UTF-8
|
||||
for ($i = 0x80; $i <= 0xFF; $i++) {
|
||||
// We don't bother excluding invalid bytes in this range,
|
||||
// because the our restriction of well-formed UTF-8 will
|
||||
// prevent these from ever occurring.
|
||||
$this->mask .= chr($i);
|
||||
}
|
||||
|
||||
/*
|
||||
PHP's internal strcspn implementation is
|
||||
O(length of string * length of mask), making it inefficient
|
||||
for large masks. However, it's still faster than
|
||||
preg_match 8)
|
||||
for (p = s1;;) {
|
||||
spanp = s2;
|
||||
do {
|
||||
if (*spanp == c || p == s1_end) {
|
||||
return p - s1;
|
||||
}
|
||||
} while (spanp++ < (s2_end - 1));
|
||||
c = *++p;
|
||||
}
|
||||
*/
|
||||
// possible optimization: invert the mask.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $generic_names = array(
|
||||
'serif' => true,
|
||||
'sans-serif' => true,
|
||||
@@ -15,73 +61,156 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
|
||||
'fantasy' => true,
|
||||
'cursive' => true
|
||||
);
|
||||
$allowed_fonts = $config->get('CSS.AllowedFonts');
|
||||
|
||||
// assume that no font names contain commas in them
|
||||
$fonts = explode(',', $string);
|
||||
$final = '';
|
||||
foreach($fonts as $font) {
|
||||
foreach ($fonts as $font) {
|
||||
$font = trim($font);
|
||||
if ($font === '') continue;
|
||||
if ($font === '') {
|
||||
continue;
|
||||
}
|
||||
// match a generic name
|
||||
if (isset($generic_names[$font])) {
|
||||
$final .= $font . ', ';
|
||||
if ($allowed_fonts === null || isset($allowed_fonts[$font])) {
|
||||
$final .= $font . ', ';
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// match a quoted name
|
||||
if ($font[0] === '"' || $font[0] === "'") {
|
||||
$length = strlen($font);
|
||||
if ($length <= 2) continue;
|
||||
$quote = $font[0];
|
||||
if ($font[$length - 1] !== $quote) continue;
|
||||
$font = substr($font, 1, $length - 2);
|
||||
|
||||
$new_font = '';
|
||||
for ($i = 0, $c = strlen($font); $i < $c; $i++) {
|
||||
if ($font[$i] === '\\') {
|
||||
$i++;
|
||||
if ($i >= $c) {
|
||||
$new_font .= '\\';
|
||||
break;
|
||||
}
|
||||
if (ctype_xdigit($font[$i])) {
|
||||
$code = $font[$i];
|
||||
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
|
||||
if (!ctype_xdigit($font[$i])) break;
|
||||
$code .= $font[$i];
|
||||
}
|
||||
// We have to be extremely careful when adding
|
||||
// new characters, to make sure we're not breaking
|
||||
// the encoding.
|
||||
$char = HTMLPurifier_Encoder::unichr(hexdec($code));
|
||||
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
|
||||
$new_font .= $char;
|
||||
if ($i < $c && trim($font[$i]) !== '') $i--;
|
||||
continue;
|
||||
}
|
||||
if ($font[$i] === "\n") continue;
|
||||
}
|
||||
$new_font .= $font[$i];
|
||||
if ($length <= 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$font = $new_font;
|
||||
$quote = $font[0];
|
||||
if ($font[$length - 1] !== $quote) {
|
||||
continue;
|
||||
}
|
||||
$font = substr($font, 1, $length - 2);
|
||||
}
|
||||
|
||||
$font = $this->expandCSSEscape($font);
|
||||
|
||||
// $font is a pure representation of the font name
|
||||
|
||||
if ($allowed_fonts !== null && !isset($allowed_fonts[$font])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ctype_alnum($font) && $font !== '') {
|
||||
// very simple font, allow it in unharmed
|
||||
$final .= $font . ', ';
|
||||
continue;
|
||||
}
|
||||
|
||||
// complicated font, requires quoting
|
||||
// bugger out on whitespace. form feed (0C) really
|
||||
// shouldn't show up regardless
|
||||
$font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
|
||||
|
||||
// armor single quotes and new lines
|
||||
$font = str_replace("\\", "\\\\", $font);
|
||||
$font = str_replace("'", "\\'", $font);
|
||||
// Here, there are various classes of characters which need
|
||||
// to be treated differently:
|
||||
// - Alphanumeric characters are essentially safe. We
|
||||
// handled these above.
|
||||
// - Spaces require quoting, though most parsers will do
|
||||
// the right thing if there aren't any characters that
|
||||
// can be misinterpreted
|
||||
// - Dashes rarely occur, but they fairly unproblematic
|
||||
// for parsing/rendering purposes.
|
||||
// The above characters cover the majority of Western font
|
||||
// names.
|
||||
// - Arbitrary Unicode characters not in ASCII. Because
|
||||
// most parsers give little thought to Unicode, treatment
|
||||
// of these codepoints is basically uniform, even for
|
||||
// punctuation-like codepoints. These characters can
|
||||
// show up in non-Western pages and are supported by most
|
||||
// major browsers, for example: "MS 明朝" is a
|
||||
// legitimate font-name
|
||||
// <http://ja.wikipedia.org/wiki/MS_明朝>. See
|
||||
// the CSS3 spec for more examples:
|
||||
// <http://www.w3.org/TR/2011/WD-css3-fonts-20110324/localizedfamilynames.png>
|
||||
// You can see live samples of these on the Internet:
|
||||
// <http://www.google.co.jp/search?q=font-family+MS+明朝|ゴシック>
|
||||
// However, most of these fonts have ASCII equivalents:
|
||||
// for example, 'MS Mincho', and it's considered
|
||||
// professional to use ASCII font names instead of
|
||||
// Unicode font names. Thanks Takeshi Terada for
|
||||
// providing this information.
|
||||
// The following characters, to my knowledge, have not been
|
||||
// used to name font names.
|
||||
// - Single quote. While theoretically you might find a
|
||||
// font name that has a single quote in its name (serving
|
||||
// as an apostrophe, e.g. Dave's Scribble), I haven't
|
||||
// been able to find any actual examples of this.
|
||||
// Internet Explorer's cssText translation (which I
|
||||
// believe is invoked by innerHTML) normalizes any
|
||||
// quoting to single quotes, and fails to escape single
|
||||
// quotes. (Note that this is not IE's behavior for all
|
||||
// CSS properties, just some sort of special casing for
|
||||
// font-family). So a single quote *cannot* be used
|
||||
// safely in the font-family context if there will be an
|
||||
// innerHTML/cssText translation. Note that Firefox 3.x
|
||||
// does this too.
|
||||
// - Double quote. In IE, these get normalized to
|
||||
// single-quotes, no matter what the encoding. (Fun
|
||||
// fact, in IE8, the 'content' CSS property gained
|
||||
// support, where they special cased to preserve encoded
|
||||
// double quotes, but still translate unadorned double
|
||||
// quotes into single quotes.) So, because their
|
||||
// fixpoint behavior is identical to single quotes, they
|
||||
// cannot be allowed either. Firefox 3.x displays
|
||||
// single-quote style behavior.
|
||||
// - Backslashes are reduced by one (so \\ -> \) every
|
||||
// iteration, so they cannot be used safely. This shows
|
||||
// up in IE7, IE8 and FF3
|
||||
// - Semicolons, commas and backticks are handled properly.
|
||||
// - The rest of the ASCII punctuation is handled properly.
|
||||
// We haven't checked what browsers do to unadorned
|
||||
// versions, but this is not important as long as the
|
||||
// browser doesn't /remove/ surrounding quotes (as IE does
|
||||
// for HTML).
|
||||
//
|
||||
// With these results in hand, we conclude that there are
|
||||
// various levels of safety:
|
||||
// - Paranoid: alphanumeric, spaces and dashes(?)
|
||||
// - International: Paranoid + non-ASCII Unicode
|
||||
// - Edgy: Everything except quotes, backslashes
|
||||
// - NoJS: Standards compliance, e.g. sod IE. Note that
|
||||
// with some judicious character escaping (since certain
|
||||
// types of escaping doesn't work) this is theoretically
|
||||
// OK as long as innerHTML/cssText is not called.
|
||||
// We believe that international is a reasonable default
|
||||
// (that we will implement now), and once we do more
|
||||
// extensive research, we may feel comfortable with dropping
|
||||
// it down to edgy.
|
||||
|
||||
// Edgy: alphanumeric, spaces, dashes, underscores and Unicode. Use of
|
||||
// str(c)spn assumes that the string was already well formed
|
||||
// Unicode (which of course it is).
|
||||
if (strspn($font, $this->mask) !== strlen($font)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Historical:
|
||||
// In the absence of innerHTML/cssText, these ugly
|
||||
// transforms don't pose a security risk (as \\ and \"
|
||||
// might--these escapes are not supported by most browsers).
|
||||
// We could try to be clever and use single-quote wrapping
|
||||
// when there is a double quote present, but I have choosen
|
||||
// not to implement that. (NOTE: you can reduce the amount
|
||||
// of escapes by one depending on what quoting style you use)
|
||||
// $font = str_replace('\\', '\\5C ', $font);
|
||||
// $font = str_replace('"', '\\22 ', $font);
|
||||
// $font = str_replace("'", '\\27 ', $font);
|
||||
|
||||
// font possibly with spaces, requires quoting
|
||||
$final .= "'$font', ";
|
||||
}
|
||||
$final = rtrim($final, ', ');
|
||||
if ($final === '') return false;
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return $final;
|
||||
}
|
||||
|
||||
|
32
library/HTMLPurifier/AttrDef/CSS/Ident.php
Normal file
32
library/HTMLPurifier/AttrDef/CSS/Ident.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Validates based on {ident} CSS grammar production
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
|
||||
// early abort: '' and '0' (strings that convert to false) are invalid
|
||||
if (!$string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
|
||||
if (!preg_match($pattern, $string)) {
|
||||
return false;
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
@@ -5,20 +5,34 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
|
||||
{
|
||||
public $def, $allow;
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
public $def;
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
public $allow;
|
||||
|
||||
/**
|
||||
* @param $def Definition to wrap
|
||||
* @param $allow Whether or not to allow !important
|
||||
* @param HTMLPurifier_AttrDef $def Definition to wrap
|
||||
* @param bool $allow Whether or not to allow !important
|
||||
*/
|
||||
public function __construct($def, $allow = false) {
|
||||
public function __construct($def, $allow = false)
|
||||
{
|
||||
$this->def = $def;
|
||||
$this->allow = $allow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intercepts and removes !important if necessary
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context) {
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// test for ! and important tokens
|
||||
$string = trim($string);
|
||||
$is_important = false;
|
||||
@@ -32,7 +46,9 @@ class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
|
||||
}
|
||||
}
|
||||
$string = $this->def->validate($string, $config, $context);
|
||||
if ($this->allow && $is_important) $string .= ' !important';
|
||||
if ($this->allow && $is_important) {
|
||||
$string .= ' !important';
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
@@ -6,42 +6,72 @@
|
||||
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
protected $min, $max;
|
||||
/**
|
||||
* @type HTMLPurifier_Length|string
|
||||
*/
|
||||
protected $min;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Length $max Minimum length, or null for no bound. String is also acceptable.
|
||||
* @param HTMLPurifier_Length $max Maximum length, or null for no bound. String is also acceptable.
|
||||
* @type HTMLPurifier_Length|string
|
||||
*/
|
||||
public function __construct($min = null, $max = null) {
|
||||
protected $max;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_Length|string $min Minimum length, or null for no bound. String is also acceptable.
|
||||
* @param HTMLPurifier_Length|string $max Maximum length, or null for no bound. String is also acceptable.
|
||||
*/
|
||||
public function __construct($min = null, $max = null)
|
||||
{
|
||||
$this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
|
||||
$this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
|
||||
// Optimizations
|
||||
if ($string === '') return false;
|
||||
if ($string === '0') return '0';
|
||||
if (strlen($string) === 1) return false;
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
if ($string === '0') {
|
||||
return '0';
|
||||
}
|
||||
if (strlen($string) === 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$length = HTMLPurifier_Length::make($string);
|
||||
if (!$length->isValid()) return false;
|
||||
if (!$length->isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($this->min) {
|
||||
$c = $length->compareTo($this->min);
|
||||
if ($c === false) return false;
|
||||
if ($c < 0) return false;
|
||||
if ($c === false) {
|
||||
return false;
|
||||
}
|
||||
if ($c < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($this->max) {
|
||||
$c = $length->compareTo($this->max);
|
||||
if ($c === false) return false;
|
||||
if ($c > 0) return false;
|
||||
if ($c === false) {
|
||||
return false;
|
||||
}
|
||||
if ($c > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $length->toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -8,46 +8,72 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Local copy of component validators.
|
||||
* Local copy of validators.
|
||||
* @type HTMLPurifier_AttrDef[]
|
||||
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
|
||||
*/
|
||||
protected $info;
|
||||
|
||||
public function __construct($config) {
|
||||
/**
|
||||
* @param HTMLPurifier_Config $config
|
||||
*/
|
||||
public function __construct($config)
|
||||
{
|
||||
$def = $config->getCSSDefinition();
|
||||
$this->info['list-style-type'] = $def->info['list-style-type'];
|
||||
$this->info['list-style-type'] = $def->info['list-style-type'];
|
||||
$this->info['list-style-position'] = $def->info['list-style-position'];
|
||||
$this->info['list-style-image'] = $def->info['list-style-image'];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// regular pre-processing
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') return false;
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// assumes URI doesn't have spaces in it
|
||||
$bits = explode(' ', strtolower($string)); // bits to process
|
||||
|
||||
$caught = array();
|
||||
$caught['type'] = false;
|
||||
$caught['type'] = false;
|
||||
$caught['position'] = false;
|
||||
$caught['image'] = false;
|
||||
$caught['image'] = false;
|
||||
|
||||
$i = 0; // number of catches
|
||||
$none = false;
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
if ($i >= 3) return; // optimization bit
|
||||
if ($bit === '') continue;
|
||||
if ($i >= 3) {
|
||||
return;
|
||||
} // optimization bit
|
||||
if ($bit === '') {
|
||||
continue;
|
||||
}
|
||||
foreach ($caught as $key => $status) {
|
||||
if ($status !== false) continue;
|
||||
if ($status !== false) {
|
||||
continue;
|
||||
}
|
||||
$r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
|
||||
if ($r === false) continue;
|
||||
if ($r === false) {
|
||||
continue;
|
||||
}
|
||||
if ($r === 'none') {
|
||||
if ($none) continue;
|
||||
else $none = true;
|
||||
if ($key == 'image') continue;
|
||||
if ($none) {
|
||||
continue;
|
||||
} else {
|
||||
$none = true;
|
||||
}
|
||||
if ($key == 'image') {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$caught[$key] = $r;
|
||||
$i++;
|
||||
@@ -55,24 +81,32 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
|
||||
}
|
||||
}
|
||||
|
||||
if (!$i) return false;
|
||||
if (!$i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
|
||||
// construct type
|
||||
if ($caught['type']) $ret[] = $caught['type'];
|
||||
if ($caught['type']) {
|
||||
$ret[] = $caught['type'];
|
||||
}
|
||||
|
||||
// construct image
|
||||
if ($caught['image']) $ret[] = $caught['image'];
|
||||
if ($caught['image']) {
|
||||
$ret[] = $caught['image'];
|
||||
}
|
||||
|
||||
// construct position
|
||||
if ($caught['position']) $ret[] = $caught['position'];
|
||||
if ($caught['position']) {
|
||||
$ret[] = $caught['position'];
|
||||
}
|
||||
|
||||
if (empty($ret)) return false;
|
||||
if (empty($ret)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $ret);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -13,9 +13,9 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance of component definition to defer validation to.
|
||||
* @type HTMLPurifier_AttrDef
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $single;
|
||||
@@ -27,32 +27,45 @@ class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
|
||||
public $max;
|
||||
|
||||
/**
|
||||
* @param $single HTMLPurifier_AttrDef to multiply
|
||||
* @param $max Max number of values allowed (usually four)
|
||||
* @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply
|
||||
* @param int $max Max number of values allowed (usually four)
|
||||
*/
|
||||
public function __construct($single, $max = 4) {
|
||||
public function __construct($single, $max = 4)
|
||||
{
|
||||
$this->single = $single;
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
$string = $this->parseCDATA($string);
|
||||
if ($string === '') return false;
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->mungeRgb($this->parseCDATA($string));
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
$parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
|
||||
$length = count($parts);
|
||||
$final = '';
|
||||
for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
|
||||
if (ctype_space($parts[$i])) continue;
|
||||
if (ctype_space($parts[$i])) {
|
||||
continue;
|
||||
}
|
||||
$result = $this->single->validate($parts[$i], $config, $context);
|
||||
if ($result !== false) {
|
||||
$final .= $result . ' ';
|
||||
$num++;
|
||||
}
|
||||
}
|
||||
if ($final === '') return false;
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return rtrim($final);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -7,32 +7,44 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not only positive values allowed.
|
||||
* Indicates whether or not only positive values are allowed.
|
||||
* @type bool
|
||||
*/
|
||||
protected $non_negative = false;
|
||||
|
||||
/**
|
||||
* @param $non_negative Bool indicating whether negatives are forbidden
|
||||
* @param bool $non_negative indicates whether negatives are forbidden
|
||||
*/
|
||||
public function __construct($non_negative = false) {
|
||||
public function __construct($non_negative = false)
|
||||
{
|
||||
$this->non_negative = $non_negative;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return string|bool
|
||||
* @warning Some contexts do not pass $config, $context. These
|
||||
* variables should not be used without checking HTMLPurifier_Length
|
||||
*/
|
||||
public function validate($number, $config, $context) {
|
||||
|
||||
public function validate($number, $config, $context)
|
||||
{
|
||||
$number = $this->parseCDATA($number);
|
||||
|
||||
if ($number === '') return false;
|
||||
if ($number === '0') return '0';
|
||||
if ($number === '') {
|
||||
return false;
|
||||
}
|
||||
if ($number === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$sign = '';
|
||||
switch ($number[0]) {
|
||||
case '-':
|
||||
if ($this->non_negative) return false;
|
||||
if ($this->non_negative) {
|
||||
return false;
|
||||
}
|
||||
$sign = '-';
|
||||
case '+':
|
||||
$number = substr($number, 1);
|
||||
@@ -44,14 +56,20 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
}
|
||||
|
||||
// Period is the only non-numeric character allowed
|
||||
if (strpos($number, '.') === false) return false;
|
||||
if (strpos($number, '.') === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
list($left, $right) = explode('.', $number, 2);
|
||||
|
||||
if ($left === '' && $right === '') return false;
|
||||
if ($left !== '' && !ctype_digit($left)) return false;
|
||||
if ($left === '' && $right === '') {
|
||||
return false;
|
||||
}
|
||||
if ($left !== '' && !ctype_digit($left)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$left = ltrim($left, '0');
|
||||
$left = ltrim($left, '0');
|
||||
$right = rtrim($right, '0');
|
||||
|
||||
if ($right === '') {
|
||||
@@ -59,11 +77,8 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
|
||||
} elseif (!ctype_digit($right)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $sign . $left . '.' . $right;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -7,34 +7,48 @@ class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_CSS_Number to defer number validation
|
||||
* Instance to defer number validation to.
|
||||
* @type HTMLPurifier_AttrDef_CSS_Number
|
||||
*/
|
||||
protected $number_def;
|
||||
|
||||
/**
|
||||
* @param Bool indicating whether to forbid negative values
|
||||
* @param bool $non_negative Whether to forbid negative values
|
||||
*/
|
||||
public function __construct($non_negative = false) {
|
||||
public function __construct($non_negative = false)
|
||||
{
|
||||
$this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = $this->parseCDATA($string);
|
||||
|
||||
if ($string === '') return false;
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
$length = strlen($string);
|
||||
if ($length === 1) return false;
|
||||
if ($string[$length - 1] !== '%') return false;
|
||||
if ($length === 1) {
|
||||
return false;
|
||||
}
|
||||
if ($string[$length - 1] !== '%') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$number = substr($string, 0, $length - 1);
|
||||
$number = $this->number_def->validate($number, $config, $context);
|
||||
|
||||
if ($number === false) return false;
|
||||
if ($number === false) {
|
||||
return false;
|
||||
}
|
||||
return "$number%";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -8,8 +8,14 @@
|
||||
class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $allowed_values = array(
|
||||
'line-through' => true,
|
||||
'overline' => true,
|
||||
@@ -18,7 +24,9 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||
|
||||
$string = strtolower($this->parseCDATA($string));
|
||||
|
||||
if ($string === 'none') return $string;
|
||||
if ($string === 'none') {
|
||||
return $string;
|
||||
}
|
||||
|
||||
$parts = explode(' ', $string);
|
||||
$final = '';
|
||||
@@ -28,11 +36,11 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
|
||||
}
|
||||
}
|
||||
$final = rtrim($final);
|
||||
if ($final === '') return false;
|
||||
if ($final === '') {
|
||||
return false;
|
||||
}
|
||||
return $final;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -12,45 +12,66 @@
|
||||
class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(true); // always embedded
|
||||
}
|
||||
|
||||
public function validate($uri_string, $config, $context) {
|
||||
/**
|
||||
* @param string $uri_string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($uri_string, $config, $context)
|
||||
{
|
||||
// parse the URI out of the string and then pass it onto
|
||||
// the parent object
|
||||
|
||||
$uri_string = $this->parseCDATA($uri_string);
|
||||
if (strpos($uri_string, 'url(') !== 0) return false;
|
||||
if (strpos($uri_string, 'url(') !== 0) {
|
||||
return false;
|
||||
}
|
||||
$uri_string = substr($uri_string, 4);
|
||||
if (strlen($uri_string) == 0) {
|
||||
return false;
|
||||
}
|
||||
$new_length = strlen($uri_string) - 1;
|
||||
if ($uri_string[$new_length] != ')') return false;
|
||||
if ($uri_string[$new_length] != ')') {
|
||||
return false;
|
||||
}
|
||||
$uri = trim(substr($uri_string, 0, $new_length));
|
||||
|
||||
if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
|
||||
$quote = $uri[0];
|
||||
$new_length = strlen($uri) - 1;
|
||||
if ($uri[$new_length] !== $quote) return false;
|
||||
if ($uri[$new_length] !== $quote) {
|
||||
return false;
|
||||
}
|
||||
$uri = substr($uri, 1, $new_length - 1);
|
||||
}
|
||||
|
||||
$keys = array( '(', ')', ',', ' ', '"', "'");
|
||||
$values = array('\\(', '\\)', '\\,', '\\ ', '\\"', "\\'");
|
||||
$uri = str_replace($values, $keys, $uri);
|
||||
$uri = $this->expandCSSEscape($uri);
|
||||
|
||||
$result = parent::validate($uri, $config, $context);
|
||||
|
||||
if ($result === false) return false;
|
||||
if ($result === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// escape necessary characters according to CSS spec
|
||||
// except for the comma, none of these should appear in the
|
||||
// URI at all
|
||||
$result = str_replace($keys, $values, $result);
|
||||
// extra sanity check; should have been done by URI
|
||||
$result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
|
||||
|
||||
return "url($result)";
|
||||
// suspicious characters are ()'; we're going to percent encode
|
||||
// them for safety.
|
||||
$result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result);
|
||||
|
||||
// there's an extra bug where ampersands lose their escaping on
|
||||
// an innerHTML cycle, so a very unlucky query parameter could
|
||||
// then change the meaning of the URL. Unfortunately, there's
|
||||
// not much we can do about that...
|
||||
return "url(\"$result\")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
44
library/HTMLPurifier/AttrDef/Clone.php
Normal file
44
library/HTMLPurifier/AttrDef/Clone.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Dummy AttrDef that mimics another AttrDef, BUT it generates clones
|
||||
* with make.
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
|
||||
{
|
||||
/**
|
||||
* What we're cloning.
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
protected $clone;
|
||||
|
||||
/**
|
||||
* @param HTMLPurifier_AttrDef $clone
|
||||
*/
|
||||
public function __construct($clone)
|
||||
{
|
||||
$this->clone = $clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $v
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($v, $config, $context)
|
||||
{
|
||||
return $this->clone->validate($v, $config, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return HTMLPurifier_AttrDef
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
return clone $this->clone;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
@@ -12,9 +12,10 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* Lookup table of valid values.
|
||||
* @type array
|
||||
* @todo Make protected
|
||||
*/
|
||||
public $valid_values = array();
|
||||
public $valid_values = array();
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not enumeration is case sensitive.
|
||||
@@ -23,17 +24,23 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
protected $case_sensitive = false; // values according to W3C spec
|
||||
|
||||
/**
|
||||
* @param $valid_values List of valid values
|
||||
* @param $case_sensitive Bool indicating whether or not case sensitive
|
||||
* @param array $valid_values List of valid values
|
||||
* @param bool $case_sensitive Whether or not case sensitive
|
||||
*/
|
||||
public function __construct(
|
||||
$valid_values = array(), $case_sensitive = false
|
||||
) {
|
||||
public function __construct($valid_values = array(), $case_sensitive = false)
|
||||
{
|
||||
$this->valid_values = array_flip($valid_values);
|
||||
$this->case_sensitive = $case_sensitive;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
if (!$this->case_sensitive) {
|
||||
// we may want to do full case-insensitive libraries
|
||||
@@ -45,11 +52,13 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $string In form of comma-delimited list of case-insensitive
|
||||
* @param string $string In form of comma-delimited list of case-insensitive
|
||||
* valid values. Example: "foo,bar,baz". Prepend "s:" to make
|
||||
* case sensitive
|
||||
* @return HTMLPurifier_AttrDef_Enum
|
||||
*/
|
||||
public function make($string) {
|
||||
public function make($string)
|
||||
{
|
||||
if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
|
||||
$string = substr($string, 2);
|
||||
$sensitive = true;
|
||||
@@ -59,7 +68,6 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
|
||||
$values = explode(',', $string);
|
||||
return new HTMLPurifier_AttrDef_Enum($values, $sensitive);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,23 +6,43 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
public $minimized = true;
|
||||
|
||||
public function __construct($name = false) {$this->name = $name;}
|
||||
/**
|
||||
* @param bool $name
|
||||
*/
|
||||
public function __construct($name = false)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
if (empty($string)) return false;
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $string Name of attribute
|
||||
* @param string $string Name of attribute
|
||||
* @return HTMLPurifier_AttrDef_HTML_Bool
|
||||
*/
|
||||
public function make($string) {
|
||||
public function make($string)
|
||||
{
|
||||
return new HTMLPurifier_AttrDef_HTML_Bool($string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -5,7 +5,14 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
|
||||
{
|
||||
protected function split($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function split($string, $config, $context)
|
||||
{
|
||||
// really, this twiddle should be lazy loaded
|
||||
$name = $config->getDefinition('HTML')->doctype->name;
|
||||
if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
|
||||
@@ -14,13 +21,20 @@ class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
|
||||
return preg_split('/\s+/', $string);
|
||||
}
|
||||
}
|
||||
protected function filter($tokens, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param array $tokens
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
protected function filter($tokens, $config, $context)
|
||||
{
|
||||
$allowed = $config->get('Attr.AllowedClasses');
|
||||
$forbidden = $config->get('Attr.ForbiddenClasses');
|
||||
$ret = array();
|
||||
foreach ($tokens as $token) {
|
||||
if (
|
||||
($allowed === null || isset($allowed[$token])) &&
|
||||
if (($allowed === null || isset($allowed[$token])) &&
|
||||
!isset($forbidden[$token]) &&
|
||||
// We need this O(n) check because of PHP's array
|
||||
// implementation that casts -0 to 0.
|
||||
|
@@ -6,27 +6,46 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
static $colors = null;
|
||||
if ($colors === null) $colors = $config->get('Core.ColorKeywords');
|
||||
if ($colors === null) {
|
||||
$colors = $config->get('Core.ColorKeywords');
|
||||
}
|
||||
|
||||
$string = trim($string);
|
||||
|
||||
if (empty($string)) return false;
|
||||
if (isset($colors[$string])) return $colors[$string];
|
||||
if ($string[0] === '#') $hex = substr($string, 1);
|
||||
else $hex = $string;
|
||||
if (empty($string)) {
|
||||
return false;
|
||||
}
|
||||
$lower = strtolower($string);
|
||||
if (isset($colors[$lower])) {
|
||||
return $colors[$lower];
|
||||
}
|
||||
if ($string[0] === '#') {
|
||||
$hex = substr($string, 1);
|
||||
} else {
|
||||
$hex = $string;
|
||||
}
|
||||
|
||||
$length = strlen($hex);
|
||||
if ($length !== 3 && $length !== 6) return false;
|
||||
if (!ctype_xdigit($hex)) return false;
|
||||
if ($length === 3) $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
|
||||
|
||||
if ($length !== 3 && $length !== 6) {
|
||||
return false;
|
||||
}
|
||||
if (!ctype_xdigit($hex)) {
|
||||
return false;
|
||||
}
|
||||
if ($length === 3) {
|
||||
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
|
||||
}
|
||||
return "#$hex";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,16 +6,33 @@
|
||||
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
|
||||
{
|
||||
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
public $valid_values = false; // uninitialized value
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
protected $case_sensitive = false;
|
||||
|
||||
public function __construct() {}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
if ($this->valid_values === false) $this->valid_values = $config->get('Attr.AllowedFrameTargets');
|
||||
return parent::validate($string, $config, $context);
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
if ($this->valid_values === false) {
|
||||
$this->valid_values = $config->get('Attr.AllowedFrameTargets');
|
||||
}
|
||||
return parent::validate($string, $config, $context);
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -12,43 +12,86 @@
|
||||
class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
// ref functionality disabled, since we also have to verify
|
||||
// whether or not the ID it refers to exists
|
||||
// selector is NOT a valid thing to use for IDREFs, because IDREFs
|
||||
// *must* target IDs that exist, whereas selector #ids do not.
|
||||
|
||||
public function validate($id, $config, $context) {
|
||||
/**
|
||||
* Determines whether or not we're validating an ID in a CSS
|
||||
* selector context.
|
||||
* @type bool
|
||||
*/
|
||||
protected $selector;
|
||||
|
||||
if (!$config->get('Attr.EnableID')) return false;
|
||||
/**
|
||||
* @param bool $selector
|
||||
*/
|
||||
public function __construct($selector = false)
|
||||
{
|
||||
$this->selector = $selector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($id, $config, $context)
|
||||
{
|
||||
if (!$this->selector && !$config->get('Attr.EnableID')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$id = trim($id); // trim it first
|
||||
|
||||
if ($id === '') return false;
|
||||
if ($id === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prefix = $config->get('Attr.IDPrefix');
|
||||
if ($prefix !== '') {
|
||||
$prefix .= $config->get('Attr.IDPrefixLocal');
|
||||
// prevent re-appending the prefix
|
||||
if (strpos($id, $prefix) !== 0) $id = $prefix . $id;
|
||||
if (strpos($id, $prefix) !== 0) {
|
||||
$id = $prefix . $id;
|
||||
}
|
||||
} elseif ($config->get('Attr.IDPrefixLocal') !== '') {
|
||||
trigger_error('%Attr.IDPrefixLocal cannot be used unless '.
|
||||
'%Attr.IDPrefix is set', E_USER_WARNING);
|
||||
trigger_error(
|
||||
'%Attr.IDPrefixLocal cannot be used unless ' .
|
||||
'%Attr.IDPrefix is set',
|
||||
E_USER_WARNING
|
||||
);
|
||||
}
|
||||
|
||||
//if (!$this->ref) {
|
||||
if (!$this->selector) {
|
||||
$id_accumulator =& $context->get('IDAccumulator');
|
||||
if (isset($id_accumulator->ids[$id])) return false;
|
||||
//}
|
||||
if (isset($id_accumulator->ids[$id])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// we purposely avoid using regex, hopefully this is faster
|
||||
|
||||
if (ctype_alpha($id)) {
|
||||
$result = true;
|
||||
if ($config->get('Attr.ID.HTML5') === true) {
|
||||
if (preg_match('/[\t\n\x0b\x0c ]/', $id)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!ctype_alpha(@$id[0])) return false;
|
||||
$trim = trim( // primitive style of regexps, I suppose
|
||||
$id,
|
||||
'A..Za..z0..9:-._'
|
||||
);
|
||||
$result = ($trim === '');
|
||||
if (ctype_alpha($id)) {
|
||||
// OK
|
||||
} else {
|
||||
if (!ctype_alpha(@$id[0])) {
|
||||
return false;
|
||||
}
|
||||
// primitive style of regexps, I suppose
|
||||
$trim = trim(
|
||||
$id,
|
||||
'A..Za..z0..9:-._'
|
||||
);
|
||||
if ($trim !== '') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$regexp = $config->get('Attr.IDBlacklistRegexp');
|
||||
@@ -56,15 +99,15 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
|
||||
return false;
|
||||
}
|
||||
|
||||
if (/*!$this->ref && */$result) $id_accumulator->add($id);
|
||||
if (!$this->selector) {
|
||||
$id_accumulator->add($id);
|
||||
}
|
||||
|
||||
// if no change was made to the ID, return the result
|
||||
// else, return the new id if stripping whitespace made it
|
||||
// valid, or return false.
|
||||
return $result ? $id : false;
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -10,32 +10,47 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
if ($string === '') return false;
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parent_result = parent::validate($string, $config, $context);
|
||||
if ($parent_result !== false) return $parent_result;
|
||||
if ($parent_result !== false) {
|
||||
return $parent_result;
|
||||
}
|
||||
|
||||
$length = strlen($string);
|
||||
$last_char = $string[$length - 1];
|
||||
|
||||
if ($last_char !== '%') return false;
|
||||
if ($last_char !== '%') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$points = substr($string, 0, $length - 1);
|
||||
|
||||
if (!is_numeric($points)) return false;
|
||||
if (!is_numeric($points)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$points = (int) $points;
|
||||
|
||||
if ($points < 0) return '0%';
|
||||
if ($points > 100) return '100%';
|
||||
|
||||
return ((string) $points) . '%';
|
||||
$points = (int)$points;
|
||||
|
||||
if ($points < 0) {
|
||||
return '0%';
|
||||
}
|
||||
if ($points > 100) {
|
||||
return '100%';
|
||||
}
|
||||
return ((string)$points) . '%';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -9,26 +9,44 @@
|
||||
class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/** Name config attribute to pull. */
|
||||
/**
|
||||
* Name config attribute to pull.
|
||||
* @type string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
public function __construct($name) {
|
||||
/**
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($name)
|
||||
{
|
||||
$configLookup = array(
|
||||
'rel' => 'AllowedRel',
|
||||
'rev' => 'AllowedRev'
|
||||
);
|
||||
if (!isset($configLookup[$name])) {
|
||||
trigger_error('Unrecognized attribute name for link '.
|
||||
'relationship.', E_USER_ERROR);
|
||||
trigger_error(
|
||||
'Unrecognized attribute name for link ' .
|
||||
'relationship.',
|
||||
E_USER_ERROR
|
||||
);
|
||||
return;
|
||||
}
|
||||
$this->name = $configLookup[$name];
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$allowed = $config->get('Attr.' . $this->name);
|
||||
if (empty($allowed)) return false;
|
||||
if (empty($allowed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$string = $this->parseCDATA($string);
|
||||
$parts = explode(' ', $string);
|
||||
@@ -37,17 +55,18 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
|
||||
$ret_lookup = array();
|
||||
foreach ($parts as $part) {
|
||||
$part = strtolower(trim($part));
|
||||
if (!isset($allowed[$part])) continue;
|
||||
if (!isset($allowed[$part])) {
|
||||
continue;
|
||||
}
|
||||
$ret_lookup[$part] = true;
|
||||
}
|
||||
|
||||
if (empty($ret_lookup)) return false;
|
||||
if (empty($ret_lookup)) {
|
||||
return false;
|
||||
}
|
||||
$string = implode(' ', array_keys($ret_lookup));
|
||||
|
||||
return $string;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -9,33 +9,52 @@
|
||||
class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
if ($string === '') return false;
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parent_result = parent::validate($string, $config, $context);
|
||||
if ($parent_result !== false) return $parent_result;
|
||||
if ($parent_result !== false) {
|
||||
return $parent_result;
|
||||
}
|
||||
|
||||
$length = strlen($string);
|
||||
$last_char = $string[$length - 1];
|
||||
|
||||
if ($last_char !== '*') return false;
|
||||
if ($last_char !== '*') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$int = substr($string, 0, $length - 1);
|
||||
|
||||
if ($int == '') return '*';
|
||||
if (!is_numeric($int)) return false;
|
||||
|
||||
$int = (int) $int;
|
||||
|
||||
if ($int < 0) return false;
|
||||
if ($int == 0) return '0';
|
||||
if ($int == 1) return '*';
|
||||
return ((string) $int) . '*';
|
||||
if ($int == '') {
|
||||
return '*';
|
||||
}
|
||||
if (!is_numeric($int)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$int = (int)$int;
|
||||
if ($int < 0) {
|
||||
return false;
|
||||
}
|
||||
if ($int == 0) {
|
||||
return '0';
|
||||
}
|
||||
if ($int == 1) {
|
||||
return '*';
|
||||
}
|
||||
return ((string)$int) . '*';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,24 +6,38 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
|
||||
// early abort: '' and '0' (strings that convert to false) are invalid
|
||||
if (!$string) return false;
|
||||
if (!$string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$tokens = $this->split($string, $config, $context);
|
||||
$tokens = $this->filter($tokens, $config, $context);
|
||||
if (empty($tokens)) return false;
|
||||
if (empty($tokens)) {
|
||||
return false;
|
||||
}
|
||||
return implode(' ', $tokens);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits a space separated list of tokens into its constituent parts.
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
protected function split($string, $config, $context) {
|
||||
protected function split($string, $config, $context)
|
||||
{
|
||||
// OPTIMIZABLE!
|
||||
// do the preg_match, capture all subpatterns for reformulation
|
||||
|
||||
@@ -31,9 +45,9 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
||||
// escaping because I don't know how to do that with regexps
|
||||
// and plus it would complicate optimization efforts (you never
|
||||
// see that anyway).
|
||||
$pattern = '/(?:(?<=\s)|\A)'. // look behind for space or string start
|
||||
'((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)'.
|
||||
'(?:(?=\s)|\z)/'; // look ahead for space or string end
|
||||
$pattern = '/(?:(?<=\s)|\A)' . // look behind for space or string start
|
||||
'((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)' .
|
||||
'(?:(?=\s)|\z)/'; // look ahead for space or string end
|
||||
preg_match_all($pattern, $string, $matches);
|
||||
return $matches[1];
|
||||
}
|
||||
@@ -42,11 +56,15 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
||||
* Template method for removing certain tokens based on arbitrary criteria.
|
||||
* @note If we wanted to be really functional, we'd do an array_filter
|
||||
* with a callback. But... we're not.
|
||||
* @param array $tokens
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
protected function filter($tokens, $config, $context) {
|
||||
protected function filter($tokens, $config, $context)
|
||||
{
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,43 +6,71 @@
|
||||
class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type int
|
||||
*/
|
||||
protected $max;
|
||||
|
||||
public function __construct($max = null) {
|
||||
/**
|
||||
* @param int $max
|
||||
*/
|
||||
public function __construct($max = null)
|
||||
{
|
||||
$this->max = $max;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
if ($string === '0') return $string;
|
||||
if ($string === '') return false;
|
||||
if ($string === '0') {
|
||||
return $string;
|
||||
}
|
||||
if ($string === '') {
|
||||
return false;
|
||||
}
|
||||
$length = strlen($string);
|
||||
if (substr($string, $length - 2) == 'px') {
|
||||
$string = substr($string, 0, $length - 2);
|
||||
}
|
||||
if (!is_numeric($string)) return false;
|
||||
$int = (int) $string;
|
||||
if (!is_numeric($string)) {
|
||||
return false;
|
||||
}
|
||||
$int = (int)$string;
|
||||
|
||||
if ($int < 0) return '0';
|
||||
if ($int < 0) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// upper-bound value, extremely high values can
|
||||
// crash operating systems, see <http://ha.ckers.org/imagecrash.html>
|
||||
// WARNING, above link WILL crash you if you're using Windows
|
||||
|
||||
if ($this->max !== null && $int > $this->max) return (string) $this->max;
|
||||
|
||||
return (string) $int;
|
||||
|
||||
if ($this->max !== null && $int > $this->max) {
|
||||
return (string)$this->max;
|
||||
}
|
||||
return (string)$int;
|
||||
}
|
||||
|
||||
public function make($string) {
|
||||
if ($string === '') $max = null;
|
||||
else $max = (int) $string;
|
||||
/**
|
||||
* @param string $string
|
||||
* @return HTMLPurifier_AttrDef
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
if ($string === '') {
|
||||
$max = null;
|
||||
} else {
|
||||
$max = (int)$string;
|
||||
}
|
||||
$class = get_class($this);
|
||||
return new $class($max);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -11,17 +11,20 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not negative values are allowed
|
||||
* Whether or not negative values are allowed.
|
||||
* @type bool
|
||||
*/
|
||||
protected $negative = true;
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not zero is allowed
|
||||
* Whether or not zero is allowed.
|
||||
* @type bool
|
||||
*/
|
||||
protected $zero = true;
|
||||
|
||||
/**
|
||||
* Bool indicating whether or not positive values are allowed
|
||||
* Whether or not positive values are allowed.
|
||||
* @type bool
|
||||
*/
|
||||
protected $positive = true;
|
||||
|
||||
@@ -30,44 +33,59 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
|
||||
* @param $zero Bool indicating whether or not zero is allowed
|
||||
* @param $positive Bool indicating whether or not positive values are allowed
|
||||
*/
|
||||
public function __construct(
|
||||
$negative = true, $zero = true, $positive = true
|
||||
) {
|
||||
public function __construct($negative = true, $zero = true, $positive = true)
|
||||
{
|
||||
$this->negative = $negative;
|
||||
$this->zero = $zero;
|
||||
$this->zero = $zero;
|
||||
$this->positive = $positive;
|
||||
}
|
||||
|
||||
public function validate($integer, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $integer
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($integer, $config, $context)
|
||||
{
|
||||
$integer = $this->parseCDATA($integer);
|
||||
if ($integer === '') return false;
|
||||
if ($integer === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we could possibly simply typecast it to integer, but there are
|
||||
// certain fringe cases that must not return an integer.
|
||||
|
||||
// clip leading sign
|
||||
if ( $this->negative && $integer[0] === '-' ) {
|
||||
if ($this->negative && $integer[0] === '-') {
|
||||
$digits = substr($integer, 1);
|
||||
if ($digits === '0') $integer = '0'; // rm minus sign for zero
|
||||
} elseif( $this->positive && $integer[0] === '+' ) {
|
||||
if ($digits === '0') {
|
||||
$integer = '0';
|
||||
} // rm minus sign for zero
|
||||
} elseif ($this->positive && $integer[0] === '+') {
|
||||
$digits = $integer = substr($integer, 1); // rm unnecessary plus
|
||||
} else {
|
||||
$digits = $integer;
|
||||
}
|
||||
|
||||
// test if it's numeric
|
||||
if (!ctype_digit($digits)) return false;
|
||||
if (!ctype_digit($digits)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// perform scope tests
|
||||
if (!$this->zero && $integer == 0) return false;
|
||||
if (!$this->positive && $integer > 0) return false;
|
||||
if (!$this->negative && $integer < 0) return false;
|
||||
if (!$this->zero && $integer == 0) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->positive && $integer > 0) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->negative && $integer < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $integer;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -7,15 +7,25 @@
|
||||
class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$string = trim($string);
|
||||
if (!$string) return false;
|
||||
if (!$string) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$subtags = explode('-', $string);
|
||||
$num_subtags = count($subtags);
|
||||
|
||||
if ($num_subtags == 0) return false; // sanity check
|
||||
if ($num_subtags == 0) { // sanity check
|
||||
return false;
|
||||
}
|
||||
|
||||
// process primary subtag : $subtags[0]
|
||||
$length = strlen($subtags[0]);
|
||||
@@ -23,15 +33,15 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
if (! ($subtags[0] == 'x' || $subtags[0] == 'i') ) {
|
||||
if (!($subtags[0] == 'x' || $subtags[0] == 'i')) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
if (! ctype_alpha($subtags[0]) ) {
|
||||
if (!ctype_alpha($subtags[0])) {
|
||||
return false;
|
||||
} elseif (! ctype_lower($subtags[0]) ) {
|
||||
} elseif (!ctype_lower($subtags[0])) {
|
||||
$subtags[0] = strtolower($subtags[0]);
|
||||
}
|
||||
break;
|
||||
@@ -40,17 +50,23 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
|
||||
}
|
||||
|
||||
$new_string = $subtags[0];
|
||||
if ($num_subtags == 1) return $new_string;
|
||||
if ($num_subtags == 1) {
|
||||
return $new_string;
|
||||
}
|
||||
|
||||
// process second subtag : $subtags[1]
|
||||
$length = strlen($subtags[1]);
|
||||
if ($length == 0 || ($length == 1 && $subtags[1] != 'x') || $length > 8 || !ctype_alnum($subtags[1])) {
|
||||
return $new_string;
|
||||
}
|
||||
if (!ctype_lower($subtags[1])) $subtags[1] = strtolower($subtags[1]);
|
||||
if (!ctype_lower($subtags[1])) {
|
||||
$subtags[1] = strtolower($subtags[1]);
|
||||
}
|
||||
|
||||
$new_string .= '-' . $subtags[1];
|
||||
if ($num_subtags == 2) return $new_string;
|
||||
if ($num_subtags == 2) {
|
||||
return $new_string;
|
||||
}
|
||||
|
||||
// process all other subtags, index 2 and up
|
||||
for ($i = 2; $i < $num_subtags; $i++) {
|
||||
@@ -63,11 +79,8 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
|
||||
}
|
||||
$new_string .= '-' . $subtags[$i];
|
||||
}
|
||||
|
||||
return $new_string;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,21 +6,41 @@
|
||||
class HTMLPurifier_AttrDef_Switch
|
||||
{
|
||||
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
protected $tag;
|
||||
protected $withTag, $withoutTag;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
protected $withTag;
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef
|
||||
*/
|
||||
protected $withoutTag;
|
||||
|
||||
/**
|
||||
* @param string $tag Tag name to switch upon
|
||||
* @param HTMLPurifier_AttrDef $with_tag Call if token matches tag
|
||||
* @param HTMLPurifier_AttrDef $without_tag Call if token doesn't match, or there is no token
|
||||
*/
|
||||
public function __construct($tag, $with_tag, $without_tag) {
|
||||
public function __construct($tag, $with_tag, $without_tag)
|
||||
{
|
||||
$this->tag = $tag;
|
||||
$this->withTag = $with_tag;
|
||||
$this->withoutTag = $without_tag;
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$token = $context->get('CurrentToken', true);
|
||||
if (!$token || $token->name !== $this->tag) {
|
||||
return $this->withoutTag->validate($string, $config, $context);
|
||||
@@ -28,7 +48,6 @@ class HTMLPurifier_AttrDef_Switch
|
||||
return $this->withTag->validate($string, $config, $context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,10 +6,16 @@
|
||||
class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
return $this->parseCDATA($string);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -7,31 +7,54 @@
|
||||
class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_URIParser
|
||||
*/
|
||||
protected $parser;
|
||||
|
||||
/**
|
||||
* @type bool
|
||||
*/
|
||||
protected $embedsResource;
|
||||
|
||||
/**
|
||||
* @param $embeds_resource_resource Does the URI here result in an extra HTTP request?
|
||||
* @param bool $embeds_resource Does the URI here result in an extra HTTP request?
|
||||
*/
|
||||
public function __construct($embeds_resource = false) {
|
||||
public function __construct($embeds_resource = false)
|
||||
{
|
||||
$this->parser = new HTMLPurifier_URIParser();
|
||||
$this->embedsResource = (bool) $embeds_resource;
|
||||
$this->embedsResource = (bool)$embeds_resource;
|
||||
}
|
||||
|
||||
public function make($string) {
|
||||
$embeds = (bool) $string;
|
||||
/**
|
||||
* @param string $string
|
||||
* @return HTMLPurifier_AttrDef_URI
|
||||
*/
|
||||
public function make($string)
|
||||
{
|
||||
$embeds = ($string === 'embedded');
|
||||
return new HTMLPurifier_AttrDef_URI($embeds);
|
||||
}
|
||||
|
||||
public function validate($uri, $config, $context) {
|
||||
|
||||
if ($config->get('URI.Disable')) return false;
|
||||
/**
|
||||
* @param string $uri
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($uri, $config, $context)
|
||||
{
|
||||
if ($config->get('URI.Disable')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$uri = $this->parseCDATA($uri);
|
||||
|
||||
// parse the URI
|
||||
$uri = $this->parser->parse($uri);
|
||||
if ($uri === false) return false;
|
||||
if ($uri === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// add embedded flag to context for validators
|
||||
$context->register('EmbeddedURI', $this->embedsResource);
|
||||
@@ -41,23 +64,35 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
|
||||
// generic validation
|
||||
$result = $uri->validate($config, $context);
|
||||
if (!$result) break;
|
||||
if (!$result) {
|
||||
break;
|
||||
}
|
||||
|
||||
// chained filtering
|
||||
$uri_def = $config->getDefinition('URI');
|
||||
$result = $uri_def->filter($uri, $config, $context);
|
||||
if (!$result) break;
|
||||
if (!$result) {
|
||||
break;
|
||||
}
|
||||
|
||||
// scheme-specific validation
|
||||
$scheme_obj = $uri->getSchemeObj($config, $context);
|
||||
if (!$scheme_obj) break;
|
||||
if ($this->embedsResource && !$scheme_obj->browsable) break;
|
||||
if (!$scheme_obj) {
|
||||
break;
|
||||
}
|
||||
if ($this->embedsResource && !$scheme_obj->browsable) {
|
||||
break;
|
||||
}
|
||||
$result = $scheme_obj->validate($uri, $config, $context);
|
||||
if (!$result) break;
|
||||
if (!$result) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Post chained filtering
|
||||
$result = $uri_def->postFilter($uri, $config, $context);
|
||||
if (!$result) break;
|
||||
if (!$result) {
|
||||
break;
|
||||
}
|
||||
|
||||
// survived gauntlet
|
||||
$ok = true;
|
||||
@@ -65,13 +100,12 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
|
||||
} while (false);
|
||||
|
||||
$context->destroy('EmbeddedURI');
|
||||
if (!$ok) return false;
|
||||
|
||||
if (!$ok) {
|
||||
return false;
|
||||
}
|
||||
// back to string
|
||||
return $uri->toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -5,8 +5,11 @@ abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
|
||||
|
||||
/**
|
||||
* Unpacks a mailbox into its display-name and address
|
||||
* @param string $string
|
||||
* @return mixed
|
||||
*/
|
||||
function unpack($string) {
|
||||
public function unpack($string)
|
||||
{
|
||||
// needs to be implemented
|
||||
}
|
||||
|
||||
|
@@ -7,15 +7,23 @@
|
||||
class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_URI_Email
|
||||
{
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
// no support for named mailboxes i.e. "Bob <bob@example.com>"
|
||||
// that needs more percent encoding to be done
|
||||
if ($string == '') return false;
|
||||
if ($string == '') {
|
||||
return false;
|
||||
}
|
||||
$string = trim($string);
|
||||
$result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string);
|
||||
return $result ? $string : false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -7,56 +7,132 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator
|
||||
* IPv4 sub-validator.
|
||||
* @type HTMLPurifier_AttrDef_URI_IPv4
|
||||
*/
|
||||
protected $ipv4;
|
||||
|
||||
/**
|
||||
* Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator
|
||||
* IPv6 sub-validator.
|
||||
* @type HTMLPurifier_AttrDef_URI_IPv6
|
||||
*/
|
||||
protected $ipv6;
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
$this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
|
||||
$this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
|
||||
}
|
||||
|
||||
public function validate($string, $config, $context) {
|
||||
/**
|
||||
* @param string $string
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($string, $config, $context)
|
||||
{
|
||||
$length = strlen($string);
|
||||
if ($string === '') return '';
|
||||
if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
|
||||
// empty hostname is OK; it's usually semantically equivalent:
|
||||
// the default host as defined by a URI scheme is used:
|
||||
//
|
||||
// If the URI scheme defines a default for host, then that
|
||||
// default applies when the host subcomponent is undefined
|
||||
// or when the registered name is empty (zero length).
|
||||
if ($string === '') {
|
||||
return '';
|
||||
}
|
||||
if ($length > 1 && $string[0] === '[' && $string[$length - 1] === ']') {
|
||||
//IPv6
|
||||
$ip = substr($string, 1, $length - 2);
|
||||
$valid = $this->ipv6->validate($ip, $config, $context);
|
||||
if ($valid === false) return false;
|
||||
return '['. $valid . ']';
|
||||
if ($valid === false) {
|
||||
return false;
|
||||
}
|
||||
return '[' . $valid . ']';
|
||||
}
|
||||
|
||||
// need to do checks on unusual encodings too
|
||||
$ipv4 = $this->ipv4->validate($string, $config, $context);
|
||||
if ($ipv4 !== false) return $ipv4;
|
||||
if ($ipv4 !== false) {
|
||||
return $ipv4;
|
||||
}
|
||||
|
||||
// A regular domain name.
|
||||
|
||||
// This breaks I18N domain names, but we don't have proper IRI support,
|
||||
// so force users to insert Punycode. If there's complaining we'll
|
||||
// try to fix things into an international friendly form.
|
||||
// This doesn't match I18N domain names, but we don't have proper IRI support,
|
||||
// so force users to insert Punycode.
|
||||
|
||||
// There is not a good sense in which underscores should be
|
||||
// allowed, since it's technically not! (And if you go as
|
||||
// far to allow everything as specified by the DNS spec...
|
||||
// well, that's literally everything, modulo some space limits
|
||||
// for the components and the overall name (which, by the way,
|
||||
// we are NOT checking!). So we (arbitrarily) decide this:
|
||||
// let's allow underscores wherever we would have allowed
|
||||
// hyphens, if they are enabled. This is a pretty good match
|
||||
// for browser behavior, for example, a large number of browsers
|
||||
// cannot handle foo_.example.com, but foo_bar.example.com is
|
||||
// fairly well supported.
|
||||
$underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : '';
|
||||
|
||||
// Based off of RFC 1738, but amended so that
|
||||
// as per RFC 3696, the top label need only not be all numeric.
|
||||
// The productions describing this are:
|
||||
$a = '[a-z]'; // alpha
|
||||
$an = '[a-z0-9]'; // alphanum
|
||||
$and = '[a-z0-9-]'; // alphanum | "-"
|
||||
$and = "[a-z0-9-$underscore]"; // alphanum | "-"
|
||||
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||
$domainlabel = "$an($and*$an)?";
|
||||
// toplabel = alpha | alpha *( alphanum | "-" ) alphanum
|
||||
$toplabel = "$a($and*$an)?";
|
||||
$domainlabel = "$an(?:$and*$an)?";
|
||||
// AMENDED as per RFC 3696
|
||||
// toplabel = alphanum | alphanum *( alphanum | "-" ) alphanum
|
||||
// side condition: not all numeric
|
||||
$toplabel = "$an(?:$and*$an)?";
|
||||
// hostname = *( domainlabel "." ) toplabel [ "." ]
|
||||
$match = preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string);
|
||||
if (!$match) return false;
|
||||
if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $matches)) {
|
||||
if (!ctype_digit($matches[1])) {
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
return $string;
|
||||
// PHP 5.3 and later support this functionality natively
|
||||
if (function_exists('idn_to_ascii')) {
|
||||
$string = idn_to_ascii($string);
|
||||
|
||||
// If we have Net_IDNA2 support, we can support IRIs by
|
||||
// punycoding them. (This is the most portable thing to do,
|
||||
// since otherwise we have to assume browsers support
|
||||
} elseif ($config->get('Core.EnableIDNA')) {
|
||||
$idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
|
||||
// we need to encode each period separately
|
||||
$parts = explode('.', $string);
|
||||
try {
|
||||
$new_parts = array();
|
||||
foreach ($parts as $part) {
|
||||
$encodable = false;
|
||||
for ($i = 0, $c = strlen($part); $i < $c; $i++) {
|
||||
if (ord($part[$i]) > 0x7a) {
|
||||
$encodable = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$encodable) {
|
||||
$new_parts[] = $part;
|
||||
} else {
|
||||
$new_parts[] = $idna->encode($part);
|
||||
}
|
||||
}
|
||||
$string = implode('.', $new_parts);
|
||||
} catch (Exception $e) {
|
||||
// XXX error reporting
|
||||
}
|
||||
}
|
||||
// Try again
|
||||
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
|
||||
return $string;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -8,32 +8,38 @@ class HTMLPurifier_AttrDef_URI_IPv4 extends HTMLPurifier_AttrDef
|
||||
{
|
||||
|
||||
/**
|
||||
* IPv4 regex, protected so that IPv6 can reuse it
|
||||
* IPv4 regex, protected so that IPv6 can reuse it.
|
||||
* @type string
|
||||
*/
|
||||
protected $ip4;
|
||||
|
||||
public function validate($aIP, $config, $context) {
|
||||
|
||||
if (!$this->ip4) $this->_loadRegex();
|
||||
|
||||
if (preg_match('#^' . $this->ip4 . '$#s', $aIP))
|
||||
{
|
||||
return $aIP;
|
||||
/**
|
||||
* @param string $aIP
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($aIP, $config, $context)
|
||||
{
|
||||
if (!$this->ip4) {
|
||||
$this->_loadRegex();
|
||||
}
|
||||
|
||||
if (preg_match('#^' . $this->ip4 . '$#s', $aIP)) {
|
||||
return $aIP;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy load function to prevent regex from being stuffed in
|
||||
* cache.
|
||||
*/
|
||||
protected function _loadRegex() {
|
||||
protected function _loadRegex()
|
||||
{
|
||||
$oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255
|
||||
$this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -9,91 +9,81 @@
|
||||
class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4
|
||||
{
|
||||
|
||||
public function validate($aIP, $config, $context) {
|
||||
|
||||
if (!$this->ip4) $this->_loadRegex();
|
||||
/**
|
||||
* @param string $aIP
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return bool|string
|
||||
*/
|
||||
public function validate($aIP, $config, $context)
|
||||
{
|
||||
if (!$this->ip4) {
|
||||
$this->_loadRegex();
|
||||
}
|
||||
|
||||
$original = $aIP;
|
||||
|
||||
$hex = '[0-9a-fA-F]';
|
||||
$blk = '(?:' . $hex . '{1,4})';
|
||||
$pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128
|
||||
$pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128
|
||||
|
||||
// prefix check
|
||||
if (strpos($aIP, '/') !== false)
|
||||
{
|
||||
if (preg_match('#' . $pre . '$#s', $aIP, $find))
|
||||
{
|
||||
$aIP = substr($aIP, 0, 0-strlen($find[0]));
|
||||
unset($find);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (strpos($aIP, '/') !== false) {
|
||||
if (preg_match('#' . $pre . '$#s', $aIP, $find)) {
|
||||
$aIP = substr($aIP, 0, 0 - strlen($find[0]));
|
||||
unset($find);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// IPv4-compatiblity check
|
||||
if (preg_match('#(?<=:'.')' . $this->ip4 . '$#s', $aIP, $find))
|
||||
{
|
||||
$aIP = substr($aIP, 0, 0-strlen($find[0]));
|
||||
$ip = explode('.', $find[0]);
|
||||
$ip = array_map('dechex', $ip);
|
||||
$aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
|
||||
unset($find, $ip);
|
||||
if (preg_match('#(?<=:' . ')' . $this->ip4 . '$#s', $aIP, $find)) {
|
||||
$aIP = substr($aIP, 0, 0 - strlen($find[0]));
|
||||
$ip = explode('.', $find[0]);
|
||||
$ip = array_map('dechex', $ip);
|
||||
$aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
|
||||
unset($find, $ip);
|
||||
}
|
||||
|
||||
// compression check
|
||||
$aIP = explode('::', $aIP);
|
||||
$c = count($aIP);
|
||||
if ($c > 2)
|
||||
{
|
||||
if ($c > 2) {
|
||||
return false;
|
||||
} elseif ($c == 2) {
|
||||
list($first, $second) = $aIP;
|
||||
$first = explode(':', $first);
|
||||
$second = explode(':', $second);
|
||||
|
||||
if (count($first) + count($second) > 8) {
|
||||
return false;
|
||||
}
|
||||
elseif ($c == 2)
|
||||
{
|
||||
list($first, $second) = $aIP;
|
||||
$first = explode(':', $first);
|
||||
$second = explode(':', $second);
|
||||
}
|
||||
|
||||
if (count($first) + count($second) > 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
while (count($first) < 8) {
|
||||
array_push($first, '0');
|
||||
}
|
||||
|
||||
while(count($first) < 8)
|
||||
{
|
||||
array_push($first, '0');
|
||||
}
|
||||
|
||||
array_splice($first, 8 - count($second), 8, $second);
|
||||
$aIP = $first;
|
||||
unset($first,$second);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aIP = explode(':', $aIP[0]);
|
||||
array_splice($first, 8 - count($second), 8, $second);
|
||||
$aIP = $first;
|
||||
unset($first, $second);
|
||||
} else {
|
||||
$aIP = explode(':', $aIP[0]);
|
||||
}
|
||||
$c = count($aIP);
|
||||
|
||||
if ($c != 8)
|
||||
{
|
||||
return false;
|
||||
if ($c != 8) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All the pieces should be 16-bit hex strings. Are they?
|
||||
foreach ($aIP as $piece)
|
||||
{
|
||||
if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
foreach ($aIP as $piece) {
|
||||
if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $original;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -20,37 +20,41 @@ abstract class HTMLPurifier_AttrTransform
|
||||
/**
|
||||
* Abstract: makes changes to the attributes dependent on multiple values.
|
||||
*
|
||||
* @param $attr Assoc array of attributes, usually from
|
||||
* @param array $attr Assoc array of attributes, usually from
|
||||
* HTMLPurifier_Token_Tag::$attr
|
||||
* @param $config Mandatory HTMLPurifier_Config object.
|
||||
* @param $context Mandatory HTMLPurifier_Context object
|
||||
* @returns Processed attribute array.
|
||||
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
|
||||
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object
|
||||
* @return array Processed attribute array.
|
||||
*/
|
||||
abstract public function transform($attr, $config, $context);
|
||||
|
||||
/**
|
||||
* Prepends CSS properties to the style attribute, creating the
|
||||
* attribute if it doesn't exist.
|
||||
* @param $attr Attribute array to process (passed by reference)
|
||||
* @param $css CSS to prepend
|
||||
* @param array &$attr Attribute array to process (passed by reference)
|
||||
* @param string $css CSS to prepend
|
||||
*/
|
||||
public function prependCSS(&$attr, $css) {
|
||||
public function prependCSS(&$attr, $css)
|
||||
{
|
||||
$attr['style'] = isset($attr['style']) ? $attr['style'] : '';
|
||||
$attr['style'] = $css . $attr['style'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes an attribute
|
||||
* @param $attr Attribute array to process (passed by reference)
|
||||
* @param $key Key of attribute to confiscate
|
||||
* @param array &$attr Attribute array to process (passed by reference)
|
||||
* @param mixed $key Key of attribute to confiscate
|
||||
* @return mixed
|
||||
*/
|
||||
public function confiscateAttr(&$attr, $key) {
|
||||
if (!isset($attr[$key])) return null;
|
||||
public function confiscateAttr(&$attr, $key)
|
||||
{
|
||||
if (!isset($attr[$key])) {
|
||||
return null;
|
||||
}
|
||||
$value = $attr[$key];
|
||||
unset($attr[$key]);
|
||||
return $value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -3,21 +3,26 @@
|
||||
/**
|
||||
* Pre-transform that changes proprietary background attribute to CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform {
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
|
||||
if (!isset($attr['background'])) return $attr;
|
||||
class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['background'])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
$background = $this->confiscateAttr($attr, 'background');
|
||||
// some validation should happen here
|
||||
|
||||
$this->prependCSS($attr, "background-image:url($background);");
|
||||
|
||||
return $attr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -8,12 +8,20 @@
|
||||
class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
if (isset($attr['dir'])) return $attr;
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (isset($attr['dir'])) {
|
||||
return $attr;
|
||||
}
|
||||
$attr['dir'] = $config->get('Attr.DefaultTextDir');
|
||||
return $attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -3,21 +3,26 @@
|
||||
/**
|
||||
* Pre-transform that changes deprecated bgcolor attribute to CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform {
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
|
||||
if (!isset($attr['bgcolor'])) return $attr;
|
||||
class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['bgcolor'])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
$bgcolor = $this->confiscateAttr($attr, 'bgcolor');
|
||||
// some validation should happen here
|
||||
|
||||
$this->prependCSS($attr, "background-color:$bgcolor;");
|
||||
|
||||
return $attr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -3,34 +3,45 @@
|
||||
/**
|
||||
* Pre-transform that changes converts a boolean attribute to fixed CSS
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_BoolToCSS extends HTMLPurifier_AttrTransform {
|
||||
|
||||
class HTMLPurifier_AttrTransform_BoolToCSS extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* Name of boolean attribute that is trigger
|
||||
* Name of boolean attribute that is trigger.
|
||||
* @type string
|
||||
*/
|
||||
protected $attr;
|
||||
|
||||
/**
|
||||
* CSS declarations to add to style, needs trailing semicolon
|
||||
* CSS declarations to add to style, needs trailing semicolon.
|
||||
* @type string
|
||||
*/
|
||||
protected $css;
|
||||
|
||||
/**
|
||||
* @param $attr string attribute name to convert from
|
||||
* @param $css string CSS declarations to add to style (needs semicolon)
|
||||
* @param string $attr attribute name to convert from
|
||||
* @param string $css CSS declarations to add to style (needs semicolon)
|
||||
*/
|
||||
public function __construct($attr, $css) {
|
||||
public function __construct($attr, $css)
|
||||
{
|
||||
$this->attr = $attr;
|
||||
$this->css = $css;
|
||||
$this->css = $css;
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
if (!isset($attr[$this->attr])) return $attr;
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr[$this->attr])) {
|
||||
return $attr;
|
||||
}
|
||||
unset($attr[$this->attr]);
|
||||
$this->prependCSS($attr, $this->css);
|
||||
return $attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -3,16 +3,24 @@
|
||||
/**
|
||||
* Pre-transform that changes deprecated border attribute to CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform {
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
if (!isset($attr['border'])) return $attr;
|
||||
class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['border'])) {
|
||||
return $attr;
|
||||
}
|
||||
$border_width = $this->confiscateAttr($attr, 'border');
|
||||
// some validation should happen here
|
||||
$this->prependCSS($attr, "border:{$border_width}px solid;");
|
||||
return $attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -4,55 +4,65 @@
|
||||
* Generic pre-transform that converts an attribute with a fixed number of
|
||||
* values (enumerated) to CSS.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform {
|
||||
|
||||
class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* Name of attribute to transform from
|
||||
* Name of attribute to transform from.
|
||||
* @type string
|
||||
*/
|
||||
protected $attr;
|
||||
|
||||
/**
|
||||
* Lookup array of attribute values to CSS
|
||||
* Lookup array of attribute values to CSS.
|
||||
* @type array
|
||||
*/
|
||||
protected $enumToCSS = array();
|
||||
|
||||
/**
|
||||
* Case sensitivity of the matching
|
||||
* Case sensitivity of the matching.
|
||||
* @type bool
|
||||
* @warning Currently can only be guaranteed to work with ASCII
|
||||
* values.
|
||||
*/
|
||||
protected $caseSensitive = false;
|
||||
|
||||
/**
|
||||
* @param $attr String attribute name to transform from
|
||||
* @param $enumToCSS Lookup array of attribute values to CSS
|
||||
* @param $case_sensitive Boolean case sensitivity indicator, default false
|
||||
* @param string $attr Attribute name to transform from
|
||||
* @param array $enum_to_css Lookup array of attribute values to CSS
|
||||
* @param bool $case_sensitive Case sensitivity indicator, default false
|
||||
*/
|
||||
public function __construct($attr, $enum_to_css, $case_sensitive = false) {
|
||||
public function __construct($attr, $enum_to_css, $case_sensitive = false)
|
||||
{
|
||||
$this->attr = $attr;
|
||||
$this->enumToCSS = $enum_to_css;
|
||||
$this->caseSensitive = (bool) $case_sensitive;
|
||||
$this->caseSensitive = (bool)$case_sensitive;
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
|
||||
if (!isset($attr[$this->attr])) return $attr;
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr[$this->attr])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
$value = trim($attr[$this->attr]);
|
||||
unset($attr[$this->attr]);
|
||||
|
||||
if (!$this->caseSensitive) $value = strtolower($value);
|
||||
if (!$this->caseSensitive) {
|
||||
$value = strtolower($value);
|
||||
}
|
||||
|
||||
if (!isset($this->enumToCSS[$value])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
$this->prependCSS($attr, $this->enumToCSS[$value]);
|
||||
|
||||
return $attr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -11,11 +11,19 @@
|
||||
class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
$src = true;
|
||||
if (!isset($attr['src'])) {
|
||||
if ($config->get('Core.RemoveInvalidImg')) return $attr;
|
||||
if ($config->get('Core.RemoveInvalidImg')) {
|
||||
return $attr;
|
||||
}
|
||||
$attr['src'] = $config->get('Attr.DefaultInvalidImage');
|
||||
$src = false;
|
||||
}
|
||||
@@ -32,11 +40,8 @@ class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
|
||||
$attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt');
|
||||
}
|
||||
}
|
||||
|
||||
return $attr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -3,42 +3,59 @@
|
||||
/**
|
||||
* Pre-transform that changes deprecated hspace and vspace attributes to CSS
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_ImgSpace extends HTMLPurifier_AttrTransform {
|
||||
|
||||
class HTMLPurifier_AttrTransform_ImgSpace extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
protected $attr;
|
||||
|
||||
/**
|
||||
* @type array
|
||||
*/
|
||||
protected $css = array(
|
||||
'hspace' => array('left', 'right'),
|
||||
'vspace' => array('top', 'bottom')
|
||||
);
|
||||
|
||||
public function __construct($attr) {
|
||||
/**
|
||||
* @param string $attr
|
||||
*/
|
||||
public function __construct($attr)
|
||||
{
|
||||
$this->attr = $attr;
|
||||
if (!isset($this->css[$attr])) {
|
||||
trigger_error(htmlspecialchars($attr) . ' is not valid space attribute');
|
||||
}
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
|
||||
if (!isset($attr[$this->attr])) return $attr;
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr[$this->attr])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
$width = $this->confiscateAttr($attr, $this->attr);
|
||||
// some validation could happen here
|
||||
|
||||
if (!isset($this->css[$this->attr])) return $attr;
|
||||
if (!isset($this->css[$this->attr])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
$style = '';
|
||||
foreach ($this->css[$this->attr] as $suffix) {
|
||||
$property = "margin-$suffix";
|
||||
$style .= "$property:{$width}px;";
|
||||
}
|
||||
|
||||
$this->prependCSS($attr, $style);
|
||||
|
||||
return $attr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -4,17 +4,31 @@
|
||||
* Performs miscellaneous cross attribute validation and filtering for
|
||||
* input elements. This is meant to be a post-transform.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform {
|
||||
|
||||
class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_HTML_Pixels
|
||||
*/
|
||||
protected $pixels;
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
$this->pixels = new HTMLPurifier_AttrDef_HTML_Pixels();
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
if (!isset($attr['type'])) $t = 'text';
|
||||
else $t = strtolower($attr['type']);
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['type'])) {
|
||||
$t = 'text';
|
||||
} else {
|
||||
$t = strtolower($attr['type']);
|
||||
}
|
||||
if (isset($attr['checked']) && $t !== 'radio' && $t !== 'checkbox') {
|
||||
unset($attr['checked']);
|
||||
}
|
||||
@@ -23,8 +37,11 @@ class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform {
|
||||
}
|
||||
if (isset($attr['size']) && $t !== 'text' && $t !== 'password') {
|
||||
$result = $this->pixels->validate($attr['size'], $config, $context);
|
||||
if ($result === false) unset($attr['size']);
|
||||
else $attr['size'] = $result;
|
||||
if ($result === false) {
|
||||
unset($attr['size']);
|
||||
} else {
|
||||
$attr['size'] = $result;
|
||||
}
|
||||
}
|
||||
if (isset($attr['src']) && $t !== 'image') {
|
||||
unset($attr['src']);
|
||||
@@ -34,7 +51,6 @@ class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform {
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -8,9 +8,15 @@
|
||||
class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
|
||||
$lang = isset($attr['lang']) ? $attr['lang'] : false;
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
$lang = isset($attr['lang']) ? $attr['lang'] : false;
|
||||
$xml_lang = isset($attr['xml:lang']) ? $attr['xml:lang'] : false;
|
||||
|
||||
if ($lang !== false && $xml_lang === false) {
|
||||
@@ -18,11 +24,8 @@ class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform
|
||||
} elseif ($xml_lang !== false) {
|
||||
$attr['lang'] = $xml_lang;
|
||||
}
|
||||
|
||||
return $attr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,22 +6,40 @@
|
||||
class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
protected $cssName;
|
||||
|
||||
public function __construct($name, $css_name = null) {
|
||||
public function __construct($name, $css_name = null)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->cssName = $css_name ? $css_name : $name;
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
if (!isset($attr[$this->name])) return $attr;
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr[$this->name])) {
|
||||
return $attr;
|
||||
}
|
||||
$length = $this->confiscateAttr($attr, $this->name);
|
||||
if(ctype_digit($length)) $length .= 'px';
|
||||
if (ctype_digit($length)) {
|
||||
$length .= 'px';
|
||||
}
|
||||
$this->prependCSS($attr, $this->cssName . ":$length;");
|
||||
return $attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -6,16 +6,28 @@
|
||||
class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
// Abort early if we're using relaxed definition of name
|
||||
if ($config->get('HTML.Attr.Name.UseCDATA')) return $attr;
|
||||
if (!isset($attr['name'])) return $attr;
|
||||
if ($config->get('HTML.Attr.Name.UseCDATA')) {
|
||||
return $attr;
|
||||
}
|
||||
if (!isset($attr['name'])) {
|
||||
return $attr;
|
||||
}
|
||||
$id = $this->confiscateAttr($attr, 'name');
|
||||
if ( isset($attr['id'])) return $attr;
|
||||
if (isset($attr['id'])) {
|
||||
return $attr;
|
||||
}
|
||||
$attr['id'] = $id;
|
||||
return $attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
@@ -8,20 +8,34 @@
|
||||
class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
$this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
if (!isset($attr['name'])) return $attr;
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['name'])) {
|
||||
return $attr;
|
||||
}
|
||||
$name = $attr['name'];
|
||||
if (isset($attr['id']) && $attr['id'] === $name) return $attr;
|
||||
if (isset($attr['id']) && $attr['id'] === $name) {
|
||||
return $attr;
|
||||
}
|
||||
$result = $this->idDef->validate($name, $config, $context);
|
||||
if ($result === false) unset($attr['name']);
|
||||
else $attr['name'] = $result;
|
||||
if ($result === false) {
|
||||
unset($attr['name']);
|
||||
} else {
|
||||
$attr['name'] = $result;
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
||||
|
52
library/HTMLPurifier/AttrTransform/Nofollow.php
Normal file
52
library/HTMLPurifier/AttrTransform/Nofollow.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
// must be called POST validation
|
||||
|
||||
/**
|
||||
* Adds rel="nofollow" to all outbound links. This transform is
|
||||
* only attached if Attr.Nofollow is TRUE.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_Nofollow extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_URIParser
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->parser = new HTMLPurifier_URIParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['href'])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
// XXX Kind of inefficient
|
||||
$url = $this->parser->parse($attr['href']);
|
||||
$scheme = $url->getSchemeObj($config, $context);
|
||||
|
||||
if ($scheme->browsable && !$url->isLocal($config, $context)) {
|
||||
if (isset($attr['rel'])) {
|
||||
$rels = explode(' ', $attr['rel']);
|
||||
if (!in_array('nofollow', $rels)) {
|
||||
$rels[] = 'nofollow';
|
||||
}
|
||||
$attr['rel'] = implode(' ', $rels);
|
||||
} else {
|
||||
$attr['rel'] = 'nofollow';
|
||||
}
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
@@ -2,9 +2,19 @@
|
||||
|
||||
class HTMLPurifier_AttrTransform_SafeEmbed extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
public $name = "SafeEmbed";
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
$attr['allowscriptaccess'] = 'never';
|
||||
$attr['allownetworking'] = 'internal';
|
||||
$attr['type'] = 'application/x-shockwave-flash';
|
||||
|
@@ -5,10 +5,22 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_SafeObject extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
public $name = "SafeObject";
|
||||
|
||||
function transform($attr, $config, $context) {
|
||||
if (!isset($attr['type'])) $attr['type'] = 'application/x-shockwave-flash';
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['type'])) {
|
||||
$attr['type'] = 'application/x-shockwave-flash';
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
}
|
||||
|
@@ -14,14 +14,30 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_SafeParam extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @type string
|
||||
*/
|
||||
public $name = "SafeParam";
|
||||
|
||||
/**
|
||||
* @type HTMLPurifier_AttrDef_URI
|
||||
*/
|
||||
private $uri;
|
||||
|
||||
public function __construct() {
|
||||
public function __construct()
|
||||
{
|
||||
$this->uri = new HTMLPurifier_AttrDef_URI(true); // embedded
|
||||
$this->wmode = new HTMLPurifier_AttrDef_Enum(array('window', 'opaque', 'transparent'));
|
||||
}
|
||||
|
||||
public function transform($attr, $config, $context) {
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
// If we add support for other objects, we'll need to alter the
|
||||
// transforms.
|
||||
switch ($attr['name']) {
|
||||
@@ -33,12 +49,25 @@ class HTMLPurifier_AttrTransform_SafeParam extends HTMLPurifier_AttrTransform
|
||||
case 'allowNetworking':
|
||||
$attr['value'] = 'internal';
|
||||
break;
|
||||
case 'allowFullScreen':
|
||||
if ($config->get('HTML.FlashAllowFullScreen')) {
|
||||
$attr['value'] = ($attr['value'] == 'true') ? 'true' : 'false';
|
||||
} else {
|
||||
$attr['value'] = 'false';
|
||||
}
|
||||
break;
|
||||
case 'wmode':
|
||||
$attr['value'] = 'window';
|
||||
$attr['value'] = $this->wmode->validate($attr['value'], $config, $context);
|
||||
break;
|
||||
case 'movie':
|
||||
case 'src':
|
||||
$attr['name'] = "movie";
|
||||
$attr['value'] = $this->uri->validate($attr['value'], $config, $context);
|
||||
break;
|
||||
case 'flashvars':
|
||||
// we're going to allow arbitrary inputs to the SWF, on
|
||||
// the reasoning that it could only hack the SWF, not us.
|
||||
break;
|
||||
// add other cases to support other param name/value pairs
|
||||
default:
|
||||
$attr['name'] = $attr['value'] = null;
|
||||
|
@@ -5,7 +5,14 @@
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
public function transform($attr, $config, $context) {
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['type'])) {
|
||||
$attr['type'] = 'text/javascript';
|
||||
}
|
||||
|
45
library/HTMLPurifier/AttrTransform/TargetBlank.php
Normal file
45
library/HTMLPurifier/AttrTransform/TargetBlank.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
// must be called POST validation
|
||||
|
||||
/**
|
||||
* Adds target="blank" to all outbound links. This transform is
|
||||
* only attached if Attr.TargetBlank is TRUE. This works regardless
|
||||
* of whether or not Attr.AllowedFrameTargets
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @type HTMLPurifier_URIParser
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->parser = new HTMLPurifier_URIParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (!isset($attr['href'])) {
|
||||
return $attr;
|
||||
}
|
||||
|
||||
// XXX Kind of inefficient
|
||||
$url = $this->parser->parse($attr['href']);
|
||||
$scheme = $url->getSchemeObj($config, $context);
|
||||
|
||||
if ($scheme->browsable && !$url->isBenign($config, $context)) {
|
||||
$attr['target'] = '_blank';
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et sw=4 sts=4
|
37
library/HTMLPurifier/AttrTransform/TargetNoopener.php
Normal file
37
library/HTMLPurifier/AttrTransform/TargetNoopener.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
// must be called POST validation
|
||||
|
||||
/**
|
||||
* Adds rel="noopener" to any links which target a different window
|
||||
* than the current one. This is used to prevent malicious websites
|
||||
* from silently replacing the original window, which could be used
|
||||
* to do phishing.
|
||||
* This transform is controlled by %HTML.TargetNoopener.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_TargetNoopener extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (isset($attr['rel'])) {
|
||||
$rels = explode(' ', $attr['rel']);
|
||||
} else {
|
||||
$rels = array();
|
||||
}
|
||||
if (isset($attr['target']) && !in_array('noopener', $rels)) {
|
||||
$rels[] = 'noopener';
|
||||
}
|
||||
if (!empty($rels) || isset($attr['rel'])) {
|
||||
$attr['rel'] = implode(' ', $rels);
|
||||
}
|
||||
|
||||
return $attr;
|
||||
}
|
||||
}
|
||||
|
37
library/HTMLPurifier/AttrTransform/TargetNoreferrer.php
Normal file
37
library/HTMLPurifier/AttrTransform/TargetNoreferrer.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
// must be called POST validation
|
||||
|
||||
/**
|
||||
* Adds rel="noreferrer" to any links which target a different window
|
||||
* than the current one. This is used to prevent malicious websites
|
||||
* from silently replacing the original window, which could be used
|
||||
* to do phishing.
|
||||
* This transform is controlled by %HTML.TargetNoreferrer.
|
||||
*/
|
||||
class HTMLPurifier_AttrTransform_TargetNoreferrer extends HTMLPurifier_AttrTransform
|
||||
{
|
||||
/**
|
||||
* @param array $attr
|
||||
* @param HTMLPurifier_Config $config
|
||||
* @param HTMLPurifier_Context $context
|
||||
* @return array
|
||||
*/
|
||||
public function transform($attr, $config, $context)
|
||||
{
|
||||
if (isset($attr['rel'])) {
|
||||
$rels = explode(' ', $attr['rel']);
|
||||
} else {
|
||||
$rels = array();
|
||||
}
|
||||
if (isset($attr['target']) && !in_array('noreferrer', $rels)) {
|
||||
$rels[] = 'noreferrer';
|
||||
}
|
||||
if (!empty($rels) || isset($attr['rel'])) {
|
||||
$attr['rel'] = implode(' ', $rels);
|
||||
}
|
||||
|
||||
return $attr;
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user