MDL-14898 upgraded html purifier to 3.1.0 in HEAD

This commit is contained in:
skodak
2008-06-16 16:39:09 +00:00
parent b553527e99
commit eb203ee412
290 changed files with 4780 additions and 3432 deletions
+122 -194
View File
@@ -1,134 +1,5 @@
<?php
require_once 'HTMLPurifier/Definition.php';
require_once 'HTMLPurifier/HTMLModuleManager.php';
// this definition and its modules MUST NOT define configuration directives
// outside of the HTML or Attr namespaces
HTMLPurifier_ConfigSchema::define(
'HTML', 'DefinitionID', null, 'string/null', '
<p>
Unique identifier for a custom-built HTML definition. If you edit
the raw version of the HTMLDefinition, introducing changes that the
configuration object does not reflect, you must specify this variable.
If you change your custom edits, you should change this directive, or
clear your cache. Example:
</p>
<pre>
$config = HTMLPurifier_Config::createDefault();
$config->set(\'HTML\', \'DefinitionID\', \'1\');
$def = $config->getHTMLDefinition();
$def->addAttribute(\'a\', \'tabindex\', \'Number\');
</pre>
<p>
In the above example, the configuration is still at the defaults, but
using the advanced API, an extra attribute has been added. The
configuration object normally has no way of knowing that this change
has taken place, so it needs an extra directive: %HTML.DefinitionID.
If someone else attempts to use the default configuration, these two
pieces of code will not clobber each other in the cache, since one has
an extra directive attached to it.
</p>
<p>
This directive has been available since 2.0.0, and in that version or
later you <em>must</em> specify a value to this directive to use the
advanced API features.
</p>
');
HTMLPurifier_ConfigSchema::define(
'HTML', 'DefinitionRev', 1, 'int', '
<p>
Revision identifier for your custom definition specified in
%HTML.DefinitionID. This serves the same purpose: uniquely identifying
your custom definition, but this one does so in a chronological
context: revision 3 is more up-to-date then revision 2. Thus, when
this gets incremented, the cache handling is smart enough to clean
up any older revisions of your definition as well as flush the
cache. This directive has been available since 2.0.0.
</p>
');
HTMLPurifier_ConfigSchema::define(
'HTML', 'BlockWrapper', 'p', 'string', '
<p>
String name of element to wrap inline elements that are inside a block
context. This only occurs in the children of blockquote in strict mode.
</p>
<p>
Example: by default value,
<code>&lt;blockquote&gt;Foo&lt;/blockquote&gt;</code> would become
<code>&lt;blockquote&gt;&lt;p&gt;Foo&lt;/p&gt;&lt;/blockquote&gt;</code>.
The <code>&lt;p&gt;</code> tags can be replaced with whatever you desire,
as long as it is a block level element. This directive has been available
since 1.3.0.
</p>
');
HTMLPurifier_ConfigSchema::define(
'HTML', 'Parent', 'div', 'string', '
<p>
String name of element that HTML fragment passed to library will be
inserted in. An interesting variation would be using span as the
parent element, meaning that only inline tags would be allowed.
This directive has been available since 1.3.0.
</p>
');
HTMLPurifier_ConfigSchema::define(
'HTML', 'AllowedElements', null, 'lookup/null', '
<p>
If HTML Purifier\'s tag set is unsatisfactory for your needs, you
can overload it with your own list of tags to allow. Note that this
method is subtractive: it does its job by taking away from HTML Purifier
usual feature set, so you cannot add a tag that HTML Purifier never
supported in the first place (like embed, form or head). If you
change this, you probably also want to change %HTML.AllowedAttributes.
</p>
<p>
<strong>Warning:</strong> If another directive conflicts with the
elements here, <em>that</em> directive will win and override.
This directive has been available since 1.3.0.
</p>
');
HTMLPurifier_ConfigSchema::define(
'HTML', 'AllowedAttributes', null, 'lookup/null', '
<p>
If HTML Purifier\'s attribute set is unsatisfactory, overload it!
The syntax is "tag.attr" or "*.attr" for the global attributes
(style, id, class, dir, lang, xml:lang).
</p>
<p>
<strong>Warning:</strong> If another directive conflicts with the
elements here, <em>that</em> directive will win and override. For
example, %HTML.EnableAttrID will take precedence over *.id in this
directive. You must set that directive to true before you can use
IDs at all. This directive has been available since 1.3.0.
</p>
');
HTMLPurifier_ConfigSchema::define(
'HTML', 'Allowed', null, 'itext/null', '
<p>
This is a convenience directive that rolls the functionality of
%HTML.AllowedElements and %HTML.AllowedAttributes into one directive.
Specify elements and attributes that are allowed using:
<code>element1[attr1|attr2],element2...</code>. You can also use
newlines instead of commas to separate elements.
</p>
<p>
<strong>Warning</strong>:
All of the constraints on the component directives are still enforced.
The syntax is a <em>subset</em> of TinyMCE\'s <code>valid_elements</code>
whitelist: directly copy-pasting it here will probably result in
broken whitelists. If %HTML.AllowedElements or %HTML.AllowedAttributes
are set, this directive has no effect.
This directive has been available since 2.0.0.
</p>
');
/**
* Definition of the purified HTML that describes allowed children,
* attributes, and many other things.
@@ -148,6 +19,9 @@ HTMLPurifier_ConfigSchema::define(
*
* @note This class is inspected by Printer_HTMLDefinition; please
* update that class if things here change.
*
* @warning Directives that change this object's structure must be in
* the HTML or Attr namespace!
*/
class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
{
@@ -156,65 +30,56 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
/**
* Associative array of element names to HTMLPurifier_ElementDef
* @public
*/
var $info = array();
public $info = array();
/**
* Associative array of global attribute name to attribute definition.
* @public
*/
var $info_global_attr = array();
public $info_global_attr = array();
/**
* String name of parent element HTML will be going into.
* @public
*/
var $info_parent = 'div';
public $info_parent = 'div';
/**
* Definition for parent element, allows parent element to be a
* tag that's not allowed inside the HTML fragment.
* @public
*/
var $info_parent_def;
public $info_parent_def;
/**
* String name of element used to wrap inline elements in block context
* @note This is rarely used except for BLOCKQUOTEs in strict mode
* @public
*/
var $info_block_wrapper = 'p';
public $info_block_wrapper = 'p';
/**
* Associative array of deprecated tag name to HTMLPurifier_TagTransform
* @public
*/
var $info_tag_transform = array();
public $info_tag_transform = array();
/**
* Indexed list of HTMLPurifier_AttrTransform to be performed before validation.
* @public
*/
var $info_attr_transform_pre = array();
public $info_attr_transform_pre = array();
/**
* Indexed list of HTMLPurifier_AttrTransform to be performed after validation.
* @public
*/
var $info_attr_transform_post = array();
public $info_attr_transform_post = array();
/**
* Nested lookup array of content set name (Block, Inline) to
* element name to whether or not it belongs in that content set.
* @public
*/
var $info_content_sets = array();
public $info_content_sets = array();
/**
* Doctype object
*/
var $doctype;
public $doctype;
@@ -229,12 +94,12 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
* @param $def Attribute definition, can be string or object, see
* HTMLPurifier_AttrTypes for details
*/
function addAttribute($element_name, $attr_name, $def) {
$module =& $this->getAnonymousModule();
public function addAttribute($element_name, $attr_name, $def) {
$module = $this->getAnonymousModule();
if (!isset($module->info[$element_name])) {
$element =& $module->addBlankElement($element_name);
$element = $module->addBlankElement($element_name);
} else {
$element =& $module->info[$element_name];
$element = $module->info[$element_name];
}
$element->attr[$attr_name] = $def;
}
@@ -244,11 +109,11 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
* @note See HTMLPurifier_HTMLModule::addElement for detailed
* parameter and return value descriptions.
*/
function &addElement($element_name, $type, $contents, $attr_collections, $attributes) {
$module =& $this->getAnonymousModule();
public function addElement($element_name, $type, $contents, $attr_collections, $attributes) {
$module = $this->getAnonymousModule();
// assume that if the user is calling this, the element
// is safe. This may not be a good idea
$element =& $module->addElement($element_name, true, $type, $contents, $attr_collections, $attributes);
$element = $module->addElement($element_name, $type, $contents, $attr_collections, $attributes);
return $element;
}
@@ -258,9 +123,9 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
* @note See HTMLPurifier_HTMLModule::addBlankElement for detailed
* parameter and return value descriptions.
*/
function &addBlankElement($element_name) {
$module =& $this->getAnonymousModule();
$element =& $module->addBlankElement($element_name);
public function addBlankElement($element_name) {
$module = $this->getAnonymousModule();
$element = $module->addBlankElement($element_name);
return $element;
}
@@ -269,7 +134,7 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
* bust out advanced features without having to make your own
* module.
*/
function &getAnonymousModule() {
public function getAnonymousModule() {
if (!$this->_anonModule) {
$this->_anonModule = new HTMLPurifier_HTMLModule();
$this->_anonModule->name = 'Anonymous';
@@ -277,22 +142,22 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
return $this->_anonModule;
}
var $_anonModule;
private $_anonModule;
// PUBLIC BUT INTERNAL VARIABLES --------------------------------------
var $type = 'HTML';
var $manager; /**< Instance of HTMLPurifier_HTMLModuleManager */
public $type = 'HTML';
public $manager; /**< Instance of HTMLPurifier_HTMLModuleManager */
/**
* Performs low-cost, preliminary initialization.
*/
function HTMLPurifier_HTMLDefinition() {
public function __construct() {
$this->manager = new HTMLPurifier_HTMLModuleManager();
}
function doSetup($config) {
protected function doSetup($config) {
$this->processModules($config);
$this->setupConfigStuff($config);
unset($this->manager);
@@ -307,7 +172,7 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
/**
* Extract out the information from the manager
*/
function processModules($config) {
protected function processModules($config) {
if ($this->_anonModule) {
// for user specific changes
@@ -343,7 +208,7 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
/**
* Sets up stuff based on config. We need a better way of doing this.
*/
function setupConfigStuff($config) {
protected function setupConfigStuff($config) {
$block_wrapper = $config->get('HTML', 'BlockWrapper');
if (isset($this->info_content_sets['Block'][$block_wrapper])) {
@@ -368,10 +233,10 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
$support = "(for information on implementing this, see the ".
"support forums) ";
// setup allowed elements
// setup allowed elements -----------------------------------------
$allowed_elements = $config->get('HTML', 'AllowedElements');
$allowed_attributes = $config->get('HTML', 'AllowedAttributes');
$allowed_attributes = $config->get('HTML', 'AllowedAttributes'); // retrieve early
if (!is_array($allowed_elements) && !is_array($allowed_attributes)) {
$allowed = $config->get('HTML', 'Allowed');
@@ -387,48 +252,108 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
}
// emit errors
foreach ($allowed_elements as $element => $d) {
$element = htmlspecialchars($element);
$element = htmlspecialchars($element); // PHP doesn't escape errors, be careful!
trigger_error("Element '$element' is not supported $support", E_USER_WARNING);
}
}
// setup allowed attributes ---------------------------------------
$allowed_attributes_mutable = $allowed_attributes; // by copy!
if (is_array($allowed_attributes)) {
foreach ($this->info_global_attr as $attr_key => $info) {
if (!isset($allowed_attributes["*.$attr_key"])) {
unset($this->info_global_attr[$attr_key]);
} elseif (isset($allowed_attributes_mutable["*.$attr_key"])) {
unset($allowed_attributes_mutable["*.$attr_key"]);
// This actually doesn't do anything, since we went away from
// global attributes. It's possible that userland code uses
// it, but HTMLModuleManager doesn't!
foreach ($this->info_global_attr as $attr => $x) {
$keys = array($attr, "*@$attr", "*.$attr");
$delete = true;
foreach ($keys as $key) {
if ($delete && isset($allowed_attributes[$key])) {
$delete = false;
}
if (isset($allowed_attributes_mutable[$key])) {
unset($allowed_attributes_mutable[$key]);
}
}
if ($delete) unset($this->info_global_attr[$attr]);
}
foreach ($this->info as $tag => $info) {
foreach ($info->attr as $attr => $attr_info) {
if (!isset($allowed_attributes["$tag.$attr"]) &&
!isset($allowed_attributes["*.$attr"])) {
unset($this->info[$tag]->attr[$attr]);
} else {
if (isset($allowed_attributes_mutable["$tag.$attr"])) {
unset($allowed_attributes_mutable["$tag.$attr"]);
} elseif (isset($allowed_attributes_mutable["*.$attr"])) {
unset($allowed_attributes_mutable["*.$attr"]);
foreach ($info->attr as $attr => $x) {
$keys = array("$tag@$attr", $attr, "*@$attr", "$tag.$attr", "*.$attr");
$delete = true;
foreach ($keys as $key) {
if ($delete && isset($allowed_attributes[$key])) {
$delete = false;
}
if (isset($allowed_attributes_mutable[$key])) {
unset($allowed_attributes_mutable[$key]);
}
}
if ($delete) unset($this->info[$tag]->attr[$attr]);
}
}
// emit errors
foreach ($allowed_attributes_mutable as $elattr => $d) {
list($element, $attribute) = explode('.', $elattr);
$element = htmlspecialchars($element);
$attribute = htmlspecialchars($attribute);
if ($element == '*') {
trigger_error("Global attribute '$attribute' is not ".
"supported in any elements $support",
E_USER_WARNING);
} else {
trigger_error("Attribute '$attribute' in element '$element' not supported $support",
E_USER_WARNING);
$bits = preg_split('/[.@]/', $elattr, 2);
$c = count($bits);
switch ($c) {
case 2:
if ($bits[0] !== '*') {
$element = htmlspecialchars($bits[0]);
$attribute = htmlspecialchars($bits[1]);
if (!isset($this->info[$element])) {
trigger_error("Cannot allow attribute '$attribute' if element '$element' is not allowed/supported $support");
} else {
trigger_error("Attribute '$attribute' in element '$element' not supported $support",
E_USER_WARNING);
}
break;
}
// otherwise fall through
case 1:
$attribute = htmlspecialchars($bits[0]);
trigger_error("Global attribute '$attribute' is not ".
"supported in any elements $support",
E_USER_WARNING);
break;
}
}
}
// setup forbidden elements ---------------------------------------
$forbidden_elements = $config->get('HTML', 'ForbiddenElements');
$forbidden_attributes = $config->get('HTML', 'ForbiddenAttributes');
foreach ($this->info as $tag => $info) {
if (isset($forbidden_elements[$tag])) {
unset($this->info[$tag]);
continue;
}
foreach ($info->attr as $attr => $x) {
if (
isset($forbidden_attributes["$tag@$attr"]) ||
isset($forbidden_attributes["*@$attr"]) ||
isset($forbidden_attributes[$attr])
) {
unset($this->info[$tag]->attr[$attr]);
continue;
} // this segment might get removed eventually
elseif (isset($forbidden_attributes["$tag.$attr"])) {
// $tag.$attr are not user supplied, so no worries!
trigger_error("Error with $tag.$attr: tag.attr syntax not supported for HTML.ForbiddenAttributes; use tag@attr instead", E_USER_WARNING);
}
}
}
foreach ($forbidden_attributes as $key => $v) {
if (strlen($key) < 2) continue;
if ($key[0] != '*') continue;
if ($key[1] == '.') {
trigger_error("Error with $key: *.attr syntax not supported for HTML.ForbiddenAttributes; use attr instead", E_USER_WARNING);
}
}
}
@@ -440,8 +365,11 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
* it is different, and you'll probably have to modify your lists
* @param $list String list to parse
* @param array($allowed_elements, $allowed_attributes)
* @todo Give this its own class, probably static interface
*/
function parseTinyMCEAllowedList($list) {
public function parseTinyMCEAllowedList($list) {
$list = str_replace(array(' ', "\t"), '', $list);
$elements = array();
$attributes = array();