mirror of
https://github.com/ezyang/htmlpurifier.git
synced 2024-12-22 08:21:52 +00:00
Implement %Attr.AllowedClasses and %Attr.ForbiddenClasses.
Signed-off-by: Edward Z. Yang <edwardzyang@thewritingpot.com>
This commit is contained in:
parent
bf71c3f392
commit
baf053b016
3
NEWS
3
NEWS
@ -31,6 +31,9 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
|
|||||||
tags that contain non-breaking spaces as well other whitespace. You
|
tags that contain non-breaking spaces as well other whitespace. You
|
||||||
can also modify which tags should have maintained with
|
can also modify which tags should have maintained with
|
||||||
%AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.
|
%AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.
|
||||||
|
! Implement %Attr.AllowedClasses, which allows administrators to restrict
|
||||||
|
classes users can use to a specified finite set of classes, and
|
||||||
|
%Attr.ForbiddenClasses, which is the logical inverse.
|
||||||
. Created script maintenance/rename-config.php for renaming a configuration
|
. Created script maintenance/rename-config.php for renaming a configuration
|
||||||
directive while maintaining its alias. This script does not change source code.
|
directive while maintaining its alias. This script does not change source code.
|
||||||
|
|
||||||
|
3
TODO
3
TODO
@ -17,10 +17,11 @@ afraid to cast your vote for the next feature to be implemented!
|
|||||||
- Incorporate data: support as implemented here:
|
- Incorporate data: support as implemented here:
|
||||||
http://htmlpurifier.org/phorum/read.php?3,3491,3548
|
http://htmlpurifier.org/phorum/read.php?3,3491,3548
|
||||||
- Fix ImgRequired to handle data correctly
|
- Fix ImgRequired to handle data correctly
|
||||||
- Provide callback/lookup table of allowed class attributes
|
|
||||||
- Think about allowing explicit order of operations hooks for transforms
|
- Think about allowing explicit order of operations hooks for transforms
|
||||||
- Allow more relaxed "class" definition than NMTOKENS for appropriate
|
- Allow more relaxed "class" definition than NMTOKENS for appropriate
|
||||||
doctypes
|
doctypes
|
||||||
|
- Lock when configuring Definition objects so we CAN'T access configuration
|
||||||
|
directives outside of what dependency has been registered.
|
||||||
|
|
||||||
FUTURE VERSIONS
|
FUTURE VERSIONS
|
||||||
---------------
|
---------------
|
||||||
|
@ -98,6 +98,8 @@ require 'HTMLPurifier/AttrDef/CSS/Percentage.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/Class.php';
|
||||||
require 'HTMLPurifier/AttrDef/HTML/Color.php';
|
require 'HTMLPurifier/AttrDef/HTML/Color.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';
|
||||||
@ -105,7 +107,6 @@ require 'HTMLPurifier/AttrDef/HTML/Pixels.php';
|
|||||||
require 'HTMLPurifier/AttrDef/HTML/Length.php';
|
require 'HTMLPurifier/AttrDef/HTML/Length.php';
|
||||||
require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
require 'HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||||
require 'HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
require 'HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||||
require 'HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
|
||||||
require 'HTMLPurifier/AttrDef/URI/Email.php';
|
require 'HTMLPurifier/AttrDef/URI/Email.php';
|
||||||
require 'HTMLPurifier/AttrDef/URI/Host.php';
|
require 'HTMLPurifier/AttrDef/URI/Host.php';
|
||||||
require 'HTMLPurifier/AttrDef/URI/IPv4.php';
|
require 'HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||||
|
@ -92,6 +92,8 @@ require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Percentage.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/Class.php';
|
||||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.php';
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Color.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';
|
||||||
@ -99,7 +101,6 @@ require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Pixels.php';
|
|||||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php';
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Length.php';
|
||||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/LinkTypes.php';
|
||||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/MultiLength.php';
|
||||||
require_once $__dir . '/HTMLPurifier/AttrDef/HTML/Nmtokens.php';
|
|
||||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php';
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Email.php';
|
||||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php';
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/Host.php';
|
||||||
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php';
|
require_once $__dir . '/HTMLPurifier/AttrDef/URI/IPv4.php';
|
||||||
|
22
library/HTMLPurifier/AttrDef/HTML/Class.php
Normal file
22
library/HTMLPurifier/AttrDef/HTML/Class.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements special behavior for class attribute (normally NMTOKENS)
|
||||||
|
*/
|
||||||
|
class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
|
||||||
|
{
|
||||||
|
protected function filter($tokens, $config, $context) {
|
||||||
|
$allowed = $config->get('Attr.AllowedClasses');
|
||||||
|
$forbidden = $config->get('Attr.ForbiddenClasses');
|
||||||
|
$ret = array();
|
||||||
|
foreach ($tokens as $token) {
|
||||||
|
if (
|
||||||
|
($allowed === null || isset($allowed[$token])) &&
|
||||||
|
!isset($forbidden[$token])
|
||||||
|
) {
|
||||||
|
$ret[] = $token;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates contents based on NMTOKENS attribute type.
|
* Validates contents based on NMTOKENS attribute type.
|
||||||
* @note The only current use for this is the class attribute in HTML
|
|
||||||
* @note Could have some functionality factored out into Nmtoken class
|
|
||||||
* @warning We cannot assume this class will be used only for 'class'
|
|
||||||
* attributes. Not sure how to hook in magic behavior, then.
|
|
||||||
*/
|
*/
|
||||||
class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
||||||
{
|
{
|
||||||
@ -17,6 +13,17 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
|
|||||||
// early abort: '' and '0' (strings that convert to false) are invalid
|
// early abort: '' and '0' (strings that convert to false) are invalid
|
||||||
if (!$string) return false;
|
if (!$string) return false;
|
||||||
|
|
||||||
|
$tokens = $this->split($string);
|
||||||
|
$tokens = $this->filter($tokens, $config, $context);
|
||||||
|
if (empty($tokens)) return false;
|
||||||
|
return implode(' ', $tokens);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Splits a space separated list of tokens into its constituent parts.
|
||||||
|
*/
|
||||||
|
protected function split($string) {
|
||||||
// OPTIMIZABLE!
|
// OPTIMIZABLE!
|
||||||
// do the preg_match, capture all subpatterns for reformulation
|
// do the preg_match, capture all subpatterns for reformulation
|
||||||
|
|
||||||
@ -24,23 +31,20 @@ 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).
|
||||||
$matches = array();
|
|
||||||
$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];
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($matches[1])) return false;
|
/**
|
||||||
|
* Template method for removing certain tokens based on arbitrary criteria.
|
||||||
// reconstruct string
|
* @note If we wanted to be really functional, we'd do an array_filter
|
||||||
$new_string = '';
|
* with a callback. But... we're not.
|
||||||
foreach ($matches[1] as $token) {
|
*/
|
||||||
$new_string .= $token . ' ';
|
protected function filter($tokens, $config, $context) {
|
||||||
}
|
return $tokens;
|
||||||
$new_string = rtrim($new_string);
|
|
||||||
|
|
||||||
return $new_string;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,9 @@ class HTMLPurifier_AttrTypes
|
|||||||
$this->info['Charsets'] = new HTMLPurifier_AttrDef_Text();
|
$this->info['Charsets'] = new HTMLPurifier_AttrDef_Text();
|
||||||
$this->info['Character'] = new HTMLPurifier_AttrDef_Text();
|
$this->info['Character'] = new HTMLPurifier_AttrDef_Text();
|
||||||
|
|
||||||
|
// "proprietary" types
|
||||||
|
$this->info['Class'] = new HTMLPurifier_AttrDef_HTML_Class();
|
||||||
|
|
||||||
// number is really a positive integer (one or more digits)
|
// number is really a positive integer (one or more digits)
|
||||||
// FIXME: ^^ not always, see start and value of list items
|
// FIXME: ^^ not always, see start and value of list items
|
||||||
$this->info['Number'] = new HTMLPurifier_AttrDef_Integer(false, false, true);
|
$this->info['Number'] = new HTMLPurifier_AttrDef_Integer(false, false, true);
|
||||||
|
Binary file not shown.
@ -0,0 +1,8 @@
|
|||||||
|
Attr.AllowedClasses
|
||||||
|
TYPE: lookup/null
|
||||||
|
VERSION: 4.0.0
|
||||||
|
DEFAULT: null
|
||||||
|
--DESCRIPTION--
|
||||||
|
List of allowed class values in the class attribute. By default, this is null,
|
||||||
|
which means all classes are allowed.
|
||||||
|
--# vim: et sw=4 sts=4
|
@ -0,0 +1,8 @@
|
|||||||
|
Attr.ForbiddenClasses
|
||||||
|
TYPE: lookup
|
||||||
|
VERSION: 4.0.0
|
||||||
|
DEFAULT: array()
|
||||||
|
--DESCRIPTION--
|
||||||
|
List of forbidden class values in the class attribute. By default, this is
|
||||||
|
empty, which means that no classes are forbidden. See also %Attr.AllowedClasses.
|
||||||
|
--# vim: et sw=4 sts=4
|
@ -8,7 +8,7 @@ class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
|
|||||||
'Core' => array(
|
'Core' => array(
|
||||||
0 => array('Style'),
|
0 => array('Style'),
|
||||||
// 'xml:space' => false,
|
// 'xml:space' => false,
|
||||||
'class' => 'NMTOKENS',
|
'class' => 'Class',
|
||||||
'id' => 'ID',
|
'id' => 'ID',
|
||||||
'title' => 'CDATA',
|
'title' => 'CDATA',
|
||||||
),
|
),
|
||||||
@ -20,6 +20,7 @@ class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
|
|||||||
0 => array('Core', 'I18N')
|
0 => array('Core', 'I18N')
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: et sw=4 sts=4
|
// vim: et sw=4 sts=4
|
||||||
|
21
tests/HTMLPurifier/AttrDef/HTML/ClassTest.php
Normal file
21
tests/HTMLPurifier/AttrDef/HTML/ClassTest.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class HTMLPurifier_AttrDef_HTML_ClassTest extends HTMLPurifier_AttrDef_HTML_NmtokensTest
|
||||||
|
{
|
||||||
|
function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
$this->def = new HTMLPurifier_AttrDef_HTML_Class();
|
||||||
|
}
|
||||||
|
function testAllowedClasses() {
|
||||||
|
$this->config->set('Attr.AllowedClasses', array('foo'));
|
||||||
|
$this->assertDef('foo');
|
||||||
|
$this->assertDef('bar', false);
|
||||||
|
$this->assertDef('foo bar', 'foo');
|
||||||
|
}
|
||||||
|
function testForbiddenClasses() {
|
||||||
|
$this->config->set('Attr.ForbiddenClasses', array('bar'));
|
||||||
|
$this->assertDef('foo');
|
||||||
|
$this->assertDef('bar', false);
|
||||||
|
$this->assertDef('foo bar', 'foo');
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,12 @@
|
|||||||
class HTMLPurifier_AttrDef_HTML_NmtokensTest extends HTMLPurifier_AttrDefHarness
|
class HTMLPurifier_AttrDef_HTML_NmtokensTest extends HTMLPurifier_AttrDefHarness
|
||||||
{
|
{
|
||||||
|
|
||||||
function testDefault() {
|
function setUp() {
|
||||||
|
parent::setUp();
|
||||||
$this->def = new HTMLPurifier_AttrDef_HTML_Nmtokens();
|
$this->def = new HTMLPurifier_AttrDef_HTML_Nmtokens();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testDefault() {
|
||||||
|
|
||||||
$this->assertDef('valid');
|
$this->assertDef('valid');
|
||||||
$this->assertDef('a0-_');
|
$this->assertDef('a0-_');
|
||||||
|
Loading…
Reference in New Issue
Block a user