Yaffs site version 1.1
[yaffs-website] / vendor / ezyang / htmlpurifier / 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, mutating it as necessary.
13      * that has valid tokens
14      * @param HTMLPurifier_Token $token Token to validate.
15      * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config
16      * @param HTMLPurifier_Context $context Instance of HTMLPurifier_Context
17      */
18     public function validateToken($token, $config, $context)
19     {
20         $definition = $config->getHTMLDefinition();
21         $e =& $context->get('ErrorCollector', true);
22
23         // initialize IDAccumulator if necessary
24         $ok =& $context->get('IDAccumulator', true);
25         if (!$ok) {
26             $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context);
27             $context->register('IDAccumulator', $id_accumulator);
28         }
29
30         // initialize CurrentToken if necessary
31         $current_token =& $context->get('CurrentToken', true);
32         if (!$current_token) {
33             $context->register('CurrentToken', $token);
34         }
35
36         if (!$token instanceof HTMLPurifier_Token_Start &&
37             !$token instanceof HTMLPurifier_Token_Empty
38         ) {
39             return;
40         }
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) {
55                     $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
56                 }
57             }
58         }
59
60         // do local transformations only applicable to this element (pre)
61         // ex. <p align="right"> to <p style="text-align:right;">
62         foreach ($definition->info[$token->name]->attr_transform_pre as $transform) {
63             $attr = $transform->transform($o = $attr, $config, $context);
64             if ($e) {
65                 if ($attr != $o) {
66                     $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
67                 }
68             }
69         }
70
71         // create alias to this element's attribute definition array, see
72         // also $d_defs (global attribute definition array)
73         // DEFINITION CALL
74         $defs = $definition->info[$token->name]->attr;
75
76         $attr_key = false;
77         $context->register('CurrentAttr', $attr_key);
78
79         // iterate through all the attribute keypairs
80         // Watch out for name collisions: $key has previously been used
81         foreach ($attr as $attr_key => $value) {
82
83             // call the definition
84             if (isset($defs[$attr_key])) {
85                 // there is a local definition defined
86                 if ($defs[$attr_key] === false) {
87                     // We've explicitly been told not to allow this element.
88                     // This is usually when there's a global definition
89                     // that must be overridden.
90                     // Theoretically speaking, we could have a
91                     // AttrDef_DenyAll, but this is faster!
92                     $result = false;
93                 } else {
94                     // validate according to the element's definition
95                     $result = $defs[$attr_key]->validate(
96                         $value,
97                         $config,
98                         $context
99                     );
100                 }
101             } elseif (isset($d_defs[$attr_key])) {
102                 // there is a global definition defined, validate according
103                 // to the global definition
104                 $result = $d_defs[$attr_key]->validate(
105                     $value,
106                     $config,
107                     $context
108                 );
109             } else {
110                 // system never heard of the attribute? DELETE!
111                 $result = false;
112             }
113
114             // put the results into effect
115             if ($result === false || $result === null) {
116                 // this is a generic error message that should replaced
117                 // with more specific ones when possible
118                 if ($e) {
119                     $e->send(E_ERROR, 'AttrValidator: Attribute removed');
120                 }
121
122                 // remove the attribute
123                 unset($attr[$attr_key]);
124             } elseif (is_string($result)) {
125                 // generally, if a substitution is happening, there
126                 // was some sort of implicit correction going on. We'll
127                 // delegate it to the attribute classes to say exactly what.
128
129                 // simple substitution
130                 $attr[$attr_key] = $result;
131             } else {
132                 // nothing happens
133             }
134
135             // we'd also want slightly more complicated substitution
136             // involving an array as the return value,
137             // although we're not sure how colliding attributes would
138             // resolve (certain ones would be completely overriden,
139             // others would prepend themselves).
140         }
141
142         $context->destroy('CurrentAttr');
143
144         // post transforms
145
146         // global (error reporting untested)
147         foreach ($definition->info_attr_transform_post as $transform) {
148             $attr = $transform->transform($o = $attr, $config, $context);
149             if ($e) {
150                 if ($attr != $o) {
151                     $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
152                 }
153             }
154         }
155
156         // local (error reporting untested)
157         foreach ($definition->info[$token->name]->attr_transform_post as $transform) {
158             $attr = $transform->transform($o = $attr, $config, $context);
159             if ($e) {
160                 if ($attr != $o) {
161                     $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
162                 }
163             }
164         }
165
166         $token->attr = $attr;
167
168         // destroy CurrentToken if we made it ourselves
169         if (!$current_token) {
170             $context->destroy('CurrentToken');
171         }
172
173     }
174
175
176 }
177
178 // vim: et sw=4 sts=4