1
0
mirror of https://github.com/ezyang/htmlpurifier.git synced 2025-08-05 21:57:26 +02:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Edward Z. Yang
c768146e4d Gusev's proposed patch
Signed-off-by: Edward Z. Yang <ezyang@mit.edu>
2013-10-12 21:24:38 -07:00
528 changed files with 9162 additions and 17887 deletions

24
.gitattributes vendored
View File

@@ -1,23 +1 @@
/.gitattributes export-ignore configdoc/usage.xml -crlf
/.github export-ignore
/.gitignore export-ignore
/art export-ignore
/benchmarks export-ignore
/configdoc export-ignore
/configdoc/usage.xml -crlf
/docs export-ignore
/Doxyfile export-ignore
/extras export-ignore
/INSTALL* export-ignore
/maintenance export-ignore
/NEWS export-ignore
/package.php export-ignore
/plugins export-ignore
/phpdoc.ini export-ignore
/smoketests export-ignore
/test-* export-ignore
/tests export-ignore
/TODO export-ignore
/update-for-release export-ignore
/WYSIWYG export-ignore
/release.config.js export-ignore

View File

@@ -1,36 +0,0 @@
name: ci
on:
push:
pull_request:
jobs:
linux_tests:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
php: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
name: PHP ${{ matrix.php }}
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
ini-values: error_reporting=E_ALL
extensions: iconv, bcmath, tidy, mbstring, intl
- name: Install dependencies
run: composer install
- name: Configure simpletest
run: cp test-settings.sample.php test-settings.php
- name: Execute Unit tests
run: php tests/index.php

View File

@@ -1,19 +0,0 @@
name: "Lint PR"
on:
pull_request_target:
types:
- opened
- edited
- synchronize
jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,29 +0,0 @@
name: release
on:
workflow_dispatch:
jobs:
release:
runs-on: ubuntu-latest
name: Release
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: 8.2
- name: Run automated release process with semantic-release
uses: cycjimmy/semantic-release-action@v4
with:
extra_plugins: |
@semantic-release/changelog
@semantic-release/git
@semantic-release/exec
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

4
.gitignore vendored
View File

