diff options
448 files changed, 9258 insertions, 407 deletions
diff --git a/composer.json b/composer.json index c99709c77..09e6d783e 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,8 @@ "sabre/dav" : "~3.2", "michelf/php-markdown" : "^1.7", "pixel418/markdownify": "^2.2", - "bshaffer/oauth2-server-php": "^1.9" + "bshaffer/oauth2-server-php": "^1.9", + "ezyang/htmlpurifier": "^4.9" }, "require-dev" : { "php" : ">=7.0", diff --git a/composer.lock b/composer.lock index 1e515ad5b..62fd0cb8a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "9842014a99ac4e654bc7bfd6061d6f60", + "content-hash": "f1d40dcfbbb2f5364ad55235efaeb5ab", "packages": [ { "name": "bshaffer/oauth2-server-php", @@ -63,6 +63,53 @@ "time": "2017-01-06T23:20:00+00:00" }, { + "name": "ezyang/htmlpurifier", + "version": "v4.9.2", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "6d50e5282afdfdfc3e0ff6d192aff56c5629b3d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/6d50e5282afdfdfc3e0ff6d192aff56c5629b3d4", + "reference": "6d50e5282afdfdfc3e0ff6d192aff56c5629b3d4", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "require-dev": { + "simpletest/simpletest": "^1.1" + }, + "type": "library", + "autoload": { + "psr-0": { + "HTMLPurifier": "library/" + }, + "files": [ + "library/HTMLPurifier.composer.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "time": "2017-03-13T06:30:53+00:00" + }, + { "name": "michelf/php-markdown", "version": "1.7.0", "source": { diff --git a/include/text.php b/include/text.php index 224ba17d0..911334a15 100644 --- a/include/text.php +++ b/include/text.php @@ -122,13 +122,23 @@ function z_input_filter($channel_id,$s,$type = 'text/bbcode') { } - +/** + * @brief Use HTMLPurifier to get standards compliant HTML. + * + * Use the <a href="http://htmlpurifier.org/" target="_blank">HTMLPurifier</a> + * library to get filtered and standards compliant HTML. + * + * @see HTMLPurifier + * + * @param string $s raw HTML + * @param boolean $allow_position allow CSS position + * @return string standards compliant filtered HTML + */ function purify_html($s, $allow_position = false) { - require_once('library/HTMLPurifier.auto.php'); - require_once('include/html2bbcode.php'); /** * @FIXME this function has html output, not bbcode - so safely purify these + * require_once('include/html2bbcode.php'); * $s = html2bb_video($s); * $s = oembed_html2bbcode($s); */ @@ -137,6 +147,15 @@ function purify_html($s, $allow_position = false) { $config->set('Cache.DefinitionImpl', null); $config->set('Attr.EnableID', true); + // If enabled, target=blank attributes are added to all links. + //$config->set('HTML.TargetBlank', true); + //$config->set('Attr.AllowedFrameTargets', ['_blank', '_self', '_parent', '_top']); + // restore old behavior of HTMLPurifier < 4.8, only used when targets allowed at all + // do not add rel="noreferrer" to all links with target attributes + //$config->set('HTML.TargetNoreferrer', false); + // do not add noopener rel attributes to links which have a target attribute associated with them + //$config->set('HTML.TargetNoopener', false); + //Allow some custom data- attributes used by built-in libs. //In this way members which do not have allowcode set can still use the built-in js libs in webpages to some extent. @@ -274,7 +293,6 @@ function purify_html($s, $allow_position = false) { new HTMLPurifier_AttrDef_CSS_Length(), new HTMLPurifier_AttrDef_CSS_Percentage() )); - } $purifier = new HTMLPurifier($config); diff --git a/library/HTMLPurifier.composer.php b/library/HTMLPurifier.composer.php deleted file mode 100644 index 6706f4e39..000000000 --- a/library/HTMLPurifier.composer.php +++ /dev/null @@ -1,4 +0,0 @@ -<?php -if (!defined('HTMLPURIFIER_PREFIX')) { - define('HTMLPURIFIER_PREFIX', __DIR__); -} diff --git a/library/HTMLPurifier/AttrDef/CSS/Color.php b/library/HTMLPurifier/AttrDef/CSS/Color.php deleted file mode 100644 index 16d2a6b98..000000000 --- a/library/HTMLPurifier/AttrDef/CSS/Color.php +++ /dev/null @@ -1,105 +0,0 @@ -<?php - -/** - * Validates Color as defined by CSS. - */ -class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef -{ - - /** - * @param string $color - * @param HTMLPurifier_Config $config - * @param HTMLPurifier_Context $context - * @return bool|string - */ - public function validate($color, $config, $context) - { - static $colors = null; - if ($colors === null) { - $colors = $config->get('Core.ColorKeywords'); - } - - $color = trim($color); - if ($color === '') { - return false; - } - - $lower = strtolower($color); - if (isset($colors[$lower])) { - return $colors[$lower]; - } - - if (strpos($color, 'rgb(') !== false) { - // rgb literal handling - $length = strlen($color); - if (strpos($color, ')') !== $length - 1) { - return false; - } - $triad = substr($color, 4, $length - 4 - 1); - $parts = explode(',', $triad); - if (count($parts) !== 3) { - return false; - } - $type = false; // to ensure that they're all the same type - $new_parts = array(); - foreach ($parts as $part) { - $part = trim($part); - if ($part === '') { - return false; - } - $length = strlen($part); - if ($part[$length - 1] === '%') { - // handle percents - if (!$type) { - $type = 'percentage'; - } elseif ($type !== 'percentage') { - return false; - } - $num = (float)substr($part, 0, $length - 1); - if ($num < 0) { - $num = 0; - } - if ($num > 100) { - $num = 100; - } - $new_parts[] = "$num%"; - } else { - // handle integers - if (!$type) { - $type = 'integer'; - } elseif ($type !== 'integer') { - return false; - } - $num = (int)$part; - if ($num < 0) { - $num = 0; - } - if ($num > 255) { - $num = 255; - } - $new_parts[] = (string)$num; - } - } - $new_triad = implode(',', $new_parts); - $color = "rgb($new_triad)"; - } else { - // hexadecimal handling - if ($color[0] === '#') { - $hex = substr($color, 1); - } else { - $hex = $color; - $color = '#' . $color; - } - $length = strlen($hex); - if ($length !== 3 && $length !== 6) { - return false; - } - if (!ctype_xdigit($hex)) { - return false; - } - } - return $color; - } -} - -// vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema.ser b/library/HTMLPurifier/ConfigSchema/schema.ser Binary files differdeleted file mode 100644 index 22ea32185..000000000 --- a/library/HTMLPurifier/ConfigSchema/schema.ser +++ /dev/null diff --git a/library/HTMLPurifier/EntityParser.php b/library/HTMLPurifier/EntityParser.php deleted file mode 100644 index 61529dcd9..000000000 --- a/library/HTMLPurifier/EntityParser.php +++ /dev/null @@ -1,153 +0,0 @@ -<?php - -// if want to implement error collecting here, we'll need to use some sort -// of global data (probably trigger_error) because it's impossible to pass -// $config or $context to the callback functions. - -/** - * Handles referencing and derefencing character entities - */ -class HTMLPurifier_EntityParser -{ - - /** - * Reference to entity lookup table. - * @type HTMLPurifier_EntityLookup - */ - protected $_entity_lookup; - - /** - * Callback regex string for parsing entities. - * @type string - */ - protected $_substituteEntitiesRegex = - '/&(?:[#]x([a-fA-F0-9]+)|[#]0*(\d+)|([A-Za-z_:][A-Za-z0-9.\-_:]*));?/'; - // 1. hex 2. dec 3. string (XML style) - - /** - * Decimal to parsed string conversion table for special entities. - * @type array - */ - protected $_special_dec2str = - array( - 34 => '"', - 38 => '&', - 39 => "'", - 60 => '<', - 62 => '>' - ); - - /** - * Stripped entity names to decimal conversion table for special entities. - * @type array - */ - protected $_special_ent2dec = - array( - 'quot' => 34, - 'amp' => 38, - 'lt' => 60, - 'gt' => 62 - ); - - /** - * Substitutes non-special entities with their parsed equivalents. Since - * running this whenever you have parsed character is t3h 5uck, we run - * it before everything else. - * - * @param string $string String to have non-special entities parsed. - * @return string Parsed string. - */ - public function substituteNonSpecialEntities($string) - { - // it will try to detect missing semicolons, but don't rely on it - return preg_replace_callback( - $this->_substituteEntitiesRegex, - array($this, 'nonSpecialEntityCallback'), - $string - ); - } - - /** - * Callback function for substituteNonSpecialEntities() that does the work. - * - * @param array $matches PCRE matches array, with 0 the entire match, and - * either index 1, 2 or 3 set with a hex value, dec value, - * or string (respectively). - * @return string Replacement string. - */ - - protected function nonSpecialEntityCallback($matches) - { - // replaces all but big five - $entity = $matches[0]; - $is_num = (@$matches[0][1] === '#'); - if ($is_num) { - $is_hex = (@$entity[2] === 'x'); - $code = $is_hex ? hexdec($matches[1]) : (int) $matches[2]; - // abort for special characters - if (isset($this->_special_dec2str[$code])) { - return $entity; - } - return HTMLPurifier_Encoder::unichr($code); - } else { - if (isset($this->_special_ent2dec[$matches[3]])) { - return $entity; - } - if (!$this->_entity_lookup) { - $this->_entity_lookup = HTMLPurifier_EntityLookup::instance(); - } - if (isset($this->_entity_lookup->table[$matches[3]])) { - return $this->_entity_lookup->table[$matches[3]]; - } else { - return $entity; - } - } - } - - /** - * Substitutes only special entities with their parsed equivalents. - * - * @notice We try to avoid calling this function because otherwise, it - * would have to be called a lot (for every parsed section). - * - * @param string $string String to have non-special entities parsed. - * @return string Parsed string. - */ - public function substituteSpecialEntities($string) - { - return preg_replace_callback( - $this->_substituteEntitiesRegex, - array($this, 'specialEntityCallback'), - $string - ); - } - - /** - * Callback function for substituteSpecialEntities() that does the work. - * - * This callback has same syntax as nonSpecialEntityCallback(). - * - * @param array $matches PCRE-style matches array, with 0 the entire match, and - * either index 1, 2 or 3 set with a hex value, dec value, - * or string (respectively). - * @return string Replacement string. - */ - protected function specialEntityCallback($matches) - { - $entity = $matches[0]; - $is_num = (@$matches[0][1] === '#'); - if ($is_num) { - $is_hex = (@$entity[2] === 'x'); - $int = $is_hex ? hexdec($matches[1]) : (int) $matches[2]; - return isset($this->_special_dec2str[$int]) ? - $this->_special_dec2str[$int] : - $entity; - } else { - return isset($this->_special_ent2dec[$matches[3]]) ? - $this->_special_ent2dec[$matches[3]] : - $entity; - } - } -} - -// vim: et sw=4 sts=4 diff --git a/tests/unit/includes/TextTest.php b/tests/unit/includes/TextTest.php index 85ed6a4fd..e2c7cbb9a 100644 --- a/tests/unit/includes/TextTest.php +++ b/tests/unit/includes/TextTest.php @@ -36,6 +36,10 @@ empty line above'; $this->assertEquals($html5elements, purify_html($html5elements)); $this->assertEquals('<button>button label</button>', purify_html('<button>button label</button>')); + // unsupported HTML5 elements + $this->assertEquals('Your HTML parser does not support HTML5 video.', purify_html('<video controls><source src="movie.ogg" type="video/ogg">Your HTML parser does not support HTML5 video.</video>')); + $this->assertEquals('Your HTML parser does not support HTML5 audio.', purify_html('<audio controls><source src="movie.ogg" "type="audio/ogg">Your HTML parser does not support HTML5 audio.</audio>')); + // preserve f6 and bootstrap additional data attributes from our own configuration $this->assertEquals('<div data-title="title">text</div>', purify_html('<div data-title="title">text</div>')); $this->assertEquals('<ul data-accordion-menu=""><li>item1</li></ul>', purify_html('<ul data-accordion-menu><li>item1</li></ul>')); @@ -51,6 +55,8 @@ empty line above'; $this->assertEquals('<a href="#">link with rel="nofollow"</a>', purify_html('<a href="#" rel="nofollow">link with rel="nofollow"</a>')); $this->assertEquals('a b', purify_html('a b')); $this->assertEquals('ä ä € €', purify_html('ä ä € €')); + $this->assertEquals('<img src="picture.png" alt="text" />', purify_html('<img src="picture.png" alt="text">')); + $this->assertEquals('', purify_html('<iframe width="560" height="315" src="https://www.youtube.com/embed/kiNGx5oL7hk" frameborder="0" allowfullscreen></iframe>')); } public function testPurifyHTML_js() { diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 4892db1e3..cd774eb7c 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,6 +6,240 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'HTMLPurifier' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.php', + 'HTMLPurifier_Arborize' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php', + 'HTMLPurifier_AttrCollections' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php', + 'HTMLPurifier_AttrDef' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef.php', + 'HTMLPurifier_AttrDef_CSS' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php', + 'HTMLPurifier_AttrDef_CSS_AlphaValue' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php', + 'HTMLPurifier_AttrDef_CSS_Background' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php', + 'HTMLPurifier_AttrDef_CSS_BackgroundPosition' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php', + 'HTMLPurifier_AttrDef_CSS_Border' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php', + 'HTMLPurifier_AttrDef_CSS_Color' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php', + 'HTMLPurifier_AttrDef_CSS_Composite' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php', + 'HTMLPurifier_AttrDef_CSS_DenyElementDecorator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php', + 'HTMLPurifier_AttrDef_CSS_Filter' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php', + 'HTMLPurifier_AttrDef_CSS_Font' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php', + 'HTMLPurifier_AttrDef_CSS_FontFamily' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php', + 'HTMLPurifier_AttrDef_CSS_Ident' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php', + 'HTMLPurifier_AttrDef_CSS_ImportantDecorator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php', + 'HTMLPurifier_AttrDef_CSS_Length' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php', + 'HTMLPurifier_AttrDef_CSS_ListStyle' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php', + 'HTMLPurifier_AttrDef_CSS_Multiple' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php', + 'HTMLPurifier_AttrDef_CSS_Number' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php', + 'HTMLPurifier_AttrDef_CSS_Percentage' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php', + 'HTMLPurifier_AttrDef_CSS_TextDecoration' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php', + 'HTMLPurifier_AttrDef_CSS_URI' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php', + 'HTMLPurifier_AttrDef_Clone' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php', + 'HTMLPurifier_AttrDef_Enum' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php', + 'HTMLPurifier_AttrDef_HTML_Bool' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php', + 'HTMLPurifier_AttrDef_HTML_Class' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php', + 'HTMLPurifier_AttrDef_HTML_Color' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php', + 'HTMLPurifier_AttrDef_HTML_FrameTarget' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php', + 'HTMLPurifier_AttrDef_HTML_ID' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php', + 'HTMLPurifier_AttrDef_HTML_Length' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php', + 'HTMLPurifier_AttrDef_HTML_LinkTypes' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php', + 'HTMLPurifier_AttrDef_HTML_MultiLength' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php', + 'HTMLPurifier_AttrDef_HTML_Nmtokens' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php', + 'HTMLPurifier_AttrDef_HTML_Pixels' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php', + 'HTMLPurifier_AttrDef_Integer' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php', + 'HTMLPurifier_AttrDef_Lang' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php', + 'HTMLPurifier_AttrDef_Switch' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php', + 'HTMLPurifier_AttrDef_Text' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php', + 'HTMLPurifier_AttrDef_URI' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php', + 'HTMLPurifier_AttrDef_URI_Email' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php', + 'HTMLPurifier_AttrDef_URI_Email_SimpleCheck' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php', + 'HTMLPurifier_AttrDef_URI_Host' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php', + 'HTMLPurifier_AttrDef_URI_IPv4' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php', + 'HTMLPurifier_AttrDef_URI_IPv6' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php', + 'HTMLPurifier_AttrTransform' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform.php', + 'HTMLPurifier_AttrTransform_Background' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php', + 'HTMLPurifier_AttrTransform_BdoDir' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php', + 'HTMLPurifier_AttrTransform_BgColor' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php', + 'HTMLPurifier_AttrTransform_BoolToCSS' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php', + 'HTMLPurifier_AttrTransform_Border' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php', + 'HTMLPurifier_AttrTransform_EnumToCSS' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php', + 'HTMLPurifier_AttrTransform_ImgRequired' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php', + 'HTMLPurifier_AttrTransform_ImgSpace' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php', + 'HTMLPurifier_AttrTransform_Input' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php', + 'HTMLPurifier_AttrTransform_Lang' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php', + 'HTMLPurifier_AttrTransform_Length' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php', + 'HTMLPurifier_AttrTransform_Name' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php', + 'HTMLPurifier_AttrTransform_NameSync' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php', + 'HTMLPurifier_AttrTransform_Nofollow' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php', + 'HTMLPurifier_AttrTransform_SafeEmbed' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php', + 'HTMLPurifier_AttrTransform_SafeObject' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php', + 'HTMLPurifier_AttrTransform_SafeParam' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php', + 'HTMLPurifier_AttrTransform_ScriptRequired' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php', + 'HTMLPurifier_AttrTransform_TargetBlank' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php', + 'HTMLPurifier_AttrTransform_TargetNoopener' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php', + 'HTMLPurifier_AttrTransform_TargetNoreferrer' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php', + 'HTMLPurifier_AttrTransform_Textarea' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php', + 'HTMLPurifier_AttrTypes' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php', + 'HTMLPurifier_AttrValidator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php', + 'HTMLPurifier_Bootstrap' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php', + 'HTMLPurifier_CSSDefinition' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php', + 'HTMLPurifier_ChildDef' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef.php', + 'HTMLPurifier_ChildDef_Chameleon' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php', + 'HTMLPurifier_ChildDef_Custom' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php', + 'HTMLPurifier_ChildDef_Empty' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php', + 'HTMLPurifier_ChildDef_List' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php', + 'HTMLPurifier_ChildDef_Optional' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php', + 'HTMLPurifier_ChildDef_Required' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php', + 'HTMLPurifier_ChildDef_StrictBlockquote' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php', + 'HTMLPurifier_ChildDef_Table' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php', + 'HTMLPurifier_Config' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Config.php', + 'HTMLPurifier_ConfigSchema' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php', + 'HTMLPurifier_ConfigSchema_Builder_ConfigSchema' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php', + 'HTMLPurifier_ConfigSchema_Builder_Xml' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php', + 'HTMLPurifier_ConfigSchema_Exception' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php', + 'HTMLPurifier_ConfigSchema_Interchange' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php', + 'HTMLPurifier_ConfigSchema_InterchangeBuilder' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php', + 'HTMLPurifier_ConfigSchema_Interchange_Directive' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php', + 'HTMLPurifier_ConfigSchema_Interchange_Id' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php', + 'HTMLPurifier_ConfigSchema_Validator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php', + 'HTMLPurifier_ConfigSchema_ValidatorAtom' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php', + 'HTMLPurifier_ContentSets' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php', + 'HTMLPurifier_Context' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Context.php', + 'HTMLPurifier_Definition' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php', + 'HTMLPurifier_DefinitionCache' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache.php', + 'HTMLPurifier_DefinitionCacheFactory' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php', + 'HTMLPurifier_DefinitionCache_Decorator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php', + 'HTMLPurifier_DefinitionCache_Decorator_Cleanup' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php', + 'HTMLPurifier_DefinitionCache_Decorator_Memory' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php', + 'HTMLPurifier_DefinitionCache_Null' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php', + 'HTMLPurifier_DefinitionCache_Serializer' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php', + 'HTMLPurifier_Doctype' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Doctype.php', + 'HTMLPurifier_DoctypeRegistry' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php', + 'HTMLPurifier_ElementDef' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ElementDef.php', + 'HTMLPurifier_Encoder' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php', + 'HTMLPurifier_EntityLookup' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup.php', + 'HTMLPurifier_EntityParser' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php', + 'HTMLPurifier_ErrorCollector' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ErrorCollector.php', + 'HTMLPurifier_ErrorStruct' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/ErrorStruct.php', + 'HTMLPurifier_Exception' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Exception.php', + 'HTMLPurifier_Filter' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php', + 'HTMLPurifier_Filter_ExtractStyleBlocks' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php', + 'HTMLPurifier_Filter_YouTube' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php', + 'HTMLPurifier_Generator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php', + 'HTMLPurifier_HTMLDefinition' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php', + 'HTMLPurifier_HTMLModule' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule.php', + 'HTMLPurifier_HTMLModuleManager' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModuleManager.php', + 'HTMLPurifier_HTMLModule_Bdo' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php', + 'HTMLPurifier_HTMLModule_CommonAttributes' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php', + 'HTMLPurifier_HTMLModule_Edit' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php', + 'HTMLPurifier_HTMLModule_Forms' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php', + 'HTMLPurifier_HTMLModule_Hypertext' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php', + 'HTMLPurifier_HTMLModule_Iframe' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php', + 'HTMLPurifier_HTMLModule_Image' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php', + 'HTMLPurifier_HTMLModule_Legacy' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php', + 'HTMLPurifier_HTMLModule_List' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php', + 'HTMLPurifier_HTMLModule_Name' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php', + 'HTMLPurifier_HTMLModule_Nofollow' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php', + 'HTMLPurifier_HTMLModule_NonXMLCommonAttributes' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php', + 'HTMLPurifier_HTMLModule_Object' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php', + 'HTMLPurifier_HTMLModule_Presentation' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php', + 'HTMLPurifier_HTMLModule_Proprietary' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php', + 'HTMLPurifier_HTMLModule_Ruby' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php', + 'HTMLPurifier_HTMLModule_SafeEmbed' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php', + 'HTMLPurifier_HTMLModule_SafeObject' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php', + 'HTMLPurifier_HTMLModule_SafeScripting' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php', + 'HTMLPurifier_HTMLModule_Scripting' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php', + 'HTMLPurifier_HTMLModule_StyleAttribute' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php', + 'HTMLPurifier_HTMLModule_Tables' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php', + 'HTMLPurifier_HTMLModule_Target' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php', + 'HTMLPurifier_HTMLModule_TargetBlank' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php', + 'HTMLPurifier_HTMLModule_TargetNoopener' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php', + 'HTMLPurifier_HTMLModule_TargetNoreferrer' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php', + 'HTMLPurifier_HTMLModule_Text' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php', + 'HTMLPurifier_HTMLModule_Tidy' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php', + 'HTMLPurifier_HTMLModule_Tidy_Name' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php', + 'HTMLPurifier_HTMLModule_Tidy_Proprietary' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php', + 'HTMLPurifier_HTMLModule_Tidy_Strict' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php', + 'HTMLPurifier_HTMLModule_Tidy_Transitional' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php', + 'HTMLPurifier_HTMLModule_Tidy_XHTML' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php', + 'HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php', + 'HTMLPurifier_HTMLModule_XMLCommonAttributes' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php', + 'HTMLPurifier_IDAccumulator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/IDAccumulator.php', + 'HTMLPurifier_Injector' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php', + 'HTMLPurifier_Injector_AutoParagraph' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php', + 'HTMLPurifier_Injector_DisplayLinkURI' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php', + 'HTMLPurifier_Injector_Linkify' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php', + 'HTMLPurifier_Injector_PurifierLinkify' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php', + 'HTMLPurifier_Injector_RemoveEmpty' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php', + 'HTMLPurifier_Injector_RemoveSpansWithoutAttributes' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php', + 'HTMLPurifier_Injector_SafeObject' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php', + 'HTMLPurifier_Language' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Language.php', + 'HTMLPurifier_LanguageFactory' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php', + 'HTMLPurifier_Language_en_x_test' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Language/classes/en-x-test.php', + 'HTMLPurifier_Length' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Length.php', + 'HTMLPurifier_Lexer' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php', + 'HTMLPurifier_Lexer_DOMLex' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php', + 'HTMLPurifier_Lexer_DirectLex' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DirectLex.php', + 'HTMLPurifier_Lexer_PH5P' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php', + 'HTMLPurifier_Node' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Node.php', + 'HTMLPurifier_Node_Comment' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php', + 'HTMLPurifier_Node_Element' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php', + 'HTMLPurifier_Node_Text' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php', + 'HTMLPurifier_PercentEncoder' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/PercentEncoder.php', + 'HTMLPurifier_Printer' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer.php', + 'HTMLPurifier_Printer_CSSDefinition' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php', + 'HTMLPurifier_Printer_ConfigForm' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_ConfigForm_NullDecorator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_ConfigForm_bool' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_ConfigForm_default' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_HTMLDefinition' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php', + 'HTMLPurifier_PropertyList' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/PropertyList.php', + 'HTMLPurifier_PropertyListIterator' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php', + 'HTMLPurifier_Queue' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php', + 'HTMLPurifier_Strategy' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy.php', + 'HTMLPurifier_Strategy_Composite' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Composite.php', + 'HTMLPurifier_Strategy_Core' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Core.php', + 'HTMLPurifier_Strategy_FixNesting' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php', + 'HTMLPurifier_Strategy_MakeWellFormed' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/MakeWellFormed.php', + 'HTMLPurifier_Strategy_RemoveForeignElements' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/RemoveForeignElements.php', + 'HTMLPurifier_Strategy_ValidateAttributes' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/ValidateAttributes.php', + 'HTMLPurifier_StringHash' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/StringHash.php', + 'HTMLPurifier_StringHashParser' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/StringHashParser.php', + 'HTMLPurifier_TagTransform' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform.php', + 'HTMLPurifier_TagTransform_Font' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Font.php', + 'HTMLPurifier_TagTransform_Simple' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Simple.php', + 'HTMLPurifier_Token' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Token.php', + 'HTMLPurifier_TokenFactory' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php', + 'HTMLPurifier_Token_Comment' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php', + 'HTMLPurifier_Token_Empty' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Empty.php', + 'HTMLPurifier_Token_End' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/End.php', + 'HTMLPurifier_Token_Start' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Start.php', + 'HTMLPurifier_Token_Tag' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Tag.php', + 'HTMLPurifier_Token_Text' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Text.php', + 'HTMLPurifier_URI' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URI.php', + 'HTMLPurifier_URIDefinition' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIDefinition.php', + 'HTMLPurifier_URIFilter' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php', + 'HTMLPurifier_URIFilter_DisableExternal' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php', + 'HTMLPurifier_URIFilter_DisableExternalResources' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php', + 'HTMLPurifier_URIFilter_DisableResources' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php', + 'HTMLPurifier_URIFilter_HostBlacklist' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php', + 'HTMLPurifier_URIFilter_MakeAbsolute' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/MakeAbsolute.php', + 'HTMLPurifier_URIFilter_Munge' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php', + 'HTMLPurifier_URIFilter_SafeIframe' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php', + 'HTMLPurifier_URIParser' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIParser.php', + 'HTMLPurifier_URIScheme' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php', + 'HTMLPurifier_URISchemeRegistry' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php', + 'HTMLPurifier_URIScheme_data' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/data.php', + 'HTMLPurifier_URIScheme_file' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php', + 'HTMLPurifier_URIScheme_ftp' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/ftp.php', + 'HTMLPurifier_URIScheme_http' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/http.php', + 'HTMLPurifier_URIScheme_https' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/https.php', + 'HTMLPurifier_URIScheme_mailto' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/mailto.php', + 'HTMLPurifier_URIScheme_news' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php', + 'HTMLPurifier_URIScheme_nntp' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php', + 'HTMLPurifier_URIScheme_tel' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php', + 'HTMLPurifier_UnitConverter' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php', + 'HTMLPurifier_VarParser' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php', + 'HTMLPurifier_VarParserException' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParserException.php', + 'HTMLPurifier_VarParser_Flexible' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php', + 'HTMLPurifier_VarParser_Native' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php', + 'HTMLPurifier_Zipper' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php', 'Hubzilla\\Import\\Import' => $baseDir . '/include/Import/Importer.php', 'Markdownify\\Converter' => $vendorDir . '/pixel418/markdownify/src/Converter.php', 'Markdownify\\ConverterExtra' => $vendorDir . '/pixel418/markdownify/src/ConverterExtra.php', diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index a78cbe6fb..bbe6fd553 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -13,4 +13,5 @@ return array( '3569eecfeed3bcf0bad3c998a494ecb8' => $vendorDir . '/sabre/xml/lib/Deserializer/functions.php', '93aa591bc4ca510c520999e34229ee79' => $vendorDir . '/sabre/xml/lib/Serializer/functions.php', 'ebdb698ed4152ae445614b69b5e4bb6a' => $vendorDir . '/sabre/http/lib/functions.php', + '2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', ); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index d880bb6f5..dfcde5bf4 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -8,4 +8,5 @@ $baseDir = dirname($vendorDir); return array( 'OAuth2' => array($vendorDir . '/bshaffer/oauth2-server-php/src'), 'Michelf' => array($vendorDir . '/michelf/php-markdown'), + 'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'), ); diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 096ee4df6..026276b2f 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -14,6 +14,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d '3569eecfeed3bcf0bad3c998a494ecb8' => __DIR__ . '/..' . '/sabre/xml/lib/Deserializer/functions.php', '93aa591bc4ca510c520999e34229ee79' => __DIR__ . '/..' . '/sabre/xml/lib/Serializer/functions.php', 'ebdb698ed4152ae445614b69b5e4bb6a' => __DIR__ . '/..' . '/sabre/http/lib/functions.php', + '2cffec82183ee1cea088009cef9a6fc3' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php', ); public static $prefixLengthsPsr4 = array ( @@ -125,9 +126,250 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d 0 => __DIR__ . '/..' . '/michelf/php-markdown', ), ), + 'H' => + array ( + 'HTMLPurifier' => + array ( + 0 => __DIR__ . '/..' . '/ezyang/htmlpurifier/library', + ), + ), ); public static $classMap = array ( + 'HTMLPurifier' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier.php', + 'HTMLPurifier_Arborize' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php', + 'HTMLPurifier_AttrCollections' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php', + 'HTMLPurifier_AttrDef' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef.php', + 'HTMLPurifier_AttrDef_CSS' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php', + 'HTMLPurifier_AttrDef_CSS_AlphaValue' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php', + 'HTMLPurifier_AttrDef_CSS_Background' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php', + 'HTMLPurifier_AttrDef_CSS_BackgroundPosition' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php', + 'HTMLPurifier_AttrDef_CSS_Border' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php', + 'HTMLPurifier_AttrDef_CSS_Color' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php', + 'HTMLPurifier_AttrDef_CSS_Composite' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php', + 'HTMLPurifier_AttrDef_CSS_DenyElementDecorator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php', + 'HTMLPurifier_AttrDef_CSS_Filter' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php', + 'HTMLPurifier_AttrDef_CSS_Font' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php', + 'HTMLPurifier_AttrDef_CSS_FontFamily' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php', + 'HTMLPurifier_AttrDef_CSS_Ident' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php', + 'HTMLPurifier_AttrDef_CSS_ImportantDecorator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php', + 'HTMLPurifier_AttrDef_CSS_Length' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php', + 'HTMLPurifier_AttrDef_CSS_ListStyle' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php', + 'HTMLPurifier_AttrDef_CSS_Multiple' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php', + 'HTMLPurifier_AttrDef_CSS_Number' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php', + 'HTMLPurifier_AttrDef_CSS_Percentage' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php', + 'HTMLPurifier_AttrDef_CSS_TextDecoration' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php', + 'HTMLPurifier_AttrDef_CSS_URI' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php', + 'HTMLPurifier_AttrDef_Clone' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php', + 'HTMLPurifier_AttrDef_Enum' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php', + 'HTMLPurifier_AttrDef_HTML_Bool' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php', + 'HTMLPurifier_AttrDef_HTML_Class' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php', + 'HTMLPurifier_AttrDef_HTML_Color' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php', + 'HTMLPurifier_AttrDef_HTML_FrameTarget' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php', + 'HTMLPurifier_AttrDef_HTML_ID' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php', + 'HTMLPurifier_AttrDef_HTML_Length' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php', + 'HTMLPurifier_AttrDef_HTML_LinkTypes' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php', + 'HTMLPurifier_AttrDef_HTML_MultiLength' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php', + 'HTMLPurifier_AttrDef_HTML_Nmtokens' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php', + 'HTMLPurifier_AttrDef_HTML_Pixels' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php', + 'HTMLPurifier_AttrDef_Integer' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php', + 'HTMLPurifier_AttrDef_Lang' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php', + 'HTMLPurifier_AttrDef_Switch' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php', + 'HTMLPurifier_AttrDef_Text' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php', + 'HTMLPurifier_AttrDef_URI' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php', + 'HTMLPurifier_AttrDef_URI_Email' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php', + 'HTMLPurifier_AttrDef_URI_Email_SimpleCheck' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php', + 'HTMLPurifier_AttrDef_URI_Host' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php', + 'HTMLPurifier_AttrDef_URI_IPv4' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php', + 'HTMLPurifier_AttrDef_URI_IPv6' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php', + 'HTMLPurifier_AttrTransform' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform.php', + 'HTMLPurifier_AttrTransform_Background' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php', + 'HTMLPurifier_AttrTransform_BdoDir' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php', + 'HTMLPurifier_AttrTransform_BgColor' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php', + 'HTMLPurifier_AttrTransform_BoolToCSS' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php', + 'HTMLPurifier_AttrTransform_Border' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php', + 'HTMLPurifier_AttrTransform_EnumToCSS' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php', + 'HTMLPurifier_AttrTransform_ImgRequired' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php', + 'HTMLPurifier_AttrTransform_ImgSpace' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php', + 'HTMLPurifier_AttrTransform_Input' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php', + 'HTMLPurifier_AttrTransform_Lang' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php', + 'HTMLPurifier_AttrTransform_Length' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php', + 'HTMLPurifier_AttrTransform_Name' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php', + 'HTMLPurifier_AttrTransform_NameSync' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php', + 'HTMLPurifier_AttrTransform_Nofollow' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php', + 'HTMLPurifier_AttrTransform_SafeEmbed' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php', + 'HTMLPurifier_AttrTransform_SafeObject' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php', + 'HTMLPurifier_AttrTransform_SafeParam' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php', + 'HTMLPurifier_AttrTransform_ScriptRequired' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php', + 'HTMLPurifier_AttrTransform_TargetBlank' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php', + 'HTMLPurifier_AttrTransform_TargetNoopener' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php', + 'HTMLPurifier_AttrTransform_TargetNoreferrer' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php', + 'HTMLPurifier_AttrTransform_Textarea' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php', + 'HTMLPurifier_AttrTypes' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php', + 'HTMLPurifier_AttrValidator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php', + 'HTMLPurifier_Bootstrap' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php', + 'HTMLPurifier_CSSDefinition' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php', + 'HTMLPurifier_ChildDef' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef.php', + 'HTMLPurifier_ChildDef_Chameleon' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php', + 'HTMLPurifier_ChildDef_Custom' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php', + 'HTMLPurifier_ChildDef_Empty' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php', + 'HTMLPurifier_ChildDef_List' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php', + 'HTMLPurifier_ChildDef_Optional' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php', + 'HTMLPurifier_ChildDef_Required' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php', + 'HTMLPurifier_ChildDef_StrictBlockquote' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php', + 'HTMLPurifier_ChildDef_Table' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php', + 'HTMLPurifier_Config' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Config.php', + 'HTMLPurifier_ConfigSchema' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php', + 'HTMLPurifier_ConfigSchema_Builder_ConfigSchema' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php', + 'HTMLPurifier_ConfigSchema_Builder_Xml' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php', + 'HTMLPurifier_ConfigSchema_Exception' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php', + 'HTMLPurifier_ConfigSchema_Interchange' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php', + 'HTMLPurifier_ConfigSchema_InterchangeBuilder' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php', + 'HTMLPurifier_ConfigSchema_Interchange_Directive' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php', + 'HTMLPurifier_ConfigSchema_Interchange_Id' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php', + 'HTMLPurifier_ConfigSchema_Validator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php', + 'HTMLPurifier_ConfigSchema_ValidatorAtom' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php', + 'HTMLPurifier_ContentSets' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php', + 'HTMLPurifier_Context' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Context.php', + 'HTMLPurifier_Definition' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php', + 'HTMLPurifier_DefinitionCache' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache.php', + 'HTMLPurifier_DefinitionCacheFactory' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php', + 'HTMLPurifier_DefinitionCache_Decorator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php', + 'HTMLPurifier_DefinitionCache_Decorator_Cleanup' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php', + 'HTMLPurifier_DefinitionCache_Decorator_Memory' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php', + 'HTMLPurifier_DefinitionCache_Null' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php', + 'HTMLPurifier_DefinitionCache_Serializer' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php', + 'HTMLPurifier_Doctype' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Doctype.php', + 'HTMLPurifier_DoctypeRegistry' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php', + 'HTMLPurifier_ElementDef' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ElementDef.php', + 'HTMLPurifier_Encoder' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php', + 'HTMLPurifier_EntityLookup' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup.php', + 'HTMLPurifier_EntityParser' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php', + 'HTMLPurifier_ErrorCollector' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ErrorCollector.php', + 'HTMLPurifier_ErrorStruct' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/ErrorStruct.php', + 'HTMLPurifier_Exception' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Exception.php', + 'HTMLPurifier_Filter' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php', + 'HTMLPurifier_Filter_ExtractStyleBlocks' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php', + 'HTMLPurifier_Filter_YouTube' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php', + 'HTMLPurifier_Generator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php', + 'HTMLPurifier_HTMLDefinition' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php', + 'HTMLPurifier_HTMLModule' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule.php', + 'HTMLPurifier_HTMLModuleManager' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModuleManager.php', + 'HTMLPurifier_HTMLModule_Bdo' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php', + 'HTMLPurifier_HTMLModule_CommonAttributes' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php', + 'HTMLPurifier_HTMLModule_Edit' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php', + 'HTMLPurifier_HTMLModule_Forms' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php', + 'HTMLPurifier_HTMLModule_Hypertext' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php', + 'HTMLPurifier_HTMLModule_Iframe' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php', + 'HTMLPurifier_HTMLModule_Image' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php', + 'HTMLPurifier_HTMLModule_Legacy' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php', + 'HTMLPurifier_HTMLModule_List' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php', + 'HTMLPurifier_HTMLModule_Name' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php', + 'HTMLPurifier_HTMLModule_Nofollow' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php', + 'HTMLPurifier_HTMLModule_NonXMLCommonAttributes' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php', + 'HTMLPurifier_HTMLModule_Object' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php', + 'HTMLPurifier_HTMLModule_Presentation' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php', + 'HTMLPurifier_HTMLModule_Proprietary' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php', + 'HTMLPurifier_HTMLModule_Ruby' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php', + 'HTMLPurifier_HTMLModule_SafeEmbed' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php', + 'HTMLPurifier_HTMLModule_SafeObject' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php', + 'HTMLPurifier_HTMLModule_SafeScripting' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php', + 'HTMLPurifier_HTMLModule_Scripting' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php', + 'HTMLPurifier_HTMLModule_StyleAttribute' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php', + 'HTMLPurifier_HTMLModule_Tables' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php', + 'HTMLPurifier_HTMLModule_Target' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php', + 'HTMLPurifier_HTMLModule_TargetBlank' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php', + 'HTMLPurifier_HTMLModule_TargetNoopener' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php', + 'HTMLPurifier_HTMLModule_TargetNoreferrer' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php', + 'HTMLPurifier_HTMLModule_Text' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php', + 'HTMLPurifier_HTMLModule_Tidy' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php', + 'HTMLPurifier_HTMLModule_Tidy_Name' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php', + 'HTMLPurifier_HTMLModule_Tidy_Proprietary' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php', + 'HTMLPurifier_HTMLModule_Tidy_Strict' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php', + 'HTMLPurifier_HTMLModule_Tidy_Transitional' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php', + 'HTMLPurifier_HTMLModule_Tidy_XHTML' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php', + 'HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php', + 'HTMLPurifier_HTMLModule_XMLCommonAttributes' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php', + 'HTMLPurifier_IDAccumulator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/IDAccumulator.php', + 'HTMLPurifier_Injector' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php', + 'HTMLPurifier_Injector_AutoParagraph' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php', + 'HTMLPurifier_Injector_DisplayLinkURI' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php', + 'HTMLPurifier_Injector_Linkify' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php', + 'HTMLPurifier_Injector_PurifierLinkify' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php', + 'HTMLPurifier_Injector_RemoveEmpty' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php', + 'HTMLPurifier_Injector_RemoveSpansWithoutAttributes' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php', + 'HTMLPurifier_Injector_SafeObject' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php', + 'HTMLPurifier_Language' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Language.php', + 'HTMLPurifier_LanguageFactory' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php', + 'HTMLPurifier_Language_en_x_test' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Language/classes/en-x-test.php', + 'HTMLPurifier_Length' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Length.php', + 'HTMLPurifier_Lexer' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php', + 'HTMLPurifier_Lexer_DOMLex' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php', + 'HTMLPurifier_Lexer_DirectLex' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DirectLex.php', + 'HTMLPurifier_Lexer_PH5P' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php', + 'HTMLPurifier_Node' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Node.php', + 'HTMLPurifier_Node_Comment' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php', + 'HTMLPurifier_Node_Element' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php', + 'HTMLPurifier_Node_Text' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php', + 'HTMLPurifier_PercentEncoder' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/PercentEncoder.php', + 'HTMLPurifier_Printer' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer.php', + 'HTMLPurifier_Printer_CSSDefinition' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php', + 'HTMLPurifier_Printer_ConfigForm' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_ConfigForm_NullDecorator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_ConfigForm_bool' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_ConfigForm_default' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php', + 'HTMLPurifier_Printer_HTMLDefinition' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php', + 'HTMLPurifier_PropertyList' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/PropertyList.php', + 'HTMLPurifier_PropertyListIterator' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php', + 'HTMLPurifier_Queue' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php', + 'HTMLPurifier_Strategy' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy.php', + 'HTMLPurifier_Strategy_Composite' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Composite.php', + 'HTMLPurifier_Strategy_Core' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Core.php', + 'HTMLPurifier_Strategy_FixNesting' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php', + 'HTMLPurifier_Strategy_MakeWellFormed' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/MakeWellFormed.php', + 'HTMLPurifier_Strategy_RemoveForeignElements' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/RemoveForeignElements.php', + 'HTMLPurifier_Strategy_ValidateAttributes' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/ValidateAttributes.php', + 'HTMLPurifier_StringHash' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/StringHash.php', + 'HTMLPurifier_StringHashParser' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/StringHashParser.php', + 'HTMLPurifier_TagTransform' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform.php', + 'HTMLPurifier_TagTransform_Font' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Font.php', + 'HTMLPurifier_TagTransform_Simple' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Simple.php', + 'HTMLPurifier_Token' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Token.php', + 'HTMLPurifier_TokenFactory' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php', + 'HTMLPurifier_Token_Comment' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php', + 'HTMLPurifier_Token_Empty' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Empty.php', + 'HTMLPurifier_Token_End' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/End.php', + 'HTMLPurifier_Token_Start' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Start.php', + 'HTMLPurifier_Token_Tag' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Tag.php', + 'HTMLPurifier_Token_Text' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Token/Text.php', + 'HTMLPurifier_URI' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URI.php', + 'HTMLPurifier_URIDefinition' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIDefinition.php', + 'HTMLPurifier_URIFilter' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php', + 'HTMLPurifier_URIFilter_DisableExternal' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php', + 'HTMLPurifier_URIFilter_DisableExternalResources' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php', + 'HTMLPurifier_URIFilter_DisableResources' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php', + 'HTMLPurifier_URIFilter_HostBlacklist' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php', + 'HTMLPurifier_URIFilter_MakeAbsolute' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/MakeAbsolute.php', + 'HTMLPurifier_URIFilter_Munge' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php', + 'HTMLPurifier_URIFilter_SafeIframe' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php', + 'HTMLPurifier_URIParser' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIParser.php', + 'HTMLPurifier_URIScheme' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php', + 'HTMLPurifier_URISchemeRegistry' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php', + 'HTMLPurifier_URIScheme_data' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/data.php', + 'HTMLPurifier_URIScheme_file' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php', + 'HTMLPurifier_URIScheme_ftp' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/ftp.php', + 'HTMLPurifier_URIScheme_http' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/http.php', + 'HTMLPurifier_URIScheme_https' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/https.php', + 'HTMLPurifier_URIScheme_mailto' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/mailto.php', + 'HTMLPurifier_URIScheme_news' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php', + 'HTMLPurifier_URIScheme_nntp' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php', + 'HTMLPurifier_URIScheme_tel' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php', + 'HTMLPurifier_UnitConverter' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php', + 'HTMLPurifier_VarParser' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php', + 'HTMLPurifier_VarParserException' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParserException.php', + 'HTMLPurifier_VarParser_Flexible' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php', + 'HTMLPurifier_VarParser_Native' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php', + 'HTMLPurifier_Zipper' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php', 'Hubzilla\\Import\\Import' => __DIR__ . '/../..' . '/include/Import/Importer.php', 'Markdownify\\Converter' => __DIR__ . '/..' . '/pixel418/markdownify/src/Converter.php', 'Markdownify\\ConverterExtra' => __DIR__ . '/..' . '/pixel418/markdownify/src/ConverterExtra.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 7449633d7..3a70e56c8 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -634,5 +634,54 @@ "oauth", "oauth2" ] + }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.9.2", + "version_normalized": "4.9.2.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "6d50e5282afdfdfc3e0ff6d192aff56c5629b3d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/6d50e5282afdfdfc3e0ff6d192aff56c5629b3d4", + "reference": "6d50e5282afdfdfc3e0ff6d192aff56c5629b3d4", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "require-dev": { + "simpletest/simpletest": "^1.1" + }, + "time": "2017-03-13T06:30:53+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "HTMLPurifier": "library/" + }, + "files": [ + "library/HTMLPurifier.composer.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ] } ] diff --git a/library/htmlpurifier-4.6.0-lite/CREDITS b/vendor/ezyang/htmlpurifier/CREDITS index 7921b45af..7921b45af 100644 --- a/library/htmlpurifier-4.6.0-lite/CREDITS +++ b/vendor/ezyang/htmlpurifier/CREDITS diff --git a/library/htmlpurifier-4.6.0-lite/INSTALL b/vendor/ezyang/htmlpurifier/INSTALL index 677c04aa0..e6dd02afa 100644 --- a/library/htmlpurifier-4.6.0-lite/INSTALL +++ b/vendor/ezyang/htmlpurifier/INSTALL @@ -15,10 +15,8 @@ with these contents. --------------------------------------------------------------------------- 1. Compatibility -HTML Purifier is PHP 5 only, and is actively tested from PHP 5.0.5 and -up. It has no core dependencies with other libraries. PHP -4 support was deprecated on December 31, 2007 with HTML Purifier 3.0.0. -HTML Purifier is not compatible with zend.ze1_compatibility_mode. +HTML Purifier is PHP 5 and PHP 7, and is actively tested from PHP 5.0.5 +and up. It has no core dependencies with other libraries. These optional extensions can enhance the capabilities of HTML Purifier: @@ -29,7 +27,10 @@ These optional extensions can enhance the capabilities of HTML Purifier: These optional libraries can enhance the capabilities of HTML Purifier: * CSSTidy : Clean CSS stylesheets using %Core.ExtractStyleBlocks + Note: You should use the modernized fork of CSSTidy available + at https://github.com/Cerdic/CSSTidy * Net_IDNA2 (PEAR) : IRI support using %Core.EnableIDNA + Note: This is not necessary for PHP 5.3 or later --------------------------------------------------------------------------- 2. Reconnaissance @@ -305,11 +306,9 @@ appropriate permissions using: chmod -R 0755 HTMLPurifier/DefinitionCache/Serializer If the above command doesn't work, you may need to assign write permissions -to all. This may be necessary if your webserver runs as nobody, but is -not recommended since it means any other user can write files in the -directory. Use: +to group: - chmod -R 0777 HTMLPurifier/DefinitionCache/Serializer + chmod -R 0775 HTMLPurifier/DefinitionCache/Serializer You can also chmod files via your FTP client; this option is usually accessible by right clicking the corresponding directory and diff --git a/vendor/ezyang/htmlpurifier/INSTALL.fr.utf8 b/vendor/ezyang/htmlpurifier/INSTALL.fr.utf8 new file mode 100644 index 000000000..95164abba --- /dev/null +++ b/vendor/ezyang/htmlpurifier/INSTALL.fr.utf8 @@ -0,0 +1,60 @@ + +Installation + Comment installer HTML Purifier + +Attention : Ce document est encodé en UTF-8, si les lettres avec des accents +ne s'affichent pas, prenez un meilleur éditeur de texte. + +L'installation de HTML Purifier est très simple, parce qu'il n'a pas besoin +de configuration. Pour les utilisateurs impatients, le code se trouve dans le +pied de page, mais je recommande de lire le document. + +1. Compatibilité + +HTML Purifier fonctionne avec PHP 5. PHP 5.0.5 est la dernière version testée. +Il ne dépend pas d'autres librairies. + +Les extensions optionnelles sont iconv (généralement déjà installée) et tidy +(répendue aussi). Si vous utilisez UTF-8 et que vous ne voulez pas l'indentation, +vous pouvez utiliser HTML Purifier sans ces extensions. + + +2. Inclure la librairie + +Quand vous devez l'utilisez, incluez le : + + require_once('/path/to/library/HTMLPurifier.auto.php'); + +Ne pas l'inclure si ce n'est pas nécessaire, car HTML Purifier est lourd. + +HTML Purifier utilise "autoload". Si vous avez défini la fonction __autoload, +vous devez ajouter cette fonction : + + spl_autoload_register('__autoload') + +Plus d'informations dans le document "INSTALL". + +3. Installation rapide + +Si votre site Web est en UTF-8 et XHTML Transitional, utilisez : + +<?php + require_once('/path/to/htmlpurifier/library/HTMLPurifier.auto.php'); + $purificateur = new HTMLPurifier(); + $html_propre = $purificateur->purify($html_a_purifier); +?> + +Sinon, utilisez : + +<?php + require_once('/path/to/html/purifier/library/HTMLPurifier.auto.load'); + $config = $HTMLPurifier_Config::createDefault(); + $config->set('Core', 'Encoding', 'ISO-8859-1'); //Remplacez par votre + encodage + $config->set('Core', 'XHTML', true); //Remplacer par false si HTML 4.01 + $purificateur = new HTMLPurifier($config); + $html_propre = $purificateur->purify($html_a_purifier); +?> + + + vim: et sw=4 sts=4 diff --git a/library/htmlpurifier-4.6.0-lite/LICENSE b/vendor/ezyang/htmlpurifier/LICENSE index 8c88a20d4..8c88a20d4 100644 --- a/library/htmlpurifier-4.6.0-lite/LICENSE +++ b/vendor/ezyang/htmlpurifier/LICENSE diff --git a/library/htmlpurifier-4.6.0-lite/NEWS b/vendor/ezyang/htmlpurifier/NEWS index 90a054620..82ebedf3e 100644 --- a/library/htmlpurifier-4.6.0-lite/NEWS +++ b/vendor/ezyang/htmlpurifier/NEWS @@ -9,6 +9,96 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier . Internal change ========================== +4.9.2, released 2017-03-12 +- Fixes PHP 5.3 compatibility +- Fix breakage when decoding decimal entities. Thanks @rybakit (#129) + +4.9.1, released 2017-03-08 +! %URI.DefaultScheme can now be set to null, in which case + all relative paths are removed. +! New CSS properties: min-width, max-width, min-height, max-height (#94) +! Transparency (rgba) and hsl/hsla supported where color CSS is present. + Thanks @fxbt for contributing the patch. (#118) +- When idn_to_ascii is defined, we might accept malformed + hostnames. Apply validation to the result in such cases. +- Close directory when done in Serializer DefinitionCache (#100) +- Deleted some asserts to avoid linters from choking (#97) +- Rework Serializer cache behavior to avoid chmod'ing if possible (#32) +- Embedded semicolons in strings in CSS are now handled correctly! +- We accidentally dropped certain Unicode characters if there was + one or more invalid characters. This has been fixed, thanks + to mpyw <ryosuke_i_628@yahoo.co.jp> +- Fix for "Don't truncate upon encountering </div> when using DOMLex" + caused a regression with HTML 4.01 Strict parsing with libxml 2.9.1 + (and maybe later versions, but known OK with libxml 2.9.4). The + fix is to go about handling truncation a bit more cleverly so that + we can wrap with divs (sidestepping the bug) but slurping out the + rest of the text in case it ran off the end. (#78) +- Fix PREG_BACKTRACK_LIMIT_ERROR in HTMLPurifier_Filter_ExtractStyle. + Thanks @breathbath for contributing the report and fix (#120) +- Fix entity decoding algorithm to be more conservative about + decoding entities that are missing trailing semicolon. + To get old behavior, set %Core.LegacyEntityDecoder to true. + (#119) +- Workaround libxml bug when HTML tags are embedded inside + script tags. To disable workaround set %Core.AggressivelyRemoveScript + to false. (#83) +# By default, when a link has a target attribute associated + with it, we now also add rel="noopener" in order to + prevent the new window from being able to overwrite + the original frame. To disable this protection, + set %HTML.TargetNoopener to FALSE. + +4.9.0 was cut on Git but never properly released; when we did the +real release we decided to skip this version number. + +4.8.0, released 2016-07-16 +# By default, when a link has a target attribute associated + with it, we now also add rel="noreferrer" in order to + prevent the new window from being able to overwrite + the original frame. To disable this protection, + set %HTML.TargetNoreferrer to FALSE. +! Full PHP 7 compatibility, the test suite is ALL GO. +! %CSS.AllowDuplicates permits duplicate CSS properties. +! Support for 'tel' URIs. +! Partial support for 'border-radius' properties when %CSS.AllowProprietary is true. + The slash syntax, i.e., 'border-radius: 2em 1em 4em / 0.5em 3em' is not + yet supported. +! %Attr.ID.HTML5 turns on HTML5-style ID handling. +- alt truncation could result in malformed UTF-8 sequence. Don't + truncate. Thanks Brandon Farber for reporting. +- Linkify regex is smarter, based off of Gruber's regex. +- IDNA supported natively on PHP 5.3 and later. +- Non all-numeric top-level names (e.g., foo.1f, 1f) are now + allowed. +- Minor bounds error fix to squash a PHP 7 notice. +- Support non-/tmp temporary directories for data:// validation +- Give a better error message when a user attempts to allow + ul/ol without allowing li. +- On some versions of PHP, the Serializer DefinitionCache could + infinite loop when the directory exists but is not listable. (#49) +- Don't match for <body> inside comments with + %Core.ConvertDocumentToFragment. (#67) +- SafeObject is now less case sensitive. (#57) +- AutoFormat.RemoveEmpty.Predicate now correctly renders in + web form. (#85) + +4.7.0, released 2015-08-04 +# opacity is now considered a "tricky" CSS property rather than a + proprietary one. +! %AutoFormat.RemoveEmpty.Predicate for specifying exactly when + an element should be considered "empty" (maybe preserve if it + has attributes), and modify iframe support so that the iframe + is removed if it is missing a src attribute. Thanks meeva for + reporting. +- Don't truncate upon encountering </div> when using DOMLex. Thanks + Myrto Christina for finally convincing me to fix this. +- Update YouTube filter for new code. +- Fix parsing of rgb() values with spaces in them for 'border' + attribute. +- Don't remove foo="" attributes if foo is a boolean attribute. Thanks + valME for reporting. + 4.6.0, released 2013-11-30 # Secure URI munge hashing algorithm has changed to hash_hmac("sha256", $url, $secret). Please update any verification scripts you may have. diff --git a/vendor/ezyang/htmlpurifier/README.md b/vendor/ezyang/htmlpurifier/README.md new file mode 100644 index 000000000..b321f2b69 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/README.md @@ -0,0 +1,29 @@ +HTML Purifier [![Build Status](https://secure.travis-ci.org/ezyang/htmlpurifier.svg?branch=master)](http://travis-ci.org/ezyang/htmlpurifier) +============= + +HTML Purifier is an HTML filtering solution that uses a unique combination +of robust whitelists and agressive parsing to ensure that not only are +XSS attacks thwarted, but the resulting HTML is standards compliant. + +HTML Purifier is oriented towards richly formatted documents from +untrusted sources that require CSS and a full tag-set. This library can +be configured to accept a more restrictive set of tags, but it won't be +as efficient as more bare-bones parsers. It will, however, do the job +right, which may be more important. + +Places to go: + +* See INSTALL for a quick installation guide +* See docs/ for developer-oriented documentation, code examples and + an in-depth installation guide. +* See WYSIWYG for information on editors like TinyMCE and FCKeditor + +HTML Purifier can be found on the web at: [http://htmlpurifier.org/](http://htmlpurifier.org/) + +## Installation + +Package available on [Composer](https://packagist.org/packages/ezyang/htmlpurifier). + +If you're using Composer to manage dependencies, you can use + + $ composer require "ezyang/htmlpurifier": "dev-master" diff --git a/vendor/ezyang/htmlpurifier/TODO b/vendor/ezyang/htmlpurifier/TODO new file mode 100644 index 000000000..1afb33cbf --- /dev/null +++ b/vendor/ezyang/htmlpurifier/TODO @@ -0,0 +1,150 @@ + +TODO List + += KEY ==================== + # Flagship + - Regular + ? Maybe I'll Do It +========================== + +If no interest is expressed for a feature that may require a considerable +amount of effort to implement, it may get endlessly delayed. Do not be +afraid to cast your vote for the next feature to be implemented! + +Things to do as soon as possible: + + - http://htmlpurifier.org/phorum/read.php?3,5560,6307#msg-6307 + - Think about allowing explicit order of operations hooks for transforms + - Fix "<.<" bug (trailing < is removed if not EOD) + - Build in better internal state dumps and debugging tools for remote + debugging + - Allowed/Allowed* have strange interactions when both set + ? Transform lone embeds into object tags + - Deprecated config options that emit warnings when you set them (with' + a way of muting the warning if you really want to) + - Make HTML.Trusted work with Output.FlashCompat + - HTML.Trusted and HTML.SafeObject have funny interaction; general + problem is what to do when a module "supersedes" another + (see also tables and basic tables.) This is a little dicier + because HTML.SafeObject has some extra functionality that + trusted might find useful. See http://htmlpurifier.org/phorum/read.php?3,5762,6100 + +FUTURE VERSIONS +--------------- + +4.9 release [OMG CONFIG PONIES] + ! Fix Printer. It's from the old days when we didn't have decent XML classes + ! Factor demo.php into a set of Printer classes, and then create a stub + file for users here (inside the actual HTML Purifier library) + - Fix error handling with form construction + - Do encoding validation in Printers, or at least, where user data comes in + - Config: Add examples to everything (make built-in which also automatically + gives output) + - Add "register" field to config schemas to eliminate dependence on + naming conventions (try to remember why we ultimately decided on tihs) + +5.0 release [HTML 5] + # Swap out code to use html5lib tokenizer and tree-builder + ! Allow turning off of FixNesting and required attribute insertion + +5.1 release [It's All About Trust] (floating) + # Implement untrusted, dangerous elements/attributes + # Implement IDREF support (harder than it seems, since you cannot have + IDREFs to non-existent IDs) + - Implement <area> (client and server side image maps are blocking + on IDREF support) + # Frameset XHTML 1.0 and HTML 4.01 doctypes + - Figure out how to simultaneously set %CSS.Trusted and %HTML.Trusted (?) + +5.2 release [Error'ed] + # Error logging for filtering/cleanup procedures + # Additional support for poorly written HTML + - Microsoft Word HTML cleaning (i.e. MsoNormal, but research essential!) + - Friendly strict handling of <address> (block -> <br>) + - XSS-attempt detection--certain errors are flagged XSS-like + - Append something to duplicate IDs so they're still usable (impl. note: the + dupe detector would also need to detect the suffix as well) + +6.0 release [Beyond HTML] + # Legit token based CSS parsing (will require revamping almost every + AttrDef class). Probably will use CSSTidy + # More control over allowed CSS properties using a modularization + # IRI support (this includes IDN) + - Standardize token armor for all areas of processing + +7.0 release [To XML and Beyond] + - Extended HTML capabilities based on namespacing and tag transforms (COMPLEX) + - Hooks for adding custom processors to custom namespaced tags and + attributes, offer default implementation + - Lots of documentation and samples + +Ongoing + - More refactoring to take advantage of PHP5's facilities + - Refactor unit tests into lots of test methods + - Plugins for major CMSes (COMPLEX) + - phpBB + - Also, a FAQ for extension writers with HTML Purifier + +AutoFormat + - Smileys + - Syntax highlighting (with GeSHi) with <pre> and possibly <?php + - Look at http://drupal.org/project/Modules/category/63 for ideas + +Neat feature related + ! Support exporting configuration, so users can easily tweak settings + in the demo, and then copy-paste into their own setup + - Advanced URI filtering schemes (see docs/proposal-new-directives.txt) + - Allow scoped="scoped" attribute in <style> tags; may be troublesome + because regular CSS has no way of uniquely identifying nodes, so we'd + have to generate IDs + - Explain how to use HTML Purifier in non-PHP languages / create + a simple command line stub (or complicated?) + - Fixes for Firefox's inability to handle COL alignment props (Bug 915) + - Automatically add non-breaking spaces to empty table cells when + empty-cells:show is applied to have compatibility with Internet Explorer + - Table of Contents generation (XHTML Compiler might be reusable). May also + be out-of-band information. + - Full set of color keywords. Also, a way to add onto them without + finalizing the configuration object. + - Write a var_export and memcached DefinitionCache - Denis + - Built-in support for target="_blank" on all external links + - Convert RTL/LTR override characters to <bdo> tags, or vice versa on demand. + Also, enable disabling of directionality + ? Externalize inline CSS to promote clean HTML, proposed by Sander Tekelenburg + ? Remove redundant tags, ex. <u><u>Underlined</u></u>. Implementation notes: + 1. Analyzing which tags to remove duplicants + 2. Ensure attributes are merged into the parent tag + 3. Extend the tag exclusion system to specify whether or not the + contents should be dropped or not (currently, there's code that could do + something like this if it didn't drop the inner text too.) + ? Make AutoParagraph also support paragraph-izing double <br> tags, and not + just double newlines. This is kind of tough to do in the current framework, + though, and might be reasonably approximated by search replacing double <br>s + with newlines before running it through HTML Purifier. + +Maintenance related (slightly boring) + # CHMOD install script for PEAR installs + ! Factor out command line parser into its own class, and unit test it + - Reduce size of internal data-structures (esp. HTMLDefinition) + - Allow merging configurations. Thus, + a -> b -> default + c -> d -> default + becomes + a -> b -> c -> d -> default + Maybe allow more fine-grained tuning of this behavior. Alternatively, + encourage people to use short plist depths before building them up. + - Time PHPT tests + +ChildDef related (very boring) + - Abstract ChildDef_BlockQuote to work with all elements that only + allow blocks in them, required or optional + - Implement lenient <ruby> child validation + +Wontfix + - Non-lossy smart alternate character encoding transformations (unless + patch provided) + - Pretty-printing HTML: users can use Tidy on the output on entire page + - Native content compression, whitespace stripping: use gzip if this is + really important + + vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/VERSION b/vendor/ezyang/htmlpurifier/VERSION new file mode 100644 index 000000000..b550c72a1 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/VERSION @@ -0,0 +1 @@ +4.9.2
\ No newline at end of file diff --git a/vendor/ezyang/htmlpurifier/WHATSNEW b/vendor/ezyang/htmlpurifier/WHATSNEW new file mode 100644 index 000000000..b435e664b --- /dev/null +++ b/vendor/ezyang/htmlpurifier/WHATSNEW @@ -0,0 +1,12 @@ +HTML Purifier 4.9.x is a maintenance release, collecting a year +of accumulated bug fixes plus a few new features. New features +include support for min/max-width/height CSS, and rgba/hsl/hsla +in color specifications. Major bugfixes include improvements +in the Serializer cache to avoid chmod'ing directories, better +entity decoding (we won't accidentally encode entities that occur +in URLs) and rel="noopener" on links with target attributes, +to prevent them from overwriting the original frame. + +4.9.0 was skipped due to a packaging problem; 4.9.2 fixes two +major regressions in PHP 5.3 support and entity decoding; no +other functional changes were applied. diff --git a/vendor/ezyang/htmlpurifier/WYSIWYG b/vendor/ezyang/htmlpurifier/WYSIWYG new file mode 100644 index 000000000..c518aacdd --- /dev/null +++ b/vendor/ezyang/htmlpurifier/WYSIWYG @@ -0,0 +1,20 @@ + +WYSIWYG - What You See Is What You Get + HTML Purifier: A Pretty Good Fit for TinyMCE and FCKeditor + +Javascript-based WYSIWYG editors, simply stated, are quite amazing. But I've +always been wary about using them due to security issues: they handle the +client-side magic, but once you've been served a piping hot load of unfiltered +HTML, what should be done then? In some situations, you can serve it uncleaned, +since you only offer these facilities to trusted(?) authors. + +Unfortunantely, for blog comments and anonymous input, BBCode, Textile and +other markup languages still reign supreme. Put simply: filtering HTML is +hard work, and these WYSIWYG authors don't offer anything to alleviate that +trouble. Therein lies the solution: + +HTML Purifier is perfect for filtering pure-HTML input from WYSIWYG editors. + +Enough said. + + vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/composer.json b/vendor/ezyang/htmlpurifier/composer.json new file mode 100644 index 000000000..80fee3db3 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/composer.json @@ -0,0 +1,25 @@ +{ + "name": "ezyang/htmlpurifier", + "description": "Standards compliant HTML filter written in PHP", + "type": "library", + "keywords": ["html"], + "homepage": "http://htmlpurifier.org/", + "license": "LGPL", + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "require": { + "php": ">=5.2" + }, + "require-dev": { + "simpletest/simpletest": "^1.1" + }, + "autoload": { + "psr-0": { "HTMLPurifier": "library/" }, + "files": ["library/HTMLPurifier.composer.php"] + } +} diff --git a/vendor/ezyang/htmlpurifier/extras/ConfigDoc/HTMLXSLTProcessor.php b/vendor/ezyang/htmlpurifier/extras/ConfigDoc/HTMLXSLTProcessor.php new file mode 100644 index 000000000..1cfec5d76 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/ConfigDoc/HTMLXSLTProcessor.php @@ -0,0 +1,91 @@ +<?php + +/** + * Decorator/extender XSLT processor specifically for HTML documents. + */ +class ConfigDoc_HTMLXSLTProcessor +{ + + /** + * Instance of XSLTProcessor + */ + protected $xsltProcessor; + + public function __construct($proc = false) + { + if ($proc === false) $proc = new XSLTProcessor(); + $this->xsltProcessor = $proc; + } + + /** + * @note Allows a string $xsl filename to be passed + */ + public function importStylesheet($xsl) + { + if (is_string($xsl)) { + $xsl_file = $xsl; + $xsl = new DOMDocument(); + $xsl->load($xsl_file); + } + return $this->xsltProcessor->importStylesheet($xsl); + } + + /** + * Transforms an XML file into compatible XHTML based on the stylesheet + * @param $xml XML DOM tree, or string filename + * @return string HTML output + * @todo Rename to transformToXHTML, as transformToHTML is misleading + */ + public function transformToHTML($xml) + { + if (is_string($xml)) { + $dom = new DOMDocument(); + $dom->load($xml); + } else { + $dom = $xml; + } + $out = $this->xsltProcessor->transformToXML($dom); + + // fudges for HTML backwards compatibility + // assumes that document is XHTML + $out = str_replace('/>', ' />', $out); // <br /> not <br/> + $out = str_replace(' xmlns=""', '', $out); // rm unnecessary xmlns + + if (class_exists('Tidy')) { + // cleanup output + $config = array( + 'indent' => true, + 'output-xhtml' => true, + 'wrap' => 80 + ); + $tidy = new Tidy; + $tidy->parseString($out, $config, 'utf8'); + $tidy->cleanRepair(); + $out = (string) $tidy; + } + + return $out; + } + + /** + * Bulk sets parameters for the XSL stylesheet + * @param array $options Associative array of options to set + */ + public function setParameters($options) + { + foreach ($options as $name => $value) { + $this->xsltProcessor->setParameter('', $name, $value); + } + } + + /** + * Forward any other calls to the XSLT processor + */ + public function __call($name, $arguments) + { + call_user_func_array(array($this->xsltProcessor, $name), $arguments); + } + +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/extras/FSTools.php b/vendor/ezyang/htmlpurifier/extras/FSTools.php new file mode 100644 index 000000000..ce0076316 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/FSTools.php @@ -0,0 +1,164 @@ +<?php + +/** + * Filesystem tools not provided by default; can recursively create, copy + * and delete folders. Some template methods are provided for extensibility. + * + * @note This class must be instantiated to be used, although it does + * not maintain state. + */ +class FSTools +{ + + private static $singleton; + + /** + * Returns a global instance of FSTools + */ + public static function singleton() + { + if (empty(FSTools::$singleton)) FSTools::$singleton = new FSTools(); + return FSTools::$singleton; + } + + /** + * Sets our global singleton to something else; useful for overloading + * functions. + */ + public static function setSingleton($singleton) + { + FSTools::$singleton = $singleton; + } + + /** + * Recursively creates a directory + * @param string $folder Name of folder to create + * @note Adapted from the PHP manual comment 76612 + */ + public function mkdirr($folder) + { + $folders = preg_split("#[\\\\/]#", $folder); + $base = ''; + for($i = 0, $c = count($folders); $i < $c; $i++) { + if(empty($folders[$i])) { + if (!$i) { + // special case for root level + $base .= DIRECTORY_SEPARATOR; + } + continue; + } + $base .= $folders[$i]; + if(!is_dir($base)){ + $this->mkdir($base); + } + $base .= DIRECTORY_SEPARATOR; + } + } + + /** + * Copy a file, or recursively copy a folder and its contents; modified + * so that copied files, if PHP, have includes removed + * @note Adapted from http://aidanlister.com/repos/v/function.copyr.php + */ + public function copyr($source, $dest) + { + // Simple copy for a file + if (is_file($source)) { + return $this->copy($source, $dest); + } + // Make destination directory + if (!is_dir($dest)) { + $this->mkdir($dest); + } + // Loop through the folder + $dir = $this->dir($source); + while ( false !== ($entry = $dir->read()) ) { + // Skip pointers + if ($entry == '.' || $entry == '..') { + continue; + } + if (!$this->copyable($entry)) { + continue; + } + // Deep copy directories + if ($dest !== "$source/$entry") { + $this->copyr("$source/$entry", "$dest/$entry"); + } + } + // Clean up + $dir->close(); + return true; + } + + /** + * Overloadable function that tests a filename for copyability. By + * default, everything should be copied; you can restrict things to + * ignore hidden files, unreadable files, etc. This function + * applies to copyr(). + */ + public function copyable($file) + { + return true; + } + + /** + * Delete a file, or a folder and its contents + * @note Adapted from http://aidanlister.com/repos/v/function.rmdirr.php + */ + public function rmdirr($dirname) + { + // Sanity check + if (!$this->file_exists($dirname)) { + return false; + } + + // Simple delete for a file + if ($this->is_file($dirname) || $this->is_link($dirname)) { + return $this->unlink($dirname); + } + + // Loop through the folder + $dir = $this->dir($dirname); + while (false !== $entry = $dir->read()) { + // Skip pointers + if ($entry == '.' || $entry == '..') { + continue; + } + // Recurse + $this->rmdirr($dirname . DIRECTORY_SEPARATOR . $entry); + } + + // Clean up + $dir->close(); + return $this->rmdir($dirname); + } + + /** + * Recursively globs a directory. + */ + public function globr($dir, $pattern, $flags = NULL) + { + $files = $this->glob("$dir/$pattern", $flags); + if ($files === false) $files = array(); + $sub_dirs = $this->glob("$dir/*", GLOB_ONLYDIR); + if ($sub_dirs === false) $sub_dirs = array(); + foreach ($sub_dirs as $sub_dir) { + $sub_files = $this->globr($sub_dir, $pattern, $flags); + $files = array_merge($files, $sub_files); + } + return $files; + } + + /** + * Allows for PHP functions to be called and be stubbed. + * @warning This function will not work for functions that need + * to pass references; manually define a stub function for those. + */ + public function __call($name, $args) + { + return call_user_func_array($name, $args); + } + +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/extras/FSTools/File.php b/vendor/ezyang/htmlpurifier/extras/FSTools/File.php new file mode 100644 index 000000000..6453a7a45 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/FSTools/File.php @@ -0,0 +1,141 @@ +<?php + +/** + * Represents a file in the filesystem + * + * @warning Be sure to distinguish between get() and write() versus + * read() and put(), the former operates on the entire file, while + * the latter operates on a handle. + */ +class FSTools_File +{ + + /** Filename of file this object represents */ + protected $name; + + /** Handle for the file */ + protected $handle = false; + + /** Instance of FSTools for interfacing with filesystem */ + protected $fs; + + /** + * Filename of file you wish to instantiate. + * @note This file need not exist + */ + public function __construct($name, $fs = false) + { + $this->name = $name; + $this->fs = $fs ? $fs : FSTools::singleton(); + } + + /** Returns the filename of the file. */ + public function getName() {return $this->name;} + + /** Returns directory of the file without trailing slash */ + public function getDirectory() {return $this->fs->dirname($this->name);} + + /** + * Retrieves the contents of a file + * @todo Throw an exception if file doesn't exist + */ + public function get() + { + return $this->fs->file_get_contents($this->name); + } + + /** Writes contents to a file, creates new file if necessary */ + public function write($contents) + { + return $this->fs->file_put_contents($this->name, $contents); + } + + /** Deletes the file */ + public function delete() + { + return $this->fs->unlink($this->name); + } + + /** Returns true if file exists and is a file. */ + public function exists() + { + return $this->fs->is_file($this->name); + } + + /** Returns last file modification time */ + public function getMTime() + { + return $this->fs->filemtime($this->name); + } + + /** + * Chmod a file + * @note We ignore errors because of some weird owner trickery due + * to SVN duality + */ + public function chmod($octal_code) + { + return @$this->fs->chmod($this->name, $octal_code); + } + + /** Opens file's handle */ + public function open($mode) + { + if ($this->handle) $this->close(); + $this->handle = $this->fs->fopen($this->name, $mode); + return true; + } + + /** Closes file's handle */ + public function close() + { + if (!$this->handle) return false; + $status = $this->fs->fclose($this->handle); + $this->handle = false; + return $status; + } + + /** Retrieves a line from an open file, with optional max length $length */ + public function getLine($length = null) + { + if (!$this->handle) $this->open('r'); + if ($length === null) return $this->fs->fgets($this->handle); + else return $this->fs->fgets($this->handle, $length); + } + + /** Retrieves a character from an open file */ + public function getChar() + { + if (!$this->handle) $this->open('r'); + return $this->fs->fgetc($this->handle); + } + + /** Retrieves an $length bytes of data from an open data */ + public function read($length) + { + if (!$this->handle) $this->open('r'); + return $this->fs->fread($this->handle, $length); + } + + /** Writes to an open file */ + public function put($string) + { + if (!$this->handle) $this->open('a'); + return $this->fs->fwrite($this->handle, $string); + } + + /** Returns TRUE if the end of the file has been reached */ + public function eof() + { + if (!$this->handle) return true; + return $this->fs->feof($this->handle); + } + + public function __destruct() + { + if ($this->handle) $this->close(); + } + +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.auto.php b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.auto.php new file mode 100644 index 000000000..4016d8afd --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.auto.php @@ -0,0 +1,11 @@ +<?php + +/** + * This is a stub include that automatically configures the include path. + */ + +set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() ); +require_once 'HTMLPurifierExtras.php'; +require_once 'HTMLPurifierExtras.autoload.php'; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload.php b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload.php new file mode 100644 index 000000000..de4a8aaaf --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload.php @@ -0,0 +1,26 @@ +<?php + +/** + * @file + * Convenience file that registers autoload handler for HTML Purifier. + * + * @warning + * This autoloader does not contain the compatibility code seen in + * HTMLPurifier_Bootstrap; the user is expected to make any necessary + * changes to use this library. + */ + +if (function_exists('spl_autoload_register')) { + spl_autoload_register(array('HTMLPurifierExtras', 'autoload')); + if (function_exists('__autoload')) { + // Be polite and ensure that userland autoload gets retained + spl_autoload_register('__autoload'); + } +} elseif (!function_exists('__autoload')) { + function __autoload($class) + { + return HTMLPurifierExtras::autoload($class); + } +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.php b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.php new file mode 100644 index 000000000..35c2ca7e7 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/HTMLPurifierExtras.php @@ -0,0 +1,31 @@ +<?php + +/** + * Meta-class for HTML Purifier's extra class hierarchies, similar to + * HTMLPurifier_Bootstrap. + */ +class HTMLPurifierExtras +{ + + public static function autoload($class) + { + $path = HTMLPurifierExtras::getPath($class); + if (!$path) return false; + require $path; + return true; + } + + public static function getPath($class) + { + if ( + strncmp('FSTools', $class, 7) !== 0 && + strncmp('ConfigDoc', $class, 9) !== 0 + ) return false; + // Custom implementations can go here + // Standard implementation: + return str_replace('_', '/', $class) . '.php'; + } + +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/extras/README b/vendor/ezyang/htmlpurifier/extras/README new file mode 100644 index 000000000..4bfece79e --- /dev/null +++ b/vendor/ezyang/htmlpurifier/extras/README @@ -0,0 +1,32 @@ + +HTML Purifier Extras + The Method Behind The Madness! + +The extras/ folder in HTML Purifier contains--you guessed it--extra things +for HTML Purifier. Specifically, these are two extra libraries called +FSTools and ConfigSchema. They're extra for a reason: you don't need them +if you're using HTML Purifier for normal usage: filtering HTML. However, +if you're a developer, and would like to test HTML Purifier, or need to +use one of HTML Purifier's maintenance scripts, chances are they'll need +these libraries. Who knows: maybe you'll find them useful too! + +Here are the libraries: + + +FSTools +------- + +Short for File System Tools, this is a poor-man's object-oriented wrapper for +the filesystem. It currently consists of two classes: + +- FSTools: This is a singleton that contains a manner of useful functions + such as recursive glob, directory removal, etc, as well as the ability + to call arbitrary native PHP functions through it like $FS->fopen(...). + This makes it a lot simpler to mock these filesystem calls for unit testing. + +- FSTools_File: This object represents a single file, and has almost any + method imaginable one would need. + +Check the files themselves for more information. + + vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier.auto.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.auto.php index 1960c399f..1960c399f 100644 --- a/library/HTMLPurifier.auto.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.auto.php diff --git a/library/HTMLPurifier.autoload.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.autoload.php index c3ea67e81..c3ea67e81 100644 --- a/library/HTMLPurifier.autoload.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.autoload.php diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier.composer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.composer.php new file mode 100644 index 000000000..52acc56b0 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.composer.php @@ -0,0 +1,4 @@ +<?php +if (!defined('HTMLPURIFIER_PREFIX')) { + define('HTMLPURIFIER_PREFIX', dirname(__FILE__)); +} diff --git a/library/HTMLPurifier.func.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.func.php index 64b140bec..64b140bec 100644 --- a/library/HTMLPurifier.func.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.func.php diff --git a/library/HTMLPurifier.includes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php index 9b7b88a87..7779fe34d 100644 --- a/library/HTMLPurifier.includes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.includes.php @@ -7,7 +7,7 @@ * 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.6.0 + * @version 4.9.2 * * @warning * You must *not* include any other HTML Purifier files before this file, @@ -137,6 +137,8 @@ require 'HTMLPurifier/AttrTransform/SafeObject.php'; require 'HTMLPurifier/AttrTransform/SafeParam.php'; require 'HTMLPurifier/AttrTransform/ScriptRequired.php'; require 'HTMLPurifier/AttrTransform/TargetBlank.php'; +require 'HTMLPurifier/AttrTransform/TargetNoopener.php'; +require 'HTMLPurifier/AttrTransform/TargetNoreferrer.php'; require 'HTMLPurifier/AttrTransform/Textarea.php'; require 'HTMLPurifier/ChildDef/Chameleon.php'; require 'HTMLPurifier/ChildDef/Custom.php'; @@ -175,6 +177,8 @@ require 'HTMLPurifier/HTMLModule/StyleAttribute.php'; require 'HTMLPurifier/HTMLModule/Tables.php'; require 'HTMLPurifier/HTMLModule/Target.php'; require 'HTMLPurifier/HTMLModule/TargetBlank.php'; +require 'HTMLPurifier/HTMLModule/TargetNoopener.php'; +require 'HTMLPurifier/HTMLModule/TargetNoreferrer.php'; require 'HTMLPurifier/HTMLModule/Text.php'; require 'HTMLPurifier/HTMLModule/Tidy.php'; require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; @@ -225,5 +229,6 @@ require 'HTMLPurifier/URIScheme/https.php'; require 'HTMLPurifier/URIScheme/mailto.php'; require 'HTMLPurifier/URIScheme/news.php'; require 'HTMLPurifier/URIScheme/nntp.php'; +require 'HTMLPurifier/URIScheme/tel.php'; require 'HTMLPurifier/VarParser/Flexible.php'; require 'HTMLPurifier/VarParser/Native.php'; diff --git a/library/HTMLPurifier.kses.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.kses.php index 752290077..752290077 100644 --- a/library/HTMLPurifier.kses.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.kses.php diff --git a/library/HTMLPurifier.path.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.path.php index 39b1b6531..39b1b6531 100644 --- a/library/HTMLPurifier.path.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.path.php diff --git a/library/HTMLPurifier.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php index 6f654fde5..9c539e225 100644 --- a/library/HTMLPurifier.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.php @@ -19,7 +19,7 @@ */ /* - HTML Purifier 4.6.0 - Standards Compliant HTML Filtering + HTML Purifier 4.9.2 - Standards Compliant HTML Filtering Copyright (C) 2006-2008 Edward Z. Yang This library is free software; you can redistribute it and/or @@ -58,12 +58,12 @@ class HTMLPurifier * Version of HTML Purifier. * @type string */ - public $version = '4.6.0'; + public $version = '4.9.2'; /** * Constant with version of HTML Purifier. */ - const VERSION = '4.6.0'; + const VERSION = '4.9.2'; /** * Global configuration object. @@ -104,7 +104,7 @@ class HTMLPurifier /** * Initializes the purifier. * - * @param HTMLPurifier_Config $config Optional HTMLPurifier_Config object + * @param HTMLPurifier_Config|mixed $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). diff --git a/library/HTMLPurifier.safe-includes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php index 9dea6d1ed..a3261f8a3 100644 --- a/library/HTMLPurifier.safe-includes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php @@ -131,6 +131,8 @@ require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.php'; +require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoopener.php'; +require_once $__dir . '/HTMLPurifier/AttrTransform/TargetNoreferrer.php'; require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php'; require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php'; @@ -169,6 +171,8 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.php'; +require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoopener.php'; +require_once $__dir . '/HTMLPurifier/HTMLModule/TargetNoreferrer.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php'; require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php'; @@ -219,5 +223,6 @@ require_once $__dir . '/HTMLPurifier/URIScheme/https.php'; require_once $__dir . '/HTMLPurifier/URIScheme/mailto.php'; require_once $__dir . '/HTMLPurifier/URIScheme/news.php'; require_once $__dir . '/HTMLPurifier/URIScheme/nntp.php'; +require_once $__dir . '/HTMLPurifier/URIScheme/tel.php'; require_once $__dir . '/HTMLPurifier/VarParser/Flexible.php'; require_once $__dir . '/HTMLPurifier/VarParser/Native.php'; diff --git a/library/HTMLPurifier/Arborize.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php index 9e6617be5..d2e9d22a2 100644 --- a/library/HTMLPurifier/Arborize.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php @@ -19,8 +19,8 @@ class HTMLPurifier_Arborize if ($token instanceof HTMLPurifier_Token_End) { $token->start = null; // [MUT] $r = array_pop($stack); - assert($r->name === $token->name); - assert(empty($token->attr)); + //assert($r->name === $token->name); + //assert(empty($token->attr)); $r->endCol = $token->col; $r->endLine = $token->line; $r->endArmor = $token->armor; @@ -32,7 +32,7 @@ class HTMLPurifier_Arborize $stack[] = $node; } } - assert(count($stack) == 1); + //assert(count($stack) == 1); return $stack[0]; } diff --git a/library/HTMLPurifier/AttrCollections.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php index 4f6c2e39a..c7b17cf14 100644 --- a/library/HTMLPurifier/AttrCollections.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php @@ -22,6 +22,11 @@ class HTMLPurifier_AttrCollections */ public function __construct($attr_types, $modules) { + $this->doConstruct($attr_types, $modules); + } + + public function doConstruct($attr_types, $modules) + { // load extensions from the modules foreach ($modules as $module) { foreach ($module->attr_collections as $coll_i => $coll) { diff --git a/library/HTMLPurifier/AttrDef.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef.php index 5ac06522b..739646fa7 100644 --- a/library/HTMLPurifier/AttrDef.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef.php @@ -86,7 +86,13 @@ abstract class HTMLPurifier_AttrDef */ protected function mungeRgb($string) { - return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string); + $p = '\s*(\d+(\.\d+)?([%]?))\s*'; + + if (preg_match('/(rgba|hsla)\(/', $string)) { + return preg_replace('/(rgba|hsla)\('.$p.','.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8,\11)', $string); + } + + return preg_replace('/(rgb|hsl)\('.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8)', $string); } /** diff --git a/library/HTMLPurifier/AttrDef/CSS.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php index 02c1641fb..ad2cb90ad 100644 --- a/library/HTMLPurifier/AttrDef/CSS.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php @@ -25,15 +25,42 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef $css = $this->parseCDATA($css); $definition = $config->getCSSDefinition(); + $allow_duplicates = $config->get("CSS.AllowDuplicates"); - // we're going to break the spec and explode by semicolons. - // This is because semicolon rarely appears in escaped form - // Doing this is generally flaky but fast - // IT MIGHT APPEAR IN URIs, see HTMLPurifier_AttrDef_CSSURI - // for details - $declarations = explode(';', $css); + // According to the CSS2.1 spec, the places where a + // non-delimiting semicolon can appear are in strings + // escape sequences. So here is some dumb hack to + // handle quotes. + $len = strlen($css); + $accum = ""; + $declarations = array(); + $quoted = false; + for ($i = 0; $i < $len; $i++) { + $c = strcspn($css, ";'\"", $i); + $accum .= substr($css, $i, $c); + $i += $c; + if ($i == $len) break; + $d = $css[$i]; + if ($quoted) { + $accum .= $d; + if ($d == $quoted) { + $quoted = false; + } + } else { + if ($d == ";") { + $declarations[] = $accum; + $accum = ""; + } else { + $accum .= $d; + $quoted = $d; + } + } + } + if ($accum != "") $declarations[] = $accum; + $propvalues = array(); + $new_declarations = ''; /** * Name of the current CSS property being validated. @@ -83,7 +110,11 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef if ($result === false) { continue; } - $propvalues[$property] = $result; + if ($allow_duplicates) { + $new_declarations .= "$property:$result;"; + } else { + $propvalues[$property] = $result; + } } $context->destroy('CurrentCSSProperty'); @@ -92,7 +123,6 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef // slightly inefficient, but it's the only way of getting rid of // duplicates. Perhaps config to optimize it, but not now. - $new_declarations = ''; foreach ($propvalues as $prop => $value) { $new_declarations .= "$prop:$value;"; } diff --git a/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php index af2b83dff..af2b83dff 100644 --- a/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Background.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php index 7f1ea3b0f..7f1ea3b0f 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Background.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php diff --git a/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php index 4580ef5a9..4580ef5a9 100644 --- a/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Border.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php index 16243ba1e..16243ba1e 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Border.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php new file mode 100644 index 000000000..d7287a00c --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php @@ -0,0 +1,161 @@ +<?php + +/** + * Validates Color as defined by CSS. + */ +class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef +{ + + /** + * @type HTMLPurifier_AttrDef_CSS_AlphaValue + */ + protected $alpha; + + public function __construct() + { + $this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue(); + } + + /** + * @param string $color + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool|string + */ + public function validate($color, $config, $context) + { + static $colors = null; + if ($colors === null) { + $colors = $config->get('Core.ColorKeywords'); + } + + $color = trim($color); + if ($color === '') { + return false; + } + + $lower = strtolower($color); + if (isset($colors[$lower])) { + return $colors[$lower]; + } + + if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) { + $length = strlen($color); + if (strpos($color, ')') !== $length - 1) { + return false; + } + + // get used function : rgb, rgba, hsl or hsla + $function = $matches[1]; + + $parameters_size = 3; + $alpha_channel = false; + if (substr($function, -1) === 'a') { + $parameters_size = 4; + $alpha_channel = true; + } + + /* + * Allowed types for values : + * parameter_position => [type => max_value] + */ + $allowed_types = array( + 1 => array('percentage' => 100, 'integer' => 255), + 2 => array('percentage' => 100, 'integer' => 255), + 3 => array('percentage' => 100, 'integer' => 255), + ); + $allow_different_types = false; + + if (strpos($function, 'hsl') !== false) { + $allowed_types = array( + 1 => array('integer' => 360), + 2 => array('percentage' => 100), + 3 => array('percentage' => 100), + ); + $allow_different_types = true; + } + + $values = trim(str_replace($function, '', $color), ' ()'); + + $parts = explode(',', $values); + if (count($parts) !== $parameters_size) { + return false; + } + + $type = false; + $new_parts = array(); + $i = 0; + + foreach ($parts as $part) { + $i++; + $part = trim($part); + + if ($part === '') { + return false; + } + + // different check for alpha channel + if ($alpha_channel === true && $i === count($parts)) { + $result = $this->alpha->validate($part, $config, $context); + + if ($result === false) { + return false; + } + + $new_parts[] = (string)$result; + continue; + } + + if (substr($part, -1) === '%') { + $current_type = 'percentage'; + } else { + $current_type = 'integer'; + } + + if (!array_key_exists($current_type, $allowed_types[$i])) { + return false; + } + + if (!$type) { + $type = $current_type; + } + + if ($allow_different_types === false && $type != $current_type) { + return false; + } + + $max_value = $allowed_types[$i][$current_type]; + + if ($current_type == 'integer') { + // Return value between range 0 -> $max_value + $new_parts[] = (int)max(min($part, $max_value), 0); + } elseif ($current_type == 'percentage') { + $new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%'; + } + } + + $new_values = implode(',', $new_parts); + + $color = $function . '(' . $new_values . ')'; + } else { + // hexadecimal handling + if ($color[0] === '#') { + $hex = substr($color, 1); + } else { + $hex = $color; + $color = '#' . $color; + } + $length = strlen($hex); + if ($length !== 3 && $length !== 6) { + return false; + } + if (!ctype_xdigit($hex)) { + return false; + } + } + return $color; + } + +} + +// vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/AttrDef/CSS/Composite.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php index 9c1750554..9c1750554 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Composite.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php diff --git a/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php index 9d77cc9aa..9d77cc9aa 100644 --- a/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Filter.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php index bde4c3301..bde4c3301 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Filter.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Font.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php index 579b97ef1..579b97ef1 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Font.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php diff --git a/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php index 74e24c881..74e24c881 100644 --- a/library/HTMLPurifier/AttrDef/CSS/FontFamily.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Ident.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php index 973002c17..973002c17 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Ident.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php diff --git a/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php index ffc989fe8..ffc989fe8 100644 --- a/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Length.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php index f12453a04..f12453a04 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Length.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php diff --git a/library/HTMLPurifier/AttrDef/CSS/ListStyle.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php index e74d42654..e74d42654 100644 --- a/library/HTMLPurifier/AttrDef/CSS/ListStyle.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Multiple.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php index 9f266cdd1..e707f871c 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Multiple.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php @@ -44,7 +44,7 @@ class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef */ public function validate($string, $config, $context) { - $string = $this->parseCDATA($string); + $string = $this->mungeRgb($this->parseCDATA($string)); if ($string === '') { return false; } diff --git a/library/HTMLPurifier/AttrDef/CSS/Number.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php index 8edc159e7..8edc159e7 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Number.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php diff --git a/library/HTMLPurifier/AttrDef/CSS/Percentage.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php index f0f25c50a..f0f25c50a 100644 --- a/library/HTMLPurifier/AttrDef/CSS/Percentage.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php diff --git a/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php index 5fd4b7f7b..5fd4b7f7b 100644 --- a/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php diff --git a/library/HTMLPurifier/AttrDef/CSS/URI.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php index f9434230e..6617acace 100644 --- a/library/HTMLPurifier/AttrDef/CSS/URI.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php @@ -33,6 +33,9 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI return false; } $uri_string = substr($uri_string, 4); + if (strlen($uri_string) == 0) { + return false; + } $new_length = strlen($uri_string) - 1; if ($uri_string[$new_length] != ')') { return false; diff --git a/library/HTMLPurifier/AttrDef/Clone.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php index 6698a00c0..6698a00c0 100644 --- a/library/HTMLPurifier/AttrDef/Clone.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php diff --git a/library/HTMLPurifier/AttrDef/Enum.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php index 8abda7f6e..8abda7f6e 100644 --- a/library/HTMLPurifier/AttrDef/Enum.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php diff --git a/library/HTMLPurifier/AttrDef/HTML/Bool.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php index 036a240e1..dea15d2cd 100644 --- a/library/HTMLPurifier/AttrDef/HTML/Bool.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php @@ -32,9 +32,6 @@ class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef */ public function validate($string, $config, $context) { - if (empty($string)) { - return false; - } return $this->name; } diff --git a/library/HTMLPurifier/AttrDef/HTML/Class.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php index d5013488f..d5013488f 100644 --- a/library/HTMLPurifier/AttrDef/HTML/Class.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php diff --git a/library/HTMLPurifier/AttrDef/HTML/Color.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php index 946ebb782..946ebb782 100644 --- a/library/HTMLPurifier/AttrDef/HTML/Color.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php diff --git a/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php index d79ba12b3..d79ba12b3 100644 --- a/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php diff --git a/library/HTMLPurifier/AttrDef/HTML/ID.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php index 3d86efb44..4ba45610f 100644 --- a/library/HTMLPurifier/AttrDef/HTML/ID.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php @@ -72,18 +72,26 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef // we purposely avoid using regex, hopefully this is faster - if (ctype_alpha($id)) { - $result = true; - } else { - if (!ctype_alpha(@$id[0])) { + if ($config->get('Attr.ID.HTML5') === true) { + if (preg_match('/[\t\n\x0b\x0c ]/', $id)) { return false; } - // primitive style of regexps, I suppose - $trim = trim( - $id, - 'A..Za..z0..9:-._' - ); - $result = ($trim === ''); + } else { + if (ctype_alpha($id)) { + // OK + } else { + if (!ctype_alpha(@$id[0])) { + return false; + } + // primitive style of regexps, I suppose + $trim = trim( + $id, + 'A..Za..z0..9:-._' + ); + if ($trim !== '') { + return false; + } + } } $regexp = $config->get('Attr.IDBlacklistRegexp'); @@ -91,14 +99,14 @@ class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef return false; } - if (!$this->selector && $result) { + if (!$this->selector) { $id_accumulator->add($id); } // if no change was made to the ID, return the result // else, return the new id if stripping whitespace made it // valid, or return false. - return $result ? $id : false; + return $id; } } diff --git a/library/HTMLPurifier/AttrDef/HTML/Length.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php index 1c4006fbb..1c4006fbb 100644 --- a/library/HTMLPurifier/AttrDef/HTML/Length.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php diff --git a/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php index 63fa04c15..63fa04c15 100644 --- a/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php diff --git a/library/HTMLPurifier/AttrDef/HTML/MultiLength.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php index bbb20f2f8..bbb20f2f8 100644 --- a/library/HTMLPurifier/AttrDef/HTML/MultiLength.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php diff --git a/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php index f79683b4f..f79683b4f 100644 --- a/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php diff --git a/library/HTMLPurifier/AttrDef/HTML/Pixels.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php index a1d019e09..a1d019e09 100644 --- a/library/HTMLPurifier/AttrDef/HTML/Pixels.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php diff --git a/library/HTMLPurifier/AttrDef/Integer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php index 400e707d2..400e707d2 100644 --- a/library/HTMLPurifier/AttrDef/Integer.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php diff --git a/library/HTMLPurifier/AttrDef/Lang.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php index 2a55cea64..2a55cea64 100644 --- a/library/HTMLPurifier/AttrDef/Lang.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php diff --git a/library/HTMLPurifier/AttrDef/Switch.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php index c7eb3199a..c7eb3199a 100644 --- a/library/HTMLPurifier/AttrDef/Switch.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php diff --git a/library/HTMLPurifier/AttrDef/Text.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php index 4553a4ea9..4553a4ea9 100644 --- a/library/HTMLPurifier/AttrDef/Text.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php diff --git a/library/HTMLPurifier/AttrDef/URI.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php index c1cd89772..c1cd89772 100644 --- a/library/HTMLPurifier/AttrDef/URI.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php diff --git a/library/HTMLPurifier/AttrDef/URI/Email.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php index daf32b764..daf32b764 100644 --- a/library/HTMLPurifier/AttrDef/URI/Email.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php diff --git a/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php index 52c0d5968..52c0d5968 100644 --- a/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php diff --git a/library/HTMLPurifier/AttrDef/URI/Host.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php index e7df800b1..3b4d18674 100644 --- a/library/HTMLPurifier/AttrDef/URI/Host.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php @@ -76,24 +76,33 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef // fairly well supported. $underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : ''; + // Based off of RFC 1738, but amended so that + // as per RFC 3696, the top label need only not be all numeric. // The productions describing this are: $a = '[a-z]'; // alpha $an = '[a-z0-9]'; // alphanum $and = "[a-z0-9-$underscore]"; // alphanum | "-" // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum - $domainlabel = "$an($and*$an)?"; - // toplabel = alpha | alpha *( alphanum | "-" ) alphanum - $toplabel = "$a($and*$an)?"; + $domainlabel = "$an(?:$and*$an)?"; + // AMENDED as per RFC 3696 + // toplabel = alphanum | alphanum *( alphanum | "-" ) alphanum + // side condition: not all numeric + $toplabel = "$an(?:$and*$an)?"; // hostname = *( domainlabel "." ) toplabel [ "." ] - if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) { - return $string; + if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $matches)) { + if (!ctype_digit($matches[1])) { + return $string; + } } + // PHP 5.3 and later support this functionality natively + if (function_exists('idn_to_ascii')) { + $string = idn_to_ascii($string); + // If we have Net_IDNA2 support, we can support IRIs by // punycoding them. (This is the most portable thing to do, // since otherwise we have to assume browsers support - - if ($config->get('Core.EnableIDNA')) { + } elseif ($config->get('Core.EnableIDNA')) { $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true)); // we need to encode each period separately $parts = explode('.', $string); @@ -114,13 +123,14 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef } } $string = implode('.', $new_parts); - if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) { - return $string; - } } catch (Exception $e) { // XXX error reporting } } + // Try again + if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) { + return $string; + } return false; } } diff --git a/library/HTMLPurifier/AttrDef/URI/IPv4.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php index 30ac16c9e..30ac16c9e 100644 --- a/library/HTMLPurifier/AttrDef/URI/IPv4.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php diff --git a/library/HTMLPurifier/AttrDef/URI/IPv6.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php index f243793ee..f243793ee 100644 --- a/library/HTMLPurifier/AttrDef/URI/IPv6.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php diff --git a/library/HTMLPurifier/AttrTransform.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform.php index b428331f1..b428331f1 100644 --- a/library/HTMLPurifier/AttrTransform.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform.php diff --git a/library/HTMLPurifier/AttrTransform/Background.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php index 2f72869a5..2f72869a5 100644 --- a/library/HTMLPurifier/AttrTransform/Background.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php diff --git a/library/HTMLPurifier/AttrTransform/BdoDir.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php index d66c04a5b..d66c04a5b 100644 --- a/library/HTMLPurifier/AttrTransform/BdoDir.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php diff --git a/library/HTMLPurifier/AttrTransform/BgColor.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php index 0f51fd2ce..0f51fd2ce 100644 --- a/library/HTMLPurifier/AttrTransform/BgColor.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php diff --git a/library/HTMLPurifier/AttrTransform/BoolToCSS.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php index f25cd0195..f25cd0195 100644 --- a/library/HTMLPurifier/AttrTransform/BoolToCSS.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php diff --git a/library/HTMLPurifier/AttrTransform/Border.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php index 057dc017f..057dc017f 100644 --- a/library/HTMLPurifier/AttrTransform/Border.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php diff --git a/library/HTMLPurifier/AttrTransform/EnumToCSS.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php index 7ccd0e3fb..7ccd0e3fb 100644 --- a/library/HTMLPurifier/AttrTransform/EnumToCSS.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php diff --git a/library/HTMLPurifier/AttrTransform/ImgRequired.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php index 7df6cb3e1..235ebb34b 100644 --- a/library/HTMLPurifier/AttrTransform/ImgRequired.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php @@ -32,8 +32,7 @@ class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform if ($src) { $alt = $config->get('Attr.DefaultImageAlt'); if ($alt === null) { - // truncate if the alt is too long - $attr['alt'] = substr(basename($attr['src']), 0, 40); + $attr['alt'] = basename($attr['src']); } else { $attr['alt'] = $alt; } diff --git a/library/HTMLPurifier/AttrTransform/ImgSpace.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php index 350b3358f..350b3358f 100644 --- a/library/HTMLPurifier/AttrTransform/ImgSpace.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php diff --git a/library/HTMLPurifier/AttrTransform/Input.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php index 3ab47ed8c..3ab47ed8c 100644 --- a/library/HTMLPurifier/AttrTransform/Input.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php diff --git a/library/HTMLPurifier/AttrTransform/Lang.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php index 5b0aff0e4..5b0aff0e4 100644 --- a/library/HTMLPurifier/AttrTransform/Lang.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php diff --git a/library/HTMLPurifier/AttrTransform/Length.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php index 853f33549..853f33549 100644 --- a/library/HTMLPurifier/AttrTransform/Length.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php diff --git a/library/HTMLPurifier/AttrTransform/Name.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php index 63cce6837..63cce6837 100644 --- a/library/HTMLPurifier/AttrTransform/Name.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php diff --git a/library/HTMLPurifier/AttrTransform/NameSync.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php index 36079b786..36079b786 100644 --- a/library/HTMLPurifier/AttrTransform/NameSync.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php diff --git a/library/HTMLPurifier/AttrTransform/Nofollow.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php index 1057ebee1..1057ebee1 100644 --- a/library/HTMLPurifier/AttrTransform/Nofollow.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php diff --git a/library/HTMLPurifier/AttrTransform/SafeEmbed.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php index 231c81a3f..231c81a3f 100644 --- a/library/HTMLPurifier/AttrTransform/SafeEmbed.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php diff --git a/library/HTMLPurifier/AttrTransform/SafeObject.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php index d1f3a4d2e..d1f3a4d2e 100644 --- a/library/HTMLPurifier/AttrTransform/SafeObject.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php diff --git a/library/HTMLPurifier/AttrTransform/SafeParam.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php index 1143b4b49..1143b4b49 100644 --- a/library/HTMLPurifier/AttrTransform/SafeParam.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php diff --git a/library/HTMLPurifier/AttrTransform/ScriptRequired.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php index b7057bbf8..b7057bbf8 100644 --- a/library/HTMLPurifier/AttrTransform/ScriptRequired.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php diff --git a/library/HTMLPurifier/AttrTransform/TargetBlank.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php index dd63ea89c..dd63ea89c 100644 --- a/library/HTMLPurifier/AttrTransform/TargetBlank.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php new file mode 100644 index 000000000..1db3c6c09 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoopener.php @@ -0,0 +1,37 @@ +<?php + +// must be called POST validation + +/** + * Adds rel="noopener" to any links which target a different window + * than the current one. This is used to prevent malicious websites + * from silently replacing the original window, which could be used + * to do phishing. + * This transform is controlled by %HTML.TargetNoopener. + */ +class HTMLPurifier_AttrTransform_TargetNoopener extends HTMLPurifier_AttrTransform +{ + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (isset($attr['rel'])) { + $rels = explode(' ', $attr['rel']); + } else { + $rels = array(); + } + if (isset($attr['target']) && !in_array('noopener', $rels)) { + $rels[] = 'noopener'; + } + if (!empty($rels) || isset($attr['rel'])) { + $attr['rel'] = implode(' ', $rels); + } + + return $attr; + } +} + diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php new file mode 100644 index 000000000..587dc2e07 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetNoreferrer.php @@ -0,0 +1,37 @@ +<?php + +// must be called POST validation + +/** + * Adds rel="noreferrer" to any links which target a different window + * than the current one. This is used to prevent malicious websites + * from silently replacing the original window, which could be used + * to do phishing. + * This transform is controlled by %HTML.TargetNoreferrer. + */ +class HTMLPurifier_AttrTransform_TargetNoreferrer extends HTMLPurifier_AttrTransform +{ + /** + * @param array $attr + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return array + */ + public function transform($attr, $config, $context) + { + if (isset($attr['rel'])) { + $rels = explode(' ', $attr['rel']); + } else { + $rels = array(); + } + if (isset($attr['target']) && !in_array('noreferrer', $rels)) { + $rels[] = 'noreferrer'; + } + if (!empty($rels) || isset($attr['rel'])) { + $attr['rel'] = implode(' ', $rels); + } + + return $attr; + } +} + diff --git a/library/HTMLPurifier/AttrTransform/Textarea.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php index 6a9f33a0c..6a9f33a0c 100644 --- a/library/HTMLPurifier/AttrTransform/Textarea.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php diff --git a/library/HTMLPurifier/AttrTypes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php index 3b70520b6..3b70520b6 100644 --- a/library/HTMLPurifier/AttrTypes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php diff --git a/library/HTMLPurifier/AttrValidator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php index f97dc93ed..f97dc93ed 100644 --- a/library/HTMLPurifier/AttrValidator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php diff --git a/library/HTMLPurifier/Bootstrap.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php index 707122bb2..707122bb2 100644 --- a/library/HTMLPurifier/Bootstrap.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php diff --git a/library/HTMLPurifier/CSSDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php index 0acdee2d9..47dfd1f66 100644 --- a/library/HTMLPurifier/CSSDefinition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php @@ -225,6 +225,10 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition ); $max = $config->get('CSS.MaxImgLength'); + $this->info['min-width'] = + $this->info['max-width'] = + $this->info['min-height'] = + $this->info['max-height'] = $this->info['width'] = $this->info['height'] = $max === null ? @@ -350,8 +354,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition $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(); + // vendor specific prefixes of opacity $this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); $this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); @@ -371,6 +374,19 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition ); $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(array('auto', 'avoid')); + $border_radius = new HTMLPurifier_AttrDef_CSS_Composite( + array( + new HTMLPurifier_AttrDef_CSS_Percentage(true), // disallow negative + new HTMLPurifier_AttrDef_CSS_Length('0') // disallow negative + )); + + $this->info['border-top-left-radius'] = + $this->info['border-top-right-radius'] = + $this->info['border-bottom-right-radius'] = + $this->info['border-bottom-left-radius'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_radius, 2); + // TODO: support SLASH syntax + $this->info['border-radius'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_radius, 4); + } /** @@ -404,6 +420,7 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition array('visible', 'hidden', 'collapse') ); $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll')); + $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue(); } /** diff --git a/library/HTMLPurifier/ChildDef.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef.php index 8eb17b82e..8eb17b82e 100644 --- a/library/HTMLPurifier/ChildDef.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef.php diff --git a/library/HTMLPurifier/ChildDef/Chameleon.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php index 7439be26b..7439be26b 100644 --- a/library/HTMLPurifier/ChildDef/Chameleon.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php diff --git a/library/HTMLPurifier/ChildDef/Custom.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php index 128132e96..128132e96 100644 --- a/library/HTMLPurifier/ChildDef/Custom.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php diff --git a/library/HTMLPurifier/ChildDef/Empty.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php index a8a6cbdd2..a8a6cbdd2 100644 --- a/library/HTMLPurifier/ChildDef/Empty.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php diff --git a/library/HTMLPurifier/ChildDef/List.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php index 891b9f6f5..5a53a4b49 100644 --- a/library/HTMLPurifier/ChildDef/List.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php @@ -38,6 +38,12 @@ class HTMLPurifier_ChildDef_List extends HTMLPurifier_ChildDef return false; } + // if li is not allowed, delete parent node + if (!isset($config->getHTMLDefinition()->info['li'])) { + trigger_error("Cannot allow ul/ol without allowing li", E_USER_WARNING); + return false; + } + // the new set of children $result = array(); diff --git a/library/HTMLPurifier/ChildDef/Optional.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php index b9468063b..b9468063b 100644 --- a/library/HTMLPurifier/ChildDef/Optional.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php diff --git a/library/HTMLPurifier/ChildDef/Required.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php index 0d1c8f5f3..0d1c8f5f3 100644 --- a/library/HTMLPurifier/ChildDef/Required.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php diff --git a/library/HTMLPurifier/ChildDef/StrictBlockquote.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php index 3270a46e1..3270a46e1 100644 --- a/library/HTMLPurifier/ChildDef/StrictBlockquote.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php diff --git a/library/HTMLPurifier/ChildDef/Table.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php index 3e4a0f218..cb6b3e6cd 100644 --- a/library/HTMLPurifier/ChildDef/Table.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php @@ -203,7 +203,7 @@ class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef $current_tr_tbody->children[] = $node; break; case '#PCDATA': - assert($node->is_whitespace); + //assert($node->is_whitespace); if ($current_tr_tbody === null) { $ret[] = $node; } else { diff --git a/library/HTMLPurifier/Config.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php index 7ada59b94..69e6d2765 100644 --- a/library/HTMLPurifier/Config.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Config.php @@ -21,7 +21,7 @@ class HTMLPurifier_Config * HTML Purifier's version * @type string */ - public $version = '4.6.0'; + public $version = '4.9.2'; /** * Whether or not to automatically finalize @@ -646,16 +646,25 @@ class HTMLPurifier_Config return $this->getDefinition($name, true, true); } + /** + * @return HTMLPurifier_HTMLDefinition + */ public function maybeGetRawHTMLDefinition() { return $this->getDefinition('HTML', true, true); } - + + /** + * @return HTMLPurifier_CSSDefinition + */ public function maybeGetRawCSSDefinition() { return $this->getDefinition('CSS', true, true); } - + + /** + * @return HTMLPurifier_URIDefinition + */ public function maybeGetRawURIDefinition() { return $this->getDefinition('URI', true, true); diff --git a/library/HTMLPurifier/ConfigSchema.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php index bfbb0f92f..bfbb0f92f 100644 --- a/library/HTMLPurifier/ConfigSchema.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php diff --git a/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php index d5906cd46..d5906cd46 100644 --- a/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php diff --git a/library/HTMLPurifier/ConfigSchema/Builder/Xml.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php index 5fa56f7dd..5fa56f7dd 100644 --- a/library/HTMLPurifier/ConfigSchema/Builder/Xml.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php diff --git a/library/HTMLPurifier/ConfigSchema/Exception.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php index 2671516c5..2671516c5 100644 --- a/library/HTMLPurifier/ConfigSchema/Exception.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php diff --git a/library/HTMLPurifier/ConfigSchema/Interchange.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php index 0e08ae8fe..0e08ae8fe 100644 --- a/library/HTMLPurifier/ConfigSchema/Interchange.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php diff --git a/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php index 127a39a67..127a39a67 100644 --- a/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php diff --git a/library/HTMLPurifier/ConfigSchema/Interchange/Id.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php index 126f09d95..126f09d95 100644 --- a/library/HTMLPurifier/ConfigSchema/Interchange/Id.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php diff --git a/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php index 655e6dd1b..655e6dd1b 100644 --- a/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php diff --git a/library/HTMLPurifier/ConfigSchema/Validator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php index fb3127788..fb3127788 100644 --- a/library/HTMLPurifier/ConfigSchema/Validator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php diff --git a/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php index c9aa3644a..c9aa3644a 100644 --- a/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser Binary files differnew file mode 100644 index 000000000..371e948f1 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt index 0517fed0a..0517fed0a 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt index 249edd647..249edd647 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt index 9a8fa6a2e..9a8fa6a2e 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt index b01788348..b01788348 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt index e774b823b..e774b823b 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt index 533165e17..533165e17 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt index 9eb7e3846..9eb7e3846 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt index 2f17bf477..2f17bf477 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt index 52654b53a..52654b53a 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt index 6440d2103..6440d2103 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt index f31d226f5..f31d226f5 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ID.HTML5.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ID.HTML5.txt new file mode 100644 index 000000000..735d4b7a1 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ID.HTML5.txt @@ -0,0 +1,10 @@ +Attr.ID.HTML5 +TYPE: bool/null +DEFAULT: null +VERSION: 4.8.0 +--DESCRIPTION-- +In HTML5, restrictions on the format of the id attribute have been significantly +relaxed, such that any string is valid so long as it contains no spaces and +is at least one character. In lieu of a general HTML5 compatibility flag, +set this configuration directive to true to use the relaxed rules. +--# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt index 5f2b5e3d2..5f2b5e3d2 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt index 6f5824586..6f5824586 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt index cc49d43fd..cc49d43fd 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt index 2c5924a7a..2c5924a7a 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt index d5caa1bb9..d5caa1bb9 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt index 2a476481a..2a476481a 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt index 663064a34..663064a34 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt index 3a48ba960..3a48ba960 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt index db58b1346..db58b1346 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt index 7996488be..7996488be 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt new file mode 100644 index 000000000..6367fe23c --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt @@ -0,0 +1,14 @@ +AutoFormat.RemoveEmpty.Predicate +TYPE: hash +VERSION: 4.7.0 +DEFAULT: array('colgroup' => array(), 'th' => array(), 'td' => array(), 'iframe' => array('src')) +--DESCRIPTION-- +<p> + Given that an element has no contents, it will be removed by default, unless + this predicate dictates otherwise. The predicate can either be an associative + map from tag name to list of attributes that must be present for the element + to be considered preserved: thus, the default always preserves <code>colgroup</code>, + <code>th</code> and <code>td</code>, and also <code>iframe</code> if it + has a <code>src</code>. +</p> +--# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt index 35c393b4e..35c393b4e 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt index ca17eb1dc..ca17eb1dc 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt index 34657ba47..34657ba47 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt index dde990ab2..dde990ab2 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowDuplicates.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowDuplicates.txt new file mode 100644 index 000000000..4d054b1f0 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowDuplicates.txt @@ -0,0 +1,11 @@ +CSS.AllowDuplicates +TYPE: bool +DEFAULT: false +VERSION: 4.8.0 +--DESCRIPTION-- +<p> + By default, HTML Purifier removes duplicate CSS properties, + like <code>color:red; color:blue</code>. If this is set to + true, duplicate properties are allowed. +</p> +--# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt index b324608f7..b324608f7 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt index 748be0eec..748be0eec 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt index 3fd465406..3fd465406 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt index 460112ebe..460112ebe 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt index 5cb7dda3b..5cb7dda3b 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt index f1f5c5f12..f1f5c5f12 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt index 7a3291470..7a3291470 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt index 148eedb8b..148eedb8b 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt index e733a61e8..e733a61e8 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt index c486724c8..c486724c8 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt index 54036507d..54036507d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt index b2b83d9ab..2e0cc8104 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt @@ -1,5 +1,5 @@ Cache.SerializerPermissions -TYPE: int +TYPE: int/null VERSION: 4.3.0 DEFAULT: 0755 --DESCRIPTION-- @@ -8,4 +8,9 @@ DEFAULT: 0755 Directory permissions of the files and directories created inside the DefinitionCache/Serializer or other custom serializer path. </p> +<p> + In HTML Purifier 4.8.0, this also supports <code>NULL</code>, + which means that no chmod'ing or directory creation shall + occur. +</p> --# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt index 568cbf3b3..568cbf3b3 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt new file mode 100644 index 000000000..b2b6ab149 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyRemoveScript.txt @@ -0,0 +1,16 @@ +Core.AggressivelyRemoveScript +TYPE: bool +VERSION: 4.9.0 +DEFAULT: true +--DESCRIPTION-- +<p> + This directive enables aggressive pre-filter removal of + script tags. This is not necessary for security, + but it can help work around a bug in libxml where embedded + HTML elements inside script sections cause the parser to + choke. To revert to pre-4.9.0 behavior, set this to false. + This directive has no effect if %Core.Trusted is true, + %Core.RemoveScriptContents is false, or %Core.HiddenElements + does not contain script. +</p> +--# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt index 2c910cc7d..2c910cc7d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt index d7317911f..d7317911f 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt index c572c14ec..c572c14ec 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt index 64b114fce..64b114fce 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt index 36f16e07e..36f16e07e 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt index 1cd4c2c96..1cd4c2c96 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt index ce243c35d..ce243c35d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt index 8bfb47c3a..8bfb47c3a 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt index a3881be75..a3881be75 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt index a7a5b249b..a7a5b249b 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt index abb499948..abb499948 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt index 915391edb..915391edb 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt index 233fca14f..233fca14f 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt new file mode 100644 index 000000000..392b43649 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LegacyEntityDecoder.txt @@ -0,0 +1,36 @@ +Core.LegacyEntityDecoder +TYPE: bool +VERSION: 4.9.0 +DEFAULT: false +--DESCRIPTION-- +<p> + Prior to HTML Purifier 4.9.0, entities were decoded by performing + a global search replace for all entities whose decoded versions + did not have special meanings under HTML, and replaced them with + their decoded versions. We would match all entities, even if they did + not have a trailing semicolon, but only if there weren't any trailing + alphanumeric characters. +</p> +<table> +<tr><th>Original</th><th>Text</th><th>Attribute</th></tr> +<tr><td>&yen;</td><td>¥</td><td>¥</td></tr> +<tr><td>&yen</td><td>¥</td><td>¥</td></tr> +<tr><td>&yena</td><td>&yena</td><td>&yena</td></tr> +<tr><td>&yen=</td><td>¥=</td><td>¥=</td></tr> +</table> +<p> + In HTML Purifier 4.9.0, we changed the behavior of entity parsing + to match entities that had missing trailing semicolons in less + cases, to more closely match HTML5 parsing behavior: +</p> +<table> +<tr><th>Original</th><th>Text</th><th>Attribute</th></tr> +<tr><td>&yen;</td><td>¥</td><td>¥</td></tr> +<tr><td>&yen</td><td>¥</td><td>¥</td></tr> +<tr><td>&yena</td><td>¥a</td><td>&yena</td></tr> +<tr><td>&yen=</td><td>¥=</td><td>&yen=</td></tr> +</table> +<p> + This flag reverts back to pre-HTML Purifier 4.9.0 behavior. +</p> +--# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt index 8983e2cca..8983e2cca 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt index eb841a759..eb841a759 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt index d77f5360d..d77f5360d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt index 4070c2a0d..4070c2a0d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt index 3397d9f71..3397d9f71 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt index a4cd966df..a4cd966df 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt index 3db50ef20..3db50ef20 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt index 16829bcda..16829bcda 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt index 7f95f54d1..7f95f54d1 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt index 6c231b2d7..6c231b2d7 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt index 078d08741..078d08741 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt index 321eaa2d8..321eaa2d8 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt index 0b2c106da..0b2c106da 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt index fcf093f17..fcf093f17 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt index 140e21423..140e21423 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt index f22e977d4..f22e977d4 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt index 1d3fa7907..1d3fa7907 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt index 5a59a55c0..5a59a55c0 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt index 151fb7b82..151fb7b82 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt index 45ae469ec..45ae469ec 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt index 524618879..524618879 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt index a64e3d7c3..6ed70b599 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt @@ -4,6 +4,6 @@ VERSION: 2.0.1 DEFAULT: NULL --DESCRIPTION-- -A custom doctype for power-users who defined there own document +A custom doctype for power-users who defined their own document type. This directive only applies when %HTML.Doctype is blank. --# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt index 103db754a..103db754a 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt index 229ae0267..229ae0267 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt index 9dab497f2..9dab497f2 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt index 7878dc0bf..7878dc0bf 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt index 57358f9ba..57358f9ba 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt index 93a53e14f..93a53e14f 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt index e424c386e..e424c386e 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt index 700b30924..700b30924 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt index 62e8e160c..62e8e160c 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt index dfb720496..dfb720496 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt index cdda09a4c..cdda09a4c 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt index 5eb6ec2b5..5eb6ec2b5 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt index ceb342e22..ceb342e22 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt index 5ebc7a19d..5ebc7a19d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt index a8b1de56b..a8b1de56b 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt index 587a16778..587a16778 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt new file mode 100644 index 000000000..dd514c0de --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoopener.txt @@ -0,0 +1,10 @@ +--# vim: et sw=4 sts=4 +HTML.TargetNoopener +TYPE: bool +VERSION: 4.8.0 +DEFAULT: TRUE +--DESCRIPTION-- +If enabled, noopener rel attributes are added to links which have +a target attribute associated with them. This prevents malicious +destinations from overwriting the original window. +--# vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt new file mode 100644 index 000000000..cb5a0b0e5 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetNoreferrer.txt @@ -0,0 +1,9 @@ +HTML.TargetNoreferrer +TYPE: bool +VERSION: 4.8.0 +DEFAULT: TRUE +--DESCRIPTION-- +If enabled, noreferrer rel attributes are added to links which have +a target attribute associated with them. This prevents malicious +destinations from overwriting the original window. +--# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt index b4c271b7f..b4c271b7f 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt index 4186ccd0d..4186ccd0d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt index 996762bd1..996762bd1 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt index 1db9237e9..1db9237e9 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt index 2a47e384f..2a47e384f 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt index 08921fde7..08921fde7 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt index d6f0d9f29..d6f0d9f29 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt index 93398e859..93398e859 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt index 79f8ad82c..79f8ad82c 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt index 232b02362..232b02362 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt index 06bab00a0..06bab00a0 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt index 071bc0295..071bc0295 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt index 666635a5f..eb97307e2 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt @@ -8,6 +8,7 @@ array ( 'ftp' => true, 'nntp' => true, 'news' => true, + 'tel' => true, ) --DESCRIPTION-- Whitelist that defines the schemes that a URI is allowed to have. This diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt index 876f0680c..876f0680c 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt index 728e378cb..834bc08c0 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt @@ -1,5 +1,5 @@ URI.DefaultScheme -TYPE: string +TYPE: string/null DEFAULT: 'http' --DESCRIPTION-- @@ -7,4 +7,9 @@ DEFAULT: 'http' Defines through what scheme the output will be served, in order to select the proper object validator when no scheme information is present. </p> + +<p> + Starting with HTML Purifier 4.9.0, the default scheme can be null, in + which case we reject all URIs which do not have explicit schemes. +</p> --# vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt index f05312ba8..f05312ba8 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt index 80cfea93f..80cfea93f 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt index 71ce025a2..71ce025a2 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt index 13c122c8c..13c122c8c 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt index abcc1efd6..abcc1efd6 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt index f891de499..f891de499 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt index ee83b121d..ee83b121d 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt index 0b6df7625..0b6df7625 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt index 4214900a5..4214900a5 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt index 58c81dcc4..58c81dcc4 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt index 6fce0fdc3..6fce0fdc3 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt index 1e17c1d46..1e17c1d46 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt index 23331a4e7..23331a4e7 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt index 79084832b..79084832b 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt diff --git a/library/HTMLPurifier/ConfigSchema/schema/info.ini b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/info.ini index 5de4505e1..5de4505e1 100644 --- a/library/HTMLPurifier/ConfigSchema/schema/info.ini +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/info.ini diff --git a/library/HTMLPurifier/ContentSets.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php index 543e3f8f1..543e3f8f1 100644 --- a/library/HTMLPurifier/ContentSets.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php diff --git a/library/HTMLPurifier/Context.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Context.php index 00e509c85..00e509c85 100644 --- a/library/HTMLPurifier/Context.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Context.php diff --git a/library/HTMLPurifier/Definition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php index bc6d43364..bc6d43364 100644 --- a/library/HTMLPurifier/Definition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php diff --git a/library/HTMLPurifier/DefinitionCache.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache.php index 67bb5b1e6..9aa8ff354 100644 --- a/library/HTMLPurifier/DefinitionCache.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache.php @@ -118,7 +118,7 @@ abstract class HTMLPurifier_DefinitionCache /** * Clears all expired (older version or revision) objects from cache - * @note Be carefuly implementing this method as flush. Flush must + * @note Be careful implementing this method as flush. Flush must * not interfere with other Definition types, and cleanup() * should not be repeatedly called by userland code. * @param HTMLPurifier_Config $config diff --git a/library/HTMLPurifier/DefinitionCache/Decorator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php index b57a51b6c..b57a51b6c 100644 --- a/library/HTMLPurifier/DefinitionCache/Decorator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php diff --git a/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php index 4991777ce..4991777ce 100644 --- a/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php diff --git a/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php index d529dce48..d529dce48 100644 --- a/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php diff --git a/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in index b1fec8d36..b1fec8d36 100644 --- a/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in diff --git a/library/HTMLPurifier/DefinitionCache/Null.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php index d9a75ce22..d9a75ce22 100644 --- a/library/HTMLPurifier/DefinitionCache/Null.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php diff --git a/library/HTMLPurifier/DefinitionCache/Serializer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php index ecacb88fe..952e48d47 100644 --- a/library/HTMLPurifier/DefinitionCache/Serializer.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php @@ -97,6 +97,12 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac } $dir = $this->generateDirectoryPath($config); $dh = opendir($dir); + // Apparently, on some versions of PHP, readdir will return + // an empty string if you pass an invalid argument to readdir. + // So you need this test. See #49. + if (false === $dh) { + return false; + } while (false !== ($filename = readdir($dh))) { if (empty($filename)) { continue; @@ -106,6 +112,8 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac } unlink($dir . '/' . $filename); } + closedir($dh); + return true; } /** @@ -119,6 +127,10 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac } $dir = $this->generateDirectoryPath($config); $dh = opendir($dir); + // See #49 (and above). + if (false === $dh) { + return false; + } while (false !== ($filename = readdir($dh))) { if (empty($filename)) { continue; @@ -131,6 +143,8 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac unlink($dir . '/' . $filename); } } + closedir($dh); + return true; } /** @@ -186,11 +200,9 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac if ($result !== false) { // set permissions of the new file (no execute) $chmod = $config->get('Cache.SerializerPermissions'); - if (!$chmod) { - $chmod = 0644; // invalid config or simpletest + if ($chmod !== null) { + chmod($file, $chmod & 0666); } - $chmod = $chmod & 0666; - chmod($file, $chmod); } return $result; } @@ -204,8 +216,10 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac { $directory = $this->generateDirectoryPath($config); $chmod = $config->get('Cache.SerializerPermissions'); - if (!$chmod) { - $chmod = 0755; // invalid config or simpletest + if ($chmod === null) { + // TODO: This races + if (is_dir($directory)) return true; + return mkdir($directory); } if (!is_dir($directory)) { $base = $this->generateBaseDirectoryPath($config); @@ -219,9 +233,16 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac } elseif (!$this->_testPermissions($base, $chmod)) { return false; } - $old = umask(0000); - mkdir($directory, $chmod); - umask($old); + if (!mkdir($directory, $chmod)) { + trigger_error( + 'Could not create directory ' . $directory . '', + E_USER_WARNING + ); + return false; + } + if (!$this->_testPermissions($directory, $chmod)) { + return false; + } } elseif (!$this->_testPermissions($directory, $chmod)) { return false; } @@ -250,7 +271,7 @@ class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCac ); return false; } - if (function_exists('posix_getuid')) { + if (function_exists('posix_getuid') && $chmod !== null) { // POSIX system, we can give more specific advice if (fileowner($dir) === posix_getuid()) { // we can chmod it ourselves diff --git a/library/HTMLPurifier/DefinitionCache/Serializer/README b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/README index 2e35c1c3d..2e35c1c3d 100644..100755 --- a/library/HTMLPurifier/DefinitionCache/Serializer/README +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/README diff --git a/library/HTMLPurifier/DefinitionCacheFactory.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php index fd1cc9be4..fd1cc9be4 100644 --- a/library/HTMLPurifier/DefinitionCacheFactory.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php diff --git a/library/HTMLPurifier/Doctype.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Doctype.php index 4acd06e5b..4acd06e5b 100644 --- a/library/HTMLPurifier/Doctype.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Doctype.php diff --git a/library/HTMLPurifier/DoctypeRegistry.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php index acc1d64a6..acc1d64a6 100644 --- a/library/HTMLPurifier/DoctypeRegistry.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php diff --git a/library/HTMLPurifier/ElementDef.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ElementDef.php index d5311cedc..d5311cedc 100644 --- a/library/HTMLPurifier/ElementDef.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ElementDef.php diff --git a/library/HTMLPurifier/Encoder.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php index fef9b5890..b94f17542 100644 --- a/library/HTMLPurifier/Encoder.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php @@ -101,6 +101,14 @@ class HTMLPurifier_Encoder * It will parse according to UTF-8 and return a valid UTF8 string, with * non-SGML codepoints excluded. * + * Specifically, it will permit: + * \x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF} + * Source: https://www.w3.org/TR/REC-xml/#NT-Char + * Arguably this function should be modernized to the HTML5 set + * of allowed characters: + * https://www.w3.org/TR/html5/syntax.html#preprocessing-the-input-stream + * which simultaneously expand and restrict the set of allowed characters. + * * @param string $str The string to clean * @param bool $force_php * @return string @@ -122,15 +130,12 @@ class HTMLPurifier_Encoder * function that needs to be able to understand UTF-8 characters. * As of right now, only smart lossless character encoding converters * would need that, and I'm probably not going to implement them. - * Once again, PHP 6 should solve all our problems. */ public static function cleanUTF8($str, $force_php = false) { // UTF-8 validity is checked since PHP 4.3.5 // 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. - // The regexp matches the XML char production, as well as well as excluding - // non-SGML codepoints U+007F to U+009F if (preg_match( '/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/Du', $str @@ -255,6 +260,7 @@ class HTMLPurifier_Encoder // 7F-9F is not strictly prohibited by XML, // but it is non-SGML, and thus we don't allow it (0xA0 <= $mUcs4 && 0xD7FF >= $mUcs4) || + (0xE000 <= $mUcs4 && 0xFFFD >= $mUcs4) || (0x10000 <= $mUcs4 && 0x10FFFF >= $mUcs4) ) ) { diff --git a/library/HTMLPurifier/EntityLookup.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup.php index f12ff13a3..f12ff13a3 100644 --- a/library/HTMLPurifier/EntityLookup.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup.php diff --git a/library/HTMLPurifier/EntityLookup/entities.ser b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup/entities.ser index e8b08128b..e8b08128b 100644 --- a/library/HTMLPurifier/EntityLookup/entities.ser +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup/entities.ser diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php new file mode 100644 index 000000000..c372b5a6a --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php @@ -0,0 +1,285 @@ +<?php + +// if want to implement error collecting here, we'll need to use some sort +// of global data (probably trigger_error) because it's impossible to pass +// $config or $context to the callback functions. + +/** + * Handles referencing and derefencing character entities + */ +class HTMLPurifier_EntityParser +{ + + /** + * Reference to entity lookup table. + * @type HTMLPurifier_EntityLookup + */ + protected $_entity_lookup; + + /** + * Callback regex string for entities in text. + * @type string + */ + protected $_textEntitiesRegex; + + /** + * Callback regex string for entities in attributes. + * @type string + */ + protected $_attrEntitiesRegex; + + /** + * Tests if the beginning of a string is a semi-optional regex + */ + protected $_semiOptionalPrefixRegex; + + public function __construct() { + // From + // http://stackoverflow.com/questions/15532252/why-is-reg-being-rendered-as-without-the-bounding-semicolon + $semi_optional = "quot|QUOT|lt|LT|gt|GT|amp|AMP|AElig|Aacute|Acirc|Agrave|Aring|Atilde|Auml|COPY|Ccedil|ETH|Eacute|Ecirc|Egrave|Euml|Iacute|Icirc|Igrave|Iuml|Ntilde|Oacute|Ocirc|Ograve|Oslash|Otilde|Ouml|REG|THORN|Uacute|Ucirc|Ugrave|Uuml|Yacute|aacute|acirc|acute|aelig|agrave|aring|atilde|auml|brvbar|ccedil|cedil|cent|copy|curren|deg|divide|eacute|ecirc|egrave|eth|euml|frac12|frac14|frac34|iacute|icirc|iexcl|igrave|iquest|iuml|laquo|macr|micro|middot|nbsp|not|ntilde|oacute|ocirc|ograve|ordf|ordm|oslash|otilde|ouml|para|plusmn|pound|raquo|reg|sect|shy|sup1|sup2|sup3|szlig|thorn|times|uacute|ucirc|ugrave|uml|uuml|yacute|yen|yuml"; + + // NB: three empty captures to put the fourth match in the right + // place + $this->_semiOptionalPrefixRegex = "/&()()()($semi_optional)/"; + + $this->_textEntitiesRegex = + '/&(?:'. + // hex + '[#]x([a-fA-F0-9]+);?|'. + // dec + '[#]0*(\d+);?|'. + // string (mandatory semicolon) + // NB: order matters: match semicolon preferentially + '([A-Za-z_:][A-Za-z0-9.\-_:]*);|'. + // string (optional semicolon) + "($semi_optional)". + ')/'; + + $this->_attrEntitiesRegex = + '/&(?:'. + // hex + '[#]x([a-fA-F0-9]+);?|'. + // dec + '[#]0*(\d+);?|'. + // string (mandatory semicolon) + // NB: order matters: match semicolon preferentially + '([A-Za-z_:][A-Za-z0-9.\-_:]*);|'. + // string (optional semicolon) + // don't match if trailing is equals or alphanumeric (URL + // like) + "($semi_optional)(?![=;A-Za-z0-9])". + ')/'; + + } + + /** + * Substitute entities with the parsed equivalents. Use this on + * textual data in an HTML document (as opposed to attributes.) + * + * @param string $string String to have entities parsed. + * @return string Parsed string. + */ + public function substituteTextEntities($string) + { + return preg_replace_callback( + $this->_textEntitiesRegex, + array($this, 'entityCallback'), + $string + ); + } + + /** + * Substitute entities with the parsed equivalents. Use this on + * attribute contents in documents. + * + * @param string $string String to have entities parsed. + * @return string Parsed string. + */ + public function substituteAttrEntities($string) + { + return preg_replace_callback( + $this->_attrEntitiesRegex, + array($this, 'entityCallback'), + $string + ); + } + + /** + * Callback function for substituteNonSpecialEntities() that does the work. + * + * @param array $matches PCRE matches array, with 0 the entire match, and + * either index 1, 2 or 3 set with a hex value, dec value, + * or string (respectively). + * @return string Replacement string. + */ + + protected function entityCallback($matches) + { + $entity = $matches[0]; + $hex_part = @$matches[1]; + $dec_part = @$matches[2]; + $named_part = empty($matches[3]) ? @$matches[4] : $matches[3]; + if ($hex_part !== NULL && $hex_part !== "") { + return HTMLPurifier_Encoder::unichr(hexdec($hex_part)); + } elseif ($dec_part !== NULL && $dec_part !== "") { + return HTMLPurifier_Encoder::unichr((int) $dec_part); + } else { + if (!$this->_entity_lookup) { + $this->_entity_lookup = HTMLPurifier_EntityLookup::instance(); + } + if (isset($this->_entity_lookup->table[$named_part])) { + return $this->_entity_lookup->table[$named_part]; + } else { + // exact match didn't match anything, so test if + // any of the semicolon optional match the prefix. + // Test that this is an EXACT match is important to + // prevent infinite loop + if (!empty($matches[3])) { + return preg_replace_callback( + $this->_semiOptionalPrefixRegex, + array($this, 'entityCallback'), + $entity + ); + } + return $entity; + } + } + } + + // LEGACY CODE BELOW + + /** + * Callback regex string for parsing entities. + * @type string + */ + protected $_substituteEntitiesRegex = + '/&(?:[#]x([a-fA-F0-9]+)|[#]0*(\d+)|([A-Za-z_:][A-Za-z0-9.\-_:]*));?/'; + // 1. hex 2. dec 3. string (XML style) + + /** + * Decimal to parsed string conversion table for special entities. + * @type array + */ + protected $_special_dec2str = + array( + 34 => '"', + 38 => '&', + 39 => "'", + 60 => '<', + 62 => '>' + ); + + /** + * Stripped entity names to decimal conversion table for special entities. + * @type array + */ + protected $_special_ent2dec = + array( + 'quot' => 34, + 'amp' => 38, + 'lt' => 60, + 'gt' => 62 + ); + + /** + * Substitutes non-special entities with their parsed equivalents. Since + * running this whenever you have parsed character is t3h 5uck, we run + * it before everything else. + * + * @param string $string String to have non-special entities parsed. + * @return string Parsed string. + */ + public function substituteNonSpecialEntities($string) + { + // it will try to detect missing semicolons, but don't rely on it + return preg_replace_callback( + $this->_substituteEntitiesRegex, + array($this, 'nonSpecialEntityCallback'), + $string + ); + } + + /** + * Callback function for substituteNonSpecialEntities() that does the work. + * + * @param array $matches PCRE matches array, with 0 the entire match, and + * either index 1, 2 or 3 set with a hex value, dec value, + * or string (respectively). + * @return string Replacement string. + */ + + protected function nonSpecialEntityCallback($matches) + { + // replaces all but big five + $entity = $matches[0]; + $is_num = (@$matches[0][1] === '#'); + if ($is_num) { + $is_hex = (@$entity[2] === 'x'); + $code = $is_hex ? hexdec($matches[1]) : (int) $matches[2]; + // abort for special characters + if (isset($this->_special_dec2str[$code])) { + return $entity; + } + return HTMLPurifier_Encoder::unichr($code); + } else { + if (isset($this->_special_ent2dec[$matches[3]])) { + return $entity; + } + if (!$this->_entity_lookup) { + $this->_entity_lookup = HTMLPurifier_EntityLookup::instance(); + } + if (isset($this->_entity_lookup->table[$matches[3]])) { + return $this->_entity_lookup->table[$matches[3]]; + } else { + return $entity; + } + } + } + + /** + * Substitutes only special entities with their parsed equivalents. + * + * @notice We try to avoid calling this function because otherwise, it + * would have to be called a lot (for every parsed section). + * + * @param string $string String to have non-special entities parsed. + * @return string Parsed string. + */ + public function substituteSpecialEntities($string) + { + return preg_replace_callback( + $this->_substituteEntitiesRegex, + array($this, 'specialEntityCallback'), + $string + ); + } + + /** + * Callback function for substituteSpecialEntities() that does the work. + * + * This callback has same syntax as nonSpecialEntityCallback(). + * + * @param array $matches PCRE-style matches array, with 0 the entire match, and + * either index 1, 2 or 3 set with a hex value, dec value, + * or string (respectively). + * @return string Replacement string. + */ + protected function specialEntityCallback($matches) + { + $entity = $matches[0]; + $is_num = (@$matches[0][1] === '#'); + if ($is_num) { + $is_hex = (@$entity[2] === 'x'); + $int = $is_hex ? hexdec($matches[1]) : (int) $matches[2]; + return isset($this->_special_dec2str[$int]) ? + $this->_special_dec2str[$int] : + $entity; + } else { + return isset($this->_special_ent2dec[$matches[3]]) ? + $this->_special_dec2str[$this->_special_ent2dec[$matches[3]]] : + $entity; + } + } +} + +// vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/ErrorCollector.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ErrorCollector.php index d47e3f2e2..d47e3f2e2 100644 --- a/library/HTMLPurifier/ErrorCollector.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ErrorCollector.php diff --git a/library/HTMLPurifier/ErrorStruct.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ErrorStruct.php index cf869d321..cf869d321 100644 --- a/library/HTMLPurifier/ErrorStruct.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/ErrorStruct.php diff --git a/library/HTMLPurifier/Exception.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Exception.php index be85b4c56..be85b4c56 100644 --- a/library/HTMLPurifier/Exception.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Exception.php diff --git a/library/HTMLPurifier/Filter.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php index c1f41ee16..c1f41ee16 100644 --- a/library/HTMLPurifier/Filter.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php diff --git a/library/HTMLPurifier/Filter/ExtractStyleBlocks.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php index 08e62c16b..66f70b0fc 100644 --- a/library/HTMLPurifier/Filter/ExtractStyleBlocks.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php @@ -95,7 +95,10 @@ class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter if ($tidy !== null) { $this->_tidy = $tidy; } - $html = preg_replace_callback('#<style(?:\s.*)?>(.+)</style>#isU', array($this, 'styleCallback'), $html); + // NB: this must be NON-greedy because if we have + // <style>foo</style> <style>bar</style> + // we must not grab foo</style> <style>bar + $html = preg_replace_callback('#<style(?:\s.*)?>(.*)<\/style>#isU', array($this, 'styleCallback'), $html); $style_blocks = $this->_styleMatches; $this->_styleMatches = array(); // reset $context->register('StyleBlocks', $style_blocks); // $context must not be reused diff --git a/library/HTMLPurifier/Filter/YouTube.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php index 411519ad6..276d8362f 100644 --- a/library/HTMLPurifier/Filter/YouTube.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php @@ -17,7 +17,7 @@ class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter public function preFilter($html, $config, $context) { $pre_regex = '#<object[^>]+>.+?' . - 'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s'; + '(?:http:)?//www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s'; $pre_replace = '<span class="youtube-embed">\1</span>'; return preg_replace($pre_regex, $pre_replace, $html); } @@ -51,10 +51,10 @@ class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter { $url = $this->armorUrl($matches[1]); return '<object width="425" height="350" type="application/x-shockwave-flash" ' . - 'data="http://www.youtube.com/' . $url . '">' . - '<param name="movie" value="http://www.youtube.com/' . $url . '"></param>' . + 'data="//www.youtube.com/' . $url . '">' . + '<param name="movie" value="//www.youtube.com/' . $url . '"></param>' . '<!--[if IE]>' . - '<embed src="http://www.youtube.com/' . $url . '"' . + '<embed src="//www.youtube.com/' . $url . '"' . 'type="application/x-shockwave-flash"' . 'wmode="transparent" width="425" height="350" />' . '<![endif]-->' . diff --git a/library/HTMLPurifier/Generator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php index 6fb568714..6fb568714 100644 --- a/library/HTMLPurifier/Generator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php diff --git a/library/HTMLPurifier/HTMLDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php index 9b7b334dd..9b7b334dd 100644 --- a/library/HTMLPurifier/HTMLDefinition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php diff --git a/library/HTMLPurifier/HTMLModule.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule.php index bb3a9230b..bb3a9230b 100644 --- a/library/HTMLPurifier/HTMLModule.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule.php diff --git a/library/HTMLPurifier/HTMLModule/Bdo.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php index 1e67c790d..1e67c790d 100644 --- a/library/HTMLPurifier/HTMLModule/Bdo.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php diff --git a/library/HTMLPurifier/HTMLModule/CommonAttributes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php index a96ab1bef..a96ab1bef 100644 --- a/library/HTMLPurifier/HTMLModule/CommonAttributes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php diff --git a/library/HTMLPurifier/HTMLModule/Edit.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php index a9042a357..a9042a357 100644 --- a/library/HTMLPurifier/HTMLModule/Edit.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php diff --git a/library/HTMLPurifier/HTMLModule/Forms.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php index 6f7ddbc05..6f7ddbc05 100644 --- a/library/HTMLPurifier/HTMLModule/Forms.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php diff --git a/library/HTMLPurifier/HTMLModule/Hypertext.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php index 72d7a31e6..72d7a31e6 100644 --- a/library/HTMLPurifier/HTMLModule/Hypertext.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php diff --git a/library/HTMLPurifier/HTMLModule/Iframe.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php index f7e7c91c0..f7e7c91c0 100644 --- a/library/HTMLPurifier/HTMLModule/Iframe.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php diff --git a/library/HTMLPurifier/HTMLModule/Image.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php index 0f5fdb3ba..0f5fdb3ba 100644 --- a/library/HTMLPurifier/HTMLModule/Image.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php diff --git a/library/HTMLPurifier/HTMLModule/Legacy.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php index 86b529957..86b529957 100644 --- a/library/HTMLPurifier/HTMLModule/Legacy.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php diff --git a/library/HTMLPurifier/HTMLModule/List.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php index 7a20ff701..7a20ff701 100644 --- a/library/HTMLPurifier/HTMLModule/List.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php diff --git a/library/HTMLPurifier/HTMLModule/Name.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php index 60c054515..60c054515 100644 --- a/library/HTMLPurifier/HTMLModule/Name.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php diff --git a/library/HTMLPurifier/HTMLModule/Nofollow.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php index dc9410a89..dc9410a89 100644 --- a/library/HTMLPurifier/HTMLModule/Nofollow.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php diff --git a/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php index da722253a..da722253a 100644 --- a/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php diff --git a/library/HTMLPurifier/HTMLModule/Object.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php index 2f9efc5c8..2f9efc5c8 100644 --- a/library/HTMLPurifier/HTMLModule/Object.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php diff --git a/library/HTMLPurifier/HTMLModule/Presentation.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php index 6458ce9d8..6458ce9d8 100644 --- a/library/HTMLPurifier/HTMLModule/Presentation.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php diff --git a/library/HTMLPurifier/HTMLModule/Proprietary.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php index 5ee3c8e67..5ee3c8e67 100644 --- a/library/HTMLPurifier/HTMLModule/Proprietary.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php diff --git a/library/HTMLPurifier/HTMLModule/Ruby.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php index a0d48924d..a0d48924d 100644 --- a/library/HTMLPurifier/HTMLModule/Ruby.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php diff --git a/library/HTMLPurifier/HTMLModule/SafeEmbed.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php index 04e6689ea..04e6689ea 100644 --- a/library/HTMLPurifier/HTMLModule/SafeEmbed.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php diff --git a/library/HTMLPurifier/HTMLModule/SafeObject.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php index 1297f80a3..1297f80a3 100644 --- a/library/HTMLPurifier/HTMLModule/SafeObject.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php diff --git a/library/HTMLPurifier/HTMLModule/SafeScripting.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php index 0330cd97f..0330cd97f 100644 --- a/library/HTMLPurifier/HTMLModule/SafeScripting.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php diff --git a/library/HTMLPurifier/HTMLModule/Scripting.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php index 8b28a7b7e..8b28a7b7e 100644 --- a/library/HTMLPurifier/HTMLModule/Scripting.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php diff --git a/library/HTMLPurifier/HTMLModule/StyleAttribute.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php index 497b832ae..497b832ae 100644 --- a/library/HTMLPurifier/HTMLModule/StyleAttribute.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php diff --git a/library/HTMLPurifier/HTMLModule/Tables.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php index 8a0b3b461..8a0b3b461 100644 --- a/library/HTMLPurifier/HTMLModule/Tables.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php diff --git a/library/HTMLPurifier/HTMLModule/Target.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php index b188ac936..b188ac936 100644 --- a/library/HTMLPurifier/HTMLModule/Target.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php diff --git a/library/HTMLPurifier/HTMLModule/TargetBlank.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php index 58ccc6894..58ccc6894 100644 --- a/library/HTMLPurifier/HTMLModule/TargetBlank.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php new file mode 100644 index 000000000..b967ff566 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoopener.php @@ -0,0 +1,21 @@ +<?php + +/** + * Module adds the target-based noopener attribute transformation to a tags. It + * is enabled by HTML.TargetNoopener + */ +class HTMLPurifier_HTMLModule_TargetNoopener extends HTMLPurifier_HTMLModule +{ + /** + * @type string + */ + public $name = 'TargetNoopener'; + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) { + $a = $this->addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetNoopener(); + } +} diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php new file mode 100644 index 000000000..32484d601 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetNoreferrer.php @@ -0,0 +1,21 @@ +<?php + +/** + * Module adds the target-based noreferrer attribute transformation to a tags. It + * is enabled by HTML.TargetNoreferrer + */ +class HTMLPurifier_HTMLModule_TargetNoreferrer extends HTMLPurifier_HTMLModule +{ + /** + * @type string + */ + public $name = 'TargetNoreferrer'; + + /** + * @param HTMLPurifier_Config $config + */ + public function setup($config) { + $a = $this->addBlankElement('a'); + $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetNoreferrer(); + } +} diff --git a/library/HTMLPurifier/HTMLModule/Text.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php index 7a65e0048..7a65e0048 100644 --- a/library/HTMLPurifier/HTMLModule/Text.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php diff --git a/library/HTMLPurifier/HTMLModule/Tidy.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php index 08aa23247..08aa23247 100644 --- a/library/HTMLPurifier/HTMLModule/Tidy.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Name.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php index a995161b2..a995161b2 100644 --- a/library/HTMLPurifier/HTMLModule/Tidy/Name.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php index 332643821..332643821 100644 --- a/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Strict.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php index 803c44fab..803c44fab 100644 --- a/library/HTMLPurifier/HTMLModule/Tidy/Strict.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php index c095ad974..c095ad974 100644 --- a/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php diff --git a/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php index 3ecddc434..3ecddc434 100644 --- a/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php diff --git a/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php index c4f16a4dc..c4f16a4dc 100644 --- a/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php diff --git a/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php index 01dbe9deb..01dbe9deb 100644 --- a/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php diff --git a/library/HTMLPurifier/HTMLModuleManager.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModuleManager.php index f3a17cb03..38c058fe2 100644 --- a/library/HTMLPurifier/HTMLModuleManager.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModuleManager.php @@ -271,6 +271,14 @@ class HTMLPurifier_HTMLModuleManager if ($config->get('HTML.TargetBlank')) { $modules[] = 'TargetBlank'; } + // NB: HTML.TargetNoreferrer and HTML.TargetNoopener must be AFTER HTML.TargetBlank + // so that its post-attr-transform gets run afterwards. + if ($config->get('HTML.TargetNoreferrer')) { + $modules[] = 'TargetNoreferrer'; + } + if ($config->get('HTML.TargetNoopener')) { + $modules[] = 'TargetNoopener'; + } // merge in custom modules $modules = array_merge($modules, $this->userModules); diff --git a/library/HTMLPurifier/IDAccumulator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/IDAccumulator.php index 65c902c07..65c902c07 100644 --- a/library/HTMLPurifier/IDAccumulator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/IDAccumulator.php diff --git a/library/HTMLPurifier/Injector.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php index 5060eef9e..5060eef9e 100644 --- a/library/HTMLPurifier/Injector.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php diff --git a/library/HTMLPurifier/Injector/AutoParagraph.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php index 4afdd128d..4afdd128d 100644 --- a/library/HTMLPurifier/Injector/AutoParagraph.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php diff --git a/library/HTMLPurifier/Injector/DisplayLinkURI.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php index c19b1bc27..c19b1bc27 100644 --- a/library/HTMLPurifier/Injector/DisplayLinkURI.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php diff --git a/library/HTMLPurifier/Injector/Linkify.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php index 069708c25..74f83eaa7 100644 --- a/library/HTMLPurifier/Injector/Linkify.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php @@ -31,9 +31,14 @@ class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector return; } - // there is/are URL(s). Let's split the string: - // Note: this regex is extremely permissive - $bits = preg_split('#((?:https?|ftp)://[^\s\'",<>()]+)#Su', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE); + // there is/are URL(s). Let's split the string. + // We use this regex: + // https://gist.github.com/gruber/249502 + // but with @cscott's backtracking fix and also + // the Unicode characters un-Unicodified. + $bits = preg_split( + '/\\b((?:[a-z][\\w\\-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]|\\((?:[^\\s()<>]|(?:\\([^\\s()<>]+\\)))*\\))+(?:\\((?:[^\\s()<>]|(?:\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'".,<>?\x{00ab}\x{00bb}\x{201c}\x{201d}\x{2018}\x{2019}]))/iu', + $token->data, -1, PREG_SPLIT_DELIM_CAPTURE); $token = array(); diff --git a/library/HTMLPurifier/Injector/PurifierLinkify.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php index cb9046f33..cb9046f33 100644 --- a/library/HTMLPurifier/Injector/PurifierLinkify.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php diff --git a/library/HTMLPurifier/Injector/RemoveEmpty.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php index cd885722e..0ebc477c6 100644 --- a/library/HTMLPurifier/Injector/RemoveEmpty.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php @@ -28,10 +28,10 @@ class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector private $removeNbspExceptions; /** + * Cached contents of %AutoFormat.RemoveEmpty.Predicate * @type array - * TODO: make me configurable */ - private $_exclude = array('colgroup' => 1, 'th' => 1, 'td' => 1, 'iframe' => 1); + private $exclude; /** * @param HTMLPurifier_Config $config @@ -45,6 +45,13 @@ class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector $this->context = $context; $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp'); $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions'); + $this->exclude = $config->get('AutoFormat.RemoveEmpty.Predicate'); + foreach ($this->exclude as $key => $attrs) { + if (!is_array($attrs)) { + // HACK, see HTMLPurifier/Printer/ConfigForm.php + $this->exclude[$key] = explode(';', $attrs); + } + } $this->attrValidator = new HTMLPurifier_AttrValidator(); } @@ -75,11 +82,15 @@ class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector break; } if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) { - if (isset($this->_exclude[$token->name])) { - return; - } $this->attrValidator->validateToken($token, $this->config, $this->context); $token->armor['ValidateAttributes'] = true; + if (isset($this->exclude[$token->name])) { + $r = true; + foreach ($this->exclude[$token->name] as $elem) { + if (!isset($token->attr[$elem])) $r = false; + } + if ($r) return; + } if (isset($token->attr['id']) || isset($token->attr['name'])) { return; } diff --git a/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php index 9ee7aa84d..9ee7aa84d 100644 --- a/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php diff --git a/library/HTMLPurifier/Injector/SafeObject.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php index 3d17e07af..317f7864d 100644 --- a/library/HTMLPurifier/Injector/SafeObject.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php @@ -36,6 +36,7 @@ class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector ); /** + * These are all lower-case keys. * @type array */ protected $allowedParam = array( @@ -43,7 +44,7 @@ class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector 'movie' => true, 'flashvars' => true, 'src' => true, - 'allowFullScreen' => true, // if omitted, assume to be 'false' + 'allowfullscreen' => true, // if omitted, assume to be 'false' ); /** @@ -93,9 +94,11 @@ class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector $token->attr['name'] === $this->addParam[$n]) { // keep token, and add to param stack $this->paramStack[$i][$n] = true; - } elseif (isset($this->allowedParam[$n])) { + } elseif (isset($this->allowedParam[strtolower($n)])) { // keep token, don't do anything to it // (could possibly check for duplicates here) + // Note: In principle, parameters should be case sensitive. + // But it seems they are not really; so accept any case. } else { $token = false; } diff --git a/library/HTMLPurifier/Language.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language.php index 65277dd43..65277dd43 100644 --- a/library/HTMLPurifier/Language.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language.php diff --git a/library/HTMLPurifier/Language/classes/en-x-test.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/classes/en-x-test.php index 8828f5cde..8828f5cde 100644 --- a/library/HTMLPurifier/Language/classes/en-x-test.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/classes/en-x-test.php diff --git a/library/HTMLPurifier/Language/messages/en-x-test.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-test.php index 1c046f379..1c046f379 100644 --- a/library/HTMLPurifier/Language/messages/en-x-test.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-test.php diff --git a/library/HTMLPurifier/Language/messages/en-x-testmini.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-testmini.php index 806c83fbf..806c83fbf 100644 --- a/library/HTMLPurifier/Language/messages/en-x-testmini.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-testmini.php diff --git a/library/HTMLPurifier/Language/messages/en.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en.php index c7f197e1e..c7f197e1e 100644 --- a/library/HTMLPurifier/Language/messages/en.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en.php diff --git a/library/HTMLPurifier/LanguageFactory.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php index 4e35272d8..4e35272d8 100644 --- a/library/HTMLPurifier/LanguageFactory.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php diff --git a/library/HTMLPurifier/Length.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Length.php index bbfbe6624..bbfbe6624 100644 --- a/library/HTMLPurifier/Length.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Length.php diff --git a/library/HTMLPurifier/Lexer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php index 43732621d..99b3c7df0 100644 --- a/library/HTMLPurifier/Lexer.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php @@ -169,21 +169,24 @@ class HTMLPurifier_Lexer ''' => "'" ); + public function parseText($string, $config) { + return $this->parseData($string, false, $config); + } + + public function parseAttr($string, $config) { + return $this->parseData($string, true, $config); + } + /** * Parses special entities into the proper characters. * * This string will translate escaped versions of the special characters * into the correct ones. * - * @warning - * You should be able to treat the output of this function as - * completely parsed, but that's only because all other entities should - * have been handled previously in substituteNonSpecialEntities() - * * @param string $string String character data to be parsed. * @return string Parsed character data. */ - public function parseData($string) + public function parseData($string, $is_attr, $config) { // following functions require at least one character if ($string === '') { @@ -209,7 +212,15 @@ class HTMLPurifier_Lexer } // hmm... now we have some uncommon entities. Use the callback. - $string = $this->_entity_parser->substituteSpecialEntities($string); + if ($config->get('Core.LegacyEntityDecoder')) { + $string = $this->_entity_parser->substituteSpecialEntities($string); + } else { + if ($is_attr) { + $string = $this->_entity_parser->substituteAttrEntities($string); + } else { + $string = $this->_entity_parser->substituteTextEntities($string); + } + } return $string; } @@ -323,7 +334,9 @@ class HTMLPurifier_Lexer } // expand entities that aren't the big five - $html = $this->_entity_parser->substituteNonSpecialEntities($html); + if ($config->get('Core.LegacyEntityDecoder')) { + $html = $this->_entity_parser->substituteNonSpecialEntities($html); + } // clean into wellformed UTF-8 string for an SGML context: this has // to be done after entity expansion because the entities sometimes @@ -335,6 +348,13 @@ class HTMLPurifier_Lexer $html = preg_replace('#<\?.+?\?>#s', '', $html); } + $hidden_elements = $config->get('Core.HiddenElements'); + if ($config->get('Core.AggressivelyRemoveScript') && + !($config->get('HTML.Trusted') || !$config->get('Core.RemoveScriptContents') + || empty($hidden_elements["script"]))) { + $html = preg_replace('#<script[^>]*>.*?</script>#i', '', $html); + } + return $html; } @@ -345,12 +365,17 @@ class HTMLPurifier_Lexer public function extractBody($html) { $matches = array(); - $result = preg_match('!<body[^>]*>(.*)</body>!is', $html, $matches); + $result = preg_match('|(.*?)<body[^>]*>(.*)</body>|is', $html, $matches); if ($result) { - return $matches[1]; - } else { - return $html; + // Make sure it's not in a comment + $comment_start = strrpos($matches[1], '<!--'); + $comment_end = strrpos($matches[1], '-->'); + if ($comment_start === false || + ($comment_end !== false && $comment_end > $comment_start)) { + return $matches[2]; + } } + return $html; } } diff --git a/library/HTMLPurifier/Lexer/DOMLex.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php index 720754454..22ab5820c 100644 --- a/library/HTMLPurifier/Lexer/DOMLex.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php @@ -72,13 +72,20 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer $doc->loadHTML($html); restore_error_handler(); + $body = $doc->getElementsByTagName('html')->item(0)-> // <html> + getElementsByTagName('body')->item(0); // <body> + + $div = $body->getElementsByTagName('div')->item(0); // <div> $tokens = array(); - $this->tokenizeDOM( - $doc->getElementsByTagName('html')->item(0)-> // <html> - getElementsByTagName('body')->item(0)-> // <body> - getElementsByTagName('div')->item(0), // <div> - $tokens - ); + $this->tokenizeDOM($div, $tokens, $config); + // If the div has a sibling, that means we tripped across + // a premature </div> tag. So remove the div we parsed, + // and then tokenize the rest of body. We can't tokenize + // the sibling directly as we'll lose the tags in that case. + if ($div->nextSibling) { + $body->removeChild($div); + $this->tokenizeDOM($body, $tokens, $config); + } return $tokens; } @@ -89,7 +96,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer * @param HTMLPurifier_Token[] $tokens Array-list of already tokenized tokens. * @return HTMLPurifier_Token of node appended to previously passed tokens. */ - protected function tokenizeDOM($node, &$tokens) + protected function tokenizeDOM($node, &$tokens, $config) { $level = 0; $nodes = array($level => new HTMLPurifier_Queue(array($node))); @@ -98,7 +105,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer while (!$nodes[$level]->isEmpty()) { $node = $nodes[$level]->shift(); // FIFO $collect = $level > 0 ? true : false; - $needEndingTag = $this->createStartNode($node, $tokens, $collect); + $needEndingTag = $this->createStartNode($node, $tokens, $collect, $config); if ($needEndingTag) { $closingNodes[$level][] = $node; } @@ -128,7 +135,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer * @return bool if the token needs an endtoken * @todo data and tagName properties don't seem to exist in DOMNode? */ - protected function createStartNode($node, &$tokens, $collect) + protected function createStartNode($node, &$tokens, $collect, $config) { // intercept non element nodes. WE MUST catch all of them, // but we're not getting the character reference nodes because @@ -152,7 +159,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer } } } - $tokens[] = $this->factory->createText($this->parseData($data)); + $tokens[] = $this->factory->createText($this->parseText($data, $config)); return false; } elseif ($node->nodeType === XML_COMMENT_NODE) { // this is code is only invoked for comments in script/style in versions @@ -253,7 +260,7 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer * @param HTMLPurifier_Context $context * @return string */ - protected function wrapHTML($html, $config, $context) + protected function wrapHTML($html, $config, $context, $use_div = true) { $def = $config->getDefinition('HTML'); $ret = ''; @@ -272,7 +279,11 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer $ret .= '<html><head>'; $ret .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />'; // No protection if $html contains a stray </div>! - $ret .= '</head><body><div>' . $html . '</div></body></html>'; + $ret .= '</head><body>'; + if ($use_div) $ret .= '<div>'; + $ret .= $html; + if ($use_div) $ret .= '</div>'; + $ret .= '</body></html>'; return $ret; } } diff --git a/library/HTMLPurifier/Lexer/DirectLex.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DirectLex.php index 746b6e315..6f1308966 100644 --- a/library/HTMLPurifier/Lexer/DirectLex.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DirectLex.php @@ -129,12 +129,12 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer // We are not inside tag and there still is another tag to parse $token = new HTMLPurifier_Token_Text( - $this->parseData( + $this->parseText( substr( $html, $cursor, $position_next_lt - $cursor - ) + ), $config ) ); if ($maintain_line_numbers) { @@ -154,11 +154,11 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer // Create Text of rest of string $token = new HTMLPurifier_Token_Text( - $this->parseData( + $this->parseText( substr( $html, $cursor - ) + ), $config ) ); if ($maintain_line_numbers) { @@ -324,8 +324,8 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer $token = new HTMLPurifier_Token_Text( '<' . - $this->parseData( - substr($html, $cursor) + $this->parseText( + substr($html, $cursor), $config ) ); if ($maintain_line_numbers) { @@ -429,7 +429,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer if ($value === false) { $value = ''; } - return array($key => $this->parseData($value)); + return array($key => $this->parseAttr($value, $config)); } // setup loop environment @@ -518,7 +518,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer if ($value === false) { $value = ''; } - $array[$key] = $this->parseData($value); + $array[$key] = $this->parseAttr($value, $config); $cursor++; } else { // boolattr diff --git a/library/HTMLPurifier/Lexer/PH5P.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php index a4587e4cd..0b452d17f 100644 --- a/library/HTMLPurifier/Lexer/PH5P.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php @@ -21,7 +21,7 @@ class HTMLPurifier_Lexer_PH5P extends HTMLPurifier_Lexer_DOMLex public function tokenizeHTML($html, $config, $context) { $new_html = $this->normalize($html, $config, $context); - $new_html = $this->wrapHTML($new_html, $config, $context); + $new_html = $this->wrapHTML($new_html, $config, $context, false /* no div */); try { $parser = new HTML5($new_html); $doc = $parser->save(); @@ -34,10 +34,9 @@ class HTMLPurifier_Lexer_PH5P extends HTMLPurifier_Lexer_DOMLex $tokens = array(); $this->tokenizeDOM( $doc->getElementsByTagName('html')->item(0)-> // <html> - getElementsByTagName('body')->item(0)-> // <body> - getElementsByTagName('div')->item(0) // <div> + getElementsByTagName('body')->item(0) // <body> , - $tokens + $tokens, $config ); return $tokens; } @@ -1516,6 +1515,7 @@ class HTML5 // Consume the maximum number of characters possible, with the // consumed characters case-sensitively matching one of the // identifiers in the first column of the entities table. + $e_name = $this->characters('0-9A-Za-z;', $this->char + 1); $len = strlen($e_name); @@ -1548,7 +1548,7 @@ class HTML5 // Return a character token for the character corresponding to the // entity name (as given by the second column of the entities table). - return html_entity_decode('&' . $entity . ';', ENT_QUOTES, 'UTF-8'); + return html_entity_decode('&' . rtrim($entity, ';') . ';', ENT_QUOTES, 'UTF-8'); } private function emitToken($token) diff --git a/library/HTMLPurifier/Node.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node.php index 3995fec9f..3995fec9f 100644 --- a/library/HTMLPurifier/Node.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node.php diff --git a/library/HTMLPurifier/Node/Comment.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php index 38ba19394..38ba19394 100644 --- a/library/HTMLPurifier/Node/Comment.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php diff --git a/library/HTMLPurifier/Node/Element.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php index 6cbf56dad..6cbf56dad 100644 --- a/library/HTMLPurifier/Node/Element.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php diff --git a/library/HTMLPurifier/Node/Text.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php index aec916647..aec916647 100644 --- a/library/HTMLPurifier/Node/Text.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php diff --git a/library/HTMLPurifier/PercentEncoder.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/PercentEncoder.php index 18c8bbb00..18c8bbb00 100644 --- a/library/HTMLPurifier/PercentEncoder.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/PercentEncoder.php diff --git a/library/HTMLPurifier/Printer.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer.php index 549e4cea1..549e4cea1 100644 --- a/library/HTMLPurifier/Printer.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer.php diff --git a/library/HTMLPurifier/Printer/CSSDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php index 29505fe12..29505fe12 100644 --- a/library/HTMLPurifier/Printer/CSSDefinition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php diff --git a/library/HTMLPurifier/Printer/ConfigForm.css b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css index 3ff1a88aa..3ff1a88aa 100644 --- a/library/HTMLPurifier/Printer/ConfigForm.css +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css diff --git a/library/HTMLPurifier/Printer/ConfigForm.js b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js index cba00c9b8..cba00c9b8 100644 --- a/library/HTMLPurifier/Printer/ConfigForm.js +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js diff --git a/library/HTMLPurifier/Printer/ConfigForm.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php index 36100ce73..65a777904 100644 --- a/library/HTMLPurifier/Printer/ConfigForm.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php @@ -327,6 +327,10 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer case HTMLPurifier_VarParser::HASH: $nvalue = ''; foreach ($value as $i => $v) { + if (is_array($v)) { + // HACK + $v = implode(";", $v); + } $nvalue .= "$i:$v" . PHP_EOL; } $value = $nvalue; diff --git a/library/HTMLPurifier/Printer/HTMLDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php index 5f2f2f8a7..5f2f2f8a7 100644 --- a/library/HTMLPurifier/Printer/HTMLDefinition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php diff --git a/library/HTMLPurifier/PropertyList.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/PropertyList.php index 189348fd9..189348fd9 100644 --- a/library/HTMLPurifier/PropertyList.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/PropertyList.php diff --git a/library/HTMLPurifier/PropertyListIterator.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php index 15b330ea3..15b330ea3 100644 --- a/library/HTMLPurifier/PropertyListIterator.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php diff --git a/library/HTMLPurifier/Queue.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php index f58db9042..f58db9042 100644 --- a/library/HTMLPurifier/Queue.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php diff --git a/library/HTMLPurifier/Strategy.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy.php index e1ff3b72d..e1ff3b72d 100644 --- a/library/HTMLPurifier/Strategy.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy.php diff --git a/library/HTMLPurifier/Strategy/Composite.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Composite.php index d7d35ce7d..d7d35ce7d 100644 --- a/library/HTMLPurifier/Strategy/Composite.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Composite.php diff --git a/library/HTMLPurifier/Strategy/Core.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Core.php index 4414c17d6..4414c17d6 100644 --- a/library/HTMLPurifier/Strategy/Core.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Core.php diff --git a/library/HTMLPurifier/Strategy/FixNesting.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php index 6fa673db9..6fa673db9 100644 --- a/library/HTMLPurifier/Strategy/FixNesting.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php diff --git a/library/HTMLPurifier/Strategy/MakeWellFormed.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/MakeWellFormed.php index e389e0011..a6eb09e45 100644 --- a/library/HTMLPurifier/Strategy/MakeWellFormed.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/MakeWellFormed.php @@ -165,7 +165,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy if (empty($zipper->front)) break; $token = $zipper->prev($token); // indicate that other injectors should not process this token, - // but we need to reprocess it + // but we need to reprocess it. See Note [Injector skips] unset($token->skip[$i]); $token->rewind = $i; if ($token instanceof HTMLPurifier_Token_Start) { @@ -210,6 +210,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy if ($token instanceof HTMLPurifier_Token_Text) { foreach ($this->injectors as $i => $injector) { if (isset($token->skip[$i])) { + // See Note [Injector skips] continue; } if ($token->rewind !== null && $token->rewind !== $i) { @@ -367,6 +368,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy if ($ok) { foreach ($this->injectors as $i => $injector) { if (isset($token->skip[$i])) { + // See Note [Injector skips] continue; } if ($token->rewind !== null && $token->rewind !== $i) { @@ -422,6 +424,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy $token->start = $current_parent; foreach ($this->injectors as $i => $injector) { if (isset($token->skip[$i])) { + // See Note [Injector skips] continue; } if ($token->rewind !== null && $token->rewind !== $i) { @@ -534,12 +537,17 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy */ protected function processToken($token, $injector = -1) { + // Zend OpCache miscompiles $token = array($token), so + // avoid this pattern. See: https://github.com/ezyang/htmlpurifier/issues/108 + // normalize forms of token if (is_object($token)) { - $token = array(1, $token); + $tmp = $token; + $token = array(1, $tmp); } if (is_int($token)) { - $token = array($token); + $tmp = $token; + $token = array($tmp); } if ($token === false) { $token = array(1); @@ -561,7 +569,12 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy list($old, $r) = $this->zipper->splice($this->token, $delete, $token); if ($injector > -1) { - // determine appropriate skips + // See Note [Injector skips] + // Determine appropriate skips. Here's what the code does: + // *If* we deleted one or more tokens, copy the skips + // of those tokens into the skips of the new tokens (in $token). + // Also, mark the newly inserted tokens as having come from + // $injector. $oldskip = isset($old[0]) ? $old[0]->skip : array(); foreach ($token as $object) { $object->skip = $oldskip; @@ -597,4 +610,50 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy } } +// Note [Injector skips] +// ~~~~~~~~~~~~~~~~~~~~~ +// When I originally designed this class, the idea behind the 'skip' +// property of HTMLPurifier_Token was to help avoid infinite loops +// in injector processing. For example, suppose you wrote an injector +// that bolded swear words. Naively, you might write it so that +// whenever you saw ****, you replaced it with <strong>****</strong>. +// +// When this happens, we will reprocess all of the tokens with the +// other injectors. Now there is an opportunity for infinite loop: +// if we rerun the swear-word injector on these tokens, we might +// see **** and then reprocess again to get +// <strong><strong>****</strong></strong> ad infinitum. +// +// Thus, the idea of a skip is that once we process a token with +// an injector, we mark all of those tokens as having "come from" +// the injector, and we never run the injector again on these +// tokens. +// +// There were two more complications, however: +// +// - With HTMLPurifier_Injector_RemoveEmpty, we noticed that if +// you had <b><i></i></b>, after you removed the <i></i>, you +// really would like this injector to go back and reprocess +// the <b> tag, discovering that it is now empty and can be +// removed. So we reintroduced the possibility of infinite looping +// by adding a "rewind" function, which let you go back to an +// earlier point in the token stream and reprocess it with injectors. +// Needless to say, we need to UN-skip the token so it gets +// reprocessed. +// +// - Suppose that you successfuly process a token, replace it with +// one with your skip mark, but now another injector wants to +// process the skipped token with another token. Should you continue +// to skip that new token, or reprocess it? If you reprocess, +// you can end up with an infinite loop where one injector converts +// <a> to <b>, and then another injector converts it back. So +// we inherit the skips, but for some reason, I thought that we +// should inherit the skip from the first token of the token +// that we deleted. Why? Well, it seems to work OK. +// +// If I were to redesign this functionality, I would absolutely not +// go about doing it this way: the semantics are just not very well +// defined, and in any case you probably wanted to operate on trees, +// not token streams. + // vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/Strategy/RemoveForeignElements.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/RemoveForeignElements.php index 1a8149ecc..1a8149ecc 100644 --- a/library/HTMLPurifier/Strategy/RemoveForeignElements.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/RemoveForeignElements.php diff --git a/library/HTMLPurifier/Strategy/ValidateAttributes.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/ValidateAttributes.php index fbb3d27c8..fbb3d27c8 100644 --- a/library/HTMLPurifier/Strategy/ValidateAttributes.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/ValidateAttributes.php diff --git a/library/HTMLPurifier/StringHash.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/StringHash.php index c07370197..c07370197 100644 --- a/library/HTMLPurifier/StringHash.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/StringHash.php diff --git a/library/HTMLPurifier/StringHashParser.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/StringHashParser.php index 7c73f8083..7c73f8083 100644 --- a/library/HTMLPurifier/StringHashParser.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/StringHashParser.php diff --git a/library/HTMLPurifier/TagTransform.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform.php index 7b8d83343..7b8d83343 100644 --- a/library/HTMLPurifier/TagTransform.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform.php diff --git a/library/HTMLPurifier/TagTransform/Font.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Font.php index 7853d90bc..7853d90bc 100644 --- a/library/HTMLPurifier/TagTransform/Font.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Font.php diff --git a/library/HTMLPurifier/TagTransform/Simple.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Simple.php index 71bf10b91..71bf10b91 100644 --- a/library/HTMLPurifier/TagTransform/Simple.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Simple.php diff --git a/library/HTMLPurifier/Token.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token.php index 85b85e072..84d3619a3 100644 --- a/library/HTMLPurifier/Token.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token.php @@ -26,7 +26,7 @@ abstract class HTMLPurifier_Token public $armor = array(); /** - * Used during MakeWellFormed. + * Used during MakeWellFormed. See Note [Injector skips] * @type */ public $skip; diff --git a/library/HTMLPurifier/Token/Comment.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php index 23453c705..23453c705 100644 --- a/library/HTMLPurifier/Token/Comment.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php diff --git a/library/HTMLPurifier/Token/Empty.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Empty.php index 78a95f555..78a95f555 100644 --- a/library/HTMLPurifier/Token/Empty.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Empty.php diff --git a/library/HTMLPurifier/Token/End.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/End.php index 59b38fdc5..59b38fdc5 100644 --- a/library/HTMLPurifier/Token/End.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/End.php diff --git a/library/HTMLPurifier/Token/Start.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Start.php index 019f317ad..019f317ad 100644 --- a/library/HTMLPurifier/Token/Start.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Start.php diff --git a/library/HTMLPurifier/Token/Tag.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Tag.php index d643fa64e..d643fa64e 100644 --- a/library/HTMLPurifier/Token/Tag.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Tag.php diff --git a/library/HTMLPurifier/Token/Text.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Text.php index f26a1c211..f26a1c211 100644 --- a/library/HTMLPurifier/Token/Text.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Token/Text.php diff --git a/library/HTMLPurifier/TokenFactory.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php index dea2446b9..dea2446b9 100644 --- a/library/HTMLPurifier/TokenFactory.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php diff --git a/library/HTMLPurifier/URI.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URI.php index a5e7ae298..9c5be39d1 100644 --- a/library/HTMLPurifier/URI.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URI.php @@ -85,11 +85,13 @@ class HTMLPurifier_URI $def = $config->getDefinition('URI'); $scheme_obj = $def->getDefaultScheme($config, $context); if (!$scheme_obj) { - // something funky happened to the default scheme object - trigger_error( - 'Default scheme object "' . $def->defaultScheme . '" was not readable', - E_USER_WARNING - ); + if ($def->defaultScheme !== null) { + // something funky happened to the default scheme object + trigger_error( + 'Default scheme object "' . $def->defaultScheme . '" was not readable', + E_USER_WARNING + ); + } // suppress error if it's null return false; } } diff --git a/library/HTMLPurifier/URIDefinition.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIDefinition.php index e0bd8bcca..e0bd8bcca 100644 --- a/library/HTMLPurifier/URIDefinition.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIDefinition.php diff --git a/library/HTMLPurifier/URIFilter.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php index 09724e9f4..09724e9f4 100644 --- a/library/HTMLPurifier/URIFilter.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php diff --git a/library/HTMLPurifier/URIFilter/DisableExternal.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php index ced1b1376..ced1b1376 100644 --- a/library/HTMLPurifier/URIFilter/DisableExternal.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php diff --git a/library/HTMLPurifier/URIFilter/DisableExternalResources.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php index c6562169e..c6562169e 100644 --- a/library/HTMLPurifier/URIFilter/DisableExternalResources.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php diff --git a/library/HTMLPurifier/URIFilter/DisableResources.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php index d5c412c44..d5c412c44 100644 --- a/library/HTMLPurifier/URIFilter/DisableResources.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php diff --git a/library/HTMLPurifier/URIFilter/HostBlacklist.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php index a6645c17e..a6645c17e 100644 --- a/library/HTMLPurifier/URIFilter/HostBlacklist.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php diff --git a/library/HTMLPurifier/URIFilter/MakeAbsolute.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/MakeAbsolute.php index c507bbff8..c507bbff8 100644 --- a/library/HTMLPurifier/URIFilter/MakeAbsolute.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/MakeAbsolute.php diff --git a/library/HTMLPurifier/URIFilter/Munge.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php index 6e03315a1..6e03315a1 100644 --- a/library/HTMLPurifier/URIFilter/Munge.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php diff --git a/library/HTMLPurifier/URIFilter/SafeIframe.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php index f609c47a3..f609c47a3 100644 --- a/library/HTMLPurifier/URIFilter/SafeIframe.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php diff --git a/library/HTMLPurifier/URIParser.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIParser.php index 0e7381a07..0e7381a07 100644 --- a/library/HTMLPurifier/URIParser.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIParser.php diff --git a/library/HTMLPurifier/URIScheme.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php index fe9e82cf2..fe9e82cf2 100644 --- a/library/HTMLPurifier/URIScheme.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php diff --git a/library/HTMLPurifier/URIScheme/data.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/data.php index 6ebca4984..41c49d553 100644 --- a/library/HTMLPurifier/URIScheme/data.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/data.php @@ -79,9 +79,18 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme } else { $raw_data = $data; } + if ( strlen($raw_data) < 12 ) { + // error; exif_imagetype throws exception with small files, + // and this likely indicates a corrupt URI/failed parse anyway + return false; + } // XXX probably want to refactor this into a general mechanism // for filtering arbitrary content types - $file = tempnam("/tmp", ""); + if (function_exists('sys_get_temp_dir')) { + $file = tempnam(sys_get_temp_dir(), ""); + } else { + $file = tempnam("/tmp", ""); + } file_put_contents($file, $raw_data); if (function_exists('exif_imagetype')) { $image_code = exif_imagetype($file); diff --git a/library/HTMLPurifier/URIScheme/file.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php index 215be4ba8..215be4ba8 100644 --- a/library/HTMLPurifier/URIScheme/file.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php diff --git a/library/HTMLPurifier/URIScheme/ftp.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/ftp.php index 1eb43ee5c..1eb43ee5c 100644 --- a/library/HTMLPurifier/URIScheme/ftp.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/ftp.php diff --git a/library/HTMLPurifier/URIScheme/http.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/http.php index ce69ec438..ce69ec438 100644 --- a/library/HTMLPurifier/URIScheme/http.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/http.php diff --git a/library/HTMLPurifier/URIScheme/https.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/https.php index 0e96882db..0e96882db 100644 --- a/library/HTMLPurifier/URIScheme/https.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/https.php diff --git a/library/HTMLPurifier/URIScheme/mailto.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/mailto.php index c3a6b602a..c3a6b602a 100644 --- a/library/HTMLPurifier/URIScheme/mailto.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/mailto.php diff --git a/library/HTMLPurifier/URIScheme/news.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php index 7490927d6..7490927d6 100644 --- a/library/HTMLPurifier/URIScheme/news.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php diff --git a/library/HTMLPurifier/URIScheme/nntp.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php index f211d715e..f211d715e 100644 --- a/library/HTMLPurifier/URIScheme/nntp.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php diff --git a/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php new file mode 100644 index 000000000..8cd193352 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/tel.php @@ -0,0 +1,46 @@ +<?php + +/** + * Validates tel (for phone numbers). + * + * The relevant specifications for this protocol are RFC 3966 and RFC 5341, + * but this class takes a much simpler approach: we normalize phone + * numbers so that they only include (possibly) a leading plus, + * and then any number of digits and x'es. + */ + +class HTMLPurifier_URIScheme_tel extends HTMLPurifier_URIScheme +{ + /** + * @type bool + */ + public $browsable = false; + + /** + * @type bool + */ + public $may_omit_host = true; + + /** + * @param HTMLPurifier_URI $uri + * @param HTMLPurifier_Config $config + * @param HTMLPurifier_Context $context + * @return bool + */ + public function doValidate(&$uri, $config, $context) + { + $uri->userinfo = null; + $uri->host = null; + $uri->port = null; + + // Delete all non-numeric characters, non-x characters + // from phone number, EXCEPT for a leading plus sign. + $uri->path = preg_replace('/(?!^\+)[^\dx]/', '', + // Normalize e(x)tension to lower-case + str_replace('X', 'x', $uri->path)); + + return true; + } +} + +// vim: et sw=4 sts=4 diff --git a/library/HTMLPurifier/URISchemeRegistry.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php index 4ac8a0b76..4ac8a0b76 100644 --- a/library/HTMLPurifier/URISchemeRegistry.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php diff --git a/library/HTMLPurifier/UnitConverter.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php index 166f3bf30..166f3bf30 100644 --- a/library/HTMLPurifier/UnitConverter.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php diff --git a/library/HTMLPurifier/VarParser.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php index 50cba6910..50cba6910 100644 --- a/library/HTMLPurifier/VarParser.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php diff --git a/library/HTMLPurifier/VarParser/Flexible.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php index b15016c5b..b15016c5b 100644 --- a/library/HTMLPurifier/VarParser/Flexible.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php diff --git a/library/HTMLPurifier/VarParser/Native.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php index f11c318ef..f11c318ef 100644 --- a/library/HTMLPurifier/VarParser/Native.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php diff --git a/library/HTMLPurifier/VarParserException.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParserException.php index 5df341495..5df341495 100644 --- a/library/HTMLPurifier/VarParserException.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/VarParserException.php diff --git a/library/HTMLPurifier/Zipper.php b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php index 6e21ea070..6e21ea070 100644 --- a/library/HTMLPurifier/Zipper.php +++ b/vendor/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php diff --git a/vendor/ezyang/htmlpurifier/maintenance/.htaccess b/vendor/ezyang/htmlpurifier/maintenance/.htaccess new file mode 100644 index 000000000..3a4288278 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/vendor/ezyang/htmlpurifier/maintenance/PH5P.patch b/vendor/ezyang/htmlpurifier/maintenance/PH5P.patch new file mode 100644 index 000000000..763709509 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/PH5P.patch @@ -0,0 +1,102 @@ +--- C:\Users\Edward\Webs\htmlpurifier\maintenance\PH5P.php 2008-07-07 09:12:12.000000000 -0400 ++++ C:\Users\Edward\Webs\htmlpurifier\maintenance/PH5P.new.php 2008-12-06 02:29:34.988800000 -0500 +@@ -65,7 +65,7 @@ + + public function __construct($data) { + $data = str_replace("\r\n", "\n", $data); +- $date = str_replace("\r", null, $data); ++ $data = str_replace("\r", null, $data); + + $this->data = $data; + $this->char = -1; +@@ -211,7 +211,10 @@ + // If nothing is returned, emit a U+0026 AMPERSAND character token. + // Otherwise, emit the character token that was returned. + $char = (!$entity) ? '&' : $entity; +- $this->emitToken($char); ++ $this->emitToken(array( ++ 'type' => self::CHARACTR, ++ 'data' => $char ++ )); + + // Finally, switch to the data state. + $this->state = 'data'; +@@ -708,7 +711,7 @@ + } elseif($char === '&') { + /* U+0026 AMPERSAND (&) + Switch to the entity in attribute value state. */ +- $this->entityInAttributeValueState('non'); ++ $this->entityInAttributeValueState(); + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) +@@ -738,7 +741,8 @@ + ? '&' + : $entity; + +- $this->emitToken($char); ++ $last = count($this->token['attr']) - 1; ++ $this->token['attr'][$last]['value'] .= $char; + } + + private function bogusCommentState() { +@@ -1066,6 +1070,11 @@ + $this->char++; + + if(in_array($id, $this->entities)) { ++ if ($e_name[$c-1] !== ';') { ++ if ($c < $len && $e_name[$c] == ';') { ++ $this->char++; // consume extra semicolon ++ } ++ } + $entity = $id; + break; + } +@@ -2084,7 +2093,7 @@ + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + +- $this->insertElement($token); ++ $this->insertElement($token, true, true); + break; + } + break; +@@ -3465,7 +3474,18 @@ + } + } + +- private function insertElement($token, $append = true) { ++ private function insertElement($token, $append = true, $check = false) { ++ // Proprietary workaround for libxml2's limitations with tag names ++ if ($check) { ++ // Slightly modified HTML5 tag-name modification, ++ // removing anything that's not an ASCII letter, digit, or hyphen ++ $token['name'] = preg_replace('/[^a-z0-9-]/i', '', $token['name']); ++ // Remove leading hyphens and numbers ++ $token['name'] = ltrim($token['name'], '-0..9'); ++ // In theory, this should ever be needed, but just in case ++ if ($token['name'] === '') $token['name'] = 'span'; // arbitrary generic choice ++ } ++ + $el = $this->dom->createElement($token['name']); + + foreach($token['attr'] as $attr) { +@@ -3659,7 +3679,7 @@ + } + } + +- private function generateImpliedEndTags(array $exclude = array()) { ++ private function generateImpliedEndTags($exclude = array()) { + /* When the steps below require the UA to generate implied end tags, + then, if the current node is a dd element, a dt element, an li element, + a p element, a td element, a th element, or a tr element, the UA must +@@ -3673,7 +3693,8 @@ + } + } + +- private function getElementCategory($name) { ++ private function getElementCategory($node) { ++ $name = $node->tagName; + if(in_array($name, $this->special)) + return self::SPECIAL; + diff --git a/vendor/ezyang/htmlpurifier/maintenance/PH5P.php b/vendor/ezyang/htmlpurifier/maintenance/PH5P.php new file mode 100644 index 000000000..9d83dcbf5 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/PH5P.php @@ -0,0 +1,3889 @@ +<?php +class HTML5 +{ + private $data; + private $char; + private $EOF; + private $state; + private $tree; + private $token; + private $content_model; + private $escape = false; + private $entities = array('AElig;','AElig','AMP;','AMP','Aacute;','Aacute', + 'Acirc;','Acirc','Agrave;','Agrave','Alpha;','Aring;','Aring','Atilde;', + 'Atilde','Auml;','Auml','Beta;','COPY;','COPY','Ccedil;','Ccedil','Chi;', + 'Dagger;','Delta;','ETH;','ETH','Eacute;','Eacute','Ecirc;','Ecirc','Egrave;', + 'Egrave','Epsilon;','Eta;','Euml;','Euml','GT;','GT','Gamma;','Iacute;', + 'Iacute','Icirc;','Icirc','Igrave;','Igrave','Iota;','Iuml;','Iuml','Kappa;', + 'LT;','LT','Lambda;','Mu;','Ntilde;','Ntilde','Nu;','OElig;','Oacute;', + 'Oacute','Ocirc;','Ocirc','Ograve;','Ograve','Omega;','Omicron;','Oslash;', + 'Oslash','Otilde;','Otilde','Ouml;','Ouml','Phi;','Pi;','Prime;','Psi;', + 'QUOT;','QUOT','REG;','REG','Rho;','Scaron;','Sigma;','THORN;','THORN', + 'TRADE;','Tau;','Theta;','Uacute;','Uacute','Ucirc;','Ucirc','Ugrave;', + 'Ugrave','Upsilon;','Uuml;','Uuml','Xi;','Yacute;','Yacute','Yuml;','Zeta;', + 'aacute;','aacute','acirc;','acirc','acute;','acute','aelig;','aelig', + 'agrave;','agrave','alefsym;','alpha;','amp;','amp','and;','ang;','apos;', + 'aring;','aring','asymp;','atilde;','atilde','auml;','auml','bdquo;','beta;', + 'brvbar;','brvbar','bull;','cap;','ccedil;','ccedil','cedil;','cedil', + 'cent;','cent','chi;','circ;','clubs;','cong;','copy;','copy','crarr;', + 'cup;','curren;','curren','dArr;','dagger;','darr;','deg;','deg','delta;', + 'diams;','divide;','divide','eacute;','eacute','ecirc;','ecirc','egrave;', + 'egrave','empty;','emsp;','ensp;','epsilon;','equiv;','eta;','eth;','eth', + 'euml;','euml','euro;','exist;','fnof;','forall;','frac12;','frac12', + 'frac14;','frac14','frac34;','frac34','frasl;','gamma;','ge;','gt;','gt', + 'hArr;','harr;','hearts;','hellip;','iacute;','iacute','icirc;','icirc', + 'iexcl;','iexcl','igrave;','igrave','image;','infin;','int;','iota;', + 'iquest;','iquest','isin;','iuml;','iuml','kappa;','lArr;','lambda;','lang;', + 'laquo;','laquo','larr;','lceil;','ldquo;','le;','lfloor;','lowast;','loz;', + 'lrm;','lsaquo;','lsquo;','lt;','lt','macr;','macr','mdash;','micro;','micro', + 'middot;','middot','minus;','mu;','nabla;','nbsp;','nbsp','ndash;','ne;', + 'ni;','not;','not','notin;','nsub;','ntilde;','ntilde','nu;','oacute;', + 'oacute','ocirc;','ocirc','oelig;','ograve;','ograve','oline;','omega;', + 'omicron;','oplus;','or;','ordf;','ordf','ordm;','ordm','oslash;','oslash', + 'otilde;','otilde','otimes;','ouml;','ouml','para;','para','part;','permil;', + 'perp;','phi;','pi;','piv;','plusmn;','plusmn','pound;','pound','prime;', + 'prod;','prop;','psi;','quot;','quot','rArr;','radic;','rang;','raquo;', + 'raquo','rarr;','rceil;','rdquo;','real;','reg;','reg','rfloor;','rho;', + 'rlm;','rsaquo;','rsquo;','sbquo;','scaron;','sdot;','sect;','sect','shy;', + 'shy','sigma;','sigmaf;','sim;','spades;','sub;','sube;','sum;','sup1;', + 'sup1','sup2;','sup2','sup3;','sup3','sup;','supe;','szlig;','szlig','tau;', + 'there4;','theta;','thetasym;','thinsp;','thorn;','thorn','tilde;','times;', + 'times','trade;','uArr;','uacute;','uacute','uarr;','ucirc;','ucirc', + 'ugrave;','ugrave','uml;','uml','upsih;','upsilon;','uuml;','uuml','weierp;', + 'xi;','yacute;','yacute','yen;','yen','yuml;','yuml','zeta;','zwj;','zwnj;'); + + const PCDATA = 0; + const RCDATA = 1; + const CDATA = 2; + const PLAINTEXT = 3; + + const DOCTYPE = 0; + const STARTTAG = 1; + const ENDTAG = 2; + const COMMENT = 3; + const CHARACTR = 4; + const EOF = 5; + + public function __construct($data) + { + $data = str_replace("\r\n", "\n", $data); + $date = str_replace("\r", null, $data); + + $this->data = $data; + $this->char = -1; + $this->EOF = strlen($data); + $this->tree = new HTML5TreeConstructer; + $this->content_model = self::PCDATA; + + $this->state = 'data'; + + while($this->state !== null) { + $this->{$this->state.'State'}(); + } + } + + public function save() + { + return $this->tree->save(); + } + + private function char() + { + return ($this->char < $this->EOF) + ? $this->data[$this->char] + : false; + } + + private function character($s, $l = 0) + { + if($s + $l < $this->EOF) { + if($l === 0) { + return $this->data[$s]; + } else { + return substr($this->data, $s, $l); + } + } + } + + private function characters($char_class, $start) + { + return preg_replace('#^(['.$char_class.']+).*#s', '\\1', substr($this->data, $start)); + } + + private function dataState() + { + // Consume the next input character + $this->char++; + $char = $this->char(); + + if($char === '&' && ($this->content_model === self::PCDATA || $this->content_model === self::RCDATA)) { + /* U+0026 AMPERSAND (&) + When the content model flag is set to one of the PCDATA or RCDATA + states: switch to the entity data state. Otherwise: treat it as per + the "anything else" entry below. */ + $this->state = 'entityData'; + + } elseif($char === '-') { + /* If the content model flag is set to either the RCDATA state or + the CDATA state, and the escape flag is false, and there are at + least three characters before this one in the input stream, and the + last four characters in the input stream, including this one, are + U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS, + and U+002D HYPHEN-MINUS ("<!--"), then set the escape flag to true. */ + if(($this->content_model === self::RCDATA || $this->content_model === + self::CDATA) && $this->escape === false && + $this->char >= 3 && $this->character($this->char - 4, 4) === '<!--') { + $this->escape = true; + } + + /* In any case, emit the input character as a character token. Stay + in the data state. */ + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => $char + )); + + /* U+003C LESS-THAN SIGN (<) */ + } elseif($char === '<' && ($this->content_model === self::PCDATA || + (($this->content_model === self::RCDATA || + $this->content_model === self::CDATA) && $this->escape === false))) { + /* When the content model flag is set to the PCDATA state: switch + to the tag open state. + + When the content model flag is set to either the RCDATA state or + the CDATA state and the escape flag is false: switch to the tag + open state. + + Otherwise: treat it as per the "anything else" entry below. */ + $this->state = 'tagOpen'; + + /* U+003E GREATER-THAN SIGN (>) */ + } elseif($char === '>') { + /* If the content model flag is set to either the RCDATA state or + the CDATA state, and the escape flag is true, and the last three + characters in the input stream including this one are U+002D + HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN ("-->"), + set the escape flag to false. */ + if(($this->content_model === self::RCDATA || + $this->content_model === self::CDATA) && $this->escape === true && + $this->character($this->char, 3) === '-->') { + $this->escape = false; + } + + /* In any case, emit the input character as a character token. + Stay in the data state. */ + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => $char + )); + + } elseif($this->char === $this->EOF) { + /* EOF + Emit an end-of-file token. */ + $this->EOF(); + + } elseif($this->content_model === self::PLAINTEXT) { + /* When the content model flag is set to the PLAINTEXT state + THIS DIFFERS GREATLY FROM THE SPEC: Get the remaining characters of + the text and emit it as a character token. */ + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => substr($this->data, $this->char) + )); + + $this->EOF(); + + } else { + /* Anything else + THIS DIFFERS GREATLY FROM THE SPEC: Get as many character that + otherwise would also be treated as a character token and emit it + as a single character token. Stay in the data state. */ + $len = strcspn($this->data, '<&', $this->char); + $char = substr($this->data, $this->char, $len); + $this->char += $len - 1; + + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => $char + )); + + $this->state = 'data'; + } + } + + private function entityDataState() + { + // Attempt to consume an entity. + $entity = $this->entity(); + + // If nothing is returned, emit a U+0026 AMPERSAND character token. + // Otherwise, emit the character token that was returned. + $char = (!$entity) ? '&' : $entity; + $this->emitToken($char); + + // Finally, switch to the data state. + $this->state = 'data'; + } + + private function tagOpenState() + { + switch($this->content_model) { + case self::RCDATA: + case self::CDATA: + /* If the next input character is a U+002F SOLIDUS (/) character, + consume it and switch to the close tag open state. If the next + input character is not a U+002F SOLIDUS (/) character, emit a + U+003C LESS-THAN SIGN character token and switch to the data + state to process the next input character. */ + if($this->character($this->char + 1) === '/') { + $this->char++; + $this->state = 'closeTagOpen'; + + } else { + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => '<' + )); + + $this->state = 'data'; + } + break; + + case self::PCDATA: + // If the content model flag is set to the PCDATA state + // Consume the next input character: + $this->char++; + $char = $this->char(); + + if($char === '!') { + /* U+0021 EXCLAMATION MARK (!) + Switch to the markup declaration open state. */ + $this->state = 'markupDeclarationOpen'; + + } elseif($char === '/') { + /* U+002F SOLIDUS (/) + Switch to the close tag open state. */ + $this->state = 'closeTagOpen'; + + } elseif(preg_match('/^[A-Za-z]$/', $char)) { + /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z + Create a new start tag token, set its tag name to the lowercase + version of the input character (add 0x0020 to the character's code + point), then switch to the tag name state. (Don't emit the token + yet; further details will be filled in before it is emitted.) */ + $this->token = array( + 'name' => strtolower($char), + 'type' => self::STARTTAG, + 'attr' => array() + ); + + $this->state = 'tagName'; + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Parse error. Emit a U+003C LESS-THAN SIGN character token and a + U+003E GREATER-THAN SIGN character token. Switch to the data state. */ + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => '<>' + )); + + $this->state = 'data'; + + } elseif($char === '?') { + /* U+003F QUESTION MARK (?) + Parse error. Switch to the bogus comment state. */ + $this->state = 'bogusComment'; + + } else { + /* Anything else + Parse error. Emit a U+003C LESS-THAN SIGN character token and + reconsume the current input character in the data state. */ + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => '<' + )); + + $this->char--; + $this->state = 'data'; + } + break; + } + } + + private function closeTagOpenState() + { + $next_node = strtolower($this->characters('A-Za-z', $this->char + 1)); + $the_same = count($this->tree->stack) > 0 && $next_node === end($this->tree->stack)->nodeName; + + if(($this->content_model === self::RCDATA || $this->content_model === self::CDATA) && + (!$the_same || ($the_same && (!preg_match('/[\t\n\x0b\x0c >\/]/', + $this->character($this->char + 1 + strlen($next_node))) || $this->EOF === $this->char)))) { + /* If the content model flag is set to the RCDATA or CDATA states then + examine the next few characters. If they do not match the tag name of + the last start tag token emitted (case insensitively), or if they do but + they are not immediately followed by one of the following characters: + * U+0009 CHARACTER TABULATION + * U+000A LINE FEED (LF) + * U+000B LINE TABULATION + * U+000C FORM FEED (FF) + * U+0020 SPACE + * U+003E GREATER-THAN SIGN (>) + * U+002F SOLIDUS (/) + * EOF + ...then there is a parse error. Emit a U+003C LESS-THAN SIGN character + token, a U+002F SOLIDUS character token, and switch to the data state + to process the next input character. */ + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => '</' + )); + + $this->state = 'data'; + + } else { + /* Otherwise, if the content model flag is set to the PCDATA state, + or if the next few characters do match that tag name, consume the + next input character: */ + $this->char++; + $char = $this->char(); + + if(preg_match('/^[A-Za-z]$/', $char)) { + /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z + Create a new end tag token, set its tag name to the lowercase version + of the input character (add 0x0020 to the character's code point), then + switch to the tag name state. (Don't emit the token yet; further details + will be filled in before it is emitted.) */ + $this->token = array( + 'name' => strtolower($char), + 'type' => self::ENDTAG + ); + + $this->state = 'tagName'; + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Parse error. Switch to the data state. */ + $this->state = 'data'; + + } elseif($this->char === $this->EOF) { + /* EOF + Parse error. Emit a U+003C LESS-THAN SIGN character token and a U+002F + SOLIDUS character token. Reconsume the EOF character in the data state. */ + $this->emitToken(array( + 'type' => self::CHARACTR, + 'data' => '</' + )); + + $this->char--; + $this->state = 'data'; + + } else { + /* Parse error. Switch to the bogus comment state. */ + $this->state = 'bogusComment'; + } + } + } + + private function tagNameState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + /* U+0009 CHARACTER TABULATION + U+000A LINE FEED (LF) + U+000B LINE TABULATION + U+000C FORM FEED (FF) + U+0020 SPACE + Switch to the before attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Emit the current tag token. Switch to the data state. */ + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif($this->char === $this->EOF) { + /* EOF + Parse error. Emit the current tag token. Reconsume the EOF + character in the data state. */ + $this->emitToken($this->token); + + $this->char--; + $this->state = 'data'; + + } elseif($char === '/') { + /* U+002F SOLIDUS (/) + Parse error unless this is a permitted slash. Switch to the before + attribute name state. */ + $this->state = 'beforeAttributeName'; + + } else { + /* Anything else + Append the current input character to the current tag token's tag name. + Stay in the tag name state. */ + $this->token['name'] .= strtolower($char); + $this->state = 'tagName'; + } + } + + private function beforeAttributeNameState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + /* U+0009 CHARACTER TABULATION + U+000A LINE FEED (LF) + U+000B LINE TABULATION + U+000C FORM FEED (FF) + U+0020 SPACE + Stay in the before attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Emit the current tag token. Switch to the data state. */ + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif($char === '/') { + /* U+002F SOLIDUS (/) + Parse error unless this is a permitted slash. Stay in the before + attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($this->char === $this->EOF) { + /* EOF + Parse error. Emit the current tag token. Reconsume the EOF + character in the data state. */ + $this->emitToken($this->token); + + $this->char--; + $this->state = 'data'; + + } else { + /* Anything else + Start a new attribute in the current tag token. Set that attribute's + name to the current input character, and its value to the empty string. + Switch to the attribute name state. */ + $this->token['attr'][] = array( + 'name' => strtolower($char), + 'value' => null + ); + + $this->state = 'attributeName'; + } + } + + private function attributeNameState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + /* U+0009 CHARACTER TABULATION + U+000A LINE FEED (LF) + U+000B LINE TABULATION + U+000C FORM FEED (FF) + U+0020 SPACE + Stay in the before attribute name state. */ + $this->state = 'afterAttributeName'; + + } elseif($char === '=') { + /* U+003D EQUALS SIGN (=) + Switch to the before attribute value state. */ + $this->state = 'beforeAttributeValue'; + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Emit the current tag token. Switch to the data state. */ + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif($char === '/' && $this->character($this->char + 1) !== '>') { + /* U+002F SOLIDUS (/) + Parse error unless this is a permitted slash. Switch to the before + attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($this->char === $this->EOF) { + /* EOF + Parse error. Emit the current tag token. Reconsume the EOF + character in the data state. */ + $this->emitToken($this->token); + + $this->char--; + $this->state = 'data'; + + } else { + /* Anything else + Append the current input character to the current attribute's name. + Stay in the attribute name state. */ + $last = count($this->token['attr']) - 1; + $this->token['attr'][$last]['name'] .= strtolower($char); + + $this->state = 'attributeName'; + } + } + + private function afterAttributeNameState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + /* U+0009 CHARACTER TABULATION + U+000A LINE FEED (LF) + U+000B LINE TABULATION + U+000C FORM FEED (FF) + U+0020 SPACE + Stay in the after attribute name state. */ + $this->state = 'afterAttributeName'; + + } elseif($char === '=') { + /* U+003D EQUALS SIGN (=) + Switch to the before attribute value state. */ + $this->state = 'beforeAttributeValue'; + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Emit the current tag token. Switch to the data state. */ + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif($char === '/' && $this->character($this->char + 1) !== '>') { + /* U+002F SOLIDUS (/) + Parse error unless this is a permitted slash. Switch to the + before attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($this->char === $this->EOF) { + /* EOF + Parse error. Emit the current tag token. Reconsume the EOF + character in the data state. */ + $this->emitToken($this->token); + + $this->char--; + $this->state = 'data'; + + } else { + /* Anything else + Start a new attribute in the current tag token. Set that attribute's + name to the current input character, and its value to the empty string. + Switch to the attribute name state. */ + $this->token['attr'][] = array( + 'name' => strtolower($char), + 'value' => null + ); + + $this->state = 'attributeName'; + } + } + + private function beforeAttributeValueState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + /* U+0009 CHARACTER TABULATION + U+000A LINE FEED (LF) + U+000B LINE TABULATION + U+000C FORM FEED (FF) + U+0020 SPACE + Stay in the before attribute value state. */ + $this->state = 'beforeAttributeValue'; + + } elseif($char === '"') { + /* U+0022 QUOTATION MARK (") + Switch to the attribute value (double-quoted) state. */ + $this->state = 'attributeValueDoubleQuoted'; + + } elseif($char === '&') { + /* U+0026 AMPERSAND (&) + Switch to the attribute value (unquoted) state and reconsume + this input character. */ + $this->char--; + $this->state = 'attributeValueUnquoted'; + + } elseif($char === '\'') { + /* U+0027 APOSTROPHE (') + Switch to the attribute value (single-quoted) state. */ + $this->state = 'attributeValueSingleQuoted'; + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Emit the current tag token. Switch to the data state. */ + $this->emitToken($this->token); + $this->state = 'data'; + + } else { + /* Anything else + Append the current input character to the current attribute's value. + Switch to the attribute value (unquoted) state. */ + $last = count($this->token['attr']) - 1; + $this->token['attr'][$last]['value'] .= $char; + + $this->state = 'attributeValueUnquoted'; + } + } + + private function attributeValueDoubleQuotedState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if($char === '"') { + /* U+0022 QUOTATION MARK (") + Switch to the before attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($char === '&') { + /* U+0026 AMPERSAND (&) + Switch to the entity in attribute value state. */ + $this->entityInAttributeValueState('double'); + + } elseif($this->char === $this->EOF) { + /* EOF + Parse error. Emit the current tag token. Reconsume the character + in the data state. */ + $this->emitToken($this->token); + + $this->char--; + $this->state = 'data'; + + } else { + /* Anything else + Append the current input character to the current attribute's value. + Stay in the attribute value (double-quoted) state. */ + $last = count($this->token['attr']) - 1; + $this->token['attr'][$last]['value'] .= $char; + + $this->state = 'attributeValueDoubleQuoted'; + } + } + + private function attributeValueSingleQuotedState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if($char === '\'') { + /* U+0022 QUOTATION MARK (') + Switch to the before attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($char === '&') { + /* U+0026 AMPERSAND (&) + Switch to the entity in attribute value state. */ + $this->entityInAttributeValueState('single'); + + } elseif($this->char === $this->EOF) { + /* EOF + Parse error. Emit the current tag token. Reconsume the character + in the data state. */ + $this->emitToken($this->token); + + $this->char--; + $this->state = 'data'; + + } else { + /* Anything else + Append the current input character to the current attribute's value. + Stay in the attribute value (single-quoted) state. */ + $last = count($this->token['attr']) - 1; + $this->token['attr'][$last]['value'] .= $char; + + $this->state = 'attributeValueSingleQuoted'; + } + } + + private function attributeValueUnquotedState() + { + // Consume the next input character: + $this->char++; + $char = $this->character($this->char); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + /* U+0009 CHARACTER TABULATION + U+000A LINE FEED (LF) + U+000B LINE TABULATION + U+000C FORM FEED (FF) + U+0020 SPACE + Switch to the before attribute name state. */ + $this->state = 'beforeAttributeName'; + + } elseif($char === '&') { + /* U+0026 AMPERSAND (&) + Switch to the entity in attribute value state. */ + $this->entityInAttributeValueState('non'); + + } elseif($char === '>') { + /* U+003E GREATER-THAN SIGN (>) + Emit the current tag token. Switch to the data state. */ + $this->emitToken($this->token); + $this->state = 'data'; + + } else { + /* Anything else + Append the current input character to the current attribute's value. + Stay in the attribute value (unquoted) state. */ + $last = count($this->token['attr']) - 1; + $this->token['attr'][$last]['value'] .= $char; + + $this->state = 'attributeValueUnquoted'; + } + } + + private function entityInAttributeValueState() + { + // Attempt to consume an entity. + $entity = $this->entity(); + + // If nothing is returned, append a U+0026 AMPERSAND character to the + // current attribute's value. Otherwise, emit the character token that + // was returned. + $char = (!$entity) + ? '&' + : $entity; + + $this->emitToken($char); + } + + private function bogusCommentState() + { + /* Consume every character up to the first U+003E GREATER-THAN SIGN + character (>) or the end of the file (EOF), whichever comes first. Emit + a comment token whose data is the concatenation of all the characters + starting from and including the character that caused the state machine + to switch into the bogus comment state, up to and including the last + consumed character before the U+003E character, if any, or up to the + end of the file otherwise. (If the comment was started by the end of + the file (EOF), the token is empty.) */ + $data = $this->characters('^>', $this->char); + $this->emitToken(array( + 'data' => $data, + 'type' => self::COMMENT + )); + + $this->char += strlen($data); + + /* Switch to the data state. */ + $this->state = 'data'; + + /* If the end of the file was reached, reconsume the EOF character. */ + if($this->char === $this->EOF) { + $this->char = $this->EOF - 1; + } + } + + private function markupDeclarationOpenState() + { + /* If the next two characters are both U+002D HYPHEN-MINUS (-) + characters, consume those two characters, create a comment token whose + data is the empty string, and switch to the comment state. */ + if($this->character($this->char + 1, 2) === '--') { + $this->char += 2; + $this->state = 'comment'; + $this->token = array( + 'data' => null, + 'type' => self::COMMENT + ); + + /* Otherwise if the next seven chacacters are a case-insensitive match + for the word "DOCTYPE", then consume those characters and switch to the + DOCTYPE state. */ + } elseif(strtolower($this->character($this->char + 1, 7)) === 'doctype') { + $this->char += 7; + $this->state = 'doctype'; + + /* Otherwise, is is a parse error. Switch to the bogus comment state. + The next character that is consumed, if any, is the first character + that will be in the comment. */ + } else { + $this->char++; + $this->state = 'bogusComment'; + } + } + + private function commentState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + /* U+002D HYPHEN-MINUS (-) */ + if($char === '-') { + /* Switch to the comment dash state */ + $this->state = 'commentDash'; + + /* EOF */ + } elseif($this->char === $this->EOF) { + /* Parse error. Emit the comment token. Reconsume the EOF character + in the data state. */ + $this->emitToken($this->token); + $this->char--; + $this->state = 'data'; + + /* Anything else */ + } else { + /* Append the input character to the comment token's data. Stay in + the comment state. */ + $this->token['data'] .= $char; + } + } + + private function commentDashState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + /* U+002D HYPHEN-MINUS (-) */ + if($char === '-') { + /* Switch to the comment end state */ + $this->state = 'commentEnd'; + + /* EOF */ + } elseif($this->char === $this->EOF) { + /* Parse error. Emit the comment token. Reconsume the EOF character + in the data state. */ + $this->emitToken($this->token); + $this->char--; + $this->state = 'data'; + + /* Anything else */ + } else { + /* Append a U+002D HYPHEN-MINUS (-) character and the input + character to the comment token's data. Switch to the comment state. */ + $this->token['data'] .= '-'.$char; + $this->state = 'comment'; + } + } + + private function commentEndState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + if($char === '>') { + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif($char === '-') { + $this->token['data'] .= '-'; + + } elseif($this->char === $this->EOF) { + $this->emitToken($this->token); + $this->char--; + $this->state = 'data'; + + } else { + $this->token['data'] .= '--'.$char; + $this->state = 'comment'; + } + } + + private function doctypeState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + $this->state = 'beforeDoctypeName'; + + } else { + $this->char--; + $this->state = 'beforeDoctypeName'; + } + } + + private function beforeDoctypeNameState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + // Stay in the before DOCTYPE name state. + + } elseif(preg_match('/^[a-z]$/', $char)) { + $this->token = array( + 'name' => strtoupper($char), + 'type' => self::DOCTYPE, + 'error' => true + ); + + $this->state = 'doctypeName'; + + } elseif($char === '>') { + $this->emitToken(array( + 'name' => null, + 'type' => self::DOCTYPE, + 'error' => true + )); + + $this->state = 'data'; + + } elseif($this->char === $this->EOF) { + $this->emitToken(array( + 'name' => null, + 'type' => self::DOCTYPE, + 'error' => true + )); + + $this->char--; + $this->state = 'data'; + + } else { + $this->token = array( + 'name' => $char, + 'type' => self::DOCTYPE, + 'error' => true + ); + + $this->state = 'doctypeName'; + } + } + + private function doctypeNameState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + $this->state = 'AfterDoctypeName'; + + } elseif($char === '>') { + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif(preg_match('/^[a-z]$/', $char)) { + $this->token['name'] .= strtoupper($char); + + } elseif($this->char === $this->EOF) { + $this->emitToken($this->token); + $this->char--; + $this->state = 'data'; + + } else { + $this->token['name'] .= $char; + } + + $this->token['error'] = ($this->token['name'] === 'HTML') + ? false + : true; + } + + private function afterDoctypeNameState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) { + // Stay in the DOCTYPE name state. + + } elseif($char === '>') { + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif($this->char === $this->EOF) { + $this->emitToken($this->token); + $this->char--; + $this->state = 'data'; + + } else { + $this->token['error'] = true; + $this->state = 'bogusDoctype'; + } + } + + private function bogusDoctypeState() + { + /* Consume the next input character: */ + $this->char++; + $char = $this->char(); + + if($char === '>') { + $this->emitToken($this->token); + $this->state = 'data'; + + } elseif($this->char === $this->EOF) { + $this->emitToken($this->token); + $this->char--; + $this->state = 'data'; + + } else { + // Stay in the bogus DOCTYPE state. + } + } + + private function entity() + { + $start = $this->char; + + // This section defines how to consume an entity. This definition is + // used when parsing entities in text and in attributes. + + // The behaviour depends on the identity of the next character (the + // one immediately after the U+0026 AMPERSAND character): + + switch($this->character($this->char + 1)) { + // U+0023 NUMBER SIGN (#) + case '#': + + // The behaviour further depends on the character after the + // U+0023 NUMBER SIGN: + switch($this->character($this->char + 1)) { + // U+0078 LATIN SMALL LETTER X + // U+0058 LATIN CAPITAL LETTER X + case 'x': + case 'X': + // Follow the steps below, but using the range of + // characters U+0030 DIGIT ZERO through to U+0039 DIGIT + // NINE, U+0061 LATIN SMALL LETTER A through to U+0066 + // LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER + // A, through to U+0046 LATIN CAPITAL LETTER F (in other + // words, 0-9, A-F, a-f). + $char = 1; + $char_class = '0-9A-Fa-f'; + break; + + // Anything else + default: + // Follow the steps below, but using the range of + // characters U+0030 DIGIT ZERO through to U+0039 DIGIT + // NINE (i.e. just 0-9). + $char = 0; + $char_class = '0-9'; + break; + } + + // Consume as many characters as match the range of characters + // given above. + $this->char++; + $e_name = $this->characters($char_class, $this->char + $char + 1); + $entity = $this->character($start, $this->char); + $cond = strlen($e_name) > 0; + + // The rest of the parsing happens bellow. + break; + + // Anything else + default: + // Consume the maximum number of characters possible, with the + // consumed characters case-sensitively matching one of the + // identifiers in the first column of the entities table. + $e_name = $this->characters('0-9A-Za-z;', $this->char + 1); + $len = strlen($e_name); + + for($c = 1; $c <= $len; $c++) { + $id = substr($e_name, 0, $c); + $this->char++; + + if(in_array($id, $this->entities)) { + $entity = $id; + break; + } + } + + $cond = isset($entity); + // The rest of the parsing happens bellow. + break; + } + + if(!$cond) { + // If no match can be made, then this is a parse error. No + // characters are consumed, and nothing is returned. + $this->char = $start; + return false; + } + + // Return a character token for the character corresponding to the + // entity name (as given by the second column of the entities table). + return html_entity_decode('&'.$entity.';', ENT_QUOTES, 'UTF-8'); + } + + private function emitToken($token) + { + $emit = $this->tree->emitToken($token); + + if(is_int($emit)) { + $this->content_model = $emit; + + } elseif($token['type'] === self::ENDTAG) { + $this->content_model = self::PCDATA; + } + } + + private function EOF() + { + $this->state = null; + $this->tree->emitToken(array( + 'type' => self::EOF + )); + } +} + +class HTML5TreeConstructer +{ + public $stack = array(); + + private $phase; + private $mode; + private $dom; + private $foster_parent = null; + private $a_formatting = array(); + + private $head_pointer = null; + private $form_pointer = null; + + private $scoping = array('button','caption','html','marquee','object','table','td','th'); + private $formatting = array('a','b','big','em','font','i','nobr','s','small','strike','strong','tt','u'); + private $special = array('address','area','base','basefont','bgsound', + 'blockquote','body','br','center','col','colgroup','dd','dir','div','dl', + 'dt','embed','fieldset','form','frame','frameset','h1','h2','h3','h4','h5', + 'h6','head','hr','iframe','image','img','input','isindex','li','link', + 'listing','menu','meta','noembed','noframes','noscript','ol','optgroup', + 'option','p','param','plaintext','pre','script','select','spacer','style', + 'tbody','textarea','tfoot','thead','title','tr','ul','wbr'); + + // The different phases. + const INIT_PHASE = 0; + const ROOT_PHASE = 1; + const MAIN_PHASE = 2; + const END_PHASE = 3; + + // The different insertion modes for the main phase. + const BEFOR_HEAD = 0; + const IN_HEAD = 1; + const AFTER_HEAD = 2; + const IN_BODY = 3; + const IN_TABLE = 4; + const IN_CAPTION = 5; + const IN_CGROUP = 6; + const IN_TBODY = 7; + const IN_ROW = 8; + const IN_CELL = 9; + const IN_SELECT = 10; + const AFTER_BODY = 11; + const IN_FRAME = 12; + const AFTR_FRAME = 13; + + // The different types of elements. + const SPECIAL = 0; + const SCOPING = 1; + const FORMATTING = 2; + const PHRASING = 3; + + const MARKER = 0; + + public function __construct() + { + $this->phase = self::INIT_PHASE; + $this->mode = self::BEFOR_HEAD; + $this->dom = new DOMDocument; + + $this->dom->encoding = 'UTF-8'; + $this->dom->preserveWhiteSpace = true; + $this->dom->substituteEntities = true; + $this->dom->strictErrorChecking = false; + } + + // Process tag tokens + public function emitToken($token) + { + switch($this->phase) { + case self::INIT_PHASE: return $this->initPhase($token); break; + case self::ROOT_PHASE: return $this->rootElementPhase($token); break; + case self::MAIN_PHASE: return $this->mainPhase($token); break; + case self::END_PHASE : return $this->trailingEndPhase($token); break; + } + } + + private function initPhase($token) + { + /* Initially, the tree construction stage must handle each token + emitted from the tokenisation stage as follows: */ + + /* A DOCTYPE token that is marked as being in error + A comment token + A start tag token + An end tag token + A character token that is not one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE + An end-of-file token */ + if((isset($token['error']) && $token['error']) || + $token['type'] === HTML5::COMMENT || + $token['type'] === HTML5::STARTTAG || + $token['type'] === HTML5::ENDTAG || + $token['type'] === HTML5::EOF || + ($token['type'] === HTML5::CHARACTR && isset($token['data']) && + !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data']))) { + /* This specification does not define how to handle this case. In + particular, user agents may ignore the entirety of this specification + altogether for such documents, and instead invoke special parse modes + with a greater emphasis on backwards compatibility. */ + + $this->phase = self::ROOT_PHASE; + return $this->rootElementPhase($token); + + /* A DOCTYPE token marked as being correct */ + } elseif(isset($token['error']) && !$token['error']) { + /* Append a DocumentType node to the Document node, with the name + attribute set to the name given in the DOCTYPE token (which will be + "HTML"), and the other attributes specific to DocumentType objects + set to null, empty lists, or the empty string as appropriate. */ + $doctype = new DOMDocumentType(null, null, 'HTML'); + + /* Then, switch to the root element phase of the tree construction + stage. */ + $this->phase = self::ROOT_PHASE; + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + } elseif(isset($token['data']) && preg_match('/^[\t\n\x0b\x0c ]+$/', + $token['data'])) { + /* Append that character to the Document node. */ + $text = $this->dom->createTextNode($token['data']); + $this->dom->appendChild($text); + } + } + + private function rootElementPhase($token) + { + /* After the initial phase, as each token is emitted from the tokenisation + stage, it must be processed as described in this section. */ + + /* A DOCTYPE token */ + if($token['type'] === HTML5::DOCTYPE) { + // Parse error. Ignore the token. + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the Document object with the data + attribute set to the data given in the comment token. */ + $comment = $this->dom->createComment($token['data']); + $this->dom->appendChild($comment); + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + } elseif($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Append that character to the Document node. */ + $text = $this->dom->createTextNode($token['data']); + $this->dom->appendChild($text); + + /* A character token that is not one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED + (FF), or U+0020 SPACE + A start tag token + An end tag token + An end-of-file token */ + } elseif(($token['type'] === HTML5::CHARACTR && + !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || + $token['type'] === HTML5::STARTTAG || + $token['type'] === HTML5::ENDTAG || + $token['type'] === HTML5::EOF) { + /* Create an HTMLElement node with the tag name html, in the HTML + namespace. Append it to the Document object. Switch to the main + phase and reprocess the current token. */ + $html = $this->dom->createElement('html'); + $this->dom->appendChild($html); + $this->stack[] = $html; + + $this->phase = self::MAIN_PHASE; + return $this->mainPhase($token); + } + } + + private function mainPhase($token) + { + /* Tokens in the main phase must be handled as follows: */ + + /* A DOCTYPE token */ + if($token['type'] === HTML5::DOCTYPE) { + // Parse error. Ignore the token. + + /* A start tag token with the tag name "html" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'html') { + /* If this start tag token was not the first start tag token, then + it is a parse error. */ + + /* For each attribute on the token, check to see if the attribute + is already present on the top element of the stack of open elements. + If it is not, add the attribute and its corresponding value to that + element. */ + foreach($token['attr'] as $attr) { + if(!$this->stack[0]->hasAttribute($attr['name'])) { + $this->stack[0]->setAttribute($attr['name'], $attr['value']); + } + } + + /* An end-of-file token */ + } elseif($token['type'] === HTML5::EOF) { + /* Generate implied end tags. */ + $this->generateImpliedEndTags(); + + /* Anything else. */ + } else { + /* Depends on the insertion mode: */ + switch($this->mode) { + case self::BEFOR_HEAD: return $this->beforeHead($token); break; + case self::IN_HEAD: return $this->inHead($token); break; + case self::AFTER_HEAD: return $this->afterHead($token); break; + case self::IN_BODY: return $this->inBody($token); break; + case self::IN_TABLE: return $this->inTable($token); break; + case self::IN_CAPTION: return $this->inCaption($token); break; + case self::IN_CGROUP: return $this->inColumnGroup($token); break; + case self::IN_TBODY: return $this->inTableBody($token); break; + case self::IN_ROW: return $this->inRow($token); break; + case self::IN_CELL: return $this->inCell($token); break; + case self::IN_SELECT: return $this->inSelect($token); break; + case self::AFTER_BODY: return $this->afterBody($token); break; + case self::IN_FRAME: return $this->inFrameset($token); break; + case self::AFTR_FRAME: return $this->afterFrameset($token); break; + case self::END_PHASE: return $this->trailingEndPhase($token); break; + } + } + } + + private function beforeHead($token) + { + /* Handle the token as follows: */ + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + if($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Append the character to the current node. */ + $this->insertText($token['data']); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data attribute + set to the data given in the comment token. */ + $this->insertComment($token['data']); + + /* A start tag token with the tag name "head" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') { + /* Create an element for the token, append the new element to the + current node and push it onto the stack of open elements. */ + $element = $this->insertElement($token); + + /* Set the head element pointer to this new element node. */ + $this->head_pointer = $element; + + /* Change the insertion mode to "in head". */ + $this->mode = self::IN_HEAD; + + /* A start tag token whose tag name is one of: "base", "link", "meta", + "script", "style", "title". Or an end tag with the tag name "html". + Or a character token that is not one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE. Or any other start tag token */ + } elseif($token['type'] === HTML5::STARTTAG || + ($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') || + ($token['type'] === HTML5::CHARACTR && !preg_match('/^[\t\n\x0b\x0c ]$/', + $token['data']))) { + /* Act as if a start tag token with the tag name "head" and no + attributes had been seen, then reprocess the current token. */ + $this->beforeHead(array( + 'name' => 'head', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + return $this->inHead($token); + + /* Any other end tag */ + } elseif($token['type'] === HTML5::ENDTAG) { + /* Parse error. Ignore the token. */ + } + } + + private function inHead($token) + { + /* Handle the token as follows: */ + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE. + + THIS DIFFERS FROM THE SPEC: If the current node is either a title, style + or script element, append the character to the current node regardless + of its content. */ + if(($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || ( + $token['type'] === HTML5::CHARACTR && in_array(end($this->stack)->nodeName, + array('title', 'style', 'script')))) { + /* Append the character to the current node. */ + $this->insertText($token['data']); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data attribute + set to the data given in the comment token. */ + $this->insertComment($token['data']); + + } elseif($token['type'] === HTML5::ENDTAG && + in_array($token['name'], array('title', 'style', 'script'))) { + array_pop($this->stack); + return HTML5::PCDATA; + + /* A start tag with the tag name "title" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'title') { + /* Create an element for the token and append the new element to the + node pointed to by the head element pointer, or, if that is null + (innerHTML case), to the current node. */ + if($this->head_pointer !== null) { + $element = $this->insertElement($token, false); + $this->head_pointer->appendChild($element); + + } else { + $element = $this->insertElement($token); + } + + /* Switch the tokeniser's content model flag to the RCDATA state. */ + return HTML5::RCDATA; + + /* A start tag with the tag name "style" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'style') { + /* Create an element for the token and append the new element to the + node pointed to by the head element pointer, or, if that is null + (innerHTML case), to the current node. */ + if($this->head_pointer !== null) { + $element = $this->insertElement($token, false); + $this->head_pointer->appendChild($element); + + } else { + $this->insertElement($token); + } + + /* Switch the tokeniser's content model flag to the CDATA state. */ + return HTML5::CDATA; + + /* A start tag with the tag name "script" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'script') { + /* Create an element for the token. */ + $element = $this->insertElement($token, false); + $this->head_pointer->appendChild($element); + + /* Switch the tokeniser's content model flag to the CDATA state. */ + return HTML5::CDATA; + + /* A start tag with the tag name "base", "link", or "meta" */ + } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('base', 'link', 'meta'))) { + /* Create an element for the token and append the new element to the + node pointed to by the head element pointer, or, if that is null + (innerHTML case), to the current node. */ + if($this->head_pointer !== null) { + $element = $this->insertElement($token, false); + $this->head_pointer->appendChild($element); + array_pop($this->stack); + + } else { + $this->insertElement($token); + } + + /* An end tag with the tag name "head" */ + } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'head') { + /* If the current node is a head element, pop the current node off + the stack of open elements. */ + if($this->head_pointer->isSameNode(end($this->stack))) { + array_pop($this->stack); + + /* Otherwise, this is a parse error. */ + } else { + // k + } + + /* Change the insertion mode to "after head". */ + $this->mode = self::AFTER_HEAD; + + /* A start tag with the tag name "head" or an end tag except "html". */ + } elseif(($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') || + ($token['type'] === HTML5::ENDTAG && $token['name'] !== 'html')) { + // Parse error. Ignore the token. + + /* Anything else */ + } else { + /* If the current node is a head element, act as if an end tag + token with the tag name "head" had been seen. */ + if($this->head_pointer->isSameNode(end($this->stack))) { + $this->inHead(array( + 'name' => 'head', + 'type' => HTML5::ENDTAG + )); + + /* Otherwise, change the insertion mode to "after head". */ + } else { + $this->mode = self::AFTER_HEAD; + } + + /* Then, reprocess the current token. */ + return $this->afterHead($token); + } + } + + private function afterHead($token) + { + /* Handle the token as follows: */ + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + if($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Append the character to the current node. */ + $this->insertText($token['data']); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data attribute + set to the data given in the comment token. */ + $this->insertComment($token['data']); + + /* A start tag token with the tag name "body" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'body') { + /* Insert a body element for the token. */ + $this->insertElement($token); + + /* Change the insertion mode to "in body". */ + $this->mode = self::IN_BODY; + + /* A start tag token with the tag name "frameset" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'frameset') { + /* Insert a frameset element for the token. */ + $this->insertElement($token); + + /* Change the insertion mode to "in frameset". */ + $this->mode = self::IN_FRAME; + + /* A start tag token whose tag name is one of: "base", "link", "meta", + "script", "style", "title" */ + } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('base', 'link', 'meta', 'script', 'style', 'title'))) { + /* Parse error. Switch the insertion mode back to "in head" and + reprocess the token. */ + $this->mode = self::IN_HEAD; + return $this->inHead($token); + + /* Anything else */ + } else { + /* Act as if a start tag token with the tag name "body" and no + attributes had been seen, and then reprocess the current token. */ + $this->afterHead(array( + 'name' => 'body', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + return $this->inBody($token); + } + } + + private function inBody($token) + { + /* Handle the token as follows: */ + + switch($token['type']) { + /* A character token */ + case HTML5::CHARACTR: + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Append the token's character to the current node. */ + $this->insertText($token['data']); + break; + + /* A comment token */ + case HTML5::COMMENT: + /* Append a Comment node to the current node with the data + attribute set to the data given in the comment token. */ + $this->insertComment($token['data']); + break; + + case HTML5::STARTTAG: + switch($token['name']) { + /* A start tag token whose tag name is one of: "script", + "style" */ + case 'script': case 'style': + /* Process the token as if the insertion mode had been "in + head". */ + return $this->inHead($token); + break; + + /* A start tag token whose tag name is one of: "base", "link", + "meta", "title" */ + case 'base': case 'link': case 'meta': case 'title': + /* Parse error. Process the token as if the insertion mode + had been "in head". */ + return $this->inHead($token); + break; + + /* A start tag token with the tag name "body" */ + case 'body': + /* Parse error. If the second element on the stack of open + elements is not a body element, or, if the stack of open + elements has only one node on it, then ignore the token. + (innerHTML case) */ + if(count($this->stack) === 1 || $this->stack[1]->nodeName !== 'body') { + // Ignore + + /* Otherwise, for each attribute on the token, check to see + if the attribute is already present on the body element (the + second element) on the stack of open elements. If it is not, + add the attribute and its corresponding value to that + element. */ + } else { + foreach($token['attr'] as $attr) { + if(!$this->stack[1]->hasAttribute($attr['name'])) { + $this->stack[1]->setAttribute($attr['name'], $attr['value']); + } + } + } + break; + + /* A start tag whose tag name is one of: "address", + "blockquote", "center", "dir", "div", "dl", "fieldset", + "listing", "menu", "ol", "p", "ul" */ + case 'address': case 'blockquote': case 'center': case 'dir': + case 'div': case 'dl': case 'fieldset': case 'listing': + case 'menu': case 'ol': case 'p': case 'ul': + /* If the stack of open elements has a p element in scope, + then act as if an end tag with the tag name p had been + seen. */ + if($this->elementInScope('p')) { + $this->emitToken(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + } + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + break; + + /* A start tag whose tag name is "form" */ + case 'form': + /* If the form element pointer is not null, ignore the + token with a parse error. */ + if($this->form_pointer !== null) { + // Ignore. + + /* Otherwise: */ + } else { + /* If the stack of open elements has a p element in + scope, then act as if an end tag with the tag name p + had been seen. */ + if($this->elementInScope('p')) { + $this->emitToken(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + } + + /* Insert an HTML element for the token, and set the + form element pointer to point to the element created. */ + $element = $this->insertElement($token); + $this->form_pointer = $element; + } + break; + + /* A start tag whose tag name is "li", "dd" or "dt" */ + case 'li': case 'dd': case 'dt': + /* If the stack of open elements has a p element in scope, + then act as if an end tag with the tag name p had been + seen. */ + if($this->elementInScope('p')) { + $this->emitToken(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + } + + $stack_length = count($this->stack) - 1; + + for($n = $stack_length; 0 <= $n; $n--) { + /* 1. Initialise node to be the current node (the + bottommost node of the stack). */ + $stop = false; + $node = $this->stack[$n]; + $cat = $this->getElementCategory($node->tagName); + + /* 2. If node is an li, dd or dt element, then pop all + the nodes from the current node up to node, including + node, then stop this algorithm. */ + if($token['name'] === $node->tagName || ($token['name'] !== 'li' + && ($node->tagName === 'dd' || $node->tagName === 'dt'))) { + for($x = $stack_length; $x >= $n ; $x--) { + array_pop($this->stack); + } + + break; + } + + /* 3. If node is not in the formatting category, and is + not in the phrasing category, and is not an address or + div element, then stop this algorithm. */ + if($cat !== self::FORMATTING && $cat !== self::PHRASING && + $node->tagName !== 'address' && $node->tagName !== 'div') { + break; + } + } + + /* Finally, insert an HTML element with the same tag + name as the token's. */ + $this->insertElement($token); + break; + + /* A start tag token whose tag name is "plaintext" */ + case 'plaintext': + /* If the stack of open elements has a p element in scope, + then act as if an end tag with the tag name p had been + seen. */ + if($this->elementInScope('p')) { + $this->emitToken(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + } + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + return HTML5::PLAINTEXT; + break; + + /* A start tag whose tag name is one of: "h1", "h2", "h3", "h4", + "h5", "h6" */ + case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': + /* If the stack of open elements has a p element in scope, + then act as if an end tag with the tag name p had been seen. */ + if($this->elementInScope('p')) { + $this->emitToken(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + } + + /* If the stack of open elements has in scope an element whose + tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then + this is a parse error; pop elements from the stack until an + element with one of those tag names has been popped from the + stack. */ + while($this->elementInScope(array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) { + array_pop($this->stack); + } + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + break; + + /* A start tag whose tag name is "a" */ + case 'a': + /* If the list of active formatting elements contains + an element whose tag name is "a" between the end of the + list and the last marker on the list (or the start of + the list if there is no marker on the list), then this + is a parse error; act as if an end tag with the tag name + "a" had been seen, then remove that element from the list + of active formatting elements and the stack of open + elements if the end tag didn't already remove it (it + might not have if the element is not in table scope). */ + $leng = count($this->a_formatting); + + for($n = $leng - 1; $n >= 0; $n--) { + if($this->a_formatting[$n] === self::MARKER) { + break; + + } elseif($this->a_formatting[$n]->nodeName === 'a') { + $this->emitToken(array( + 'name' => 'a', + 'type' => HTML5::ENDTAG + )); + break; + } + } + + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an HTML element for the token. */ + $el = $this->insertElement($token); + + /* Add that element to the list of active formatting + elements. */ + $this->a_formatting[] = $el; + break; + + /* A start tag whose tag name is one of: "b", "big", "em", "font", + "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */ + case 'b': case 'big': case 'em': case 'font': case 'i': + case 'nobr': case 's': case 'small': case 'strike': + case 'strong': case 'tt': case 'u': + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an HTML element for the token. */ + $el = $this->insertElement($token); + + /* Add that element to the list of active formatting + elements. */ + $this->a_formatting[] = $el; + break; + + /* A start tag token whose tag name is "button" */ + case 'button': + /* If the stack of open elements has a button element in scope, + then this is a parse error; act as if an end tag with the tag + name "button" had been seen, then reprocess the token. (We don't + do that. Unnecessary.) */ + if($this->elementInScope('button')) { + $this->inBody(array( + 'name' => 'button', + 'type' => HTML5::ENDTAG + )); + } + + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Insert a marker at the end of the list of active + formatting elements. */ + $this->a_formatting[] = self::MARKER; + break; + + /* A start tag token whose tag name is one of: "marquee", "object" */ + case 'marquee': case 'object': + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Insert a marker at the end of the list of active + formatting elements. */ + $this->a_formatting[] = self::MARKER; + break; + + /* A start tag token whose tag name is "xmp" */ + case 'xmp': + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Switch the content model flag to the CDATA state. */ + return HTML5::CDATA; + break; + + /* A start tag whose tag name is "table" */ + case 'table': + /* If the stack of open elements has a p element in scope, + then act as if an end tag with the tag name p had been seen. */ + if($this->elementInScope('p')) { + $this->emitToken(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + } + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Change the insertion mode to "in table". */ + $this->mode = self::IN_TABLE; + break; + + /* A start tag whose tag name is one of: "area", "basefont", + "bgsound", "br", "embed", "img", "param", "spacer", "wbr" */ + case 'area': case 'basefont': case 'bgsound': case 'br': + case 'embed': case 'img': case 'param': case 'spacer': + case 'wbr': + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Immediately pop the current node off the stack of open elements. */ + array_pop($this->stack); + break; + + /* A start tag whose tag name is "hr" */ + case 'hr': + /* If the stack of open elements has a p element in scope, + then act as if an end tag with the tag name p had been seen. */ + if($this->elementInScope('p')) { + $this->emitToken(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + } + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Immediately pop the current node off the stack of open elements. */ + array_pop($this->stack); + break; + + /* A start tag whose tag name is "image" */ + case 'image': + /* Parse error. Change the token's tag name to "img" and + reprocess it. (Don't ask.) */ + $token['name'] = 'img'; + return $this->inBody($token); + break; + + /* A start tag whose tag name is "input" */ + case 'input': + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an input element for the token. */ + $element = $this->insertElement($token, false); + + /* If the form element pointer is not null, then associate the + input element with the form element pointed to by the form + element pointer. */ + $this->form_pointer !== null + ? $this->form_pointer->appendChild($element) + : end($this->stack)->appendChild($element); + + /* Pop that input element off the stack of open elements. */ + array_pop($this->stack); + break; + + /* A start tag whose tag name is "isindex" */ + case 'isindex': + /* Parse error. */ + // w/e + + /* If the form element pointer is not null, + then ignore the token. */ + if($this->form_pointer === null) { + /* Act as if a start tag token with the tag name "form" had + been seen. */ + $this->inBody(array( + 'name' => 'body', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + /* Act as if a start tag token with the tag name "hr" had + been seen. */ + $this->inBody(array( + 'name' => 'hr', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + /* Act as if a start tag token with the tag name "p" had + been seen. */ + $this->inBody(array( + 'name' => 'p', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + /* Act as if a start tag token with the tag name "label" + had been seen. */ + $this->inBody(array( + 'name' => 'label', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + /* Act as if a stream of character tokens had been seen. */ + $this->insertText('This is a searchable index. '. + 'Insert your search keywords here: '); + + /* Act as if a start tag token with the tag name "input" + had been seen, with all the attributes from the "isindex" + token, except with the "name" attribute set to the value + "isindex" (ignoring any explicit "name" attribute). */ + $attr = $token['attr']; + $attr[] = array('name' => 'name', 'value' => 'isindex'); + + $this->inBody(array( + 'name' => 'input', + 'type' => HTML5::STARTTAG, + 'attr' => $attr + )); + + /* Act as if a stream of character tokens had been seen + (see below for what they should say). */ + $this->insertText('This is a searchable index. '. + 'Insert your search keywords here: '); + + /* Act as if an end tag token with the tag name "label" + had been seen. */ + $this->inBody(array( + 'name' => 'label', + 'type' => HTML5::ENDTAG + )); + + /* Act as if an end tag token with the tag name "p" had + been seen. */ + $this->inBody(array( + 'name' => 'p', + 'type' => HTML5::ENDTAG + )); + + /* Act as if a start tag token with the tag name "hr" had + been seen. */ + $this->inBody(array( + 'name' => 'hr', + 'type' => HTML5::ENDTAG + )); + + /* Act as if an end tag token with the tag name "form" had + been seen. */ + $this->inBody(array( + 'name' => 'form', + 'type' => HTML5::ENDTAG + )); + } + break; + + /* A start tag whose tag name is "textarea" */ + case 'textarea': + $this->insertElement($token); + + /* Switch the tokeniser's content model flag to the + RCDATA state. */ + return HTML5::RCDATA; + break; + + /* A start tag whose tag name is one of: "iframe", "noembed", + "noframes" */ + case 'iframe': case 'noembed': case 'noframes': + $this->insertElement($token); + + /* Switch the tokeniser's content model flag to the CDATA state. */ + return HTML5::CDATA; + break; + + /* A start tag whose tag name is "select" */ + case 'select': + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Change the insertion mode to "in select". */ + $this->mode = self::IN_SELECT; + break; + + /* A start or end tag whose tag name is one of: "caption", "col", + "colgroup", "frame", "frameset", "head", "option", "optgroup", + "tbody", "td", "tfoot", "th", "thead", "tr". */ + case 'caption': case 'col': case 'colgroup': case 'frame': + case 'frameset': case 'head': case 'option': case 'optgroup': + case 'tbody': case 'td': case 'tfoot': case 'th': case 'thead': + case 'tr': + // Parse error. Ignore the token. + break; + + /* A start or end tag whose tag name is one of: "event-source", + "section", "nav", "article", "aside", "header", "footer", + "datagrid", "command" */ + case 'event-source': case 'section': case 'nav': case 'article': + case 'aside': case 'header': case 'footer': case 'datagrid': + case 'command': + // Work in progress! + break; + + /* A start tag token not covered by the previous entries */ + default: + /* Reconstruct the active formatting elements, if any. */ + $this->reconstructActiveFormattingElements(); + + $this->insertElement($token); + break; + } + break; + + case HTML5::ENDTAG: + switch($token['name']) { + /* An end tag with the tag name "body" */ + case 'body': + /* If the second element in the stack of open elements is + not a body element, this is a parse error. Ignore the token. + (innerHTML case) */ + if(count($this->stack) < 2 || $this->stack[1]->nodeName !== 'body') { + // Ignore. + + /* If the current node is not the body element, then this + is a parse error. */ + } elseif(end($this->stack)->nodeName !== 'body') { + // Parse error. + } + + /* Change the insertion mode to "after body". */ + $this->mode = self::AFTER_BODY; + break; + + /* An end tag with the tag name "html" */ + case 'html': + /* Act as if an end tag with tag name "body" had been seen, + then, if that token wasn't ignored, reprocess the current + token. */ + $this->inBody(array( + 'name' => 'body', + 'type' => HTML5::ENDTAG + )); + + return $this->afterBody($token); + break; + + /* An end tag whose tag name is one of: "address", "blockquote", + "center", "dir", "div", "dl", "fieldset", "listing", "menu", + "ol", "pre", "ul" */ + case 'address': case 'blockquote': case 'center': case 'dir': + case 'div': case 'dl': case 'fieldset': case 'listing': + case 'menu': case 'ol': case 'pre': case 'ul': + /* If the stack of open elements has an element in scope + with the same tag name as that of the token, then generate + implied end tags. */ + if($this->elementInScope($token['name'])) { + $this->generateImpliedEndTags(); + + /* Now, if the current node is not an element with + the same tag name as that of the token, then this + is a parse error. */ + // w/e + + /* If the stack of open elements has an element in + scope with the same tag name as that of the token, + then pop elements from this stack until an element + with that tag name has been popped from the stack. */ + for($n = count($this->stack) - 1; $n >= 0; $n--) { + if($this->stack[$n]->nodeName === $token['name']) { + $n = -1; + } + + array_pop($this->stack); + } + } + break; + + /* An end tag whose tag name is "form" */ + case 'form': + /* If the stack of open elements has an element in scope + with the same tag name as that of the token, then generate + implied end tags. */ + if($this->elementInScope($token['name'])) { + $this->generateImpliedEndTags(); + + } + + if(end($this->stack)->nodeName !== $token['name']) { + /* Now, if the current node is not an element with the + same tag name as that of the token, then this is a parse + error. */ + // w/e + + } else { + /* Otherwise, if the current node is an element with + the same tag name as that of the token pop that element + from the stack. */ + array_pop($this->stack); + } + + /* In any case, set the form element pointer to null. */ + $this->form_pointer = null; + break; + + /* An end tag whose tag name is "p" */ + case 'p': + /* If the stack of open elements has a p element in scope, + then generate implied end tags, except for p elements. */ + if($this->elementInScope('p')) { + $this->generateImpliedEndTags(array('p')); + + /* If the current node is not a p element, then this is + a parse error. */ + // k + + /* If the stack of open elements has a p element in + scope, then pop elements from this stack until the stack + no longer has a p element in scope. */ + for($n = count($this->stack) - 1; $n >= 0; $n--) { + if($this->elementInScope('p')) { + array_pop($this->stack); + + } else { + break; + } + } + } + break; + + /* An end tag whose tag name is "dd", "dt", or "li" */ + case 'dd': case 'dt': case 'li': + /* If the stack of open elements has an element in scope + whose tag name matches the tag name of the token, then + generate implied end tags, except for elements with the + same tag name as the token. */ + if($this->elementInScope($token['name'])) { + $this->generateImpliedEndTags(array($token['name'])); + + /* If the current node is not an element with the same + tag name as the token, then this is a parse error. */ + // w/e + + /* If the stack of open elements has an element in scope + whose tag name matches the tag name of the token, then + pop elements from this stack until an element with that + tag name has been popped from the stack. */ + for($n = count($this->stack) - 1; $n >= 0; $n--) { + if($this->stack[$n]->nodeName === $token['name']) { + $n = -1; + } + + array_pop($this->stack); + } + } + break; + + /* An end tag whose tag name is one of: "h1", "h2", "h3", "h4", + "h5", "h6" */ + case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': + $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'); + + /* If the stack of open elements has in scope an element whose + tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then + generate implied end tags. */ + if($this->elementInScope($elements)) { + $this->generateImpliedEndTags(); + + /* Now, if the current node is not an element with the same + tag name as that of the token, then this is a parse error. */ + // w/e + + /* If the stack of open elements has in scope an element + whose tag name is one of "h1", "h2", "h3", "h4", "h5", or + "h6", then pop elements from the stack until an element + with one of those tag names has been popped from the stack. */ + while($this->elementInScope($elements)) { + array_pop($this->stack); + } + } + break; + + /* An end tag whose tag name is one of: "a", "b", "big", "em", + "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */ + case 'a': case 'b': case 'big': case 'em': case 'font': + case 'i': case 'nobr': case 's': case 'small': case 'strike': + case 'strong': case 'tt': case 'u': + /* 1. Let the formatting element be the last element in + the list of active formatting elements that: + * is between the end of the list and the last scope + marker in the list, if any, or the start of the list + otherwise, and + * has the same tag name as the token. + */ + while(true) { + for($a = count($this->a_formatting) - 1; $a >= 0; $a--) { + if($this->a_formatting[$a] === self::MARKER) { + break; + + } elseif($this->a_formatting[$a]->tagName === $token['name']) { + $formatting_element = $this->a_formatting[$a]; + $in_stack = in_array($formatting_element, $this->stack, true); + $fe_af_pos = $a; + break; + } + } + + /* If there is no such node, or, if that node is + also in the stack of open elements but the element + is not in scope, then this is a parse error. Abort + these steps. The token is ignored. */ + if(!isset($formatting_element) || ($in_stack && + !$this->elementInScope($token['name']))) { + break; + + /* Otherwise, if there is such a node, but that node + is not in the stack of open elements, then this is a + parse error; remove the element from the list, and + abort these steps. */ + } elseif(isset($formatting_element) && !$in_stack) { + unset($this->a_formatting[$fe_af_pos]); + $this->a_formatting = array_merge($this->a_formatting); + break; + } + + /* 2. Let the furthest block be the topmost node in the + stack of open elements that is lower in the stack + than the formatting element, and is not an element in + the phrasing or formatting categories. There might + not be one. */ + $fe_s_pos = array_search($formatting_element, $this->stack, true); + $length = count($this->stack); + + for($s = $fe_s_pos + 1; $s < $length; $s++) { + $category = $this->getElementCategory($this->stack[$s]->nodeName); + + if($category !== self::PHRASING && $category !== self::FORMATTING) { + $furthest_block = $this->stack[$s]; + } + } + + /* 3. If there is no furthest block, then the UA must + skip the subsequent steps and instead just pop all + the nodes from the bottom of the stack of open + elements, from the current node up to the formatting + element, and remove the formatting element from the + list of active formatting elements. */ + if(!isset($furthest_block)) { + for($n = $length - 1; $n >= $fe_s_pos; $n--) { + array_pop($this->stack); + } + + unset($this->a_formatting[$fe_af_pos]); + $this->a_formatting = array_merge($this->a_formatting); + break; + } + + /* 4. Let the common ancestor be the element + immediately above the formatting element in the stack + of open elements. */ + $common_ancestor = $this->stack[$fe_s_pos - 1]; + + /* 5. If the furthest block has a parent node, then + remove the furthest block from its parent node. */ + if($furthest_block->parentNode !== null) { + $furthest_block->parentNode->removeChild($furthest_block); + } + + /* 6. Let a bookmark note the position of the + formatting element in the list of active formatting + elements relative to the elements on either side + of it in the list. */ + $bookmark = $fe_af_pos; + + /* 7. Let node and last node be the furthest block. + Follow these steps: */ + $node = $furthest_block; + $last_node = $furthest_block; + + while(true) { + for($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) { + /* 7.1 Let node be the element immediately + prior to node in the stack of open elements. */ + $node = $this->stack[$n]; + + /* 7.2 If node is not in the list of active + formatting elements, then remove node from + the stack of open elements and then go back + to step 1. */ + if(!in_array($node, $this->a_formatting, true)) { + unset($this->stack[$n]); + $this->stack = array_merge($this->stack); + + } else { + break; + } + } + + /* 7.3 Otherwise, if node is the formatting + element, then go to the next step in the overall + algorithm. */ + if($node === $formatting_element) { + break; + + /* 7.4 Otherwise, if last node is the furthest + block, then move the aforementioned bookmark to + be immediately after the node in the list of + active formatting elements. */ + } elseif($last_node === $furthest_block) { + $bookmark = array_search($node, $this->a_formatting, true) + 1; + } + + /* 7.5 If node has any children, perform a + shallow clone of node, replace the entry for + node in the list of active formatting elements + with an entry for the clone, replace the entry + for node in the stack of open elements with an + entry for the clone, and let node be the clone. */ + if($node->hasChildNodes()) { + $clone = $node->cloneNode(); + $s_pos = array_search($node, $this->stack, true); + $a_pos = array_search($node, $this->a_formatting, true); + + $this->stack[$s_pos] = $clone; + $this->a_formatting[$a_pos] = $clone; + $node = $clone; + } + + /* 7.6 Insert last node into node, first removing + it from its previous parent node if any. */ + if($last_node->parentNode !== null) { + $last_node->parentNode->removeChild($last_node); + } + + $node->appendChild($last_node); + + /* 7.7 Let last node be node. */ + $last_node = $node; + } + + /* 8. Insert whatever last node ended up being in + the previous step into the common ancestor node, + first removing it from its previous parent node if + any. */ + if($last_node->parentNode !== null) { + $last_node->parentNode->removeChild($last_node); + } + + $common_ancestor->appendChild($last_node); + + /* 9. Perform a shallow clone of the formatting + element. */ + $clone = $formatting_element->cloneNode(); + + /* 10. Take all of the child nodes of the furthest + block and append them to the clone created in the + last step. */ + while($furthest_block->hasChildNodes()) { + $child = $furthest_block->firstChild; + $furthest_block->removeChild($child); + $clone->appendChild($child); + } + + /* 11. Append that clone to the furthest block. */ + $furthest_block->appendChild($clone); + + /* 12. Remove the formatting element from the list + of active formatting elements, and insert the clone + into the list of active formatting elements at the + position of the aforementioned bookmark. */ + $fe_af_pos = array_search($formatting_element, $this->a_formatting, true); + unset($this->a_formatting[$fe_af_pos]); + $this->a_formatting = array_merge($this->a_formatting); + + $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1); + $af_part2 = array_slice($this->a_formatting, $bookmark, count($this->a_formatting)); + $this->a_formatting = array_merge($af_part1, array($clone), $af_part2); + + /* 13. Remove the formatting element from the stack + of open elements, and insert the clone into the stack + of open elements immediately after (i.e. in a more + deeply nested position than) the position of the + furthest block in that stack. */ + $fe_s_pos = array_search($formatting_element, $this->stack, true); + $fb_s_pos = array_search($furthest_block, $this->stack, true); + unset($this->stack[$fe_s_pos]); + + $s_part1 = array_slice($this->stack, 0, $fb_s_pos); + $s_part2 = array_slice($this->stack, $fb_s_pos + 1, count($this->stack)); + $this->stack = array_merge($s_part1, array($clone), $s_part2); + + /* 14. Jump back to step 1 in this series of steps. */ + unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block); + } + break; + + /* An end tag token whose tag name is one of: "button", + "marquee", "object" */ + case 'button': case 'marquee': case 'object': + /* If the stack of open elements has an element in scope whose + tag name matches the tag name of the token, then generate implied + tags. */ + if($this->elementInScope($token['name'])) { + $this->generateImpliedEndTags(); + + /* Now, if the current node is not an element with the same + tag name as the token, then this is a parse error. */ + // k + + /* Now, if the stack of open elements has an element in scope + whose tag name matches the tag name of the token, then pop + elements from the stack until that element has been popped from + the stack, and clear the list of active formatting elements up + to the last marker. */ + for($n = count($this->stack) - 1; $n >= 0; $n--) { + if($this->stack[$n]->nodeName === $token['name']) { + $n = -1; + } + + array_pop($this->stack); + } + + $marker = end(array_keys($this->a_formatting, self::MARKER, true)); + + for($n = count($this->a_formatting) - 1; $n > $marker; $n--) { + array_pop($this->a_formatting); + } + } + break; + + /* Or an end tag whose tag name is one of: "area", "basefont", + "bgsound", "br", "embed", "hr", "iframe", "image", "img", + "input", "isindex", "noembed", "noframes", "param", "select", + "spacer", "table", "textarea", "wbr" */ + case 'area': case 'basefont': case 'bgsound': case 'br': + case 'embed': case 'hr': case 'iframe': case 'image': + case 'img': case 'input': case 'isindex': case 'noembed': + case 'noframes': case 'param': case 'select': case 'spacer': + case 'table': case 'textarea': case 'wbr': + // Parse error. Ignore the token. + break; + + /* An end tag token not covered by the previous entries */ + default: + for($n = count($this->stack) - 1; $n >= 0; $n--) { + /* Initialise node to be the current node (the bottommost + node of the stack). */ + $node = end($this->stack); + + /* If node has the same tag name as the end tag token, + then: */ + if($token['name'] === $node->nodeName) { + /* Generate implied end tags. */ + $this->generateImpliedEndTags(); + + /* If the tag name of the end tag token does not + match the tag name of the current node, this is a + parse error. */ + // k + + /* Pop all the nodes from the current node up to + node, including node, then stop this algorithm. */ + for($x = count($this->stack) - $n; $x >= $n; $x--) { + array_pop($this->stack); + } + + } else { + $category = $this->getElementCategory($node); + + if($category !== self::SPECIAL && $category !== self::SCOPING) { + /* Otherwise, if node is in neither the formatting + category nor the phrasing category, then this is a + parse error. Stop this algorithm. The end tag token + is ignored. */ + return false; + } + } + } + break; + } + break; + } + } + + private function inTable($token) + { + $clear = array('html', 'table'); + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + if($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Append the character to the current node. */ + $text = $this->dom->createTextNode($token['data']); + end($this->stack)->appendChild($text); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data + attribute set to the data given in the comment token. */ + $comment = $this->dom->createComment($token['data']); + end($this->stack)->appendChild($comment); + + /* A start tag whose tag name is "caption" */ + } elseif($token['type'] === HTML5::STARTTAG && + $token['name'] === 'caption') { + /* Clear the stack back to a table context. */ + $this->clearStackToTableContext($clear); + + /* Insert a marker at the end of the list of active + formatting elements. */ + $this->a_formatting[] = self::MARKER; + + /* Insert an HTML element for the token, then switch the + insertion mode to "in caption". */ + $this->insertElement($token); + $this->mode = self::IN_CAPTION; + + /* A start tag whose tag name is "colgroup" */ + } elseif($token['type'] === HTML5::STARTTAG && + $token['name'] === 'colgroup') { + /* Clear the stack back to a table context. */ + $this->clearStackToTableContext($clear); + + /* Insert an HTML element for the token, then switch the + insertion mode to "in column group". */ + $this->insertElement($token); + $this->mode = self::IN_CGROUP; + + /* A start tag whose tag name is "col" */ + } elseif($token['type'] === HTML5::STARTTAG && + $token['name'] === 'col') { + $this->inTable(array( + 'name' => 'colgroup', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + $this->inColumnGroup($token); + + /* A start tag whose tag name is one of: "tbody", "tfoot", "thead" */ + } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('tbody', 'tfoot', 'thead'))) { + /* Clear the stack back to a table context. */ + $this->clearStackToTableContext($clear); + + /* Insert an HTML element for the token, then switch the insertion + mode to "in table body". */ + $this->insertElement($token); + $this->mode = self::IN_TBODY; + + /* A start tag whose tag name is one of: "td", "th", "tr" */ + } elseif($token['type'] === HTML5::STARTTAG && + in_array($token['name'], array('td', 'th', 'tr'))) { + /* Act as if a start tag token with the tag name "tbody" had been + seen, then reprocess the current token. */ + $this->inTable(array( + 'name' => 'tbody', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + return $this->inTableBody($token); + + /* A start tag whose tag name is "table" */ + } elseif($token['type'] === HTML5::STARTTAG && + $token['name'] === 'table') { + /* Parse error. Act as if an end tag token with the tag name "table" + had been seen, then, if that token wasn't ignored, reprocess the + current token. */ + $this->inTable(array( + 'name' => 'table', + 'type' => HTML5::ENDTAG + )); + + return $this->mainPhase($token); + + /* An end tag whose tag name is "table" */ + } elseif($token['type'] === HTML5::ENDTAG && + $token['name'] === 'table') { + /* If the stack of open elements does not have an element in table + scope with the same tag name as the token, this is a parse error. + Ignore the token. (innerHTML case) */ + if(!$this->elementInScope($token['name'], true)) { + return false; + + /* Otherwise: */ + } else { + /* Generate implied end tags. */ + $this->generateImpliedEndTags(); + + /* Now, if the current node is not a table element, then this + is a parse error. */ + // w/e + + /* Pop elements from this stack until a table element has been + popped from the stack. */ + while(true) { + $current = end($this->stack)->nodeName; + array_pop($this->stack); + + if($current === 'table') { + break; + } + } + + /* Reset the insertion mode appropriately. */ + $this->resetInsertionMode(); + } + + /* An end tag whose tag name is one of: "body", "caption", "col", + "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" */ + } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], + array('body', 'caption', 'col', 'colgroup', 'html', 'tbody', 'td', + 'tfoot', 'th', 'thead', 'tr'))) { + // Parse error. Ignore the token. + + /* Anything else */ + } else { + /* Parse error. Process the token as if the insertion mode was "in + body", with the following exception: */ + + /* If the current node is a table, tbody, tfoot, thead, or tr + element, then, whenever a node would be inserted into the current + node, it must instead be inserted into the foster parent element. */ + if(in_array(end($this->stack)->nodeName, + array('table', 'tbody', 'tfoot', 'thead', 'tr'))) { + /* The foster parent element is the parent element of the last + table element in the stack of open elements, if there is a + table element and it has such a parent element. If there is no + table element in the stack of open elements (innerHTML case), + then the foster parent element is the first element in the + stack of open elements (the html element). Otherwise, if there + is a table element in the stack of open elements, but the last + table element in the stack of open elements has no parent, or + its parent node is not an element, then the foster parent + element is the element before the last table element in the + stack of open elements. */ + for($n = count($this->stack) - 1; $n >= 0; $n--) { + if($this->stack[$n]->nodeName === 'table') { + $table = $this->stack[$n]; + break; + } + } + + if(isset($table) && $table->parentNode !== null) { + $this->foster_parent = $table->parentNode; + + } elseif(!isset($table)) { + $this->foster_parent = $this->stack[0]; + + } elseif(isset($table) && ($table->parentNode === null || + $table->parentNode->nodeType !== XML_ELEMENT_NODE)) { + $this->foster_parent = $this->stack[$n - 1]; + } + } + + $this->inBody($token); + } + } + + private function inCaption($token) + { + /* An end tag whose tag name is "caption" */ + if($token['type'] === HTML5::ENDTAG && $token['name'] === 'caption') { + /* If the stack of open elements does not have an element in table + scope with the same tag name as the token, this is a parse error. + Ignore the token. (innerHTML case) */ + if(!$this->elementInScope($token['name'], true)) { + // Ignore + + /* Otherwise: */ + } else { + /* Generate implied end tags. */ + $this->generateImpliedEndTags(); + + /* Now, if the current node is not a caption element, then this + is a parse error. */ + // w/e + + /* Pop elements from this stack until a caption element has + been popped from the stack. */ + while(true) { + $node = end($this->stack)->nodeName; + array_pop($this->stack); + + if($node === 'caption') { + break; + } + } + + /* Clear the list of active formatting elements up to the last + marker. */ + $this->clearTheActiveFormattingElementsUpToTheLastMarker(); + + /* Switch the insertion mode to "in table". */ + $this->mode = self::IN_TABLE; + } + + /* A start tag whose tag name is one of: "caption", "col", "colgroup", + "tbody", "td", "tfoot", "th", "thead", "tr", or an end tag whose tag + name is "table" */ + } elseif(($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', + 'thead', 'tr'))) || ($token['type'] === HTML5::ENDTAG && + $token['name'] === 'table')) { + /* Parse error. Act as if an end tag with the tag name "caption" + had been seen, then, if that token wasn't ignored, reprocess the + current token. */ + $this->inCaption(array( + 'name' => 'caption', + 'type' => HTML5::ENDTAG + )); + + return $this->inTable($token); + + /* An end tag whose tag name is one of: "body", "col", "colgroup", + "html", "tbody", "td", "tfoot", "th", "thead", "tr" */ + } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], + array('body', 'col', 'colgroup', 'html', 'tbody', 'tfoot', 'th', + 'thead', 'tr'))) { + // Parse error. Ignore the token. + + /* Anything else */ + } else { + /* Process the token as if the insertion mode was "in body". */ + $this->inBody($token); + } + } + + private function inColumnGroup($token) + { + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + if($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Append the character to the current node. */ + $text = $this->dom->createTextNode($token['data']); + end($this->stack)->appendChild($text); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data + attribute set to the data given in the comment token. */ + $comment = $this->dom->createComment($token['data']); + end($this->stack)->appendChild($comment); + + /* A start tag whose tag name is "col" */ + } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'col') { + /* Insert a col element for the token. Immediately pop the current + node off the stack of open elements. */ + $this->insertElement($token); + array_pop($this->stack); + + /* An end tag whose tag name is "colgroup" */ + } elseif($token['type'] === HTML5::ENDTAG && + $token['name'] === 'colgroup') { + /* If the current node is the root html element, then this is a + parse error, ignore the token. (innerHTML case) */ + if(end($this->stack)->nodeName === 'html') { + // Ignore + + /* Otherwise, pop the current node (which will be a colgroup + element) from the stack of open elements. Switch the insertion + mode to "in table". */ + } else { + array_pop($this->stack); + $this->mode = self::IN_TABLE; + } + + /* An end tag whose tag name is "col" */ + } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'col') { + /* Parse error. Ignore the token. */ + + /* Anything else */ + } else { + /* Act as if an end tag with the tag name "colgroup" had been seen, + and then, if that token wasn't ignored, reprocess the current token. */ + $this->inColumnGroup(array( + 'name' => 'colgroup', + 'type' => HTML5::ENDTAG + )); + + return $this->inTable($token); + } + } + + private function inTableBody($token) + { + $clear = array('tbody', 'tfoot', 'thead', 'html'); + + /* A start tag whose tag name is "tr" */ + if($token['type'] === HTML5::STARTTAG && $token['name'] === 'tr') { + /* Clear the stack back to a table body context. */ + $this->clearStackToTableContext($clear); + + /* Insert a tr element for the token, then switch the insertion + mode to "in row". */ + $this->insertElement($token); + $this->mode = self::IN_ROW; + + /* A start tag whose tag name is one of: "th", "td" */ + } elseif($token['type'] === HTML5::STARTTAG && + ($token['name'] === 'th' || $token['name'] === 'td')) { + /* Parse error. Act as if a start tag with the tag name "tr" had + been seen, then reprocess the current token. */ + $this->inTableBody(array( + 'name' => 'tr', + 'type' => HTML5::STARTTAG, + 'attr' => array() + )); + + return $this->inRow($token); + + /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */ + } elseif($token['type'] === HTML5::ENDTAG && + in_array($token['name'], array('tbody', 'tfoot', 'thead'))) { + /* If the stack of open elements does not have an element in table + scope with the same tag name as the token, this is a parse error. + Ignore the token. */ + if(!$this->elementInScope($token['name'], true)) { + // Ignore + + /* Otherwise: */ + } else { + /* Clear the stack back to a table body context. */ + $this->clearStackToTableContext($clear); + + /* Pop the current node from the stack of open elements. Switch + the insertion mode to "in table". */ + array_pop($this->stack); + $this->mode = self::IN_TABLE; + } + + /* A start tag whose tag name is one of: "caption", "col", "colgroup", + "tbody", "tfoot", "thead", or an end tag whose tag name is "table" */ + } elseif(($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('caption', 'col', 'colgroup', 'tbody', 'tfoor', 'thead'))) || + ($token['type'] === HTML5::STARTTAG && $token['name'] === 'table')) { + /* If the stack of open elements does not have a tbody, thead, or + tfoot element in table scope, this is a parse error. Ignore the + token. (innerHTML case) */ + if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), true)) { + // Ignore. + + /* Otherwise: */ + } else { + /* Clear the stack back to a table body context. */ + $this->clearStackToTableContext($clear); + + /* Act as if an end tag with the same tag name as the current + node ("tbody", "tfoot", or "thead") had been seen, then + reprocess the current token. */ + $this->inTableBody(array( + 'name' => end($this->stack)->nodeName, + 'type' => HTML5::ENDTAG + )); + + return $this->mainPhase($token); + } + + /* An end tag whose tag name is one of: "body", "caption", "col", + "colgroup", "html", "td", "th", "tr" */ + } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], + array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) { + /* Parse error. Ignore the token. */ + + /* Anything else */ + } else { + /* Process the token as if the insertion mode was "in table". */ + $this->inTable($token); + } + } + + private function inRow($token) + { + $clear = array('tr', 'html'); + + /* A start tag whose tag name is one of: "th", "td" */ + if($token['type'] === HTML5::STARTTAG && + ($token['name'] === 'th' || $token['name'] === 'td')) { + /* Clear the stack back to a table row context. */ + $this->clearStackToTableContext($clear); + + /* Insert an HTML element for the token, then switch the insertion + mode to "in cell". */ + $this->insertElement($token); + $this->mode = self::IN_CELL; + + /* Insert a marker at the end of the list of active formatting + elements. */ + $this->a_formatting[] = self::MARKER; + + /* An end tag whose tag name is "tr" */ + } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'tr') { + /* If the stack of open elements does not have an element in table + scope with the same tag name as the token, this is a parse error. + Ignore the token. (innerHTML case) */ + if(!$this->elementInScope($token['name'], true)) { + // Ignore. + + /* Otherwise: */ + } else { + /* Clear the stack back to a table row context. */ + $this->clearStackToTableContext($clear); + + /* Pop the current node (which will be a tr element) from the + stack of open elements. Switch the insertion mode to "in table + body". */ + array_pop($this->stack); + $this->mode = self::IN_TBODY; + } + + /* A start tag whose tag name is one of: "caption", "col", "colgroup", + "tbody", "tfoot", "thead", "tr" or an end tag whose tag name is "table" */ + } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr'))) { + /* Act as if an end tag with the tag name "tr" had been seen, then, + if that token wasn't ignored, reprocess the current token. */ + $this->inRow(array( + 'name' => 'tr', + 'type' => HTML5::ENDTAG + )); + + return $this->inCell($token); + + /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */ + } elseif($token['type'] === HTML5::ENDTAG && + in_array($token['name'], array('tbody', 'tfoot', 'thead'))) { + /* If the stack of open elements does not have an element in table + scope with the same tag name as the token, this is a parse error. + Ignore the token. */ + if(!$this->elementInScope($token['name'], true)) { + // Ignore. + + /* Otherwise: */ + } else { + /* Otherwise, act as if an end tag with the tag name "tr" had + been seen, then reprocess the current token. */ + $this->inRow(array( + 'name' => 'tr', + 'type' => HTML5::ENDTAG + )); + + return $this->inCell($token); + } + + /* An end tag whose tag name is one of: "body", "caption", "col", + "colgroup", "html", "td", "th" */ + } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], + array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) { + /* Parse error. Ignore the token. */ + + /* Anything else */ + } else { + /* Process the token as if the insertion mode was "in table". */ + $this->inTable($token); + } + } + + private function inCell($token) + { + /* An end tag whose tag name is one of: "td", "th" */ + if($token['type'] === HTML5::ENDTAG && + ($token['name'] === 'td' || $token['name'] === 'th')) { + /* If the stack of open elements does not have an element in table + scope with the same tag name as that of the token, then this is a + parse error and the token must be ignored. */ + if(!$this->elementInScope($token['name'], true)) { + // Ignore. + + /* Otherwise: */ + } else { + /* Generate implied end tags, except for elements with the same + tag name as the token. */ + $this->generateImpliedEndTags(array($token['name'])); + + /* Now, if the current node is not an element with the same tag + name as the token, then this is a parse error. */ + // k + + /* Pop elements from this stack until an element with the same + tag name as the token has been popped from the stack. */ + while(true) { + $node = end($this->stack)->nodeName; + array_pop($this->stack); + + if($node === $token['name']) { + break; + } + } + + /* Clear the list of active formatting elements up to the last + marker. */ + $this->clearTheActiveFormattingElementsUpToTheLastMarker(); + + /* Switch the insertion mode to "in row". (The current node + will be a tr element at this point.) */ + $this->mode = self::IN_ROW; + } + + /* A start tag whose tag name is one of: "caption", "col", "colgroup", + "tbody", "td", "tfoot", "th", "thead", "tr" */ + } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', + 'thead', 'tr'))) { + /* If the stack of open elements does not have a td or th element + in table scope, then this is a parse error; ignore the token. + (innerHTML case) */ + if(!$this->elementInScope(array('td', 'th'), true)) { + // Ignore. + + /* Otherwise, close the cell (see below) and reprocess the current + token. */ + } else { + $this->closeCell(); + return $this->inRow($token); + } + + /* A start tag whose tag name is one of: "caption", "col", "colgroup", + "tbody", "td", "tfoot", "th", "thead", "tr" */ + } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'], + array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', + 'thead', 'tr'))) { + /* If the stack of open elements does not have a td or th element + in table scope, then this is a parse error; ignore the token. + (innerHTML case) */ + if(!$this->elementInScope(array('td', 'th'), true)) { + // Ignore. + + /* Otherwise, close the cell (see below) and reprocess the current + token. */ + } else { + $this->closeCell(); + return $this->inRow($token); + } + + /* An end tag whose tag name is one of: "body", "caption", "col", + "colgroup", "html" */ + } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], + array('body', 'caption', 'col', 'colgroup', 'html'))) { + /* Parse error. Ignore the token. */ + + /* An end tag whose tag name is one of: "table", "tbody", "tfoot", + "thead", "tr" */ + } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'], + array('table', 'tbody', 'tfoot', 'thead', 'tr'))) { + /* If the stack of open elements does not have an element in table + scope with the same tag name as that of the token (which can only + happen for "tbody", "tfoot" and "thead", or, in the innerHTML case), + then this is a parse error and the token must be ignored. */ + if(!$this->elementInScope($token['name'], true)) { + // Ignore. + + /* Otherwise, close the cell (see below) and reprocess the current + token. */ + } else { + $this->closeCell(); + return $this->inRow($token); + } + + /* Anything else */ + } else { + /* Process the token as if the insertion mode was "in body". */ + $this->inBody($token); + } + } + + private function inSelect($token) + { + /* Handle the token as follows: */ + + /* A character token */ + if($token['type'] === HTML5::CHARACTR) { + /* Append the token's character to the current node. */ + $this->insertText($token['data']); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data + attribute set to the data given in the comment token. */ + $this->insertComment($token['data']); + + /* A start tag token whose tag name is "option" */ + } elseif($token['type'] === HTML5::STARTTAG && + $token['name'] === 'option') { + /* If the current node is an option element, act as if an end tag + with the tag name "option" had been seen. */ + if(end($this->stack)->nodeName === 'option') { + $this->inSelect(array( + 'name' => 'option', + 'type' => HTML5::ENDTAG + )); + } + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* A start tag token whose tag name is "optgroup" */ + } elseif($token['type'] === HTML5::STARTTAG && + $token['name'] === 'optgroup') { + /* If the current node is an option element, act as if an end tag + with the tag name "option" had been seen. */ + if(end($this->stack)->nodeName === 'option') { + $this->inSelect(array( + 'name' => 'option', + 'type' => HTML5::ENDTAG + )); + } + + /* If the current node is an optgroup element, act as if an end tag + with the tag name "optgroup" had been seen. */ + if(end($this->stack)->nodeName === 'optgroup') { + $this->inSelect(array( + 'name' => 'optgroup', + 'type' => HTML5::ENDTAG + )); + } + + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* An end tag token whose tag name is "optgroup" */ + } elseif($token['type'] === HTML5::ENDTAG && + $token['name'] === 'optgroup') { + /* First, if the current node is an option element, and the node + immediately before it in the stack of open elements is an optgroup + element, then act as if an end tag with the tag name "option" had + been seen. */ + $elements_in_stack = count($this->stack); + + if($this->stack[$elements_in_stack - 1]->nodeName === 'option' && + $this->stack[$elements_in_stack - 2]->nodeName === 'optgroup') { + $this->inSelect(array( + 'name' => 'option', + 'type' => HTML5::ENDTAG + )); + } + + /* If the current node is an optgroup element, then pop that node + from the stack of open elements. Otherwise, this is a parse error, + ignore the token. */ + if($this->stack[$elements_in_stack - 1] === 'optgroup') { + array_pop($this->stack); + } + + /* An end tag token whose tag name is "option" */ + } elseif($token['type'] === HTML5::ENDTAG && + $token['name'] === 'option') { + /* If the current node is an option element, then pop that node + from the stack of open elements. Otherwise, this is a parse error, + ignore the token. */ + if(end($this->stack)->nodeName === 'option') { + array_pop($this->stack); + } + + /* An end tag whose tag name is "select" */ + } elseif($token['type'] === HTML5::ENDTAG && + $token['name'] === 'select') { + /* If the stack of open elements does not have an element in table + scope with the same tag name as the token, this is a parse error. + Ignore the token. (innerHTML case) */ + if(!$this->elementInScope($token['name'], true)) { + // w/e + + /* Otherwise: */ + } else { + /* Pop elements from the stack of open elements until a select + element has been popped from the stack. */ + while(true) { + $current = end($this->stack)->nodeName; + array_pop($this->stack); + + if($current === 'select') { + break; + } + } + + /* Reset the insertion mode appropriately. */ + $this->resetInsertionMode(); + } + + /* A start tag whose tag name is "select" */ + } elseif($token['name'] === 'select' && + $token['type'] === HTML5::STARTTAG) { + /* Parse error. Act as if the token had been an end tag with the + tag name "select" instead. */ + $this->inSelect(array( + 'name' => 'select', + 'type' => HTML5::ENDTAG + )); + + /* An end tag whose tag name is one of: "caption", "table", "tbody", + "tfoot", "thead", "tr", "td", "th" */ + } elseif(in_array($token['name'], array('caption', 'table', 'tbody', + 'tfoot', 'thead', 'tr', 'td', 'th')) && $token['type'] === HTML5::ENDTAG) { + /* Parse error. */ + // w/e + + /* If the stack of open elements has an element in table scope with + the same tag name as that of the token, then act as if an end tag + with the tag name "select" had been seen, and reprocess the token. + Otherwise, ignore the token. */ + if($this->elementInScope($token['name'], true)) { + $this->inSelect(array( + 'name' => 'select', + 'type' => HTML5::ENDTAG + )); + + $this->mainPhase($token); + } + + /* Anything else */ + } else { + /* Parse error. Ignore the token. */ + } + } + + private function afterBody($token) + { + /* Handle the token as follows: */ + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + if($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Process the token as it would be processed if the insertion mode + was "in body". */ + $this->inBody($token); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the first element in the stack of open + elements (the html element), with the data attribute set to the + data given in the comment token. */ + $comment = $this->dom->createComment($token['data']); + $this->stack[0]->appendChild($comment); + + /* An end tag with the tag name "html" */ + } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') { + /* If the parser was originally created in order to handle the + setting of an element's innerHTML attribute, this is a parse error; + ignore the token. (The element will be an html element in this + case.) (innerHTML case) */ + + /* Otherwise, switch to the trailing end phase. */ + $this->phase = self::END_PHASE; + + /* Anything else */ + } else { + /* Parse error. Set the insertion mode to "in body" and reprocess + the token. */ + $this->mode = self::IN_BODY; + return $this->inBody($token); + } + } + + private function inFrameset($token) + { + /* Handle the token as follows: */ + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */ + if($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Append the character to the current node. */ + $this->insertText($token['data']); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data + attribute set to the data given in the comment token. */ + $this->insertComment($token['data']); + + /* A start tag with the tag name "frameset" */ + } elseif($token['name'] === 'frameset' && + $token['type'] === HTML5::STARTTAG) { + $this->insertElement($token); + + /* An end tag with the tag name "frameset" */ + } elseif($token['name'] === 'frameset' && + $token['type'] === HTML5::ENDTAG) { + /* If the current node is the root html element, then this is a + parse error; ignore the token. (innerHTML case) */ + if(end($this->stack)->nodeName === 'html') { + // Ignore + + } else { + /* Otherwise, pop the current node from the stack of open + elements. */ + array_pop($this->stack); + + /* If the parser was not originally created in order to handle + the setting of an element's innerHTML attribute (innerHTML case), + and the current node is no longer a frameset element, then change + the insertion mode to "after frameset". */ + $this->mode = self::AFTR_FRAME; + } + + /* A start tag with the tag name "frame" */ + } elseif($token['name'] === 'frame' && + $token['type'] === HTML5::STARTTAG) { + /* Insert an HTML element for the token. */ + $this->insertElement($token); + + /* Immediately pop the current node off the stack of open elements. */ + array_pop($this->stack); + + /* A start tag with the tag name "noframes" */ + } elseif($token['name'] === 'noframes' && + $token['type'] === HTML5::STARTTAG) { + /* Process the token as if the insertion mode had been "in body". */ + $this->inBody($token); + + /* Anything else */ + } else { + /* Parse error. Ignore the token. */ + } + } + + private function afterFrameset($token) + { + /* Handle the token as follows: */ + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */ + if($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Append the character to the current node. */ + $this->insertText($token['data']); + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the current node with the data + attribute set to the data given in the comment token. */ + $this->insertComment($token['data']); + + /* An end tag with the tag name "html" */ + } elseif($token['name'] === 'html' && + $token['type'] === HTML5::ENDTAG) { + /* Switch to the trailing end phase. */ + $this->phase = self::END_PHASE; + + /* A start tag with the tag name "noframes" */ + } elseif($token['name'] === 'noframes' && + $token['type'] === HTML5::STARTTAG) { + /* Process the token as if the insertion mode had been "in body". */ + $this->inBody($token); + + /* Anything else */ + } else { + /* Parse error. Ignore the token. */ + } + } + + private function trailingEndPhase($token) + { + /* After the main phase, as each token is emitted from the tokenisation + stage, it must be processed as described in this section. */ + + /* A DOCTYPE token */ + if($token['type'] === HTML5::DOCTYPE) { + // Parse error. Ignore the token. + + /* A comment token */ + } elseif($token['type'] === HTML5::COMMENT) { + /* Append a Comment node to the Document object with the data + attribute set to the data given in the comment token. */ + $comment = $this->dom->createComment($token['data']); + $this->dom->appendChild($comment); + + /* A character token that is one of one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE */ + } elseif($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) { + /* Process the token as it would be processed in the main phase. */ + $this->mainPhase($token); + + /* A character token that is not one of U+0009 CHARACTER TABULATION, + U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF), + or U+0020 SPACE. Or a start tag token. Or an end tag token. */ + } elseif(($token['type'] === HTML5::CHARACTR && + preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || + $token['type'] === HTML5::STARTTAG || $token['type'] === HTML5::ENDTAG) { + /* Parse error. Switch back to the main phase and reprocess the + token. */ + $this->phase = self::MAIN_PHASE; + return $this->mainPhase($token); + + /* An end-of-file token */ + } elseif($token['type'] === HTML5::EOF) { + /* OMG DONE!! */ + } + } + + private function insertElement($token, $append = true) + { + $el = $this->dom->createElement($token['name']); + + foreach($token['attr'] as $attr) { + if(!$el->hasAttribute($attr['name'])) { + $el->setAttribute($attr['name'], $attr['value']); + } + } + + $this->appendToRealParent($el); + $this->stack[] = $el; + + return $el; + } + + private function insertText($data) + { + $text = $this->dom->createTextNode($data); + $this->appendToRealParent($text); + } + + private function insertComment($data) + { + $comment = $this->dom->createComment($data); + $this->appendToRealParent($comment); + } + + private function appendToRealParent($node) + { + if($this->foster_parent === null) { + end($this->stack)->appendChild($node); + + } elseif($this->foster_parent !== null) { + /* If the foster parent element is the parent element of the + last table element in the stack of open elements, then the new + node must be inserted immediately before the last table element + in the stack of open elements in the foster parent element; + otherwise, the new node must be appended to the foster parent + element. */ + for($n = count($this->stack) - 1; $n >= 0; $n--) { + if($this->stack[$n]->nodeName === 'table' && + $this->stack[$n]->parentNode !== null) { + $table = $this->stack[$n]; + break; + } + } + + if(isset($table) && $this->foster_parent->isSameNode($table->parentNode)) + $this->foster_parent->insertBefore($node, $table); + else + $this->foster_parent->appendChild($node); + + $this->foster_parent = null; + } + } + + private function elementInScope($el, $table = false) + { + if(is_array($el)) { + foreach($el as $element) { + if($this->elementInScope($element, $table)) { + return true; + } + } + + return false; + } + + $leng = count($this->stack); + + for($n = 0; $n < $leng; $n++) { + /* 1. Initialise node to be the current node (the bottommost node of + the stack). */ + $node = $this->stack[$leng - 1 - $n]; + + if($node->tagName === $el) { + /* 2. If node is the target node, terminate in a match state. */ + return true; + + } elseif($node->tagName === 'table') { + /* 3. Otherwise, if node is a table element, terminate in a failure + state. */ + return false; + + } elseif($table === true && in_array($node->tagName, array('caption', 'td', + 'th', 'button', 'marquee', 'object'))) { + /* 4. Otherwise, if the algorithm is the "has an element in scope" + variant (rather than the "has an element in table scope" variant), + and node is one of the following, terminate in a failure state. */ + return false; + + } elseif($node === $node->ownerDocument->documentElement) { + /* 5. Otherwise, if node is an html element (root element), terminate + in a failure state. (This can only happen if the node is the topmost + node of the stack of open elements, and prevents the next step from + being invoked if there are no more elements in the stack.) */ + return false; + } + + /* Otherwise, set node to the previous entry in the stack of open + elements and return to step 2. (This will never fail, since the loop + will always terminate in the previous step if the top of the stack + is reached.) */ + } + } + + private function reconstructActiveFormattingElements() + { + /* 1. If there are no entries in the list of active formatting elements, + then there is nothing to reconstruct; stop this algorithm. */ + $formatting_elements = count($this->a_formatting); + + if($formatting_elements === 0) { + return false; + } + + /* 3. Let entry be the last (most recently added) element in the list + of active formatting elements. */ + $entry = end($this->a_formatting); + + /* 2. If the last (most recently added) entry in the list of active + formatting elements is a marker, or if it is an element that is in the + stack of open elements, then there is nothing to reconstruct; stop this + algorithm. */ + if($entry === self::MARKER || in_array($entry, $this->stack, true)) { + return false; + } + + for($a = $formatting_elements - 1; $a >= 0; true) { + /* 4. If there are no entries before entry in the list of active + formatting elements, then jump to step 8. */ + if($a === 0) { + $step_seven = false; + break; + } + + /* 5. Let entry be the entry one earlier than entry in the list of + active formatting elements. */ + $a--; + $entry = $this->a_formatting[$a]; + + /* 6. If entry is neither a marker nor an element that is also in + thetack of open elements, go to step 4. */ + if($entry === self::MARKER || in_array($entry, $this->stack, true)) { + break; + } + } + + while(true) { + /* 7. Let entry be the element one later than entry in the list of + active formatting elements. */ + if(isset($step_seven) && $step_seven === true) { + $a++; + $entry = $this->a_formatting[$a]; + } + + /* 8. Perform a shallow clone of the element entry to obtain clone. */ + $clone = $entry->cloneNode(); + + /* 9. Append clone to the current node and push it onto the stack + of open elements so that it is the new current node. */ + end($this->stack)->appendChild($clone); + $this->stack[] = $clone; + + /* 10. Replace the entry for entry in the list with an entry for + clone. */ + $this->a_formatting[$a] = $clone; + + /* 11. If the entry for clone in the list of active formatting + elements is not the last entry in the list, return to step 7. */ + if(end($this->a_formatting) !== $clone) { + $step_seven = true; + } else { + break; + } + } + } + + private function clearTheActiveFormattingElementsUpToTheLastMarker() + { + /* When the steps below require the UA to clear the list of active + formatting elements up to the last marker, the UA must perform the + following steps: */ + + while(true) { + /* 1. Let entry be the last (most recently added) entry in the list + of active formatting elements. */ + $entry = end($this->a_formatting); + + /* 2. Remove entry from the list of active formatting elements. */ + array_pop($this->a_formatting); + + /* 3. If entry was a marker, then stop the algorithm at this point. + The list has been cleared up to the last marker. */ + if($entry === self::MARKER) { + break; + } + } + } + + private function generateImpliedEndTags(array $exclude = array()) + { + /* When the steps below require the UA to generate implied end tags, + then, if the current node is a dd element, a dt element, an li element, + a p element, a td element, a th element, or a tr element, the UA must + act as if an end tag with the respective tag name had been seen and + then generate implied end tags again. */ + $node = end($this->stack); + $elements = array_diff(array('dd', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude); + + while(in_array(end($this->stack)->nodeName, $elements)) { + array_pop($this->stack); + } + } + + private function getElementCategory($name) + { + if(in_array($name, $this->special)) + return self::SPECIAL; + + elseif(in_array($name, $this->scoping)) + return self::SCOPING; + + elseif(in_array($name, $this->formatting)) + return self::FORMATTING; + + else + return self::PHRASING; + } + + private function clearStackToTableContext($elements) + { + /* When the steps above require the UA to clear the stack back to a + table context, it means that the UA must, while the current node is not + a table element or an html element, pop elements from the stack of open + elements. If this causes any elements to be popped from the stack, then + this is a parse error. */ + while(true) { + $node = end($this->stack)->nodeName; + + if(in_array($node, $elements)) { + break; + } else { + array_pop($this->stack); + } + } + } + + private function resetInsertionMode() + { + /* 1. Let last be false. */ + $last = false; + $leng = count($this->stack); + + for($n = $leng - 1; $n >= 0; $n--) { + /* 2. Let node be the last node in the stack of open elements. */ + $node = $this->stack[$n]; + + /* 3. If node is the first node in the stack of open elements, then + set last to true. If the element whose innerHTML attribute is being + set is neither a td element nor a th element, then set node to the + element whose innerHTML attribute is being set. (innerHTML case) */ + if($this->stack[0]->isSameNode($node)) { + $last = true; + } + + /* 4. If node is a select element, then switch the insertion mode to + "in select" and abort these steps. (innerHTML case) */ + if($node->nodeName === 'select') { + $this->mode = self::IN_SELECT; + break; + + /* 5. If node is a td or th element, then switch the insertion mode + to "in cell" and abort these steps. */ + } elseif($node->nodeName === 'td' || $node->nodeName === 'th') { + $this->mode = self::IN_CELL; + break; + + /* 6. If node is a tr element, then switch the insertion mode to + "in row" and abort these steps. */ + } elseif($node->nodeName === 'tr') { + $this->mode = self::IN_ROW; + break; + + /* 7. If node is a tbody, thead, or tfoot element, then switch the + insertion mode to "in table body" and abort these steps. */ + } elseif(in_array($node->nodeName, array('tbody', 'thead', 'tfoot'))) { + $this->mode = self::IN_TBODY; + break; + + /* 8. If node is a caption element, then switch the insertion mode + to "in caption" and abort these steps. */ + } elseif($node->nodeName === 'caption') { + $this->mode = self::IN_CAPTION; + break; + + /* 9. If node is a colgroup element, then switch the insertion mode + to "in column group" and abort these steps. (innerHTML case) */ + } elseif($node->nodeName === 'colgroup') { + $this->mode = self::IN_CGROUP; + break; + + /* 10. If node is a table element, then switch the insertion mode + to "in table" and abort these steps. */ + } elseif($node->nodeName === 'table') { + $this->mode = self::IN_TABLE; + break; + + /* 11. If node is a head element, then switch the insertion mode + to "in body" ("in body"! not "in head"!) and abort these steps. + (innerHTML case) */ + } elseif($node->nodeName === 'head') { + $this->mode = self::IN_BODY; + break; + + /* 12. If node is a body element, then switch the insertion mode to + "in body" and abort these steps. */ + } elseif($node->nodeName === 'body') { + $this->mode = self::IN_BODY; + break; + + /* 13. If node is a frameset element, then switch the insertion + mode to "in frameset" and abort these steps. (innerHTML case) */ + } elseif($node->nodeName === 'frameset') { + $this->mode = self::IN_FRAME; + break; + + /* 14. If node is an html element, then: if the head element + pointer is null, switch the insertion mode to "before head", + otherwise, switch the insertion mode to "after head". In either + case, abort these steps. (innerHTML case) */ + } elseif($node->nodeName === 'html') { + $this->mode = ($this->head_pointer === null) + ? self::BEFOR_HEAD + : self::AFTER_HEAD; + + break; + + /* 15. If last is true, then set the insertion mode to "in body" + and abort these steps. (innerHTML case) */ + } elseif($last) { + $this->mode = self::IN_BODY; + break; + } + } + } + + private function closeCell() + { + /* If the stack of open elements has a td or th element in table scope, + then act as if an end tag token with that tag name had been seen. */ + foreach(array('td', 'th') as $cell) { + if($this->elementInScope($cell, true)) { + $this->inCell(array( + 'name' => $cell, + 'type' => HTML5::ENDTAG + )); + + break; + } + } + } + + public function save() + { + return $this->dom; + } +} diff --git a/vendor/ezyang/htmlpurifier/maintenance/add-vimline.php b/vendor/ezyang/htmlpurifier/maintenance/add-vimline.php new file mode 100644 index 000000000..d6a8eb202 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/add-vimline.php @@ -0,0 +1,130 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +/** + * @file + * Adds vimline to files + */ + +chdir(dirname(__FILE__) . '/..'); +$FS = new FSTools(); + +$vimline = 'vim: et sw=4 sts=4'; + +$files = $FS->globr('.', '*'); +foreach ($files as $file) { + if ( + !is_file($file) || + prefix_is('./docs/doxygen', $file) || + prefix_is('./library/standalone', $file) || + prefix_is('./docs/specimens', $file) || + postfix_is('.ser', $file) || + postfix_is('.tgz', $file) || + postfix_is('.patch', $file) || + postfix_is('.dtd', $file) || + postfix_is('.ent', $file) || + postfix_is('.png', $file) || + postfix_is('.ico', $file) || + // wontfix + postfix_is('.vtest', $file) || + postfix_is('.svg', $file) || + postfix_is('.phpt', $file) || + postfix_is('VERSION', $file) || + postfix_is('WHATSNEW', $file) || + postfix_is('configdoc/usage.xml', $file) || + postfix_is('library/HTMLPurifier.includes.php', $file) || + postfix_is('library/HTMLPurifier.safe-includes.php', $file) || + postfix_is('smoketests/xssAttacks.xml', $file) || + // phpt files + postfix_is('.diff', $file) || + postfix_is('.exp', $file) || + postfix_is('.log', $file) || + postfix_is('.out', $file) || + + $file == './library/HTMLPurifier/Lexer/PH5P.php' || + $file == './maintenance/PH5P.php' + ) continue; + $ext = strrchr($file, '.'); + if ( + postfix_is('README', $file) || + postfix_is('LICENSE', $file) || + postfix_is('CREDITS', $file) || + postfix_is('INSTALL', $file) || + postfix_is('NEWS', $file) || + postfix_is('TODO', $file) || + postfix_is('WYSIWYG', $file) || + postfix_is('Changelog', $file) + ) $ext = '.txt'; + if (postfix_is('Doxyfile', $file)) $ext = 'Doxyfile'; + if (postfix_is('.php.in', $file)) $ext = '.php'; + $no_nl = false; + switch ($ext) { + case '.php': + case '.inc': + case '.js': + $line = '// %s'; + break; + case '.html': + case '.xsl': + case '.xml': + case '.htc': + $line = "<!-- %s\n-->"; + break; + case '.htmlt': + $no_nl = true; + $line = '--# %s'; + break; + case '.ini': + $line = '; %s'; + break; + case '.css': + $line = '/* %s */'; + break; + case '.bat': + $line = 'rem %s'; + break; + case '.txt': + case '.utf8': + if ( + prefix_is('./library/HTMLPurifier/ConfigSchema', $file) || + prefix_is('./smoketests/test-schema', $file) || + prefix_is('./tests/HTMLPurifier/StringHashParser', $file) + ) { + $no_nl = true; + $line = '--# %s'; + } else { + $line = ' %s'; + } + break; + case 'Doxyfile': + $line = '# %s'; + break; + default: + throw new Exception('Unknown file: ' . $file); + } + + echo "$file\n"; + $contents = file_get_contents($file); + + $regex = '~' . str_replace('%s', 'vim: .+', preg_quote($line, '~')) . '~m'; + $contents = preg_replace($regex, '', $contents); + + $contents = rtrim($contents); + + if (strpos($contents, "\r\n") !== false) $nl = "\r\n"; + elseif (strpos($contents, "\n") !== false) $nl = "\n"; + elseif (strpos($contents, "\r") !== false) $nl = "\r"; + else $nl = PHP_EOL; + + if (!$no_nl) $contents .= $nl; + $contents .= $nl . str_replace('%s', $vimline, $line) . $nl; + + file_put_contents($file, $contents); + +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/common.php b/vendor/ezyang/htmlpurifier/maintenance/common.php new file mode 100644 index 000000000..342bc205a --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/common.php @@ -0,0 +1,25 @@ +<?php + +function assertCli() +{ + if (php_sapi_name() != 'cli' && !getenv('PHP_IS_CLI')) { + echo 'Script cannot be called from web-browser (if you are indeed calling via cli, +set environment variable PHP_IS_CLI to work around this).'; + exit(1); + } +} + +function prefix_is($comp, $subject) +{ + return strncmp($comp, $subject, strlen($comp)) === 0; +} + +function postfix_is($comp, $subject) +{ + return strlen($subject) < $comp ? false : substr($subject, -strlen($comp)) === $comp; +} + +// Load useful stuff like FSTools +require_once dirname(__FILE__) . '/../extras/HTMLPurifierExtras.auto.php'; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/compile-doxygen.sh b/vendor/ezyang/htmlpurifier/maintenance/compile-doxygen.sh new file mode 100755 index 000000000..ecd1127fd --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/compile-doxygen.sh @@ -0,0 +1,11 @@ +#!/bin/bash +cd .. +mkdir docs/doxygen +rm -Rf docs/doxygen/* +doxygen 1>docs/doxygen/info.log 2>docs/doxygen/errors.log +if [ "$?" != 0 ]; then + cat docs/doxygen/errors.log + exit +fi +cd docs +tar czf doxygen.tgz doxygen diff --git a/vendor/ezyang/htmlpurifier/maintenance/config-scanner.php b/vendor/ezyang/htmlpurifier/maintenance/config-scanner.php new file mode 100644 index 000000000..c614d1fbc --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/config-scanner.php @@ -0,0 +1,155 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +require_once '../library/HTMLPurifier.auto.php'; +assertCli(); + +if (version_compare(PHP_VERSION, '5.2.2', '<')) { + echo "This script requires PHP 5.2.2 or later, for tokenizer line numbers."; + exit(1); +} + +/** + * @file + * Scans HTML Purifier source code for $config tokens and records the + * directive being used; configdoc can use this info later. + * + * Currently, this just dumps all the info onto the console. Eventually, it + * will create an XML file that our XSLT transform can use. + */ + +$FS = new FSTools(); +chdir(dirname(__FILE__) . '/../library/'); +$raw_files = $FS->globr('.', '*.php'); +$files = array(); +foreach ($raw_files as $file) { + $file = substr($file, 2); // rm leading './' + if (strncmp('standalone/', $file, 11) === 0) continue; // rm generated files + if (substr_count($file, '.') > 1) continue; // rm meta files + $files[] = $file; +} + +/** + * Moves the $i cursor to the next non-whitespace token + */ +function consumeWhitespace($tokens, &$i) +{ + do {$i++;} while (is_array($tokens[$i]) && $tokens[$i][0] === T_WHITESPACE); +} + +/** + * Tests whether or not a token is a particular type. There are three run-cases: + * - ($token, $expect_token): tests if the token is $expect_token type; + * - ($token, $expect_value): tests if the token is the string $expect_value; + * - ($token, $expect_token, $expect_value): tests if token is $expect_token type, and + * its string representation is $expect_value + */ +function testToken($token, $value_or_token, $value = null) +{ + if (is_null($value)) { + if (is_int($value_or_token)) return is_array($token) && $token[0] === $value_or_token; + else return $token === $value_or_token; + } else { + return is_array($token) && $token[0] === $value_or_token && $token[1] === $value; + } +} + +$counter = 0; +$full_counter = 0; +$tracker = array(); + +foreach ($files as $file) { + $tokens = token_get_all(file_get_contents($file)); + $file = str_replace('\\', '/', $file); + for ($i = 0, $c = count($tokens); $i < $c; $i++) { + $ok = false; + // Match $config + if (!$ok && testToken($tokens[$i], T_VARIABLE, '$config')) $ok = true; + // Match $this->config + while (!$ok && testToken($tokens[$i], T_VARIABLE, '$this')) { + consumeWhitespace($tokens, $i); + if (!testToken($tokens[$i], T_OBJECT_OPERATOR)) break; + consumeWhitespace($tokens, $i); + if (testToken($tokens[$i], T_STRING, 'config')) $ok = true; + break; + } + if (!$ok) continue; + + $ok = false; + for($i++; $i < $c; $i++) { + if ($tokens[$i] === ',' || $tokens[$i] === ')' || $tokens[$i] === ';') { + break; + } + if (is_string($tokens[$i])) continue; + if ($tokens[$i][0] === T_OBJECT_OPERATOR) { + $ok = true; + break; + } + } + if (!$ok) continue; + + $line = $tokens[$i][2]; + + consumeWhitespace($tokens, $i); + if (!testToken($tokens[$i], T_STRING, 'get')) continue; + + consumeWhitespace($tokens, $i); + if (!testToken($tokens[$i], '(')) continue; + + $full_counter++; + + $matched = false; + do { + + // What we currently don't match are batch retrievals, and + // wildcard retrievals. This data might be useful in the future, + // which is why we have a do {} while loop that doesn't actually + // do anything. + + consumeWhitespace($tokens, $i); + if (!testToken($tokens[$i], T_CONSTANT_ENCAPSED_STRING)) continue; + $id = substr($tokens[$i][1], 1, -1); + + $counter++; + $matched = true; + + if (!isset($tracker[$id])) $tracker[$id] = array(); + if (!isset($tracker[$id][$file])) $tracker[$id][$file] = array(); + $tracker[$id][$file][] = $line; + + } while (0); + + //echo "$file:$line uses $namespace.$directive\n"; + } +} + +echo "\n$counter/$full_counter instances of \$config or \$this->config found in source code.\n"; + +echo "Generating XML... "; + +$xw = new XMLWriter(); +$xw->openURI('../configdoc/usage.xml'); +$xw->setIndent(true); +$xw->startDocument('1.0', 'UTF-8'); +$xw->startElement('usage'); +foreach ($tracker as $id => $files) { + $xw->startElement('directive'); + $xw->writeAttribute('id', $id); + foreach ($files as $file => $lines) { + $xw->startElement('file'); + $xw->writeAttribute('name', $file); + foreach ($lines as $line) { + $xw->writeElement('line', $line); + } + $xw->endElement(); + } + $xw->endElement(); +} +$xw->endElement(); +$xw->flush(); + +echo "done!\n"; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/flush-definition-cache.php b/vendor/ezyang/htmlpurifier/maintenance/flush-definition-cache.php new file mode 100755 index 000000000..138badb65 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/flush-definition-cache.php @@ -0,0 +1,42 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +/** + * @file + * Flushes the definition serial cache. This file should be + * called if changes to any subclasses of HTMLPurifier_Definition + * or related classes (such as HTMLPurifier_HTMLModule) are made. This + * may also be necessary if you've modified a customized version. + * + * @param Accepts one argument, cache type to flush; otherwise flushes all + * the caches. + */ + +echo "Flushing cache... \n"; + +require_once(dirname(__FILE__) . '/../library/HTMLPurifier.auto.php'); + +$config = HTMLPurifier_Config::createDefault(); + +$names = array('HTML', 'CSS', 'URI', 'Test'); +if (isset($argv[1])) { + if (in_array($argv[1], $names)) { + $names = array($argv[1]); + } else { + throw new Exception("Cache parameter {$argv[1]} is not a valid cache"); + } +} + +foreach ($names as $name) { + echo " - Flushing $name\n"; + $cache = new HTMLPurifier_DefinitionCache_Serializer($name); + $cache->flush($config); +} + +echo "Cache flushed successfully.\n"; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/flush.php b/vendor/ezyang/htmlpurifier/maintenance/flush.php new file mode 100644 index 000000000..c0853d230 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/flush.php @@ -0,0 +1,30 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +/** + * @file + * Runs all generation/flush cache scripts to ensure that somewhat volatile + * generated files are up-to-date. + */ + +function e($cmd) +{ + echo "\$ $cmd\n"; + passthru($cmd, $status); + echo "\n"; + if ($status) exit($status); +} + +$php = empty($_SERVER['argv'][1]) ? 'php' : $_SERVER['argv'][1]; + +e($php . ' generate-includes.php'); +e($php . ' generate-schema-cache.php'); +e($php . ' flush-definition-cache.php'); +e($php . ' generate-standalone.php'); +e($php . ' config-scanner.php'); + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/generate-entity-file.php b/vendor/ezyang/htmlpurifier/maintenance/generate-entity-file.php new file mode 100755 index 000000000..ff1713e39 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/generate-entity-file.php @@ -0,0 +1,75 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +/** + * @file + * Parses *.ent files into an entity lookup table, and then serializes and + * writes the whole kaboodle to a file. The resulting file is cached so + * that this script does not need to be run. This script should rarely, + * if ever, be run, since HTML's entities are fairly immutable. + */ + +// here's where the entity files are located, assuming working directory +// is the same as the location of this PHP file. Needs trailing slash. +$entity_dir = '../docs/entities/'; + +// defines the output file for the serialized content. +$output_file = '../library/HTMLPurifier/EntityLookup/entities.ser'; + +// courtesy of a PHP manual comment +function unichr($dec) +{ + if ($dec < 128) { + $utf = chr($dec); + } elseif ($dec < 2048) { + $utf = chr(192 + (($dec - ($dec % 64)) / 64)); + $utf .= chr(128 + ($dec % 64)); + } else { + $utf = chr(224 + (($dec - ($dec % 4096)) / 4096)); + $utf .= chr(128 + ((($dec % 4096) - ($dec % 64)) / 64)); + $utf .= chr(128 + ($dec % 64)); + } + return $utf; +} + +if ( !is_dir($entity_dir) ) exit("Fatal Error: Can't find entity directory.\n"); +if ( file_exists($output_file) ) exit("Fatal Error: output file already exists.\n"); + +$dh = @opendir($entity_dir); +if ( !$dh ) exit("Fatal Error: Cannot read entity directory.\n"); + +$entity_files = array(); +while (($file = readdir($dh)) !== false) { + if (@$file[0] === '.') continue; + if (substr(strrchr($file, "."), 1) !== 'ent') continue; + $entity_files[] = $file; +} +closedir($dh); + +if ( !$entity_files ) exit("Fatal Error: No entity files to parse.\n"); + +$entity_table = array(); +$regexp = '/<!ENTITY\s+([A-Za-z0-9]+)\s+"&#(?:38;#)?([0-9]+);">/'; + +foreach ( $entity_files as $file ) { + $contents = file_get_contents($entity_dir . $file); + $matches = array(); + preg_match_all($regexp, $contents, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $entity_table[$match[1]] = unichr($match[2]); + } +} + +$output = serialize($entity_table); + +$fh = fopen($output_file, 'w'); +fwrite($fh, $output); +fclose($fh); + +echo "Completed successfully."; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/generate-includes.php b/vendor/ezyang/htmlpurifier/maintenance/generate-includes.php new file mode 100644 index 000000000..01e1c2aba --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/generate-includes.php @@ -0,0 +1,192 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +require_once '../tests/path2class.func.php'; +require_once '../library/HTMLPurifier/Bootstrap.php'; +assertCli(); + +/** + * @file + * Generates an include stub for users who do not want to use the autoloader. + * When new files are added to HTML Purifier's main codebase, this file should + * be called. + */ + +chdir(dirname(__FILE__) . '/../library/'); +$FS = new FSTools(); + +$exclude_dirs = array( + 'HTMLPurifier/Language/', + 'HTMLPurifier/ConfigSchema/', + 'HTMLPurifier/Filter/', + 'HTMLPurifier/Printer/', + /* These should be excluded, but need to have ConfigSchema support first + + */ +); +$exclude_files = array( + 'HTMLPurifier/Lexer/PEARSax3.php', + 'HTMLPurifier/Lexer/PH5P.php', + 'HTMLPurifier/Printer.php', +); + +// Determine what files need to be included: +echo 'Scanning for files... '; +$raw_files = $FS->globr('.', '*.php'); +if (!$raw_files) throw new Exception('Did not find any PHP source files'); +$files = array(); +foreach ($raw_files as $file) { + $file = substr($file, 2); // rm leading './' + if (strncmp('standalone/', $file, 11) === 0) continue; // rm generated files + if (substr_count($file, '.') > 1) continue; // rm meta files + $ok = true; + foreach ($exclude_dirs as $dir) { + if (strncmp($dir, $file, strlen($dir)) === 0) { + $ok = false; + break; + } + } + if (!$ok) continue; // rm excluded directories + if (in_array($file, $exclude_files)) continue; // rm excluded files + $files[] = $file; +} +echo "done!\n"; + +// Reorder list so that dependencies are included first: + +/** + * Returns a lookup array of dependencies for a file. + * + * @note This function expects that format $name extends $parent on one line + * + * @param string $file + * File to check dependencies of. + * @return array + * Lookup array of files the file is dependent on, sorted accordingly. + */ +function get_dependency_lookup($file) +{ + static $cache = array(); + if (isset($cache[$file])) return $cache[$file]; + if (!file_exists($file)) { + echo "File doesn't exist: $file\n"; + return array(); + } + $fh = fopen($file, 'r'); + $deps = array(); + while (!feof($fh)) { + $line = fgets($fh); + if (strncmp('class', $line, 5) === 0) { + // The implementation here is fragile and will break if we attempt + // to use interfaces. Beware! + $arr = explode(' extends ', trim($line, ' {'."\n\r"), 2); + if (count($arr) < 2) break; + $parent = $arr[1]; + $dep_file = HTMLPurifier_Bootstrap::getPath($parent); + if (!$dep_file) break; + $deps[$dep_file] = true; + break; + } + } + fclose($fh); + foreach (array_keys($deps) as $file) { + // Extra dependencies must come *before* base dependencies + $deps = get_dependency_lookup($file) + $deps; + } + $cache[$file] = $deps; + return $deps; +} + +/** + * Sorts files based on dependencies. This function is lazy and will not + * group files with dependencies together; it will merely ensure that a file + * is never included before its dependencies are. + * + * @param $files + * Files array to sort. + * @return + * Sorted array ($files is not modified by reference!) + */ +function dep_sort($files) +{ + $ret = array(); + $cache = array(); + foreach ($files as $file) { + if (isset($cache[$file])) continue; + $deps = get_dependency_lookup($file); + foreach (array_keys($deps) as $dep) { + if (!isset($cache[$dep])) { + $ret[] = $dep; + $cache[$dep] = true; + } + } + $cache[$file] = true; + $ret[] = $file; + } + return $ret; +} + +$files = dep_sort($files); + +// Build the actual include stub: + +$version = trim(file_get_contents('../VERSION')); + +// stub +$php = "<?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 $version + * + * @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. + */ + +"; + +foreach ($files as $file) { + $php .= "require '$file';" . PHP_EOL; +} + +echo "Writing HTMLPurifier.includes.php... "; +file_put_contents('HTMLPurifier.includes.php', $php); +echo "done!\n"; + +$php = "<?php + +/** + * @file + * This file was auto-generated by generate-includes.php and includes all of + * the core files required by HTML Purifier. This is a convenience stub that + * includes all files using dirname(__FILE__) and require_once. PLEASE DO NOT + * EDIT THIS FILE, changes will be overwritten the next time the script is run. + * + * Changes to include_path are not necessary. + */ + +\$__dir = dirname(__FILE__); + +"; + +foreach ($files as $file) { + $php .= "require_once \$__dir . '/$file';" . PHP_EOL; +} + +echo "Writing HTMLPurifier.safe-includes.php... "; +file_put_contents('HTMLPurifier.safe-includes.php', $php); +echo "done!\n"; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/generate-ph5p-patch.php b/vendor/ezyang/htmlpurifier/maintenance/generate-ph5p-patch.php new file mode 100644 index 000000000..c92a7d211 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/generate-ph5p-patch.php @@ -0,0 +1,22 @@ +<?php + +/** + * @file + * This file compares our version of PH5P with Jero's original version, and + * generates a patch of the differences. This script should be run whenever + * library/HTMLPurifier/Lexer/PH5P.php is modified. + */ + +$orig = realpath(dirname(__FILE__) . '/PH5P.php'); +$new = realpath(dirname(__FILE__) . '/../library/HTMLPurifier/Lexer/PH5P.php'); +$newt = dirname(__FILE__) . '/PH5P.new.php'; // temporary file + +// minor text-processing of new file to get into same format as original +$new_src = file_get_contents($new); +$new_src = '<?php' . PHP_EOL . substr($new_src, strpos($new_src, 'class HTML5 {')); + +file_put_contents($newt, $new_src); +shell_exec("diff -u \"$orig\" \"$newt\" > PH5P.patch"); +unlink($newt); + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/generate-schema-cache.php b/vendor/ezyang/htmlpurifier/maintenance/generate-schema-cache.php new file mode 100644 index 000000000..339ff12da --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/generate-schema-cache.php @@ -0,0 +1,45 @@ +#!/usr/bin/php +<?php + +require_once dirname(__FILE__) . '/common.php'; +require_once dirname(__FILE__) . '/../library/HTMLPurifier.auto.php'; +assertCli(); + +/** + * @file + * Generates a schema cache file, saving it to + * library/HTMLPurifier/ConfigSchema/schema.ser. + * + * This should be run when new configuration options are added to + * HTML Purifier. A cached version is available via the repository + * so this does not normally have to be regenerated. + * + * If you have a directory containing custom configuration schema files, + * you can simple add a path to that directory as a parameter to + * this, and they will get included. + */ + +$target = dirname(__FILE__) . '/../library/HTMLPurifier/ConfigSchema/schema.ser'; + +$builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder(); +$interchange = new HTMLPurifier_ConfigSchema_Interchange(); + +$builder->buildDir($interchange); + +$loader = dirname(__FILE__) . '/../config-schema.php'; +if (file_exists($loader)) include $loader; +foreach ($_SERVER['argv'] as $i => $dir) { + if ($i === 0) continue; + $builder->buildDir($interchange, realpath($dir)); +} + +$interchange->validate(); + +$schema_builder = new HTMLPurifier_ConfigSchema_Builder_ConfigSchema(); +$schema = $schema_builder->build($interchange); + +echo "Saving schema... "; +file_put_contents($target, serialize($schema)); +echo "done!\n"; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/generate-standalone.php b/vendor/ezyang/htmlpurifier/maintenance/generate-standalone.php new file mode 100755 index 000000000..254d4d83b --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/generate-standalone.php @@ -0,0 +1,159 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +/** + * @file + * Compiles all of HTML Purifier's library files into one big file + * named HTMLPurifier.standalone.php. This is usually called during the + * release process. + */ + +/** + * Global hash that tracks already loaded includes + */ +$GLOBALS['loaded'] = array(); + +/** + * Custom FSTools for this script that overloads some behavior + * @warning The overloading of copy() is not necessarily global for + * this script. Watch out! + */ +class MergeLibraryFSTools extends FSTools +{ + public function copyable($entry) + { + // Skip hidden files + if ($entry[0] == '.') { + return false; + } + return true; + } + public function copy($source, $dest) + { + copy_and_remove_includes($source, $dest); + } +} +$FS = new MergeLibraryFSTools(); + +/** + * Replaces the includes inside PHP source code with the corresponding + * source. + * @param string $text PHP source code to replace includes from + */ +function replace_includes($text) +{ + // also remove vim modelines + return preg_replace_callback( + "/require(?:_once)? ['\"]([^'\"]+)['\"];/", + 'replace_includes_callback', + $text + ); +} + +/** + * Removes leading PHP tags from included files. Assumes that there is + * no trailing tag. Also removes vim modelines. + * @note This is safe for files that have internal <?php + * @param string $text Text to have leading PHP tag from + */ +function remove_php_tags($text) +{ + $text = preg_replace('#// vim:.+#', '', $text); + return substr($text, 5); +} + +/** + * Copies the contents of a directory to the standalone directory + * @param string $dir Directory to copy + */ +function make_dir_standalone($dir) +{ + global $FS; + return $FS->copyr($dir, 'standalone/' . $dir); +} + +/** + * Copies the contents of a file to the standalone directory + * @param string $file File to copy + */ +function make_file_standalone($file) +{ + global $FS; + $FS->mkdirr('standalone/' . dirname($file)); + copy_and_remove_includes($file, 'standalone/' . $file); + return true; +} + +/** + * Copies a file to another location recursively, if it is a PHP file + * remove includes + * @param string $file Original file + * @param string $sfile New location of file + */ +function copy_and_remove_includes($file, $sfile) +{ + $contents = file_get_contents($file); + if (strrchr($file, '.') === '.php') $contents = replace_includes($contents); + return file_put_contents($sfile, $contents); +} + +/** + * @param $matches preg_replace_callback matches array, where index 1 + * is the filename to include + */ +function replace_includes_callback($matches) +{ + $file = $matches[1]; + $preserve = array( + // PEAR (external) + 'XML/HTMLSax3.php' => 1 + ); + if (isset($preserve[$file])) { + return $matches[0]; + } + if (isset($GLOBALS['loaded'][$file])) return ''; + $GLOBALS['loaded'][$file] = true; + return replace_includes(remove_php_tags(file_get_contents($file))); +} + +echo 'Generating includes file... '; +shell_exec('php generate-includes.php'); +echo "done!\n"; + +chdir(dirname(__FILE__) . '/../library/'); + +echo 'Creating full file...'; +$contents = replace_includes(file_get_contents('HTMLPurifier.includes.php')); +$contents = str_replace( + // Note that bootstrap is now inside the standalone file + "define('HTMLPURIFIER_PREFIX', realpath(dirname(__FILE__) . '/..'));", + "define('HTMLPURIFIER_PREFIX', dirname(__FILE__) . '/standalone'); + set_include_path(HTMLPURIFIER_PREFIX . PATH_SEPARATOR . get_include_path());", + $contents +); +file_put_contents('HTMLPurifier.standalone.php', $contents); +echo ' done!' . PHP_EOL; + +echo 'Creating standalone directory...'; +$FS->rmdirr('standalone'); // ensure a clean copy + +// data files +$FS->mkdirr('standalone/HTMLPurifier/DefinitionCache/Serializer'); +make_file_standalone('HTMLPurifier/EntityLookup/entities.ser'); +make_file_standalone('HTMLPurifier/ConfigSchema/schema.ser'); + +// non-standard inclusion setup +make_dir_standalone('HTMLPurifier/ConfigSchema'); +make_dir_standalone('HTMLPurifier/Language'); +make_dir_standalone('HTMLPurifier/Filter'); +make_dir_standalone('HTMLPurifier/Printer'); +make_file_standalone('HTMLPurifier/Printer.php'); +make_file_standalone('HTMLPurifier/Lexer/PH5P.php'); + +echo ' done!' . PHP_EOL; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/merge-library.php b/vendor/ezyang/htmlpurifier/maintenance/merge-library.php new file mode 100755 index 000000000..de2eecdc0 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/merge-library.php @@ -0,0 +1,11 @@ +#!/usr/bin/php +<?php + +/** + * @file + * Deprecated in favor of generate-standalone.php. + */ + +require dirname(__FILE__) . '/generate-standalone.php'; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/old-extract-schema.php b/vendor/ezyang/htmlpurifier/maintenance/old-extract-schema.php new file mode 100644 index 000000000..514a08dd9 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/old-extract-schema.php @@ -0,0 +1,71 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +echo "Please do not run this script. It is here for historical purposes only."; +exit; + +/** + * @file + * Extracts all definitions inside a configuration schema + * (HTMLPurifier_ConfigSchema) and exports them as plain text files. + * + * @todo Extract version numbers. + */ + +define('HTMLPURIFIER_SCHEMA_STRICT', true); // description data needs to be collected +require_once dirname(__FILE__) . '/../library/HTMLPurifier.auto.php'; + +// We need includes to ensure all HTMLPurifier_ConfigSchema calls are +// performed. +require_once 'HTMLPurifier.includes.php'; + +// Also, these extra files will be necessary. +require_once 'HTMLPurifier/Filter/ExtractStyleBlocks.php'; + +/** + * Takes a hash and saves its contents to library/HTMLPurifier/ConfigSchema/ + */ +function saveHash($hash) +{ + if ($hash === false) return; + $dir = realpath(dirname(__FILE__) . '/../library/HTMLPurifier/ConfigSchema'); + $name = $hash['ID'] . '.txt'; + $file = $dir . '/' . $name; + if (file_exists($file)) { + trigger_error("File already exists; skipped $name"); + return; + } + $file = new FSTools_File($file); + $file->open('w'); + $multiline = false; + foreach ($hash as $key => $value) { + $multiline = $multiline || (strpos($value, "\n") !== false); + if ($multiline) { + $file->put("--$key--" . PHP_EOL); + $file->put(str_replace("\n", PHP_EOL, $value) . PHP_EOL); + } else { + if ($key == 'ID') { + $file->put("$value" . PHP_EOL); + } else { + $file->put("$key: $value" . PHP_EOL); + } + } + } + $file->close(); +} + +$schema = HTMLPurifier_ConfigSchema::instance(); +$adapter = new HTMLPurifier_ConfigSchema_StringHashReverseAdapter($schema); + +foreach ($schema->info as $ns => $ns_array) { + saveHash($adapter->get($ns)); + foreach ($ns_array as $dir => $x) { + saveHash($adapter->get($ns, $dir)); + } +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/old-remove-require-once.php b/vendor/ezyang/htmlpurifier/maintenance/old-remove-require-once.php new file mode 100644 index 000000000..f47c7d0f1 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/old-remove-require-once.php @@ -0,0 +1,32 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +echo "Please do not run this script. It is here for historical purposes only."; +exit; + +/** + * @file + * Removes leading includes from files. + * + * @note + * This does not remove inline includes; those must be handled manually. + */ + +chdir(dirname(__FILE__) . '/../tests/HTMLPurifier'); +$FS = new FSTools(); + +$files = $FS->globr('.', '*.php'); +foreach ($files as $file) { + if (substr_count(basename($file), '.') > 1) continue; + $old_code = file_get_contents($file); + $new_code = preg_replace("#^require_once .+[\n\r]*#m", '', $old_code); + if ($old_code !== $new_code) { + file_put_contents($file, $new_code); + } +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/old-remove-schema-def.php b/vendor/ezyang/htmlpurifier/maintenance/old-remove-schema-def.php new file mode 100644 index 000000000..5ae031973 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/old-remove-schema-def.php @@ -0,0 +1,32 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +echo "Please do not run this script. It is here for historical purposes only."; +exit; + +/** + * @file + * Removes ConfigSchema function calls from source files. + */ + +chdir(dirname(__FILE__) . '/../library/'); +$FS = new FSTools(); + +$files = $FS->globr('.', '*.php'); +foreach ($files as $file) { + if (substr_count(basename($file), '.') > 1) continue; + $old_code = file_get_contents($file); + $new_code = preg_replace("#^HTMLPurifier_ConfigSchema::.+?\);[\n\r]*#ms", '', $old_code); + if ($old_code !== $new_code) { + file_put_contents($file, $new_code); + } + if (preg_match('#^\s+HTMLPurifier_ConfigSchema::#m', $new_code)) { + echo "Indented ConfigSchema call in $file\n"; + } +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/regenerate-docs.sh b/vendor/ezyang/htmlpurifier/maintenance/regenerate-docs.sh new file mode 100755 index 000000000..6f4d720ff --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/regenerate-docs.sh @@ -0,0 +1,5 @@ +#!/bin/bash -e +./compile-doxygen.sh +cd ../docs +scp doxygen.tgz htmlpurifier.org:/home/ezyang/htmlpurifier.org +ssh htmlpurifier.org "cd /home/ezyang/htmlpurifier.org && ./reload-docs.sh" diff --git a/vendor/ezyang/htmlpurifier/maintenance/remove-trailing-whitespace.php b/vendor/ezyang/htmlpurifier/maintenance/remove-trailing-whitespace.php new file mode 100644 index 000000000..857870546 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/remove-trailing-whitespace.php @@ -0,0 +1,37 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +/** + * @file + * Removes trailing whitespace from files. + */ + +chdir(dirname(__FILE__) . '/..'); +$FS = new FSTools(); + +$files = $FS->globr('.', '{,.}*', GLOB_BRACE); +foreach ($files as $file) { + if ( + !is_file($file) || + prefix_is('./.git', $file) || + prefix_is('./docs/doxygen', $file) || + postfix_is('.ser', $file) || + postfix_is('.tgz', $file) || + postfix_is('.patch', $file) || + postfix_is('.dtd', $file) || + postfix_is('.ent', $file) || + $file == './library/HTMLPurifier/Lexer/PH5P.php' || + $file == './maintenance/PH5P.php' + ) continue; + $contents = file_get_contents($file); + $result = preg_replace('/^(.*?)[ \t]+(\r?)$/m', '\1\2', $contents, -1, $count); + if (!$count) continue; + echo "$file\n"; + file_put_contents($file, $result); +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/maintenance/rename-config.php b/vendor/ezyang/htmlpurifier/maintenance/rename-config.php new file mode 100644 index 000000000..6e59e2a79 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/rename-config.php @@ -0,0 +1,84 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +require_once '../library/HTMLPurifier.auto.php'; +assertCli(); + +/** + * @file + * Renames a configuration directive. This involves renaming the file, + * adding an alias, and then regenerating the cache. You still have to + * manually go through and fix any calls to the directive. + * @warning This script doesn't handle multi-stringhash files. + */ + +$argv = $_SERVER['argv']; +if (count($argv) < 3) { + echo "Usage: {$argv[0]} OldName NewName\n"; + exit(1); +} + +chdir('../library/HTMLPurifier/ConfigSchema/schema'); + +$old = $argv[1]; +$new = $argv[2]; + +if (!file_exists("$old.txt")) { + echo "Cannot move undefined configuration directive $old\n"; + exit(1); +} + +if ($old === $new) { + echo "Attempting to move to self, aborting\n"; + exit(1); +} + +if (file_exists("$new.txt")) { + echo "Cannot move to already defined directive $new\n"; + exit(1); +} + +$file = "$old.txt"; +$builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder(); +$interchange = new HTMLPurifier_ConfigSchema_Interchange(); +$builder->buildFile($interchange, $file); +$contents = file_get_contents($file); + +if (strpos($contents, "\r\n") !== false) { + $nl = "\r\n"; +} elseif (strpos($contents, "\r") !== false) { + $nl = "\r"; +} else { + $nl = "\n"; +} + +// replace name with new name +$contents = str_replace($old, $new, $contents); + +if ($interchange->directives[$old]->aliases) { + $pos_alias = strpos($contents, 'ALIASES:'); + $pos_ins = strpos($contents, $nl, $pos_alias); + if ($pos_ins === false) $pos_ins = strlen($contents); + $contents = + substr($contents, 0, $pos_ins) . ", $old" . substr($contents, $pos_ins); + file_put_contents($file, $contents); +} else { + $lines = explode($nl, $contents); + $insert = false; + foreach ($lines as $n => $line) { + if (strncmp($line, '--', 2) === 0) { + $insert = $n; + break; + } + } + if (!$insert) { + $lines[] = "ALIASES: $old"; + } else { + array_splice($lines, $insert, 0, "ALIASES: $old"); + } + file_put_contents($file, implode($nl, $lines)); +} + +rename("$old.txt", "$new.txt") || exit(1); diff --git a/vendor/ezyang/htmlpurifier/maintenance/update-config.php b/vendor/ezyang/htmlpurifier/maintenance/update-config.php new file mode 100644 index 000000000..2d8a7a9c1 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/maintenance/update-config.php @@ -0,0 +1,34 @@ +#!/usr/bin/php +<?php + +chdir(dirname(__FILE__)); +require_once 'common.php'; +assertCli(); + +/** + * @file + * Converts all instances of $config->set and $config->get to the new + * format, as described by docs/dev-config-bcbreaks.txt + */ + +$FS = new FSTools(); +chdir(dirname(__FILE__) . '/..'); +$raw_files = $FS->globr('.', '*.php'); +foreach ($raw_files as $file) { + $file = substr($file, 2); // rm leading './' + if (strpos($file, 'library/standalone/') === 0) continue; + if (strpos($file, 'maintenance/update-config.php') === 0) continue; + if (strpos($file, 'test-settings.php') === 0) continue; + if (substr_count($file, '.') > 1) continue; // rm meta files + // process the file + $contents = file_get_contents($file); + $contents = preg_replace( + "#config->(set|get)\('(.+?)', '(.+?)'#", + "config->\\1('\\2.\\3'", + $contents + ); + if ($contents === '') continue; + file_put_contents($file, $contents); +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/package.php b/vendor/ezyang/htmlpurifier/package.php new file mode 100644 index 000000000..bfef93622 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/package.php @@ -0,0 +1,61 @@ +<?php + +set_time_limit(0); + +require_once 'PEAR/PackageFileManager2.php'; +require_once 'PEAR/PackageFileManager/File.php'; +PEAR::setErrorHandling(PEAR_ERROR_PRINT); +$pkg = new PEAR_PackageFileManager2; + +$pkg->setOptions( + array( + 'baseinstalldir' => '/', + 'packagefile' => 'package.xml', + 'packagedirectory' => realpath(dirname(__FILE__) . '/library'), + 'filelistgenerator' => 'file', + 'include' => array('*'), + 'dir_roles' => array('/' => 'php'), // hack to put *.ser files in the right place + 'ignore' => array( + 'HTMLPurifier.standalone.php', + 'HTMLPurifier.path.php', + '*.tar.gz', + '*.tgz', + 'standalone/' + ), + ) +); + +$pkg->setPackage('HTMLPurifier'); +$pkg->setLicense('LGPL', 'http://www.gnu.org/licenses/lgpl.html'); +$pkg->setSummary('Standards-compliant HTML filter'); +$pkg->setDescription( + 'HTML Purifier is an HTML filter that will remove all malicious code + (better known as XSS) with a thoroughly audited, secure yet permissive + whitelist and will also make sure your documents are standards + compliant.' +); + +$pkg->addMaintainer('lead', 'ezyang', 'Edward Z. Yang', 'admin@htmlpurifier.org', 'yes'); + +$version = trim(file_get_contents('VERSION')); +$api_version = substr($version, 0, strrpos($version, '.')); + +$pkg->setChannel('htmlpurifier.org'); +$pkg->setAPIVersion($api_version); +$pkg->setAPIStability('stable'); +$pkg->setReleaseVersion($version); +$pkg->setReleaseStability('stable'); + +$pkg->addRelease(); + +$pkg->setNotes(file_get_contents('WHATSNEW')); +$pkg->setPackageType('php'); + +$pkg->setPhpDep('5.0.0'); +$pkg->setPearinstallerDep('1.4.3'); + +$pkg->generateContents(); + +$pkg->writePackageFile(); + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/phpdoc.ini b/vendor/ezyang/htmlpurifier/phpdoc.ini new file mode 100644 index 000000000..c4c372353 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/phpdoc.ini @@ -0,0 +1,102 @@ +;; phpDocumentor parse configuration file +;; +;; This file is designed to cut down on repetitive typing on the command-line or web interface +;; You can copy this file to create a number of configuration files that can be used with the +;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web +;; interface will automatically generate a list of .ini files that can be used. +;; +;; default.ini is used to generate the online manual at http://www.phpdoc.org/docs +;; +;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini +;; +;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net> +;; +;; WARNING: do not change the name of any command-line parameters, phpDocumentor will ignore them + +[Parse Data] +;; title of all the documentation +;; legal values: any string +title = HTML Purifier API Documentation + +;; parse files that start with a . like .bash_profile +;; legal values: true, false +hidden = false + +;; show elements marked @access private in documentation by setting this to on +;; legal values: on, off +parseprivate = off + +;; parse with javadoc-like description (first sentence is always the short description) +;; legal values: on, off +javadocdesc = on + +;; add any custom @tags separated by commas here +;; legal values: any legal tagname separated by commas. +;customtags = mytag1,mytag2 + +;; This is only used by the XML:DocBook/peardoc2 converter +defaultcategoryname = Documentation + +;; what is the main package? +;; legal values: alphanumeric string plus - and _ +defaultpackagename = HTMLPurifier + +;; output any parsing information? set to on for cron jobs +;; legal values: on +;quiet = on + +;; parse a PEAR-style repository. Do not turn this on if your project does +;; not have a parent directory named "pear" +;; legal values: on/off +;pear = on + +;; where should the documentation be written? +;; legal values: a legal path +target = docs/phpdoc + +;; Which files should be parsed out as special documentation files, such as README, +;; INSTALL and CHANGELOG? This overrides the default files found in +;; phpDocumentor.ini (this file is not a user .ini file, but the global file) +readmeinstallchangelog = README, INSTALL, NEWS, WYSIWYG, SLOW, LICENSE, CREDITS + +;; limit output to the specified packages, even if others are parsed +;; legal values: package names separated by commas +;packageoutput = package1,package2 + +;; comma-separated list of files to parse +;; legal values: paths separated by commas +;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory + +;; comma-separated list of directories to parse +;; legal values: directory paths separated by commas +;directory = /path1,/path2,.,..,subdirectory +;directory = /home/jeichorn/cvs/pear +directory = . + +;; template base directory (the equivalent directory of <installdir>/phpDocumentor) +;templatebase = /path/to/my/templates + +;; directory to find any example files in through @example and {@example} tags +;examplesdir = /path/to/my/templates + +;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore +;; legal values: any wildcard strings separated by commas +;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/ +ignore = *tests*,*benchmarks*,*docs*,*test-settings.php,*configdoc*,*maintenance*,*smoketests*,*standalone*,*.svn*,*conf* + +sourcecode = on + +;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format +;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib, +;; HTML:frames:earthli, +;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de, +;; HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli +;; HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS +;; PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default +output=HTML:frames:default + +;; turn this option on if you want highlighted source code for every file +;; legal values: on/off +sourcecode = on + +; vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/modx.txt b/vendor/ezyang/htmlpurifier/plugins/modx.txt new file mode 100644 index 000000000..0763821b5 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/modx.txt @@ -0,0 +1,112 @@ + +MODx Plugin + +MODx <http://www.modxcms.com/> is an open source PHP application framework. +I first came across them in my referrer logs when tillda asked if anyone +could implement an HTML Purifier plugin. This forum thread +<http://modxcms.com/forums/index.php/topic,6604.0.html> eventually resulted +in the fruition of this plugin that davidm says, "is on top of my favorite +list." HTML Purifier goes great with WYSIWYG editors! + + + +1. Credits + +PaulGregory wrote the overall structure of the code. I added the +slashes hack. + + + +2. Install + +First, you need to place HTML Purifier library somewhere. The code here +assumes that you've placed in MODx's assets/plugins/htmlpurifier (no version +number). + +Log into the manager, and navigate: + +Resources > Manage Resources > Plugins tab > New Plugin + +Type in a name (probably HTML Purifier), and copy paste this code into the +textarea: + +-------------------------------------------------------------------------------- +$e = &$modx->Event; +if ($e->name == 'OnBeforeDocFormSave') { + global $content; + + include_once '../assets/plugins/htmlpurifier/library/HTMLPurifier.auto.php'; + $purifier = new HTMLPurifier(); + + static $magic_quotes = null; + if ($magic_quotes === null) { + // this is an ugly hack because this hook hasn't + // had the backslashes removed yet when magic_quotes_gpc is on, + // but HTMLPurifier must not have the quotes slashed. + $magic_quotes = get_magic_quotes_gpc(); + } + + if ($magic_quotes) $content = stripslashes($content); + $content = $purifier->purify($content); + if ($magic_quotes) $content = addslashes($content); +} +-------------------------------------------------------------------------------- + +Then navigate to the System Events tab and check "OnBeforeDocFormSave". +Save the plugin. HTML Purifier now is integrated! + + + +3. Making sure it works + +You can test HTML Purifier by deliberately putting in crappy HTML and seeing +whether or not it gets fixed. A better way is to put in something like this: + +<p lang="fr">Il est bon</p> + +...and seeing whether or not the content comes out as: + +<p lang="fr" xml:lang="fr">Il est bon</p> + +(lang to xml:lang synchronization is one of the many features HTML Purifier +has). + + + +4. Caveat Emptor + +This code does not intercept save requests from the QuickEdit plugin, this may +be added in a later version. It also modifies things on save, so there's a +slight chance that HTML Purifier may make a boo-boo and accidently mess things +up (the original version is not saved). + +Finally, make sure that MODx is using UTF-8. If you are using, say, a French +localisation, you may be using Latin-1, if that's the case, configure +HTML Purifier properly like this: + +$config = HTMLPurifier_Config::createDefault(); +$config->set('Core', 'Encoding', 'ISO-8859-1'); // or whatever encoding +$purifier = new HTMLPurifier($config); + + + +5. Known Bugs + +'rn' characters sometimes mysteriously appear after purification. We are +currently investigating this issue. See: <http://htmlpurifier.org/phorum/read.php?3,1866> + + + +6. See Also + +A modified version of Jot 1.1.3 is available, which integrates with HTML +Purifier. You can check it out here: <http://modxcms.com/forums/index.php/topic,25621.msg161970.html> + + +X. Changelog + +2008-06-16 +- Updated code to work with 3.1.0 and later +- Add Known Bugs and See Also section + + vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/.gitignore b/vendor/ezyang/htmlpurifier/plugins/phorum/.gitignore new file mode 100644 index 000000000..8325e0902 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/.gitignore @@ -0,0 +1,2 @@ +migrate.php +htmlpurifier/* diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/Changelog b/vendor/ezyang/htmlpurifier/plugins/phorum/Changelog new file mode 100644 index 000000000..9f939e54a --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/Changelog @@ -0,0 +1,27 @@ +Changelog HTMLPurifier : Phorum Mod +||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + += KEY ==================== + # Breaks back-compat + ! Feature + - Bugfix + + Sub-comment + . Internal change +========================== + +Version 4.0.0 for Phorum 5.2, released July 9, 2009 +# Works only with HTML Purifier 4.0.0 +! Better installation documentation +- Fixed double encoded quotes +- Fixed fatal error when migrate.php is blank + +Version 3.0.0 for Phorum 5.2, released January 12, 2008 +# WYSIWYG and suppress_message options are now configurable via web + interface. +- Module now compatible with Phorum 5.2, primary bugs were in migration + code as well as signature and edit message handling. This module is NOT + compatible with Phorum 5.1. +- Buggy WYSIWYG mode refined +. AutoFormatParam added to list of default configuration namespaces + + vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/INSTALL b/vendor/ezyang/htmlpurifier/plugins/phorum/INSTALL new file mode 100644 index 000000000..23c76fc5c --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/INSTALL @@ -0,0 +1,84 @@ + +Install + How to install the Phorum HTML Purifier plugin + +0. PREREQUISITES +---------------- +This Phorum module only works on PHP5 and with HTML Purifier 4.0.0 +or later. + +1. UNZIP +-------- +Unzip phorum-htmlpurifier-x.y.z, producing an htmlpurifier folder. +You've already done this step if you're reading this! + +2. MOVE +------- +Move the htmlpurifier folder to the mods/ folder of your Phorum +installation, so the directory structure looks like: + +phorum/ + mods/ + htmlpurifier/ + INSTALL - this install file + info.txt, ... - the module files + htmlpurifier/ + +3. INSTALL HTML PURIFIER +------------------------ +Download and unzip HTML Purifier <htmlpurifier.org>. Place the contents of +the library/ folder in the htmlpurifier/htmlpurifier folder. Your directory +structure will look like: + +phorum/ + mods/ + htmlpurifier/ + htmlpurifier/ + HTMLPurifier.auto.php + ... - other files + HTMLPurifier/ + +Advanced users: + If you have HTML Purifier installed elsewhere on your server, + all you need is an HTMLPurifier.auto.php file in the library folder which + includes the HTMLPurifier.auto.php file in your install. + +4. MIGRATE +---------- +If you're setting up a new Phorum installation, all you need to do is create +a blank migrate.php file in the htmlpurifier module folder (NOT the library +folder. + +If you have an old Phorum installation and was using BBCode, +copy migrate.bbcode.php to migrate.php. If you were using a different input +format, follow the instructions in migrate.bbcode.php to create your own custom +migrate.php file. + +Your directory structure should now look like this: + +phorum/ + mods/ + htmlpurifier/ + migrate.php + +5. ENABLE +--------- +Navigate to your Phorum admin panel at http://example.com/phorum/admin.php, +click on Global Settings > Modules, scroll to "HTML Purifier Phorum Mod" and +turn it On. + +6. MIGRATE SIGNATURES +--------------------- +If you're setting up a new Phorum installation, skip this step. + +If you allowed your users to make signatures, navigate to the module settings +page of HTML Purifier (Global Settings > Modules > HTML Purifier Phorum Mod > +Configure), type in "yes" in the "Confirm" box, and press "Migrate." + +ONLY DO THIS ONCE! BE SURE TO BACK UP YOUR DATABASE! + +7. CONFIGURE +------------ +Configure using Edit settings. See that page for more information. + + vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/README b/vendor/ezyang/htmlpurifier/plugins/phorum/README new file mode 100644 index 000000000..0524ed39d --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/README @@ -0,0 +1,45 @@ + +HTML Purifier Phorum Mod - Filter your HTML the Standards-Compliant Way! + +This Phorum mod enables HTML posting on Phorum. Under normal circumstances, +this would cause a huge security risk, but because we are running +HTML through HTML Purifier, output is guaranteed to be XSS free and +standards-compliant. + +This mod requires HTML input, and previous markup languages need to be +converted accordingly. Thus, it is vital that you create a 'migrate.php' +file that works with your installation. If you're using the built-in +BBCode formatting, simply move migrate.bbcode.php to that place; for +other markup languages, consult said file for instructions on how +to adapt it to your needs. + + -- NOTE ------------------------------------------------- + You can also run this module in parallel with another + formatting module; this module attempts to place itself + at the end of the filtering chain. However, if any + previous modules produce insecure HTML (for instance, + a JavaScript email obfuscator) they will get cleaned. + +This module will not work if 'migrate.php' is not created, and an improperly +made migration file may *CORRUPT* Phorum, so please take your time to +do this correctly. It should go without saying to *BACKUP YOUR DATABASE* +before attempting anything here. If no migration is necessary, you can +simply create a blank migrate.php file. HTML Purifier is smart and will +not re-migrate already processed messages. However, the original code +is irretrievably lost (we may change this in the future.) + +This module will not automatically migrate user signatures, because this +process may take a long time. After installing the HTML Purifier module and +then configuring 'migrate.php', navigate to Settings and click 'Migrate +Signatures' to migrate all user signatures to HTML. + +All of HTML Purifier's usual functions are configurable via the mod settings +page. If you require custom configuration, create config.php file in +the mod directory that edits a $config variable. Be sure, also, to +set $PHORUM['mod_htmlpurifier']['wysiwyg'] to TRUE if you are using a +WYSIWYG editor (you can do this through a common hook or the web +configuration form). + +Visit HTML Purifier at <http://htmlpurifier.org/>. + + vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/config.default.php b/vendor/ezyang/htmlpurifier/plugins/phorum/config.default.php new file mode 100644 index 000000000..e047c0b42 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/config.default.php @@ -0,0 +1,57 @@ +<?php + +if(!defined("PHORUM")) exit; + +// default HTML Purifier configuration settings +$config->set('HTML.Allowed', + // alphabetically sorted +'a[href|title] +abbr[title] +acronym[title] +b +blockquote[cite] +br +caption +cite +code +dd +del +dfn +div +dl +dt +em +i +img[src|alt|title|class] +ins +kbd +li +ol +p +pre +s +strike +strong +sub +sup +table +tbody +td +tfoot +th +thead +tr +tt +u +ul +var'); +$config->set('AutoFormat.AutoParagraph', true); +$config->set('AutoFormat.Linkify', true); +$config->set('HTML.Doctype', 'XHTML 1.0 Transitional'); +$config->set('Core.AggressivelyFixLt', true); +$config->set('Core.Encoding', $GLOBALS['PHORUM']['DATA']['CHARSET']); // we'll change this eventually +if (strtolower($GLOBALS['PHORUM']['DATA']['CHARSET']) !== 'utf-8') { + $config->set('Core.EscapeNonASCIICharacters', true); +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/htmlpurifier.php b/vendor/ezyang/htmlpurifier/plugins/phorum/htmlpurifier.php new file mode 100644 index 000000000..f66d8c36c --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/htmlpurifier.php @@ -0,0 +1,316 @@ +<?php + +/** + * HTML Purifier Phorum Mod. Filter your HTML the Standards-Compliant Way! + * + * This Phorum mod enables users to post raw HTML into Phorum. But never + * fear: with the help of HTML Purifier, this HTML will be beat into + * de-XSSed and standards-compliant form, safe for general consumption. + * It is not recommended, but possible to run this mod in parallel + * with other formatters (in short, please DISABLE the BBcode mod). + * + * For help migrating from your previous markup language to pure HTML + * please check the migrate.bbcode.php file. + * + * If you'd like to use this with a WYSIWYG editor, make sure that + * editor sets $PHORUM['mod_htmlpurifier']['wysiwyg'] to true. Otherwise, + * administrators who need to edit other people's comments may be at + * risk for some nasty attacks. + * + * Tested with Phorum 5.2.11. + */ + +// Note: Cache data is base64 encoded because Phorum insists on flinging +// to the user and expecting it to come back unharmed, newlines and +// all, which ain't happening. It's slower, it takes up more space, but +// at least it won't get mutilated + +/** + * Purifies a data array + */ +function phorum_htmlpurifier_format($data) +{ + $PHORUM = $GLOBALS["PHORUM"]; + + $purifier =& HTMLPurifier::getInstance(); + $cache_serial = $PHORUM['mod_htmlpurifier']['body_cache_serial']; + + foreach($data as $message_id => $message){ + if(isset($message['body'])) { + + if ($message_id) { + // we're dealing with a real message, not a fake, so + // there a number of shortcuts that can be taken + + if (isset($message['meta']['htmlpurifier_light'])) { + // format hook was called outside of Phorum's normal + // functions, do the abridged purification + $data[$message_id]['body'] = $purifier->purify($message['body']); + continue; + } + + if (!empty($PHORUM['args']['purge'])) { + // purge the cache, must be below the following if + unset($message['meta']['body_cache']); + } + + if ( + isset($message['meta']['body_cache']) && + isset($message['meta']['body_cache_serial']) && + $message['meta']['body_cache_serial'] == $cache_serial + ) { + // cached version is present, bail out early + $data[$message_id]['body'] = base64_decode($message['meta']['body_cache']); + continue; + } + } + + // migration might edit this array, that's why it's defined + // so early + $updated_message = array(); + + // create the $body variable + if ( + $message_id && // message must be real to migrate + !isset($message['meta']['body_cache_serial']) + ) { + // perform migration + $fake_data = array(); + list($signature, $edit_message) = phorum_htmlpurifier_remove_sig_and_editmessage($message); + $fake_data[$message_id] = $message; + $fake_data = phorum_htmlpurifier_migrate($fake_data); + $body = $fake_data[$message_id]['body']; + $body = str_replace("<phorum break>\n", "\n", $body); + $updated_message['body'] = $body; // save it in + $body .= $signature . $edit_message; // add it back in + } else { + // reverse Phorum's pre-processing + $body = $message['body']; + // order is important + $body = str_replace("<phorum break>\n", "\n", $body); + $body = str_replace(array('<','>','&', '"'), array('<','>','&','"'), $body); + if (!$message_id && defined('PHORUM_CONTROL_CENTER')) { + // we're in control.php, so it was double-escaped + $body = str_replace(array('<','>','&', '"'), array('<','>','&','"'), $body); + } + } + + $body = $purifier->purify($body); + + // dynamically update the cache (MUST BE DONE HERE!) + // this is inefficient because it's one db call per + // cache miss, but once the cache is in place things are + // a lot zippier. + + if ($message_id) { // make sure it's not a fake id + $updated_message['meta'] = $message['meta']; + $updated_message['meta']['body_cache'] = base64_encode($body); + $updated_message['meta']['body_cache_serial'] = $cache_serial; + phorum_db_update_message($message_id, $updated_message); + } + + // must not get overloaded until after we cache it, otherwise + // we'll inadvertently change the original text + $data[$message_id]['body'] = $body; + + } + } + + return $data; +} + +// ----------------------------------------------------------------------- +// This is fragile code, copied from read.php:596 (Phorum 5.2.6). Please +// keep this code in-sync with Phorum + +/** + * Generates a signature based on a message array + */ +function phorum_htmlpurifier_generate_sig($row) +{ + $phorum_sig = ''; + if(isset($row["user"]["signature"]) + && isset($row['meta']['show_signature']) && $row['meta']['show_signature']==1){ + $phorum_sig=trim($row["user"]["signature"]); + if(!empty($phorum_sig)){ + $phorum_sig="\n\n$phorum_sig"; + } + } + return $phorum_sig; +} + +/** + * Generates an edit message based on a message array + */ +function phorum_htmlpurifier_generate_editmessage($row) +{ + $PHORUM = $GLOBALS['PHORUM']; + $editmessage = ''; + if(isset($row['meta']['edit_count']) && $row['meta']['edit_count'] > 0) { + $editmessage = str_replace ("%count%", $row['meta']['edit_count'], $PHORUM["DATA"]["LANG"]["EditedMessage"]); + $editmessage = str_replace ("%lastedit%", phorum_date($PHORUM["short_date_time"],$row['meta']['edit_date']), $editmessage); + $editmessage = str_replace ("%lastuser%", $row['meta']['edit_username'], $editmessage); + $editmessage = "\n\n\n\n$editmessage"; + } + return $editmessage; +} + +// End fragile code +// ----------------------------------------------------------------------- + +/** + * Removes the signature and edit message from a message + * @param $row Message passed by reference + */ +function phorum_htmlpurifier_remove_sig_and_editmessage(&$row) +{ + $signature = phorum_htmlpurifier_generate_sig($row); + $editmessage = phorum_htmlpurifier_generate_editmessage($row); + $replacements = array(); + // we need to remove add <phorum break> as that is the form these + // extra bits are in. + if ($signature) $replacements[str_replace("\n", "<phorum break>\n", $signature)] = ''; + if ($editmessage) $replacements[str_replace("\n", "<phorum break>\n", $editmessage)] = ''; + $row['body'] = strtr($row['body'], $replacements); + return array($signature, $editmessage); +} + +/** + * Indicate that data is fully HTML and not from migration, invalidate + * previous caches + * @note This function could generate the actual cache entries, but + * since there's data missing that must be deferred to the first read + */ +function phorum_htmlpurifier_posting($message) +{ + $PHORUM = $GLOBALS["PHORUM"]; + unset($message['meta']['body_cache']); // invalidate the cache + $message['meta']['body_cache_serial'] = $PHORUM['mod_htmlpurifier']['body_cache_serial']; + return $message; +} + +/** + * Overload quoting mechanism to prevent default, mail-style quote from happening + */ +function phorum_htmlpurifier_quote($array) +{ + $PHORUM = $GLOBALS["PHORUM"]; + $purifier =& HTMLPurifier::getInstance(); + $text = $purifier->purify($array[1]); + $source = htmlspecialchars($array[0]); + return "<blockquote cite=\"$source\">\n$text\n</blockquote>"; +} + +/** + * Ensure that our format hook is processed last. Also, loads the library. + * @credits <http://secretsauce.phorum.org/snippets/make_bbcode_last_formatter.php.txt> + */ +function phorum_htmlpurifier_common() +{ + require_once(dirname(__FILE__).'/htmlpurifier/HTMLPurifier.auto.php'); + require(dirname(__FILE__).'/init-config.php'); + + $config = phorum_htmlpurifier_get_config(); + HTMLPurifier::getInstance($config); + + // increment revision.txt if you want to invalidate the cache + $GLOBALS['PHORUM']['mod_htmlpurifier']['body_cache_serial'] = $config->getSerial(); + + // load migration + if (file_exists(dirname(__FILE__) . '/migrate.php')) { + include(dirname(__FILE__) . '/migrate.php'); + } else { + echo '<strong>Error:</strong> No migration path specified for HTML Purifier, please check + <tt>modes/htmlpurifier/migrate.bbcode.php</tt> for instructions on + how to migrate from your previous markup language.'; + exit; + } + + if (!function_exists('phorum_htmlpurifier_migrate')) { + // Dummy function + function phorum_htmlpurifier_migrate($data) {return $data;} + } + +} + +/** + * Pre-emptively performs purification if it looks like a WYSIWYG editor + * is being used + */ +function phorum_htmlpurifier_before_editor($message) +{ + if (!empty($GLOBALS['PHORUM']['mod_htmlpurifier']['wysiwyg'])) { + if (!empty($message['body'])) { + $body = $message['body']; + // de-entity-ize contents + $body = str_replace(array('<','>','&'), array('<','>','&'), $body); + $purifier =& HTMLPurifier::getInstance(); + $body = $purifier->purify($body); + // re-entity-ize contents + $body = htmlspecialchars($body, ENT_QUOTES, $GLOBALS['PHORUM']['DATA']['CHARSET']); + $message['body'] = $body; + } + } + return $message; +} + +function phorum_htmlpurifier_editor_after_subject() +{ + // don't show this message if it's a WYSIWYG editor, since it will + // then be handled automatically + if (!empty($GLOBALS['PHORUM']['mod_htmlpurifier']['wysiwyg'])) { + $i = $GLOBALS['PHORUM']['DATA']['MODE']; + if ($i == 'quote' || $i == 'edit' || $i == 'moderation') { + ?> + <div> + <p> + <strong>Notice:</strong> HTML has been scrubbed for your safety. + If you would like to see the original, turn off WYSIWYG mode + (consult your administrator for details.) + </p> + </div> + <?php + } + return; + } + if (!empty($GLOBALS['PHORUM']['mod_htmlpurifier']['suppress_message'])) return; + ?><div class="htmlpurifier-help"> + <p> + <strong>HTML input</strong> is enabled. Make sure you escape all HTML and + angled brackets with <code>&lt;</code> and <code>&gt;</code>. + </p><?php + $purifier =& HTMLPurifier::getInstance(); + $config = $purifier->config; + if ($config->get('AutoFormat.AutoParagraph')) { + ?><p> + <strong>Auto-paragraphing</strong> is enabled. Double + newlines will be converted to paragraphs; for single + newlines, use the <code>pre</code> tag. + </p><?php + } + $html_definition = $config->getDefinition('HTML'); + $allowed = array(); + foreach ($html_definition->info as $name => $x) $allowed[] = "<code>$name</code>"; + sort($allowed); + $allowed_text = implode(', ', $allowed); + ?><p><strong>Allowed tags:</strong> <?php + echo $allowed_text; + ?>.</p><?php + ?> + </p> + <p> + For inputting literal code such as HTML and PHP for display, use + CDATA tags to auto-escape your angled brackets, and <code>pre</code> + to preserve newlines: + </p> + <pre><pre><![CDATA[ +<em>Place code here</em> +]]></pre></pre> + <p> + Power users, you can hide this notice with: + <pre>.htmlpurifier-help {display:none;}</pre> + </p> + </div><?php +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/info.txt b/vendor/ezyang/htmlpurifier/plugins/phorum/info.txt new file mode 100644 index 000000000..723465490 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/info.txt @@ -0,0 +1,18 @@ +title: HTML Purifier Phorum Mod +desc: This module enables standards-compliant HTML filtering on Phorum. Please check migrate.bbcode.php before enabling this mod. +author: Edward Z. Yang +url: http://htmlpurifier.org/ +version: 4.0.0 + +hook: format|phorum_htmlpurifier_format +hook: quote|phorum_htmlpurifier_quote +hook: posting_custom_action|phorum_htmlpurifier_posting +hook: common|phorum_htmlpurifier_common +hook: before_editor|phorum_htmlpurifier_before_editor +hook: tpl_editor_after_subject|phorum_htmlpurifier_editor_after_subject + +# This module is meant to be a drop-in for bbcode, so make it run last. +priority: run module after * +priority: run hook format after * + + vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/init-config.php b/vendor/ezyang/htmlpurifier/plugins/phorum/init-config.php new file mode 100644 index 000000000..e19787b4b --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/init-config.php @@ -0,0 +1,30 @@ +<?php + +/** + * Initializes the appropriate configuration from either a PHP file + * or a module configuration value + * @return Instance of HTMLPurifier_Config + */ +function phorum_htmlpurifier_get_config($default = false) +{ + global $PHORUM; + $config_exists = phorum_htmlpurifier_config_file_exists(); + if ($default || $config_exists || !isset($PHORUM['mod_htmlpurifier']['config'])) { + $config = HTMLPurifier_Config::createDefault(); + include(dirname(__FILE__) . '/config.default.php'); + if ($config_exists) { + include(dirname(__FILE__) . '/config.php'); + } + unset($PHORUM['mod_htmlpurifier']['config']); // unnecessary + } else { + $config = HTMLPurifier_Config::create($PHORUM['mod_htmlpurifier']['config']); + } + return $config; +} + +function phorum_htmlpurifier_config_file_exists() +{ + return file_exists(dirname(__FILE__) . '/config.php'); +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/migrate.bbcode.php b/vendor/ezyang/htmlpurifier/plugins/phorum/migrate.bbcode.php new file mode 100644 index 000000000..0d0919455 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/migrate.bbcode.php @@ -0,0 +1,31 @@ +<?php + +/** + * This file is responsible for migrating from a specific markup language + * like BBCode or Markdown to HTML. WARNING: THIS PROCESS IS NOT REVERSIBLE + * + * Copy this file to 'migrate.php' and it will automatically work for + * BBCode; you may need to tweak this a little to get it to work for other + * languages (usually, just replace the include name and the function name). + * + * If you do NOT want to have any migration performed (for instance, you + * are installing the module on a new forum with no posts), simply remove + * phorum_htmlpurifier_migrate() function. You still need migrate.php + * present, otherwise the module won't work. This ensures that the user + * explicitly says, "No, I do not need to migrate." + */ + +if(!defined("PHORUM")) exit; + +require_once(dirname(__FILE__) . "/../bbcode/bbcode.php"); + +/** + * 'format' hook style function that will be called to convert + * legacy markup into HTML. + */ +function phorum_htmlpurifier_migrate($data) +{ + return phorum_mod_bbcode_format($data); // bbcode's 'format' hook +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/settings.php b/vendor/ezyang/htmlpurifier/plugins/phorum/settings.php new file mode 100644 index 000000000..8158f0282 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/settings.php @@ -0,0 +1,64 @@ +<?php + +// based off of BBCode's settings file + +/** + * HTML Purifier Phorum mod settings configuration. This provides + * a convenient web-interface for editing the most common HTML Purifier + * configuration directives. You can also specify custom configuration + * by creating a 'config.php' file. + */ + +if(!defined("PHORUM_ADMIN")) exit; + +// error reporting is good! +error_reporting(E_ALL ^ E_NOTICE); + +// load library and other paraphenalia +require_once './include/admin/PhorumInputForm.php'; +require_once (dirname(__FILE__) . '/htmlpurifier/HTMLPurifier.auto.php'); +require_once (dirname(__FILE__) . '/init-config.php'); +require_once (dirname(__FILE__) . '/settings/migrate-sigs-form.php'); +require_once (dirname(__FILE__) . '/settings/migrate-sigs.php'); +require_once (dirname(__FILE__) . '/settings/form.php'); +require_once (dirname(__FILE__) . '/settings/save.php'); + +// define friendly configuration directives. you can expand this array +// to get more web-definable directives +$PHORUM['mod_htmlpurifier']['directives'] = array( + 'URI.Host', // auto-detectable + 'URI.DisableExternal', + 'URI.DisableExternalResources', + 'URI.DisableResources', + 'URI.Munge', + 'URI.HostBlacklist', + 'URI.Disable', + 'HTML.TidyLevel', + 'HTML.Doctype', // auto-detectable + 'HTML.Allowed', + 'AutoFormat', + '-AutoFormat.Custom', + 'AutoFormatParam', + 'Output.TidyFormat', +); + +// lower this setting if you're getting time outs/out of memory +$PHORUM['mod_htmlpurifier']['migrate-sigs-increment'] = 100; + +if (isset($_POST['reset'])) { + unset($PHORUM['mod_htmlpurifier']['config']); +} + +if ($offset = phorum_htmlpurifier_migrate_sigs_check()) { + // migrate signatures + phorum_htmlpurifier_migrate_sigs($offset); +} elseif(!empty($_POST)){ + // save settings + phorum_htmlpurifier_save_settings(); +} + +phorum_htmlpurifier_show_migrate_sigs_form(); +echo '<br />'; +phorum_htmlpurifier_show_form(); + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/settings/form.php b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/form.php new file mode 100644 index 000000000..9b6ad5f39 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/form.php @@ -0,0 +1,95 @@ +<?php + +function phorum_htmlpurifier_show_form() +{ + if (phorum_htmlpurifier_config_file_exists()) { + phorum_htmlpurifier_show_config_info(); + return; + } + + global $PHORUM; + + $config = phorum_htmlpurifier_get_config(); + + $frm = new PhorumInputForm ("", "post", "Save"); + $frm->hidden("module", "modsettings"); + $frm->hidden("mod", "htmlpurifier"); // this is the directory name that the Settings file lives in + + if (!empty($error)){ + echo "$error<br />"; + } + + $frm->addbreak("Edit settings for the HTML Purifier module"); + + $frm->addMessage('<p>The box below sets <code>$PHORUM[\'mod_htmlpurifier\'][\'wysiwyg\']</code>. + When checked, contents sent for edit are now purified and the + informative message is disabled. If your WYSIWYG editor is disabled for + admin edits, you can safely keep this unchecked.</p>'); + $frm->addRow('Use WYSIWYG?', $frm->checkbox('wysiwyg', '1', '', $PHORUM['mod_htmlpurifier']['wysiwyg'])); + + $frm->addMessage('<p>The box below sets <code>$PHORUM[\'mod_htmlpurifier\'][\'suppress_message\']</code>, + which removes the big how-to use + HTML Purifier message.</p>'); + $frm->addRow('Suppress information?', $frm->checkbox('suppress_message', '1', '', $PHORUM['mod_htmlpurifier']['suppress_message'])); + + $frm->addMessage('<p>Click on directive links to read what each option does + (links do not open in new windows).</p> + <p>For more flexibility (for instance, you want to edit the full + range of configuration directives), you can create a <tt>config.php</tt> + file in your <tt>mods/htmlpurifier/</tt> directory. Doing so will, + however, make the web configuration interface unavailable.</p>'); + + require_once 'HTMLPurifier/Printer/ConfigForm.php'; + $htmlpurifier_form = new HTMLPurifier_Printer_ConfigForm('config', 'http://htmlpurifier.org/live/configdoc/plain.html#%s'); + $htmlpurifier_form->setTextareaDimensions(23, 7); // widen a little, since we have space + + $frm->addMessage($htmlpurifier_form->render( + $config, $PHORUM['mod_htmlpurifier']['directives'], false)); + + $frm->addMessage("<strong>Warning: Changing HTML Purifier's configuration will invalidate + the cache. Expect to see a flurry of database activity after you change + any of these settings.</strong>"); + + $frm->addrow('Reset to defaults:', $frm->checkbox("reset", "1", "", false)); + + // hack to include extra styling + echo '<style type="text/css">' . $htmlpurifier_form->getCSS() . ' + .hp-config {margin-left:auto;margin-right:auto;} + </style>'; + $js = $htmlpurifier_form->getJavaScript(); + echo '<script type="text/javascript">'."<!--\n$js\n//-->".'</script>'; + + $frm->show(); +} + +function phorum_htmlpurifier_show_config_info() +{ + global $PHORUM; + + // update mod_htmlpurifier for housekeeping + phorum_htmlpurifier_commit_settings(); + + // politely tell user how to edit settings manually +?> + <div class="input-form-td-break">How to edit settings for HTML Purifier module</div> + <p> + A <tt>config.php</tt> file exists in your <tt>mods/htmlpurifier/</tt> + directory. This file contains your custom configuration: in order to + change it, please navigate to that file and edit it accordingly. + You can also set <code>$GLOBALS['PHORUM']['mod_htmlpurifier']['wysiwyg']</code> + or <code>$GLOBALS['PHORUM']['mod_htmlpurifier']['suppress_message']</code> + </p> + <p> + To use the web interface, delete <tt>config.php</tt> (or rename it to + <tt>config.php.bak</tt>). + </p> + <p> + <strong>Warning: Changing HTML Purifier's configuration will invalidate + the cache. Expect to see a flurry of database activity after you change + any of these settings.</strong> + </p> +<?php + +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs-form.php b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs-form.php new file mode 100644 index 000000000..abea3b51d --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs-form.php @@ -0,0 +1,22 @@ +<?php + +function phorum_htmlpurifier_show_migrate_sigs_form() +{ + $frm = new PhorumInputForm ('', "post", "Migrate"); + $frm->hidden("module", "modsettings"); + $frm->hidden("mod", "htmlpurifier"); + $frm->hidden("migrate-sigs", "1"); + $frm->addbreak("Migrate user signatures to HTML"); + $frm->addMessage('This operation will migrate your users signatures + to HTML. <strong>This process is irreversible and must only be performed once.</strong> + Type in yes in the confirmation field to migrate.'); + if (!file_exists(dirname(__FILE__) . '/../migrate.php')) { + $frm->addMessage('Migration file does not exist, cannot migrate signatures. + Please check <tt>migrate.bbcode.php</tt> on how to create an appropriate file.'); + } else { + $frm->addrow('Confirm:', $frm->text_box("confirmation", "")); + } + $frm->show(); +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs.php b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs.php new file mode 100644 index 000000000..5ea9cd0b8 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs.php @@ -0,0 +1,79 @@ +<?php + +function phorum_htmlpurifier_migrate_sigs_check() +{ + global $PHORUM; + $offset = 0; + if (!empty($_POST['migrate-sigs'])) { + if (!isset($_POST['confirmation']) || strtolower($_POST['confirmation']) !== 'yes') { + echo 'Invalid confirmation code.'; + exit; + } + $PHORUM['mod_htmlpurifier']['migrate-sigs'] = true; + phorum_db_update_settings(array("mod_htmlpurifier"=>$PHORUM["mod_htmlpurifier"])); + $offset = 1; + } elseif (!empty($_GET['migrate-sigs']) && $PHORUM['mod_htmlpurifier']['migrate-sigs']) { + $offset = (int) $_GET['migrate-sigs']; + } + return $offset; +} + +function phorum_htmlpurifier_migrate_sigs($offset) +{ + global $PHORUM; + + if(!$offset) return; // bail out quick if $offset == 0 + + // theoretically, we could get rid of this multi-request + // doo-hickery if safe mode is off + @set_time_limit(0); // attempt to let this run + $increment = $PHORUM['mod_htmlpurifier']['migrate-sigs-increment']; + + require_once(dirname(__FILE__) . '/../migrate.php'); + // migrate signatures + // do this in batches so we don't run out of time/space + $end = $offset + $increment; + $user_ids = array(); + for ($i = $offset; $i < $end; $i++) { + $user_ids[] = $i; + } + $userinfos = phorum_db_user_get_fields($user_ids, 'signature'); + foreach ($userinfos as $i => $user) { + if (empty($user['signature'])) continue; + $sig = $user['signature']; + // perform standard Phorum processing on the sig + $sig = str_replace(array("&","<",">"), array("&","<",">"), $sig); + $sig = preg_replace("/<((http|https|ftp):\/\/[a-z0-9;\/\?:@=\&\$\-_\.\+!*'\(\),~%]+?)>/i", "$1", $sig); + // prepare fake data to pass to migration function + $fake_data = array(array("author"=>"", "email"=>"", "subject"=>"", 'body' => $sig)); + list($fake_message) = phorum_htmlpurifier_migrate($fake_data); + $user['signature'] = $fake_message['body']; + if (!phorum_api_user_save($user)) { + exit('Error while saving user data'); + } + } + unset($userinfos); // free up memory + + // query for highest ID in database + $type = $PHORUM['DBCONFIG']['type']; + $sql = "select MAX(user_id) from {$PHORUM['user_table']}"; + $row = phorum_db_interact(DB_RETURN_ROW, $sql); + $top_id = (int) $row[0]; + + $offset += $increment; + if ($offset > $top_id) { // test for end condition + echo 'Migration finished'; + $PHORUM['mod_htmlpurifier']['migrate-sigs'] = false; + phorum_htmlpurifier_commit_settings(); + return true; + } + $host = $_SERVER['HTTP_HOST']; + $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\'); + $extra = 'admin.php?module=modsettings&mod=htmlpurifier&migrate-sigs=' . $offset; + // relies on output buffering to work + header("Location: http://$host$uri/$extra"); + exit; + +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/plugins/phorum/settings/save.php b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/save.php new file mode 100644 index 000000000..2aefaf83a --- /dev/null +++ b/vendor/ezyang/htmlpurifier/plugins/phorum/settings/save.php @@ -0,0 +1,29 @@ +<?php + +function phorum_htmlpurifier_save_settings() +{ + global $PHORUM; + if (phorum_htmlpurifier_config_file_exists()) { + echo "Cannot update settings, <code>mods/htmlpurifier/config.php</code> already exists. To change + settings, edit that file. To use the web form, delete that file.<br />"; + } else { + $config = phorum_htmlpurifier_get_config(true); + if (!isset($_POST['reset'])) $config->mergeArrayFromForm($_POST, 'config', $PHORUM['mod_htmlpurifier']['directives']); + $PHORUM['mod_htmlpurifier']['config'] = $config->getAll(); + } + $PHORUM['mod_htmlpurifier']['wysiwyg'] = !empty($_POST['wysiwyg']); + $PHORUM['mod_htmlpurifier']['suppress_message'] = !empty($_POST['suppress_message']); + if(!phorum_htmlpurifier_commit_settings()){ + $error="Database error while updating settings."; + } else { + echo "Settings Updated<br />"; + } +} + +function phorum_htmlpurifier_commit_settings() +{ + global $PHORUM; + return phorum_db_update_settings(array("mod_htmlpurifier"=>$PHORUM["mod_htmlpurifier"])); +} + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/release1-update.php b/vendor/ezyang/htmlpurifier/release1-update.php new file mode 100644 index 000000000..834d38567 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/release1-update.php @@ -0,0 +1,110 @@ +<?php + +// release script +// PHP 5.0 only + +if (php_sapi_name() != 'cli') { + echo 'Release script cannot be called from web-browser.'; + exit; +} + +if (!isset($argv[1])) { + echo +'php release.php [version] + HTML Purifier release script +'; + exit; +} + +$version = trim($argv[1]); + +// Bump version numbers: + +// ...in VERSION +file_put_contents('VERSION', $version); + +// ...in NEWS +if ($is_dev = (strpos($version, 'dev') === false)) { + $date = date('Y-m-d'); + $news_c = str_replace( + $l = "$version, unknown release date", + "$version, released $date", + file_get_contents('NEWS'), + $c + ); + if (!$c) { + echo 'Could not update NEWS, missing ' . $l . PHP_EOL; + exit; + } elseif ($c > 1) { + echo 'More than one release declaration in NEWS replaced' . PHP_EOL; + exit; + } + file_put_contents('NEWS', $news_c); +} + +// ...in Doxyfile +$doxyfile_c = preg_replace( + '/(?<=PROJECT_NUMBER {9}= )[^\s]+/m', // brittle + $version, + file_get_contents('Doxyfile'), + 1, $c +); +if (!$c) { + echo 'Could not update Doxyfile, missing PROJECT_NUMBER.' . PHP_EOL; + exit; +} +file_put_contents('Doxyfile', $doxyfile_c); + +// ...in HTMLPurifier.php +$htmlpurifier_c = file_get_contents('library/HTMLPurifier.php'); +$htmlpurifier_c = preg_replace( + '/HTML Purifier .+? - /', + "HTML Purifier $version - ", + $htmlpurifier_c, + 1, $c +); +if (!$c) { + echo 'Could not update HTMLPurifier.php, missing HTML Purifier [version] header.' . PHP_EOL; + exit; +} +$htmlpurifier_c = preg_replace( + '/public \$version = \'.+?\';/', + "public \$version = '$version';", + $htmlpurifier_c, + 1, $c +); +if (!$c) { + echo 'Could not update HTMLPurifier.php, missing public $version.' . PHP_EOL; + exit; +} +$htmlpurifier_c = preg_replace( + '/const VERSION = \'.+?\';/', + "const VERSION = '$version';", + $htmlpurifier_c, + 1, $c +); +if (!$c) { + echo 'Could not update HTMLPurifier.php, missing const $version.' . PHP_EOL; + exit; +} +file_put_contents('library/HTMLPurifier.php', $htmlpurifier_c); + +$config_c = file_get_contents('library/HTMLPurifier/Config.php'); +$config_c = preg_replace( + '/public \$version = \'.+?\';/', + "public \$version = '$version';", + $config_c, + 1, $c +); +if (!$c) { + echo 'Could not update Config.php, missing public $version.' . PHP_EOL; + exit; +} +file_put_contents('library/HTMLPurifier/Config.php', $config_c); + +passthru('php maintenance/flush.php'); + +if ($is_dev) echo "Review changes, write something in WHATSNEW and FOCUS, and then commit with log 'Release $version.'" . PHP_EOL; +else echo "Numbers updated to dev, no other modifications necessary!"; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/release2-tag.php b/vendor/ezyang/htmlpurifier/release2-tag.php new file mode 100644 index 000000000..25e5300d8 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/release2-tag.php @@ -0,0 +1,22 @@ +<?php + +// Tags releases + +if (php_sapi_name() != 'cli') { + echo 'Release script cannot be called from web-browser.'; + exit; +} + +require 'svn.php'; + +$svn_info = my_svn_info('.'); + +$version = trim(file_get_contents('VERSION')); + +$trunk_url = $svn_info['Repository Root'] . '/htmlpurifier/trunk'; +$trunk_tag_url = $svn_info['Repository Root'] . '/htmlpurifier/tags/' . $version; + +echo "Tagging trunk to tags/$version..."; +passthru("svn copy --message \"Tag $version release.\" $trunk_url $trunk_tag_url"); + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/test-settings.sample.php b/vendor/ezyang/htmlpurifier/test-settings.sample.php new file mode 100644 index 000000000..480b66279 --- /dev/null +++ b/vendor/ezyang/htmlpurifier/test-settings.sample.php @@ -0,0 +1,74 @@ +<?php + +// ATTENTION! DO NOT EDIT THIS FILE! +// This file is necessary to run the unit tests and profiling scripts. +// Please copy it to 'test-settings.php' and make the necessary edits. + +// Note: The only external library you *need* is SimpleTest; everything else +// is optional. + +// We've got a lot of tests, so we recommend turning the limit off. +set_time_limit(0); + +// Turning off output buffering will prevent mysterious errors from core dumps. +$data = @ob_get_clean(); +if ($data !== false && $data !== '') { + echo "Output buffer contains data [".urlencode($data)."]\n"; + exit; +} + +// ----------------------------------------------------------------------------- +// REQUIRED SETTINGS + +// Note on running SimpleTest: +// You want the Git copy of SimpleTest, found here: +// https://github.com/simpletest/simpletest/ +// +// If SimpleTest is borked with HTML Purifier, please contact me or +// the SimpleTest devs; I am a developer for SimpleTest so I should be +// able to quickly assess a fix. SimpleTest's problem is my problem! + +// Where is SimpleTest located? Remember to include a trailing slash! +$simpletest_location = '/path/to/simpletest/'; + +// ----------------------------------------------------------------------------- +// OPTIONAL SETTINGS + +// Note on running PHPT: +// Vanilla PHPT from https://github.com/tswicegood/PHPT_Core should +// work fine on Linux w/o multitest. +// +// To do multitest or Windows testing, you'll need some more +// patches at https://github.com/ezyang/PHPT_Core +// +// I haven't tested the Windows setup in a while so I don't know if +// it still works. + +// Should PHPT tests be enabled? +$GLOBALS['HTMLPurifierTest']['PHPT'] = false; + +// If PHPT isn't in your Path via PEAR, set that here: +// set_include_path('/path/to/phpt/Core/src' . PATH_SEPARATOR . get_include_path()); + +// Where is CSSTidy located? (Include trailing slash. Leave false to disable.) +$csstidy_location = false; + +// For tests/multitest.php, which versions to test? +$versions_to_test = array(); + +// Stable PHP binary to use when invoking maintenance scripts. +$php = 'php'; + +// For tests/multitest.php, what is the multi-version executable? It must +// accept an extra parameter (version number) before all other arguments +$phpv = false; + +// Should PEAR tests be run? If you've got a valid PEAR installation, set this +// to true (or, if it's not in the include path, to its install directory). +$GLOBALS['HTMLPurifierTest']['PEAR'] = false; + +// If PEAR is enabled, what PEAR tests should be run? (Note: you will +// need to ensure these libraries are installed) +$GLOBALS['HTMLPurifierTest']['Net_IDNA2'] = true; + +// vim: et sw=4 sts=4 diff --git a/vendor/ezyang/htmlpurifier/test-settings.travis.php b/vendor/ezyang/htmlpurifier/test-settings.travis.php new file mode 100644 index 000000000..b1edce4aa --- /dev/null +++ b/vendor/ezyang/htmlpurifier/test-settings.travis.php @@ -0,0 +1,72 @@ +<?php + +// This file is the configuration for Travis testing. + +// Note: The only external library you *need* is SimpleTest; everything else +// is optional. + +// We've got a lot of tests, so we recommend turning the limit off. +set_time_limit(0); + +// Turning off output buffering will prevent mysterious errors from core dumps. +$data = @ob_get_clean(); +if ($data !== false && $data !== '') { + echo "Output buffer contains data [".urlencode($data)."]\n"; + exit; +} + +// ----------------------------------------------------------------------------- +// REQUIRED SETTINGS + +// Note on running SimpleTest: +// You want the Git copy of SimpleTest, found here: +// https://github.com/simpletest/simpletest/ +// +// If SimpleTest is borked with HTML Purifier, please contact me or +// the SimpleTest devs; I am a developer for SimpleTest so I should be +// able to quickly assess a fix. SimpleTest's problem is my problem! + +// Where is SimpleTest located? Remember to include a trailing slash! +$simpletest_location = dirname(__FILE__) . '/simpletest/'; + +// ----------------------------------------------------------------------------- +// OPTIONAL SETTINGS + +// Note on running PHPT: +// Vanilla PHPT from https://github.com/tswicegood/PHPT_Core should +// work fine on Linux w/o multitest. +// +// To do multitest or Windows testing, you'll need some more +// patches at https://github.com/ezyang/PHPT_Core +// +// I haven't tested the Windows setup in a while so I don't know if +// it still works. + +// Should PHPT tests be enabled? +$GLOBALS['HTMLPurifierTest']['PHPT'] = false; + +// If PHPT isn't in your Path via PEAR, set that here: +// set_include_path('/path/to/phpt/Core/src' . PATH_SEPARATOR . get_include_path()); + +// Where is CSSTidy located? (Include trailing slash. Leave false to disable.) +$csstidy_location = false; + +// For tests/multitest.php, which versions to test? +$versions_to_test = array(); + +// Stable PHP binary to use when invoking maintenance scripts. +$php = 'php'; + +// For tests/multitest.php, what is the multi-version executable? It must +// accept an extra parameter (version number) before all other arguments +$phpv = false; + +// Should PEAR tests be run? If you've got a valid PEAR installation, set this +// to true (or, if it's not in the include path, to its install directory). +$GLOBALS['HTMLPurifierTest']['PEAR'] = false; + +// If PEAR is enabled, what PEAR tests should be run? (Note: you will +// need to ensure these libraries are installed) +$GLOBALS['HTMLPurifierTest']['Net_IDNA2'] = true; + +// vim: et sw=4 sts=4 |