File indexing completed on 2024-12-22 05:36:19

0001 <?php
0002 
0003 /**
0004  * Custom validation class, accepts DTD child definitions
0005  *
0006  * @warning Currently this class is an all or nothing proposition, that is,
0007  *          it will only give a bool return value.
0008  */
0009 class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef
0010 {
0011     /**
0012      * @type string
0013      */
0014     public $type = 'custom';
0015 
0016     /**
0017      * @type bool
0018      */
0019     public $allow_empty = false;
0020 
0021     /**
0022      * Allowed child pattern as defined by the DTD.
0023      * @type string
0024      */
0025     public $dtd_regex;
0026 
0027     /**
0028      * PCRE regex derived from $dtd_regex.
0029      * @type string
0030      */
0031     private $_pcre_regex;
0032 
0033     /**
0034      * @param $dtd_regex Allowed child pattern from the DTD
0035      */
0036     public function __construct($dtd_regex)
0037     {
0038         $this->dtd_regex = $dtd_regex;
0039         $this->_compileRegex();
0040     }
0041 
0042     /**
0043      * Compiles the PCRE regex from a DTD regex ($dtd_regex to $_pcre_regex)
0044      */
0045     protected function _compileRegex()
0046     {
0047         $raw = str_replace(' ', '', $this->dtd_regex);
0048         if ($raw{0} != '(') {
0049             $raw = "($raw)";
0050         }
0051         $el = '[#a-zA-Z0-9_.-]+';
0052         $reg = $raw;
0053 
0054         // COMPLICATED! AND MIGHT BE BUGGY! I HAVE NO CLUE WHAT I'M
0055         // DOING! Seriously: if there's problems, please report them.
0056 
0057         // collect all elements into the $elements array
0058         preg_match_all("/$el/", $reg, $matches);
0059         foreach ($matches[0] as $match) {
0060             $this->elements[$match] = true;
0061         }
0062 
0063         // setup all elements as parentheticals with leading commas
0064         $reg = preg_replace("/$el/", '(,\\0)', $reg);
0065 
0066         // remove commas when they were not solicited
0067         $reg = preg_replace("/([^,(|]\(+),/", '\\1', $reg);
0068 
0069         // remove all non-paranthetical commas: they are handled by first regex
0070         $reg = preg_replace("/,\(/", '(', $reg);
0071 
0072         $this->_pcre_regex = $reg;
0073     }
0074 
0075     /**
0076      * @param HTMLPurifier_Node[] $children
0077      * @param HTMLPurifier_Config $config
0078      * @param HTMLPurifier_Context $context
0079      * @return bool
0080      */
0081     public function validateChildren($children, $config, $context)
0082     {
0083         $list_of_children = '';
0084         $nesting = 0; // depth into the nest
0085         foreach ($children as $node) {
0086             if (!empty($node->is_whitespace)) {
0087                 continue;
0088             }
0089             $list_of_children .= $node->name . ',';
0090         }
0091         // add leading comma to deal with stray comma declarations
0092         $list_of_children = ',' . rtrim($list_of_children, ',');
0093         $okay =
0094             preg_match(
0095                 '/^,?' . $this->_pcre_regex . '$/',
0096                 $list_of_children
0097             );
0098         return (bool)$okay;
0099     }
0100 }
0101 
0102 // vim: et sw=4 sts=4