"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "framework/vendors/htmlpurifier/HTMLPurifier.standalone.php" between
yii-1.1.19.5790cb.tar.gz and yii-1.1.20.6ed384.tar.gz

About: Yii is a high-performance component-based PHP framework for developing large-scale Web applications. Hint: Yii 1.1 is now in maintenance mode.

HTMLPurifier.standalone.php  (yii-1.1.19.5790cb):HTMLPurifier.standalone.php  (yii-1.1.20.6ed384)
<?php <?php
/** /**
* @file * @file
* This file was auto-generated by generate-includes.php and includes all of * 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 * 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 * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
* FILE, changes will be overwritten the next time the script is run. * FILE, changes will be overwritten the next time the script is run.
* *
* @version 4.9.2 * @version 4.9.3
* *
* @warning * @warning
* You must *not* include any other HTML Purifier files before this file, * You must *not* include any other HTML Purifier files before this file,
* because 'require' not 'require_once' is used. * because 'require' not 'require_once' is used.
* *
* @warning * @warning
* This file requires that the include path contains the HTML Purifier * This file requires that the include path contains the HTML Purifier
* library directory; this is not auto-set. * library directory; this is not auto-set.
*/ */
skipping to change at line 40 skipping to change at line 40
* -# Making the tokens well-formed, * -# Making the tokens well-formed,
* -# Fixing the nesting of the nodes, and * -# Fixing the nesting of the nodes, and
* -# Validating attributes of the nodes; and * -# Validating attributes of the nodes; and
* -# Generating HTML from the purified tokens. * -# Generating HTML from the purified tokens.
* *
* However, most users will only need to interface with the HTMLPurifier * However, most users will only need to interface with the HTMLPurifier
* and HTMLPurifier_Config. * and HTMLPurifier_Config.
*/ */
/* /*
HTML Purifier 4.9.2 - Standards Compliant HTML Filtering HTML Purifier 4.9.3 - Standards Compliant HTML Filtering
Copyright (C) 2006-2008 Edward Z. Yang Copyright (C) 2006-2008 Edward Z. Yang
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. 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, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
skipping to change at line 79 skipping to change at line 79
* @todo We need an easier way to inject strategies using the configuration * @todo We need an easier way to inject strategies using the configuration
* object. * object.
*/ */
class HTMLPurifier class HTMLPurifier
{ {
/** /**
* Version of HTML Purifier. * Version of HTML Purifier.
* @type string * @type string
*/ */
public $version = '4.9.2'; public $version = '4.9.3';
/** /**
* Constant with version of HTML Purifier. * Constant with version of HTML Purifier.
*/ */
const VERSION = '4.9.2'; const VERSION = '4.9.3';
/** /**
* Global configuration object. * Global configuration object.
* @type HTMLPurifier_Config * @type HTMLPurifier_Config
*/ */
public $config; public $config;
/** /**
* Array of extra filter objects to run on HTML, * Array of extra filter objects to run on HTML,
* for backwards compatibility. * for backwards compatibility.
skipping to change at line 226 skipping to change at line 226
$filters = array_merge($filters, $this->filters); $filters = array_merge($filters, $this->filters);
// maybe prepare(), but later // maybe prepare(), but later
for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) { for ($i = 0, $filter_size = count($filters); $i < $filter_size; $i++) {
$html = $filters[$i]->preFilter($html, $config, $context); $html = $filters[$i]->preFilter($html, $config, $context);
} }
// purified HTML // purified HTML
$html = $html =
$this->generator->generateFromTokens( $this->generator->generateFromTokens(
// list of tokens // list of tokens
$this->strategy->execute( $this->strategy->execute(
// list of un-purified tokens // list of un-purified tokens
$lexer->tokenizeHTML( $lexer->tokenizeHTML(
// un-purified HTML // un-purified HTML
$html, $html,
$config, $config,
$context $context
), ),
$config, $config,
$context $context
) )
); );
for ($i = $filter_size - 1; $i >= 0; $i--) { for ($i = $filter_size - 1; $i >= 0; $i--) {
skipping to change at line 1079 skipping to change at line 1079
$autoload = array('HTMLPurifier_Bootstrap', 'autoload'); $autoload = array('HTMLPurifier_Bootstrap', 'autoload');
if (($funcs = spl_autoload_functions()) === false) { if (($funcs = spl_autoload_functions()) === false) {
spl_autoload_register($autoload); spl_autoload_register($autoload);
} elseif (function_exists('spl_autoload_unregister')) { } elseif (function_exists('spl_autoload_unregister')) {
if (version_compare(PHP_VERSION, '5.3.0', '>=')) { if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
// prepend flag exists, no need for shenanigans // prepend flag exists, no need for shenanigans
spl_autoload_register($autoload, true, true); spl_autoload_register($autoload, true, true);
} else { } else {
$buggy = version_compare(PHP_VERSION, '5.2.11', '<'); $buggy = version_compare(PHP_VERSION, '5.2.11', '<');
$compat = version_compare(PHP_VERSION, '5.1.2', '<=') && $compat = version_compare(PHP_VERSION, '5.1.2', '<=') &&
version_compare(PHP_VERSION, '5.1.0', '>='); version_compare(PHP_VERSION, '5.1.0', '>=');
foreach ($funcs as $func) { foreach ($funcs as $func) {
if ($buggy && is_array($func)) { if ($buggy && is_array($func)) {
// :TRICKY: There are some compatibility issues and some // :TRICKY: There are some compatibility issues and some
// places where we need to error out // places where we need to error out
$reflector = new ReflectionMethod($func[0], $func[1]); $reflector = new ReflectionMethod($func[0], $func[1]);
if (!$reflector->isStatic()) { if (!$reflector->isStatic()) {
throw new Exception( throw new Exception(
'HTML Purifier autoloader registrar is not compa tible 'HTML Purifier autoloader registrar is not compa tible
with non-static object methods due to PHP Bug #4 4144; with non-static object methods due to PHP Bug #4 4144;
Please do not use HTMLPurifier.autoload.php (or any Please do not use HTMLPurifier.autoload.php (or any
skipping to change at line 1191 skipping to change at line 1191
* @param HTMLPurifier_Config $config * @param HTMLPurifier_Config $config
*/ */
protected function doSetup($config) protected function doSetup($config)
{ {
$this->info['text-align'] = new HTMLPurifier_AttrDef_Enum( $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum(
array('left', 'right', 'center', 'justify'), array('left', 'right', 'center', 'justify'),
false false
); );
$border_style = $border_style =
$this->info['border-bottom-style'] = $this->info['border-bottom-style'] =
$this->info['border-right-style'] = $this->info['border-right-style'] =
$this->info['border-left-style'] = $this->info['border-left-style'] =
$this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum( $this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum(
array( array(
'none', 'none',
'hidden', 'hidden',
'dotted', 'dotted',
'dashed', 'dashed',
'solid', 'solid',
'double', 'double',
'groove', 'groove',
'ridge', 'ridge',
'inset', 'inset',
'outset' 'outset'
), ),
false false
); );
$this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($bor der_style); $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($bor der_style);
$this->info['clear'] = new HTMLPurifier_AttrDef_Enum( $this->info['clear'] = new HTMLPurifier_AttrDef_Enum(
array('none', 'left', 'right', 'both'), array('none', 'left', 'right', 'both'),
false false
); );
$this->info['float'] = new HTMLPurifier_AttrDef_Enum( $this->info['float'] = new HTMLPurifier_AttrDef_Enum(
array('none', 'left', 'right'), array('none', 'left', 'right'),
false false
skipping to change at line 1274 skipping to change at line 1274
$this->info['background-image'] = $uri_or_none; $this->info['background-image'] = $uri_or_none;
$this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum( $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum(
array('repeat', 'repeat-x', 'repeat-y', 'no-repeat') array('repeat', 'repeat-x', 'repeat-y', 'no-repeat')
); );
$this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum( $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
array('scroll', 'fixed') array('scroll', 'fixed')
); );
$this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_Backgr oundPosition(); $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_Backgr oundPosition();
$border_color = $border_color =
$this->info['border-top-color'] = $this->info['border-top-color'] =
$this->info['border-bottom-color'] = $this->info['border-bottom-color'] =
$this->info['border-left-color'] = $this->info['border-left-color'] =
$this->info['border-right-color'] = $this->info['border-right-color'] =
$this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Compo $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite
site( (
array( array(
new HTMLPurifier_AttrDef_Enum(array('transparent')), new HTMLPurifier_AttrDef_Enum(array('transparent')),
new HTMLPurifier_AttrDef_CSS_Color() new HTMLPurifier_AttrDef_CSS_Color()
) )
); );
$this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($con fig); $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($con fig);
$this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($bor der_color); $this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($bor der_color);
$border_width = $border_width =
$this->info['border-top-width'] = $this->info['border-top-width'] =
$this->info['border-bottom-width'] = $this->info['border-bottom-width'] =
$this->info['border-left-width'] = $this->info['border-left-width'] =
$this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Com $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composi
posite( te(
array( array(
new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')),
')), new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative )
) );
);
$this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($bor der_width); $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($bor der_width);
$this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite( $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(
array( array(
new HTMLPurifier_AttrDef_Enum(array('normal')), new HTMLPurifier_AttrDef_Enum(array('normal')),
new HTMLPurifier_AttrDef_CSS_Length() new HTMLPurifier_AttrDef_CSS_Length()
) )
); );
skipping to change at line 1346 skipping to change at line 1346
$this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite( $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(
array( array(
new HTMLPurifier_AttrDef_Enum(array('normal')), new HTMLPurifier_AttrDef_Enum(array('normal')),
new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Percentage(true) new HTMLPurifier_AttrDef_CSS_Percentage(true)
) )
); );
$margin = $margin =
$this->info['margin-top'] = $this->info['margin-top'] =
$this->info['margin-bottom'] = $this->info['margin-bottom'] =
$this->info['margin-left'] = $this->info['margin-left'] =
$this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(
( array(
array( new HTMLPurifier_AttrDef_CSS_Length(),
new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage(),
new HTMLPurifier_AttrDef_CSS_Percentage(), new HTMLPurifier_AttrDef_Enum(array('auto'))
new HTMLPurifier_AttrDef_Enum(array('auto')) )
) );
);
$this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin); $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin);
// non-negative // non-negative
$padding = $padding =
$this->info['padding-top'] = $this->info['padding-top'] =
$this->info['padding-bottom'] = $this->info['padding-bottom'] =
$this->info['padding-left'] = $this->info['padding-left'] =
$this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composit $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(
e( array(
array( new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Length('0'), new HTMLPurifier_AttrDef_CSS_Percentage(true)
new HTMLPurifier_AttrDef_CSS_Percentage(true) )
) );
);
$this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding) ; $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding) ;
$this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite( $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(
array( array(
new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Length(),
new HTMLPurifier_AttrDef_CSS_Percentage() new HTMLPurifier_AttrDef_CSS_Percentage()
) )
); );
skipping to change at line 1722 skipping to change at line 1722
* *
* @todo Reconsider some of the public member variables * @todo Reconsider some of the public member variables
*/ */
class HTMLPurifier_Config class HTMLPurifier_Config
{ {
/** /**
* HTML Purifier's version * HTML Purifier's version
* @type string * @type string
*/ */
public $version = '4.9.2'; public $version = '4.9.3';
/** /**
* Whether or not to automatically finalize * Whether or not to automatically finalize
* the object if a read operation is done. * the object if a read operation is done.
* @type bool * @type bool
*/ */
public $autoFinalize = true; public $autoFinalize = true;
// protected member variables // protected member variables
skipping to change at line 2034 skipping to change at line 2034
return; return;
} }
$this->aliasMode = true; $this->aliasMode = true;
$this->set($def->key, $value); $this->set($def->key, $value);
$this->aliasMode = false; $this->aliasMode = false;
$this->triggerError("$key is an alias, preferred directive name is { $def->key}", E_USER_NOTICE); $this->triggerError("$key is an alias, preferred directive name is { $def->key}", E_USER_NOTICE);
return; return;
} }
// Raw type might be negative when using the fully optimized form // Raw type might be negative when using the fully optimized form
// of stdclass, which indicates allow_null == true // of stdClass, which indicates allow_null == true
$rtype = is_int($def) ? $def : $def->type; $rtype = is_int($def) ? $def : $def->type;
if ($rtype < 0) { if ($rtype < 0) {
$type = -$rtype; $type = -$rtype;
$allow_null = true; $allow_null = true;
} else { } else {
$type = $rtype; $type = $rtype;
$allow_null = isset($def->allow_null); $allow_null = isset($def->allow_null);
} }
try { try {
skipping to change at line 2483 skipping to change at line 2483
/** /**
* Merges in configuration values from $_GET/$_POST to object. NOT STATIC. * Merges in configuration values from $_GET/$_POST to object. NOT STATIC.
* *
* @param array $array $_GET or $_POST array to import * @param array $array $_GET or $_POST array to import
* @param string|bool $index Index/name that the config variables are in * @param string|bool $index Index/name that the config variables are in
* @param array|bool $allowed List of allowed namespaces/directives * @param array|bool $allowed List of allowed namespaces/directives
* @param bool $mq_fix Boolean whether or not to enable magic quotes fix * @param bool $mq_fix Boolean whether or not to enable magic quotes fix
*/ */
public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true) public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true)
{ {
$ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allow $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowe
ed, $mq_fix, $this->def); d, $mq_fix, $this->def);
$this->loadArray($ret); $this->loadArray($ret);
} }
/** /**
* Prepares an array from a form into something usable for the more * Prepares an array from a form into something usable for the more
* strict parts of HTMLPurifier_Config * strict parts of HTMLPurifier_Config
* *
* @param array $array $_GET or $_POST array to import * @param array $array $_GET or $_POST array to import
* @param string|bool $index Index/name that the config variables are in * @param string|bool $index Index/name that the config variables are in
* @param array|bool $allowed List of allowed namespaces/directives * @param array|bool $allowed List of allowed namespaces/directives
* @param bool $mq_fix Boolean whether or not to enable magic quotes fix * @param bool $mq_fix Boolean whether or not to enable magic quotes fix
skipping to change at line 2642 skipping to change at line 2642
* @type array * @type array
*/ */
public $defaultPlist; public $defaultPlist;
/** /**
* Definition of the directives. * Definition of the directives.
* The structure of this is: * The structure of this is:
* *
* array( * array(
* 'Namespace' => array( * 'Namespace' => array(
* 'Directive' => new stdclass(), * 'Directive' => new stdClass(),
* ) * )
* ) * )
* *
* The stdclass may have the following properties: * The stdClass may have the following properties:
* *
* - If isAlias isn't set: * - If isAlias isn't set:
* - type: Integer type of directive, see HTMLPurifier_VarParser for de finitions * - type: Integer type of directive, see HTMLPurifier_VarParser for de finitions
* - allow_null: If set, this directive allows null values * - allow_null: If set, this directive allows null values
* - aliases: If set, an associative array of value aliases to real val ues * - aliases: If set, an associative array of value aliases to real val ues
* - allowed: If set, a lookup array of allowed (string) values * - allowed: If set, a lookup array of allowed (string) values
* - If isAlias is set: * - If isAlias is set:
* - namespace: Namespace this directive aliases to * - namespace: Namespace this directive aliases to
* - name: Directive name this directive aliases to * - name: Directive name this directive aliases to
* *
* In certain degenerate cases, stdclass will actually be an integer. In * In certain degenerate cases, stdClass will actually be an integer. In
* that case, the value is equivalent to an stdclass with the type * that case, the value is equivalent to an stdClass with the type
* property set to the integer. If the integer is negative, type is * property set to the integer. If the integer is negative, type is
* equal to the absolute value of integer, and allow_null is true. * equal to the absolute value of integer, and allow_null is true.
* *
* This class is friendly with HTMLPurifier_Config. If you need introspectio n * This class is friendly with HTMLPurifier_Config. If you need introspectio n
* about the schema, you're better of using the ConfigSchema_Interchange, * about the schema, you're better of using the ConfigSchema_Interchange,
* which uses more memory but has much richer information. * which uses more memory but has much richer information.
* @type array * @type array
*/ */
public $info = array(); public $info = array();
skipping to change at line 2723 skipping to change at line 2723
* @warning This method's signature is slightly different from the legacy * @warning This method's signature is slightly different from the legacy
* define() static method! Beware! * define() static method! Beware!
* @param string $key Name of directive * @param string $key Name of directive
* @param mixed $default Default value of directive * @param mixed $default Default value of directive
* @param string $type Allowed type of the directive. See * @param string $type Allowed type of the directive. See
* HTMLPurifier_DirectiveDef::$type for allowed values * HTMLPurifier_DirectiveDef::$type for allowed values
* @param bool $allow_null Whether or not to allow null values * @param bool $allow_null Whether or not to allow null values
*/ */
public function add($key, $default, $type, $allow_null) public function add($key, $default, $type, $allow_null)
{ {
$obj = new stdclass(); $obj = new stdClass();
$obj->type = is_int($type) ? $type : HTMLPurifier_VarParser::$types[$typ e]; $obj->type = is_int($type) ? $type : HTMLPurifier_VarParser::$types[$typ e];
if ($allow_null) { if ($allow_null) {
$obj->allow_null = true; $obj->allow_null = true;
} }
$this->info[$key] = $obj; $this->info[$key] = $obj;
$this->defaults[$key] = $default; $this->defaults[$key] = $default;
$this->defaultPlist->set($key, $default); $this->defaultPlist->set($key, $default);
} }
/** /**
skipping to change at line 2770 skipping to change at line 2770
$this->info[$key]->allowed = $allowed; $this->info[$key]->allowed = $allowed;
} }
/** /**
* Defines a directive alias for backwards compatibility * Defines a directive alias for backwards compatibility
* @param string $key Directive that will be aliased * @param string $key Directive that will be aliased
* @param string $new_key Directive that the alias will be to * @param string $new_key Directive that the alias will be to
*/ */
public function addAlias($key, $new_key) public function addAlias($key, $new_key)
{ {
$obj = new stdclass; $obj = new stdClass;
$obj->key = $new_key; $obj->key = $new_key;
$obj->isAlias = true; $obj->isAlias = true;
$this->info[$key] = $obj; $this->info[$key] = $obj;
} }
/** /**
* Replaces any stdclass that only has the type property with type integer. * Replaces any stdClass that only has the type property with type integer.
*/ */
public function postProcess() public function postProcess()
{ {
foreach ($this->info as $key => $v) { foreach ($this->info as $key => $v) {
if (count((array) $v) == 1) { if (count((array) $v) == 1) {
$this->info[$key] = $v->type; $this->info[$key] = $v->type;
} elseif (count((array) $v) == 2 && isset($v->allow_null)) { } elseif (count((array) $v) == 2 && isset($v->allow_null)) {
$this->info[$key] = -$v->type; $this->info[$key] = -$v->type;
} }
} }
skipping to change at line 3082 skipping to change at line 3082
} }
/** /**
* Generates a unique identifier for a particular configuration * Generates a unique identifier for a particular configuration
* @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config
* @return string * @return string
*/ */
public function generateKey($config) public function generateKey($config)
{ {
return $config->version . ',' . // possibly replace with function calls return $config->version . ',' . // possibly replace with function calls
$config->getBatchSerial($this->type) . ',' . $config->getBatchSerial($this->type) . ',' .
$config->get($this->type . '.DefinitionRev'); $config->get($this->type . '.DefinitionRev');
} }
/** /**
* Tests whether or not a key is old with respect to the configuration's * Tests whether or not a key is old with respect to the configuration's
* version and revision number. * version and revision number.
* @param string $key Key to test * @param string $key Key to test
* @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config to tes t against * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config to tes t against
* @return bool * @return bool
*/ */
public function isOld($key, $config) public function isOld($key, $config)
skipping to change at line 3845 skipping to change at line 3845
// This is an optimization: if the string is already valid UTF-8, no // This is an optimization: if the string is already valid UTF-8, no
// need to do PHP stuff. 99% of the time, this will be the case. // need to do PHP stuff. 99% of the time, this will be the case.
if (preg_match( if (preg_match(
'/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{1 0000}-\x{10FFFF}]*$/Du', '/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{1 0000}-\x{10FFFF}]*$/Du',
$str $str
)) { )) {
return $str; return $str;
} }
$mState = 0; // cached expected number of octets after the current octet $mState = 0; // cached expected number of octets after the current octet
// until the beginning of the next UTF8 character sequence // until the beginning of the next UTF8 character sequence
$mUcs4 = 0; // cached Unicode character $mUcs4 = 0; // cached Unicode character
$mBytes = 1; // cached expected number of octets in the current sequence $mBytes = 1; // cached expected number of octets in the current sequence
// original code involved an $out that was an array of Unicode // original code involved an $out that was an array of Unicode
// codepoints. Instead of having to convert back into UTF-8, we've // codepoints. Instead of having to convert back into UTF-8, we've
// decided to directly append valid UTF-8 characters onto a string // decided to directly append valid UTF-8 characters onto a string
// $out once they're done. $char accumulates raw bytes, while $mUcs4 // $out once they're done. $char accumulates raw bytes, while $mUcs4
// turns into the Unicode code point, so there's some redundancy. // turns into the Unicode code point, so there's some redundancy.
$out = ''; $out = '';
skipping to change at line 4016 skipping to change at line 4016
// | | 1110zzzz | 10yyyyyy | 10xxxxxx | 3 byte 0x00000800..0x0000FF FF // | | 1110zzzz | 10yyyyyy | 10xxxxxx | 3 byte 0x00000800..0x0000FF FF
// | 11110www | 10wwzzzz | 10yyyyyy | 10xxxxxx | 4 byte 0x00010000..0x0010FF FF // | 11110www | 10wwzzzz | 10yyyyyy | 10xxxxxx | 4 byte 0x00010000..0x0010FF FF
// +----------+----------+----------+----------+ // +----------+----------+----------+----------+
// | 00000000 | 00011111 | 11111111 | 11111111 | Theoretical upper limit of legal scalars: 2097151 (0x001FFFFF) // | 00000000 | 00011111 | 11111111 | 11111111 | Theoretical upper limit of legal scalars: 2097151 (0x001FFFFF)
// | 00000000 | 00010000 | 11111111 | 11111111 | Defined upper limit of lega l scalar codes // | 00000000 | 00010000 | 11111111 | 11111111 | Defined upper limit of lega l scalar codes
// +----------+----------+----------+----------+ // +----------+----------+----------+----------+
public static function unichr($code) public static function unichr($code)
{ {
if ($code > 1114111 or $code < 0 or if ($code > 1114111 or $code < 0 or
($code >= 55296 and $code <= 57343) ) { ($code >= 55296 and $code <= 57343) ) {
// bits are set outside the "valid" range as defined // bits are set outside the "valid" range as defined
// by UNICODE 4.1.0 // by UNICODE 4.1.0
return ''; return '';
} }
$x = $y = $z = $w = 0; $x = $y = $z = $w = 0;
if ($code < 128) { if ($code < 128) {
// regular ASCII character // regular ASCII character
$x = $code; $x = $code;
} else { } else {
skipping to change at line 4514 skipping to change at line 4514
} }
// LEGACY CODE BELOW // LEGACY CODE BELOW
/** /**
* Callback regex string for parsing entities. * Callback regex string for parsing entities.
* @type string * @type string
*/ */
protected $_substituteEntitiesRegex = protected $_substituteEntitiesRegex =
'/&(?:[#]x([a-fA-F0-9]+)|[#]0*(\d+)|([A-Za-z_:][A-Za-z0-9.\-_:]*));?/'; '/&(?:[#]x([a-fA-F0-9]+)|[#]0*(\d+)|([A-Za-z_:][A-Za-z0-9.\-_:]*));?/';
// 1. hex 2. dec 3. string (XML style) // 1. hex 2. dec 3. string (XML style)
/** /**
* Decimal to parsed string conversion table for special entities. * Decimal to parsed string conversion table for special entities.
* @type array * @type array
*/ */
protected $_special_dec2str = protected $_special_dec2str =
array( array(
34 => '"', 34 => '"',
38 => '&', 38 => '&',
39 => "'", 39 => "'",
60 => '<', 60 => '<',
62 => '>' 62 => '>'
); );
/** /**
* Stripped entity names to decimal conversion table for special entities. * Stripped entity names to decimal conversion table for special entities.
* @type array * @type array
*/ */
protected $_special_ent2dec = protected $_special_ent2dec =
array( array(
'quot' => 34, 'quot' => 34,
'amp' => 38, 'amp' => 38,
'lt' => 60, 'lt' => 60,
'gt' => 62 'gt' => 62
); );
/** /**
* Substitutes non-special entities with their parsed equivalents. Since * Substitutes non-special entities with their parsed equivalents. Since
* running this whenever you have parsed character is t3h 5uck, we run * running this whenever you have parsed character is t3h 5uck, we run
* it before everything else. * it before everything else.
* *
* @param string $string String to have non-special entities parsed. * @param string $string String to have non-special entities parsed.
* @return string Parsed string. * @return string Parsed string.
*/ */
public function substituteNonSpecialEntities($string) public function substituteNonSpecialEntities($string)
skipping to change at line 5122 skipping to change at line 5122
} }
$html .= $this->generateFromToken($tokens[$i]); $html .= $this->generateFromToken($tokens[$i]);
} }
// Tidy cleanup // Tidy cleanup
if (extension_loaded('tidy') && $this->config->get('Output.TidyFormat')) { if (extension_loaded('tidy') && $this->config->get('Output.TidyFormat')) {
$tidy = new Tidy; $tidy = new Tidy;
$tidy->parseString( $tidy->parseString(
$html, $html,
array( array(
'indent'=> true, 'indent'=> true,
'output-xhtml' => $this->_xhtml, 'output-xhtml' => $this->_xhtml,
'show-body-only' => true, 'show-body-only' => true,
'indent-spaces' => 2, 'indent-spaces' => 2,
'wrap' => 68, 'wrap' => 68,
), ),
'utf8' 'utf8'
); );
$tidy->cleanRepair(); $tidy->cleanRepair();
$html = (string) $tidy; // explicit cast necessary $html = (string) $tidy; // explicit cast necessary
} }
// Normalize newlines to system defined value // Normalize newlines to system defined value
if ($this->config->get('Core.NormalizeNewlines')) { if ($this->config->get('Core.NormalizeNewlines')) {
$nl = $this->config->get('Output.Newline'); $nl = $this->config->get('Output.Newline');
skipping to change at line 5162 skipping to change at line 5162
public function generateFromToken($token) public function generateFromToken($token)
{ {
if (!$token instanceof HTMLPurifier_Token) { if (!$token instanceof HTMLPurifier_Token) {
trigger_error('Cannot generate HTML from non-HTMLPurifier_Token obje ct', E_USER_WARNING); trigger_error('Cannot generate HTML from non-HTMLPurifier_Token obje ct', E_USER_WARNING);
return ''; return '';
} elseif ($token instanceof HTMLPurifier_Token_Start) { } elseif ($token instanceof HTMLPurifier_Token_Start) {
$attr = $this->generateAttributes($token->attr, $token->name); $attr = $this->generateAttributes($token->attr, $token->name);
if ($this->_flashCompat) { if ($this->_flashCompat) {
if ($token->name == "object") { if ($token->name == "object") {
$flash = new stdclass(); $flash = new stdClass();
$flash->attr = $token->attr; $flash->attr = $token->attr;
$flash->param = array(); $flash->param = array();
$this->_flashStack[] = $flash; $this->_flashStack[] = $flash;
} }
} }
return '<' . $token->name . ($attr ? ' ' : '') . $attr . '>'; return '<' . $token->name . ($attr ? ' ' : '') . $attr . '>';
} elseif ($token instanceof HTMLPurifier_Token_End) { } elseif ($token instanceof HTMLPurifier_Token_End) {
$_extra = ''; $_extra = '';
if ($this->_flashCompat) { if ($this->_flashCompat) {
skipping to change at line 5184 skipping to change at line 5184
// doesn't do anything for now // doesn't do anything for now
} }
} }
return $_extra . '</' . $token->name . '>'; return $_extra . '</' . $token->name . '>';
} elseif ($token instanceof HTMLPurifier_Token_Empty) { } elseif ($token instanceof HTMLPurifier_Token_Empty) {
if ($this->_flashCompat && $token->name == "param" && !empty($this-> _flashStack)) { if ($this->_flashCompat && $token->name == "param" && !empty($this-> _flashStack)) {
$this->_flashStack[count($this->_flashStack)-1]->param[$token->a ttr['name']] = $token->attr['value']; $this->_flashStack[count($this->_flashStack)-1]->param[$token->a ttr['name']] = $token->attr['value'];
} }
$attr = $this->generateAttributes($token->attr, $token->name); $attr = $this->generateAttributes($token->attr, $token->name);
return '<' . $token->name . ($attr ? ' ' : '') . $attr . return '<' . $token->name . ($attr ? ' ' : '') . $attr .
( $this->_xhtml ? ' /': '' ) // <br /> v. <br> ( $this->_xhtml ? ' /': '' ) // <br /> v. <br>
. '>'; . '>';
} elseif ($token instanceof HTMLPurifier_Token_Text) { } elseif ($token instanceof HTMLPurifier_Token_Text) {
return $this->escape($token->data, ENT_NOQUOTES); return $this->escape($token->data, ENT_NOQUOTES);
} elseif ($token instanceof HTMLPurifier_Token_Comment) { } elseif ($token instanceof HTMLPurifier_Token_Comment) {
return '<!--' . $token->data . '-->'; return '<!--' . $token->data . '-->';
} else { } else {
return ''; return '';
skipping to change at line 5678 skipping to change at line 5678
"'$element' is not allowed/supported $suppor t" "'$element' is not allowed/supported $suppor t"
); );
} else { } else {
trigger_error( trigger_error(
"Attribute '$attribute' in element '$element ' not supported $support", "Attribute '$attribute' in element '$element ' not supported $support",
E_USER_WARNING E_USER_WARNING
); );
} }
break; break;
} }
// otherwise fall through // otherwise fall through
case 1: case 1:
$attribute = htmlspecialchars($bits[0]); $attribute = htmlspecialchars($bits[0]);
trigger_error( trigger_error(
"Global attribute '$attribute' is not ". "Global attribute '$attribute' is not ".
"supported in any elements $support", "supported in any elements $support",
E_USER_WARNING E_USER_WARNING
); );
break; break;
} }
} }
skipping to change at line 6386 skipping to change at line 6386
foreach ($module->info as $name => $def) { foreach ($module->info as $name => $def) {
if (!isset($this->elementLookup[$name])) { if (!isset($this->elementLookup[$name])) {
$this->elementLookup[$name] = array(); $this->elementLookup[$name] = array();
} }
$this->elementLookup[$name][] = $module->name; $this->elementLookup[$name][] = $module->name;
} }
} }
// note the different choice // note the different choice
$this->contentSets = new HTMLPurifier_ContentSets( $this->contentSets = new HTMLPurifier_ContentSets(
// content set assembly deals with all possible modules, // content set assembly deals with all possible modules,
// not just ones deemed to be "safe" // not just ones deemed to be "safe"
$this->modules $this->modules
); );
$this->attrCollections = new HTMLPurifier_AttrCollections( $this->attrCollections = new HTMLPurifier_AttrCollections(
$this->attrTypes, $this->attrTypes,
// there is no way to directly disable a global attribute, // there is no way to directly disable a global attribute,
// but using AllowedAttributes or simply not including // but using AllowedAttributes or simply not including
// the module in your custom doctype should be sufficient // the module in your custom doctype should be sufficient
$this->modules $this->modules
); );
} }
skipping to change at line 7524 skipping to change at line 7524
$inst = $lexer; $inst = $lexer;
} else { } else {
if (is_null($lexer)) { if (is_null($lexer)) {
do { do {
// auto-detection algorithm // auto-detection algorithm
if ($needs_tracking) { if ($needs_tracking) {
$lexer = 'DirectLex'; $lexer = 'DirectLex';
break; break;
} }
if (class_exists('DOMDocument') && if (class_exists('DOMDocument', false) &&
method_exists('DOMDocument', 'loadHTML') && method_exists('DOMDocument', 'loadHTML') &&
!extension_loaded('domxml') !extension_loaded('domxml')
) { ) {
// check for DOM support, because while it's part of the // check for DOM support, because while it's part of the
// core, it can be disabled compile time. Also, the PECL // core, it can be disabled compile time. Also, the PECL
// domxml extension overrides the default DOM, and is ev il // domxml extension overrides the default DOM, and is ev il
// and nasty and we shan't bother to support it // and nasty and we shan't bother to support it
$lexer = 'DOMLex'; $lexer = 'DOMLex';
} else { } else {
$lexer = 'DirectLex'; $lexer = 'DirectLex';
skipping to change at line 7779 skipping to change at line 7779
$html = HTMLPurifier_Encoder::cleanUTF8($html); $html = HTMLPurifier_Encoder::cleanUTF8($html);
// if processing instructions are to removed, remove them now // if processing instructions are to removed, remove them now
if ($config->get('Core.RemoveProcessingInstructions')) { if ($config->get('Core.RemoveProcessingInstructions')) {
$html = preg_replace('#<\?.+?\?>#s', '', $html); $html = preg_replace('#<\?.+?\?>#s', '', $html);
} }
$hidden_elements = $config->get('Core.HiddenElements'); $hidden_elements = $config->get('Core.HiddenElements');
if ($config->get('Core.AggressivelyRemoveScript') && if ($config->get('Core.AggressivelyRemoveScript') &&
!($config->get('HTML.Trusted') || !$config->get('Core.RemoveScriptCo ntents') !($config->get('HTML.Trusted') || !$config->get('Core.RemoveScriptCo ntents')
|| empty($hidden_elements["script"]))) { || empty($hidden_elements["script"]))) {
$html = preg_replace('#<script[^>]*>.*?</script>#i', '', $html); $html = preg_replace('#<script[^>]*>.*?</script>#i', '', $html);
} }
return $html; return $html;
} }
/** /**
* Takes a string of HTML (fragment or document) and returns the content * Takes a string of HTML (fragment or document) and returns the content
* @todo Consider making protected * @todo Consider making protected
*/ */
skipping to change at line 10812 skipping to change at line 10812
$i++; $i++;
break; break;
} }
} }
if (!$i) { if (!$i) {
return false; return false;
} }
if ($caught['position'] !== false) { if ($caught['position'] !== false) {
$caught['position'] = $this->info['background-position']-> $caught['position'] = $this->info['background-position']->
validate($caught['position'], $config, $context); validate($caught['position'], $config, $context);
} }
$ret = array(); $ret = array();
foreach ($caught as $value) { foreach ($caught as $value) {
if ($value === false) { if ($value === false) {
continue; continue;
} }
$ret[] = $value; $ret[] = $value;
} }
skipping to change at line 12965 skipping to change at line 12965
if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $match es)) { if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $match es)) {
if (!ctype_digit($matches[1])) { if (!ctype_digit($matches[1])) {
return $string; return $string;
} }
} }
// PHP 5.3 and later support this functionality natively // PHP 5.3 and later support this functionality natively
if (function_exists('idn_to_ascii')) { if (function_exists('idn_to_ascii')) {
$string = idn_to_ascii($string); $string = idn_to_ascii($string);
// If we have Net_IDNA2 support, we can support IRIs by // If we have Net_IDNA2 support, we can support IRIs by
// punycoding them. (This is the most portable thing to do, // punycoding them. (This is the most portable thing to do,
// since otherwise we have to assume browsers support // since otherwise we have to assume browsers support
} elseif ($config->get('Core.EnableIDNA')) { } elseif ($config->get('Core.EnableIDNA')) {
$idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => fals e, 'strict' => true)); $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => fals e, 'strict' => true));
// we need to encode each period separately // we need to encode each period separately
$parts = explode('.', $string); $parts = explode('.', $string);
try { try {
$new_parts = array(); $new_parts = array();
foreach ($parts as $part) { foreach ($parts as $part) {
$encodable = false; $encodable = false;
for ($i = 0, $c = strlen($part); $i < $c; $i++) { for ($i = 0, $c = strlen($part); $i < $c; $i++) {
if (ord($part[$i]) > 0x7a) { if (ord($part[$i]) > 0x7a) {
skipping to change at line 14230 skipping to change at line 14230
trigger_error("Cannot allow ul/ol without allowing li", E_USER_WARNI NG); trigger_error("Cannot allow ul/ol without allowing li", E_USER_WARNI NG);
return false; return false;
} }
// the new set of children // the new set of children
$result = array(); $result = array();
// a little sanity check to make sure it's not ALL whitespace // a little sanity check to make sure it's not ALL whitespace
$all_whitespace = true; $all_whitespace = true;
$current_li = false; $current_li = null;
foreach ($children as $node) { foreach ($children as $node) {
if (!empty($node->is_whitespace)) { if (!empty($node->is_whitespace)) {
$result[] = $node; $result[] = $node;
continue; continue;
} }
$all_whitespace = false; // phew, we're not talking about whitespace $all_whitespace = false; // phew, we're not talking about whitespace
if ($node->name === 'li') { if ($node->name === 'li') {
// good // good
$current_li = $node; $current_li = $node;
$result[] = $node; $result[] = $node;
} else { } else {
// we want to tuck this into the previous li // we want to tuck this into the previous li
// Invariant: we expect the node to be ol/ul // Invariant: we expect the node to be ol/ul
// ToDo: Make this more robust in the case of not ol/ul // ToDo: Make this more robust in the case of not ol/ul
// by distinguishing between existing li and li created // by distinguishing between existing li and li created
// to handle non-list elements; non-list elements should // to handle non-list elements; non-list elements should
// not be appended to an existing li; only li created // not be appended to an existing li; only li created
// for non-list. This distinction is not currently made. // for non-list. This distinction is not currently made.
if ($current_li === false) { if ($current_li === null) {
$current_li = new HTMLPurifier_Node_Element('li'); $current_li = new HTMLPurifier_Node_Element('li');
$result[] = $current_li; $result[] = $current_li;
} }
$current_li->children[] = $node; $current_li->children[] = $node;
$current_li->empty = false; // XXX fascinating! Check for this e rror elsewhere ToDo $current_li->empty = false; // XXX fascinating! Check for this e rror elsewhere ToDo
} }
} }
if (empty($result)) { if (empty($result)) {
return false; return false;
} }
skipping to change at line 14499 skipping to change at line 14499
$def = $config->getHTMLDefinition(); $def = $config->getHTMLDefinition();
$block_wrap_name = $def->info_block_wrapper; $block_wrap_name = $def->info_block_wrapper;
$block_wrap = false; $block_wrap = false;
$ret = array(); $ret = array();
foreach ($result as $node) { foreach ($result as $node) {
if ($block_wrap === false) { if ($block_wrap === false) {
if (($node instanceof HTMLPurifier_Node_Text && !$node->is_white space) || if (($node instanceof HTMLPurifier_Node_Text && !$node->is_white space) ||
($node instanceof HTMLPurifier_Node_Element && !isset($this- >elements[$node->name]))) { ($node instanceof HTMLPurifier_Node_Element && !isset($this- >elements[$node->name]))) {
$block_wrap = new HTMLPurifier_Node_Element($def->info_b $block_wrap = new HTMLPurifier_Node_Element($def->info_block
lock_wrapper); _wrapper);
$ret[] = $block_wrap; $ret[] = $block_wrap;
} }
} else { } else {
if ($node instanceof HTMLPurifier_Node_Element && isset($this->e lements[$node->name])) { if ($node instanceof HTMLPurifier_Node_Element && isset($this->e lements[$node->name])) {
$block_wrap = false; $block_wrap = false;
} }
} }
if ($block_wrap) { if ($block_wrap) {
$block_wrap->children[] = $node; $block_wrap->children[] = $node;
} else { } else {
skipping to change at line 14619 skipping to change at line 14619
$initial_ws = array(); $initial_ws = array();
$after_caption_ws = array(); $after_caption_ws = array();
$after_thead_ws = array(); $after_thead_ws = array();
$after_tfoot_ws = array(); $after_tfoot_ws = array();
// as many of these as you want // as many of these as you want
$cols = array(); $cols = array();
$content = array(); $content = array();
$tbody_mode = false; // if true, then we need to wrap any stray $tbody_mode = false; // if true, then we need to wrap any stray
// <tr>s with a <tbody>. // <tr>s with a <tbody>.
$ws_accum =& $initial_ws; $ws_accum =& $initial_ws;
foreach ($children as $node) { foreach ($children as $node) {
if ($node instanceof HTMLPurifier_Node_Comment) { if ($node instanceof HTMLPurifier_Node_Comment) {
$ws_accum[] = $node; $ws_accum[] = $node;
continue; continue;
} }
switch ($node->name) { switch ($node->name) {
case 'tbody': case 'tbody':
$tbody_mode = true; $tbody_mode = true;
// fall through // fall through
case 'tr': case 'tr':
$content[] = $node;
$ws_accum =& $content;
break;
case 'caption':
// there can only be one caption!
if ($caption !== false) break;
$caption = $node;
$ws_accum =& $after_caption_ws;
break;
case 'thead':
$tbody_mode = true;
// XXX This breaks rendering properties with
// Firefox, which never floats a <thead> to
// the top. Ever. (Our scheme will float the
// first <thead> to the top.) So maybe
// <thead>s that are not first should be
// turned into <tbody>? Very tricky, indeed.
if ($thead === false) {
$thead = $node;
$ws_accum =& $after_thead_ws;
} else {
// Oops, there's a second one! What
// should we do? Current behavior is to
// transmutate the first and last entries into
// tbody tags, and then put into content.
// Maybe a better idea is to *attach
// it* to the existing thead or tfoot?
// We don't do this, because Firefox
// doesn't float an extra tfoot to the
// bottom like it does for the first one.
$node->name = 'tbody';
$content[] = $node;
$ws_accum =& $content;
}
break;
case 'tfoot':
// see above for some aveats
$tbody_mode = true;
if ($tfoot === false) {
$tfoot = $node;
$ws_accum =& $after_tfoot_ws;
} else {
$node->name = 'tbody';
$content[] = $node; $content[] = $node;
$ws_accum =& $content; $ws_accum =& $content;
} break;
break; case 'caption':
case 'colgroup': // there can only be one caption!
case 'col': if ($caption !== false) break;
$cols[] = $node; $caption = $node;
$ws_accum =& $cols; $ws_accum =& $after_caption_ws;
break; break;
case '#PCDATA': case 'thead':
// How is whitespace handled? We treat is as sticky to $tbody_mode = true;
// the *end* of the previous element. So all of the // XXX This breaks rendering properties with
// nonsense we have worked on is to keep things // Firefox, which never floats a <thead> to
// together. // the top. Ever. (Our scheme will float the
if (!empty($node->is_whitespace)) { // first <thead> to the top.) So maybe
$ws_accum[] = $node; // <thead>s that are not first should be
} // turned into <tbody>? Very tricky, indeed.
break; if ($thead === false) {
$thead = $node;
$ws_accum =& $after_thead_ws;
} else {
// Oops, there's a second one! What
// should we do? Current behavior is to
// transmutate the first and last entries into
// tbody tags, and then put into content.
// Maybe a better idea is to *attach
// it* to the existing thead or tfoot?
// We don't do this, because Firefox
// doesn't float an extra tfoot to the
// bottom like it does for the first one.
$node->name = 'tbody';
$content[] = $node;
$ws_accum =& $content;
}
break;
case 'tfoot':
// see above for some aveats
$tbody_mode = true;
if ($tfoot === false) {
$tfoot = $node;
$ws_accum =& $after_tfoot_ws;
} else {
$node->name = 'tbody';
$content[] = $node;
$ws_accum =& $content;
}
break;
case 'colgroup':
case 'col':
$cols[] = $node;
$ws_accum =& $cols;
break;
case '#PCDATA':
// How is whitespace handled? We treat is as sticky to
// the *end* of the previous element. So all of the
// nonsense we have worked on is to keep things
// together.
if (!empty($node->is_whitespace)) {
$ws_accum[] = $node;
}
break;
} }
} }
if (empty($content)) { if (empty($content)) {
return false; return false;
} }
$ret = $initial_ws; $ret = $initial_ws;
if ($caption !== false) { if ($caption !== false) {
$ret[] = $caption; $ret[] = $caption;
skipping to change at line 14724 skipping to change at line 14724
$ret[] = $tfoot; $ret[] = $tfoot;
$ret = array_merge($ret, $after_tfoot_ws); $ret = array_merge($ret, $after_tfoot_ws);
} }
if ($tbody_mode) { if ($tbody_mode) {
// we have to shuffle tr into tbody // we have to shuffle tr into tbody
$current_tr_tbody = null; $current_tr_tbody = null;
foreach($content as $node) { foreach($content as $node) {
switch ($node->name) { switch ($node->name) {
case 'tbody': case 'tbody':
$current_tr_tbody = null; $current_tr_tbody = null;
$ret[] = $node;
break;
case 'tr':
if ($current_tr_tbody === null) {
$current_tr_tbody = new HTMLPurifier_Node_Element('tbody
');
$ret[] = $current_tr_tbody;
}
$current_tr_tbody->children[] = $node;
break;
case '#PCDATA':
//assert($node->is_whitespace);
if ($current_tr_tbody === null) {
$ret[] = $node; $ret[] = $node;
} else { break;
case 'tr':
if ($current_tr_tbody === null) {
$current_tr_tbody = new HTMLPurifier_Node_Element('t
body');
$ret[] = $current_tr_tbody;
}
$current_tr_tbody->children[] = $node; $current_tr_tbody->children[] = $node;
} break;
break; case '#PCDATA':
//assert($node->is_whitespace);
if ($current_tr_tbody === null) {
$ret[] = $node;
} else {
$current_tr_tbody->children[] = $node;
}
break;
} }
} }
} else { } else {
$ret = array_merge($ret, $content); $ret = array_merge($ret, $content);
} }
return $ret; return $ret;
} }
} }
skipping to change at line 18230 skipping to change at line 18230
$html = $this->wrapHTML($html, $config, $context); $html = $this->wrapHTML($html, $config, $context);
$doc = new DOMDocument(); $doc = new DOMDocument();
$doc->encoding = 'UTF-8'; // theoretically, the above has this covered $doc->encoding = 'UTF-8'; // theoretically, the above has this covered
set_error_handler(array($this, 'muteErrorHandler')); set_error_handler(array($this, 'muteErrorHandler'));
$doc->loadHTML($html); $doc->loadHTML($html);
restore_error_handler(); restore_error_handler();
$body = $doc->getElementsByTagName('html')->item(0)-> // <html> $body = $doc->getElementsByTagName('html')->item(0)-> // <html>
getElementsByTagName('body')->item(0); // <body> getElementsByTagName('body')->item(0); // <body>
$div = $body->getElementsByTagName('div')->item(0); // <div> $div = $body->getElementsByTagName('div')->item(0); // <div>
$tokens = array(); $tokens = array();
$this->tokenizeDOM($div, $tokens, $config); $this->tokenizeDOM($div, $tokens, $config);
// If the div has a sibling, that means we tripped across // If the div has a sibling, that means we tripped across
// a premature </div> tag. So remove the div we parsed, // a premature </div> tag. So remove the div we parsed,
// and then tokenize the rest of body. We can't tokenize // and then tokenize the rest of body. We can't tokenize
// the sibling directly as we'll lose the tags in that case. // the sibling directly as we'll lose the tags in that case.
if ($div->nextSibling) { if ($div->nextSibling) {
$body->removeChild($div); $body->removeChild($div);
skipping to change at line 19267 skipping to change at line 19267
// } // }
// //
// Thus, we will represent a stack frame as array($node, // Thus, we will represent a stack frame as array($node,
// $is_inline, stack of children) // $is_inline, stack of children)
// e.g. array_reverse($node->children) - already processed // e.g. array_reverse($node->children) - already processed
// children. // children.
$parent_def = $definition->info_parent_def; $parent_def = $definition->info_parent_def;
$stack = array( $stack = array(
array($top_node, array($top_node,
$parent_def->descendants_are_inline, $parent_def->descendants_are_inline,
$parent_def->excludes, // exclusions $parent_def->excludes, // exclusions
0) 0)
); );
while (!empty($stack)) { while (!empty($stack)) {
list($node, $is_inline, $excludes, $ix) = array_pop($stack); list($node, $is_inline, $excludes, $ix) = array_pop($stack);
// recursive call // recursive call
$go = false; $go = false;
$def = empty($stack) ? $definition->info_parent_def : $definition->i nfo[$node->name]; $def = empty($stack) ? $definition->info_parent_def : $definition->i nfo[$node->name];
while (isset($node->children[$ix])) { while (isset($node->children[$ix])) {
$child = $node->children[$ix++]; $child = $node->children[$ix++];
if ($child instanceof HTMLPurifier_Node_Element) { if ($child instanceof HTMLPurifier_Node_Element) {
$go = true; $go = true;
$stack[] = array($node, $is_inline, $excludes, $ix); $stack[] = array($node, $is_inline, $excludes, $ix);
$stack[] = array($child, $stack[] = array($child,
// ToDo: I don't think it matters if it's def or // ToDo: I don't think it matters if it's def or
// child_def, but double check this... // child_def, but double check this...
$is_inline || $def->descendants_are_inline, $is_inline || $def->descendants_are_inline,
empty($def->excludes) ? $excludes empty($def->excludes) ? $excludes
: array_merge($excludes, $def->exc ludes), : array_merge($excludes, $def->excludes),
0); 0);
break; break;
} }
}; };
if ($go) continue; if ($go) continue;
list($token, $d) = $node->toTokenPair(); list($token, $d) = $node->toTokenPair();
// base case // base case
if ($excludes_enabled && isset($excludes[$node->name])) { if ($excludes_enabled && isset($excludes[$node->name])) {
$node->dead = true; $node->dead = true;
if ($e) $e->send(E_ERROR, 'Strategy_FixNesting: Node excluded'); if ($e) $e->send(E_ERROR, 'Strategy_FixNesting: Node excluded');
skipping to change at line 19493 skipping to change at line 19493
// a note on reprocessing: // a note on reprocessing:
// In order to reduce code duplication, whenever some code needs // In order to reduce code duplication, whenever some code needs
// to make HTML changes in order to make things "correct", the // to make HTML changes in order to make things "correct", the
// new HTML gets sent through the purifier, regardless of its // new HTML gets sent through the purifier, regardless of its
// status. This means that if we add a start token, because it // status. This means that if we add a start token, because it
// was totally necessary, we don't have to update nesting; we just // was totally necessary, we don't have to update nesting; we just
// punt ($reprocess = true; continue;) and it does that for us. // punt ($reprocess = true; continue;) and it does that for us.
// isset is in loop because $tokens size changes during loop exec // isset is in loop because $tokens size changes during loop exec
for (;; for (;;
// only increment if we don't need to reprocess // only increment if we don't need to reprocess
$reprocess ? $reprocess = false : $token = $zipper->next($token)) { $reprocess ? $reprocess = false : $token = $zipper->next($token)) {
// check for a rewind // check for a rewind
if (is_int($i)) { if (is_int($i)) {
// possibility: disable rewinding if the current token has a // possibility: disable rewinding if the current token has a
// rewind set on it already. This would offer protection from // rewind set on it already. This would offer protection from
// infinite loop, but might hinder some advanced rewinding. // infinite loop, but might hinder some advanced rewinding.
$rewind_offset = $this->injectors[$i]->getRewindOffset(); $rewind_offset = $this->injectors[$i]->getRewindOffset();
if (is_int($rewind_offset)) { if (is_int($rewind_offset)) {
for ($j = 0; $j < $rewind_offset; $j++) { for ($j = 0; $j < $rewind_offset; $j++) {
if (empty($zipper->front)) break; if (empty($zipper->front)) break;
skipping to change at line 20071 skipping to change at line 20071
} }
if (!empty($token->is_tag)) { if (!empty($token->is_tag)) {
// DEFINITION CALL // DEFINITION CALL
// before any processing, try to transform the element // before any processing, try to transform the element
if (isset($definition->info_tag_transform[$token->name])) { if (isset($definition->info_tag_transform[$token->name])) {
$original_name = $token->name; $original_name = $token->name;
// there is a transformation for this tag // there is a transformation for this tag
// DEFINITION CALL // DEFINITION CALL
$token = $definition-> $token = $definition->
info_tag_transform[$token->name]->transform($token, $con fig, $context); info_tag_transform[$token->name]->transform($token, $config, $context);
if ($e) { if ($e) {
$e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Tag transform', $original_name); $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Tag transform', $original_name);
} }
} }
if (isset($definition->info[$token->name])) { if (isset($definition->info[$token->name])) {
// mostly everything's good, but // mostly everything's good, but
// we need to make sure required attributes are in order // we need to make sure required attributes are in order
if (($token instanceof HTMLPurifier_Token_Start || $token in stanceof HTMLPurifier_Token_Empty) && if (($token instanceof HTMLPurifier_Token_Start || $token in stanceof HTMLPurifier_Token_Empty) &&
$definition->info[$token->name]->required_attr && $definition->info[$token->name]->required_attr &&
skipping to change at line 21466 skipping to change at line 21466
*/ */
public function doValidate(&$uri, $config, $context) public function doValidate(&$uri, $config, $context)
{ {
$uri->userinfo = null; $uri->userinfo = null;
$uri->host = null; $uri->host = null;
$uri->port = null; $uri->port = null;
// Delete all non-numeric characters, non-x characters // Delete all non-numeric characters, non-x characters
// from phone number, EXCEPT for a leading plus sign. // from phone number, EXCEPT for a leading plus sign.
$uri->path = preg_replace('/(?!^\+)[^\dx]/', '', $uri->path = preg_replace('/(?!^\+)[^\dx]/', '',
// Normalize e(x)tension to lower-case // Normalize e(x)tension to lower-case
str_replace('X', 'x', $uri->path)); str_replace('X', 'x', $uri->path));
return true; return true;
} }
} }
/** /**
* Performs safe variable parsing based on types which can be used by * Performs safe variable parsing based on types which can be used by
* users. This may not be able to represent all possible data inputs, * users. This may not be able to represent all possible data inputs,
* however. * however.
*/ */
 End of changes. 53 change blocks. 
212 lines changed or deleted 209 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)