]> git.mxchange.org Git - friendica.git/blob - library/HTMLPurifier/AttrValidator.php
more friend suggestions
[friendica.git] / library / HTMLPurifier / AttrValidator.php
1 <?php
2
3 /**
4  * Validates the attributes of a token. Doesn't manage required attributes
5  * very well. The only reason we factored this out was because RemoveForeignElements
6  * also needed it besides ValidateAttributes.
7  */
8 class HTMLPurifier_AttrValidator
9 {
10
11     /**
12      * Validates the attributes of a token, returning a modified token
13      * that has valid tokens
14      * @param $token Reference to token to validate. We require a reference
15      *     because the operation this class performs on the token are
16      *     not atomic, so the context CurrentToken to be updated
17      *     throughout
18      * @param $config Instance of HTMLPurifier_Config
19      * @param $context Instance of HTMLPurifier_Context
20      */
21     public function validateToken(&$token, &$config, $context) {
22
23         $definition = $config->getHTMLDefinition();
24         $e =& $context->get('ErrorCollector', true);
25
26         // initialize IDAccumulator if necessary
27         $ok =& $context->get('IDAccumulator', true);
28         if (!$ok) {
29             $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
30             $context->register('IDAccumulator', $id_accumulator);
31         }
32
33         // initialize CurrentToken if necessary
34         $current_token =& $context->get('CurrentToken', true);
35         if (!$current_token) $context->register('CurrentToken', $token);
36
37         if (
38             !$token instanceof HTMLPurifier_Token_Start &&
39             !$token instanceof HTMLPurifier_Token_Empty
40         ) return $token;
41
42         // create alias to global definition array, see also $defs
43         // DEFINITION CALL
44         $d_defs = $definition->info_global_attr;
45
46         // don't update token until the very end, to ensure an atomic update
47         $attr = $token->attr;
48
49         // do global transformations (pre)
50         // nothing currently utilizes this
51         foreach ($definition->info_attr_transform_pre as $transform) {
52             $attr = $transform->transform($o = $attr, $config, $context);
53             if ($e) {
54                 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
55             }
56         }
57
58         // do local transformations only applicable to this element (pre)
59         // ex. <p align="right"> to <p style="text-align:right;">
60         foreach ($definition->info[$token->name]->attr_transform_pre as $transform) {
61             $attr = $transform->transform($o = $attr, $config, $context);
62             if ($e) {
63                 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
64             }
65         }
66
67         // create alias to this element's attribute definition array, see
68         // also $d_defs (global attribute definition array)
69         // DEFINITION CALL
70         $defs = $definition->info[$token->name]->attr;
71
72         $attr_key = false;
73         $context->register('CurrentAttr', $attr_key);
74
75         // iterate through all the attribute keypairs
76         // Watch out for name collisions: $key has previously been used
77         foreach ($attr as $attr_key => $value) {
78
79             // call the definition
80             if ( isset($defs[$attr_key]) ) {
81                 // there is a local definition defined
82                 if ($defs[$attr_key] === false) {
83                     // We've explicitly been told not to allow this element.
84                     // This is usually when there's a global definition
85                     // that must be overridden.
86                     // Theoretically speaking, we could have a
87                     // AttrDef_DenyAll, but this is faster!
88                     $result = false;
89                 } else {
90                     // validate according to the element's definition
91                     $result = $defs[$attr_key]->validate(
92                                     $value, $config, $context
93                                );
94                 }
95             } elseif ( isset($d_defs[$attr_key]) ) {
96                 // there is a global definition defined, validate according
97                 // to the global definition
98                 $result = $d_defs[$attr_key]->validate(
99                                 $value, $config, $context
100                            );
101             } else {
102                 // system never heard of the attribute? DELETE!
103                 $result = false;
104             }
105
106             // put the results into effect
107             if ($result === false || $result === null) {
108                 // this is a generic error message that should replaced
109                 // with more specific ones when possible
110                 if ($e) $e->send(E_ERROR, 'AttrValidator: Attribute removed');
111
112                 // remove the attribute
113                 unset($attr[$attr_key]);
114             } elseif (is_string($result)) {
115                 // generally, if a substitution is happening, there
116                 // was some sort of implicit correction going on. We'll
117                 // delegate it to the attribute classes to say exactly what.
118
119                 // simple substitution
120                 $attr[$attr_key] = $result;
121             } else {
122                 // nothing happens
123             }
124
125             // we'd also want slightly more complicated substitution
126             // involving an array as the return value,
127             // although we're not sure how colliding attributes would
128             // resolve (certain ones would be completely overriden,
129             // others would prepend themselves).
130         }
131
132         $context->destroy('CurrentAttr');
133
134         // post transforms
135
136         // global (error reporting untested)
137         foreach ($definition->info_attr_transform_post as $transform) {
138             $attr = $transform->transform($o = $attr, $config, $context);
139             if ($e) {
140                 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
141             }
142         }
143
144         // local (error reporting untested)
145         foreach ($definition->info[$token->name]->attr_transform_post as $transform) {
146             $attr = $transform->transform($o = $attr, $config, $context);
147             if ($e) {
148                 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
149             }
150         }
151
152         $token->attr = $attr;
153
154         // destroy CurrentToken if we made it ourselves
155         if (!$current_token) $context->destroy('CurrentToken');
156
157     }
158
159
160 }
161
162 // vim: et sw=4 sts=4