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