/demo/yii/vendors/htmlpurifier/HTMLPurifier.standalone.php
PHP | 14492 lines | 7496 code | 2503 blank | 4493 comment | 1442 complexity | 7d678df995783a3e3f130996946c003d MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, BSD-2-Clause, Apache-2.0
Large files files are truncated, but you can click here to view the full file
- <?php
-
- /**
- * @file
- * This file was auto-generated by generate-includes.php and includes all of
- * the core files required by HTML Purifier. Use this if performance is a
- * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
- * FILE, changes will be overwritten the next time the script is run.
- *
- * @version 4.4.0
- *
- * @warning
- * You must *not* include any other HTML Purifier files before this file,
- * because 'require' not 'require_once' is used.
- *
- * @warning
- * This file requires that the include path contains the HTML Purifier
- * library directory; this is not auto-set.
- */
-
-
-
- /*! @mainpage
- *
- * HTML Purifier is an HTML filter that will take an arbitrary snippet of
- * HTML and rigorously test, validate and filter it into a version that
- * is safe for output onto webpages. It achieves this by:
- *
- * -# Lexing (parsing into tokens) the document,
- * -# Executing various strategies on the tokens:
- * -# Removing all elements not in the whitelist,
- * -# Making the tokens well-formed,
- * -# Fixing the nesting of the nodes, and
- * -# Validating attributes of the nodes; and
- * -# Generating HTML from the purified tokens.
- *
- * However, most users will only need to interface with the HTMLPurifier
- * and HTMLPurifier_Config.
- */
-
- /*
- HTML Purifier 4.4.0 - Standards Compliant HTML Filtering
- Copyright (C) 2006-2008 Edward Z. Yang
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
- /**
- * Facade that coordinates HTML Purifier's subsystems in order to purify HTML.
- *
- * @note There are several points in which configuration can be specified
- * for HTML Purifier. The precedence of these (from lowest to
- * highest) is as follows:
- * -# Instance: new HTMLPurifier($config)
- * -# Invocation: purify($html, $config)
- * These configurations are entirely independent of each other and
- * are *not* merged (this behavior may change in the future).
- *
- * @todo We need an easier way to inject strategies using the configuration
- * object.
- */
- class HTMLPurifier
- {
-
- /** Version of HTML Purifier */
- public $version = '4.4.0';
-
- /** Constant with version of HTML Purifier */
- const VERSION = '4.4.0';
-
- /** Global configuration object */
- public $config;
-
- /** Array of extra HTMLPurifier_Filter objects to run on HTML, for backwards compatibility */
- private $filters = array();
-
- /** Single instance of HTML Purifier */
- private static $instance;
-
- protected $strategy, $generator;
-
- /**
- * Resultant HTMLPurifier_Context of last run purification. Is an array
- * of contexts if the last called method was purifyArray().
- */
- public $context;
-
- /**
- * Initializes the purifier.
- * @param $config Optional HTMLPurifier_Config object for all instances of
- * the purifier, if omitted, a default configuration is
- * supplied (which can be overridden on a per-use basis).
- * The parameter can also be any type that
- * HTMLPurifier_Config::create() supports.
- */
- public function __construct($config = null) {
-
- $this->config = HTMLPurifier_Config::create($config);
-
- $this->strategy = new HTMLPurifier_Strategy_Core();
-
- }
-
- /**
- * Adds a filter to process the output. First come first serve
- * @param $filter HTMLPurifier_Filter object
- */
- public function addFilter($filter) {
- trigger_error('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom', E_USER_WARNING);
- $this->filters[] = $filter;
- }
-
- /**
- * Filters an HTML snippet/document to be XSS-free and standards-compliant.
- *
- * @param $html String of HTML to purify
- * @param $config HTMLPurifier_Config object for this operation, if omitted,
- * defaults to the config object specified during this
- * object's construction. The parameter can also be any type
- * that HTMLPurifier_Config::create() supports.
- * @return Purified HTML
- */
- public function purify($html, $config = null) {
-
- // :TODO: make the config merge in, instead of replace
- $config = $config ? HTMLPurifier_Config::create($config) : $this->config;
-
- // implementation is partially environment dependant, partially
- // configuration dependant
- $lexer = HTMLPurifier_Lexer::create($config);
-
- $context = new HTMLPurifier_Context();
-
- // setup HTML generator
- $this->generator = new HTMLPurifier_Generator($config, $context);
- $context->register('Generator', $this->generator);
-
- // set up global context variables
- if ($config->get('Core.CollectErrors')) {
- // may get moved out if other facilities use it
- $language_factory = HTMLPurifier_LanguageFactory::instance();
- $language = $language_factory->create($config, $context);
- $context->register('Locale', $language);
-
- $error_collector = new HTMLPurifier_ErrorCollector($context);
- $context->register('ErrorCollector', $error_collector);
- }
-
- // setup id_accumulator context, necessary due to the fact that
- // AttrValidator can be called from many places
- $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
- $context->register('IDAccumulator', $id_accumulator);
-
- $html = HTMLPurifier_Encoder::convertToUTF8($html, $config, $context);
-
- // setup filters
- $filter_flags = $config->getBatch('Filter');
- $custom_filters = $filter_flags['Custom'];
- unset($filter_flags['Custom']);
- $filters = array();
- foreach ($filter_flags as $filter => $flag) {
- if (!$flag) continue;
- if (strpos($filter, '.') !== false) continue;
- $class = "HTMLPurifier_Filter_$filter";
- $filters[] = new $class;
- }
- foreach ($custom_filters as $filter) {
- // maybe "HTMLPurifier_Filter_$filter", but be consistent with AutoFormat
- $filters[] = $filter;
- }
- $filters = array_merge($filters, $this->filters);
- // maybe prepare(), but later
-
- for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) {
- $html = $filters[$i]->preFilter($html, $config, $context);
- }
-
- // purified HTML
- $html =
- $this->generator->generateFromTokens(
- // list of tokens
- $this->strategy->execute(
- // list of un-purified tokens
- $lexer->tokenizeHTML(
- // un-purified HTML
- $html, $config, $context
- ),
- $config, $context
- )
- );
-
- for ($i = $filter_size - 1; $i >= 0; $i--) {
- $html = $filters[$i]->postFilter($html, $config, $context);
- }
-
- $html = HTMLPurifier_Encoder::convertFromUTF8($html, $config, $context);
- $this->context =& $context;
- return $html;
- }
-
- /**
- * Filters an array of HTML snippets
- * @param $config Optional HTMLPurifier_Config object for this operation.
- * See HTMLPurifier::purify() for more details.
- * @return Array of purified HTML
- */
- public function purifyArray($array_of_html, $config = null) {
- $context_array = array();
- foreach ($array_of_html as $key => $html) {
- $array_of_html[$key] = $this->purify($html, $config);
- $context_array[$key] = $this->context;
- }
- $this->context = $context_array;
- return $array_of_html;
- }
-
- /**
- * Singleton for enforcing just one HTML Purifier in your system
- * @param $prototype Optional prototype HTMLPurifier instance to
- * overload singleton with, or HTMLPurifier_Config
- * instance to configure the generated version with.
- */
- public static function instance($prototype = null) {
- if (!self::$instance || $prototype) {
- if ($prototype instanceof HTMLPurifier) {
- self::$instance = $prototype;
- } elseif ($prototype) {
- self::$instance = new HTMLPurifier($prototype);
- } else {
- self::$instance = new HTMLPurifier();
- }
- }
- return self::$instance;
- }
-
- /**
- * @note Backwards compatibility, see instance()
- */
- public static function getInstance($prototype = null) {
- return HTMLPurifier::instance($prototype);
- }
-
- }
-
-
-
- /**
- * Defines common attribute collections that modules reference
- */
-
- class HTMLPurifier_AttrCollections
- {
-
- /**
- * Associative array of attribute collections, indexed by name
- */
- public $info = array();
-
- /**
- * Performs all expansions on internal data for use by other inclusions
- * It also collects all attribute collection extensions from
- * modules
- * @param $attr_types HTMLPurifier_AttrTypes instance
- * @param $modules Hash array of HTMLPurifier_HTMLModule members
- */
- public function __construct($attr_types, $modules) {
- // load extensions from the modules
- foreach ($modules as $module) {
- foreach ($module->attr_collections as $coll_i => $coll) {
- if (!isset($this->info[$coll_i])) {
- $this->info[$coll_i] = array();
- }
- foreach ($coll as $attr_i => $attr) {
- if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
- // merge in includes
- $this->info[$coll_i][$attr_i] = array_merge(
- $this->info[$coll_i][$attr_i], $attr);
- continue;
- }
- $this->info[$coll_i][$attr_i] = $attr;
- }
- }
- }
- // perform internal expansions and inclusions
- foreach ($this->info as $name => $attr) {
- // merge attribute collections that include others
- $this->performInclusions($this->info[$name]);
- // replace string identifiers with actual attribute objects
- $this->expandIdentifiers($this->info[$name], $attr_types);
- }
- }
-
- /**
- * Takes a reference to an attribute associative array and performs
- * all inclusions specified by the zero index.
- * @param &$attr Reference to attribute array
- */
- public function performInclusions(&$attr) {
- if (!isset($attr[0])) return;
- $merge = $attr[0];
- $seen = array(); // recursion guard
- // loop through all the inclusions
- for ($i = 0; isset($merge[$i]); $i++) {
- if (isset($seen[$merge[$i]])) continue;
- $seen[$merge[$i]] = true;
- // foreach attribute of the inclusion, copy it over
- if (!isset($this->info[$merge[$i]])) continue;
- foreach ($this->info[$merge[$i]] as $key => $value) {
- if (isset($attr[$key])) continue; // also catches more inclusions
- $attr[$key] = $value;
- }
- if (isset($this->info[$merge[$i]][0])) {
- // recursion
- $merge = array_merge($merge, $this->info[$merge[$i]][0]);
- }
- }
- unset($attr[0]);
- }
-
- /**
- * Expands all string identifiers in an attribute array by replacing
- * them with the appropriate values inside HTMLPurifier_AttrTypes
- * @param &$attr Reference to attribute array
- * @param $attr_types HTMLPurifier_AttrTypes instance
- */
- public function expandIdentifiers(&$attr, $attr_types) {
-
- // because foreach will process new elements we add, make sure we
- // skip duplicates
- $processed = array();
-
- foreach ($attr as $def_i => $def) {
- // skip inclusions
- if ($def_i === 0) continue;
-
- if (isset($processed[$def_i])) continue;
-
- // determine whether or not attribute is required
- if ($required = (strpos($def_i, '*') !== false)) {
- // rename the definition
- unset($attr[$def_i]);
- $def_i = trim($def_i, '*');
- $attr[$def_i] = $def;
- }
-
- $processed[$def_i] = true;
-
- // if we've already got a literal object, move on
- if (is_object($def)) {
- // preserve previous required
- $attr[$def_i]->required = ($required || $attr[$def_i]->required);
- continue;
- }
-
- if ($def === false) {
- unset($attr[$def_i]);
- continue;
- }
-
- if ($t = $attr_types->get($def)) {
- $attr[$def_i] = $t;
- $attr[$def_i]->required = $required;
- } else {
- unset($attr[$def_i]);
- }
- }
-
- }
-
- }
-
-
-
- /**
- * Base class for all validating attribute definitions.
- *
- * This family of classes forms the core for not only HTML attribute validation,
- * but also any sort of string that needs to be validated or cleaned (which
- * means CSS properties and composite definitions are defined here too).
- * Besides defining (through code) what precisely makes the string valid,
- * subclasses are also responsible for cleaning the code if possible.
- */
-
- abstract class HTMLPurifier_AttrDef
- {
-
- /**
- * Tells us whether or not an HTML attribute is minimized. Has no
- * meaning in other contexts.
- */
- public $minimized = false;
-
- /**
- * Tells us whether or not an HTML attribute is required. Has no
- * meaning in other contexts
- */
- public $required = false;
-
- /**
- * Validates and cleans passed string according to a definition.
- *
- * @param $string String to be validated and cleaned.
- * @param $config Mandatory HTMLPurifier_Config object.
- * @param $context Mandatory HTMLPurifier_AttrContext object.
- */
- abstract public function validate($string, $config, $context);
-
- /**
- * Convenience method that parses a string as if it were CDATA.
- *
- * This method process a string in the manner specified at
- * <http://www.w3.org/TR/html4/types.html#h-6.2> by removing
- * leading and trailing whitespace, ignoring line feeds, and replacing
- * carriage returns and tabs with spaces. While most useful for HTML
- * attributes specified as CDATA, it can also be applied to most CSS
- * values.
- *
- * @note This method is not entirely standards compliant, as trim() removes
- * more types of whitespace than specified in the spec. In practice,
- * this is rarely a problem, as those extra characters usually have
- * already been removed by HTMLPurifier_Encoder.
- *
- * @warning This processing is inconsistent with XML's whitespace handling
- * as specified by section 3.3.3 and referenced XHTML 1.0 section
- * 4.7. However, note that we are NOT necessarily
- * parsing XML, thus, this behavior may still be correct. We
- * assume that newlines have been normalized.
- */
- public function parseCDATA($string) {
- $string = trim($string);
- $string = str_replace(array("\n", "\t", "\r"), ' ', $string);
- return $string;
- }
-
- /**
- * Factory method for creating this class from a string.
- * @param $string String construction info
- * @return Created AttrDef object corresponding to $string
- */
- public function make($string) {
- // default implementation, return a flyweight of this object.
- // If $string has an effect on the returned object (i.e. you
- // need to overload this method), it is best
- // to clone or instantiate new copies. (Instantiation is safer.)
- return $this;
- }
-
- /**
- * Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
- * properly. THIS IS A HACK!
- */
- protected function mungeRgb($string) {
- return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
- }
-
- /**
- * Parses a possibly escaped CSS string and returns the "pure"
- * version of it.
- */
- protected function expandCSSEscape($string) {
- // flexibly parse it
- $ret = '';
- for ($i = 0, $c = strlen($string); $i < $c; $i++) {
- if ($string[$i] === '\\') {
- $i++;
- if ($i >= $c) {
- $ret .= '\\';
- break;
- }
- if (ctype_xdigit($string[$i])) {
- $code = $string[$i];
- for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
- if (!ctype_xdigit($string[$i])) break;
- $code .= $string[$i];
- }
- // We have to be extremely careful when adding
- // new characters, to make sure we're not breaking
- // the encoding.
- $char = HTMLPurifier_Encoder::unichr(hexdec($code));
- if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
- $ret .= $char;
- if ($i < $c && trim($string[$i]) !== '') $i--;
- continue;
- }
- if ($string[$i] === "\n") continue;
- }
- $ret .= $string[$i];
- }
- return $ret;
- }
-
- }
-
-
-
- /**
- * Processes an entire attribute array for corrections needing multiple values.
- *
- * Occasionally, a certain attribute will need to be removed and popped onto
- * another value. Instead of creating a complex return syntax for
- * HTMLPurifier_AttrDef, we just pass the whole attribute array to a
- * specialized object and have that do the special work. That is the
- * family of HTMLPurifier_AttrTransform.
- *
- * An attribute transformation can be assigned to run before or after
- * HTMLPurifier_AttrDef validation. See HTMLPurifier_HTMLDefinition for
- * more details.
- */
-
- abstract class HTMLPurifier_AttrTransform
- {
-
- /**
- * Abstract: makes changes to the attributes dependent on multiple values.
- *
- * @param $attr Assoc array of attributes, usually from
- * HTMLPurifier_Token_Tag::$attr
- * @param $config Mandatory HTMLPurifier_Config object.
- * @param $context Mandatory HTMLPurifier_Context object
- * @returns Processed attribute array.
- */
- abstract public function transform($attr, $config, $context);
-
- /**
- * Prepends CSS properties to the style attribute, creating the
- * attribute if it doesn't exist.
- * @param $attr Attribute array to process (passed by reference)
- * @param $css CSS to prepend
- */
- public function prependCSS(&$attr, $css) {
- $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
- $attr['style'] = $css . $attr['style'];
- }
-
- /**
- * Retrieves and removes an attribute
- * @param $attr Attribute array to process (passed by reference)
- * @param $key Key of attribute to confiscate
- */
- public function confiscateAttr(&$attr, $key) {
- if (!isset($attr[$key])) return null;
- $value = $attr[$key];
- unset($attr[$key]);
- return $value;
- }
-
- }
-
-
-
- /**
- * Provides lookup array of attribute types to HTMLPurifier_AttrDef objects
- */
- class HTMLPurifier_AttrTypes
- {
- /**
- * Lookup array of attribute string identifiers to concrete implementations
- */
- protected $info = array();
-
- /**
- * Constructs the info array, supplying default implementations for attribute
- * types.
- */
- public function __construct() {
- // XXX This is kind of poor, since we don't actually /clone/
- // instances; instead, we use the supplied make() attribute. So,
- // the underlying class must know how to deal with arguments.
- // With the old implementation of Enum, that ignored its
- // arguments when handling a make dispatch, the IAlign
- // definition wouldn't work.
-
- // pseudo-types, must be instantiated via shorthand
- $this->info['Enum'] = new HTMLPurifier_AttrDef_Enum();
- $this->info['Bool'] = new HTMLPurifier_AttrDef_HTML_Bool();
-
- $this->info['CDATA'] = new HTMLPurifier_AttrDef_Text();
- $this->info['ID'] = new HTMLPurifier_AttrDef_HTML_ID();
- $this->info['Length'] = new HTMLPurifier_AttrDef_HTML_Length();
- $this->info['MultiLength'] = new HTMLPurifier_AttrDef_HTML_MultiLength();
- $this->info['NMTOKENS'] = new HTMLPurifier_AttrDef_HTML_Nmtokens();
- $this->info['Pixels'] = new HTMLPurifier_AttrDef_HTML_Pixels();
- $this->info['Text'] = new HTMLPurifier_AttrDef_Text();
- $this->info['URI'] = new HTMLPurifier_AttrDef_URI();
- $this->info['LanguageCode'] = new HTMLPurifier_AttrDef_Lang();
- $this->info['Color'] = new HTMLPurifier_AttrDef_HTML_Color();
- $this->info['IAlign'] = self::makeEnum('top,middle,bottom,left,right');
- $this->info['LAlign'] = self::makeEnum('top,bottom,left,right');
- $this->info['FrameTarget'] = new HTMLPurifier_AttrDef_HTML_FrameTarget();
-
- // unimplemented aliases
- $this->info['ContentType'] = new HTMLPurifier_AttrDef_Text();
- $this->info['ContentTypes'] = new HTMLPurifier_AttrDef_Text();
- $this->info['Charsets'] = 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)
- // FIXME: ^^ not always, see start and value of list items
- $this->info['Number'] = new HTMLPurifier_AttrDef_Integer(false, false, true);
- }
-
- private static function makeEnum($in) {
- return new HTMLPurifier_AttrDef_Clone(new HTMLPurifier_AttrDef_Enum(explode(',', $in)));
- }
-
- /**
- * Retrieves a type
- * @param $type String type name
- * @return Object AttrDef for type
- */
- public function get($type) {
-
- // determine if there is any extra info tacked on
- if (strpos($type, '#') !== false) list($type, $string) = explode('#', $type, 2);
- else $string = '';
-
- if (!isset($this->info[$type])) {
- trigger_error('Cannot retrieve undefined attribute type ' . $type, E_USER_ERROR);
- return;
- }
-
- return $this->info[$type]->make($string);
-
- }
-
- /**
- * Sets a new implementation for a type
- * @param $type String type name
- * @param $impl Object AttrDef for type
- */
- public function set($type, $impl) {
- $this->info[$type] = $impl;
- }
- }
-
-
-
- /**
- * Validates the attributes of a token. Doesn't manage required attributes
- * very well. The only reason we factored this out was because RemoveForeignElements
- * also needed it besides ValidateAttributes.
- */
- class HTMLPurifier_AttrValidator
- {
-
- /**
- * Validates the attributes of a token, returning a modified token
- * that has valid tokens
- * @param $token Reference to token to validate. We require a reference
- * because the operation this class performs on the token are
- * not atomic, so the context CurrentToken to be updated
- * throughout
- * @param $config Instance of HTMLPurifier_Config
- * @param $context Instance of HTMLPurifier_Context
- */
- public function validateToken(&$token, &$config, $context) {
-
- $definition = $config->getHTMLDefinition();
- $e =& $context->get('ErrorCollector', true);
-
- // initialize IDAccumulator if necessary
- $ok =& $context->get('IDAccumulator', true);
- if (!$ok) {
- $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
- $context->register('IDAccumulator', $id_accumulator);
- }
-
- // initialize CurrentToken if necessary
- $current_token =& $context->get('CurrentToken', true);
- if (!$current_token) $context->register('CurrentToken', $token);
-
- if (
- !$token instanceof HTMLPurifier_Token_Start &&
- !$token instanceof HTMLPurifier_Token_Empty
- ) return $token;
-
- // create alias to global definition array, see also $defs
- // DEFINITION CALL
- $d_defs = $definition->info_global_attr;
-
- // don't update token until the very end, to ensure an atomic update
- $attr = $token->attr;
-
- // do global transformations (pre)
- // nothing currently utilizes this
- foreach ($definition->info_attr_transform_pre as $transform) {
- $attr = $transform->transform($o = $attr, $config, $context);
- if ($e) {
- if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
- }
- }
-
- // do local transformations only applicable to this element (pre)
- // ex. <p align="right"> to <p style="text-align:right;">
- foreach ($definition->info[$token->name]->attr_transform_pre as $transform) {
- $attr = $transform->transform($o = $attr, $config, $context);
- if ($e) {
- if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
- }
- }
-
- // create alias to this element's attribute definition array, see
- // also $d_defs (global attribute definition array)
- // DEFINITION CALL
- $defs = $definition->info[$token->name]->attr;
-
- $attr_key = false;
- $context->register('CurrentAttr', $attr_key);
-
- // iterate through all the attribute keypairs
- // Watch out for name collisions: $key has previously been used
- foreach ($attr as $attr_key => $value) {
-
- // call the definition
- if ( isset($defs[$attr_key]) ) {
- // there is a local definition defined
- if ($defs[$attr_key] === false) {
- // We've explicitly been told not to allow this element.
- // This is usually when there's a global definition
- // that must be overridden.
- // Theoretically speaking, we could have a
- // AttrDef_DenyAll, but this is faster!
- $result = false;
- } else {
- // validate according to the element's definition
- $result = $defs[$attr_key]->validate(
- $value, $config, $context
- );
- }
- } elseif ( isset($d_defs[$attr_key]) ) {
- // there is a global definition defined, validate according
- // to the global definition
- $result = $d_defs[$attr_key]->validate(
- $value, $config, $context
- );
- } else {
- // system never heard of the attribute? DELETE!
- $result = false;
- }
-
- // put the results into effect
- if ($result === false || $result === null) {
- // this is a generic error message that should replaced
- // with more specific ones when possible
- if ($e) $e->send(E_ERROR, 'AttrValidator: Attribute removed');
-
- // remove the attribute
- unset($attr[$attr_key]);
- } elseif (is_string($result)) {
- // generally, if a substitution is happening, there
- // was some sort of implicit correction going on. We'll
- // delegate it to the attribute classes to say exactly what.
-
- // simple substitution
- $attr[$attr_key] = $result;
- } else {
- // nothing happens
- }
-
- // we'd also want slightly more complicated substitution
- // involving an array as the return value,
- // although we're not sure how colliding attributes would
- // resolve (certain ones would be completely overriden,
- // others would prepend themselves).
- }
-
- $context->destroy('CurrentAttr');
-
- // post transforms
-
- // global (error reporting untested)
- foreach ($definition->info_attr_transform_post as $transform) {
- $attr = $transform->transform($o = $attr, $config, $context);
- if ($e) {
- if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
- }
- }
-
- // local (error reporting untested)
- foreach ($definition->info[$token->name]->attr_transform_post as $transform) {
- $attr = $transform->transform($o = $attr, $config, $context);
- if ($e) {
- if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
- }
- }
-
- $token->attr = $attr;
-
- // destroy CurrentToken if we made it ourselves
- if (!$current_token) $context->destroy('CurrentToken');
-
- }
-
-
- }
-
-
-
- // constants are slow, so we use as few as possible
- if (!defined('HTMLPURIFIER_PREFIX')) {
- define('HTMLPURIFIER_PREFIX', dirname(__FILE__) . '/standalone');
- set_include_path(HTMLPURIFIER_PREFIX . PATH_SEPARATOR . get_include_path());
- }
-
- // accomodations for versions earlier than 5.0.2
- // borrowed from PHP_Compat, LGPL licensed, by Aidan Lister <aidan@php.net>
- if (!defined('PHP_EOL')) {
- switch (strtoupper(substr(PHP_OS, 0, 3))) {
- case 'WIN':
- define('PHP_EOL', "\r\n");
- break;
- case 'DAR':
- define('PHP_EOL', "\r");
- break;
- default:
- define('PHP_EOL', "\n");
- }
- }
-
- /**
- * Bootstrap class that contains meta-functionality for HTML Purifier such as
- * the autoload function.
- *
- * @note
- * This class may be used without any other files from HTML Purifier.
- */
- class HTMLPurifier_Bootstrap
- {
-
- /**
- * Autoload function for HTML Purifier
- * @param $class Class to load
- */
- public static function autoload($class) {
- $file = HTMLPurifier_Bootstrap::getPath($class);
- if (!$file) return false;
- // Technically speaking, it should be ok and more efficient to
- // just do 'require', but Antonio Parraga reports that with
- // Zend extensions such as Zend debugger and APC, this invariant
- // may be broken. Since we have efficient alternatives, pay
- // the cost here and avoid the bug.
- require_once HTMLPURIFIER_PREFIX . '/' . $file;
- return true;
- }
-
- /**
- * Returns the path for a specific class.
- */
- public static function getPath($class) {
- if (strncmp('HTMLPurifier', $class, 12) !== 0) return false;
- // Custom implementations
- if (strncmp('HTMLPurifier_Language_', $class, 22) === 0) {
- $code = str_replace('_', '-', substr($class, 22));
- $file = 'HTMLPurifier/Language/classes/' . $code . '.php';
- } else {
- $file = str_replace('_', '/', $class) . '.php';
- }
- if (!file_exists(HTMLPURIFIER_PREFIX . '/' . $file)) return false;
- return $file;
- }
-
- /**
- * "Pre-registers" our autoloader on the SPL stack.
- */
- public static function registerAutoload() {
- $autoload = array('HTMLPurifier_Bootstrap', 'autoload');
- if ( ($funcs = spl_autoload_functions()) === false ) {
- spl_autoload_register($autoload);
- } elseif (function_exists('spl_autoload_unregister')) {
- $buggy = version_compare(PHP_VERSION, '5.2.11', '<');
- $compat = version_compare(PHP_VERSION, '5.1.2', '<=') &&
- version_compare(PHP_VERSION, '5.1.0', '>=');
- foreach ($funcs as $func) {
- if ($buggy && is_array($func)) {
- // :TRICKY: There are some compatibility issues and some
- // places where we need to error out
- $reflector = new ReflectionMethod($func[0], $func[1]);
- if (!$reflector->isStatic()) {
- throw new Exception('
- HTML Purifier autoloader registrar is not compatible
- with non-static object methods due to PHP Bug #44144;
- Please do not use HTMLPurifier.autoload.php (or any
- file that includes this file); instead, place the code:
- spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\'))
- after your own autoloaders.
- ');
- }
- // Suprisingly, spl_autoload_register supports the
- // Class::staticMethod callback format, although call_user_func doesn't
- if ($compat) $func = implode('::', $func);
- }
- spl_autoload_unregister($func);
- }
- spl_autoload_register($autoload);
- foreach ($funcs as $func) spl_autoload_register($func);
- }
- }
-
- }
-
-
-
- /**
- * Super-class for definition datatype objects, implements serialization
- * functions for the class.
- */
- abstract class HTMLPurifier_Definition
- {
-
- /**
- * Has setup() been called yet?
- */
- public $setup = false;
-
- /**
- * If true, write out the final definition object to the cache after
- * setup. This will be true only if all invocations to get a raw
- * definition object are also optimized. This does not cause file
- * system thrashing because on subsequent calls the cached object
- * is used and any writes to the raw definition object are short
- * circuited. See enduser-customize.html for the high-level
- * picture.
- */
- public $optimized = null;
-
- /**
- * What type of definition is it?
- */
- public $type;
-
- /**
- * Sets up the definition object into the final form, something
- * not done by the constructor
- * @param $config HTMLPurifier_Config instance
- */
- abstract protected function doSetup($config);
-
- /**
- * Setup function that aborts if already setup
- * @param $config HTMLPurifier_Config instance
- */
- public function setup($config) {
- if ($this->setup) return;
- $this->setup = true;
- $this->doSetup($config);
- }
-
- }
-
-
-
- /**
- * Defines allowed CSS attributes and what their values are.
- * @see HTMLPurifier_HTMLDefinition
- */
- class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
- {
-
- public $type = 'CSS';
-
- /**
- * Assoc array of attribute name to definition object.
- */
- public $info = array();
-
- /**
- * Constructs the info array. The meat of this class.
- */
- protected function doSetup($config) {
-
- $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum(
- array('left', 'right', 'center', 'justify'), false);
-
- $border_style =
- $this->info['border-bottom-style'] =
- $this->info['border-right-style'] =
- $this->info['border-left-style'] =
- $this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum(
- array('none', 'hidden', 'dotted', 'dashed', 'solid', 'double',
- 'groove', 'ridge', 'inset', 'outset'), false);
-
- $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style);
-
- $this->info['clear'] = new HTMLPurifier_AttrDef_Enum(
- array('none', 'left', 'right', 'both'), false);
- $this->info['float'] = new HTMLPurifier_AttrDef_Enum(
- array('none', 'left', 'right'), false);
- $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum(
- array('normal', 'italic', 'oblique'), false);
- $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum(
- array('normal', 'small-caps'), false);
-
- $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite(
- array(
- new HTMLPurifier_AttrDef_Enum(array('none')),
- new HTMLPurifier_AttrDef_CSS_URI()
- )
- );
-
- $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum(
- array('inside', 'outside'), false);
- $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum(
- array('disc', 'circle', 'square', 'decimal', 'lower-roman',
- 'upper-roman', 'lower-alpha', 'upper-alpha', 'none'), false);
- $this->info['list-style-image'] = $uri_or_none;
-
- $this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config);
-
- $this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum(
- array('capitalize', 'uppercase', 'lowercase', 'none'), false);
- $this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color();
-
- $this->info['background-image'] = $uri_or_none;
- $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum(
- array('repeat', 'repeat-x', 'repeat-y', 'no-repeat')
- );
- $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
- array('scroll', 'fixed')
- );
- $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition();
-
- $border_color =
- $this->info['border-top-color'] =
- $this->info['border-bottom-color'] =
- $this->info['border-left-color'] =
- $this->info['border-right-color'] =
- $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Enum(array('transparent')),
- new HTMLPurifier_AttrDef_CSS_Color()
- ));
-
- $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config);
-
- $this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color);
-
- $border_width =
- $this->info['border-top-width'] =
- $this->info['border-bottom-width'] =
- $this->info['border-left-width'] =
- $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')),
- new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
- ));
-
- $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
-
- $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Enum(array('normal')),
- new HTMLPurifier_AttrDef_CSS_Length()
- ));
-
- $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Enum(array('normal')),
- new HTMLPurifier_AttrDef_CSS_Length()
- ));
-
- $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Enum(array('xx-small', 'x-small',
- 'small', 'medium', 'large', 'x-large', 'xx-large',
- 'larger', 'smaller')),
- new HTMLPurifier_AttrDef_CSS_Percentage(),
- new HTMLPurifier_AttrDef_CSS_Length()
- ));
-
- $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Enum(array('normal')),
- new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
- new HTMLPurifier_AttrDef_CSS_Length('0'),
- new HTMLPurifier_AttrDef_CSS_Percentage(true)
- ));
-
- $margin =
- $this->info['margin-top'] =
- $this->info['margin-bottom'] =
- $this->info['margin-left'] =
- $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_CSS_Length(),
- new HTMLPurifier_AttrDef_CSS_Percentage(),
- new HTMLPurifier_AttrDef_Enum(array('auto'))
- ));
-
- $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin);
-
- // non-negative
- $padding =
- $this->info['padding-top'] =
- $this->info['padding-bottom'] =
- $this->info['padding-left'] =
- $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_CSS_Length('0'),
- new HTMLPurifier_AttrDef_CSS_Percentage(true)
- ));
-
- $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding);
-
- $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_CSS_Length(),
- new HTMLPurifier_AttrDef_CSS_Percentage()
- ));
-
- $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_CSS_Length('0'),
- new HTMLPurifier_AttrDef_CSS_Percentage(true),
- new HTMLPurifier_AttrDef_Enum(array('auto'))
- ));
- $max = $config->get('CSS.MaxImgLength');
-
- $this->info['width'] =
- $this->info['height'] =
- $max === null ?
- $trusted_wh :
- new HTMLPurifier_AttrDef_Switch('img',
- // For img tags:
- new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_CSS_Length('0', $max),
- new HTMLPurifier_AttrDef_Enum(array('auto'))
- )),
- // For everyone else:
- $trusted_wh
- );
-
- $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();
-
- $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily();
-
- // this could use specialized code
- $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum(
- array('normal', 'bold', 'bolder', 'lighter', '100', '200', '300',
- '400', '500', '600', '700', '800', '900'), false);
-
- // MUST be called after other font properties, as it references
- // a CSSDefinition object
- $this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config);
-
- // same here
- $this->info['border'] =
- $this->info['border-bottom'] =
- $this->info['border-top'] =
- $this->info['border-left'] =
- $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config);
-
- $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum(array(
- 'collapse', 'separate'));
-
- $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum(array(
- 'top', 'bottom'));
-
- $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum(array(
- 'auto', 'fixed'));
-
- $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Enum(array('baseline', 'sub', 'super',
- 'top', 'text-top', 'middle', 'bottom', 'text-bottom')),
- new HTMLPurifier_AttrDef_CSS_Length(),
- new HTMLPurifier_AttrDef_CSS_Percentage()
- ));
-
- $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2);
-
- // partial support
- $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
-
- if ($config->get('CSS.Proprietary')) {
- $this->doSetupProprietary($config);
- }
-
- if ($config->get('CSS.AllowTricky')) {
- $this->doSetupTricky($config);
- }
-
- if ($config->get('CSS.Trusted')) {
- $this->doSetupTrusted($config);
- }
-
- $allow_important = $config->get('CSS.AllowImportant');
- // wrap all attr-defs with decorator that handles !important
- foreach ($this->info as $k => $v) {
- $this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important);
- }
-
- $this->setupConfigStuff($config);
- }
-
- protected function doSetupProprietary($config) {
- // Internet Explorer only scrollbar colors
- $this->info['scrollbar-arrow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
- $this->info['scrollbar-base-color'] = new HTMLPurifier_AttrDef_CSS_Color();
- $this->info['scrollbar-darkshadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
- $this->info['scrollbar-face-color'] = new HTMLPurifier_AttrDef_CSS_Color();
- $this->info['scrollbar-highlight-color'] = new HTMLPurifier_AttrDef_CSS_Color();
- $this->info['scrollbar-shadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
-
- // technically not proprietary, but CSS3, and no one supports it
- $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
- $this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
- $this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
-
- // only opacity, for now
- $this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter();
-
- }
-
- protected function doSetupTricky($config) {
- $this->info['display'] = new HTMLPurifier_AttrDef_Enum(array(
- 'inline', 'block', 'list-item', 'run-in', 'compact',
- 'marker', 'table', 'inline-table', 'table-row-group',
- 'table-header-group', 'table-footer-group', 'table-row',
- 'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none'
- ));
- $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum(array(
- 'visible', 'hidden', 'collapse'
- ));
- $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll'));
- }
-
- protected function doSetupTrusted($config) {
- $this->info['position'] = new HTMLPurifier_AttrDef_Enum(array(
- 'static', 'relative', 'absolute', 'fixed'
- ));
- $this->info['top'] =
- $this->info['left'] =
- $this->info['right'] =
- $this->info['bottom'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_CSS_Length(),
- new HTMLPurifier_AttrDef_CSS_Percentage(),
- new HTMLPurifier_AttrDef_Enum(array('auto')),
- ));
- $this->info['z-index'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
- new HTMLPurifier_AttrDef_Integer(),
- new HTMLPurifier_AttrDef_Enum(array('auto')),
- ));
- }
-
- /**
- * Performs extra config-based processing. Based off of
- * HTMLPurifier_HTMLDefinition.
- * @todo Refactor duplicate elements into common class (probably using
- * composition, not inheritance).
- */
- protected function setupConfigStuff($config) {
-
- // setup allowed elements
- $support = "(for information on implementing this, see the ".
- "support forums) ";
- $allowed_properties = $config->get('CSS.AllowedProperties');
- if ($allowed_properties !== null) {
- foreach ($this->info as $name => $d) {
- if(!isset($allowed_properties[$name])) unset($this->info[$name]);
- unset($allowed_properties[$name]);
- }
- // emit errors
- foreach ($allowed_properties as $name => $d) {
- // :TODO: Is this htmlspecialchars() call really necessary?
- $name = htmlspecialchars($name);
- trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING);
- }
- }
-
- $forbidden_properties = $config->get('CSS.ForbiddenProperties');
- if ($forbidden_properties !== null) {
- foreach ($this->info as $name => $d) {
- if (isset($forbidden_properties[$name])) {
- unset($this->info[$name]);
- }
- }
- }
- …
Large files files are truncated, but you can click here to view the full file