@@ -22,7 +22,3 @@ docs/doxygen*
/*.php /*.php
vendor vendor
composer.lock composer.lock
*.rej
*.orig
*.bak
core

View File

@@ -31,7 +31,7 @@ PROJECT_NAME = HTMLPurifier
# This could be handy for archiving the generated documentation or # This could be handy for archiving the generated documentation or
# if some version control system is used. # if some version control system is used.
PROJECT_NUMBER = 4.18.0 PROJECT_NUMBER = 4.5.0
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put. # base path where the generated documentation will be put.

13
FOCUS Normal file
View File

@@ -0,0 +1,13 @@
4 - Minor 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

49
INSTALL
View File

@@ -15,8 +15,10 @@ with these contents.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
1. Compatibility 1. Compatibility
HTML Purifier is PHP 5 and PHP 7, and is actively tested from PHP 5.3 HTML Purifier is PHP 5 only, and is actively tested from PHP 5.0.5 and
and up. It has no core dependencies with other libraries. 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 not compatible with zend.ze1_compatibility_mode.
These optional extensions can enhance the capabilities of HTML Purifier: These optional extensions can enhance the capabilities of HTML Purifier:
@@ -27,10 +29,7 @@ These optional extensions can enhance the capabilities of HTML Purifier:
These optional libraries can enhance the capabilities of HTML Purifier: These optional libraries can enhance the capabilities of HTML Purifier:
* CSSTidy : Clean CSS stylesheets using %Core.ExtractStyleBlocks * 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 * Net_IDNA2 (PEAR) : IRI support using %Core.EnableIDNA
Note: This is not necessary for PHP 5.3 or later
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
2. Reconnaissance 2. Reconnaissance
@@ -101,6 +100,31 @@ Autoload compatibility
autoloader, but there are some cases where you will need to change autoloader, but there are some cases where you will need to change
your own code to accomodate HTML Purifier. These are those cases: your own code to accomodate HTML Purifier. These are those cases:
PHP VERSION IS LESS THAN 5.1.2, AND YOU'VE DEFINED __autoload
Because spl_autoload_register() doesn't exist in early versions
of PHP 5, HTML Purifier has no way of adding itself to the autoload
stack. Modify your __autoload function to test
HTMLPurifier_Bootstrap::autoload($class)
For example, suppose your autoload function looks like this:
function __autoload($class) {
require str_replace('_', '/', $class) . '.php';
return true;
}
A modified version with HTML Purifier would look like this:
function __autoload($class) {
if (HTMLPurifier_Bootstrap::autoload($class)) return true;
require str_replace('_', '/', $class) . '.php';
return true;
}
Note that there *is* some custom behavior in our autoloader; the
original autoloader in our example would work for 99% of the time,
but would fail when including language files.
AN __autoload FUNCTION IS DECLARED AFTER OUR AUTOLOADER IS REGISTERED AN __autoload FUNCTION IS DECLARED AFTER OUR AUTOLOADER IS REGISTERED
spl_autoload_register() has the curious behavior of disabling spl_autoload_register() has the curious behavior of disabling
the existing __autoload() handler. Users need to explicitly the existing __autoload() handler. Users need to explicitly
@@ -113,6 +137,11 @@ Autoload compatibility
spl_autoload_register('__autoload') spl_autoload_register('__autoload')
Users should also be on guard if they use a version of PHP previous
to 5.1.2 without an autoloader--HTML Purifier will define __autoload()
for you, which can collide with an autoloader that was added by *you*
later.
For better performance For better performance
---------------------- ----------------------
@@ -174,7 +203,9 @@ For advanced users
HTMLPurifier.autoload.php HTMLPurifier.autoload.php
Registers our autoload handler HTMLPurifier_Bootstrap::autoload($class). Registers our autoload handler HTMLPurifier_Bootstrap::autoload($class).
You can do these operations by yourself, if you like. You can do these operations by yourself--in fact, you must modify your own
autoload handler if you are using a version of PHP earlier than PHP 5.1.2
(See "Autoload compatibility" above).
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
@@ -274,9 +305,11 @@ appropriate permissions using:
chmod -R 0755 HTMLPurifier/DefinitionCache/Serializer chmod -R 0755 HTMLPurifier/DefinitionCache/Serializer
If the above command doesn't work, you may need to assign write permissions If the above command doesn't work, you may need to assign write permissions
to group: to all. This may be necessary if your webserver runs as nobody, but is
not recommended since it means any other user can write files in the
directory. Use:
chmod -R 0775 HTMLPurifier/DefinitionCache/Serializer chmod -R 0777 HTMLPurifier/DefinitionCache/Serializer
You can also chmod files via your FTP client; this option You can also chmod files via your FTP client; this option
is usually accessible by right clicking the corresponding directory and is usually accessible by right clicking the corresponding directory and

View File

@@ -1,60 +1,69 @@

Installation Installation
Comment installer HTML Purifier Comment installer HTML Purifier
Attention : Ce document est encodé en UTF-8, si les lettres avec des accents Attention: Ce document a encode en UTF-8. Si les lettres avec les accents
ne s'affichent pas, prenez un meilleur éditeur de texte. 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.
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é 1. Compatibilité
HTML Purifier fonctionne avec PHP 5. PHP 5.3 est la dernière version testée. HTML Purifier fonctionne dans PHP 5. PHP 5.0.5 est le dernier
Il ne dépend pas d'autres librairies. version que je le testais. Il ne dépend de les autre librairies.
Les extensions optionnelles sont iconv (généralement déjà installée) et tidy Les extensions optionnel est iconv (en général déjà installer) et
(répendue aussi). Si vous utilisez UTF-8 et que vous ne voulez pas l'indentation, tidy (répandu aussi). Si vous utilisez UTF-8 et ne voulez pas
vous pouvez utiliser HTML Purifier sans ces extensions. l'indentation, vous pouvez utiliser HTML Purifier sans ces extensions.
2. Inclure la librairie 2. Inclure la librarie
Quand vous devez l'utilisez, incluez le : Utilisez:
require_once('/path/to/library/HTMLPurifier.auto.php'); require_once '/path/to/library/HTMLPurifier.auto.php';
Ne pas l'inclure si ce n'est pas nécessaire, car HTML Purifier est lourd. ...quand vous devez utiliser HTML Purifier (ne inclure pas quand vous
ne devez pas, parce que HTML Purifier est trés grand.)
HTML Purifier utilise "autoload". Si vous avez défini la fonction __autoload, HTML Purifier utilise 'autoload'. Si vous avez définu la fonction
vous devez ajouter cette fonction : __autoload, vous doivez ajoute cet programme:
spl_autoload_register('__autoload') spl_autoload_register('__autoload')
Plus d'informations dans le document "INSTALL". Plus d'information est dans le document 'INSTALL'.
3. Installation rapide
Si votre site Web est en UTF-8 et XHTML Transitional, utilisez : 3. Installation vite
Si votre site web est en UTF-8 et XHTML Transitional, utilisez:
<?php <?php
require_once('/path/to/htmlpurifier/library/HTMLPurifier.auto.php'); require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
$purificateur = new HTMLPurifier(); $purificateur = new HTMLPurifier();
$html_propre = $purificateur->purify($html_a_purifier); $html_propre = $purificateur->purify($html_salle);
?> ?>
Sinon, utilisez : Sinon, utilisez:
<?php <?php
require_once('/path/to/html/purifier/library/HTMLPurifier.auto.load'); require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
$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_a_purifier);
?>
$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
$purificateur = new HTMLPurifier($config);
$html_propre = $purificateur->purify($html_salle);
?>
vim: et sw=4 sts=4 vim: et sw=4 sts=4

254
NEWS
View File

@@ -1,46 +1,3 @@
# [4.18.0](https://github.com/ezyang/htmlpurifier/compare/v4.17.0...v4.18.0) (2024-11-01)
### Bug Fixes
* Adjust Core.AllowHostnameUnderscore to consider that "_" is defined as Unreserved Characters in RFC 3986 ([#406](https://github.com/ezyang/htmlpurifier/issues/406)) ([d9fbef8](https://github.com/ezyang/htmlpurifier/commit/d9fbef8e27f6a0848a8987a8534351de98eb0fa1))
* Avoid a deprecated error when the attribute name is numeric and DirectLex is used ([#412](https://github.com/ezyang/htmlpurifier/issues/412)) ([f0fbf51](https://github.com/ezyang/htmlpurifier/commit/f0fbf510981b27fc03168efdb17d6bff48f521af))
* checking that node has property name ([#399](https://github.com/ezyang/htmlpurifier/issues/399)) ([9ca5a36](https://github.com/ezyang/htmlpurifier/commit/9ca5a3687bd2e6e42ed9d5199b2cfb1dbd6dbdc2))
* Ignore conditional comments ([#401](https://github.com/ezyang/htmlpurifier/issues/401)) ([4828fdf](https://github.com/ezyang/htmlpurifier/commit/4828fdf45a93eeeacfcbcc855f96f9a7e6b4ed44))
* Support PHP 8.4 ([#396](https://github.com/ezyang/htmlpurifier/issues/396)) ([92da247](https://github.com/ezyang/htmlpurifier/commit/92da2473ffbb3ed5e894560d4166b1ca8032aeb3))
* undefined array key warning ([#419](https://github.com/ezyang/htmlpurifier/issues/419)) ([01be377](https://github.com/ezyang/htmlpurifier/commit/01be377f93654fad4d3fbc8c81779f14316eaecf))
### Features
* Add allowfullscreen attr for iframe ([#411](https://github.com/ezyang/htmlpurifier/issues/411)) ([70754a2](https://github.com/ezyang/htmlpurifier/commit/70754a253342f67a67425cfa81029db3a5c1bd28))
* add directive for removing blank nodes ([#404](https://github.com/ezyang/htmlpurifier/issues/404)) ([c9d60c9](https://github.com/ezyang/htmlpurifier/commit/c9d60c96d799c02bc357c88a49f422034b6914fd))
* Add support for CSS aspect-ratio ([#408](https://github.com/ezyang/htmlpurifier/issues/408)) ([93bee73](https://github.com/ezyang/htmlpurifier/commit/93bee733497a098b65daf5910f1c435d347860a4))
* Allow universal CSS values for all properties ([#410](https://github.com/ezyang/htmlpurifier/issues/410)) ([9723267](https://github.com/ezyang/htmlpurifier/commit/972326785d201b81e1095bc296b99bbcfa8c7fd4))
# [4.17.0](https://github.com/ezyang/htmlpurifier/compare/v4.16.0...v4.17.0) (2023-11-17)
### Bug Fixes
* CSSTidy ImportantComments not handled properly ([#359](https://github.com/ezyang/htmlpurifier/issues/359)) ([78a9b4d](https://github.com/ezyang/htmlpurifier/commit/78a9b4d0dae8bce9a70e4e7e551bf51e9a23706d))
* fix CI ([#361](https://github.com/ezyang/htmlpurifier/issues/361)) ([9ec687c](https://github.com/ezyang/htmlpurifier/commit/9ec687c904a1fe66a5395d22c50f7043e045d1d3))
* Invalid scheme check in Attr.TargetBlank ([#363](https://github.com/ezyang/htmlpurifier/issues/363)) ([0176ef4](https://github.com/ezyang/htmlpurifier/commit/0176ef4bb6f57103fdcb60a802603e60e81ee93e))
* semantic release ([#339](https://github.com/ezyang/htmlpurifier/issues/339)) ([d82f3d9](https://github.com/ezyang/htmlpurifier/commit/d82f3d996a0d9b0f23364946d9a14408c1ad72c5))
* semantic release ([#341](https://github.com/ezyang/htmlpurifier/issues/341)) ([e55fead](https://github.com/ezyang/htmlpurifier/commit/e55fead09f39430d30f48438f06e7bc2326efc94)), closes [#339](https://github.com/ezyang/htmlpurifier/issues/339)
* Support for locales using decimal separators other than . (dot) ([#372](https://github.com/ezyang/htmlpurifier/issues/372)) ([43f49ac](https://github.com/ezyang/htmlpurifier/commit/43f49ac9a51b81dfd07d3bc8dcfc5ec5637a5e3b))
### Features
* Add support for all text-decoration properties ([#360](https://github.com/ezyang/htmlpurifier/issues/360)) ([2d775c0](https://github.com/ezyang/htmlpurifier/commit/2d775c01874e2f676ba1a2d9fe69b47c2a823061))
* Allows commas to be included in tel URI ([#389](https://github.com/ezyang/htmlpurifier/issues/389)) ([ec92490](https://github.com/ezyang/htmlpurifier/commit/ec924901392f088d334622f806b9449b17b75d7b)), closes [#388](https://github.com/ezyang/htmlpurifier/issues/388)
### Reverts
* Revert "fix: semantic release (#339)" (#340) ([3e83215](https://github.com/ezyang/htmlpurifier/commit/3e832152a6173f880c6495a3ab2b0e5235e253a6)), closes [#339](https://github.com/ezyang/htmlpurifier/issues/339) [#340](https://github.com/ezyang/htmlpurifier/issues/340)
NEWS ( CHANGELOG and HISTORY ) HTMLPurifier NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@@ -52,219 +9,10 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Internal change . Internal change
========================== ==========================
4.15.0, released 2022-09-18 4.6.0, unknown release date
! PHP 8.1 and 8.2 support, esp. fixes for deprecation warnings. A joint effort
by David Rans, Tim Düsterhus, Kieran and John Flatness.
! Allow contenteditable="false" (#336), contributed by Kieran.
- Replace PHP 8.1 deprecated utf8_ functions with mbstring (#326),
contributed by John Flatness.
- Enhanced composer suggestions with extensions (#317), contributed by
func0der.
4.14.0, released 2021-12-24
! Add "background-size" support (#289), contributed by Václav Smítal
! Transform deprecated width attribute when tidying HTML, contributed by
Kieran.
- PHP 8 support, contributed by Maksims Sļotovs.
- Improved PHP 7.3 compatibility, contributed by kishor.
- Avoid spurious magic quotes notice in PHP 7.4. Thanks
Jasper Zonneveld for the fix.
- Do not remove thead from table even if there are no tbody/tr (#264).
Thanks Marcus Artner for the fix.
- Fix "Parameter must be an array or an object that implements
Countable" (#285)". Thanks Kieran for this fix.
. Fix unnecessary reference assignment, handling behavior change from
PHP5 and PHP7. Thanks Arkadiusz Biczewski for the fix.
4.13.0, released 2020-06-28
! Add %HTML.Forms directive, which lets you accept forms in user
HTML without requiring full %HTML.Trusted. Note that forms can
be (trivially) used to setup phishing; e.g., an attacker can
use CSS absolute positioning to overlay a form on top of a login
element, so please be sure to use this with care! Fixes #213.
Thanks Mateusz Turcza for contributing this feature.
! tr@bgcolor attribute is now supported. Thanks Kieran Brahney
for this enhancement.
- Further improvements to PHP 7.4 support, contributed by Witold
Wasiczko and Eloy Lafuente.
- Fix PSR-0 compatibility. Thanks Jordi Boggiano for contributing
part of this fix.
- Fix bug with purifyArray where it doesn't work on empty arrays.
Thanks Fräntz Miccoli for the fix.
- Reduce amount of maintenance scripts included in distribution
packages. Thanks Sergei Morozov for this patch.
- Remove leading zeros unless if it is only a zero, fixes #239. Thanks
lubomirbartos for this fix.
- Correct type hinting of maybeGet*, fixes #240. Thanks Anders Jenbo
for this fix.
4.12.0, released 2019-10-27
! PHP 7.4 is supported, thank you Witold Wasiczko, Mateuz Turcza and
Edi Modrić
- PHPDocs for HTMLModule::addElement() and Bool attr are fixed (thanks
Mateusz)
4.11.0, released 2019-07-14
# SafeScripting now matches case-sensitively against its whitelist (previously it was
case-insensitive.) Thanks Dimitri Gritsajuk <gritsajuk.dimitri@gmail.com>
for reporting.
! New directive %Core.AllowParseManyTags which allows parsing of many nested tags.
Thanks M. Suzuki <msuzuki1986@gmail.com> for contributing the patch.
! purifyArray now supports multidimensional arrays. Thanks
Sandro Miguel Marques <sandromiguel@sandromiguel.com> for contributing this patch.
! initial and inherit settings available for width, height, and the min-/max-
versions thereof. Thanks Michael Kliewe <info@phpgansta.de> for contributing
this patch.
! More color names are supported. Thanks Daijobou for contributing.
- Compatibility fixes for PHP 7.3, including new CI for PHP 7.3
(thank you Lukas Neumann <lksnmnn@gmail.com>) and removal of
reserved words in our constants (thanks Darko Hrgovic <darko@darkodev.com>
- Compatibility fixes for HHVM. Thanks Mateusz Turcza for contributing
this fix.
- HTML Purifier now never defines __autoload, fixing #196. Thanks
Michael Kliewe for reporting.
- In some situations, Config.php would report an undefined index: class
error; this has been fixed. Thanks DiLong Fa for contributing
this fix.
- We no longer produce <script /> tags; we always explicitly write
out the open and close tag. Thanks Dimitri Gritsajuk
<gritsajuk.dimitri@gmail.com> for contributing this fix.
- Better compatibility when IDNA constants are not present. Thanks
Mateusz Turcza <xemlock@gmail.com> for contributing this fix.
4.10.0, released 2018-02-22
# PHP 5.3 is no longer officially supported by HTML Purifier
(we did not specifically break support, but we are no longer
testing on PHP 5.3)
! Relative CSS length units are now supported
- A few PHP 7.2 compatibility fixes, thanks John Flatness
<john@zerocrates.org>
- Improve portability with old versions of libxml which don't
support accessing the data of a node
- IDNA2008 is now used for converting domains to ASCII, fixing
some rather strange bugs with international domains
- Fix race condition resulting in E_WARNING when creating
directories with Serializer
4.9.3, released 2017-06-02
- Workaround PHP 7.1 infinite loop when opcode cache is enabled.
Thanks @Xiphin (#134, #135)
- Don't use autoloader when testing for DOMDocument. Hypothetically,
this could cause your install to start using DirectLex if you had
previously been monkeypatching in a custom, autoloaded implementation
of DOMDocument. Don't do that. Thanks @Izumi-kun (#130)
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 # URI parsing algorithm was made more strict, so only prefixes which
looks like schemes will actually be schemes. Thanks looks like schemes will actually be schemes. Thanks
Michael Gusev <mgusev@sugarcrm.com> for fixing. 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 4.5.0, released 2013-02-17
# Fix bug where stacked attribute transforms clobber each other; # Fix bug where stacked attribute transforms clobber each other;

View File

@@ -1,8 +1,9 @@
HTML Purifier [![Build Status](https://github.com/ezyang/htmlpurifier/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/ezyang/htmlpurifier/actions/workflows/ci.yml)
============= README
All about HTML Purifier
HTML Purifier is an HTML filtering solution that uses a unique combination HTML Purifier is an HTML filtering solution that uses a unique combination
of robust whitelists and aggressive parsing to ensure that not only are of robust whitelists and agressive parsing to ensure that not only are
XSS attacks thwarted, but the resulting HTML is standards compliant. XSS attacks thwarted, but the resulting HTML is standards compliant.
HTML Purifier is oriented towards richly formatted documents from HTML Purifier is oriented towards richly formatted documents from
@@ -18,12 +19,6 @@ Places to go:
an in-depth installation guide. an in-depth installation guide.
* See WYSIWYG for information on editors like TinyMCE and FCKeditor * See WYSIWYG for information on editors like TinyMCE and FCKeditor
HTML Purifier can be found on the web at: [http://htmlpurifier.org/](http://htmlpurifier.org/) HTML Purifier can be found on the web at: http://htmlpurifier.org/
## Installation vim: et sw=4 sts=4
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

2
TODO
View File

@@ -32,7 +32,7 @@ Things to do as soon as possible:
FUTURE VERSIONS FUTURE VERSIONS
--------------- ---------------
4.9 release [OMG CONFIG PONIES] 4.6 release [OMG CONFIG PONIES]
! Fix Printer. It's from the old days when we didn't have decent XML classes ! 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 ! Factor demo.php into a set of Printer classes, and then create a stub
file for users here (inside the actual HTML Purifier library) file for users here (inside the actual HTML Purifier library)

View File

@@ -1 +1 @@
4.18.0 4.5.0

6
WHATSNEW Normal file
View File

@@ -0,0 +1,6 @@
HTML Purifier 4.5.0 is a minor bugfix and feature release, containing an
accumulation of changes over a year. CSS support has been extended to
support display:inline-block, white-space, underscores in font families,
page-break-* CSS3 properties (when proprietary is enabled.) We now use
SHA-1 to identify cached definitions, and the semantics of stacked
attribute transforms has changed slightly.

View File

@@ -1,7 +1 @@
<IfModule mod_authz_core.c> Deny from all
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Deny from all
</ifModule>

View File

@@ -23,16 +23,15 @@ if (version_compare(PHP_VERSION, '5', '>=')) {
class RowTimer extends Benchmark_Timer class RowTimer extends Benchmark_Timer
{ {
public $name; var $name;
public function __construct($name, $auto = false) function RowTimer($name, $auto = false) {
{
$this->name = htmlentities($name); $this->name = htmlentities($name);
$this->Benchmark_Timer($auto); $this->Benchmark_Timer($auto);
} }
public function getOutput() function getOutput() {
{
$total = $this->TimeElapsed(); $total = $this->TimeElapsed();
$result = $this->getProfiling(); $result = $this->getProfiling();
$dashes = ''; $dashes = '';
@@ -69,8 +68,7 @@ class RowTimer extends Benchmark_Timer
} }
} }
function print_lexers() function print_lexers() {
{
global $LEXERS; global $LEXERS;
$first = true; $first = true;
foreach ($LEXERS as $key => $value) { foreach ($LEXERS as $key => $value) {
@@ -80,8 +78,7 @@ function print_lexers()
} }
} }
function do_benchmark($name, $document) function do_benchmark($name, $document) {
{
global $LEXERS, $RUNS; global $LEXERS, $RUNS;
$config = HTMLPurifier_Config::createDefault(); $config = HTMLPurifier_Config::createDefault();

View File

@@ -4,7 +4,7 @@
"type": "library", "type": "library",
"keywords": ["html"], "keywords": ["html"],
"homepage": "http://htmlpurifier.org/", "homepage": "http://htmlpurifier.org/",
"license": "LGPL-2.1-or-later", "license": "LGPL",
"authors": [ "authors": [
{ {
"name": "Edward Z. Yang", "name": "Edward Z. Yang",
@@ -13,33 +13,10 @@
} }
], ],
"require": { "require": {
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" "php": ">=5.2"
},
"require-dev": {
"cerdic/css-tidy": "^1.7 || ^2.0",
"simpletest/simpletest": "dev-master"
}, },
"autoload": { "autoload": {
"psr-0": { "HTMLPurifier": "library/" }, "psr-0": { "HTMLPurifier": "library/" },
"files": ["library/HTMLPurifier.composer.php"], "files": ["library/HTMLPurifier.composer.php"]
"exclude-from-classmap": [ }
"/library/HTMLPurifier/Language/"
]
},
"suggest": {
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
"ext-bcmath": "Used for unit conversion and imagecrash protection",
"ext-tidy": "Used for pretty-printing HTML"
},
"config": {
"sort-packages": true
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/ezyang/simpletest.git",
"no-api": true
}
]
} }

View File

@@ -2,610 +2,546 @@
<usage> <usage>
<directive id="Core.CollectErrors"> <directive id="Core.CollectErrors">
<file name="HTMLPurifier.php"> <file name="HTMLPurifier.php">
<line>162</line> <line>131</line>
</file> </file>
<file name="HTMLPurifier/Lexer.php"> <file name="HTMLPurifier/Lexer.php">
<line>90</line> <line>81</line>
<line>315</line> <line>284</line>
</file> </file>
<file name="HTMLPurifier/Lexer/DirectLex.php"> <file name="HTMLPurifier/Lexer/DirectLex.php">
<line>67</line> <line>53</line>
<line>87</line> <line>73</line>
<line>385</line> <line>348</line>
</file> </file>
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php"> <file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>57</line> <line>50</line>
</file> </file>
</directive> </directive>
<directive id="CSS.MaxImgLength"> <directive id="CSS.MaxImgLength">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>253</line> <line>157</line>
</file> </file>
</directive> </directive>
<directive id="CSS.Proprietary"> <directive id="CSS.Proprietary">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>397</line> <line>215</line>
</file> </file>
</directive> </directive>
<directive id="CSS.AllowTricky"> <directive id="CSS.AllowTricky">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>401</line> <line>219</line>
</file> </file>
</directive> </directive>
<directive id="CSS.Trusted"> <directive id="CSS.Trusted">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>405</line> <line>223</line>
</file> </file>
</directive> </directive>
<directive id="CSS.AllowImportant"> <directive id="CSS.AllowImportant">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>409</line> <line>227</line>
</file> </file>
</directive> </directive>
<directive id="CSS.AllowedProperties"> <directive id="CSS.AllowedProperties">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>538</line> <line>302</line>
</file> </file>
</directive> </directive>
<directive id="CSS.ForbiddenProperties"> <directive id="CSS.ForbiddenProperties">
<file name="HTMLPurifier/CSSDefinition.php"> <file name="HTMLPurifier/CSSDefinition.php">
<line>554</line> <line>316</line>
</file> </file>
</directive> </directive>
<directive id="Cache.DefinitionImpl"> <directive id="Cache.DefinitionImpl">
<file name="HTMLPurifier/DefinitionCacheFactory.php"> <file name="HTMLPurifier/DefinitionCacheFactory.php">
<line>66</line> <line>49</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Doctype"> <directive id="HTML.Doctype">
<file name="HTMLPurifier/DoctypeRegistry.php"> <file name="HTMLPurifier/DoctypeRegistry.php">
<line>119</line> <line>83</line>
</file> </file>
</directive> </directive>
<directive id="HTML.CustomDoctype"> <directive id="HTML.CustomDoctype">
<file name="HTMLPurifier/DoctypeRegistry.php"> <file name="HTMLPurifier/DoctypeRegistry.php">
<line>123</line> <line>85</line>
</file> </file>
</directive> </directive>
<directive id="HTML.XHTML"> <directive id="HTML.XHTML">
<file name="HTMLPurifier/DoctypeRegistry.php"> <file name="HTMLPurifier/DoctypeRegistry.php">
<line>128</line> <line>88</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Strict"> <directive id="HTML.Strict">
<file name="HTMLPurifier/DoctypeRegistry.php"> <file name="HTMLPurifier/DoctypeRegistry.php">
<line>133</line> <line>93</line>
</file> </file>
</directive> </directive>
<directive id="Core.Encoding"> <directive id="Core.Encoding">
<file name="HTMLPurifier/Encoder.php"> <file name="HTMLPurifier/Encoder.php">
<line>380</line> <line>337</line>
<line>428</line> <line>372</line>
</file> </file>
</directive> </directive>
<directive id="Test.ForceNoIconv"> <directive id="Test.ForceNoIconv">
<file name="HTMLPurifier/Encoder.php"> <file name="HTMLPurifier/Encoder.php">
<line>388</line> <line>341</line>
<line>439</line> <line>379</line>
</file> </file>
</directive> </directive>
<directive id="Core.EscapeNonASCIICharacters"> <directive id="Core.EscapeNonASCIICharacters">
<file name="HTMLPurifier/Encoder.php"> <file name="HTMLPurifier/Encoder.php">
<line>429</line> <line>373</line>
</file> </file>
</directive> </directive>
<directive id="Output.CommentScriptContents"> <directive id="Output.CommentScriptContents">
<file name="HTMLPurifier/Generator.php"> <file name="HTMLPurifier/Generator.php">
<line>70</line> <line>61</line>
</file> </file>
</directive> </directive>
<directive id="Output.FixInnerHTML"> <directive id="Output.FixInnerHTML">
<file name="HTMLPurifier/Generator.php"> <file name="HTMLPurifier/Generator.php">
<line>71</line> <line>62</line>
</file> </file>
</directive> </directive>
<directive id="Output.SortAttr"> <directive id="Output.SortAttr">
<file name="HTMLPurifier/Generator.php"> <file name="HTMLPurifier/Generator.php">
<line>72</line> <line>63</line>
</file> </file>
</directive> </directive>
<directive id="Output.FlashCompat"> <directive id="Output.FlashCompat">
<file name="HTMLPurifier/Generator.php"> <file name="HTMLPurifier/Generator.php">
<line>73</line> <line>64</line>
</file> </file>
</directive> </directive>
<directive id="Output.TidyFormat"> <directive id="Output.TidyFormat">
<file name="HTMLPurifier/Generator.php"> <file name="HTMLPurifier/Generator.php">
<line>104</line> <line>93</line>
</file> </file>
</directive> </directive>
<directive id="Core.NormalizeNewlines"> <directive id="Core.NormalizeNewlines">
<file name="HTMLPurifier/Generator.php"> <file name="HTMLPurifier/Generator.php">
<line>122</line> <line>107</line>
</file> </file>
<file name="HTMLPurifier/Lexer.php"> <file name="HTMLPurifier/Lexer.php">
<line>299</line> <line>266</line>
</file> </file>
</directive> </directive>
<directive id="Output.Newline"> <directive id="Output.Newline">
<file name="HTMLPurifier/Generator.php"> <file name="HTMLPurifier/Generator.php">
<line>123</line> <line>108</line>
</file> </file>
</directive> </directive>
<directive id="HTML.BlockWrapper"> <directive id="HTML.BlockWrapper">
<file name="HTMLPurifier/HTMLDefinition.php"> <file name="HTMLPurifier/HTMLDefinition.php">
<line>263</line> <line>222</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Parent"> <directive id="HTML.Parent">
<file name="HTMLPurifier/HTMLDefinition.php"> <file name="HTMLPurifier/HTMLDefinition.php">
<line>273</line> <line>230</line>
</file> </file>
</directive> </directive>
<directive id="HTML.AllowedElements"> <directive id="HTML.AllowedElements">
<file name="HTMLPurifier/HTMLDefinition.php"> <file name="HTMLPurifier/HTMLDefinition.php">
<line>291</line> <line>247</line>
</file> </file>
</directive> </directive>
<directive id="HTML.AllowedAttributes"> <directive id="HTML.AllowedAttributes">
<file name="HTMLPurifier/HTMLDefinition.php"> <file name="HTMLPurifier/HTMLDefinition.php">
<line>292</line> <line>248</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Allowed"> <directive id="HTML.Allowed">
<file name="HTMLPurifier/HTMLDefinition.php"> <file name="HTMLPurifier/HTMLDefinition.php">
<line>295</line> <line>251</line>
</file> </file>
</directive> </directive>
<directive id="HTML.ForbiddenElements"> <directive id="HTML.ForbiddenElements">
<file name="HTMLPurifier/HTMLDefinition.php"> <file name="HTMLPurifier/HTMLDefinition.php">
<line>399</line> <line>342</line>
</file> </file>
</directive> </directive>
<directive id="HTML.ForbiddenAttributes"> <directive id="HTML.ForbiddenAttributes">
<file name="HTMLPurifier/HTMLDefinition.php"> <file name="HTMLPurifier/HTMLDefinition.php">
<line>400</line> <line>343</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Trusted"> <directive id="HTML.Trusted">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>234</line> <line>204</line>
</file> </file>
<file name="HTMLPurifier/Lexer.php"> <file name="HTMLPurifier/Lexer.php">
<line>304</line> <line>271</line>
<line>342</line>
</file>
<file name="HTMLPurifier/AttrDef/HTML/ContentEditable.php">
<line>8</line>
</file>
<file name="HTMLPurifier/HTMLModule/Iframe.php">
<line>43</line>
</file> </file>
<file name="HTMLPurifier/HTMLModule/Image.php"> <file name="HTMLPurifier/HTMLModule/Image.php">
<line>37</line> <line>27</line>
</file> </file>
<file name="HTMLPurifier/Lexer/DirectLex.php"> <file name="HTMLPurifier/Lexer/DirectLex.php">
<line>47</line> <line>36</line>
</file> </file>
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php"> <file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>30</line> <line>23</line>
</file> </file>
</directive> </directive>
<directive id="HTML.AllowedModules"> <directive id="HTML.AllowedModules">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>241</line> <line>211</line>
</file> </file>
</directive> </directive>
<directive id="HTML.CoreModules"> <directive id="HTML.CoreModules">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>242</line> <line>212</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Proprietary"> <directive id="HTML.Proprietary">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>256</line> <line>222</line>
</file> </file>
</directive> </directive>
<directive id="HTML.SafeObject"> <directive id="HTML.SafeObject">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>259</line> <line>225</line>
</file> </file>
</directive> </directive>
<directive id="HTML.SafeEmbed"> <directive id="HTML.SafeEmbed">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>262</line> <line>228</line>
</file> </file>
</directive> </directive>
<directive id="HTML.SafeScripting"> <directive id="HTML.SafeScripting">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>265</line> <line>231</line>
</file> </file>
<file name="HTMLPurifier/HTMLModule/SafeScripting.php"> <file name="HTMLPurifier/HTMLModule/SafeScripting.php">
<line>22</line> <line>17</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Nofollow"> <directive id="HTML.Nofollow">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>268</line> <line>234</line>
</file> </file>
</directive> </directive>
<directive id="HTML.TargetBlank"> <directive id="HTML.TargetBlank">
<file name="HTMLPurifier/HTMLModuleManager.php"> <file name="HTMLPurifier/HTMLModuleManager.php">
<line>271</line> <line>237</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> </file>
</directive> </directive>
<directive id="Attr.IDBlacklist"> <directive id="Attr.IDBlacklist">
<file name="HTMLPurifier/IDAccumulator.php"> <file name="HTMLPurifier/IDAccumulator.php">
<line>27</line> <line>26</line>
</file> </file>
</directive> </directive>
<directive id="Core.Language"> <directive id="Core.Language">
<file name="HTMLPurifier/LanguageFactory.php"> <file name="HTMLPurifier/LanguageFactory.php">
<line>93</line> <line>88</line>
</file> </file>
</directive> </directive>
<directive id="Core.LexerImpl"> <directive id="Core.LexerImpl">
<file name="HTMLPurifier/Lexer.php"> <file name="HTMLPurifier/Lexer.php">
<line>85</line> <line>76</line>
</file> </file>
</directive> </directive>
<directive id="Core.MaintainLineNumbers"> <directive id="Core.MaintainLineNumbers">
<file name="HTMLPurifier/Lexer.php"> <file name="HTMLPurifier/Lexer.php">
<line>89</line> <line>80</line>
</file> </file>
<file name="HTMLPurifier/Lexer/DirectLex.php"> <file name="HTMLPurifier/Lexer/DirectLex.php">
<line>62</line> <line>48</line>
</file>
</directive>
<directive id="Core.LegacyEntityDecoder">
<file name="HTMLPurifier/Lexer.php">
<line>220</line>
<line>326</line>
</file> </file>
</directive> </directive>
<directive id="Core.ConvertDocumentToFragment"> <directive id="Core.ConvertDocumentToFragment">
<file name="HTMLPurifier/Lexer.php"> <file name="HTMLPurifier/Lexer.php">
<line>313</line> <line>282</line>
</file> </file>
</directive> </directive>
<directive id="Core.RemoveProcessingInstructions"> <directive id="Core.RemoveProcessingInstructions">
<file name="HTMLPurifier/Lexer.php"> <file name="HTMLPurifier/Lexer.php">
<line>336</line> <line>303</line>
</file>
</directive>
<directive id="Core.HiddenElements">
<file name="HTMLPurifier/Lexer.php">
<line>340</line>
</file>
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>36</line>
</file>
</directive>
<directive id="Core.AggressivelyRemoveScript">
<file name="HTMLPurifier/Lexer.php">
<line>341</line>
</file>
</directive>
<directive id="Core.RemoveScriptContents">
<file name="HTMLPurifier/Lexer.php">
<line>342</line>
</file>
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>35</line>
</file> </file>
</directive> </directive>
<directive id="URI."> <directive id="URI.">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>65</line> <line>60</line>
</file> </file>
<file name="HTMLPurifier/URIFilter/Munge.php"> <file name="HTMLPurifier/URIFilter/Munge.php">
<line>46</line> <line>12</line>
</file> </file>
</directive> </directive>
<directive id="URI.Host"> <directive id="URI.Host">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>76</line> <line>70</line>
</file> </file>
<file name="HTMLPurifier/URIScheme.php"> <file name="HTMLPurifier/URIScheme.php">
<line>89</line> <line>81</line>
</file> </file>
</directive> </directive>
<directive id="URI.Base"> <directive id="URI.Base">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>77</line> <line>71</line>
</file> </file>
</directive> </directive>
<directive id="URI.DefaultScheme"> <directive id="URI.DefaultScheme">
<file name="HTMLPurifier/URIDefinition.php"> <file name="HTMLPurifier/URIDefinition.php">
<line>84</line> <line>78</line>
</file> </file>
</directive> </directive>
<directive id="URI.AllowedSchemes"> <directive id="URI.AllowedSchemes">
<file name="HTMLPurifier/URISchemeRegistry.php"> <file name="HTMLPurifier/URISchemeRegistry.php">
<line>48</line> <line>41</line>
</file> </file>
</directive> </directive>
<directive id="URI.OverrideAllowedSchemes"> <directive id="URI.OverrideAllowedSchemes">
<file name="HTMLPurifier/URISchemeRegistry.php"> <file name="HTMLPurifier/URISchemeRegistry.php">
<line>49</line> <line>42</line>
</file>
</directive>
<directive id="CSS.AllowDuplicates">
<file name="HTMLPurifier/AttrDef/CSS.php">
<line>28</line>
</file> </file>
</directive> </directive>
<directive id="URI.Disable"> <directive id="URI.Disable">
<file name="HTMLPurifier/AttrDef/URI.php"> <file name="HTMLPurifier/AttrDef/URI.php">
<line>47</line> <line>28</line>
</file> </file>
</directive> </directive>
<directive id="Core.ColorKeywords"> <directive id="Core.ColorKeywords">
<file name="HTMLPurifier/AttrDef/CSS/Color.php"> <file name="HTMLPurifier/AttrDef/CSS/Color.php">
<line>29</line> <line>12</line>
</file> </file>
<file name="HTMLPurifier/AttrDef/HTML/Color.php"> <file name="HTMLPurifier/AttrDef/HTML/Color.php">
<line>19</line> <line>12</line>
</file> </file>
</directive> </directive>
<directive id="CSS.AllowedFonts"> <directive id="CSS.AllowedFonts">
<file name="HTMLPurifier/AttrDef/CSS/FontFamily.php"> <file name="HTMLPurifier/AttrDef/CSS/FontFamily.php">
<line>62</line> <line>50</line>
</file> </file>
</directive> </directive>
<directive id="Attr.AllowedClasses"> <directive id="Attr.AllowedClasses">
<file name="HTMLPurifier/AttrDef/HTML/Class.php"> <file name="HTMLPurifier/AttrDef/HTML/Class.php">
<line>33</line> <line>18</line>
</file> </file>
</directive> </directive>
<directive id="Attr.ForbiddenClasses"> <directive id="Attr.ForbiddenClasses">
<file name="HTMLPurifier/AttrDef/HTML/Class.php"> <file name="HTMLPurifier/AttrDef/HTML/Class.php">
<line>34</line> <line>19</line>
</file> </file>
</directive> </directive>
<directive id="Attr.AllowedFrameTargets"> <directive id="Attr.AllowedFrameTargets">
<file name="HTMLPurifier/AttrDef/HTML/FrameTarget.php"> <file name="HTMLPurifier/AttrDef/HTML/FrameTarget.php">
<line>32</line> <line>15</line>
</file> </file>
</directive> </directive>
<directive id="Attr.EnableID"> <directive id="Attr.EnableID">
<file name="HTMLPurifier/AttrDef/HTML/ID.php"> <file name="HTMLPurifier/AttrDef/HTML/ID.php">
<line>41</line> <line>30</line>
</file> </file>
</directive> </directive>
<directive id="Attr.IDPrefix"> <directive id="Attr.IDPrefix">
<file name="HTMLPurifier/AttrDef/HTML/ID.php"> <file name="HTMLPurifier/AttrDef/HTML/ID.php">
<line>51</line> <line>36</line>
</file> </file>
</directive> </directive>
<directive id="Attr.IDPrefixLocal"> <directive id="Attr.IDPrefixLocal">
<file name="HTMLPurifier/AttrDef/HTML/ID.php"> <file name="HTMLPurifier/AttrDef/HTML/ID.php">
<line>53</line> <line>38</line>
<line>58</line> <line>41</line>
</file>
</directive>
<directive id="Attr.ID.HTML5">
<file name="HTMLPurifier/AttrDef/HTML/ID.php">
<line>75</line>
</file> </file>
</directive> </directive>
<directive id="Attr.IDBlacklistRegexp"> <directive id="Attr.IDBlacklistRegexp">
<file name="HTMLPurifier/AttrDef/HTML/ID.php"> <file name="HTMLPurifier/AttrDef/HTML/ID.php">
<line>97</line> <line>64</line>
</file> </file>
</directive> </directive>
<directive id="Attr."> <directive id="Attr.">
<file name="HTMLPurifier/AttrDef/HTML/LinkTypes.php"> <file name="HTMLPurifier/AttrDef/HTML/LinkTypes.php">
<line>46</line> <line>30</line>
</file>
</directive>
<directive id="Core.AllowHostnameUnderscore">
<file name="HTMLPurifier/AttrDef/URI/Host.php">
<line>71</line>
</file> </file>
</directive> </directive>
<directive id="Core.EnableIDNA"> <directive id="Core.EnableIDNA">
<file name="HTMLPurifier/AttrDef/URI/Host.php"> <file name="HTMLPurifier/AttrDef/URI/Host.php">
<line>103</line> <line>67</line>
</file> </file>
</directive> </directive>
<directive id="Attr.DefaultTextDir"> <directive id="Attr.DefaultTextDir">
<file name="HTMLPurifier/AttrTransform/BdoDir.php"> <file name="HTMLPurifier/AttrTransform/BdoDir.php">
<line>22</line> <line>13</line>
</file> </file>
</directive> </directive>
<directive id="Core.RemoveInvalidImg"> <directive id="Core.RemoveInvalidImg">
<file name="HTMLPurifier/AttrTransform/ImgRequired.php"> <file name="HTMLPurifier/AttrTransform/ImgRequired.php">
<line>24</line> <line>18</line>
</file> </file>
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php"> <file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>27</line> <line>20</line>
</file> </file>
</directive> </directive>
<directive id="Attr.DefaultInvalidImage"> <directive id="Attr.DefaultInvalidImage">
<file name="HTMLPurifier/AttrTransform/ImgRequired.php"> <file name="HTMLPurifier/AttrTransform/ImgRequired.php">
<line>27</line> <line>19</line>
</file> </file>
</directive> </directive>
<directive id="Attr.DefaultImageAlt"> <directive id="Attr.DefaultImageAlt">
<file name="HTMLPurifier/AttrTransform/ImgRequired.php"> <file name="HTMLPurifier/AttrTransform/ImgRequired.php">
<line>33</line> <line>25</line>
</file> </file>
</directive> </directive>
<directive id="Attr.DefaultInvalidImageAlt"> <directive id="Attr.DefaultInvalidImageAlt">
<file name="HTMLPurifier/AttrTransform/ImgRequired.php"> <file name="HTMLPurifier/AttrTransform/ImgRequired.php">
<line>40</line> <line>33</line>
</file> </file>
</directive> </directive>
<directive id="HTML.Attr.Name.UseCDATA"> <directive id="HTML.Attr.Name.UseCDATA">
<file name="HTMLPurifier/AttrTransform/Name.php"> <file name="HTMLPurifier/AttrTransform/Name.php">
<line>18</line> <line>11</line>
</file> </file>
<file name="HTMLPurifier/HTMLModule/Name.php"> <file name="HTMLPurifier/HTMLModule/Name.php">
<line>19</line> <line>13</line>
</file> </file>
</directive> </directive>
<directive id="HTML.FlashAllowFullScreen"> <directive id="HTML.FlashAllowFullScreen">
<file name="HTMLPurifier/AttrTransform/SafeParam.php"> <file name="HTMLPurifier/AttrTransform/SafeParam.php">
<line>58</line> <line>38</line>
</file>
</directive>
<directive id="Core.EscapeInvalidChildren">
<file name="HTMLPurifier/ChildDef/Required.php">
<line>62</line>
</file> </file>
</directive> </directive>
<directive id="Cache.SerializerPath"> <directive id="Cache.SerializerPath">
<file name="HTMLPurifier/DefinitionCache/Serializer.php"> <file name="HTMLPurifier/DefinitionCache/Serializer.php">
<line>185</line> <line>91</line>
</file> </file>
</directive> </directive>
<directive id="Cache.SerializerPermissions"> <directive id="Cache.SerializerPermissions">
<file name="HTMLPurifier/DefinitionCache/Serializer.php"> <file name="HTMLPurifier/DefinitionCache/Serializer.php">
<line>202</line> <line>107</line>
<line>218</line> <line>124</line>
</file> </file>
</directive> </directive>
<directive id="Filter.ExtractStyleBlocks.TidyImpl"> <directive id="Filter.ExtractStyleBlocks.TidyImpl">
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php"> <file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
<line>106</line> <line>55</line>
</file> </file>
</directive> </directive>
<directive id="Filter.ExtractStyleBlocks.Scope"> <directive id="Filter.ExtractStyleBlocks.Scope">
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php"> <file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
<line>137</line> <line>79</line>
</file> </file>
</directive> </directive>
<directive id="Filter.ExtractStyleBlocks.Escaping"> <directive id="Filter.ExtractStyleBlocks.Escaping">
<file name="HTMLPurifier/Filter/ExtractStyleBlocks.php"> <file name="HTMLPurifier/Filter/ExtractStyleBlocks.php">
<line>351</line> <line>277</line>
</file>
</directive>
<directive id="HTML.Forms">
<file name="HTMLPurifier/HTMLModule/Forms.php">
<line>31</line>
</file> </file>
</directive> </directive>
<directive id="HTML.SafeIframe"> <directive id="HTML.SafeIframe">
<file name="HTMLPurifier/HTMLModule/Iframe.php"> <file name="HTMLPurifier/HTMLModule/Iframe.php">
<line>28</line> <line>17</line>
</file> </file>
<file name="HTMLPurifier/URIFilter/SafeIframe.php"> <file name="HTMLPurifier/URIFilter/SafeIframe.php">
<line>48</line> <line>23</line>
</file> </file>
</directive> </directive>
<directive id="HTML.MaxImgLength"> <directive id="HTML.MaxImgLength">
<file name="HTMLPurifier/HTMLModule/Image.php"> <file name="HTMLPurifier/HTMLModule/Image.php">
<line>21</line> <line>14</line>
</file> </file>
<file name="HTMLPurifier/HTMLModule/SafeEmbed.php"> <file name="HTMLPurifier/HTMLModule/SafeEmbed.php">
<line>18</line> <line>13</line>
</file> </file>
<file name="HTMLPurifier/HTMLModule/SafeObject.php"> <file name="HTMLPurifier/HTMLModule/SafeObject.php">
<line>24</line> <line>19</line>
</file> </file>
</directive> </directive>
<directive id="HTML.TidyLevel"> <directive id="HTML.TidyLevel">
<file name="HTMLPurifier/HTMLModule/Tidy.php"> <file name="HTMLPurifier/HTMLModule/Tidy.php">
<line>50</line> <line>45</line>
</file> </file>
</directive> </directive>
<directive id="HTML.TidyAdd"> <directive id="HTML.TidyAdd">
<file name="HTMLPurifier/HTMLModule/Tidy.php"> <file name="HTMLPurifier/HTMLModule/Tidy.php">
<line>54</line> <line>49</line>
</file> </file>
</directive> </directive>
<directive id="HTML.TidyRemove"> <directive id="HTML.TidyRemove">
<file name="HTMLPurifier/HTMLModule/Tidy.php"> <file name="HTMLPurifier/HTMLModule/Tidy.php">
<line>55</line> <line>50</line>
</file> </file>
</directive> </directive>
<directive id="AutoFormat.PurifierLinkify.DocURL"> <directive id="AutoFormat.PurifierLinkify.DocURL">
<file name="HTMLPurifier/Injector/PurifierLinkify.php"> <file name="HTMLPurifier/Injector/PurifierLinkify.php">
<line>31</line> <line>15</line>
</file> </file>
</directive> </directive>
<directive id="AutoFormat.RemoveEmpty.RemoveNbsp"> <directive id="AutoFormat.RemoveEmpty.RemoveNbsp">
<file name="HTMLPurifier/Injector/RemoveEmpty.php"> <file name="HTMLPurifier/Injector/RemoveEmpty.php">
<line>46</line> <line>15</line>
</file> </file>
</directive> </directive>
<directive id="AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions"> <directive id="AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions">
<file name="HTMLPurifier/Injector/RemoveEmpty.php"> <file name="HTMLPurifier/Injector/RemoveEmpty.php">
<line>47</line> <line>16</line>
</file>
</directive>
<directive id="AutoFormat.RemoveEmpty.Predicate">
<file name="HTMLPurifier/Injector/RemoveEmpty.php">
<line>48</line>
</file> </file>
</directive> </directive>
<directive id="Core.AggressivelyFixLt"> <directive id="Core.AggressivelyFixLt">
<file name="HTMLPurifier/Lexer/DOMLex.php"> <file name="HTMLPurifier/Lexer/DOMLex.php">
<line>54</line> <line>44</line>
</file>
</directive>
<directive id="Core.AllowParseManyTags">
<file name="HTMLPurifier/Lexer/DOMLex.php">
<line>72</line>
</file>
</directive>
<directive id="Core.RemoveBlanks">
<file name="HTMLPurifier/Lexer/DOMLex.php">
<line>75</line>
</file> </file>
</directive> </directive>
<directive id="Core.DirectLexLineNumberSyncInterval"> <directive id="Core.DirectLexLineNumberSyncInterval">
<file name="HTMLPurifier/Lexer/DirectLex.php"> <file name="HTMLPurifier/Lexer/DirectLex.php">
<line>84</line> <line>70</line>
</file> </file>
</directive> </directive>
<directive id="Core.DisableExcludes"> <directive id="Core.DisableExcludes">
<file name="HTMLPurifier/Strategy/FixNesting.php"> <file name="HTMLPurifier/Strategy/FixNesting.php">
<line>54</line> <line>57</line>
</file> </file>
</directive> </directive>
<directive id="Core.EscapeInvalidTags"> <directive id="Core.EscapeInvalidTags">
<file name="HTMLPurifier/Strategy/MakeWellFormed.php"> <file name="HTMLPurifier/Strategy/MakeWellFormed.php">
<line>72</line> <line>53</line>
</file> </file>
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php"> <file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>26</line> <line>19</line>
</file> </file>
</directive> </directive>
<directive id="HTML.AllowedComments"> <directive id="HTML.AllowedComments">
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php"> <file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>31</line> <line>24</line>
</file> </file>
</directive> </directive>
<directive id="HTML.AllowedCommentsRegexp"> <directive id="HTML.AllowedCommentsRegexp">
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php"> <file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>32</line> <line>25</line>
</file>
</directive>
<directive id="Core.RemoveScriptContents">
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>28</line>
</file>
</directive>
<directive id="Core.HiddenElements">
<file name="HTMLPurifier/Strategy/RemoveForeignElements.php">
<line>29</line>
</file> </file>
</directive> </directive>
<directive id="URI.HostBlacklist"> <directive id="URI.HostBlacklist">
<file name="HTMLPurifier/URIFilter/HostBlacklist.php"> <file name="HTMLPurifier/URIFilter/HostBlacklist.php">
<line>25</line> <line>12</line>
</file> </file>
</directive> </directive>
<directive id="URI.MungeResources"> <directive id="URI.MungeResources">
<file name="HTMLPurifier/URIFilter/Munge.php"> <file name="HTMLPurifier/URIFilter/Munge.php">
<line>48</line> <line>14</line>
</file> </file>
</directive> </directive>
<directive id="URI.MungeSecretKey"> <directive id="URI.MungeSecretKey">
<file name="HTMLPurifier/URIFilter/Munge.php"> <file name="HTMLPurifier/URIFilter/Munge.php">
<line>49</line> <line>15</line>
</file> </file>
</directive> </directive>
<directive id="URI.SafeIframeRegexp"> <directive id="URI.SafeIframeRegexp">
<file name="HTMLPurifier/URIFilter/SafeIframe.php"> <file name="HTMLPurifier/URIFilter/SafeIframe.php">
<line>35</line> <line>18</line>
</file> </file>
</directive> </directive>
</usage> </usage>

View File

@@ -25,6 +25,5 @@ URIScheme - needs to have callable generic checks
mailto - doesn't validate emails, doesn't validate querystring mailto - doesn't validate emails, doesn't validate querystring
news - doesn't validate opaque path news - doesn't validate opaque path
nntp - doesn't constrain 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 vim: et sw=4 sts=4

View File

@@ -75,7 +75,6 @@ Core is the potpourri of directives, mostly regarding some minor behavioral
tweaks for HTML handling abilities. tweaks for HTML handling abilities.
AggressivelyFixLt AggressivelyFixLt
AllowParseManyTags
ConvertDocumentToFragment ConvertDocumentToFragment
DirectLexLineNumberSyncInterval DirectLexLineNumberSyncInterval
LexerImpl LexerImpl

View File

@@ -228,7 +228,7 @@ Test.Example</pre>
</tr> </tr>
<tr> <tr>
<td>mixed</td> <td>mixed</td>
<td>new stdClass</td> <td>new stdclass</td>
<td>Any PHP variable is fine</td> <td>Any PHP variable is fine</td>
</tr> </tr>
</tbody> </tbody>

View File

@@ -11,8 +11,7 @@ class ConfigDoc_HTMLXSLTProcessor
*/ */
protected $xsltProcessor; protected $xsltProcessor;
public function __construct($proc = false) public function __construct($proc = false) {
{
if ($proc === false) $proc = new XSLTProcessor(); if ($proc === false) $proc = new XSLTProcessor();
$this->xsltProcessor = $proc; $this->xsltProcessor = $proc;
} }
@@ -20,8 +19,7 @@ class ConfigDoc_HTMLXSLTProcessor
/** /**
* @note Allows a string $xsl filename to be passed * @note Allows a string $xsl filename to be passed
*/ */
public function importStylesheet($xsl) public function importStylesheet($xsl) {
{
if (is_string($xsl)) { if (is_string($xsl)) {
$xsl_file = $xsl; $xsl_file = $xsl;
$xsl = new DOMDocument(); $xsl = new DOMDocument();
@@ -36,8 +34,7 @@ class ConfigDoc_HTMLXSLTProcessor
* @return string HTML output * @return string HTML output
* @todo Rename to transformToXHTML, as transformToHTML is misleading * @todo Rename to transformToXHTML, as transformToHTML is misleading
*/ */
public function transformToHTML($xml) public function transformToHTML($xml) {
{
if (is_string($xml)) { if (is_string($xml)) {
$dom = new DOMDocument(); $dom = new DOMDocument();
$dom->load($xml); $dom->load($xml);
@@ -71,8 +68,7 @@ class ConfigDoc_HTMLXSLTProcessor
* Bulk sets parameters for the XSL stylesheet * Bulk sets parameters for the XSL stylesheet
* @param array $options Associative array of options to set * @param array $options Associative array of options to set
*/ */
public function setParameters($options) public function setParameters($options) {
{
foreach ($options as $name => $value) { foreach ($options as $name => $value) {
$this->xsltProcessor->setParameter('', $name, $value); $this->xsltProcessor->setParameter('', $name, $value);
} }
@@ -81,8 +77,7 @@ class ConfigDoc_HTMLXSLTProcessor
/** /**
* Forward any other calls to the XSLT processor * 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); call_user_func_array(array($this->xsltProcessor, $name), $arguments);
} }

View File

@@ -15,8 +15,7 @@ class FSTools
/** /**
* Returns a global instance of FSTools * Returns a global instance of FSTools
*/ */
public static function singleton() static public function singleton() {
{
if (empty(FSTools::$singleton)) FSTools::$singleton = new FSTools(); if (empty(FSTools::$singleton)) FSTools::$singleton = new FSTools();
return FSTools::$singleton; return FSTools::$singleton;
} }
@@ -25,8 +24,7 @@ class FSTools
* Sets our global singleton to something else; useful for overloading * Sets our global singleton to something else; useful for overloading
* functions. * functions.
*/ */
public static function setSingleton($singleton) static public function setSingleton($singleton) {
{
FSTools::$singleton = $singleton; FSTools::$singleton = $singleton;
} }
@@ -35,8 +33,7 @@ class FSTools
* @param string $folder Name of folder to create * @param string $folder Name of folder to create
* @note Adapted from the PHP manual comment 76612 * @note Adapted from the PHP manual comment 76612
*/ */
public function mkdirr($folder) public function mkdirr($folder) {
{
$folders = preg_split("#[\\\\/]#", $folder); $folders = preg_split("#[\\\\/]#", $folder);
$base = ''; $base = '';
for($i = 0, $c = count($folders); $i < $c; $i++) { for($i = 0, $c = count($folders); $i < $c; $i++) {
@@ -60,8 +57,7 @@ class FSTools
* so that copied files, if PHP, have includes removed * so that copied files, if PHP, have includes removed
* @note Adapted from http://aidanlister.com/repos/v/function.copyr.php * @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 // Simple copy for a file
if (is_file($source)) { if (is_file($source)) {
return $this->copy($source, $dest); return $this->copy($source, $dest);
@@ -96,8 +92,7 @@ class FSTools
* ignore hidden files, unreadable files, etc. This function * ignore hidden files, unreadable files, etc. This function
* applies to copyr(). * applies to copyr().
*/ */
public function copyable($file) public function copyable($file) {
{
return true; return true;
} }
@@ -136,8 +131,7 @@ class FSTools
/** /**
* Recursively globs a directory. * Recursively globs a directory.
*/ */
public function globr($dir, $pattern, $flags = 0) public function globr($dir, $pattern, $flags = NULL) {
{
$files = $this->glob("$dir/$pattern", $flags); $files = $this->glob("$dir/$pattern", $flags);
if ($files === false) $files = array(); if ($files === false) $files = array();
$sub_dirs = $this->glob("$dir/*", GLOB_ONLYDIR); $sub_dirs = $this->glob("$dir/*", GLOB_ONLYDIR);
@@ -154,8 +148,7 @@ class FSTools
* @warning This function will not work for functions that need * @warning This function will not work for functions that need
* to pass references; manually define a stub function for those. * 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); return call_user_func_array($name, $args);
} }

View File

@@ -23,8 +23,7 @@ class FSTools_File
* Filename of file you wish to instantiate. * Filename of file you wish to instantiate.
* @note This file need not exist * @note This file need not exist
*/ */
public function __construct($name, $fs = false) public function __construct($name, $fs = false) {
{
$this->name = $name; $this->name = $name;
$this->fs = $fs ? $fs : FSTools::singleton(); $this->fs = $fs ? $fs : FSTools::singleton();
} }
@@ -39,32 +38,27 @@ class FSTools_File
* Retrieves the contents of a file * Retrieves the contents of a file
* @todo Throw an exception if file doesn't exist * @todo Throw an exception if file doesn't exist
*/ */
public function get() public function get() {
{
return $this->fs->file_get_contents($this->name); return $this->fs->file_get_contents($this->name);
} }
/** Writes contents to a file, creates new file if necessary */ /** 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); return $this->fs->file_put_contents($this->name, $contents);
} }
/** Deletes the file */ /** Deletes the file */
public function delete() public function delete() {
{
return $this->fs->unlink($this->name); return $this->fs->unlink($this->name);
} }
/** Returns true if file exists and is a file. */ /** Returns true if file exists and is a file. */
public function exists() public function exists() {
{
return $this->fs->is_file($this->name); return $this->fs->is_file($this->name);
} }
/** Returns last file modification time */ /** Returns last file modification time */
public function getMTime() public function getMTime() {
{
return $this->fs->filemtime($this->name); return $this->fs->filemtime($this->name);
} }
@@ -73,22 +67,19 @@ class FSTools_File
* @note We ignore errors because of some weird owner trickery due * @note We ignore errors because of some weird owner trickery due
* to SVN duality * to SVN duality
*/ */
public function chmod($octal_code) public function chmod($octal_code) {
{
return @$this->fs->chmod($this->name, $octal_code); return @$this->fs->chmod($this->name, $octal_code);
} }
/** Opens file's handle */ /** Opens file's handle */
public function open($mode) public function open($mode) {
{
if ($this->handle) $this->close(); if ($this->handle) $this->close();
$this->handle = $this->fs->fopen($this->name, $mode); $this->handle = $this->fs->fopen($this->name, $mode);
return true; return true;
} }
/** Closes file's handle */ /** Closes file's handle */
public function close() public function close() {
{
if (!$this->handle) return false; if (!$this->handle) return false;
$status = $this->fs->fclose($this->handle); $status = $this->fs->fclose($this->handle);
$this->handle = false; $this->handle = false;
@@ -96,43 +87,37 @@ class FSTools_File
} }
/** Retrieves a line from an open file, with optional max length $length */ /** 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 (!$this->handle) $this->open('r');
if ($length === null) return $this->fs->fgets($this->handle); if ($length === null) return $this->fs->fgets($this->handle);
else return $this->fs->fgets($this->handle, $length); else return $this->fs->fgets($this->handle, $length);
} }
/** Retrieves a character from an open file */ /** Retrieves a character from an open file */
public function getChar() public function getChar() {
{
if (!$this->handle) $this->open('r'); if (!$this->handle) $this->open('r');
return $this->fs->fgetc($this->handle); return $this->fs->fgetc($this->handle);
} }
/** Retrieves an $length bytes of data from an open data */ /** Retrieves an $length bytes of data from an open data */
public function read($length) public function read($length) {
{
if (!$this->handle) $this->open('r'); if (!$this->handle) $this->open('r');
return $this->fs->fread($this->handle, $length); return $this->fs->fread($this->handle, $length);
} }
/** Writes to an open file */ /** Writes to an open file */
public function put($string) public function put($string) {
{
if (!$this->handle) $this->open('a'); if (!$this->handle) $this->open('a');
return $this->fs->fwrite($this->handle, $string); return $this->fs->fwrite($this->handle, $string);
} }
/** Returns TRUE if the end of the file has been reached */ /** Returns TRUE if the end of the file has been reached */
public function eof() public function eof() {
{
if (!$this->handle) return true; if (!$this->handle) return true;
return $this->fs->feof($this->handle); return $this->fs->feof($this->handle);
} }
public function __destruct() public function __destruct() {
{
if ($this->handle) $this->close(); if ($this->handle) $this->close();
} }

View File

@@ -1,15 +0,0 @@
<?php
/**
* @file
* Legacy autoloader for systems lacking spl_autoload_register
*
* Must be separate to prevent deprecation warning on PHP 7.2
*/
function __autoload($class)
{
return HTMLPurifierExtras::autoload($class);
}
// vim: et sw=4 sts=4

View File

@@ -17,7 +17,9 @@ if (function_exists('spl_autoload_register')) {
spl_autoload_register('__autoload'); spl_autoload_register('__autoload');
} }
} elseif (!function_exists('__autoload')) { } elseif (!function_exists('__autoload')) {
require dirname(__FILE__) . '/HTMLPurifierExtras.autoload-legacy.php'; function __autoload($class) {
return HTMLPurifierExtras::autoload($class);
}
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,16 +7,14 @@
class HTMLPurifierExtras class HTMLPurifierExtras
{ {
public static function autoload($class) public static function autoload($class) {
{
$path = HTMLPurifierExtras::getPath($class); $path = HTMLPurifierExtras::getPath($class);
if (!$path) return false; if (!$path) return false;
require $path; require $path;
return true; return true;
} }
public static function getPath($class) public static function getPath($class) {
{
if ( if (
strncmp('FSTools', $class, 7) !== 0 && strncmp('FSTools', $class, 7) !== 0 &&
strncmp('ConfigDoc', $class, 9) !== 0 strncmp('ConfigDoc', $class, 9) !== 0

View File

@@ -1,14 +0,0 @@
<?php
/**
* @file
* Legacy autoloader for systems lacking spl_autoload_register
*
*/
spl_autoload_register(function($class)
{
return HTMLPurifier_Bootstrap::autoload($class);
});
// vim: et sw=4 sts=4

View File

@@ -14,10 +14,11 @@ if (function_exists('spl_autoload_register') && function_exists('spl_autoload_un
spl_autoload_register('__autoload'); spl_autoload_register('__autoload');
} }
} elseif (!function_exists('__autoload')) { } elseif (!function_exists('__autoload')) {
require dirname(__FILE__) . '/HTMLPurifier.autoload-legacy.php'; function __autoload($class) {
return HTMLPurifier_Bootstrap::autoload($class);
}
} }
// phpcs:ignore PHPCompatibility.IniDirectives.RemovedIniDirectives.zend_ze1_compatibility_modeRemoved
if (ini_get('zend.ze1_compatibility_mode')) { 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); trigger_error("HTML Purifier is not compatible with zend.ze1_compatibility_mode; please turn it off", E_USER_ERROR);
} }

View File

@@ -1,4 +1,4 @@
<?php <?php
if (!defined('HTMLPURIFIER_PREFIX')) { if (!defined('HTMLPURIFIER_PREFIX')) {
define('HTMLPURIFIER_PREFIX', dirname(__FILE__)); define('HTMLPURIFIER_PREFIX', __DIR__);
} }

View File

@@ -8,13 +8,11 @@
/** /**
* Purify HTML. * Purify HTML.
* @param string $html String HTML to purify * @param $html String HTML to purify
* @param mixed $config Configuration to use, can be any value accepted by * @param $config Configuration to use, can be any value accepted by
* HTMLPurifier_Config::create() * HTMLPurifier_Config::create()
* @return string
*/ */
function HTMLPurifier($html, $config = null) function HTMLPurifier($html, $config = null) {
{
static $purifier = false; static $purifier = false;
if (!$purifier) { if (!$purifier) {
$purifier = new HTMLPurifier(); $purifier = new HTMLPurifier();

View File

@@ -7,7 +7,7 @@
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS * 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. * FILE, changes will be overwritten the next time the script is run.
* *
* @version 4.18.0 * @version 4.5.0
* *
* @warning * @warning
* You must *not* include any other HTML Purifier files before this file, * You must *not* include any other HTML Purifier files before this file,
@@ -19,7 +19,8 @@
*/ */
require 'HTMLPurifier.php'; require 'HTMLPurifier.php';
require 'HTMLPurifier/Arborize.php'; require 'HTMLPurifier/Array.php';
require 'HTMLPurifier/ArrayNode.php';
require 'HTMLPurifier/AttrCollections.php'; require 'HTMLPurifier/AttrCollections.php';
require 'HTMLPurifier/AttrDef.php'; require 'HTMLPurifier/AttrDef.php';
require 'HTMLPurifier/AttrTransform.php'; require 'HTMLPurifier/AttrTransform.php';
@@ -37,6 +38,7 @@ require 'HTMLPurifier/DefinitionCache.php';
require 'HTMLPurifier/DefinitionCacheFactory.php'; require 'HTMLPurifier/DefinitionCacheFactory.php';
require 'HTMLPurifier/Doctype.php'; require 'HTMLPurifier/Doctype.php';
require 'HTMLPurifier/DoctypeRegistry.php'; require 'HTMLPurifier/DoctypeRegistry.php';
require 'HTMLPurifier/DoublyLinkedList.php';
require 'HTMLPurifier/ElementDef.php'; require 'HTMLPurifier/ElementDef.php';
require 'HTMLPurifier/Encoder.php'; require 'HTMLPurifier/Encoder.php';
require 'HTMLPurifier/EntityLookup.php'; require 'HTMLPurifier/EntityLookup.php';
@@ -55,11 +57,9 @@ require 'HTMLPurifier/Language.php';
require 'HTMLPurifier/LanguageFactory.php'; require 'HTMLPurifier/LanguageFactory.php';
require 'HTMLPurifier/Length.php'; require 'HTMLPurifier/Length.php';
require 'HTMLPurifier/Lexer.php'; require 'HTMLPurifier/Lexer.php';
require 'HTMLPurifier/Node.php';
require 'HTMLPurifier/PercentEncoder.php'; require 'HTMLPurifier/PercentEncoder.php';
require 'HTMLPurifier/PropertyList.php'; require 'HTMLPurifier/PropertyList.php';
require 'HTMLPurifier/PropertyListIterator.php'; require 'HTMLPurifier/PropertyListIterator.php';
require 'HTMLPurifier/Queue.php';
require 'HTMLPurifier/Strategy.php'; require 'HTMLPurifier/Strategy.php';
require 'HTMLPurifier/StringHash.php'; require 'HTMLPurifier/StringHash.php';
require 'HTMLPurifier/StringHashParser.php'; require 'HTMLPurifier/StringHashParser.php';
@@ -75,7 +75,6 @@ require 'HTMLPurifier/URISchemeRegistry.php';
require 'HTMLPurifier/UnitConverter.php'; require 'HTMLPurifier/UnitConverter.php';
require 'HTMLPurifier/VarParser.php'; require 'HTMLPurifier/VarParser.php';
require 'HTMLPurifier/VarParserException.php'; require 'HTMLPurifier/VarParserException.php';
require 'HTMLPurifier/Zipper.php';
require 'HTMLPurifier/AttrDef/CSS.php'; require 'HTMLPurifier/AttrDef/CSS.php';
require 'HTMLPurifier/AttrDef/Clone.php'; require 'HTMLPurifier/AttrDef/Clone.php';
require 'HTMLPurifier/AttrDef/Enum.php'; require 'HTMLPurifier/AttrDef/Enum.php';
@@ -101,14 +100,12 @@ require 'HTMLPurifier/AttrDef/CSS/Length.php';
require 'HTMLPurifier/AttrDef/CSS/ListStyle.php'; require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
require 'HTMLPurifier/AttrDef/CSS/Multiple.php'; require 'HTMLPurifier/AttrDef/CSS/Multiple.php';
require 'HTMLPurifier/AttrDef/CSS/Percentage.php'; require 'HTMLPurifier/AttrDef/CSS/Percentage.php';
require 'HTMLPurifier/AttrDef/CSS/Ratio.php';
require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php'; require 'HTMLPurifier/AttrDef/CSS/TextDecoration.php';
require 'HTMLPurifier/AttrDef/CSS/URI.php'; require 'HTMLPurifier/AttrDef/CSS/URI.php';
require 'HTMLPurifier/AttrDef/HTML/Bool.php'; require 'HTMLPurifier/AttrDef/HTML/Bool.php';
require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php'; require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php';
require 'HTMLPurifier/AttrDef/HTML/Class.php'; require 'HTMLPurifier/AttrDef/HTML/Class.php';
require 'HTMLPurifier/AttrDef/HTML/Color.php'; require 'HTMLPurifier/AttrDef/HTML/Color.php';
require 'HTMLPurifier/AttrDef/HTML/ContentEditable.php';
require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php'; require 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
require 'HTMLPurifier/AttrDef/HTML/ID.php'; require 'HTMLPurifier/AttrDef/HTML/ID.php';
require 'HTMLPurifier/AttrDef/HTML/Pixels.php'; require 'HTMLPurifier/AttrDef/HTML/Pixels.php';
@@ -139,8 +136,6 @@ require 'HTMLPurifier/AttrTransform/SafeObject.php';
require 'HTMLPurifier/AttrTransform/SafeParam.php'; require 'HTMLPurifier/AttrTransform/SafeParam.php';
require 'HTMLPurifier/AttrTransform/ScriptRequired.php'; require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
require 'HTMLPurifier/AttrTransform/TargetBlank.php'; require 'HTMLPurifier/AttrTransform/TargetBlank.php';
require 'HTMLPurifier/AttrTransform/TargetNoopener.php';
require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php';
require 'HTMLPurifier/AttrTransform/Textarea.php'; require 'HTMLPurifier/AttrTransform/Textarea.php';
require 'HTMLPurifier/ChildDef/Chameleon.php'; require 'HTMLPurifier/ChildDef/Chameleon.php';
require 'HTMLPurifier/ChildDef/Custom.php'; require 'HTMLPurifier/ChildDef/Custom.php';
@@ -179,8 +174,6 @@ require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
require 'HTMLPurifier/HTMLModule/Tables.php'; require 'HTMLPurifier/HTMLModule/Tables.php';
require 'HTMLPurifier/HTMLModule/Target.php'; require 'HTMLPurifier/HTMLModule/Target.php';
require 'HTMLPurifier/HTMLModule/TargetBlank.php'; require 'HTMLPurifier/HTMLModule/TargetBlank.php';
require 'HTMLPurifier/HTMLModule/TargetNoopener.php';
require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php';
require 'HTMLPurifier/HTMLModule/Text.php'; require 'HTMLPurifier/HTMLModule/Text.php';
require 'HTMLPurifier/HTMLModule/Tidy.php'; require 'HTMLPurifier/HTMLModule/Tidy.php';
require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
@@ -199,9 +192,6 @@ require 'HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
require 'HTMLPurifier/Injector/SafeObject.php'; require 'HTMLPurifier/Injector/SafeObject.php';
require 'HTMLPurifier/Lexer/DOMLex.php'; require 'HTMLPurifier/Lexer/DOMLex.php';
require 'HTMLPurifier/Lexer/DirectLex.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/Composite.php';
require 'HTMLPurifier/Strategy/Core.php'; require 'HTMLPurifier/Strategy/Core.php';
require 'HTMLPurifier/Strategy/FixNesting.php'; require 'HTMLPurifier/Strategy/FixNesting.php';
@@ -231,6 +221,5 @@ require 'HTMLPurifier/URIScheme/https.php';
require 'HTMLPurifier/URIScheme/mailto.php'; require 'HTMLPurifier/URIScheme/mailto.php';
require 'HTMLPurifier/URIScheme/news.php'; require 'HTMLPurifier/URIScheme/news.php';
require 'HTMLPurifier/URIScheme/nntp.php'; require 'HTMLPurifier/URIScheme/nntp.php';
require 'HTMLPurifier/URIScheme/tel.php';
require 'HTMLPurifier/VarParser/Flexible.php'; require 'HTMLPurifier/VarParser/Flexible.php';
require 'HTMLPurifier/VarParser/Native.php'; require 'HTMLPurifier/VarParser/Native.php';

View File

@@ -7,8 +7,7 @@
require_once dirname(__FILE__) . '/HTMLPurifier.auto.php'; 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(); $config = HTMLPurifier_Config::createDefault();
$allowed_elements = array(); $allowed_elements = array();
$allowed_attributes = array(); $allowed_attributes = array();
@@ -20,6 +19,7 @@ function kses($string, $allowed_html, $allowed_protocols = null)
} }
$config->set('HTML.AllowedElements', $allowed_elements); $config->set('HTML.AllowedElements', $allowed_elements);
$config->set('HTML.AllowedAttributes', $allowed_attributes); $config->set('HTML.AllowedAttributes', $allowed_attributes);
$allowed_schemes = array();
if ($allowed_protocols !== null) { if ($allowed_protocols !== null) {
$config->set('URI.AllowedSchemes', $allowed_protocols); $config->set('URI.AllowedSchemes', $allowed_protocols);
} }

View File

@@ -19,7 +19,7 @@
*/ */
/* /*
HTML Purifier 4.18.0 - Standards Compliant HTML Filtering HTML Purifier 4.5.0 - Standards Compliant HTML Filtering
Copyright (C) 2006-2008 Edward Z. Yang Copyright (C) 2006-2008 Edward Z. Yang
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
@@ -54,97 +54,66 @@
class HTMLPurifier class HTMLPurifier
{ {
/** /** Version of HTML Purifier */
* Version of HTML Purifier. public $version = '4.5.0';
* @type string
*/
public $version = '4.18.0';
/** /** Constant with version of HTML Purifier */
* Constant with version of HTML Purifier. const VERSION = '4.5.0';
*/
const VERSION = '4.18.0';
/** /** Global configuration object */
* Global configuration object.
* @type HTMLPurifier_Config
*/
public $config; public $config;
/** /** Array of extra HTMLPurifier_Filter objects to run on HTML, for backwards compatibility */
* Array of extra filter objects to run on HTML,
* for backwards compatibility.
* @type HTMLPurifier_Filter[]
*/
private $filters = array(); private $filters = array();
/** /** Single instance of HTML Purifier */
* Single instance of HTML Purifier.
* @type HTMLPurifier
*/
private static $instance; private static $instance;
/** protected $strategy, $generator;
* @type HTMLPurifier_Strategy_Core
*/
protected $strategy;
/** /**
* @type HTMLPurifier_Generator * Resultant HTMLPurifier_Context of last run purification. Is an array
*/ * of contexts if the last called method was purifyArray().
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; public $context;
/** /**
* Initializes the purifier. * Initializes the purifier.
* * @param $config Optional HTMLPurifier_Config object for all instances of
* @param HTMLPurifier_Config|mixed $config Optional HTMLPurifier_Config object * the purifier, if omitted, a default configuration is
* for all instances of the purifier, if omitted, a default * supplied (which can be overridden on a per-use basis).
* configuration is supplied (which can be overridden on a
* per-use basis).
* The parameter can also be any type that * The parameter can also be any type that
* HTMLPurifier_Config::create() supports. * HTMLPurifier_Config::create() supports.
*/ */
public function __construct($config = null) public function __construct($config = null) {
{
$this->config = HTMLPurifier_Config::create($config); $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 * 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) public function addFilter($filter) {
{ trigger_error('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom', E_USER_WARNING);
trigger_error(
'HTMLPurifier->addFilter() is deprecated, use configuration directives' .
' in the Filter namespace or Filter.Custom',
E_USER_WARNING
);
$this->filters[] = $filter; $this->filters[] = $filter;
} }
/** /**
* Filters an HTML snippet/document to be XSS-free and standards-compliant. * Filters an HTML snippet/document to be XSS-free and standards-compliant.
* *
* @param string $html String of HTML to purify * @param $html String of HTML to purify
* @param HTMLPurifier_Config $config Config object for this operation, * @param $config HTMLPurifier_Config object for this operation, if omitted,
* if omitted, defaults to the config object specified during this * defaults to the config object specified during this
* object's construction. The parameter can also be any type * object's construction. The parameter can also be any type
* that HTMLPurifier_Config::create() supports. * 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 // :TODO: make the config merge in, instead of replace
$config = $config ? HTMLPurifier_Config::create($config) : $this->config; $config = $config ? HTMLPurifier_Config::create($config) : $this->config;
@@ -182,12 +151,8 @@ class HTMLPurifier
unset($filter_flags['Custom']); unset($filter_flags['Custom']);
$filters = array(); $filters = array();
foreach ($filter_flags as $filter => $flag) { foreach ($filter_flags as $filter => $flag) {
if (!$flag) { if (!$flag) continue;
continue; if (strpos($filter, '.') !== false) continue;
}
if (strpos($filter, '.') !== false) {
continue;
}
$class = "HTMLPurifier_Filter_$filter"; $class = "HTMLPurifier_Filter_$filter";
$filters[] = new $class; $filters[] = new $class;
} }
@@ -210,12 +175,9 @@ class HTMLPurifier
// list of un-purified tokens // list of un-purified tokens
$lexer->tokenizeHTML( $lexer->tokenizeHTML(
// un-purified HTML // un-purified HTML
$html, $html, $config, $context
$config,
$context
), ),
$config, $config, $context
$context
) )
); );
@@ -230,41 +192,27 @@ class HTMLPurifier
/** /**
* Filters an array of HTML snippets * 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. * 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(); $context_array = array();
$array = array(); foreach ($array_of_html as $key => $html) {
foreach($array_of_html as $key=>$value){ $array_of_html[$key] = $this->purify($html, $config);
if (is_array($value)) {
$array[$key] = $this->purifyArray($value, $config);
} else {
$array[$key] = $this->purify($value, $config);
}
$context_array[$key] = $this->context; $context_array[$key] = $this->context;
} }
$this->context = $context_array; $this->context = $context_array;
return $array; return $array_of_html;
} }
/** /**
* Singleton for enforcing just one HTML Purifier in your system * Singleton for enforcing just one HTML Purifier in your system
* * @param $prototype Optional prototype HTMLPurifier instance to
* @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype * overload singleton with, or HTMLPurifier_Config
* HTMLPurifier instance to overload singleton with, * instance to configure the generated version 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 (!self::$instance || $prototype) {
if ($prototype instanceof HTMLPurifier) { if ($prototype instanceof HTMLPurifier) {
self::$instance = $prototype; self::$instance = $prototype;
@@ -278,20 +226,12 @@ 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() * @note Backwards compatibility, see instance()
*/ */
public static function getInstance($prototype = null) public static function getInstance($prototype = null) {
{
return HTMLPurifier::instance($prototype); return HTMLPurifier::instance($prototype);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -13,7 +13,8 @@
$__dir = dirname(__FILE__); $__dir = dirname(__FILE__);
require_once $__dir . '/HTMLPurifier.php'; require_once $__dir . '/HTMLPurifier.php';
require_once $__dir . '/HTMLPurifier/Arborize.php'; require_once $__dir . '/HTMLPurifier/Array.php';
require_once $__dir . '/HTMLPurifier/ArrayNode.php';
require_once $__dir . '/HTMLPurifier/AttrCollections.php'; require_once $__dir . '/HTMLPurifier/AttrCollections.php';
require_once $__dir . '/HTMLPurifier/AttrDef.php'; require_once $__dir . '/HTMLPurifier/AttrDef.php';
require_once $__dir . '/HTMLPurifier/AttrTransform.php'; require_once $__dir . '/HTMLPurifier/AttrTransform.php';
@@ -31,6 +32,7 @@ require_once $__dir . '/HTMLPurifier/DefinitionCache.php';
require_once $__dir . '/HTMLPurifier/DefinitionCacheFactory.php'; require_once $__dir . '/HTMLPurifier/DefinitionCacheFactory.php';
require_once $__dir . '/HTMLPurifier/Doctype.php'; require_once $__dir . '/HTMLPurifier/Doctype.php';
require_once $__dir . '/HTMLPurifier/DoctypeRegistry.php'; require_once $__dir . '/HTMLPurifier/DoctypeRegistry.php';
require_once $__dir . '/HTMLPurifier/DoublyLinkedList.php';
require_once $__dir . '/HTMLPurifier/ElementDef.php'; require_once $__dir . '/HTMLPurifier/ElementDef.php';
require_once $__dir . '/HTMLPurifier/Encoder.php'; require_once $__dir . '/HTMLPurifier/Encoder.php';
require_once $__dir . '/HTMLPurifier/EntityLookup.php'; require_once $__dir . '/HTMLPurifier/EntityLookup.php';
@@ -49,11 +51,9 @@ require_once $__dir . '/HTMLPurifier/Language.php';
require_once $__dir . '/HTMLPurifier/LanguageFactory.php'; require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
require_once $__dir . '/HTMLPurifier/Length.php'; require_once $__dir . '/HTMLPurifier/Length.php';
require_once $__dir . '/HTMLPurifier/Lexer.php'; require_once $__dir . '/HTMLPurifier/Lexer.php';
require_once $__dir . '/HTMLPurifier/Node.php';
require_once $__dir . '/HTMLPurifier/PercentEncoder.php'; require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
require_once $__dir . '/HTMLPurifier/PropertyList.php'; require_once $__dir . '/HTMLPurifier/PropertyList.php';
require_once $__dir . '/HTMLPurifier/PropertyListIterator.php'; require_once $__dir . '/HTMLPurifier/PropertyListIterator.php';
require_once $__dir . '/HTMLPurifier/Queue.php';
require_once $__dir . '/HTMLPurifier/Strategy.php'; require_once $__dir . '/HTMLPurifier/Strategy.php';
require_once $__dir . '/HTMLPurifier/StringHash.php'; require_once $__dir . '/HTMLPurifier/StringHash.php';
require_once $__dir . '/HTMLPurifier/StringHashParser.php'; require_once $__dir . '/HTMLPurifier/StringHashParser.php';
@@ -69,7 +69,6 @@ require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
require_once $__dir . '/HTMLPurifier/UnitConverter.php'; require_once $__dir . '/HTMLPurifier/UnitConverter.php';
require_once $__dir . '/HTMLPurifier/VarParser.php'; require_once $__dir . '/HTMLPurifier/VarParser.php';
require_once $__dir . '/HTMLPurifier/VarParserException.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/CSS.php';
require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php'; require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php';
require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php'; require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
@@ -95,14 +94,12 @@ require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Multiple.php';
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.php';
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ratio.php';
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/TextDecoration.php';
require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php'; require_once $__dir . '/HTMLPurifier/AttrDef/CSS/URI.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Bool.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Class.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Class.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ContentEditable.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/FrameTarget.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/ID.php';
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php'; require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php';
@@ -133,8 +130,6 @@ require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php';
require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.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/AttrTransform/Textarea.php';
require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
@@ -173,8 +168,6 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.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/Text.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php';
require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
@@ -193,9 +186,6 @@ require_once $__dir . '/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php'; require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php';
require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php'; require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.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/Composite.php';
require_once $__dir . '/HTMLPurifier/Strategy/Core.php'; require_once $__dir . '/HTMLPurifier/Strategy/Core.php';
require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php'; require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php';
@@ -225,6 +215,5 @@ require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php'; require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php';
require_once $__dir . '/HTMLPurifier/URIScheme/news.php'; require_once $__dir . '/HTMLPurifier/URIScheme/news.php';
require_once $__dir . '/HTMLPurifier/URIScheme/nntp.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/Flexible.php';
require_once $__dir . '/HTMLPurifier/VarParser/Native.php'; require_once $__dir . '/HTMLPurifier/VarParser/Native.php';

View File

@@ -1,71 +0,0 @@
<?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;
}
}

View File

@@ -0,0 +1,184 @@
<?php
class HTMLPurifier_Array implements ArrayAccess
{
/**
* @param HTMLPurifier_ArrayNode
*/
public $head = null;
/**
* @var int
*/
protected $count = 0;
/**
* @var int
*/
protected $offset = 0;
/**
* @var HTMLPurifier_ArrayNode
*/
protected $offsetItem = null;
public function __construct(array $array = array())
{
/**
* @var HTMLPurifier_ArrayNode $temp
*/
$temp = null;
$i = 0;
foreach ($array as &$v) {
$item = new HTMLPurifier_ArrayNode($v);
if ($this->head == null) {
$this->head = &$item;
}
if ($temp instanceof HTMLPurifier_ArrayNode) {
$item->prev = &$temp;
$temp->next = &$item;
}
unset($temp);
$temp = &$item;
$i ++;
unset($item, $v);
}
$this->count = $i;
$this->offset = 0;
$this->offsetItem = &$this->head;
}
protected function findIndex($offset)
{
if ($this->head == null) {
return array(
'correct' => false,
'value' => null
);
}
$current = &$this->head;
$index = 0;
if ($this->offset <= $offset && $this->offsetItem instanceof HTMLPurifier_ArrayNode) {
$current = &$this->offsetItem;
$index = $this->offset;
}
while ($current->next instanceof HTMLPurifier_ArrayNode && $index != $offset) {
$current = &$current->next;
$index ++;
}
if ($index == $offset) {
$this->offset = $offset;
$this->offsetItem = &$current;
return array(
'correct' => true,
'value' => &$current
);
}
return array(
'correct' => false,
'value' => &$current
);
}
public function insertBefore($offset, $value)
{
$result = $this->findIndex($offset);
$this->count ++;
$item = new HTMLPurifier_ArrayNode($value);
if ($result['correct'] == false) {
if ($result['value'] instanceof HTMLPurifier_ArrayNode) {
$result['value']->next = &$item;
$item->prev = &$result['value'];
}
} else {
if ($result['value'] instanceof HTMLPurifier_ArrayNode) {
$item->prev = &$result['value']->prev;
$item->next = &$result['value'];
}
if ($item->prev instanceof HTMLPurifier_ArrayNode) {
$item->prev->next = &$item;
}
if ($result['value'] instanceof HTMLPurifier_ArrayNode) {
$result['value']->prev = &$item;
}
}
if ($offset == 0) {
$this->head = &$item;
}
if ($offset <= $this->offset && $this->offsetItem instanceof HTMLPurifier_ArrayNode) {
$this->offsetItem = &$this->offsetItem->prev;
}
}
public function remove($offset)
{
$result = $this->findIndex($offset);
if ($result['correct']) {
$this->count --;
$item = $result['value'];
$item->prev->next = &$result['value']->next;
$item->next->prev = &$result['value']->prev;
if ($offset == 0) {
$this->head = &$item->next;
}
if ($offset < $this->offset) {
$this->offset --;
} elseif ($offset == $this->offset) {
$this->offsetItem = &$item->next;
}
}
}
public function getArray()
{
$return = array();
$head = $this->head;
while ($head instanceof HTMLPurifier_ArrayNode) {
$return[] = $head->value;
$head = &$head->next;
}
return $return;
}
public function offsetExists($offset)
{
return $offset >= 0 && $offset < $this->count;
}
public function offsetGet($offset)
{
$result = $this->findIndex($offset);
if ($result['correct']) {
return $result['value']->value;
}
return null;
}
public function offsetSet($offset, $value)
{
$result = $this->findIndex($offset);
if ($result['correct']) {
$result['value']->value = &$value;
}
}
public function offsetUnset($offset)
{
$this->remove($offset);
}
}

View File

@@ -0,0 +1,24 @@
<?php
class HTMLPurifier_ArrayNode
{
public function __construct(&$value)
{
$this->value = &$value;
}
/**
* @var HTMLPurifier_ArrayNode
*/
public $prev = null;
/**
* @var HTMLPurifier_ArrayNode
*/
public $next = null;
/**
* @var mixed
*/
public $value = null;
}

View File

@@ -8,8 +8,7 @@ class HTMLPurifier_AttrCollections
{ {
/** /**
* Associative array of attribute collections, indexed by name. * Associative array of attribute collections, indexed by name
* @type array
*/ */
public $info = array(); public $info = array();
@@ -17,16 +16,10 @@ class HTMLPurifier_AttrCollections
* Performs all expansions on internal data for use by other inclusions * Performs all expansions on internal data for use by other inclusions
* It also collects all attribute collection extensions from * It also collects all attribute collection extensions from
* modules * modules
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance * @param $attr_types HTMLPurifier_AttrTypes instance
* @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members * @param $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 // load extensions from the modules
foreach ($modules as $module) { foreach ($modules as $module) {
foreach ($module->attr_collections as $coll_i => $coll) { foreach ($module->attr_collections as $coll_i => $coll) {
@@ -37,9 +30,7 @@ class HTMLPurifier_AttrCollections
if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) { if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
// merge in includes // merge in includes
$this->info[$coll_i][$attr_i] = array_merge( $this->info[$coll_i][$attr_i] = array_merge(
$this->info[$coll_i][$attr_i], $this->info[$coll_i][$attr_i], $attr);
$attr
);
continue; continue;
} }
$this->info[$coll_i][$attr_i] = $attr; $this->info[$coll_i][$attr_i] = $attr;
@@ -58,29 +49,20 @@ class HTMLPurifier_AttrCollections
/** /**
* Takes a reference to an attribute associative array and performs * Takes a reference to an attribute associative array and performs
* all inclusions specified by the zero index. * all inclusions specified by the zero index.
* @param array &$attr Reference to attribute array * @param &$attr Reference to attribute array
*/ */
public function performInclusions(&$attr) public function performInclusions(&$attr) {
{ if (!isset($attr[0])) return;
if (!isset($attr[0])) {
return;
}
$merge = $attr[0]; $merge = $attr[0];
$seen = array(); // recursion guard $seen = array(); // recursion guard
// loop through all the inclusions // loop through all the inclusions
for ($i = 0; isset($merge[$i]); $i++) { for ($i = 0; isset($merge[$i]); $i++) {
if (isset($seen[$merge[$i]])) { if (isset($seen[$merge[$i]])) continue;
continue;
}
$seen[$merge[$i]] = true; $seen[$merge[$i]] = true;
// foreach attribute of the inclusion, copy it over // foreach attribute of the inclusion, copy it over
if (!isset($this->info[$merge[$i]])) { if (!isset($this->info[$merge[$i]])) continue;
continue;
}
foreach ($this->info[$merge[$i]] as $key => $value) { foreach ($this->info[$merge[$i]] as $key => $value) {
if (isset($attr[$key])) { if (isset($attr[$key])) continue; // also catches more inclusions
continue;
} // also catches more inclusions
$attr[$key] = $value; $attr[$key] = $value;
} }
if (isset($this->info[$merge[$i]][0])) { if (isset($this->info[$merge[$i]][0])) {
@@ -94,24 +76,20 @@ class HTMLPurifier_AttrCollections
/** /**
* Expands all string identifiers in an attribute array by replacing * Expands all string identifiers in an attribute array by replacing
* them with the appropriate values inside HTMLPurifier_AttrTypes * them with the appropriate values inside HTMLPurifier_AttrTypes
* @param array &$attr Reference to attribute array * @param &$attr Reference to attribute array
* @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance * @param $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 // because foreach will process new elements we add, make sure we
// skip duplicates // skip duplicates
$processed = array(); $processed = array();
foreach ($attr as $def_i => $def) { foreach ($attr as $def_i => $def) {
// skip inclusions // skip inclusions
if ($def_i === 0) { if ($def_i === 0) continue;
continue;
}
if (isset($processed[$def_i])) { if (isset($processed[$def_i])) continue;
continue;
}
// determine whether or not attribute is required // determine whether or not attribute is required
if ($required = (strpos($def_i, '*') !== false)) { if ($required = (strpos($def_i, '*') !== false)) {
@@ -142,7 +120,9 @@ class HTMLPurifier_AttrCollections
unset($attr[$def_i]); unset($attr[$def_i]);
} }
} }
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -14,25 +14,23 @@ abstract class HTMLPurifier_AttrDef
{ {
/** /**
* Tells us whether or not an HTML attribute is minimized. * Tells us whether or not an HTML attribute is minimized. Has no
* Has no meaning in other contexts. * meaning in other contexts.
* @type bool
*/ */
public $minimized = false; public $minimized = false;
/** /**
* Tells us whether or not an HTML attribute is required. * Tells us whether or not an HTML attribute is required. Has no
* Has no meaning in other contexts * meaning in other contexts
* @type bool
*/ */
public $required = false; public $required = false;
/** /**
* Validates and cleans passed string according to a definition. * Validates and cleans passed string according to a definition.
* *
* @param string $string String to be validated and cleaned. * @param $string String to be validated and cleaned.
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object. * @param $config Mandatory HTMLPurifier_Config object.
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object. * @param $context Mandatory HTMLPurifier_AttrContext object.
*/ */
abstract public function validate($string, $config, $context); abstract public function validate($string, $config, $context);
@@ -57,8 +55,7 @@ abstract class HTMLPurifier_AttrDef
* parsing XML, thus, this behavior may still be correct. We * parsing XML, thus, this behavior may still be correct. We
* assume that newlines have been normalized. * assume that newlines have been normalized.
*/ */
public function parseCDATA($string) public function parseCDATA($string) {
{
$string = trim($string); $string = trim($string);
$string = str_replace(array("\n", "\t", "\r"), ' ', $string); $string = str_replace(array("\n", "\t", "\r"), ' ', $string);
return $string; return $string;
@@ -66,11 +63,10 @@ abstract class HTMLPurifier_AttrDef
/** /**
* Factory method for creating this class from a string. * Factory method for creating this class from a string.
* @param string $string String construction info * @param $string String construction info
* @return HTMLPurifier_AttrDef Created AttrDef object corresponding to $string * @return Created AttrDef object corresponding to $string
*/ */
public function make($string) public function make($string) {
{
// default implementation, return a flyweight of this object. // default implementation, return a flyweight of this object.
// If $string has an effect on the returned object (i.e. you // If $string has an effect on the returned object (i.e. you
// need to overload this method), it is best // need to overload this method), it is best
@@ -81,26 +77,16 @@ abstract class HTMLPurifier_AttrDef
/** /**
* Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work * Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
* properly. THIS IS A HACK! * properly. THIS IS A HACK!
* @param string $string a CSS colour definition
* @return string
*/ */
protected function mungeRgb($string) protected function mungeRgb($string) {
{ return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $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" * Parses a possibly escaped CSS string and returns the "pure"
* version of it. * version of it.
*/ */
protected function expandCSSEscape($string) protected function expandCSSEscape($string) {
{
// flexibly parse it // flexibly parse it
$ret = ''; $ret = '';
for ($i = 0, $c = strlen($string); $i < $c; $i++) { for ($i = 0, $c = strlen($string); $i < $c; $i++) {
@@ -113,32 +99,25 @@ abstract class HTMLPurifier_AttrDef
if (ctype_xdigit($string[$i])) { if (ctype_xdigit($string[$i])) {
$code = $string[$i]; $code = $string[$i];
for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) { for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
if (!ctype_xdigit($string[$i])) { if (!ctype_xdigit($string[$i])) break;
break;
}
$code .= $string[$i]; $code .= $string[$i];
} }
// We have to be extremely careful when adding // We have to be extremely careful when adding
// new characters, to make sure we're not breaking // new characters, to make sure we're not breaking
// the encoding. // the encoding.
$char = HTMLPurifier_Encoder::unichr(hexdec($code)); $char = HTMLPurifier_Encoder::unichr(hexdec($code));
if (HTMLPurifier_Encoder::cleanUTF8($char) === '') { if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
continue;
}
$ret .= $char; $ret .= $char;
if ($i < $c && trim($string[$i]) !== '') { if ($i < $c && trim($string[$i]) !== '') $i--;
$i--;
}
continue;
}
if ($string[$i] === "\n") {
continue; continue;
} }
if ($string[$i] === "\n") continue;
} }
$ret .= $string[$i]; $ret .= $string[$i];
} }
return $ret; return $ret;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -14,60 +14,20 @@
class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef 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); $css = $this->parseCDATA($css);
$definition = $config->getCSSDefinition(); $definition = $config->getCSSDefinition();
$allow_duplicates = $config->get("CSS.AllowDuplicates");
$universal_attrdef = new HTMLPurifier_AttrDef_Enum( // we're going to break the spec and explode by semicolons.
array( // This is because semicolon rarely appears in escaped form
'initial', // Doing this is generally flaky but fast
'inherit', // IT MIGHT APPEAR IN URIs, see HTMLPurifier_AttrDef_CSSURI
'unset', // for details
)
);
// 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;
$declarations = explode(';', $css);
$propvalues = array(); $propvalues = array();
$new_declarations = '';
/** /**
* Name of the current CSS property being validated. * Name of the current CSS property being validated.
@@ -76,49 +36,35 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
$context->register('CurrentCSSProperty', $property); $context->register('CurrentCSSProperty', $property);
foreach ($declarations as $declaration) { foreach ($declarations as $declaration) {
if (!$declaration) { if (!$declaration) continue;
continue; if (!strpos($declaration, ':')) continue;
}
if (!strpos($declaration, ':')) {
continue;
}
list($property, $value) = explode(':', $declaration, 2); list($property, $value) = explode(':', $declaration, 2);
$property = trim($property); $property = trim($property);
$value = trim($value); $value = trim($value);
$ok = false; $ok = false;
do { do {
if (isset($definition->info[$property])) { if (isset($definition->info[$property])) {
$ok = true; $ok = true;
break; break;
} }
if (ctype_lower($property)) { if (ctype_lower($property)) break;
break;
}
$property = strtolower($property); $property = strtolower($property);
if (isset($definition->info[$property])) { if (isset($definition->info[$property])) {
$ok = true; $ok = true;
break; break;
} }
} while (0); } while(0);
if (!$ok) { if (!$ok) continue;
continue; // inefficient call, since the validator will do this again
} if (strtolower(trim($value)) !== 'inherit') {
$result = $universal_attrdef->validate($value, $config, $context); // inherit works for everything (but only on the base property)
if ($result === false) {
$result = $definition->info[$property]->validate( $result = $definition->info[$property]->validate(
$value, $value, $config, $context );
$config,
$context
);
}
if ($result === false) {
continue;
}
if ($allow_duplicates) {
$new_declarations .= "$property:$result;";
} else { } else {
$propvalues[$property] = $result; $result = 'inherit';
} }
if ($result === false) continue;
$propvalues[$property] = $result;
} }
$context->destroy('CurrentCSSProperty'); $context->destroy('CurrentCSSProperty');
@@ -127,6 +73,7 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
// slightly inefficient, but it's the only way of getting rid of // slightly inefficient, but it's the only way of getting rid of
// duplicates. Perhaps config to optimize it, but not now. // duplicates. Perhaps config to optimize it, but not now.
$new_declarations = '';
foreach ($propvalues as $prop => $value) { foreach ($propvalues as $prop => $value) {
$new_declarations .= "$prop:$value;"; $new_declarations .= "$prop:$value;";
} }

View File

@@ -3,32 +3,19 @@
class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number 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 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); $result = parent::validate($number, $config, $context);
if ($result === false) { if ($result === false) return $result;
return $result; $float = (float) $result;
} if ($float < 0.0) $result = '0';
$float = (float)$result; if ($float > 1.0) $result = '1';
if ($float < 0.0) {
$result = '0';
}
if ($float > 1.0) {
$result = '1';
}
return $result; return $result;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -9,38 +9,24 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
/** /**
* Local copy of component validators. * Local copy of component validators.
* @type HTMLPurifier_AttrDef[]
* @note See HTMLPurifier_AttrDef_Font::$info for a similar impl. * @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
*/ */
protected $info; protected $info;
/** public function __construct($config) {
* @param HTMLPurifier_Config $config
*/
public function __construct($config)
{
$def = $config->getCSSDefinition(); $def = $config->getCSSDefinition();
$this->info['background-color'] = $def->info['background-color']; $this->info['background-color'] = $def->info['background-color'];
$this->info['background-image'] = $def->info['background-image']; $this->info['background-image'] = $def->info['background-image'];
$this->info['background-repeat'] = $def->info['background-repeat']; $this->info['background-repeat'] = $def->info['background-repeat'];
$this->info['background-attachment'] = $def->info['background-attachment']; $this->info['background-attachment'] = $def->info['background-attachment'];
$this->info['background-position'] = $def->info['background-position']; $this->info['background-position'] = $def->info['background-position'];
$this->info['background-size'] = $def->info['background-size'];
} }
/** 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 // regular pre-processing
$string = $this->parseCDATA($string); $string = $this->parseCDATA($string);
if ($string === '') { if ($string === '') return false;
return false;
}
// munge rgb() decl if necessary // munge rgb() decl if necessary
$string = $this->mungeRgb($string); $string = $this->mungeRgb($string);
@@ -49,35 +35,27 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
$bits = explode(' ', $string); // bits to process $bits = explode(' ', $string); // bits to process
$caught = array(); $caught = array();
$caught['color'] = false; $caught['color'] = false;
$caught['image'] = false; $caught['image'] = false;
$caught['repeat'] = false; $caught['repeat'] = false;
$caught['attachment'] = false; $caught['attachment'] = false;
$caught['position'] = false; $caught['position'] = false;
$caught['size'] = false;
$i = 0; // number of catches $i = 0; // number of catches
$none = false;
foreach ($bits as $bit) { foreach ($bits as $bit) {
if ($bit === '') { if ($bit === '') continue;
continue;
}
foreach ($caught as $key => $status) { foreach ($caught as $key => $status) {
if ($key != 'position') { if ($key != 'position') {
if ($status !== false) { if ($status !== false) continue;
continue;
}
$r = $this->info['background-' . $key]->validate($bit, $config, $context); $r = $this->info['background-' . $key]->validate($bit, $config, $context);
} else { } else {
$r = $bit; $r = $bit;
} }
if ($r === false) { if ($r === false) continue;
continue;
}
if ($key == 'position') { if ($key == 'position') {
if ($caught[$key] === false) { if ($caught[$key] === false) $caught[$key] = '';
$caught[$key] = '';
}
$caught[$key] .= $r . ' '; $caught[$key] .= $r . ' ';
} else { } else {
$caught[$key] = $r; $caught[$key] = $r;
@@ -87,9 +65,7 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
} }
} }
if (!$i) { if (!$i) return false;
return false;
}
if ($caught['position'] !== false) { if ($caught['position'] !== false) {
$caught['position'] = $this->info['background-position']-> $caught['position'] = $this->info['background-position']->
validate($caught['position'], $config, $context); validate($caught['position'], $config, $context);
@@ -97,17 +73,15 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
$ret = array(); $ret = array();
foreach ($caught as $value) { foreach ($caught as $value) {
if ($value === false) { if ($value === false) continue;
continue;
}
$ret[] = $value; $ret[] = $value;
} }
if (empty($ret)) { if (empty($ret)) return false;
return false;
}
return implode(' ', $ret); return implode(' ', $ret);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -44,30 +44,15 @@
class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
{ {
/**
* @type HTMLPurifier_AttrDef_CSS_Length
*/
protected $length; protected $length;
/**
* @type HTMLPurifier_AttrDef_CSS_Percentage
*/
protected $percentage; protected $percentage;
public function __construct() public function __construct() {
{ $this->length = new HTMLPurifier_AttrDef_CSS_Length();
$this->length = new HTMLPurifier_AttrDef_CSS_Length();
$this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage(); $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); $string = $this->parseCDATA($string);
$bits = explode(' ', $string); $bits = explode(' ', $string);
@@ -89,9 +74,7 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
); );
foreach ($bits as $bit) { foreach ($bits as $bit) {
if ($bit === '') { if ($bit === '') continue;
continue;
}
// test for keyword // test for keyword
$lbit = ctype_lower($bit) ? $bit : strtolower($bit); $lbit = ctype_lower($bit) ? $bit : strtolower($bit);
@@ -121,37 +104,30 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
$measures[] = $r; $measures[] = $r;
$i++; $i++;
} }
} }
if (!$i) { if (!$i) return false; // no valid values were caught
return false;
} // no valid values were caught
$ret = array(); $ret = array();
// first keyword // first keyword
if ($keywords['h']) { if ($keywords['h']) $ret[] = $keywords['h'];
$ret[] = $keywords['h']; elseif ($keywords['ch']) {
} elseif ($keywords['ch']) {
$ret[] = $keywords['ch']; $ret[] = $keywords['ch'];
$keywords['cv'] = false; // prevent re-use: center = center center $keywords['cv'] = false; // prevent re-use: center = center center
} elseif (count($measures)) {
$ret[] = array_shift($measures);
} }
elseif (count($measures)) $ret[] = array_shift($measures);
if ($keywords['v']) { if ($keywords['v']) $ret[] = $keywords['v'];
$ret[] = $keywords['v']; elseif ($keywords['cv']) $ret[] = $keywords['cv'];
} elseif ($keywords['cv']) { elseif (count($measures)) $ret[] = array_shift($measures);
$ret[] = $keywords['cv'];
} elseif (count($measures)) {
$ret[] = array_shift($measures);
}
if (empty($ret)) { if (empty($ret)) return false;
return false;
}
return implode(' ', $ret); return implode(' ', $ret);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,29 +8,17 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
/** /**
* Local copy of properties this property is shorthand for. * Local copy of properties this property is shorthand for.
* @type HTMLPurifier_AttrDef[]
*/ */
protected $info = array(); protected $info = array();
/** public function __construct($config) {
* @param HTMLPurifier_Config $config
*/
public function __construct($config)
{
$def = $config->getCSSDefinition(); $def = $config->getCSSDefinition();
$this->info['border-width'] = $def->info['border-width']; $this->info['border-width'] = $def->info['border-width'];
$this->info['border-style'] = $def->info['border-style']; $this->info['border-style'] = $def->info['border-style'];
$this->info['border-top-color'] = $def->info['border-top-color']; $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->parseCDATA($string);
$string = $this->mungeRgb($string); $string = $this->mungeRgb($string);
$bits = explode(' ', $string); $bits = explode(' ', $string);
@@ -38,9 +26,7 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
$ret = ''; // return value $ret = ''; // return value
foreach ($bits as $bit) { foreach ($bits as $bit) {
foreach ($this->info as $propname => $validator) { foreach ($this->info as $propname => $validator) {
if (isset($done[$propname])) { if (isset($done[$propname])) continue;
continue;
}
$r = $validator->validate($bit, $config, $context); $r = $validator->validate($bit, $config, $context);
if ($r !== false) { if ($r !== false) {
$ret .= $r . ' '; $ret .= $r . ' ';
@@ -51,6 +37,7 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
} }
return rtrim($ret); return rtrim($ret);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,137 +6,56 @@
class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef 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; static $colors = null;
if ($colors === null) { if ($colors === null) $colors = $config->get('Core.ColorKeywords');
$colors = $config->get('Core.ColorKeywords');
}
$color = trim($color); $color = trim($color);
if ($color === '') { if ($color === '') return false;
return false;
}
$lower = strtolower($color); $lower = strtolower($color);
if (isset($colors[$lower])) { if (isset($colors[$lower])) return $colors[$lower];
return $colors[$lower];
}
if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) { if (strpos($color, 'rgb(') !== false) {
// rgb literal handling
$length = strlen($color); $length = strlen($color);
if (strpos($color, ')') !== $length - 1) { if (strpos($color, ')') !== $length - 1) return false;
return false; $triad = substr($color, 4, $length - 4 - 1);
} $parts = explode(',', $triad);
if (count($parts) !== 3) return false;
// get used function : rgb, rgba, hsl or hsla $type = false; // to ensure that they're all the same type
$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(); $new_parts = array();
$i = 0;
foreach ($parts as $part) { foreach ($parts as $part) {
$i++;
$part = trim($part); $part = trim($part);
if ($part === '') return false;
if ($part === '') { $length = strlen($part);
return false; if ($part[$length - 1] === '%') {
} // handle percents
if (!$type) {
// different check for alpha channel $type = 'percentage';
if ($alpha_channel === true && $i === count($parts)) { } elseif ($type !== 'percentage') {
$result = $this->alpha->validate($part, $config, $context);
if ($result === false) {
return false; return false;
} }
$num = (float) substr($part, 0, $length - 1);
$new_parts[] = (string)$result; if ($num < 0) $num = 0;
continue; if ($num > 100) $num = 100;
} $new_parts[] = "$num%";
if (substr($part, -1) === '%') {
$current_type = 'percentage';
} else { } else {
$current_type = 'integer'; // handle integers
} if (!$type) {
$type = 'integer';
if (!array_key_exists($current_type, $allowed_types[$i])) { } elseif ($type !== 'integer') {
return false; return false;
} }
$num = (int) $part;
if (!$type) { if ($num < 0) $num = 0;
$type = $current_type; if ($num > 255) $num = 255;
} $new_parts[] = (string) $num;
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);
$new_values = implode(',', $new_parts); $color = "rgb($new_triad)";
$color = $function . '(' . $new_values . ')';
} else { } else {
// hexadecimal handling // hexadecimal handling
if ($color[0] === '#') { if ($color[0] === '#') {
@@ -146,14 +65,12 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
$color = '#' . $color; $color = '#' . $color;
} }
$length = strlen($hex); $length = strlen($hex);
if ($length !== 3 && $length !== 6) { if ($length !== 3 && $length !== 6) return false;
return false; if (!ctype_xdigit($hex)) return false;
}
if (!ctype_xdigit($hex)) {
return false;
}
} }
return $color; return $color;
} }
} }

View File

@@ -13,36 +13,26 @@ class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
{ {
/** /**
* List of objects that may process strings. * List of HTMLPurifier_AttrDef objects that may process strings
* @type HTMLPurifier_AttrDef[]
* @todo Make protected * @todo Make protected
*/ */
public $defs; public $defs;
/** /**
* @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects * @param $defs List of HTMLPurifier_AttrDef objects
*/ */
public function __construct($defs) public function __construct($defs) {
{
$this->defs = $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) { foreach ($this->defs as $i => $def) {
$result = $this->defs[$i]->validate($string, $config, $context); $result = $this->defs[$i]->validate($string, $config, $context);
if ($result !== false) { if ($result !== false) return $result;
return $result;
}
} }
return false; return false;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -5,38 +5,22 @@
*/ */
class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
{ {
/** public $def, $element;
* @type HTMLPurifier_AttrDef
*/
public $def;
/**
* @type string
*/
public $element;
/** /**
* @param HTMLPurifier_AttrDef $def Definition to wrap * @param $def Definition to wrap
* @param string $element Element to deny * @param $element Element to deny
*/ */
public function __construct($def, $element) public function __construct($def, $element) {
{
$this->def = $def; $this->def = $def;
$this->element = $element; $this->element = $element;
} }
/** /**
* Checks if CurrentToken is set and equal to $this->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); $token = $context->get('CurrentToken', true);
if ($token && $token->name == $this->element) { if ($token && $token->name == $this->element) return false;
return false;
}
return $this->def->validate($string, $config, $context); return $this->def->validate($string, $config, $context);
} }
} }

View File

@@ -7,37 +7,23 @@
*/ */
class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
{ {
/**
* @type HTMLPurifier_AttrDef_Integer
*/
protected $intValidator; protected $intValidator;
public function __construct() public function __construct() {
{
$this->intValidator = new HTMLPurifier_AttrDef_Integer(); $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); $value = $this->parseCDATA($value);
if ($value === 'none') { if ($value === 'none') return $value;
return $value;
}
// if we looped this we could support multiple filters // if we looped this we could support multiple filters
$function_length = strcspn($value, '('); $function_length = strcspn($value, '(');
$function = trim(substr($value, 0, $function_length)); $function = trim(substr($value, 0, $function_length));
if ($function !== 'alpha' && if ($function !== 'alpha' &&
$function !== 'Alpha' && $function !== 'Alpha' &&
$function !== 'progid:DXImageTransform.Microsoft.Alpha' $function !== 'progid:DXImageTransform.Microsoft.Alpha'
) { ) return false;
return false;
}
$cursor = $function_length + 1; $cursor = $function_length + 1;
$parameters_length = strcspn($value, ')', $cursor); $parameters_length = strcspn($value, ')', $cursor);
$parameters = substr($value, $cursor, $parameters_length); $parameters = substr($value, $cursor, $parameters_length);
@@ -46,25 +32,15 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
$lookup = array(); $lookup = array();
foreach ($params as $param) { foreach ($params as $param) {
list($key, $value) = explode('=', $param); list($key, $value) = explode('=', $param);
$key = trim($key); $key = trim($key);
$value = trim($value); $value = trim($value);
if (isset($lookup[$key])) { if (isset($lookup[$key])) continue;
continue; if ($key !== 'opacity') continue;
}
if ($key !== 'opacity') {
continue;
}
$value = $this->intValidator->validate($value, $config, $context); $value = $this->intValidator->validate($value, $config, $context);
if ($value === false) { if ($value === false) continue;
continue; $int = (int) $value;
} if ($int > 100) $value = '100';
$int = (int)$value; if ($int < 0) $value = '0';
if ($int > 100) {
$value = '100';
}
if ($int < 0) {
$value = '0';
}
$ret_params[] = "$key=$value"; $ret_params[] = "$key=$value";
$lookup[$key] = true; $lookup[$key] = true;
} }
@@ -72,6 +48,7 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
$ret_function = "$function($ret_parameters)"; $ret_function = "$function($ret_parameters)";
return $ret_function; return $ret_function;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,8 +7,8 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
{ {
/** /**
* Local copy of validators * Local copy of component validators.
* @type HTMLPurifier_AttrDef[] *
* @note If we moved specific CSS property definitions to their own * @note If we moved specific CSS property definitions to their own
* classes instead of having them be assembled at run time by * classes instead of having them be assembled at run time by
* CSSDefinition, this wouldn't be necessary. We'd instantiate * CSSDefinition, this wouldn't be necessary. We'd instantiate
@@ -16,28 +16,18 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
*/ */
protected $info = array(); protected $info = array();
/** public function __construct($config) {
* @param HTMLPurifier_Config $config
*/
public function __construct($config)
{
$def = $config->getCSSDefinition(); $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-variant'] = $def->info['font-variant'];
$this->info['font-weight'] = $def->info['font-weight']; $this->info['font-weight'] = $def->info['font-weight'];
$this->info['font-size'] = $def->info['font-size']; $this->info['font-size'] = $def->info['font-size'];
$this->info['line-height'] = $def->info['line-height']; $this->info['line-height'] = $def->info['line-height'];
$this->info['font-family'] = $def->info['font-family']; $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( static $system_fonts = array(
'caption' => true, 'caption' => true,
'icon' => true, 'icon' => true,
@@ -49,9 +39,7 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
// regular pre-processing // regular pre-processing
$string = $this->parseCDATA($string); $string = $this->parseCDATA($string);
if ($string === '') { if ($string === '') return false;
return false;
}
// check if it's one of the keywords // check if it's one of the keywords
$lowercase_string = strtolower($string); $lowercase_string = strtolower($string);
@@ -66,20 +54,15 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
$final = ''; // output $final = ''; // output
for ($i = 0, $size = count($bits); $i < $size; $i++) { for ($i = 0, $size = count($bits); $i < $size; $i++) {
if ($bits[$i] === '') { if ($bits[$i] === '') continue;
continue;
}
switch ($stage) { switch ($stage) {
case 0: // attempting to catch font-style, font-variant or font-weight
// attempting to catch font-style, font-variant or font-weight
case 0:
foreach ($stage_1 as $validator_name) { foreach ($stage_1 as $validator_name) {
if (isset($caught[$validator_name])) { if (isset($caught[$validator_name])) continue;
continue;
}
$r = $this->info[$validator_name]->validate( $r = $this->info[$validator_name]->validate(
$bits[$i], $bits[$i], $config, $context);
$config,
$context
);
if ($r !== false) { if ($r !== false) {
$final .= $r . ' '; $final .= $r . ' ';
$caught[$validator_name] = true; $caught[$validator_name] = true;
@@ -87,17 +70,15 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
} }
} }
// all three caught, continue on // all three caught, continue on
if (count($caught) >= 3) { if (count($caught) >= 3) $stage = 1;
$stage = 1; if ($r !== false) break;
}
if ($r !== false) { // attempting to catch font-size and perhaps line-height
break; case 1:
}
case 1: // attempting to catch font-size and perhaps line-height
$found_slash = false; $found_slash = false;
if (strpos($bits[$i], '/') !== false) { if (strpos($bits[$i], '/') !== false) {
list($font_size, $line_height) = list($font_size, $line_height) =
explode('/', $bits[$i]); explode('/', $bits[$i]);
if ($line_height === '') { if ($line_height === '') {
// ooh, there's a space after the slash! // ooh, there's a space after the slash!
$line_height = false; $line_height = false;
@@ -108,19 +89,14 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
$line_height = false; $line_height = false;
} }
$r = $this->info['font-size']->validate( $r = $this->info['font-size']->validate(
$font_size, $font_size, $config, $context);
$config,
$context
);
if ($r !== false) { if ($r !== false) {
$final .= $r; $final .= $r;
// attempt to catch line-height // attempt to catch line-height
if ($line_height === false) { if ($line_height === false) {
// we need to scroll forward // we need to scroll forward
for ($j = $i + 1; $j < $size; $j++) { for ($j = $i + 1; $j < $size; $j++) {
if ($bits[$j] === '') { if ($bits[$j] === '') continue;
continue;
}
if ($bits[$j] === '/') { if ($bits[$j] === '/') {
if ($found_slash) { if ($found_slash) {
return false; return false;
@@ -140,10 +116,7 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
if ($found_slash) { if ($found_slash) {
$i = $j; $i = $j;
$r = $this->info['line-height']->validate( $r = $this->info['line-height']->validate(
$line_height, $line_height, $config, $context);
$config,
$context
);
if ($r !== false) { if ($r !== false) {
$final .= '/' . $r; $final .= '/' . $r;
} }
@@ -153,14 +126,13 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
break; break;
} }
return false; return false;
case 2: // attempting to catch font-family
// attempting to catch font-family
case 2:
$font_family = $font_family =
implode(' ', array_slice($bits, $i, $size - $i)); implode(' ', array_slice($bits, $i, $size - $i));
$r = $this->info['font-family']->validate( $r = $this->info['font-family']->validate(
$font_family, $font_family, $config, $context);
$config,
$context
);
if ($r !== false) { if ($r !== false) {
$final .= $r . ' '; $final .= $r . ' ';
// processing completed successfully // processing completed successfully
@@ -171,6 +143,7 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
} }
return false; return false;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,23 +8,18 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
protected $mask = null; protected $mask = null;
public function __construct() public function __construct() {
{ $this->mask = '_- ';
// Lowercase letters for ($c = 'a'; $c <= 'z'; $c++) $this->mask .= $c;
$l = range('a', 'z'); for ($c = 'A'; $c <= 'Z'; $c++) $this->mask .= $c;
// Uppercase letters for ($c = '0'; $c <= '9'; $c++) $this->mask .= $c; // cast-y, but should be fine
$u = range('A', 'Z'); // special bytes used by UTF-8
// Digits for ($i = 0x80; $i <= 0xFF; $i++) {
$d = range('0', '9'); // We don't bother excluding invalid bytes in this range,
// Special bytes used by UTF-8 // because the our restriction of well-formed UTF-8 will
$b = array_map('chr', range(0x80, 0xFF)); // prevent these from ever occurring.
// All valid characters for the mask $this->mask .= chr($i);
$c = array_merge($l, $u, $d, $b); }
// Concatenate all valid characters into a string
// Use '_- ' as an initial value
$this->mask = array_reduce($c, function ($carry, $value) {
return $carry . $value;
}, '_- ');
/* /*
PHP's internal strcspn implementation is PHP's internal strcspn implementation is
@@ -44,14 +39,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
// possible optimization: invert the mask. // possible optimization: invert the mask.
} }
/** 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 $generic_names = array( static $generic_names = array(
'serif' => true, 'serif' => true,
'sans-serif' => true, 'sans-serif' => true,
@@ -64,11 +52,9 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
// assume that no font names contain commas in them // assume that no font names contain commas in them
$fonts = explode(',', $string); $fonts = explode(',', $string);
$final = ''; $final = '';
foreach ($fonts as $font) { foreach($fonts as $font) {
$font = trim($font); $font = trim($font);
if ($font === '') { if ($font === '') continue;
continue;
}
// match a generic name // match a generic name
if (isset($generic_names[$font])) { if (isset($generic_names[$font])) {
if ($allowed_fonts === null || isset($allowed_fonts[$font])) { if ($allowed_fonts === null || isset($allowed_fonts[$font])) {
@@ -79,13 +65,9 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
// match a quoted name // match a quoted name
if ($font[0] === '"' || $font[0] === "'") { if ($font[0] === '"' || $font[0] === "'") {
$length = strlen($font); $length = strlen($font);
if ($length <= 2) { if ($length <= 2) continue;
continue;
}
$quote = $font[0]; $quote = $font[0];
if ($font[$length - 1] !== $quote) { if ($font[$length - 1] !== $quote) continue;
continue;
}
$font = substr($font, 1, $length - 2); $font = substr($font, 1, $length - 2);
} }
@@ -206,9 +188,7 @@ class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
$final .= "'$font', "; $final .= "'$font', ";
} }
$final = rtrim($final, ', '); $final = rtrim($final, ', ');
if ($final === '') { if ($final === '') return false;
return false;
}
return $final; return $final;
} }

View File

@@ -6,27 +6,19 @@
class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_CSS_Ident 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); $string = trim($string);
// early abort: '' and '0' (strings that convert to false) are invalid // early abort: '' and '0' (strings that convert to false) are invalid
if (!$string) { if (!$string) return false;
return false;
}
$pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/'; $pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
if (!preg_match($pattern, $string)) { if (!preg_match($pattern, $string)) return false;
return false;
}
return $string; return $string;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -5,34 +5,20 @@
*/ */
class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
{ {
/** public $def, $allow;
* @type HTMLPurifier_AttrDef
*/
public $def;
/**
* @type bool
*/
public $allow;
/** /**
* @param HTMLPurifier_AttrDef $def Definition to wrap * @param $def Definition to wrap
* @param bool $allow Whether or not to allow !important * @param $allow Whether or not to allow !important
*/ */
public function __construct($def, $allow = false) public function __construct($def, $allow = false) {
{
$this->def = $def; $this->def = $def;
$this->allow = $allow; $this->allow = $allow;
} }
/** /**
* Intercepts and removes !important if necessary * 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 // test for ! and important tokens
$string = trim($string); $string = trim($string);
$is_important = false; $is_important = false;
@@ -46,9 +32,7 @@ class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
} }
} }
$string = $this->def->validate($string, $config, $context); $string = $this->def->validate($string, $config, $context);
if ($this->allow && $is_important) { if ($this->allow && $is_important) $string .= ' !important';
$string .= ' !important';
}
return $string; return $string;
} }
} }

View File

@@ -6,72 +6,42 @@
class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
{ {
/** protected $min, $max;
* @type HTMLPurifier_Length|string
*/
protected $min;
/** /**
* @type HTMLPurifier_Length|string * @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.
*/ */
protected $max; public function __construct($min = null, $max = null) {
/**
* @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->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
$this->max = $max !== null ? HTMLPurifier_Length::make($max) : 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); $string = $this->parseCDATA($string);
// Optimizations // Optimizations
if ($string === '') { if ($string === '') return false;
return false; if ($string === '0') return '0';
} if (strlen($string) === 1) return false;
if ($string === '0') {
return '0';
}
if (strlen($string) === 1) {
return false;
}
$length = HTMLPurifier_Length::make($string); $length = HTMLPurifier_Length::make($string);
if (!$length->isValid()) { if (!$length->isValid()) return false;
return false;
}
if ($this->min) { if ($this->min) {
$c = $length->compareTo($this->min); $c = $length->compareTo($this->min);
if ($c === false) { if ($c === false) return false;
return false; if ($c < 0) return false;
}
if ($c < 0) {
return false;
}
} }
if ($this->max) { if ($this->max) {
$c = $length->compareTo($this->max); $c = $length->compareTo($this->max);
if ($c === false) { if ($c === false) return false;
return false; if ($c > 0) return false;
}
if ($c > 0) {
return false;
}
} }
return $length->toString(); return $length->toString();
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,72 +8,46 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
{ {
/** /**
* Local copy of validators. * Local copy of component validators.
* @type HTMLPurifier_AttrDef[]
* @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl. * @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
*/ */
protected $info; protected $info;
/** public function __construct($config) {
* @param HTMLPurifier_Config $config
*/
public function __construct($config)
{
$def = $config->getCSSDefinition(); $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-position'] = $def->info['list-style-position'];
$this->info['list-style-image'] = $def->info['list-style-image']; $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 // regular pre-processing
$string = $this->parseCDATA($string); $string = $this->parseCDATA($string);
if ($string === '') { if ($string === '') return false;
return false;
}
// assumes URI doesn't have spaces in it // assumes URI doesn't have spaces in it
$bits = explode(' ', strtolower($string)); // bits to process $bits = explode(' ', strtolower($string)); // bits to process
$caught = array(); $caught = array();
$caught['type'] = false; $caught['type'] = false;
$caught['position'] = false; $caught['position'] = false;
$caught['image'] = false; $caught['image'] = false;
$i = 0; // number of catches $i = 0; // number of catches
$none = false; $none = false;
foreach ($bits as $bit) { foreach ($bits as $bit) {
if ($i >= 3) { if ($i >= 3) return; // optimization bit
return; if ($bit === '') continue;
} // optimization bit
if ($bit === '') {
continue;
}
foreach ($caught as $key => $status) { foreach ($caught as $key => $status) {
if ($status !== false) { if ($status !== false) continue;
continue;
}
$r = $this->info['list-style-' . $key]->validate($bit, $config, $context); $r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
if ($r === false) { if ($r === false) continue;
continue;
}
if ($r === 'none') { if ($r === 'none') {
if ($none) { if ($none) continue;
continue; else $none = true;
} else { if ($key == 'image') continue;
$none = true;
}
if ($key == 'image') {
continue;
}
} }
$caught[$key] = $r; $caught[$key] = $r;
$i++; $i++;
@@ -81,32 +55,24 @@ class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
} }
} }
if (!$i) { if (!$i) return false;
return false;
}
$ret = array(); $ret = array();
// construct type // construct type
if ($caught['type']) { if ($caught['type']) $ret[] = $caught['type'];
$ret[] = $caught['type'];
}
// construct image // construct image
if ($caught['image']) { if ($caught['image']) $ret[] = $caught['image'];
$ret[] = $caught['image'];
}
// construct position // construct position
if ($caught['position']) { if ($caught['position']) $ret[] = $caught['position'];
$ret[] = $caught['position'];
}
if (empty($ret)) { if (empty($ret)) return false;
return false;
}
return implode(' ', $ret); return implode(' ', $ret);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -13,9 +13,9 @@
*/ */
class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
{ {
/** /**
* Instance of component definition to defer validation to. * Instance of component definition to defer validation to.
* @type HTMLPurifier_AttrDef
* @todo Make protected * @todo Make protected
*/ */
public $single; public $single;
@@ -27,45 +27,32 @@ class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
public $max; public $max;
/** /**
* @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply * @param $single HTMLPurifier_AttrDef to multiply
* @param int $max Max number of values allowed (usually four) * @param $max Max number of values allowed (usually four)
*/ */
public function __construct($single, $max = 4) public function __construct($single, $max = 4) {
{
$this->single = $single; $this->single = $single;
$this->max = $max; $this->max = $max;
} }
/** public function validate($string, $config, $context) {
* @param string $string $string = $this->parseCDATA($string);
* @param HTMLPurifier_Config $config if ($string === '') return false;
* @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 $parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
$length = count($parts); $length = count($parts);
$final = ''; $final = '';
for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) { for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
if (ctype_space($parts[$i])) { if (ctype_space($parts[$i])) continue;
continue;
}
$result = $this->single->validate($parts[$i], $config, $context); $result = $this->single->validate($parts[$i], $config, $context);
if ($result !== false) { if ($result !== false) {
$final .= $result . ' '; $final .= $result . ' ';
$num++; $num++;
} }
} }
if ($final === '') { if ($final === '') return false;
return false;
}
return rtrim($final); return rtrim($final);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,44 +7,32 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
{ {
/** /**
* Indicates whether or not only positive values are allowed. * Bool indicating whether or not only positive values allowed.
* @type bool
*/ */
protected $non_negative = false; protected $non_negative = false;
/** /**
* @param bool $non_negative indicates whether negatives are forbidden * @param $non_negative Bool indicating whether negatives are forbidden
*/ */
public function __construct($non_negative = false) public function __construct($non_negative = false) {
{
$this->non_negative = $non_negative; $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 * @warning Some contexts do not pass $config, $context. These
* variables should not be used without checking HTMLPurifier_Length * 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); $number = $this->parseCDATA($number);
if ($number === '') { if ($number === '') return false;
return false; if ($number === '0') return '0';
}
if ($number === '0') {
return '0';
}
$sign = ''; $sign = '';
switch ($number[0]) { switch ($number[0]) {
case '-': case '-':
if ($this->non_negative) { if ($this->non_negative) return false;
return false;
}
$sign = '-'; $sign = '-';
case '+': case '+':
$number = substr($number, 1); $number = substr($number, 1);
@@ -56,26 +44,14 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
} }
// Period is the only non-numeric character allowed // Period is the only non-numeric character allowed
if (strpos($number, '.') === false) { if (strpos($number, '.') === false) return false;
return false;
}
list($left, $right) = explode('.', $number, 2); list($left, $right) = explode('.', $number, 2);
if ($left === '' && $right === '') { if ($left === '' && $right === '') return false;
return false; if ($left !== '' && !ctype_digit($left)) return false;
}
if ($left !== '' && !ctype_digit($left)) {
return false;
}
// Remove leading zeros until positive number or a zero stays left
if (ltrim($left, '0') != '') {
$left = ltrim($left, '0');
} else {
$left = '0';
}
$left = ltrim($left, '0');
$right = rtrim($right, '0'); $right = rtrim($right, '0');
if ($right === '') { if ($right === '') {
@@ -83,8 +59,11 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
} elseif (!ctype_digit($right)) { } elseif (!ctype_digit($right)) {
return false; return false;
} }
return $sign . $left . '.' . $right; return $sign . $left . '.' . $right;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,48 +7,34 @@ class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
{ {
/** /**
* Instance to defer number validation to. * Instance of HTMLPurifier_AttrDef_CSS_Number to defer number validation
* @type HTMLPurifier_AttrDef_CSS_Number
*/ */
protected $number_def; protected $number_def;
/** /**
* @param bool $non_negative Whether to forbid negative values * @param Bool indicating 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); $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); $string = $this->parseCDATA($string);
if ($string === '') { if ($string === '') return false;
return false;
}
$length = strlen($string); $length = strlen($string);
if ($length === 1) { if ($length === 1) return false;
return false; if ($string[$length - 1] !== '%') return false;
}
if ($string[$length - 1] !== '%') {
return false;
}
$number = substr($string, 0, $length - 1); $number = substr($string, 0, $length - 1);
$number = $this->number_def->validate($number, $config, $context); $number = $this->number_def->validate($number, $config, $context);
if ($number === false) { if ($number === false) return false;
return false;
}
return "$number%"; return "$number%";
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -1,46 +0,0 @@
<?php
/**
* Validates a ratio as defined by the CSS spec.
*/
class HTMLPurifier_AttrDef_CSS_Ratio extends HTMLPurifier_AttrDef
{
/**
* @param string $ratio Ratio to validate
* @param HTMLPurifier_Config $config Configuration options
* @param HTMLPurifier_Context $context Context
*
* @return string|boolean
*
* @warning Some contexts do not pass $config, $context. These
* variables should not be used without checking HTMLPurifier_Length
*/
public function validate($ratio, $config, $context)
{
$ratio = $this->parseCDATA($ratio);
$parts = explode('/', $ratio, 2);
$length = count($parts);
if ($length < 1 || $length > 2) {
return false;
}
$num = new \HTMLPurifier_AttrDef_CSS_Number();
if ($length === 1) {
return $num->validate($parts[0], $config, $context);
}
$num1 = $num->validate($parts[0], $config, $context);
$num2 = $num->validate($parts[1], $config, $context);
if ($num1 === false || $num2 === false) {
return false;
}
return $num1 . '/' . $num2;
}
}
// vim: et sw=4 sts=4

View File

@@ -8,14 +8,8 @@
class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef 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( static $allowed_values = array(
'line-through' => true, 'line-through' => true,
'overline' => true, 'overline' => true,
@@ -24,9 +18,7 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
$string = strtolower($this->parseCDATA($string)); $string = strtolower($this->parseCDATA($string));
if ($string === 'none') { if ($string === 'none') return $string;
return $string;
}
$parts = explode(' ', $string); $parts = explode(' ', $string);
$final = ''; $final = '';
@@ -36,11 +28,11 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
} }
} }
$final = rtrim($final); $final = rtrim($final);
if ($final === '') { if ($final === '') return false;
return false;
}
return $final; return $final;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -12,42 +12,25 @@
class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
{ {
public function __construct() public function __construct() {
{
parent::__construct(true); // always embedded 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 // parse the URI out of the string and then pass it onto
// the parent object // the parent object
$uri_string = $this->parseCDATA($uri_string); $uri_string = $this->parseCDATA($uri_string);
if (strpos($uri_string, 'url(') !== 0) { if (strpos($uri_string, 'url(') !== 0) return false;
return false;
}
$uri_string = substr($uri_string, 4); $uri_string = substr($uri_string, 4);
if (strlen($uri_string) == 0) {
return false;
}
$new_length = strlen($uri_string) - 1; $new_length = strlen($uri_string) - 1;
if ($uri_string[$new_length] != ')') { if ($uri_string[$new_length] != ')') return false;
return false;
}
$uri = trim(substr($uri_string, 0, $new_length)); $uri = trim(substr($uri_string, 0, $new_length));
if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) { if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
$quote = $uri[0]; $quote = $uri[0];
$new_length = strlen($uri) - 1; $new_length = strlen($uri) - 1;
if ($uri[$new_length] !== $quote) { if ($uri[$new_length] !== $quote) return false;
return false;
}
$uri = substr($uri, 1, $new_length - 1); $uri = substr($uri, 1, $new_length - 1);
} }
@@ -55,9 +38,7 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
$result = parent::validate($uri, $config, $context); $result = parent::validate($uri, $config, $context);
if ($result === false) { if ($result === false) return false;
return false;
}
// extra sanity check; should have been done by URI // extra sanity check; should have been done by URI
$result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result); $result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
@@ -70,8 +51,11 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
// an innerHTML cycle, so a very unlucky query parameter could // an innerHTML cycle, so a very unlucky query parameter could
// then change the meaning of the URL. Unfortunately, there's // then change the meaning of the URL. Unfortunately, there's
// not much we can do about that... // not much we can do about that...
return "url(\"$result\")"; return "url(\"$result\")";
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,38 +7,22 @@
class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
{ {
/** /**
* What we're cloning. * What we're cloning
* @type HTMLPurifier_AttrDef
*/ */
protected $clone; protected $clone;
/** public function __construct($clone) {
* @param HTMLPurifier_AttrDef $clone
*/
public function __construct($clone)
{
$this->clone = $clone; $this->clone = $clone;
} }
/** public function validate($v, $config, $context) {
* @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); return $this->clone->validate($v, $config, $context);
} }
/** public function make($string) {
* @param string $string
* @return HTMLPurifier_AttrDef
*/
public function make($string)
{
return clone $this->clone; return clone $this->clone;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -12,10 +12,9 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
/** /**
* Lookup table of valid values. * Lookup table of valid values.
* @type array
* @todo Make protected * @todo Make protected
*/ */
public $valid_values = array(); public $valid_values = array();
/** /**
* Bool indicating whether or not enumeration is case sensitive. * Bool indicating whether or not enumeration is case sensitive.
@@ -24,23 +23,17 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
protected $case_sensitive = false; // values according to W3C spec protected $case_sensitive = false; // values according to W3C spec
/** /**
* @param array $valid_values List of valid values * @param $valid_values List of valid values
* @param bool $case_sensitive Whether or not case sensitive * @param $case_sensitive Bool indicating 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->valid_values = array_flip($valid_values);
$this->case_sensitive = $case_sensitive; $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); $string = trim($string);
if (!$this->case_sensitive) { if (!$this->case_sensitive) {
// we may want to do full case-insensitive libraries // we may want to do full case-insensitive libraries
@@ -52,13 +45,11 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
} }
/** /**
* @param string $string In form of comma-delimited list of case-insensitive * @param $string In form of comma-delimited list of case-insensitive
* valid values. Example: "foo,bar,baz". Prepend "s:" to make * valid values. Example: "foo,bar,baz". Prepend "s:" to make
* case sensitive * case sensitive
* @return HTMLPurifier_AttrDef_Enum
*/ */
public function make($string) public function make($string) {
{
if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') { if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
$string = substr($string, 2); $string = substr($string, 2);
$sensitive = true; $sensitive = true;
@@ -68,6 +59,7 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
$values = explode(',', $string); $values = explode(',', $string);
return new HTMLPurifier_AttrDef_Enum($values, $sensitive); return new HTMLPurifier_AttrDef_Enum($values, $sensitive);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,43 +6,23 @@
class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
{ {
/**
* @type string
*/
protected $name; protected $name;
/**
* @type bool
*/
public $minimized = true; public $minimized = true;
/** public function __construct($name = false) {$this->name = $name;}
* @param bool|string $name
*/
public function __construct($name = false)
{
$this->name = $name;
}
/** public function validate($string, $config, $context) {
* @param string $string if (empty($string)) return false;
* @param HTMLPurifier_Config $config
* @param HTMLPurifier_Context $context
* @return bool|string
*/
public function validate($string, $config, $context)
{
return $this->name; return $this->name;
} }
/** /**
* @param string $string Name of attribute * @param $string Name of attribute
* @return HTMLPurifier_AttrDef_HTML_Bool
*/ */
public function make($string) public function make($string) {
{
return new HTMLPurifier_AttrDef_HTML_Bool($string); return new HTMLPurifier_AttrDef_HTML_Bool($string);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -5,14 +5,7 @@
*/ */
class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens 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 // really, this twiddle should be lazy loaded
$name = $config->getDefinition('HTML')->doctype->name; $name = $config->getDefinition('HTML')->doctype->name;
if ($name == "XHTML 1.1" || $name == "XHTML 2.0") { if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
@@ -21,20 +14,13 @@ class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
return preg_split('/\s+/', $string); 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'); $allowed = $config->get('Attr.AllowedClasses');
$forbidden = $config->get('Attr.ForbiddenClasses'); $forbidden = $config->get('Attr.ForbiddenClasses');
$ret = array(); $ret = array();
foreach ($tokens as $token) { foreach ($tokens as $token) {
if (($allowed === null || isset($allowed[$token])) && if (
($allowed === null || isset($allowed[$token])) &&
!isset($forbidden[$token]) && !isset($forbidden[$token]) &&
// We need this O(n) check because of PHP's array // We need this O(n) check because of PHP's array
// implementation that casts -0 to 0. // implementation that casts -0 to 0.

View File

@@ -6,46 +6,28 @@
class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef 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; static $colors = null;
if ($colors === null) { if ($colors === null) $colors = $config->get('Core.ColorKeywords');
$colors = $config->get('Core.ColorKeywords');
}
$string = trim($string); $string = trim($string);
if (empty($string)) { if (empty($string)) return false;
return false;
}
$lower = strtolower($string); $lower = strtolower($string);
if (isset($colors[$lower])) { if (isset($colors[$lower])) return $colors[$lower];
return $colors[$lower]; if ($string[0] === '#') $hex = substr($string, 1);
} else $hex = $string;
if ($string[0] === '#') {
$hex = substr($string, 1);
} else {
$hex = $string;
}
$length = strlen($hex); $length = strlen($hex);
if ($length !== 3 && $length !== 6) { if ($length !== 3 && $length !== 6) return false;
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 (!ctype_xdigit($hex)) {
return false;
}
if ($length === 3) {
$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
}
return "#$hex"; return "#$hex";
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -1,16 +0,0 @@
<?php
class HTMLPurifier_AttrDef_HTML_ContentEditable extends HTMLPurifier_AttrDef
{
public function validate($string, $config, $context)
{
$allowed = array('false');
if ($config->get('HTML.Trusted')) {
$allowed = array('', 'true', 'false');
}
$enum = new HTMLPurifier_AttrDef_Enum($allowed);
return $enum->validate($string, $config, $context);
}
}

View File

@@ -6,33 +6,16 @@
class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
{ {
/**
* @type array
*/
public $valid_values = false; // uninitialized value public $valid_values = false; // uninitialized value
/**
* @type bool
*/
protected $case_sensitive = false; protected $case_sensitive = false;
public function __construct() public function __construct() {}
{
}
/** public function validate($string, $config, $context) {
* @param string $string if ($this->valid_values === false) $this->valid_values = $config->get('Attr.AllowedFrameTargets');
* @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); return parent::validate($string, $config, $context);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -18,80 +18,47 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
/** /**
* Determines whether or not we're validating an ID in a CSS * Determines whether or not we're validating an ID in a CSS
* selector context. * selector context.
* @type bool
*/ */
protected $selector; protected $selector;
/** public function __construct($selector = false) {
* @param bool $selector
*/
public function __construct($selector = false)
{
$this->selector = $selector; $this->selector = $selector;
} }
/** public function validate($id, $config, $context) {
* @param string $id
* @param HTMLPurifier_Config $config if (!$this->selector && !$config->get('Attr.EnableID')) return false;
* @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 $id = trim($id); // trim it first
if ($id === '') { if ($id === '') return false;
return false;
}
$prefix = $config->get('Attr.IDPrefix'); $prefix = $config->get('Attr.IDPrefix');
if ($prefix !== '') { if ($prefix !== '') {
$prefix .= $config->get('Attr.IDPrefixLocal'); $prefix .= $config->get('Attr.IDPrefixLocal');
// prevent re-appending the prefix // prevent re-appending the prefix
if (strpos($id, $prefix) !== 0) { if (strpos($id, $prefix) !== 0) $id = $prefix . $id;
$id = $prefix . $id;
}
} elseif ($config->get('Attr.IDPrefixLocal') !== '') { } elseif ($config->get('Attr.IDPrefixLocal') !== '') {
trigger_error( trigger_error('%Attr.IDPrefixLocal cannot be used unless '.
'%Attr.IDPrefixLocal cannot be used unless ' . '%Attr.IDPrefix is set', E_USER_WARNING);
'%Attr.IDPrefix is set',
E_USER_WARNING
);
} }
if (!$this->selector) { if (!$this->selector) {
$id_accumulator =& $context->get('IDAccumulator'); $id_accumulator =& $context->get('IDAccumulator');
if (isset($id_accumulator->ids[$id])) { if (isset($id_accumulator->ids[$id])) return false;
return false;
}
} }
// we purposely avoid using regex, hopefully this is faster // we purposely avoid using regex, hopefully this is faster
if ($config->get('Attr.ID.HTML5') === true) { if (ctype_alpha($id)) {
if (preg_match('/[\t\n\x0b\x0c ]/', $id)) { $result = true;
return false;
}
} else { } else {
if (ctype_alpha($id)) { if (!ctype_alpha(@$id[0])) return false;
// OK $trim = trim( // primitive style of regexps, I suppose
} else { $id,
if (!ctype_alpha(@$id[0])) { 'A..Za..z0..9:-._'
return false; );
} $result = ($trim === '');
// primitive style of regexps, I suppose
$trim = trim(
$id,
'A..Za..z0..9:-._'
);
if ($trim !== '') {
return false;
}
}
} }
$regexp = $config->get('Attr.IDBlacklistRegexp'); $regexp = $config->get('Attr.IDBlacklistRegexp');
@@ -99,15 +66,15 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
return false; return false;
} }
if (!$this->selector) { if (!$this->selector && $result) $id_accumulator->add($id);
$id_accumulator->add($id);
}
// if no change was made to the ID, return the result // if no change was made to the ID, return the result
// else, return the new id if stripping whitespace made it // else, return the new id if stripping whitespace made it
// valid, or return false. // valid, or return false.
return $id; return $result ? $id : false;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -10,47 +10,32 @@
class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels 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); $string = trim($string);
if ($string === '') { if ($string === '') return false;
return false;
}
$parent_result = parent::validate($string, $config, $context); $parent_result = parent::validate($string, $config, $context);
if ($parent_result !== false) { if ($parent_result !== false) return $parent_result;
return $parent_result;
}
$length = strlen($string); $length = strlen($string);
$last_char = $string[$length - 1]; $last_char = $string[$length - 1];
if ($last_char !== '%') { if ($last_char !== '%') return false;
return false;
}
$points = substr($string, 0, $length - 1); $points = substr($string, 0, $length - 1);
if (!is_numeric($points)) { if (!is_numeric($points)) return false;
return false;
}
$points = (int)$points; $points = (int) $points;
if ($points < 0) return '0%';
if ($points > 100) return '100%';
return ((string) $points) . '%';
if ($points < 0) {
return '0%';
}
if ($points > 100) {
return '100%';
}
return ((string)$points) . '%';
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -9,44 +9,26 @@
class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
{ {
/** /** Name config attribute to pull. */
* Name config attribute to pull.
* @type string
*/
protected $name; protected $name;
/** public function __construct($name) {
* @param string $name
*/
public function __construct($name)
{
$configLookup = array( $configLookup = array(
'rel' => 'AllowedRel', 'rel' => 'AllowedRel',
'rev' => 'AllowedRev' 'rev' => 'AllowedRev'
); );
if (!isset($configLookup[$name])) { if (!isset($configLookup[$name])) {
trigger_error( trigger_error('Unrecognized attribute name for link '.
'Unrecognized attribute name for link ' . 'relationship.', E_USER_ERROR);
'relationship.',
E_USER_ERROR
);
return; return;
} }
$this->name = $configLookup[$name]; $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); $allowed = $config->get('Attr.' . $this->name);
if (empty($allowed)) { if (empty($allowed)) return false;
return false;
}
$string = $this->parseCDATA($string); $string = $this->parseCDATA($string);
$parts = explode(' ', $string); $parts = explode(' ', $string);
@@ -55,18 +37,17 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
$ret_lookup = array(); $ret_lookup = array();
foreach ($parts as $part) { foreach ($parts as $part) {
$part = strtolower(trim($part)); $part = strtolower(trim($part));
if (!isset($allowed[$part])) { if (!isset($allowed[$part])) continue;
continue;
}
$ret_lookup[$part] = true; $ret_lookup[$part] = true;
} }
if (empty($ret_lookup)) { if (empty($ret_lookup)) return false;
return false;
}
$string = implode(' ', array_keys($ret_lookup)); $string = implode(' ', array_keys($ret_lookup));
return $string; return $string;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -9,52 +9,33 @@
class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length 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); $string = trim($string);
if ($string === '') { if ($string === '') return false;
return false;
}
$parent_result = parent::validate($string, $config, $context); $parent_result = parent::validate($string, $config, $context);
if ($parent_result !== false) { if ($parent_result !== false) return $parent_result;
return $parent_result;
}
$length = strlen($string); $length = strlen($string);
$last_char = $string[$length - 1]; $last_char = $string[$length - 1];
if ($last_char !== '*') { if ($last_char !== '*') return false;
return false;
}
$int = substr($string, 0, $length - 1); $int = substr($string, 0, $length - 1);
if ($int == '') { if ($int == '') return '*';
return '*'; if (!is_numeric($int)) return false;
}
if (!is_numeric($int)) { $int = (int) $int;
return false;
} if ($int < 0) return false;
if ($int == 0) return '0';
if ($int == 1) return '*';
return ((string) $int) . '*';
$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 // vim: et sw=4 sts=4

View File

@@ -6,38 +6,24 @@
class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef 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); $string = trim($string);
// early abort: '' and '0' (strings that convert to false) are invalid // early abort: '' and '0' (strings that convert to false) are invalid
if (!$string) { if (!$string) return false;
return false;
}
$tokens = $this->split($string, $config, $context); $tokens = $this->split($string, $config, $context);
$tokens = $this->filter($tokens, $config, $context); $tokens = $this->filter($tokens, $config, $context);
if (empty($tokens)) { if (empty($tokens)) return false;
return false;
}
return implode(' ', $tokens); return implode(' ', $tokens);
} }
/** /**
* Splits a space separated list of tokens into its constituent parts. * 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! // OPTIMIZABLE!
// do the preg_match, capture all subpatterns for reformulation // do the preg_match, capture all subpatterns for reformulation
@@ -45,9 +31,9 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
// escaping because I don't know how to do that with regexps // escaping because I don't know how to do that with regexps
// and plus it would complicate optimization efforts (you never // and plus it would complicate optimization efforts (you never
// see that anyway). // see that anyway).
$pattern = '/(?:(?<=\s)|\A)' . // look behind for space or string start $pattern = '/(?:(?<=\s)|\A)'. // look behind for space or string start
'((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)' . '((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)'.
'(?:(?=\s)|\z)/'; // look ahead for space or string end '(?:(?=\s)|\z)/'; // look ahead for space or string end
preg_match_all($pattern, $string, $matches); preg_match_all($pattern, $string, $matches);
return $matches[1]; return $matches[1];
} }
@@ -56,15 +42,11 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
* Template method for removing certain tokens based on arbitrary criteria. * Template method for removing certain tokens based on arbitrary criteria.
* @note If we wanted to be really functional, we'd do an array_filter * @note If we wanted to be really functional, we'd do an array_filter
* with a callback. But... we're not. * 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; return $tokens;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,71 +6,43 @@
class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
{ {
/**
* @type int
*/
protected $max; protected $max;
/** public function __construct($max = null) {
* @param int $max
*/
public function __construct($max = null)
{
$this->max = $max; $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); $string = trim($string);
if ($string === '0') { if ($string === '0') return $string;
return $string; if ($string === '') return false;
}
if ($string === '') {
return false;
}
$length = strlen($string); $length = strlen($string);
if (substr($string, $length - 2) == 'px') { if (substr($string, $length - 2) == 'px') {
$string = substr($string, 0, $length - 2); $string = substr($string, 0, $length - 2);
} }
if (!is_numeric($string)) { if (!is_numeric($string)) return false;
return false; $int = (int) $string;
}
$int = (int)$string;
if ($int < 0) { if ($int < 0) return '0';
return '0';
}
// upper-bound value, extremely high values can // upper-bound value, extremely high values can
// crash operating systems, see <http://ha.ckers.org/imagecrash.html> // crash operating systems, see <http://ha.ckers.org/imagecrash.html>
// WARNING, above link WILL crash you if you're using Windows // WARNING, above link WILL crash you if you're using Windows
if ($this->max !== null && $int > $this->max) { if ($this->max !== null && $int > $this->max) return (string) $this->max;
return (string)$this->max;
} return (string) $int;
return (string)$int;
} }
/** public function make($string) {
* @param string $string if ($string === '') $max = null;
* @return HTMLPurifier_AttrDef else $max = (int) $string;
*/
public function make($string)
{
if ($string === '') {
$max = null;
} else {
$max = (int)$string;
}
$class = get_class($this); $class = get_class($this);
return new $class($max); return new $class($max);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -11,20 +11,17 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
{ {
/** /**
* Whether or not negative values are allowed. * Bool indicating whether or not negative values are allowed
* @type bool
*/ */
protected $negative = true; protected $negative = true;
/** /**
* Whether or not zero is allowed. * Bool indicating whether or not zero is allowed
* @type bool
*/ */
protected $zero = true; protected $zero = true;
/** /**
* Whether or not positive values are allowed. * Bool indicating whether or not positive values are allowed
* @type bool
*/ */
protected $positive = true; protected $positive = true;
@@ -33,59 +30,44 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
* @param $zero Bool indicating whether or not zero is allowed * @param $zero Bool indicating whether or not zero is allowed
* @param $positive Bool indicating whether or not positive values are 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->negative = $negative;
$this->zero = $zero; $this->zero = $zero;
$this->positive = $positive; $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); $integer = $this->parseCDATA($integer);
if ($integer === '') { if ($integer === '') return false;
return false;
}
// we could possibly simply typecast it to integer, but there are // we could possibly simply typecast it to integer, but there are
// certain fringe cases that must not return an integer. // certain fringe cases that must not return an integer.
// clip leading sign // clip leading sign
if ($this->negative && $integer[0] === '-') { if ( $this->negative && $integer[0] === '-' ) {
$digits = substr($integer, 1); $digits = substr($integer, 1);
if ($digits === '0') { if ($digits === '0') $integer = '0'; // rm minus sign for zero
$integer = '0'; } elseif( $this->positive && $integer[0] === '+' ) {
} // rm minus sign for zero
} elseif ($this->positive && $integer[0] === '+') {
$digits = $integer = substr($integer, 1); // rm unnecessary plus $digits = $integer = substr($integer, 1); // rm unnecessary plus
} else { } else {
$digits = $integer; $digits = $integer;
} }
// test if it's numeric // test if it's numeric
if (!ctype_digit($digits)) { if (!ctype_digit($digits)) return false;
return false;
}
// perform scope tests // perform scope tests
if (!$this->zero && $integer == 0) { if (!$this->zero && $integer == 0) return false;
return false; if (!$this->positive && $integer > 0) return false;
} if (!$this->negative && $integer < 0) return false;
if (!$this->positive && $integer > 0) {
return false;
}
if (!$this->negative && $integer < 0) {
return false;
}
return $integer; return $integer;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,25 +7,15 @@
class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef 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); $string = trim($string);
if (!$string) { if (!$string) return false;
return false;
}
$subtags = explode('-', $string); $subtags = explode('-', $string);
$num_subtags = count($subtags); $num_subtags = count($subtags);
if ($num_subtags == 0) { // sanity check if ($num_subtags == 0) return false; // sanity check
return false;
}
// process primary subtag : $subtags[0] // process primary subtag : $subtags[0]
$length = strlen($subtags[0]); $length = strlen($subtags[0]);
@@ -33,15 +23,15 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
case 0: case 0:
return false; return false;
case 1: case 1:
if (!($subtags[0] == 'x' || $subtags[0] == 'i')) { if (! ($subtags[0] == 'x' || $subtags[0] == 'i') ) {
return false; return false;
} }
break; break;
case 2: case 2:
case 3: case 3:
if (!ctype_alpha($subtags[0])) { if (! ctype_alpha($subtags[0]) ) {
return false; return false;
} elseif (!ctype_lower($subtags[0])) { } elseif (! ctype_lower($subtags[0]) ) {
$subtags[0] = strtolower($subtags[0]); $subtags[0] = strtolower($subtags[0]);
} }
break; break;
@@ -50,23 +40,17 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
} }
$new_string = $subtags[0]; $new_string = $subtags[0];
if ($num_subtags == 1) { if ($num_subtags == 1) return $new_string;
return $new_string;
}
// process second subtag : $subtags[1] // process second subtag : $subtags[1]
$length = strlen($subtags[1]); $length = strlen($subtags[1]);
if ($length == 0 || ($length == 1 && $subtags[1] != 'x') || $length > 8 || !ctype_alnum($subtags[1])) { if ($length == 0 || ($length == 1 && $subtags[1] != 'x') || $length > 8 || !ctype_alnum($subtags[1])) {
return $new_string; return $new_string;
} }
if (!ctype_lower($subtags[1])) { if (!ctype_lower($subtags[1])) $subtags[1] = strtolower($subtags[1]);
$subtags[1] = strtolower($subtags[1]);
}
$new_string .= '-' . $subtags[1]; $new_string .= '-' . $subtags[1];
if ($num_subtags == 2) { if ($num_subtags == 2) return $new_string;
return $new_string;
}
// process all other subtags, index 2 and up // process all other subtags, index 2 and up
for ($i = 2; $i < $num_subtags; $i++) { for ($i = 2; $i < $num_subtags; $i++) {
@@ -79,8 +63,11 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
} }
$new_string .= '-' . $subtags[$i]; $new_string .= '-' . $subtags[$i];
} }
return $new_string; return $new_string;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,41 +6,21 @@
class HTMLPurifier_AttrDef_Switch class HTMLPurifier_AttrDef_Switch
{ {
/**
* @type string
*/
protected $tag; protected $tag;
protected $withTag, $withoutTag;
/**
* @type HTMLPurifier_AttrDef
*/
protected $withTag;
/**
* @type HTMLPurifier_AttrDef
*/
protected $withoutTag;
/** /**
* @param string $tag Tag name to switch upon * @param string $tag Tag name to switch upon
* @param HTMLPurifier_AttrDef $with_tag Call if token matches tag * @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 * @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->tag = $tag;
$this->withTag = $with_tag; $this->withTag = $with_tag;
$this->withoutTag = $without_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); $token = $context->get('CurrentToken', true);
if (!$token || $token->name !== $this->tag) { if (!$token || $token->name !== $this->tag) {
return $this->withoutTag->validate($string, $config, $context); return $this->withoutTag->validate($string, $config, $context);
@@ -48,6 +28,7 @@ class HTMLPurifier_AttrDef_Switch
return $this->withTag->validate($string, $config, $context); return $this->withTag->validate($string, $config, $context);
} }
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,16 +6,10 @@
class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef 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); return $this->parseCDATA($string);
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,54 +7,31 @@
class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
{ {
/**
* @type HTMLPurifier_URIParser
*/
protected $parser; protected $parser;
/**
* @type bool
*/
protected $embedsResource; protected $embedsResource;
/** /**
* @param bool $embeds_resource Does the URI here result in an extra HTTP request? * @param $embeds_resource_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->parser = new HTMLPurifier_URIParser();
$this->embedsResource = (bool)$embeds_resource; $this->embedsResource = (bool) $embeds_resource;
} }
/** public function make($string) {
* @param string $string
* @return HTMLPurifier_AttrDef_URI
*/
public function make($string)
{
$embeds = ($string === 'embedded'); $embeds = ($string === 'embedded');
return new HTMLPurifier_AttrDef_URI($embeds); return new HTMLPurifier_AttrDef_URI($embeds);
} }
/** public function validate($uri, $config, $context) {
* @param string $uri
* @param HTMLPurifier_Config $config if ($config->get('URI.Disable')) return false;
* @param HTMLPurifier_Context $context
* @return bool|string
*/
public function validate($uri, $config, $context)
{
if ($config->get('URI.Disable')) {
return false;
}
$uri = $this->parseCDATA($uri); $uri = $this->parseCDATA($uri);
// parse the URI // parse the URI
$uri = $this->parser->parse($uri); $uri = $this->parser->parse($uri);
if ($uri === false) { if ($uri === false) return false;
return false;
}
// add embedded flag to context for validators // add embedded flag to context for validators
$context->register('EmbeddedURI', $this->embedsResource); $context->register('EmbeddedURI', $this->embedsResource);
@@ -64,35 +41,23 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
// generic validation // generic validation
$result = $uri->validate($config, $context); $result = $uri->validate($config, $context);
if (!$result) { if (!$result) break;
break;
}
// chained filtering // chained filtering
$uri_def = $config->getDefinition('URI'); $uri_def = $config->getDefinition('URI');
$result = $uri_def->filter($uri, $config, $context); $result = $uri_def->filter($uri, $config, $context);
if (!$result) { if (!$result) break;
break;
}
// scheme-specific validation // scheme-specific validation
$scheme_obj = $uri->getSchemeObj($config, $context); $scheme_obj = $uri->getSchemeObj($config, $context);
if (!$scheme_obj) { if (!$scheme_obj) break;
break; if ($this->embedsResource && !$scheme_obj->browsable) break;
}
if ($this->embedsResource && !$scheme_obj->browsable) {
break;
}
$result = $scheme_obj->validate($uri, $config, $context); $result = $scheme_obj->validate($uri, $config, $context);
if (!$result) { if (!$result) break;
break;
}
// Post chained filtering // Post chained filtering
$result = $uri_def->postFilter($uri, $config, $context); $result = $uri_def->postFilter($uri, $config, $context);
if (!$result) { if (!$result) break;
break;
}
// survived gauntlet // survived gauntlet
$ok = true; $ok = true;
@@ -100,12 +65,13 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
} while (false); } while (false);
$context->destroy('EmbeddedURI'); $context->destroy('EmbeddedURI');
if (!$ok) { if (!$ok) return false;
return false;
}
// back to string // back to string
return $uri->toString(); return $uri->toString();
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -5,11 +5,8 @@ abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
/** /**
* Unpacks a mailbox into its display-name and address * Unpacks a mailbox into its display-name and address
* @param string $string
* @return mixed
*/ */
public function unpack($string) function unpack($string) {
{
// needs to be implemented // needs to be implemented
} }

View File

@@ -7,23 +7,15 @@
class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_URI_Email 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>" // no support for named mailboxes i.e. "Bob <bob@example.com>"
// that needs more percent encoding to be done // that needs more percent encoding to be done
if ($string == '') { if ($string == '') return false;
return false;
}
$string = trim($string); $string = trim($string);
$result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string); $result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string);
return $result ? $string : false; return $result ? $string : false;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -7,31 +7,21 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
{ {
/** /**
* IPv4 sub-validator. * Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator
* @type HTMLPurifier_AttrDef_URI_IPv4
*/ */
protected $ipv4; protected $ipv4;
/** /**
* IPv6 sub-validator. * Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator
* @type HTMLPurifier_AttrDef_URI_IPv6
*/ */
protected $ipv6; protected $ipv6;
public function __construct() public function __construct() {
{
$this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4(); $this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
$this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6(); $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); $length = strlen($string);
// empty hostname is OK; it's usually semantically equivalent: // empty hostname is OK; it's usually semantically equivalent:
// the default host as defined by a URI scheme is used: // the default host as defined by a URI scheme is used:
@@ -39,68 +29,42 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
// If the URI scheme defines a default for host, then that // If the URI scheme defines a default for host, then that
// default applies when the host subcomponent is undefined // default applies when the host subcomponent is undefined
// or when the registered name is empty (zero length). // or when the registered name is empty (zero length).
if ($string === '') { if ($string === '') return '';
return ''; if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
}
if ($length > 1 && $string[0] === '[' && $string[$length - 1] === ']') {
//IPv6 //IPv6
$ip = substr($string, 1, $length - 2); $ip = substr($string, 1, $length - 2);
$valid = $this->ipv6->validate($ip, $config, $context); $valid = $this->ipv6->validate($ip, $config, $context);
if ($valid === false) { if ($valid === false) return false;
return false; return '['. $valid . ']';
}
return '[' . $valid . ']';
} }
// need to do checks on unusual encodings too // need to do checks on unusual encodings too
$ipv4 = $this->ipv4->validate($string, $config, $context); $ipv4 = $this->ipv4->validate($string, $config, $context);
if ($ipv4 !== false) { if ($ipv4 !== false) return $ipv4;
return $ipv4;
}
// A regular domain name. // A regular domain name.
// This doesn't match I18N domain names, but we don't have proper IRI support, // This doesn't match I18N domain names, but we don't have proper IRI support,
// so force users to insert Punycode. // so force users to insert Punycode.
// Underscores defined as Unreserved Characters in RFC 3986 are
// allowed in a URI. There are cases where we want to consider a
// URI containing "_" such as "_dmarc.example.com".
// Underscores are not allowed in the default. If you want to
// allow it, set Core.AllowHostnameUnderscore to true.
$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: // The productions describing this are:
$a = '[a-z]'; // alpha $a = '[a-z]'; // alpha
$an = "[a-z0-9$underscore]"; // alphanum $an = '[a-z0-9]'; // alphanum
$and = "[a-z0-9-$underscore]"; // alphanum | "-" $and = '[a-z0-9-]'; // alphanum | "-"
// domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
$domainlabel = "$an(?:$and*$an)?"; $domainlabel = "$an($and*$an)?";
// AMENDED as per RFC 3696 // toplabel = alpha | alpha *( alphanum | "-" ) alphanum
// toplabel = alphanum | alphanum *( alphanum | "-" ) alphanum $toplabel = "$a($and*$an)?";
// side condition: not all numeric
$toplabel = "$an(?:$and*$an)?";
// hostname = *( domainlabel "." ) toplabel [ "." ] // hostname = *( domainlabel "." ) toplabel [ "." ]
if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $matches)) { if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
if (!ctype_digit($matches[1])) { return $string;
return $string;
}
} }
// PHP 5.3 and later support this functionality natively
if (function_exists('idn_to_ascii')) {
if (defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46')) {
$string = idn_to_ascii($string, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
} else {
$string = idn_to_ascii($string);
}
// If we have Net_IDNA2 support, we can support IRIs by // If we have Net_IDNA2 support, we can support IRIs by
// punycoding them. (This is the most portable thing to do, // punycoding them. (This is the most portable thing to do,
// since otherwise we have to assume browsers support // since otherwise we have to assume browsers support
} elseif ($config->get('Core.EnableIDNA') && class_exists('Net_IDNA2')) {
if ($config->get('Core.EnableIDNA')) {
$idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true)); $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
// we need to encode each period separately // we need to encode each period separately
$parts = explode('.', $string); $parts = explode('.', $string);
@@ -121,16 +85,17 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
} }
} }
$string = implode('.', $new_parts); $string = implode('.', $new_parts);
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
return $string;
}
} catch (Exception $e) { } catch (Exception $e) {
// XXX error reporting // XXX error reporting
} }
} }
// Try again
if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
return $string;
}
return false; return false;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,38 +8,32 @@ 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; protected $ip4;
/** public function validate($aIP, $config, $context) {
* @param string $aIP
* @param HTMLPurifier_Config $config if (!$this->ip4) $this->_loadRegex();
* @param HTMLPurifier_Context $context
* @return bool|string if (preg_match('#^' . $this->ip4 . '$#s', $aIP))
*/ {
public function validate($aIP, $config, $context) return $aIP;
{
if (!$this->ip4) {
$this->_loadRegex();
} }
if (preg_match('#^' . $this->ip4 . '$#s', $aIP)) {
return $aIP;
}
return false; return false;
} }
/** /**
* Lazy load function to prevent regex from being stuffed in * Lazy load function to prevent regex from being stuffed in
* cache. * 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 $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})"; $this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})";
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -9,81 +9,91 @@
class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4 class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4
{ {
/** public function validate($aIP, $config, $context) {
* @param string $aIP
* @param HTMLPurifier_Config $config if (!$this->ip4) $this->_loadRegex();
* @param HTMLPurifier_Context $context
* @return bool|string
*/
public function validate($aIP, $config, $context)
{
if (!$this->ip4) {
$this->_loadRegex();
}
$original = $aIP; $original = $aIP;
$hex = '[0-9a-fA-F]'; $hex = '[0-9a-fA-F]';
$blk = '(?:' . $hex . '{1,4})'; $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 // prefix check
if (strpos($aIP, '/') !== false) { if (strpos($aIP, '/') !== false)
if (preg_match('#' . $pre . '$#s', $aIP, $find)) { {
$aIP = substr($aIP, 0, 0 - strlen($find[0])); if (preg_match('#' . $pre . '$#s', $aIP, $find))
unset($find); {
} else { $aIP = substr($aIP, 0, 0-strlen($find[0]));
return false; unset($find);
} }
else
{
return false;
}
} }
// IPv4-compatiblity check // IPv4-compatiblity check
if (preg_match('#(?<=:' . ')' . $this->ip4 . '$#s', $aIP, $find)) { if (preg_match('#(?<=:'.')' . $this->ip4 . '$#s', $aIP, $find))
$aIP = substr($aIP, 0, 0 - strlen($find[0])); {
$ip = explode('.', $find[0]); $aIP = substr($aIP, 0, 0-strlen($find[0]));
$ip = array_map('dechex', $ip); $ip = explode('.', $find[0]);
$aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3]; $ip = array_map('dechex', $ip);
unset($find, $ip); $aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
unset($find, $ip);
} }
// compression check // compression check
$aIP = explode('::', $aIP); $aIP = explode('::', $aIP);
$c = count($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; return false;
} }
elseif ($c == 2)
{
list($first, $second) = $aIP;
$first = explode(':', $first);
$second = explode(':', $second);
while (count($first) < 8) { if (count($first) + count($second) > 8)
array_push($first, '0'); {
} return false;
}
array_splice($first, 8 - count($second), 8, $second); while(count($first) < 8)
$aIP = $first; {
unset($first, $second); array_push($first, '0');
} 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); $c = count($aIP);
if ($c != 8) { if ($c != 8)
return false; {
return false;
} }
// All the pieces should be 16-bit hex strings. Are they? // All the pieces should be 16-bit hex strings. Are they?
foreach ($aIP as $piece) { foreach ($aIP as $piece)
if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece))) { {
return false; if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece)))
} {
return false;
}
} }
return $original; return $original;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -20,41 +20,37 @@ abstract class HTMLPurifier_AttrTransform
/** /**
* Abstract: makes changes to the attributes dependent on multiple values. * Abstract: makes changes to the attributes dependent on multiple values.
* *
* @param array $attr Assoc array of attributes, usually from * @param $attr Assoc array of attributes, usually from
* HTMLPurifier_Token_Tag::$attr * HTMLPurifier_Token_Tag::$attr
* @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object. * @param $config Mandatory HTMLPurifier_Config object.
* @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object * @param $context Mandatory HTMLPurifier_Context object
* @return array Processed attribute array. * @returns Processed attribute array.
*/ */
abstract public function transform($attr, $config, $context); abstract public function transform($attr, $config, $context);
/** /**
* Prepends CSS properties to the style attribute, creating the * Prepends CSS properties to the style attribute, creating the
* attribute if it doesn't exist. * attribute if it doesn't exist.
* @param array &$attr Attribute array to process (passed by reference) * @param $attr Attribute array to process (passed by reference)
* @param string $css CSS to prepend * @param $css CSS to prepend
*/ */
public function prependCSS(&$attr, $css) public function prependCSS(&$attr, $css) {
{
$attr['style'] = isset($attr['style']) ? $attr['style'] : ''; $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
$attr['style'] = $css . $attr['style']; $attr['style'] = $css . $attr['style'];
} }
/** /**
* Retrieves and removes an attribute * Retrieves and removes an attribute
* @param array &$attr Attribute array to process (passed by reference) * @param $attr Attribute array to process (passed by reference)
* @param mixed $key Key of attribute to confiscate * @param $key Key of attribute to confiscate
* @return mixed
*/ */
public function confiscateAttr(&$attr, $key) public function confiscateAttr(&$attr, $key) {
{ if (!isset($attr[$key])) return null;
if (!isset($attr[$key])) {
return null;
}
$value = $attr[$key]; $value = $attr[$key];
unset($attr[$key]); unset($attr[$key]);
return $value; return $value;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -3,26 +3,21 @@
/** /**
* Pre-transform that changes proprietary background attribute to CSS. * Pre-transform that changes proprietary background attribute to CSS.
*/ */
class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform {
{
/** public function transform($attr, $config, $context) {
* @param array $attr
* @param HTMLPurifier_Config $config if (!isset($attr['background'])) return $attr;
* @param HTMLPurifier_Context $context
* @return array
*/
public function transform($attr, $config, $context)
{
if (!isset($attr['background'])) {
return $attr;
}
$background = $this->confiscateAttr($attr, 'background'); $background = $this->confiscateAttr($attr, 'background');
// some validation should happen here // some validation should happen here
$this->prependCSS($attr, "background-image:url($background);"); $this->prependCSS($attr, "background-image:url($background);");
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,20 +8,12 @@
class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform
{ {
/** public function transform($attr, $config, $context) {
* @param array $attr if (isset($attr['dir'])) return $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'); $attr['dir'] = $config->get('Attr.DefaultTextDir');
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -3,26 +3,21 @@
/** /**
* Pre-transform that changes deprecated bgcolor attribute to CSS. * Pre-transform that changes deprecated bgcolor attribute to CSS.
*/ */
class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform {
{
/** public function transform($attr, $config, $context) {
* @param array $attr
* @param HTMLPurifier_Config $config if (!isset($attr['bgcolor'])) return $attr;
* @param HTMLPurifier_Context $context
* @return array
*/
public function transform($attr, $config, $context)
{
if (!isset($attr['bgcolor'])) {
return $attr;
}
$bgcolor = $this->confiscateAttr($attr, 'bgcolor'); $bgcolor = $this->confiscateAttr($attr, 'bgcolor');
// some validation should happen here // some validation should happen here
$this->prependCSS($attr, "background-color:$bgcolor;"); $this->prependCSS($attr, "background-color:$bgcolor;");
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -3,45 +3,34 @@
/** /**
* Pre-transform that changes converts a boolean attribute to fixed CSS * 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; protected $attr;
/** /**
* CSS declarations to add to style, needs trailing semicolon. * CSS declarations to add to style, needs trailing semicolon
* @type string
*/ */
protected $css; protected $css;
/** /**
* @param string $attr attribute name to convert from * @param $attr string attribute name to convert from
* @param string $css CSS declarations to add to style (needs semicolon) * @param $css string CSS declarations to add to style (needs semicolon)
*/ */
public function __construct($attr, $css) public function __construct($attr, $css) {
{
$this->attr = $attr; $this->attr = $attr;
$this->css = $css; $this->css = $css;
} }
/** public function transform($attr, $config, $context) {
* @param array $attr if (!isset($attr[$this->attr])) return $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]); unset($attr[$this->attr]);
$this->prependCSS($attr, $this->css); $this->prependCSS($attr, $this->css);
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -3,24 +3,16 @@
/** /**
* Pre-transform that changes deprecated border attribute to CSS. * Pre-transform that changes deprecated border attribute to CSS.
*/ */
class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform {
{
/** public function transform($attr, $config, $context) {
* @param array $attr if (!isset($attr['border'])) return $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'); $border_width = $this->confiscateAttr($attr, 'border');
// some validation should happen here // some validation should happen here
$this->prependCSS($attr, "border:{$border_width}px solid;"); $this->prependCSS($attr, "border:{$border_width}px solid;");
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -4,65 +4,55 @@
* Generic pre-transform that converts an attribute with a fixed number of * Generic pre-transform that converts an attribute with a fixed number of
* values (enumerated) to CSS. * 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; protected $attr;
/** /**
* Lookup array of attribute values to CSS. * Lookup array of attribute values to CSS
* @type array
*/ */
protected $enumToCSS = 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 * @warning Currently can only be guaranteed to work with ASCII
* values. * values.
*/ */
protected $caseSensitive = false; protected $caseSensitive = false;
/** /**
* @param string $attr Attribute name to transform from * @param $attr String attribute name to transform from
* @param array $enum_to_css Lookup array of attribute values to CSS * @param $enumToCSS Lookup array of attribute values to CSS
* @param bool $case_sensitive Case sensitivity indicator, default false * @param $case_sensitive Boolean 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->attr = $attr;
$this->enumToCSS = $enum_to_css; $this->enumToCSS = $enum_to_css;
$this->caseSensitive = (bool)$case_sensitive; $this->caseSensitive = (bool) $case_sensitive;
} }
/** public function transform($attr, $config, $context) {
* @param array $attr
* @param HTMLPurifier_Config $config if (!isset($attr[$this->attr])) return $attr;
* @param HTMLPurifier_Context $context
* @return array
*/
public function transform($attr, $config, $context)
{
if (!isset($attr[$this->attr])) {
return $attr;
}
$value = trim($attr[$this->attr]); $value = trim($attr[$this->attr]);
unset($attr[$this->attr]); unset($attr[$this->attr]);
if (!$this->caseSensitive) { if (!$this->caseSensitive) $value = strtolower($value);
$value = strtolower($value);
}
if (!isset($this->enumToCSS[$value])) { if (!isset($this->enumToCSS[$value])) {
return $attr; return $attr;
} }
$this->prependCSS($attr, $this->enumToCSS[$value]); $this->prependCSS($attr, $this->enumToCSS[$value]);
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -11,19 +11,11 @@
class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform 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; $src = true;
if (!isset($attr['src'])) { if (!isset($attr['src'])) {
if ($config->get('Core.RemoveInvalidImg')) { if ($config->get('Core.RemoveInvalidImg')) return $attr;
return $attr;
}
$attr['src'] = $config->get('Attr.DefaultInvalidImage'); $attr['src'] = $config->get('Attr.DefaultInvalidImage');
$src = false; $src = false;
} }
@@ -32,7 +24,8 @@ class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
if ($src) { if ($src) {
$alt = $config->get('Attr.DefaultImageAlt'); $alt = $config->get('Attr.DefaultImageAlt');
if ($alt === null) { if ($alt === null) {
$attr['alt'] = basename($attr['src']); // truncate if the alt is too long
$attr['alt'] = substr(basename($attr['src']),0,40);
} else { } else {
$attr['alt'] = $alt; $attr['alt'] = $alt;
} }
@@ -40,8 +33,11 @@ class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
$attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt'); $attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt');
} }
} }
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -3,59 +3,42 @@
/** /**
* Pre-transform that changes deprecated hspace and vspace attributes to CSS * 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;
/** protected $attr;
* @type array
*/
protected $css = array( protected $css = array(
'hspace' => array('left', 'right'), 'hspace' => array('left', 'right'),
'vspace' => array('top', 'bottom') 'vspace' => array('top', 'bottom')
); );
/** public function __construct($attr) {
* @param string $attr
*/
public function __construct($attr)
{
$this->attr = $attr; $this->attr = $attr;
if (!isset($this->css[$attr])) { if (!isset($this->css[$attr])) {
trigger_error(htmlspecialchars($attr) . ' is not valid space attribute'); trigger_error(htmlspecialchars($attr) . ' is not valid space attribute');
} }
} }
/** public function transform($attr, $config, $context) {
* @param array $attr
* @param HTMLPurifier_Config $config if (!isset($attr[$this->attr])) return $attr;
* @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); $width = $this->confiscateAttr($attr, $this->attr);
// some validation could happen here // some validation could happen here
if (!isset($this->css[$this->attr])) { if (!isset($this->css[$this->attr])) return $attr;
return $attr;
}
$style = ''; $style = '';
foreach ($this->css[$this->attr] as $suffix) { foreach ($this->css[$this->attr] as $suffix) {
$property = "margin-$suffix"; $property = "margin-$suffix";
$style .= "$property:{$width}px;"; $style .= "$property:{$width}px;";
} }
$this->prependCSS($attr, $style); $this->prependCSS($attr, $style);
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -4,31 +4,17 @@
* Performs miscellaneous cross attribute validation and filtering for * Performs miscellaneous cross attribute validation and filtering for
* input elements. This is meant to be a post-transform. * 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; protected $pixels;
public function __construct() public function __construct() {
{
$this->pixels = new HTMLPurifier_AttrDef_HTML_Pixels(); $this->pixels = new HTMLPurifier_AttrDef_HTML_Pixels();
} }
/** public function transform($attr, $config, $context) {
* @param array $attr if (!isset($attr['type'])) $t = 'text';
* @param HTMLPurifier_Config $config else $t = strtolower($attr['type']);
* @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') { if (isset($attr['checked']) && $t !== 'radio' && $t !== 'checkbox') {
unset($attr['checked']); unset($attr['checked']);
} }
@@ -37,11 +23,8 @@ class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform
} }
if (isset($attr['size']) && $t !== 'text' && $t !== 'password') { if (isset($attr['size']) && $t !== 'text' && $t !== 'password') {
$result = $this->pixels->validate($attr['size'], $config, $context); $result = $this->pixels->validate($attr['size'], $config, $context);
if ($result === false) { if ($result === false) unset($attr['size']);
unset($attr['size']); else $attr['size'] = $result;
} else {
$attr['size'] = $result;
}
} }
if (isset($attr['src']) && $t !== 'image') { if (isset($attr['src']) && $t !== 'image') {
unset($attr['src']); unset($attr['src']);
@@ -51,6 +34,7 @@ class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform
} }
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,15 +8,9 @@
class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform
{ {
/** public function transform($attr, $config, $context) {
* @param array $attr
* @param HTMLPurifier_Config $config $lang = isset($attr['lang']) ? $attr['lang'] : false;
* @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; $xml_lang = isset($attr['xml:lang']) ? $attr['xml:lang'] : false;
if ($lang !== false && $xml_lang === false) { if ($lang !== false && $xml_lang === false) {
@@ -24,8 +18,11 @@ class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform
} elseif ($xml_lang !== false) { } elseif ($xml_lang !== false) {
$attr['lang'] = $xml_lang; $attr['lang'] = $xml_lang;
} }
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,40 +6,22 @@
class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
{ {
/**
* @type string
*/
protected $name; protected $name;
/**
* @type string
*/
protected $cssName; protected $cssName;
public function __construct($name, $css_name = null) public function __construct($name, $css_name = null) {
{
$this->name = $name; $this->name = $name;
$this->cssName = $css_name ? $css_name : $name; $this->cssName = $css_name ? $css_name : $name;
} }
/** public function transform($attr, $config, $context) {
* @param array $attr if (!isset($attr[$this->name])) return $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); $length = $this->confiscateAttr($attr, $this->name);
if (ctype_digit($length)) { if(ctype_digit($length)) $length .= 'px';
$length .= 'px';
}
$this->prependCSS($attr, $this->cssName . ":$length;"); $this->prependCSS($attr, $this->cssName . ":$length;");
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -6,28 +6,16 @@
class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform 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 // Abort early if we're using relaxed definition of name
if ($config->get('HTML.Attr.Name.UseCDATA')) { if ($config->get('HTML.Attr.Name.UseCDATA')) return $attr;
return $attr; if (!isset($attr['name'])) return $attr;
}
if (!isset($attr['name'])) {
return $attr;
}
$id = $this->confiscateAttr($attr, 'name'); $id = $this->confiscateAttr($attr, 'name');
if (isset($attr['id'])) { if ( isset($attr['id'])) return $attr;
return $attr;
}
$attr['id'] = $id; $attr['id'] = $id;
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,39 +8,20 @@
class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
{ {
/** public function __construct() {
* @type HTMLPurifier_AttrDef_HTML_ID
*/
public $idDef;
public function __construct()
{
$this->idDef = new HTMLPurifier_AttrDef_HTML_ID(); $this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
} }
/** public function transform($attr, $config, $context) {
* @param array $attr if (!isset($attr['name'])) return $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']; $name = $attr['name'];
if (isset($attr['id']) && $attr['id'] === $name) { if (isset($attr['id']) && $attr['id'] === $name) return $attr;
return $attr;
}
$result = $this->idDef->validate($name, $config, $context); $result = $this->idDef->validate($name, $config, $context);
if ($result === false) { if ($result === false) unset($attr['name']);
unset($attr['name']); else $attr['name'] = $result;
} else {
$attr['name'] = $result;
}
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -8,24 +8,14 @@
*/ */
class HTMLPurifier_AttrTransform_Nofollow extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_Nofollow extends HTMLPurifier_AttrTransform
{ {
/**
* @type HTMLPurifier_URIParser
*/
private $parser; private $parser;
public function __construct() public function __construct() {
{
$this->parser = new HTMLPurifier_URIParser(); $this->parser = new HTMLPurifier_URIParser();
} }
/** 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['href'])) { if (!isset($attr['href'])) {
return $attr; return $attr;
} }
@@ -45,8 +35,11 @@ class HTMLPurifier_AttrTransform_Nofollow extends HTMLPurifier_AttrTransform
$attr['rel'] = 'nofollow'; $attr['rel'] = 'nofollow';
} }
} }
return $attr; return $attr;
} }
} }
// vim: et sw=4 sts=4 // vim: et sw=4 sts=4

View File

@@ -2,19 +2,9 @@
class HTMLPurifier_AttrTransform_SafeEmbed extends HTMLPurifier_AttrTransform class HTMLPurifier_AttrTransform_SafeEmbed extends HTMLPurifier_AttrTransform
{ {
/**
* @type string
*/
public $name = "SafeEmbed"; 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['allowscriptaccess'] = 'never';
$attr['allownetworking'] = 'internal'; $attr['allownetworking'] = 'internal';
$attr['type'] = 'application/x-shockwave-flash'; $attr['type'] = 'application/x-shockwave-flash';

Some files were not shown because too many files have changed in this diff Show More