| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | /** |
|---|
| 4 | * Custom validation class, accepts DTD child definitions |
|---|
| 5 | * |
|---|
| 6 | * @warning Currently this class is an all or nothing proposition, that is, |
|---|
| 7 | * it will only give a bool return value. |
|---|
| 8 | * @note This class is currently not used by any code, although it is unit |
|---|
| 9 | * tested. |
|---|
| 10 | */ |
|---|
| 11 | class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef |
|---|
| 12 | { |
|---|
| 13 | public $type = 'custom'; |
|---|
| 14 | public $allow_empty = false; |
|---|
| 15 | /** |
|---|
| 16 | * Allowed child pattern as defined by the DTD |
|---|
| 17 | */ |
|---|
| 18 | public $dtd_regex; |
|---|
| 19 | /** |
|---|
| 20 | * PCRE regex derived from $dtd_regex |
|---|
| 21 | * @private |
|---|
| 22 | */ |
|---|
| 23 | private $_pcre_regex; |
|---|
| 24 | /** |
|---|
| 25 | * @param $dtd_regex Allowed child pattern from the DTD |
|---|
| 26 | */ |
|---|
| 27 | public function __construct($dtd_regex) { |
|---|
| 28 | $this->dtd_regex = $dtd_regex; |
|---|
| 29 | $this->_compileRegex(); |
|---|
| 30 | } |
|---|
| 31 | /** |
|---|
| 32 | * Compiles the PCRE regex from a DTD regex ($dtd_regex to $_pcre_regex) |
|---|
| 33 | */ |
|---|
| 34 | protected function _compileRegex() { |
|---|
| 35 | $raw = str_replace(' ', '', $this->dtd_regex); |
|---|
| 36 | if ($raw{0} != '(') { |
|---|
| 37 | $raw = "($raw)"; |
|---|
| 38 | } |
|---|
| 39 | $el = '[#a-zA-Z0-9_.-]+'; |
|---|
| 40 | $reg = $raw; |
|---|
| 41 | |
|---|
| 42 | // COMPLICATED! AND MIGHT BE BUGGY! I HAVE NO CLUE WHAT I'M |
|---|
| 43 | // DOING! Seriously: if there's problems, please report them. |
|---|
| 44 | |
|---|
| 45 | // collect all elements into the $elements array |
|---|
| 46 | preg_match_all("/$el/", $reg, $matches); |
|---|
| 47 | foreach ($matches[0] as $match) { |
|---|
| 48 | $this->elements[$match] = true; |
|---|
| 49 | } |
|---|
| 50 | |
|---|
| 51 | // setup all elements as parentheticals with leading commas |
|---|
| 52 | $reg = preg_replace("/$el/", '(,\\0)', $reg); |
|---|
| 53 | |
|---|
| 54 | // remove commas when they were not solicited |
|---|
| 55 | $reg = preg_replace("/([^,(|]\(+),/", '\\1', $reg); |
|---|
| 56 | |
|---|
| 57 | // remove all non-paranthetical commas: they are handled by first regex |
|---|
| 58 | $reg = preg_replace("/,\(/", '(', $reg); |
|---|
| 59 | |
|---|
| 60 | $this->_pcre_regex = $reg; |
|---|
| 61 | } |
|---|
| 62 | public function validateChildren($tokens_of_children, $config, $context) { |
|---|
| 63 | $list_of_children = ''; |
|---|
| 64 | $nesting = 0; // depth into the nest |
|---|
| 65 | foreach ($tokens_of_children as $token) { |
|---|
| 66 | if (!empty($token->is_whitespace)) continue; |
|---|
| 67 | |
|---|
| 68 | $is_child = ($nesting == 0); // direct |
|---|
| 69 | |
|---|
| 70 | if ($token instanceof HTMLPurifier_Token_Start) { |
|---|
| 71 | $nesting++; |
|---|
| 72 | } elseif ($token instanceof HTMLPurifier_Token_End) { |
|---|
| 73 | $nesting--; |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | if ($is_child) { |
|---|
| 77 | $list_of_children .= $token->name . ','; |
|---|
| 78 | } |
|---|
| 79 | } |
|---|
| 80 | // add leading comma to deal with stray comma declarations |
|---|
| 81 | $list_of_children = ',' . rtrim($list_of_children, ','); |
|---|
| 82 | $okay = |
|---|
| 83 | preg_match( |
|---|
| 84 | '/^,?'.$this->_pcre_regex.'$/', |
|---|
| 85 | $list_of_children |
|---|
| 86 | ); |
|---|
| 87 | |
|---|
| 88 | return (bool) $okay; |
|---|
| 89 | } |
|---|
| 90 | } |
|---|
| 91 | |
|---|