*/
/*
- HTML Purifier 1.6.0 - Standards Compliant HTML Filtering
+ HTML Purifier 1.6.1 - Standards Compliant HTML Filtering
Copyright (C) 2006 Edward Z. Yang
This library is free software; you can redistribute it and/or
class HTMLPurifier
{
- var $version = '1.6.0';
+ var $version = '1.6.1';
var $config;
var $filters;
// Enum = Enumerated
/**
* Validates a keyword against a list of valid values.
+ * @warning The case-insensitive compare of this function uses PHP's
+ * built-in strtolower and ctype_lower functions, which may
+ * cause problems with international comparisons
*/
class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
{
function validate($string, $config, &$context) {
$string = trim($string);
if (!$this->case_sensitive) {
+ // we may want to do full case-insensitive libraries
$string = ctype_lower($string) ? $string : strtolower($string);
}
$result = isset($this->valid_values[$string]);
--- /dev/null
+<?php
+
+HTMLPurifier_ConfigSchema::define(
+ 'Attr', 'AllowedFrameTargets', array(), 'lookup',
+ 'Lookup table of all allowed link frame targets. Some commonly used '.
+ 'link targets include _blank, _self, _parent and _top. Values should '.
+ 'be lowercase, as validation will be done in a case-sensitive manner '.
+ 'despite W3C\'s recommendation. XHTML 1.0 Strict does not permit '.
+ 'the target attribute so this directive will have no effect in that '.
+ 'doctype. XHTML 1.1 does not enable the Target module by default, you '.
+ 'will have to manually enable it (see the module documentation for more details.)'
+);
+
+require_once 'HTMLPurifier/AttrDef/Enum.php';
+
+/**
+ * Special-case enum attribute definition that lazy loads allowed frame targets
+ */
+class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
+{
+
+ var $valid_values = false; // uninitialized value
+ var $case_sensitive = false;
+
+ function HTMLPurifier_AttrDef_HTML_FrameTarget() {}
+
+ function validate($string, $config, &$context) {
+ if ($this->valid_values === false) $this->valid_values = $config->get('Attr', 'AllowedFrameTargets');
+ return parent::validate($string, $config, $context);
+ }
+
+}
+
+?>
\ No newline at end of file
function transform($attr, $config, &$context) {
trigger_error('Cannot call abstract function', E_USER_ERROR);
}
+
+ /**
+ * Prepends CSS properties to the style attribute, creating the
+ * attribute if it doesn't exist.
+ * @param $attr Attribute array to process (passed by reference)
+ * @param $css CSS to prepend
+ */
+ function prependCSS(&$attr, $css) {
+ $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
+ $attr['style'] = $css . $attr['style'];
+ }
+
+ /**
+ * Retrieves and removes an attribute
+ * @param $attr Attribute array to process (passed by reference)
+ * @param $key Key of attribute to confiscate
+ */
+ function confiscateAttr(&$attr, $key) {
+ if (!isset($attr[$key])) return null;
+ $value = $attr[$key];
+ unset($attr[$key]);
+ return $value;
+ }
+
}
?>
\ No newline at end of file
if (!isset($attr['bgcolor'])) return $attr;
- $bgcolor = $attr['bgcolor'];
- unset($attr['bgcolor']);
+ $bgcolor = $this->confiscateAttr($attr, 'bgcolor');
// some validation should happen here
- $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
- $attr['style'] = "background-color:$bgcolor;" . $attr['style'];
+ $this->prependCSS($attr, "background-color:$bgcolor;");
return $attr;
--- /dev/null
+<?php
+
+require_once 'HTMLPurifier/AttrTransform.php';
+
+/**
+ * Pre-transform that changes converts a boolean attribute to fixed CSS
+ */
+class HTMLPurifier_AttrTransform_BoolToCSS
+extends HTMLPurifier_AttrTransform {
+
+ /**
+ * Name of boolean attribute that is trigger
+ */
+ var $attr;
+
+ /**
+ * CSS declarations to add to style, needs trailing semicolon
+ */
+ var $css;
+
+ /**
+ * @param $attr string attribute name to convert from
+ * @param $css string CSS declarations to add to style (needs semicolon)
+ */
+ function HTMLPurifier_AttrTransform_BoolToCSS($attr, $css) {
+ $this->attr = $attr;
+ $this->css = $css;
+ }
+
+ function transform($attr, $config, &$context) {
+ if (!isset($attr[$this->attr])) return $attr;
+ unset($attr[$this->attr]);
+ $this->prependCSS($attr, $this->css);
+ return $attr;
+ }
+
+}
+
+?>
\ No newline at end of file
/**
* Pre-transform that changes deprecated border attribute to CSS.
*/
-class HTMLPurifier_AttrTransform_Border
-extends HTMLPurifier_AttrTransform {
+class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform {
function transform($attr, $config, &$context) {
-
if (!isset($attr['border'])) return $attr;
-
- $border_width = $attr['border'];
- unset($attr['border']);
+ $border_width = $this->confiscateAttr($attr, 'border');
// some validation should happen here
-
- $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
- $attr['style'] = "border:{$border_width}px solid;" . $attr['style'];
-
+ $this->prependCSS($attr, "border:{$border_width}px solid;");
return $attr;
-
}
}
--- /dev/null
+<?php
+
+require_once 'HTMLPurifier/AttrTransform.php';
+
+/**
+ * Generic pre-transform that converts an attribute with a fixed number of
+ * values (enumerated) to CSS.
+ */
+class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform {
+
+ /**
+ * Name of attribute to transform from
+ */
+ var $attr;
+
+ /**
+ * Lookup array of attribute values to CSS
+ */
+ var $enumToCSS = array();
+
+ /**
+ * Case sensitivity of the matching
+ * @warning Currently can only be guaranteed to work with ASCII
+ * values.
+ */
+ var $caseSensitive = false;
+
+ /**
+ * @param $attr String attribute name to transform from
+ * @param $enumToCSS Lookup array of attribute values to CSS
+ * @param $case_sensitive Boolean case sensitivity indicator, default false
+ */
+ function HTMLPurifier_AttrTransform_EnumToCSS($attr, $enum_to_css, $case_sensitive = false) {
+ $this->attr = $attr;
+ $this->enumToCSS = $enum_to_css;
+ $this->caseSensitive = (bool) $case_sensitive;
+ }
+
+ function transform($attr, $config, &$context) {
+
+ if (!isset($attr[$this->attr])) return $attr;
+
+ $value = trim($attr[$this->attr]);
+ unset($attr[$this->attr]);
+
+ if (!$this->caseSensitive) $value = strtolower($value);
+
+ if (!isset($this->enumToCSS[$value])) {
+ return $attr;
+ }
+
+ $this->prependCSS($attr, $this->enumToCSS[$value]);
+
+ return $attr;
+
+ }
+
+}
+
+?>
\ No newline at end of file
--- /dev/null
+<?php
+
+require_once 'HTMLPurifier/AttrTransform.php';
+
+/**
+ * Pre-transform that changes deprecated hspace and vspace attributes to CSS
+ */
+class HTMLPurifier_AttrTransform_ImgSpace
+extends HTMLPurifier_AttrTransform {
+
+ var $attr;
+ var $css = array(
+ 'hspace' => array('left', 'right'),
+ 'vspace' => array('top', 'bottom')
+ );
+
+ function HTMLPurifier_AttrTransform_ImgSpace($attr) {
+ $this->attr = $attr;
+ if (!isset($this->css[$attr])) {
+ trigger_error(htmlspecialchars($attr) . ' is not valid space attribute');
+ }
+ }
+
+ function transform($attr, $config, &$context) {
+
+ if (!isset($attr[$this->attr])) return $attr;
+
+ $width = $this->confiscateAttr($attr, $this->attr);
+ // some validation could happen here
+
+ if (!isset($this->css[$this->attr])) return $attr;
+
+ $style = '';
+ foreach ($this->css[$this->attr] as $suffix) {
+ $property = "margin-$suffix";
+ $style .= "$property:{$width}px;";
+ }
+
+ $this->prependCSS($attr, $style);
+
+ return $attr;
+
+ }
+
+}
+
+?>
\ No newline at end of file
function transform($attr, $config, &$context) {
if (!isset($attr[$this->name])) return $attr;
- $length = $attr[$this->name];
- unset($attr[$this->name]);
+ $length = $this->confiscateAttr($attr, $this->name);
if(ctype_digit($length)) $length .= 'px';
-
- $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
- $attr['style'] = $this->cssName . ":$length;" . $attr['style'];
-
+ $this->prependCSS($attr, $this->cssName . ":$length;");
return $attr;
}
{
function transform($attr, $config, &$context) {
-
if (!isset($attr['name'])) return $attr;
-
- $name = $attr['name'];
- unset($attr['name']);
-
- if (isset($attr['id'])) {
- // ID already set, discard name
- return $attr;
- }
-
- $attr['id'] = $name;
-
+ $id = $this->confiscateAttr($attr, 'name');
+ if ( isset($attr['id'])) return $attr;
+ $attr['id'] = $id;
return $attr;
-
}
}
new HTMLPurifier_AttrDef_CSS_Percentage()
));
+ // partial support
+ $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
+
}
}
case 'hash':
case 'lookup':
if (is_string($var)) {
+ // special case: technically, this is an array with
+ // a single empty string item, but having an empty
+ // array is more intuitive
+ if ($var == '') return array();
// simplistic string to array method that only works
// for simple lists of tag names or alphanumeric characters
$var = explode(',',$var);
// later keys takes precedence
foreach($def->attr as $k => $v) {
- if ($k == 0) {
+ if ($k === 0) {
// merge in the includes
// sorry, no way to override an include
foreach ($v as $v2) {
$this->manager->setup($this->config);
foreach ($this->manager->activeModules as $module) {
- foreach($module->info_tag_transform as $k => $v) $this->info_tag_transform[$k] = $v;
- foreach($module->info_attr_transform_pre as $k => $v) $this->info_attr_transform_pre[$k] = $v;
- foreach($module->info_attr_transform_post as $k => $v) $this->info_attr_transform_post[$k]= $v;
+ foreach($module->info_tag_transform as $k => $v) {
+ if ($v === false) unset($this->info_tag_transform[$k]);
+ else $this->info_tag_transform[$k] = $v;
+ }
+ foreach($module->info_attr_transform_pre as $k => $v) {
+ if ($v === false) unset($this->info_attr_transform_pre[$k]);
+ else $this->info_attr_transform_pre[$k] = $v;
+ }
+ foreach($module->info_attr_transform_post as $k => $v) {
+ if ($v === false) unset($this->info_attr_transform_post[$k]);
+ else $this->info_attr_transform_post[$k] = $v;
+ }
}
$this->info = $this->manager->getElements($this->config);
var $name = 'Bdo';
var $elements = array('bdo');
- var $info = array();
var $content_sets = array('Inline' => 'bdo');
var $attr_collections = array(
'I18N' => array('dir' => false)
var $name = 'Edit';
var $elements = array('del', 'ins');
- var $info = array();
var $content_sets = array('Inline' => 'del | ins');
function HTMLPurifier_HTMLModule_Edit() {
var $name = 'Hypertext';
var $elements = array('a');
- var $info = array();
var $content_sets = array('Inline' => 'a');
function HTMLPurifier_HTMLModule_Hypertext() {
var $name = 'Image';
var $elements = array('img');
- var $info = array();
var $content_sets = array('Inline' => 'img');
function HTMLPurifier_HTMLModule_Image() {
var $name = 'List';
var $elements = array('dl', 'dt', 'dd', 'ol', 'ul', 'li');
- var $info = array();
+
// According to the abstract schema, the List content set is a fully formed
// one or more expr, but it invariably occurs in an optional declaration
// so we're not going to do that subtlety. It might cause trouble
var $name = 'Presentation';
var $elements = array('b', 'big', 'hr', 'i', 'small', 'sub', 'sup', 'tt');
- var $info = array();
var $content_sets = array(
'Block' => 'hr',
'Inline' => 'b | big | i | small | sub | sup | tt'
--- /dev/null
+<?php
+
+/*
+
+WARNING: THIS MODULE IS EXTREMELY DANGEROUS AS IT ENABLES INLINE SCRIPTING
+INSIDE HTML PURIFIER DOCUMENTS. USE ONLY WITH TRUSTED USER INPUT!!!
+
+Usage:
+
+require_once 'HTMLPurifier/HTMLModule/Scripting.php';
+$def =& $config->getHTMLDefinition(true); // get the raw version
+$def->manager->addModule('Scripting');
+
+This must come before any other calls to getHTMLDefinition()
+
+*/
+
+/**
+ * Implements required attribute stipulation for <script>
+ */
+class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform
+{
+ function transform($attr, $config, &$context) {
+ if (!isset($attr['type'])) {
+ $attr['type'] = 'text/javascript';
+ }
+ return $attr;
+ }
+}
+
+/**
+ * XHTML 1.1 Scripting module, defines elements that are used to contain
+ * information pertaining to executable scripts or the lack of support
+ * for executable scripts.
+ * @note This module does not contain inline scripting elements
+ */
+class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
+{
+ var $name = 'Scripting';
+ var $elements = array('script', 'noscript');
+ var $content_sets = array('Block' => 'script | noscript', 'Inline' => 'script | noscript');
+
+ function HTMLPurifier_HTMLModule_Scripting() {
+ // TODO: create custom child-definition for noscript that
+ // auto-wraps stray #PCDATA in a similar manner to
+ // blockquote's custom definition (we would use it but
+ // blockquote's contents are optional while noscript's contents
+ // are required)
+ foreach ($this->elements as $element) {
+ $this->info[$element] = new HTMLPurifier_ElementDef();
+ }
+ $this->info['noscript']->attr = array( 0 => array('Common') );
+ $this->info['noscript']->content_model = 'Heading | List | Block';
+ $this->info['noscript']->content_model_type = 'required';
+ $this->info['script']->attr = array(
+ 'defer' => new HTMLPurifier_AttrDef_Enum(array('defer')),
+ 'src' => new HTMLPurifier_AttrDef_URI(true),
+ 'type' => new HTMLPurifier_AttrDef_Enum(array('text/javascript'))
+ );
+ $this->info['script']->content_model = '#PCDATA';
+ $this->info['script']->content_model_type = 'optional';
+ $this->info['script']->attr_transform_post['type'] =
+ new HTMLPurifier_AttrTransform_ScriptRequired();
+ }
+}
+
+?>
\ No newline at end of file
var $name = 'Tables';
var $elements = array('caption', 'table', 'td', 'th', 'tr', 'col',
'colgroup', 'tbody', 'thead', 'tfoot');
- var $info = array();
var $content_sets = array('Block' => 'table');
function HTMLPurifier_HTMLModule_Tables() {
--- /dev/null
+<?php
+
+require_once 'HTMLPurifier/AttrDef/HTML/FrameTarget.php';
+
+/**
+ * XHTML 1.1 Target Module, defines target attribute in link elements.
+ */
+class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule
+{
+
+ var $name = 'Target';
+ var $elements = array('a');
+
+ function HTMLPurifier_HTMLModule_Target() {
+ foreach ($this->elements as $e) {
+ $this->info[$e] = new HTMLPurifier_ElementDef();
+ $this->info[$e]->standalone = false;
+ $this->info[$e]->attr = array(
+ 'target' => new HTMLPurifier_AttrDef_HTML_FrameTarget()
+ );
+ }
+ }
+
+}
+
+?>
\ No newline at end of file
'h4', 'h5', 'h6', 'kbd', 'p', 'pre', 'q', 'samp', 'span', 'strong',
'var', 'nolink', 'tex', 'algebra'); //moodle modification
- var $info = array();
-
var $content_sets = array(
'Heading' => 'h1 | h2 | h3 | h4 | h5 | h6',
'Block' => 'address | blockquote | div | p | pre | nolink | tex | algebra', //moodle modification
require_once 'HTMLPurifier/TagTransform/Font.php';
require_once 'HTMLPurifier/AttrTransform/Lang.php';
-require_once 'HTMLPurifier/AttrTransform/TextAlign.php';
require_once 'HTMLPurifier/AttrTransform/BgColor.php';
+require_once 'HTMLPurifier/AttrTransform/BoolToCSS.php';
require_once 'HTMLPurifier/AttrTransform/Border.php';
require_once 'HTMLPurifier/AttrTransform/Name.php';
require_once 'HTMLPurifier/AttrTransform/Length.php';
+require_once 'HTMLPurifier/AttrTransform/ImgSpace.php';
+require_once 'HTMLPurifier/AttrTransform/EnumToCSS.php';
/**
* Proprietary module that transforms deprecated elements into Strict
// we're actually modifying these elements, not defining them
var $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p',
- 'blockquote', 'table', 'td', 'th', 'tr', 'img', 'a', 'hr');
+ 'blockquote', 'table', 'td', 'th', 'tr', 'img', 'a', 'hr', 'br',
+ 'caption', 'ul', 'ol', 'li');
var $info_tag_transform = array(
// placeholders, see constructor for definitions
function HTMLPurifier_HTMLModule_TransformToStrict() {
+ // behavior with transformations when there's another CSS property
+ // working on it is interesting: the CSS will *always* override
+ // the deprecated attribute, whereas an inline CSS declaration will
+ // override the corresponding declaration in, say, an external
+ // stylesheet. This behavior won't affect most people, but it
+ // does represent an operational difference we CANNOT fix.
+
// deprecated tag transforms
$this->info_tag_transform['font'] = new HTMLPurifier_TagTransform_Font();
$this->info_tag_transform['menu'] = new HTMLPurifier_TagTransform_Simple('ul');
}
// deprecated attribute transforms
+
+ // align battery
+ $align_lookup = array();
+ $align_values = array('left', 'right', 'center', 'justify');
+ foreach ($align_values as $v) $align_lookup[$v] = "text-align:$v;";
$this->info['h1']->attr_transform_pre['align'] =
$this->info['h2']->attr_transform_pre['align'] =
$this->info['h3']->attr_transform_pre['align'] =
$this->info['h5']->attr_transform_pre['align'] =
$this->info['h6']->attr_transform_pre['align'] =
$this->info['p'] ->attr_transform_pre['align'] =
- new HTMLPurifier_AttrTransform_TextAlign();
+ new HTMLPurifier_AttrTransform_EnumToCSS('align', $align_lookup);
// xml:lang <=> lang mirroring, implement in TransformToStrict,
// this is overridden in TransformToXHTML11
$this->info['th']->attr_transform_pre['width'] =
$this->info['hr']->attr_transform_pre['width'] = new HTMLPurifier_AttrTransform_Length('width');
+ $this->info['td']->attr_transform_pre['nowrap'] =
+ $this->info['th']->attr_transform_pre['nowrap'] = new HTMLPurifier_AttrTransform_BoolToCSS('nowrap', 'white-space:nowrap;');
+
$this->info['td']->attr_transform_pre['height'] =
$this->info['th']->attr_transform_pre['height'] = new HTMLPurifier_AttrTransform_Length('height');
+ $this->info['img']->attr_transform_pre['hspace'] = new HTMLPurifier_AttrTransform_ImgSpace('hspace');
+ $this->info['img']->attr_transform_pre['vspace'] = new HTMLPurifier_AttrTransform_ImgSpace('vspace');
+
+ $this->info['hr']->attr_transform_pre['size'] = new HTMLPurifier_AttrTransform_Length('size', 'height');
+
+ // this transformation is not precise but often good enough.
+ // different browsers use different styles to designate noshade
+ $this->info['hr']->attr_transform_pre['noshade'] = new HTMLPurifier_AttrTransform_BoolToCSS('noshade', 'color:#808080;background-color:#808080;border: 0;');
+
+ $this->info['br']->attr_transform_pre['clear'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('clear', array(
+ 'left' => 'clear:left;',
+ 'right' => 'clear:right;',
+ 'all' => 'clear:both;',
+ 'none' => 'clear:none;',
+ ));
+
+ // this is a slightly unreasonable attribute
+ $this->info['caption']->attr_transform_pre['align'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+ // we're following IE's behavior, not Firefox's, due
+ // to the fact that no one supports caption-side:right,
+ // W3C included (with CSS 2.1)
+ 'left' => 'text-align:left;',
+ 'right' => 'text-align:right;',
+ 'top' => 'caption-side:top;',
+ 'bottom' => 'caption-side:bottom;' // not supported by IE
+ ));
+
+ $this->info['table']->attr_transform_pre['align'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+ 'left' => 'float:left;',
+ 'center' => 'margin-left:auto;margin-right:auto;',
+ 'right' => 'float:right;'
+ ));
+
+ $this->info['img']->attr_transform_pre['align'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+ 'left' => 'float:left;',
+ 'right' => 'float:right;',
+ 'top' => 'vertical-align:top;',
+ 'middle' => 'vertical-align:middle;',
+ 'bottom' => 'vertical-align:baseline;',
+ ));
+
+ $this->info['hr']->attr_transform_pre['align'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
+ 'left' => 'margin-left:0;margin-right:auto;text-align:left;',
+ 'center' => 'margin-left:auto;margin-right:auto;text-align:center;',
+ 'right' => 'margin-left:auto;margin-right:0;text-align:right;'
+ ));
+
+ $ul_types = array(
+ 'disc' => 'list-style-type:disc;',
+ 'square' => 'list-style-type:square;',
+ 'circle' => 'list-style-type:circle;'
+ );
+ $ol_types = array(
+ '1' => 'list-style-type:decimal;',
+ 'i' => 'list-style-type:lower-roman;',
+ 'I' => 'list-style-type:upper-roman;',
+ 'a' => 'list-style-type:lower-alpha;',
+ 'A' => 'list-style-type:upper-alpha;'
+ );
+ $li_types = $ul_types + $ol_types;
+
+ $this->info['ul']->attr_transform_pre['type'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('type', $ul_types);
+ $this->info['ol']->attr_transform_pre['type'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('type', $ol_types, true);
+ $this->info['li']->attr_transform_pre['type'] =
+ new HTMLPurifier_AttrTransform_EnumToCSS('type', $li_types, true);
+
+
}
var $defines_child_def = true;
<?php
+require_once 'HTMLPurifier/AttrTransform/Lang.php';
+
/**
* Proprietary module that transforms XHTML 1.0 deprecated aspects into
* XHTML 1.1 compliant ones, when possible. For maximum effectiveness,
'lang' => false // remove it
);
+ function HTMLPurifier_HTMLModule_TransformToXHTML11() {
+ $this->info_attr_transform_pre['lang'] = new HTMLPurifier_AttrTransform_Lang();
+ }
+
}
?>
\ No newline at end of file
require_once 'HTMLPurifier/HTMLModule/Image.php';
require_once 'HTMLPurifier/HTMLModule/StyleAttribute.php';
require_once 'HTMLPurifier/HTMLModule/Legacy.php';
+require_once 'HTMLPurifier/HTMLModule/Target.php';
// proprietary modules
require_once 'HTMLPurifier/HTMLModule/TransformToStrict.php';
'CommonAttributes',
'Text', 'Hypertext', 'List', 'Presentation',
'Edit', 'Bdo', 'Tables', 'Image', 'StyleAttribute',
+ 'Target',
// define-redefine
'Legacy',
// redefine
'HTML 4.01 Transitional' => array(array('XHTML 1.0 Transitional')),
'HTML 4.01 Strict' => array(array('XHTML 1.0 Strict')),
// XHTML definitions
- 'XHTML 1.0 Transitional' => array( array('XHTML 1.0 Strict'), 'Legacy' ),
+ 'XHTML 1.0 Transitional' => array( array('XHTML 1.0 Strict'), 'Legacy', 'Target' ),
'XHTML 1.0 Strict' => array(array('_Common')),
'XHTML 1.1' => array(array('_Common')),
);
* @param $module Mixed: string module name, with or without
* HTMLPurifier_HTMLModule prefix, or instance of
* subclass of HTMLPurifier_HTMLModule.
+ * @note This function will not call autoload, you must instantiate
+ * (and thus invoke) autoload outside the method.
+ * @note If a string is passed as a module name, different variants
+ * will be tested in this order:
+ * - Check for HTMLPurifier_HTMLModule_$name
+ * - Check all prefixes with $name in order they were added
+ * - Check for literal object name
+ * - Throw fatal error
+ * If your object name collides with an internal class, specify
+ * your module manually.
*/
function addModule($module) {
if (is_string($module)) {
$original_module = $module;
- if (!class_exists($module)) {
- foreach ($this->prefixes as $prefix) {
- $module = $prefix . $original_module;
- if (class_exists($module)) break;
+ $ok = false;
+ foreach ($this->prefixes as $prefix) {
+ $module = $prefix . $original_module;
+ if ($this->_classExists($module)) {
+ $ok = true;
+ break;
}
}
- if (!class_exists($module)) {
- trigger_error($original_module . ' module does not exist',
- E_USER_ERROR);
- return;
+ if (!$ok) {
+ $module = $original_module;
+ if (!$this->_classExists($module)) {
+ trigger_error($original_module . ' module does not exist',
+ E_USER_ERROR);
+ return;
+ }
}
$module = new $module();
}
}
}
+ /**
+ * Safely tests for class existence without invoking __autoload in PHP5
+ * @param $name String class name to test
+ * @private
+ */
+ function _classExists($name) {
+ static $is_php_4 = null;
+ if ($is_php_4 === null) {
+ $is_php_4 = version_compare(PHP_VERSION, '5', '<');
+ }
+ if ($is_php_4) {
+ return class_exists($name);
+ } else {
+ return class_exists($name, false);
+ }
+ }
+
/**
* Makes a collection active, while also making it valid if not
* already done so. See $activeModules for the semantics of "active".
$elements = array();
foreach ($this->activeModules as $module) {
- foreach ($module->elements as $name) {
+ foreach ($module->info as $name => $v) {
+ if (isset($elements[$name])) continue;
$elements[$name] = $this->getElement($name, $config);
}
}
}
-?>
\ No newline at end of file
+?>
continue;
}
+ // Check leading character is alnum, if not, we may
+ // have accidently grabbed an emoticon. Translate into
+ // text and go our merry way
+ if (!ctype_alnum($segment[0])) {
+ $array[] = new
+ HTMLPurifier_Token_Text(
+ '<' .
+ $this->parseData(
+ $segment
+ ) .
+ '>'
+ );
+ $cursor = $position_next_gt + 1;
+ $inside_tag = false;
+ continue;
+ }
+
// Check if it is explicitly self closing, if so, remove
// trailing slash. Remember, we could have a tag like <br>, so
// any later token processing scripts must convert improperly
$generator = new HTMLPurifier_Generator();
$result = array();
$escape_invalid_tags = $config->get('Core', 'EscapeInvalidTags');
+ $remove_invalid_img = $config->get('Core', 'RemoveInvalidImg');
foreach($tokens as $token) {
if (!empty( $token->is_tag )) {
// DEFINITION CALL
// hard-coded image special case, pre-emptively drop
// if not available. Probably not abstract-able
- if ( $token->name == 'img' ) {
+ if ( $token->name == 'img' && $remove_invalid_img ) {
if (!isset($token->attr['src'])) {
continue;
}
var $transform_to = 'span';
var $_size_lookup = array(
+ '0' => 'xx-small',
'1' => 'xx-small',
'2' => 'small',
'3' => 'medium',
'6' => 'xx-large',
'7' => '300%',
'-1' => 'smaller',
- '+1' => 'larger',
'-2' => '60%',
+ '+1' => 'larger',
'+2' => '150%',
+ '+3' => '200%',
'+4' => '300%'
);
// handle size transform
if (isset($attr['size'])) {
+ // normalize large numbers
+ if ($attr['size']{0} == '+' || $attr['size']{0} == '-') {
+ $size = (int) $attr['size'];
+ if ($size < -2) $attr['size'] = '-2';
+ if ($size > 4) $attr['size'] = '+4';
+ } else {
+ $size = (int) $attr['size'];
+ if ($size > 7) $attr['size'] = '7';
+ }
if (isset($this->_size_lookup[$attr['size']])) {
$prepend_style .= 'font-size:' .
$this->_size_lookup[$attr['size']] . ';';
-Description of HTML Purifier v1.6.0 library import into Moodle
+Description of HTML Purifier v1.6.1 library import into Moodle
Changes:
* Text.php - added nolink, tex and algebra tags