Changeset 103194 in spip-zone


Ignore:
Timestamp:
Mar 8, 2017, 1:47:47 PM (3 years ago)
Author:
real3t@…
Message:

Mise à jour de la library HTMLPurifier en 4.9.1

==> Support de PHP 7 inclus !

Changelog : http://repo.or.cz/w/htmlpurifier.git?a=blob_plain;f=NEWS (précédemment, on était en 4.7.0)

Location:
_plugins_/htmlpurifier
Files:
23 added
8 edited

Legend:

Unmodified
Added
Removed
  • _plugins_/htmlpurifier/lib/HTMLPurifier.standalone.php

    r94428 r103194  
    88 * FILE, changes will be overwritten the next time the script is run.
    99 *
    10  * @version 4.7.0
     10 * @version 4.9.1
    1111 *
    1212 * @warning
     
    4040
    4141/*
    42     HTML Purifier 4.7.0 - Standards Compliant HTML Filtering
     42    HTML Purifier 4.9.1 - Standards Compliant HTML Filtering
    4343    Copyright (C) 2006-2008 Edward Z. Yang
    4444
     
    7979     * @type string
    8080     */
    81     public $version = '4.7.0';
     81    public $version = '4.9.1';
    8282
    8383    /**
    8484     * Constant with version of HTML Purifier.
    8585     */
    86     const VERSION = '4.7.0';
     86    const VERSION = '4.9.1';
    8787
    8888    /**
     
    125125     * Initializes the purifier.
    126126     *
    127      * @param HTMLPurifier_Config $config Optional HTMLPurifier_Config object
     127     * @param HTMLPurifier_Config|mixed $config Optional HTMLPurifier_Config object
    128128     *                for all instances of the purifier, if omitted, a default
    129129     *                configuration is supplied (which can be overridden on a
     
    333333                $token->start = null; // [MUT]
    334334                $r = array_pop($stack);
    335                 assert($r->name === $token->name);
    336                 assert(empty($token->attr));
     335                //assert($r->name === $token->name);
     336                //assert(empty($token->attr));
    337337                $r->endCol = $token->col;
    338338                $r->endLine = $token->line;
     
    346346            }
    347347        }
    348         assert(count($stack) == 1);
     348        //assert(count($stack) == 1);
    349349        return $stack[0];
    350350    }
     
    408408    public function __construct($attr_types, $modules)
    409409    {
     410        $this->doConstruct($attr_types, $modules);
     411    }
     412
     413    public function doConstruct($attr_types, $modules)
     414    {
    410415        // load extensions from the modules
    411416        foreach ($modules as $module) {
     
    616621    protected function mungeRgb($string)
    617622    {
    618         return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
     623        $p = '\s*(\d+(\.\d+)?([%]?))\s*';
     624
     625        if (preg_match('/(rgba|hsla)\(/', $string)) {
     626            return preg_replace('/(rgba|hsla)\('.$p.','.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8,\11)', $string);
     627        }
     628
     629        return preg_replace('/(rgb|hsl)\('.$p.','.$p.','.$p.'\)/', '\1(\2,\5,\8)', $string);
    619630    }
    620631
     
    14131424        $max = $config->get('CSS.MaxImgLength');
    14141425
     1426        $this->info['min-width'] =
     1427        $this->info['max-width'] =
     1428        $this->info['min-height'] =
     1429        $this->info['max-height'] =
    14151430        $this->info['width'] =
    14161431        $this->info['height'] =
     
    15571572        );
    15581573        $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(array('auto', 'avoid'));
     1574
     1575        $border_radius = new HTMLPurifier_AttrDef_CSS_Composite(
     1576            array(
     1577                new HTMLPurifier_AttrDef_CSS_Percentage(true), // disallow negative
     1578                new HTMLPurifier_AttrDef_CSS_Length('0') // disallow negative
     1579            ));
     1580
     1581        $this->info['border-top-left-radius'] =
     1582        $this->info['border-top-right-radius'] =
     1583        $this->info['border-bottom-right-radius'] =
     1584        $this->info['border-bottom-left-radius'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_radius, 2);
     1585        // TODO: support SLASH syntax
     1586        $this->info['border-radius'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_radius, 4);
    15591587
    15601588    }
     
    17371765     * @type string
    17381766     */
    1739     public $version = '4.7.0';
     1767    public $version = '4.9.1';
    17401768
    17411769    /**
     
    31993227    /**
    32003228     * Clears all expired (older version or revision) objects from cache
    3201      * @note Be carefuly implementing this method as flush. Flush must
     3229     * @note Be careful implementing this method as flush. Flush must
    32023230     *       not interfere with other Definition types, and cleanup()
    32033231     *       should not be repeatedly called by userland code.
     
    38533881     * non-SGML codepoints excluded.
    38543882     *
     3883     * Specifically, it will permit:
     3884     * \x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}
     3885     * Source: https://www.w3.org/TR/REC-xml/#NT-Char
     3886     * Arguably this function should be modernized to the HTML5 set
     3887     * of allowed characters:
     3888     * https://www.w3.org/TR/html5/syntax.html#preprocessing-the-input-stream
     3889     * which simultaneously expand and restrict the set of allowed characters.
     3890     *
    38553891     * @param string $str The string to clean
    38563892     * @param bool $force_php
     
    38743910     *       As of right now, only smart lossless character encoding converters
    38753911     *       would need that, and I'm probably not going to implement them.
    3876      *       Once again, PHP 6 should solve all our problems.
    38773912     */
    38783913    public static function cleanUTF8($str, $force_php = false)
     
    38813916        // This is an optimization: if the string is already valid UTF-8, no
    38823917        // need to do PHP stuff. 99% of the time, this will be the case.
    3883         // The regexp matches the XML char production, as well as well as excluding
    3884         // non-SGML codepoints U+007F to U+009F
    38853918        if (preg_match(
    38863919            '/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/Du',
     
    40074040                                // but it is non-SGML, and thus we don't allow it
    40084041                                (0xA0 <= $mUcs4 && 0xD7FF >= $mUcs4) ||
     4042                                (0xE000 <= $mUcs4 && 0xFFFD >= $mUcs4) ||
    40094043                                (0x10000 <= $mUcs4 && 0x10FFFF >= $mUcs4)
    40104044                            )
     
    44304464
    44314465    /**
     4466     * Callback regex string for entities in text.
     4467     * @type string
     4468     */
     4469    protected $_textEntitiesRegex;
     4470
     4471    /**
     4472     * Callback regex string for entities in attributes.
     4473     * @type string
     4474     */
     4475    protected $_attrEntitiesRegex;
     4476
     4477    /**
     4478     * Tests if the beginning of a string is a semi-optional regex
     4479     */
     4480    protected $_semiOptionalPrefixRegex;
     4481
     4482    public function __construct() {
     4483        // From
     4484        // http://stackoverflow.com/questions/15532252/why-is-reg-being-rendered-as-without-the-bounding-semicolon
     4485        $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";
     4486
     4487        // NB: three empty captures to put the fourth match in the right
     4488        // place
     4489        $this->_semiOptionalPrefixRegex = "/&()()()($semi_optional)/";
     4490
     4491        $this->_textEntitiesRegex =
     4492            '/&(?:'.
     4493            // hex
     4494            '[#]x([a-fA-F0-9]+);?|'.
     4495            // dec
     4496            '[#]0*(\d+);?|'.
     4497            // string (mandatory semicolon)
     4498            // NB: order matters: match semicolon preferentially
     4499            '([A-Za-z_:][A-Za-z0-9.\-_:]*);|'.
     4500            // string (optional semicolon)
     4501            "($semi_optional)".
     4502            ')/';
     4503
     4504        $this->_attrEntitiesRegex =
     4505            '/&(?:'.
     4506            // hex
     4507            '[#]x([a-fA-F0-9]+);?|'.
     4508            // dec
     4509            '[#]0*(\d+);?|'.
     4510            // string (mandatory semicolon)
     4511            // NB: order matters: match semicolon preferentially
     4512            '([A-Za-z_:][A-Za-z0-9.\-_:]*);|'.
     4513            // string (optional semicolon)
     4514            // don't match if trailing is equals or alphanumeric (URL
     4515            // like)
     4516            "($semi_optional)(?![=;A-Za-z0-9])".
     4517            ')/';
     4518
     4519    }
     4520
     4521    /**
     4522     * Substitute entities with the parsed equivalents.  Use this on
     4523     * textual data in an HTML document (as opposed to attributes.)
     4524     *
     4525     * @param string $string String to have entities parsed.
     4526     * @return string Parsed string.
     4527     */
     4528    public function substituteTextEntities($string)
     4529    {
     4530        return preg_replace_callback(
     4531            $this->_textEntitiesRegex,
     4532            array($this, 'entityCallback'),
     4533            $string
     4534        );
     4535    }
     4536
     4537    /**
     4538     * Substitute entities with the parsed equivalents.  Use this on
     4539     * attribute contents in documents.
     4540     *
     4541     * @param string $string String to have entities parsed.
     4542     * @return string Parsed string.
     4543     */
     4544    public function substituteAttrEntities($string)
     4545    {
     4546        return preg_replace_callback(
     4547            $this->_attrEntitiesRegex,
     4548            array($this, 'entityCallback'),
     4549            $string
     4550        );
     4551    }
     4552
     4553    /**
     4554     * Callback function for substituteNonSpecialEntities() that does the work.
     4555     *
     4556     * @param array $matches  PCRE matches array, with 0 the entire match, and
     4557     *                  either index 1, 2 or 3 set with a hex value, dec value,
     4558     *                  or string (respectively).
     4559     * @return string Replacement string.
     4560     */
     4561
     4562    protected function entityCallback($matches)
     4563    {
     4564        $entity = $matches[0];
     4565        $hex_part = @$matches[1];
     4566        $dec_part = @$matches[2];
     4567        $named_part = empty($matches[3]) ? @$matches[4] : $matches[3];
     4568        if ($hex_part) {
     4569            return HTMLPurifier_Encoder::unichr(hexdec($hex_part));
     4570        } elseif ($dec_part) {
     4571            return HTMLPurifier_Encoder((int) $dec_part);
     4572        } else {
     4573            if (!$this->_entity_lookup) {
     4574                $this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
     4575            }
     4576            if (isset($this->_entity_lookup->table[$named_part])) {
     4577                return $this->_entity_lookup->table[$named_part];
     4578            } else {
     4579                // exact match didn't match anything, so test if
     4580                // any of the semicolon optional match the prefix.
     4581                // Test that this is an EXACT match is important to
     4582                // prevent infinite loop
     4583                if (!empty($matches[3])) {
     4584                    return preg_replace_callback(
     4585                        $this->_semiOptionalPrefixRegex,
     4586                        array($this, 'entityCallback'),
     4587                        $entity
     4588                    );
     4589                }
     4590                return $entity;
     4591            }
     4592        }
     4593    }
     4594
     4595    // LEGACY CODE BELOW
     4596
     4597    /**
    44324598     * Callback regex string for parsing entities.
    44334599     * @type string
     
    45574723        } else {
    45584724            return isset($this->_special_ent2dec[$matches[3]]) ?
    4559                 $this->_special_ent2dec[$matches[3]] :
     4725                $this->_special_dec2str[$this->_special_ent2dec[$matches[3]]] :
    45604726                $entity;
    45614727        }
     
    62936459        if ($config->get('HTML.TargetBlank')) {
    62946460            $modules[] = 'TargetBlank';
     6461        }
     6462        // NB: HTML.TargetNoreferrer and HTML.TargetNoopener must be AFTER HTML.TargetBlank
     6463        // so that its post-attr-transform gets run afterwards.
     6464        if ($config->get('HTML.TargetNoreferrer')) {
     6465            $modules[] = 'TargetNoreferrer';
     6466        }
     6467        if ($config->get('HTML.TargetNoopener')) {
     6468            $modules[] = 'TargetNoopener';
    62956469        }
    62966470
     
    75687742        );
    75697743
     7744    public function parseText($string, $config) {
     7745        return $this->parseData($string, false, $config);
     7746    }
     7747
     7748    public function parseAttr($string, $config) {
     7749        return $this->parseData($string, true, $config);
     7750    }
     7751
    75707752    /**
    75717753     * Parses special entities into the proper characters.
     
    75747756     * into the correct ones.
    75757757     *
    7576      * @warning
    7577      * You should be able to treat the output of this function as
    7578      * completely parsed, but that's only because all other entities should
    7579      * have been handled previously in substituteNonSpecialEntities()
    7580      *
    75817758     * @param string $string String character data to be parsed.
    75827759     * @return string Parsed character data.
    75837760     */
    7584     public function parseData($string)
     7761    public function parseData($string, $is_attr, $config)
    75857762    {
    75867763        // following functions require at least one character
     
    76087785
    76097786        // hmm... now we have some uncommon entities. Use the callback.
    7610         $string = $this->_entity_parser->substituteSpecialEntities($string);
     7787        if ($config->get('Core.LegacyEntityDecoder')) {
     7788            $string = $this->_entity_parser->substituteSpecialEntities($string);
     7789        } else {
     7790            if ($is_attr) {
     7791                $string = $this->_entity_parser->substituteAttrEntities($string);
     7792            } else {
     7793                $string = $this->_entity_parser->substituteTextEntities($string);
     7794            }
     7795        }
    76117796        return $string;
    76127797    }
     
    77227907
    77237908        // expand entities that aren't the big five
    7724         $html = $this->_entity_parser->substituteNonSpecialEntities($html);
     7909        if ($config->get('Core.LegacyEntityDecoder')) {
     7910            $html = $this->_entity_parser->substituteNonSpecialEntities($html);
     7911        }
    77257912
    77267913        // clean into wellformed UTF-8 string for an SGML context: this has
     
    77347921        }
    77357922
     7923        if ($config->get('Core.AggressivelyRemoveScript') &&
     7924            !($config->get('HTML.Trusted') || !$config->get('Core.RemoveScriptContents')
     7925            || empty($config->get('Core.HiddenElements')["script"]))) {
     7926            $html = preg_replace('#<script[^>]*>.*?</script>#i', '', $html);
     7927        }
     7928
    77367929        return $html;
    77377930    }
     
    77447937    {
    77457938        $matches = array();
    7746         $result = preg_match('!<body[^>]*>(.*)</body>!is', $html, $matches);
     7939        $result = preg_match('|(.*?)<body[^>]*>(.*)</body>|is', $html, $matches);
    77477940        if ($result) {
    7748             return $matches[1];
    7749         } else {
    7750             return $html;
    7751         }
     7941            // Make sure it's not in a comment
     7942            $comment_start = strrpos($matches[1], '<!--');
     7943            $comment_end   = strrpos($matches[1], '-->');
     7944            if ($comment_start === false ||
     7945                ($comment_end !== false && $comment_end > $comment_start)) {
     7946                return $matches[2];
     7947            }
     7948        }
     7949        return $html;
    77527950    }
    77537951}
     
    84188616
    84198617    /**
    8420      * Used during MakeWellFormed.
     8618     * Used during MakeWellFormed.  See Note [Injector skips]
    84218619     * @type
    84228620     */
     
    86978895            $scheme_obj = $def->getDefaultScheme($config, $context);
    86988896            if (!$scheme_obj) {
    8699                 // something funky happened to the default scheme object
    8700                 trigger_error(
    8701                     'Default scheme object "' . $def->defaultScheme . '" was not readable',
    8702                     E_USER_WARNING
    8703                 );
     8897                if ($def->defaultScheme !== null) {
     8898                    // something funky happened to the default scheme object
     8899                    trigger_error(
     8900                        'Default scheme object "' . $def->defaultScheme . '" was not readable',
     8901                        E_USER_WARNING
     8902                    );
     8903                } // suppress error if it's null
    87048904                return false;
    87058905            }
     
    1007410274
    1007510275        $definition = $config->getCSSDefinition();
    10076 
    10077         // we're going to break the spec and explode by semicolons.
    10078         // This is because semicolon rarely appears in escaped form
    10079         // Doing this is generally flaky but fast
    10080         // IT MIGHT APPEAR IN URIs, see HTMLPurifier_AttrDef_CSSURI
    10081         // for details
    10082 
    10083         $declarations = explode(';', $css);
     10276        $allow_duplicates = $config->get("CSS.AllowDuplicates");
     10277
     10278
     10279        // According to the CSS2.1 spec, the places where a
     10280        // non-delimiting semicolon can appear are in strings
     10281        // escape sequences.   So here is some dumb hack to
     10282        // handle quotes.
     10283        $len = strlen($css);
     10284        $accum = "";
     10285        $declarations = array();
     10286        $quoted = false;
     10287        for ($i = 0; $i < $len; $i++) {
     10288            $c = strcspn($css, ";'\"", $i);
     10289            $accum .= substr($css, $i, $c);
     10290            $i += $c;
     10291            if ($i == $len) break;
     10292            $d = $css[$i];
     10293            if ($quoted) {
     10294                $accum .= $d;
     10295                if ($d == $quoted) {
     10296                    $quoted = false;
     10297                }
     10298            } else {
     10299                if ($d == ";") {
     10300                    $declarations[] = $accum;
     10301                    $accum = "";
     10302                } else {
     10303                    $accum .= $d;
     10304                    $quoted = $d;
     10305                }
     10306            }
     10307        }
     10308        if ($accum != "") $declarations[] = $accum;
     10309
    1008410310        $propvalues = array();
     10311        $new_declarations = '';
    1008510312
    1008610313        /**
     
    1013210359                continue;
    1013310360            }
    10134             $propvalues[$property] = $result;
     10361            if ($allow_duplicates) {
     10362                $new_declarations .= "$property:$result;";
     10363            } else {
     10364                $propvalues[$property] = $result;
     10365            }
    1013510366        }
    1013610367
     
    1014110372        // duplicates. Perhaps config to optimize it, but not now.
    1014210373
    10143         $new_declarations = '';
    1014410374        foreach ($propvalues as $prop => $value) {
    1014510375            $new_declarations .= "$prop:$value;";
     
    1109611326
    1109711327    /**
     11328     * @type HTMLPurifier_AttrDef_CSS_AlphaValue
     11329     */
     11330    protected $alpha;
     11331
     11332    public function __construct()
     11333    {
     11334        $this->alpha = new HTMLPurifier_AttrDef_CSS_AlphaValue();
     11335    }
     11336
     11337    /**
    1109811338     * @param string $color
    1109911339     * @param HTMLPurifier_Config $config
     
    1111811358        }
    1111911359
    11120         if (strpos($color, 'rgb(') !== false) {
    11121             // rgb literal handling
     11360        if (preg_match('#(rgb|rgba|hsl|hsla)\(#', $color, $matches) === 1) {
    1112211361            $length = strlen($color);
    1112311362            if (strpos($color, ')') !== $length - 1) {
    1112411363                return false;
    1112511364            }
    11126             $triad = substr($color, 4, $length - 4 - 1);
    11127             $parts = explode(',', $triad);
    11128             if (count($parts) !== 3) {
     11365
     11366            // get used function : rgb, rgba, hsl or hsla
     11367            $function = $matches[1];
     11368
     11369            $parameters_size = 3;
     11370            $alpha_channel = false;
     11371            if (substr($function, -1) === 'a') {
     11372                $parameters_size = 4;
     11373                $alpha_channel = true;
     11374            }
     11375
     11376            /*
     11377             * Allowed types for values :
     11378             * parameter_position => [type => max_value]
     11379             */
     11380            $allowed_types = [
     11381                1 => ['percentage' => 100, 'integer' => 255],
     11382                2 => ['percentage' => 100, 'integer' => 255],
     11383                3 => ['percentage' => 100, 'integer' => 255],
     11384            ];
     11385            $allow_different_types = false;
     11386
     11387            if (strpos($function, 'hsl') !== false) {
     11388                $allowed_types = [
     11389                    1 => ['integer' => 360],
     11390                    2 => ['percentage' => 100],
     11391                    3 => ['percentage' => 100],
     11392                ];
     11393                $allow_different_types = true;
     11394            }
     11395
     11396            $values = trim(str_replace($function, '', $color), ' ()');
     11397
     11398            $parts = explode(',', $values);
     11399            if (count($parts) !== $parameters_size) {
    1112911400                return false;
    1113011401            }
    11131             $type = false; // to ensure that they're all the same type
     11402
     11403            $type = false;
    1113211404            $new_parts = array();
     11405            $i = 0;
     11406
    1113311407            foreach ($parts as $part) {
     11408                $i++;
    1113411409                $part = trim($part);
     11410
    1113511411                if ($part === '') {
    1113611412                    return false;
    1113711413                }
    11138                 $length = strlen($part);
    11139                 if ($part[$length - 1] === '%') {
    11140                     // handle percents
    11141                     if (!$type) {
    11142                         $type = 'percentage';
    11143                     } elseif ($type !== 'percentage') {
     11414
     11415                // different check for alpha channel
     11416                if ($alpha_channel === true && $i === count($parts)) {
     11417                    $result = $this->alpha->validate($part, $config, $context);
     11418
     11419                    if ($result === false) {
    1114411420                        return false;
    1114511421                    }
    11146                     $num = (float)substr($part, 0, $length - 1);
    11147                     if ($num < 0) {
    11148                         $num = 0;
    11149                     }
    11150                     if ($num > 100) {
    11151                         $num = 100;
    11152                     }
    11153                     $new_parts[] = "$num%";
     11422
     11423                    $new_parts[] = (string)$result;
     11424                    continue;
     11425                }
     11426
     11427                if (substr($part, -1) === '%') {
     11428                    $current_type = 'percentage';
    1115411429                } else {
    11155                     // handle integers
    11156                     if (!$type) {
    11157                         $type = 'integer';
    11158                     } elseif ($type !== 'integer') {
    11159                         return false;
    11160                     }
    11161                     $num = (int)$part;
    11162                     if ($num < 0) {
    11163                         $num = 0;
    11164                     }
    11165                     if ($num > 255) {
    11166                         $num = 255;
    11167                     }
    11168                     $new_parts[] = (string)$num;
     11430                    $current_type = 'integer';
    1116911431                }
    11170             }
    11171             $new_triad = implode(',', $new_parts);
    11172             $color = "rgb($new_triad)";
     11432
     11433                if (!array_key_exists($current_type, $allowed_types[$i])) {
     11434                    return false;
     11435                }
     11436
     11437                if (!$type) {
     11438                    $type = $current_type;
     11439                }
     11440
     11441                if ($allow_different_types === false && $type != $current_type) {
     11442                    return false;
     11443                }
     11444
     11445                $max_value = $allowed_types[$i][$current_type];
     11446
     11447                if ($current_type == 'integer') {
     11448                    // Return value between range 0 -> $max_value
     11449                    $new_parts[] = (int)max(min($part, $max_value), 0);
     11450                } elseif ($current_type == 'percentage') {
     11451                    $new_parts[] = (float)max(min(rtrim($part, '%'), $max_value), 0) . '%';
     11452                }
     11453            }
     11454
     11455            $new_values = implode(',', $new_parts);
     11456
     11457            $color = $function . '(' . $new_values . ')';
    1117311458        } else {
    1117411459            // hexadecimal handling
     
    1118911474        return $color;
    1119011475    }
     11476
    1119111477}
    1119211478
     
    1225212538        }
    1225312539        $uri_string = substr($uri_string, 4);
     12540        if (strlen($uri_string) == 0) {
     12541            return false;
     12542        }
    1225412543        $new_length = strlen($uri_string) - 1;
    1225512544        if ($uri_string[$new_length] != ')') {
     
    1262612915        // we purposely avoid using regex, hopefully this is faster
    1262712916
    12628         if (ctype_alpha($id)) {
    12629             $result = true;
     12917        if ($config->get('Attr.ID.HTML5') === true) {
     12918            if (preg_match('/[\t\n\x0b\x0c ]/', $id)) {
     12919                return false;
     12920            }
    1263012921        } else {
    12631             if (!ctype_alpha(@$id[0])) {
    12632                 return false;
    12633             }
    12634             // primitive style of regexps, I suppose
    12635             $trim = trim(
    12636                 $id,
    12637                 'A..Za..z0..9:-._'
    12638             );
    12639             $result = ($trim === '');
     12922            if (ctype_alpha($id)) {
     12923                // OK
     12924            } else {
     12925                if (!ctype_alpha(@$id[0])) {
     12926                    return false;
     12927                }
     12928                // primitive style of regexps, I suppose
     12929                $trim = trim(
     12930                    $id,
     12931                    'A..Za..z0..9:-._'
     12932                );
     12933                if ($trim !== '') {
     12934                    return false;
     12935                }
     12936            }
    1264012937        }
    1264112938
     
    1264512942        }
    1264612943
    12647         if (!$this->selector && $result) {
     12944        if (!$this->selector) {
    1264812945            $id_accumulator->add($id);
    1264912946        }
     
    1265212949        // else, return the new id if stripping whitespace made it
    1265312950        //     valid, or return false.
    12654         return $result ? $id : false;
     12951        return $id;
    1265512952    }
    1265612953}
     
    1302513322        $underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : '';
    1302613323
     13324        // Based off of RFC 1738, but amended so that
     13325        // as per RFC 3696, the top label need only not be all numeric.
    1302713326        // The productions describing this are:
    1302813327        $a   = '[a-z]';     // alpha
     
    1303013329        $and = "[a-z0-9-$underscore]"; // alphanum | "-"
    1303113330        // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
    13032         $domainlabel = "$an($and*$an)?";
    13033         // toplabel    = alpha | alpha *( alphanum | "-" ) alphanum
    13034         $toplabel = "$a($and*$an)?";
     13331        $domainlabel = "$an(?:$and*$an)?";
     13332        // AMENDED as per RFC 3696
     13333        // toplabel    = alphanum | alphanum *( alphanum | "-" ) alphanum
     13334        //      side condition: not all numeric
     13335        $toplabel = "$an(?:$and*$an)?";
    1303513336        // hostname    = *( domainlabel "." ) toplabel [ "." ]
    13036         if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
    13037             return $string;
    13038         }
     13337        if (preg_match("/^(?:$domainlabel\.)*($toplabel)\.?$/i", $string, $matches)) {
     13338            if (!ctype_digit($matches[1])) {
     13339                return $string;
     13340            }
     13341        }
     13342
     13343        // PHP 5.3 and later support this functionality natively
     13344        if (function_exists('idn_to_ascii')) {
     13345            $string = idn_to_ascii($string);
    1303913346
    1304013347        // If we have Net_IDNA2 support, we can support IRIs by
    1304113348        // punycoding them. (This is the most portable thing to do,
    1304213349        // since otherwise we have to assume browsers support
    13043 
    13044         if ($config->get('Core.EnableIDNA')) {
     13350        } elseif ($config->get('Core.EnableIDNA')) {
    1304513351            $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
    1304613352            // we need to encode each period separately
     
    1306313369                }
    1306413370                $string = implode('.', $new_parts);
    13065                 if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
    13066                     return $string;
    13067                 }
    1306813371            } catch (Exception $e) {
    1306913372                // XXX error reporting
    1307013373            }
     13374        }
     13375        // Try again
     13376        if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
     13377            return $string;
    1307113378        }
    1307213379        return false;
     
    1350613813                $alt = $config->get('Attr.DefaultImageAlt');
    1350713814                if ($alt === null) {
    13508                     // truncate if the alt is too long
    13509                     $attr['alt'] = substr(basename($attr['src']), 0, 40);
     13815                    $attr['alt'] = basename($attr['src']);
    1351013816                } else {
    1351113817                    $attr['alt'] = $alt;
     
    1405414360
    1405514361
     14362// must be called POST validation
     14363
     14364/**
     14365 * Adds rel="noopener" to any links which target a different window
     14366 * than the current one.  This is used to prevent malicious websites
     14367 * from silently replacing the original window, which could be used
     14368 * to do phishing.
     14369 * This transform is controlled by %HTML.TargetNoopener.
     14370 */
     14371class HTMLPurifier_AttrTransform_TargetNoopener extends HTMLPurifier_AttrTransform
     14372{
     14373    /**
     14374     * @param array $attr
     14375     * @param HTMLPurifier_Config $config
     14376     * @param HTMLPurifier_Context $context
     14377     * @return array
     14378     */
     14379    public function transform($attr, $config, $context)
     14380    {
     14381        if (isset($attr['rel'])) {
     14382            $rels = explode(' ', $attr['rel']);
     14383        } else {
     14384            $rels = array();
     14385        }
     14386        if (isset($attr['target']) && !in_array('noopener', $rels)) {
     14387            $rels[] = 'noopener';
     14388        }
     14389        if (!empty($rels) || isset($attr['rel'])) {
     14390            $attr['rel'] = implode(' ', $rels);
     14391        }
     14392
     14393        return $attr;
     14394    }
     14395}
     14396
     14397
     14398
     14399
     14400// must be called POST validation
     14401
     14402/**
     14403 * Adds rel="noreferrer" to any links which target a different window
     14404 * than the current one.  This is used to prevent malicious websites
     14405 * from silently replacing the original window, which could be used
     14406 * to do phishing.
     14407 * This transform is controlled by %HTML.TargetNoreferrer.
     14408 */
     14409class HTMLPurifier_AttrTransform_TargetNoreferrer extends HTMLPurifier_AttrTransform
     14410{
     14411    /**
     14412     * @param array $attr
     14413     * @param HTMLPurifier_Config $config
     14414     * @param HTMLPurifier_Context $context
     14415     * @return array
     14416     */
     14417    public function transform($attr, $config, $context)
     14418    {
     14419        if (isset($attr['rel'])) {
     14420            $rels = explode(' ', $attr['rel']);
     14421        } else {
     14422            $rels = array();
     14423        }
     14424        if (isset($attr['target']) && !in_array('noreferrer', $rels)) {
     14425            $rels[] = 'noreferrer';
     14426        }
     14427        if (!empty($rels) || isset($attr['rel'])) {
     14428            $attr['rel'] = implode(' ', $rels);
     14429        }
     14430
     14431        return $attr;
     14432    }
     14433}
     14434
     14435
     14436
     14437
    1405614438/**
    1405714439 * Sets height/width defaults for <textarea>
     
    1432714709        // if there are no tokens, delete parent node
    1432814710        if (empty($children)) {
     14711            return false;
     14712        }
     14713
     14714        // if li is not allowed, delete parent node
     14715        if (!isset($config->getHTMLDefinition()->info['li'])) {
     14716            trigger_error("Cannot allow ul/ol without allowing li", E_USER_WARNING);
    1432914717            return false;
    1433014718        }
     
    1485815246                    break;
    1485915247                case '#PCDATA':
    14860                     assert($node->is_whitespace);
     15248                    //assert($node->is_whitespace);
    1486115249                    if ($current_tr_tbody === null) {
    1486215250                        $ret[] = $node;
     
    1516715555        $dir = $this->generateDirectoryPath($config);
    1516815556        $dh = opendir($dir);
     15557        // Apparently, on some versions of PHP, readdir will return
     15558        // an empty string if you pass an invalid argument to readdir.
     15559        // So you need this test.  See #49.
     15560        if (false === $dh) {
     15561            return false;
     15562        }
    1516915563        while (false !== ($filename = readdir($dh))) {
    1517015564            if (empty($filename)) {
     
    1517615570            unlink($dir . '/' . $filename);
    1517715571        }
     15572        closedir($dh);
     15573        return true;
    1517815574    }
    1517915575
     
    1518915585        $dir = $this->generateDirectoryPath($config);
    1519015586        $dh = opendir($dir);
     15587        // See #49 (and above).
     15588        if (false === $dh) {
     15589            return false;
     15590        }
    1519115591        while (false !== ($filename = readdir($dh))) {
    1519215592            if (empty($filename)) {
     
    1520115601            }
    1520215602        }
     15603        closedir($dh);
     15604        return true;
    1520315605    }
    1520415606
     
    1525615658            // set permissions of the new file (no execute)
    1525715659            $chmod = $config->get('Cache.SerializerPermissions');
    15258             if (!$chmod) {
    15259                 $chmod = 0644; // invalid config or simpletest
    15260             }
    15261             $chmod = $chmod & 0666;
    15262             chmod($file, $chmod);
     15660            if ($chmod !== null) {
     15661                chmod($file, $chmod & 0666);
     15662            }
    1526315663        }
    1526415664        return $result;
     
    1527415674        $directory = $this->generateDirectoryPath($config);
    1527515675        $chmod = $config->get('Cache.SerializerPermissions');
    15276         if (!$chmod) {
    15277             $chmod = 0755; // invalid config or simpletest
     15676        if ($chmod === null) {
     15677            // TODO: This races
     15678            if (is_dir($directory)) return true;
     15679            return mkdir($directory);
    1527815680        }
    1527915681        if (!is_dir($directory)) {
     
    1528915691                return false;
    1529015692            }
    15291             mkdir($directory, $chmod);
    15292             if (!$this->_testPermissions($directory, $chmod)) {
     15693            if (!mkdir($directory, $chmod)) {
    1529315694                trigger_error(
    15294                     'Base directory ' . $base . ' does not exist,
    15295                     please create or change using %Cache.SerializerPath',
     15695                    'Could not create directory ' . $directory . '',
    1529615696                    E_USER_WARNING
    1529715697                );
     15698                return false;
     15699            }
     15700            if (!$this->_testPermissions($directory, $chmod)) {
    1529815701                return false;
    1529915702            }
     
    1532615729            return false;
    1532715730        }
    15328         if (function_exists('posix_getuid')) {
     15731        if (function_exists('posix_getuid') && $chmod !== null) {
    1532915732            // POSIX system, we can give more specific advice
    1533015733            if (fileowner($dir) === posix_getuid()) {
     
    1687517278
    1687617279/**
     17280 * Module adds the target-based noopener attribute transformation to a tags.  It
     17281 * is enabled by HTML.TargetNoopener
     17282 */
     17283class HTMLPurifier_HTMLModule_TargetNoopener extends HTMLPurifier_HTMLModule
     17284{
     17285    /**
     17286     * @type string
     17287     */
     17288    public $name = 'TargetNoopener';
     17289
     17290    /**
     17291     * @param HTMLPurifier_Config $config
     17292     */
     17293    public function setup($config) {
     17294        $a = $this->addBlankElement('a');
     17295        $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetNoopener();
     17296    }
     17297}
     17298
     17299
     17300
     17301/**
     17302 * Module adds the target-based noreferrer attribute transformation to a tags.  It
     17303 * is enabled by HTML.TargetNoreferrer
     17304 */
     17305class HTMLPurifier_HTMLModule_TargetNoreferrer extends HTMLPurifier_HTMLModule
     17306{
     17307    /**
     17308     * @type string
     17309     */
     17310    public $name = 'TargetNoreferrer';
     17311
     17312    /**
     17313     * @param HTMLPurifier_Config $config
     17314     */
     17315    public function setup($config) {
     17316        $a = $this->addBlankElement('a');
     17317        $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetNoreferrer();
     17318    }
     17319}
     17320
     17321
     17322
     17323/**
    1687717324 * XHTML 1.1 Text Module, defines basic text containers. Core Module.
    1687817325 * @note In the normative XML Schema specification, this module
     
    1798018427        }
    1798118428
    17982         // there is/are URL(s). Let's split the string:
    17983         // Note: this regex is extremely permissive
    17984         $bits = preg_split('#((?:https?|ftp)://[^\s\'",<>()]+)#Su', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE);
     18429        // there is/are URL(s). Let's split the string.
     18430        // We use this regex:
     18431        // https://gist.github.com/gruber/249502
     18432        // but with @cscott's backtracking fix and also
     18433        // the Unicode characters un-Unicodified.
     18434        $bits = preg_split(
     18435            '/\\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',
     18436            $token->data, -1, PREG_SPLIT_DELIM_CAPTURE);
    1798518437
    1798618438
     
    1812718579        $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions');
    1812818580        $this->exclude = $config->get('AutoFormat.RemoveEmpty.Predicate');
     18581        foreach ($this->exclude as $key => $attrs) {
     18582            if (!is_array($attrs)) {
     18583                // HACK, see HTMLPurifier/Printer/ConfigForm.php
     18584                $this->exclude[$key] = explode(';', $attrs);
     18585            }
     18586        }
    1812918587        $this->attrValidator = new HTMLPurifier_AttrValidator();
    1813018588    }
     
    1830918767
    1831018768    /**
     18769     * These are all lower-case keys.
    1831118770     * @type array
    1831218771     */
     
    1831618775        'flashvars' => true,
    1831718776        'src' => true,
    18318         'allowFullScreen' => true, // if omitted, assume to be 'false'
     18777        'allowfullscreen' => true, // if omitted, assume to be 'false'
    1831918778    );
    1832018779
     
    1836618825                    // keep token, and add to param stack
    1836718826                    $this->paramStack[$i][$n] = true;
    18368                 } elseif (isset($this->allowedParam[$n])) {
     18827                } elseif (isset($this->allowedParam[strtolower($n)])) {
    1836918828                    // keep token, don't do anything to it
    1837018829                    // (could possibly check for duplicates here)
     18830                    // Note: In principle, parameters should be case sensitive.
     18831                    // But it seems they are not really; so accept any case.
    1837118832                } else {
    1837218833                    $token = false;
     
    1846718928        restore_error_handler();
    1846818929
     18930        $body = $doc->getElementsByTagName('html')->item(0)-> // <html>
     18931                      getElementsByTagName('body')->item(0);  // <body>
     18932
     18933        $div = $body->getElementsByTagName('div')->item(0); // <div>
    1846918934        $tokens = array();
    18470         $this->tokenizeDOM(
    18471             $doc->getElementsByTagName('html')->item(0)-> // <html>
    18472             getElementsByTagName('body')->item(0), //   <body>
    18473             $tokens
    18474         );
     18935        $this->tokenizeDOM($div, $tokens, $config);
     18936        // If the div has a sibling, that means we tripped across
     18937        // a premature </div> tag.  So remove the div we parsed,
     18938        // and then tokenize the rest of body.  We can't tokenize
     18939        // the sibling directly as we'll lose the tags in that case.
     18940        if ($div->nextSibling) {
     18941            $body->removeChild($div);
     18942            $this->tokenizeDOM($body, $tokens, $config);
     18943        }
    1847518944        return $tokens;
    1847618945    }
     
    1848318952     * @return HTMLPurifier_Token of node appended to previously passed tokens.
    1848418953     */
    18485     protected function tokenizeDOM($node, &$tokens)
     18954    protected function tokenizeDOM($node, &$tokens, $config)
    1848618955    {
    1848718956        $level = 0;
     
    1849218961                $node = $nodes[$level]->shift(); // FIFO
    1849318962                $collect = $level > 0 ? true : false;
    18494                 $needEndingTag = $this->createStartNode($node, $tokens, $collect);
     18963                $needEndingTag = $this->createStartNode($node, $tokens, $collect, $config);
    1849518964                if ($needEndingTag) {
    1849618965                    $closingNodes[$level][] = $node;
     
    1852218991     * @todo data and tagName properties don't seem to exist in DOMNode?
    1852318992     */
    18524     protected function createStartNode($node, &$tokens, $collect)
     18993    protected function createStartNode($node, &$tokens, $collect, $config)
    1852518994    {
    1852618995        // intercept non element nodes. WE MUST catch all of them,
     
    1854619015                }
    1854719016            }
    18548             $tokens[] = $this->factory->createText($this->parseData($data));
     19017            $tokens[] = $this->factory->createText($this->parseText($data, $config));
    1854919018            return false;
    1855019019        } elseif ($node->nodeType === XML_COMMENT_NODE) {
     
    1864719116     * @return string
    1864819117     */
    18649     protected function wrapHTML($html, $config, $context)
     19118    protected function wrapHTML($html, $config, $context, $use_div = true)
    1865019119    {
    1865119120        $def = $config->getDefinition('HTML');
     
    1866619135        $ret .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
    1866719136        // No protection if $html contains a stray </div>!
    18668         $ret .= '</head><body>' . $html . '</body></html>';
     19137        $ret .= '</head><body>';
     19138        if ($use_div) $ret .= '<div>';
     19139        $ret .= $html;
     19140        if ($use_div) $ret .= '</div>';
     19141        $ret .= '</body></html>';
    1866919142        return $ret;
    1867019143    }
     
    1880419277                $token = new
    1880519278                HTMLPurifier_Token_Text(
    18806                     $this->parseData(
     19279                    $this->parseText(
    1880719280                        substr(
    1880819281                            $html,
    1880919282                            $cursor,
    1881019283                            $position_next_lt - $cursor
    18811                         )
     19284                        ), $config
    1881219285                    )
    1881319286                );
     
    1882919302                $token = new
    1883019303                HTMLPurifier_Token_Text(
    18831                     $this->parseData(
     19304                    $this->parseText(
    1883219305                        substr(
    1883319306                            $html,
    1883419307                            $cursor
    18835                         )
     19308                        ), $config
    1883619309                    )
    1883719310                );
     
    1899919472                HTMLPurifier_Token_Text(
    1900019473                    '<' .
    19001                     $this->parseData(
    19002                         substr($html, $cursor)
     19474                    $this->parseText(
     19475                        substr($html, $cursor), $config
    1900319476                    )
    1900419477                );
     
    1910419577                $value = '';
    1910519578            }
    19106             return array($key => $this->parseData($value));
     19579            return array($key => $this->parseAttr($value, $config));
    1910719580        }
    1910819581
     
    1919319666                    $value = '';
    1919419667                }
    19195                 $array[$key] = $this->parseData($value);
     19668                $array[$key] = $this->parseAttr($value, $config);
    1919619669                $cursor++;
    1919719670            } else {
     
    1976320236                        $token = $zipper->prev($token);
    1976420237                        // indicate that other injectors should not process this token,
    19765                         // but we need to reprocess it
     20238                        // but we need to reprocess it.  See Note [Injector skips]
    1976620239                        unset($token->skip[$i]);
    1976720240                        $token->rewind = $i;
     
    1980820281                    foreach ($this->injectors as $i => $injector) {
    1980920282                        if (isset($token->skip[$i])) {
     20283                            // See Note [Injector skips]
    1981020284                            continue;
    1981120285                        }
     
    1996520439                foreach ($this->injectors as $i => $injector) {
    1996620440                    if (isset($token->skip[$i])) {
     20441                        // See Note [Injector skips]
    1996720442                        continue;
    1996820443                    }
     
    2002020495                foreach ($this->injectors as $i => $injector) {
    2002120496                    if (isset($token->skip[$i])) {
     20497                        // See Note [Injector skips]
    2002220498                        continue;
    2002320499                    }
     
    2013220608    protected function processToken($token, $injector = -1)
    2013320609    {
     20610        // Zend OpCache miscompiles $token = array($token), so
     20611        // avoid this pattern.  See: https://github.com/ezyang/htmlpurifier/issues/108
     20612
    2013420613        // normalize forms of token
    2013520614        if (is_object($token)) {
    20136             $token = array(1, $token);
     20615            $tmp = $token;
     20616            $token = array(1, $tmp);
    2013720617        }
    2013820618        if (is_int($token)) {
    20139             $token = array($token);
     20619            $tmp = $token;
     20620            $token = array($tmp);
    2014020621        }
    2014120622        if ($token === false) {
     
    2015920640
    2016020641        if ($injector > -1) {
    20161             // determine appropriate skips
     20642            // See Note [Injector skips]
     20643            // Determine appropriate skips.  Here's what the code does:
     20644            //  *If* we deleted one or more tokens, copy the skips
     20645            //  of those tokens into the skips of the new tokens (in $token).
     20646            //  Also, mark the newly inserted tokens as having come from
     20647            //  $injector.
    2016220648            $oldskip = isset($old[0]) ? $old[0]->skip : array();
    2016320649            foreach ($token as $object) {
     
    2019420680    }
    2019520681}
     20682
     20683// Note [Injector skips]
     20684// ~~~~~~~~~~~~~~~~~~~~~
     20685// When I originally designed this class, the idea behind the 'skip'
     20686// property of HTMLPurifier_Token was to help avoid infinite loops
     20687// in injector processing.  For example, suppose you wrote an injector
     20688// that bolded swear words.  Naively, you might write it so that
     20689// whenever you saw ****, you replaced it with <strong>****</strong>.
     20690//
     20691// When this happens, we will reprocess all of the tokens with the
     20692// other injectors.  Now there is an opportunity for infinite loop:
     20693// if we rerun the swear-word injector on these tokens, we might
     20694// see **** and then reprocess again to get
     20695// <strong><strong>****</strong></strong> ad infinitum.
     20696//
     20697// Thus, the idea of a skip is that once we process a token with
     20698// an injector, we mark all of those tokens as having "come from"
     20699// the injector, and we never run the injector again on these
     20700// tokens.
     20701//
     20702// There were two more complications, however:
     20703//
     20704//  - With HTMLPurifier_Injector_RemoveEmpty, we noticed that if
     20705//    you had <b><i></i></b>, after you removed the <i></i>, you
     20706//    really would like this injector to go back and reprocess
     20707//    the <b> tag, discovering that it is now empty and can be
     20708//    removed.  So we reintroduced the possibility of infinite looping
     20709//    by adding a "rewind" function, which let you go back to an
     20710//    earlier point in the token stream and reprocess it with injectors.
     20711//    Needless to say, we need to UN-skip the token so it gets
     20712//    reprocessed.
     20713//
     20714//  - Suppose that you successfuly process a token, replace it with
     20715//    one with your skip mark, but now another injector wants to
     20716//    process the skipped token with another token.  Should you continue
     20717//    to skip that new token, or reprocess it?  If you reprocess,
     20718//    you can end up with an infinite loop where one injector converts
     20719//    <a> to <b>, and then another injector converts it back.  So
     20720//    we inherit the skips, but for some reason, I thought that we
     20721//    should inherit the skip from the first token of the token
     20722//    that we deleted.  Why?  Well, it seems to work OK.
     20723//
     20724// If I were to redesign this functionality, I would absolutely not
     20725// go about doing it this way: the semantics are just not very well
     20726// defined, and in any case you probably wanted to operate on trees,
     20727// not token streams.
    2019620728
    2019720729
     
    2140121933            $raw_data = $data;
    2140221934        }
     21935        if ( strlen($raw_data) < 12 ) {
     21936            // error; exif_imagetype throws exception with small files,
     21937            // and this likely indicates a corrupt URI/failed parse anyway
     21938            return false;
     21939        }
    2140321940        // XXX probably want to refactor this into a general mechanism
    2140421941        // for filtering arbitrary content types
    21405         $file = tempnam("/tmp", "");
     21942        if (function_exists('sys_get_temp_dir')) {
     21943            $file = tempnam(sys_get_temp_dir(), "");
     21944        } else {
     21945            $file = tempnam("/tmp", "");
     21946        }
    2140621947        file_put_contents($file, $raw_data);
    2140721948        if (function_exists('exif_imagetype')) {
     
    2171222253        $uri->userinfo = null;
    2171322254        $uri->query = null;
     22255        return true;
     22256    }
     22257}
     22258
     22259
     22260
     22261
     22262
     22263/**
     22264 * Validates tel (for phone numbers).
     22265 *
     22266 * The relevant specifications for this protocol are RFC 3966 and RFC 5341,
     22267 * but this class takes a much simpler approach: we normalize phone
     22268 * numbers so that they only include (possibly) a leading plus,
     22269 * and then any number of digits and x'es.
     22270 */
     22271
     22272class HTMLPurifier_URIScheme_tel extends HTMLPurifier_URIScheme
     22273{
     22274    /**
     22275     * @type bool
     22276     */
     22277    public $browsable = false;
     22278
     22279    /**
     22280     * @type bool
     22281     */
     22282    public $may_omit_host = true;
     22283
     22284    /**
     22285     * @param HTMLPurifier_URI $uri
     22286     * @param HTMLPurifier_Config $config
     22287     * @param HTMLPurifier_Context $context
     22288     * @return bool
     22289     */
     22290    public function doValidate(&$uri, $config, $context)
     22291    {
     22292        $uri->userinfo = null;
     22293        $uri->host     = null;
     22294        $uri->port     = null;
     22295
     22296        // Delete all non-numeric characters, non-x characters
     22297        // from phone number, EXCEPT for a leading plus sign.
     22298        $uri->path = preg_replace('/(?!^\+)[^\dx]/', '',
     22299                     // Normalize e(x)tension to lower-case
     22300                     str_replace('X', 'x', $uri->path));
     22301
    2171422302        return true;
    2171522303    }
  • _plugins_/htmlpurifier/lib/standalone/HTMLPurifier/ConfigSchema/schema.ser

    r94428 r103194  
    1 O:25:"HTMLPurifier_ConfigSchema":3:{s:8:"defaults";a:119:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";s:6:"1200px";s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:17:{s:6:"maroon";s:7:"#800000";s:3:"red";s:7:"#FF0000";s:6:"orange";s:7:"#FFA500";s:6:"yellow";s:7:"#FFFF00";s:5:"olive";s:7:"#808000";s:6:"purple";s:7:"#800080";s:7:"fuchsia";s:7:"#FF00FF";s:5:"white";s:7:"#FFFFFF";s:4:"lime";s:7:"#00FF00";s:5:"green";s:7:"#008000";s:4:"navy";s:7:"#000080";s:4:"blue";s:7:"#0000FF";s:4:"aqua";s:7:"#00FFFF";s:4:"teal";s:7:"#008080";s:5:"black";s:7:"#000000";s:6:"silver";s:7:"#C0C0C0";s:4:"gray";s:7:"#808080";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:17:"HTML.MaxImgLength";i:1200;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:6:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;}s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:20:"URI.SafeIframeRegexp";N;}s:12:"defaultPlist";O:25:"HTMLPurifier_PropertyList":3:{s:7:"*data";a:119:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";s:6:"1200px";s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:17:{s:6:"maroon";s:7:"#800000";s:3:"red";s:7:"#FF0000";s:6:"orange";s:7:"#FFA500";s:6:"yellow";s:7:"#FFFF00";s:5:"olive";s:7:"#808000";s:6:"purple";s:7:"#800080";s:7:"fuchsia";s:7:"#FF00FF";s:5:"white";s:7:"#FFFFFF";s:4:"lime";s:7:"#00FF00";s:5:"green";s:7:"#008000";s:4:"navy";s:7:"#000080";s:4:"blue";s:7:"#0000FF";s:4:"aqua";s:7:"#00FFFF";s:4:"teal";s:7:"#008080";s:5:"black";s:7:"#000000";s:6:"silver";s:7:"#C0C0C0";s:4:"gray";s:7:"#808080";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:17:"HTML.MaxImgLength";i:1200;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:6:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;}s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:20:"URI.SafeIframeRegexp";N;}s:9:"*parent";N;s:8:"*cache";N;}s:4:"info";a:132:{s:19:"Attr.AllowedClasses";i:-8;s:24:"Attr.AllowedFrameTargets";i:8;s:15:"Attr.AllowedRel";i:8;s:15:"Attr.AllowedRev";i:8;s:18:"Attr.ClassUseCDATA";i:-7;s:20:"Attr.DefaultImageAlt";i:-1;s:24:"Attr.DefaultInvalidImage";i:1;s:27:"Attr.DefaultInvalidImageAlt";i:1;s:19:"Attr.DefaultTextDir";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:2:{s:3:"ltr";b:1;s:3:"rtl";b:1;}}s:13:"Attr.EnableID";i:7;s:17:"HTML.EnableAttrID";O:8:"stdClass":2:{s:3:"key";s:13:"Attr.EnableID";s:7:"isAlias";b:1;}s:21:"Attr.ForbiddenClasses";i:8;s:16:"Attr.IDBlacklist";i:9;s:22:"Attr.IDBlacklistRegexp";i:-1;s:13:"Attr.IDPrefix";i:1;s:18:"Attr.IDPrefixLocal";i:1;s:24:"AutoFormat.AutoParagraph";i:7;s:17:"AutoFormat.Custom";i:9;s:25:"AutoFormat.DisplayLinkURI";i:7;s:18:"AutoFormat.Linkify";i:7;s:33:"AutoFormat.PurifierLinkify.DocURL";i:1;s:37:"AutoFormatParam.PurifierLinkifyDocURL";O:8:"stdClass":2:{s:3:"key";s:33:"AutoFormat.PurifierLinkify.DocURL";s:7:"isAlias";b:1;}s:26:"AutoFormat.PurifierLinkify";i:7;s:32:"AutoFormat.RemoveEmpty.Predicate";i:10;s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";i:8;s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";i:7;s:22:"AutoFormat.RemoveEmpty";i:7;s:39:"AutoFormat.RemoveSpansWithoutAttributes";i:7;s:18:"CSS.AllowImportant";i:7;s:15:"CSS.AllowTricky";i:7;s:16:"CSS.AllowedFonts";i:-8;s:21:"CSS.AllowedProperties";i:-8;s:17:"CSS.DefinitionRev";i:5;s:23:"CSS.ForbiddenProperties";i:8;s:16:"CSS.MaxImgLength";i:-1;s:15:"CSS.Proprietary";i:7;s:11:"CSS.Trusted";i:7;s:20:"Cache.DefinitionImpl";i:-1;s:20:"Core.DefinitionCache";O:8:"stdClass":2:{s:3:"key";s:20:"Cache.DefinitionImpl";s:7:"isAlias";b:1;}s:20:"Cache.SerializerPath";i:-1;s:27:"Cache.SerializerPermissions";i:5;s:22:"Core.AggressivelyFixLt";i:7;s:28:"Core.AllowHostnameUnderscore";i:7;s:18:"Core.CollectErrors";i:7;s:18:"Core.ColorKeywords";i:10;s:30:"Core.ConvertDocumentToFragment";i:7;s:24:"Core.AcceptFullDocuments";O:8:"stdClass":2:{s:3:"key";s:30:"Core.ConvertDocumentToFragment";s:7:"isAlias";b:1;}s:36:"Core.DirectLexLineNumberSyncInterval";i:5;s:20:"Core.DisableExcludes";i:7;s:15:"Core.EnableIDNA";i:7;s:13:"Core.Encoding";i:2;s:26:"Core.EscapeInvalidChildren";i:7;s:22:"Core.EscapeInvalidTags";i:7;s:29:"Core.EscapeNonASCIICharacters";i:7;s:19:"Core.HiddenElements";i:8;s:13:"Core.Language";i:1;s:14:"Core.LexerImpl";i:-11;s:24:"Core.MaintainLineNumbers";i:-7;s:22:"Core.NormalizeNewlines";i:7;s:21:"Core.RemoveInvalidImg";i:7;s:33:"Core.RemoveProcessingInstructions";i:7;s:25:"Core.RemoveScriptContents";i:-7;s:13:"Filter.Custom";i:9;s:34:"Filter.ExtractStyleBlocks.Escaping";i:7;s:33:"Filter.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:38:"FilterParam.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:31:"Filter.ExtractStyleBlocks.Scope";i:-1;s:30:"Filter.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:35:"FilterParam.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:34:"Filter.ExtractStyleBlocks.TidyImpl";i:-11;s:38:"FilterParam.ExtractStyleBlocksTidyImpl";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.TidyImpl";s:7:"isAlias";b:1;}s:25:"Filter.ExtractStyleBlocks";i:7;s:14:"Filter.YouTube";i:7;s:12:"HTML.Allowed";i:-4;s:22:"HTML.AllowedAttributes";i:-8;s:20:"HTML.AllowedComments";i:8;s:26:"HTML.AllowedCommentsRegexp";i:-1;s:20:"HTML.AllowedElements";i:-8;s:19:"HTML.AllowedModules";i:-8;s:23:"HTML.Attr.Name.UseCDATA";i:7;s:17:"HTML.BlockWrapper";i:1;s:16:"HTML.CoreModules";i:8;s:18:"HTML.CustomDoctype";i:-1;s:17:"HTML.DefinitionID";i:-1;s:18:"HTML.DefinitionRev";i:5;s:12:"HTML.Doctype";O:8:"stdClass":3:{s:4:"type";i:1;s:10:"allow_null";b:1;s:7:"allowed";a:5:{s:22:"HTML 4.01 Transitional";b:1;s:16:"HTML 4.01 Strict";b:1;s:22:"XHTML 1.0 Transitional";b:1;s:16:"XHTML 1.0 Strict";b:1;s:9:"XHTML 1.1";b:1;}}s:25:"HTML.FlashAllowFullScreen";i:7;s:24:"HTML.ForbiddenAttributes";i:8;s:22:"HTML.ForbiddenElements";i:8;s:17:"HTML.MaxImgLength";i:-5;s:13:"HTML.Nofollow";i:7;s:11:"HTML.Parent";i:1;s:16:"HTML.Proprietary";i:7;s:14:"HTML.SafeEmbed";i:7;s:15:"HTML.SafeIframe";i:7;s:15:"HTML.SafeObject";i:7;s:18:"HTML.SafeScripting";i:8;s:11:"HTML.Strict";i:7;s:16:"HTML.TargetBlank";i:7;s:12:"HTML.TidyAdd";i:8;s:14:"HTML.TidyLevel";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:4:{s:4:"none";b:1;s:5:"light";b:1;s:6:"medium";b:1;s:5:"heavy";b:1;}}s:15:"HTML.TidyRemove";i:8;s:12:"HTML.Trusted";i:7;s:10:"HTML.XHTML";i:7;s:10:"Core.XHTML";O:8:"stdClass":2:{s:3:"key";s:10:"HTML.XHTML";s:7:"isAlias";b:1;}s:28:"Output.CommentScriptContents";i:7;s:26:"Core.CommentScriptContents";O:8:"stdClass":2:{s:3:"key";s:28:"Output.CommentScriptContents";s:7:"isAlias";b:1;}s:19:"Output.FixInnerHTML";i:7;s:18:"Output.FlashCompat";i:7;s:14:"Output.Newline";i:-1;s:15:"Output.SortAttr";i:7;s:17:"Output.TidyFormat";i:7;s:15:"Core.TidyFormat";O:8:"stdClass":2:{s:3:"key";s:17:"Output.TidyFormat";s:7:"isAlias";b:1;}s:17:"Test.ForceNoIconv";i:7;s:18:"URI.AllowedSchemes";i:8;s:8:"URI.Base";i:-1;s:17:"URI.DefaultScheme";i:1;s:16:"URI.DefinitionID";i:-1;s:17:"URI.DefinitionRev";i:5;s:11:"URI.Disable";i:7;s:15:"Attr.DisableURI";O:8:"stdClass":2:{s:3:"key";s:11:"URI.Disable";s:7:"isAlias";b:1;}s:19:"URI.DisableExternal";i:7;s:28:"URI.DisableExternalResources";i:7;s:20:"URI.DisableResources";i:7;s:8:"URI.Host";i:-1;s:17:"URI.HostBlacklist";i:9;s:16:"URI.MakeAbsolute";i:7;s:9:"URI.Munge";i:-1;s:18:"URI.MungeResources";i:7;s:18:"URI.MungeSecretKey";i:-1;s:26:"URI.OverrideAllowedSchemes";i:7;s:20:"URI.SafeIframeRegexp";i:-1;}}
     1O:25:"HTMLPurifier_ConfigSchema":3:{s:8:"defaults";a:125:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:13:"Attr.ID.HTML5";N;s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:19:"CSS.AllowDuplicates";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";s:6:"1200px";s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:29:"Core.AggressivelyRemoveScript";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:17:{s:6:"maroon";s:7:"#800000";s:3:"red";s:7:"#FF0000";s:6:"orange";s:7:"#FFA500";s:6:"yellow";s:7:"#FFFF00";s:5:"olive";s:7:"#808000";s:6:"purple";s:7:"#800080";s:7:"fuchsia";s:7:"#FF00FF";s:5:"white";s:7:"#FFFFFF";s:4:"lime";s:7:"#00FF00";s:5:"green";s:7:"#008000";s:4:"navy";s:7:"#000080";s:4:"blue";s:7:"#0000FF";s:4:"aqua";s:7:"#00FFFF";s:4:"teal";s:7:"#008080";s:5:"black";s:7:"#000000";s:6:"silver";s:7:"#C0C0C0";s:4:"gray";s:7:"#808080";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:24:"Core.LegacyEntityDecoder";b:0;s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:17:"HTML.MaxImgLength";i:1200;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:19:"HTML.TargetNoopener";b:1;s:21:"HTML.TargetNoreferrer";b:1;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:7:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;s:3:"tel";b:1;}s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:20:"URI.SafeIframeRegexp";N;}s:12:"defaultPlist";O:25:"HTMLPurifier_PropertyList":3:{s:7:"*data";a:125:{s:19:"Attr.AllowedClasses";N;s:24:"Attr.AllowedFrameTargets";a:0:{}s:15:"Attr.AllowedRel";a:0:{}s:15:"Attr.AllowedRev";a:0:{}s:18:"Attr.ClassUseCDATA";N;s:20:"Attr.DefaultImageAlt";N;s:24:"Attr.DefaultInvalidImage";s:0:"";s:27:"Attr.DefaultInvalidImageAlt";s:13:"Invalid image";s:19:"Attr.DefaultTextDir";s:3:"ltr";s:13:"Attr.EnableID";b:0;s:21:"Attr.ForbiddenClasses";a:0:{}s:13:"Attr.ID.HTML5";N;s:16:"Attr.IDBlacklist";a:0:{}s:22:"Attr.IDBlacklistRegexp";N;s:13:"Attr.IDPrefix";s:0:"";s:18:"Attr.IDPrefixLocal";s:0:"";s:24:"AutoFormat.AutoParagraph";b:0;s:17:"AutoFormat.Custom";a:0:{}s:25:"AutoFormat.DisplayLinkURI";b:0;s:18:"AutoFormat.Linkify";b:0;s:33:"AutoFormat.PurifierLinkify.DocURL";s:3:"#%s";s:26:"AutoFormat.PurifierLinkify";b:0;s:32:"AutoFormat.RemoveEmpty.Predicate";a:4:{s:8:"colgroup";a:0:{}s:2:"th";a:0:{}s:2:"td";a:0:{}s:6:"iframe";a:1:{i:0;s:3:"src";}}s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";a:2:{s:2:"td";b:1;s:2:"th";b:1;}s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";b:0;s:22:"AutoFormat.RemoveEmpty";b:0;s:39:"AutoFormat.RemoveSpansWithoutAttributes";b:0;s:19:"CSS.AllowDuplicates";b:0;s:18:"CSS.AllowImportant";b:0;s:15:"CSS.AllowTricky";b:0;s:16:"CSS.AllowedFonts";N;s:21:"CSS.AllowedProperties";N;s:17:"CSS.DefinitionRev";i:1;s:23:"CSS.ForbiddenProperties";a:0:{}s:16:"CSS.MaxImgLength";s:6:"1200px";s:15:"CSS.Proprietary";b:0;s:11:"CSS.Trusted";b:0;s:20:"Cache.DefinitionImpl";s:10:"Serializer";s:20:"Cache.SerializerPath";N;s:27:"Cache.SerializerPermissions";i:493;s:22:"Core.AggressivelyFixLt";b:1;s:29:"Core.AggressivelyRemoveScript";b:1;s:28:"Core.AllowHostnameUnderscore";b:0;s:18:"Core.CollectErrors";b:0;s:18:"Core.ColorKeywords";a:17:{s:6:"maroon";s:7:"#800000";s:3:"red";s:7:"#FF0000";s:6:"orange";s:7:"#FFA500";s:6:"yellow";s:7:"#FFFF00";s:5:"olive";s:7:"#808000";s:6:"purple";s:7:"#800080";s:7:"fuchsia";s:7:"#FF00FF";s:5:"white";s:7:"#FFFFFF";s:4:"lime";s:7:"#00FF00";s:5:"green";s:7:"#008000";s:4:"navy";s:7:"#000080";s:4:"blue";s:7:"#0000FF";s:4:"aqua";s:7:"#00FFFF";s:4:"teal";s:7:"#008080";s:5:"black";s:7:"#000000";s:6:"silver";s:7:"#C0C0C0";s:4:"gray";s:7:"#808080";}s:30:"Core.ConvertDocumentToFragment";b:1;s:36:"Core.DirectLexLineNumberSyncInterval";i:0;s:20:"Core.DisableExcludes";b:0;s:15:"Core.EnableIDNA";b:0;s:13:"Core.Encoding";s:5:"utf-8";s:26:"Core.EscapeInvalidChildren";b:0;s:22:"Core.EscapeInvalidTags";b:0;s:29:"Core.EscapeNonASCIICharacters";b:0;s:19:"Core.HiddenElements";a:2:{s:6:"script";b:1;s:5:"style";b:1;}s:13:"Core.Language";s:2:"en";s:24:"Core.LegacyEntityDecoder";b:0;s:14:"Core.LexerImpl";N;s:24:"Core.MaintainLineNumbers";N;s:22:"Core.NormalizeNewlines";b:1;s:21:"Core.RemoveInvalidImg";b:1;s:33:"Core.RemoveProcessingInstructions";b:0;s:25:"Core.RemoveScriptContents";N;s:13:"Filter.Custom";a:0:{}s:34:"Filter.ExtractStyleBlocks.Escaping";b:1;s:31:"Filter.ExtractStyleBlocks.Scope";N;s:34:"Filter.ExtractStyleBlocks.TidyImpl";N;s:25:"Filter.ExtractStyleBlocks";b:0;s:14:"Filter.YouTube";b:0;s:12:"HTML.Allowed";N;s:22:"HTML.AllowedAttributes";N;s:20:"HTML.AllowedComments";a:0:{}s:26:"HTML.AllowedCommentsRegexp";N;s:20:"HTML.AllowedElements";N;s:19:"HTML.AllowedModules";N;s:23:"HTML.Attr.Name.UseCDATA";b:0;s:17:"HTML.BlockWrapper";s:1:"p";s:16:"HTML.CoreModules";a:7:{s:9:"Structure";b:1;s:4:"Text";b:1;s:9:"Hypertext";b:1;s:4:"List";b:1;s:22:"NonXMLCommonAttributes";b:1;s:19:"XMLCommonAttributes";b:1;s:16:"CommonAttributes";b:1;}s:18:"HTML.CustomDoctype";N;s:17:"HTML.DefinitionID";N;s:18:"HTML.DefinitionRev";i:1;s:12:"HTML.Doctype";N;s:25:"HTML.FlashAllowFullScreen";b:0;s:24:"HTML.ForbiddenAttributes";a:0:{}s:22:"HTML.ForbiddenElements";a:0:{}s:17:"HTML.MaxImgLength";i:1200;s:13:"HTML.Nofollow";b:0;s:11:"HTML.Parent";s:3:"div";s:16:"HTML.Proprietary";b:0;s:14:"HTML.SafeEmbed";b:0;s:15:"HTML.SafeIframe";b:0;s:15:"HTML.SafeObject";b:0;s:18:"HTML.SafeScripting";a:0:{}s:11:"HTML.Strict";b:0;s:16:"HTML.TargetBlank";b:0;s:19:"HTML.TargetNoopener";b:1;s:21:"HTML.TargetNoreferrer";b:1;s:12:"HTML.TidyAdd";a:0:{}s:14:"HTML.TidyLevel";s:6:"medium";s:15:"HTML.TidyRemove";a:0:{}s:12:"HTML.Trusted";b:0;s:10:"HTML.XHTML";b:1;s:28:"Output.CommentScriptContents";b:1;s:19:"Output.FixInnerHTML";b:1;s:18:"Output.FlashCompat";b:0;s:14:"Output.Newline";N;s:15:"Output.SortAttr";b:0;s:17:"Output.TidyFormat";b:0;s:17:"Test.ForceNoIconv";b:0;s:18:"URI.AllowedSchemes";a:7:{s:4:"http";b:1;s:5:"https";b:1;s:6:"mailto";b:1;s:3:"ftp";b:1;s:4:"nntp";b:1;s:4:"news";b:1;s:3:"tel";b:1;}s:8:"URI.Base";N;s:17:"URI.DefaultScheme";s:4:"http";s:16:"URI.DefinitionID";N;s:17:"URI.DefinitionRev";i:1;s:11:"URI.Disable";b:0;s:19:"URI.DisableExternal";b:0;s:28:"URI.DisableExternalResources";b:0;s:20:"URI.DisableResources";b:0;s:8:"URI.Host";N;s:17:"URI.HostBlacklist";a:0:{}s:16:"URI.MakeAbsolute";b:0;s:9:"URI.Munge";N;s:18:"URI.MungeResources";b:0;s:18:"URI.MungeSecretKey";N;s:26:"URI.OverrideAllowedSchemes";b:1;s:20:"URI.SafeIframeRegexp";N;}s:9:"*parent";N;s:8:"*cache";N;}s:4:"info";a:138:{s:19:"Attr.AllowedClasses";i:-8;s:24:"Attr.AllowedFrameTargets";i:8;s:15:"Attr.AllowedRel";i:8;s:15:"Attr.AllowedRev";i:8;s:18:"Attr.ClassUseCDATA";i:-7;s:20:"Attr.DefaultImageAlt";i:-1;s:24:"Attr.DefaultInvalidImage";i:1;s:27:"Attr.DefaultInvalidImageAlt";i:1;s:19:"Attr.DefaultTextDir";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:2:{s:3:"ltr";b:1;s:3:"rtl";b:1;}}s:13:"Attr.EnableID";i:7;s:17:"HTML.EnableAttrID";O:8:"stdClass":2:{s:3:"key";s:13:"Attr.EnableID";s:7:"isAlias";b:1;}s:21:"Attr.ForbiddenClasses";i:8;s:13:"Attr.ID.HTML5";i:-7;s:16:"Attr.IDBlacklist";i:9;s:22:"Attr.IDBlacklistRegexp";i:-1;s:13:"Attr.IDPrefix";i:1;s:18:"Attr.IDPrefixLocal";i:1;s:24:"AutoFormat.AutoParagraph";i:7;s:17:"AutoFormat.Custom";i:9;s:25:"AutoFormat.DisplayLinkURI";i:7;s:18:"AutoFormat.Linkify";i:7;s:33:"AutoFormat.PurifierLinkify.DocURL";i:1;s:37:"AutoFormatParam.PurifierLinkifyDocURL";O:8:"stdClass":2:{s:3:"key";s:33:"AutoFormat.PurifierLinkify.DocURL";s:7:"isAlias";b:1;}s:26:"AutoFormat.PurifierLinkify";i:7;s:32:"AutoFormat.RemoveEmpty.Predicate";i:10;s:44:"AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions";i:8;s:33:"AutoFormat.RemoveEmpty.RemoveNbsp";i:7;s:22:"AutoFormat.RemoveEmpty";i:7;s:39:"AutoFormat.RemoveSpansWithoutAttributes";i:7;s:19:"CSS.AllowDuplicates";i:7;s:18:"CSS.AllowImportant";i:7;s:15:"CSS.AllowTricky";i:7;s:16:"CSS.AllowedFonts";i:-8;s:21:"CSS.AllowedProperties";i:-8;s:17:"CSS.DefinitionRev";i:5;s:23:"CSS.ForbiddenProperties";i:8;s:16:"CSS.MaxImgLength";i:-1;s:15:"CSS.Proprietary";i:7;s:11:"CSS.Trusted";i:7;s:20:"Cache.DefinitionImpl";i:-1;s:20:"Core.DefinitionCache";O:8:"stdClass":2:{s:3:"key";s:20:"Cache.DefinitionImpl";s:7:"isAlias";b:1;}s:20:"Cache.SerializerPath";i:-1;s:27:"Cache.SerializerPermissions";i:-5;s:22:"Core.AggressivelyFixLt";i:7;s:29:"Core.AggressivelyRemoveScript";i:7;s:28:"Core.AllowHostnameUnderscore";i:7;s:18:"Core.CollectErrors";i:7;s:18:"Core.ColorKeywords";i:10;s:30:"Core.ConvertDocumentToFragment";i:7;s:24:"Core.AcceptFullDocuments";O:8:"stdClass":2:{s:3:"key";s:30:"Core.ConvertDocumentToFragment";s:7:"isAlias";b:1;}s:36:"Core.DirectLexLineNumberSyncInterval";i:5;s:20:"Core.DisableExcludes";i:7;s:15:"Core.EnableIDNA";i:7;s:13:"Core.Encoding";i:2;s:26:"Core.EscapeInvalidChildren";i:7;s:22:"Core.EscapeInvalidTags";i:7;s:29:"Core.EscapeNonASCIICharacters";i:7;s:19:"Core.HiddenElements";i:8;s:13:"Core.Language";i:1;s:24:"Core.LegacyEntityDecoder";i:7;s:14:"Core.LexerImpl";i:-11;s:24:"Core.MaintainLineNumbers";i:-7;s:22:"Core.NormalizeNewlines";i:7;s:21:"Core.RemoveInvalidImg";i:7;s:33:"Core.RemoveProcessingInstructions";i:7;s:25:"Core.RemoveScriptContents";i:-7;s:13:"Filter.Custom";i:9;s:34:"Filter.ExtractStyleBlocks.Escaping";i:7;s:33:"Filter.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:38:"FilterParam.ExtractStyleBlocksEscaping";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.Escaping";s:7:"isAlias";b:1;}s:31:"Filter.ExtractStyleBlocks.Scope";i:-1;s:30:"Filter.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:35:"FilterParam.ExtractStyleBlocksScope";O:8:"stdClass":2:{s:3:"key";s:31:"Filter.ExtractStyleBlocks.Scope";s:7:"isAlias";b:1;}s:34:"Filter.ExtractStyleBlocks.TidyImpl";i:-11;s:38:"FilterParam.ExtractStyleBlocksTidyImpl";O:8:"stdClass":2:{s:3:"key";s:34:"Filter.ExtractStyleBlocks.TidyImpl";s:7:"isAlias";b:1;}s:25:"Filter.ExtractStyleBlocks";i:7;s:14:"Filter.YouTube";i:7;s:12:"HTML.Allowed";i:-4;s:22:"HTML.AllowedAttributes";i:-8;s:20:"HTML.AllowedComments";i:8;s:26:"HTML.AllowedCommentsRegexp";i:-1;s:20:"HTML.AllowedElements";i:-8;s:19:"HTML.AllowedModules";i:-8;s:23:"HTML.Attr.Name.UseCDATA";i:7;s:17:"HTML.BlockWrapper";i:1;s:16:"HTML.CoreModules";i:8;s:18:"HTML.CustomDoctype";i:-1;s:17:"HTML.DefinitionID";i:-1;s:18:"HTML.DefinitionRev";i:5;s:12:"HTML.Doctype";O:8:"stdClass":3:{s:4:"type";i:1;s:10:"allow_null";b:1;s:7:"allowed";a:5:{s:22:"HTML 4.01 Transitional";b:1;s:16:"HTML 4.01 Strict";b:1;s:22:"XHTML 1.0 Transitional";b:1;s:16:"XHTML 1.0 Strict";b:1;s:9:"XHTML 1.1";b:1;}}s:25:"HTML.FlashAllowFullScreen";i:7;s:24:"HTML.ForbiddenAttributes";i:8;s:22:"HTML.ForbiddenElements";i:8;s:17:"HTML.MaxImgLength";i:-5;s:13:"HTML.Nofollow";i:7;s:11:"HTML.Parent";i:1;s:16:"HTML.Proprietary";i:7;s:14:"HTML.SafeEmbed";i:7;s:15:"HTML.SafeIframe";i:7;s:15:"HTML.SafeObject";i:7;s:18:"HTML.SafeScripting";i:8;s:11:"HTML.Strict";i:7;s:16:"HTML.TargetBlank";i:7;s:19:"HTML.TargetNoopener";i:7;s:21:"HTML.TargetNoreferrer";i:7;s:12:"HTML.TidyAdd";i:8;s:14:"HTML.TidyLevel";O:8:"stdClass":2:{s:4:"type";i:1;s:7:"allowed";a:4:{s:4:"none";b:1;s:5:"light";b:1;s:6:"medium";b:1;s:5:"heavy";b:1;}}s:15:"HTML.TidyRemove";i:8;s:12:"HTML.Trusted";i:7;s:10:"HTML.XHTML";i:7;s:10:"Core.XHTML";O:8:"stdClass":2:{s:3:"key";s:10:"HTML.XHTML";s:7:"isAlias";b:1;}s:28:"Output.CommentScriptContents";i:7;s:26:"Core.CommentScriptContents";O:8:"stdClass":2:{s:3:"key";s:28:"Output.CommentScriptContents";s:7:"isAlias";b:1;}s:19:"Output.FixInnerHTML";i:7;s:18:"Output.FlashCompat";i:7;s:14:"Output.Newline";i:-1;s:15:"Output.SortAttr";i:7;s:17:"Output.TidyFormat";i:7;s:15:"Core.TidyFormat";O:8:"stdClass":2:{s:3:"key";s:17:"Output.TidyFormat";s:7:"isAlias";b:1;}s:17:"Test.ForceNoIconv";i:7;s:18:"URI.AllowedSchemes";i:8;s:8:"URI.Base";i:-1;s:17:"URI.DefaultScheme";i:-1;s:16:"URI.DefinitionID";i:-1;s:17:"URI.DefinitionRev";i:5;s:11:"URI.Disable";i:7;s:15:"Attr.DisableURI";O:8:"stdClass":2:{s:3:"key";s:11:"URI.Disable";s:7:"isAlias";b:1;}s:19:"URI.DisableExternal";i:7;s:28:"URI.DisableExternalResources";i:7;s:20:"URI.DisableResources";i:7;s:8:"URI.Host";i:-1;s:17:"URI.HostBlacklist";i:9;s:16:"URI.MakeAbsolute";i:7;s:9:"URI.Munge";i:-1;s:18:"URI.MungeResources";i:7;s:18:"URI.MungeSecretKey";i:-1;s:26:"URI.OverrideAllowedSchemes";i:7;s:20:"URI.SafeIframeRegexp";i:-1;}}
  • _plugins_/htmlpurifier/lib/standalone/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt

    r43383 r103194  
    99  'nntp' => true,
    1010  'news' => true,
     11  'tel' => true,
    1112)
    1213--DESCRIPTION--
  • _plugins_/htmlpurifier/lib/standalone/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt

    r43383 r103194  
    11URI.DefaultScheme
    2 TYPE: string
     2TYPE: string/null
    33DEFAULT: 'http'
    44--DESCRIPTION--
     
    88    select the proper object validator when no scheme information is present.
    99</p>
     10
     11<p>
     12    Starting with HTML Purifier 4.9.0, the default scheme can be null, in
     13    which case we reject all URIs which do not have explicit schemes.
     14</p>
    1015--# vim: et sw=4 sts=4
  • _plugins_/htmlpurifier/lib/standalone/HTMLPurifier/Filter/ExtractStyleBlocks.php

    r94428 r103194  
    9696            $this->_tidy = $tidy;
    9797        }
    98         $html = preg_replace_callback('#<style(?:\s.*)?>(.+)</style>#isU', array($this, 'styleCallback'), $html);
     98        // NB: this must be NON-greedy because if we have
     99        // <style>foo</style>  <style>bar</style>
     100        // we must not grab foo</style>  <style>bar
     101        $html = preg_replace_callback('#<style(?:\s.*)?>(.*)<\/style>#isU', array($this, 'styleCallback'), $html);
    99102        $style_blocks = $this->_styleMatches;
    100103        $this->_styleMatches = array(); // reset
  • _plugins_/htmlpurifier/lib/standalone/HTMLPurifier/Lexer/PH5P.php

    r94428 r103194  
    2222    {
    2323        $new_html = $this->normalize($html, $config, $context);
    24         $new_html = $this->wrapHTML($new_html, $config, $context);
     24        $new_html = $this->wrapHTML($new_html, $config, $context, false /* no div */);
    2525        try {
    2626            $parser = new HTML5($new_html);
     
    3535        $this->tokenizeDOM(
    3636            $doc->getElementsByTagName('html')->item(0)-> // <html>
    37                 getElementsByTagName('body')->item(0) //   <body>
     37                  getElementsByTagName('body')->item(0) //   <body>
    3838            ,
    39             $tokens
     39            $tokens, $config
    4040        );
    4141        return $tokens;
     
    15161516                // consumed characters case-sensitively matching one of the
    15171517                // identifiers in the first column of the entities table.
     1518
    15181519                $e_name = $this->characters('0-9A-Za-z;', $this->char + 1);
    15191520                $len = strlen($e_name);
     
    15481549        // Return a character token for the character corresponding to the
    15491550        // entity name (as given by the second column of the entities table).
    1550         return html_entity_decode('&' . $entity . ';', ENT_QUOTES, 'UTF-8');
     1551        return html_entity_decode('&' . rtrim($entity, ';') . ';', ENT_QUOTES, 'UTF-8');
    15511552    }
    15521553
  • _plugins_/htmlpurifier/lib/standalone/HTMLPurifier/Printer/ConfigForm.php

    r94428 r103194  
    328328                    $nvalue = '';
    329329                    foreach ($value as $i => $v) {
     330                        if (is_array($v)) {
     331                            // HACK
     332                            $v = implode(";", $v);
     333                        }
    330334                        $nvalue .= "$i:$v" . PHP_EOL;
    331335                    }
  • _plugins_/htmlpurifier/plugin.xml

    r96561 r103194  
    33        <slogan>S&#233;curiser l'affichage de certains textes</slogan>
    44        <auteur>[Edward Z. Yang->http://htmlpurifier.org/], Mise en plugin SPIP : RealET et Fil</auteur>
    5         <version>4.7.0</version>
     5        <version>4.9.1</version>
    66        <etat>stable</etat>
    77        <description>
Note: See TracChangeset for help on using the changeset viewer.