[1.3.1] Standardized all attribute handling variables to attr, made it plural
[htmlpurifier.git] / library / HTMLPurifier / Strategy / ValidateAttributes.php
blob07744f803d25ca062d0b6eb2742dd1439183c213
1 <?php
3 require_once 'HTMLPurifier/Strategy.php';
4 require_once 'HTMLPurifier/HTMLDefinition.php';
5 require_once 'HTMLPurifier/IDAccumulator.php';
7 HTMLPurifier_ConfigSchema::define(
8 'Attr', 'IDBlacklist', array(), 'list',
9 'Array of IDs not allowed in the document.');
11 /**
12 * Validate all attributes in the tokens.
15 class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy
18 function execute($tokens, $config, &$context) {
20 $definition = $config->getHTMLDefinition();
22 // setup id_accumulator context
23 $id_accumulator = new HTMLPurifier_IDAccumulator();
24 $id_accumulator->load($config->get('Attr', 'IDBlacklist'));
25 $context->register('IDAccumulator', $id_accumulator);
27 // create alias to global definition array, see also $defs
28 // DEFINITION CALL
29 $d_defs = $definition->info_global_attr;
31 foreach ($tokens as $key => $token) {
33 // only process tokens that have attributes,
34 // namely start and empty tags
35 if ($token->type !== 'start' && $token->type !== 'empty') continue;
37 // copy out attributes for easy manipulation
38 $attr = $token->attr;
40 // do global transformations (pre)
41 // nothing currently utilizes this
42 foreach ($definition->info_attr_transform_pre as $transform) {
43 $attr = $transform->transform($attr, $config, $context);
46 // do local transformations only applicable to this element (pre)
47 // ex. <p align="right"> to <p style="text-align:right;">
48 foreach ($definition->info[$token->name]->attr_transform_pre
49 as $transform
50 ) {
51 $attr = $transform->transform($attr, $config, $context);
54 // create alias to this element's attribute definition array, see
55 // also $d_defs (global attribute definition array)
56 // DEFINITION CALL
57 $defs = $definition->info[$token->name]->attr;
59 // iterate through all the attribute keypairs
60 // Watch out for name collisions: $key has previously been used
61 foreach ($attr as $attr_key => $value) {
63 // call the definition
64 if ( isset($defs[$attr_key]) ) {
65 // there is a local definition defined
66 if ($defs[$attr_key] === false) {
67 // We've explicitly been told not to allow this element.
68 // This is usually when there's a global definition
69 // that must be overridden.
70 // Theoretically speaking, we could have a
71 // AttrDef_DenyAll, but this is faster!
72 $result = false;
73 } else {
74 // validate according to the element's definition
75 $result = $defs[$attr_key]->validate(
76 $value, $config, $context
79 } elseif ( isset($d_defs[$attr_key]) ) {
80 // there is a global definition defined, validate according
81 // to the global definition
82 $result = $d_defs[$attr_key]->validate(
83 $value, $config, $context
85 } else {
86 // system never heard of the attribute? DELETE!
87 $result = false;
90 // put the results into effect
91 if ($result === false || $result === null) {
92 // remove the attribute
93 unset($attr[$attr_key]);
94 } elseif (is_string($result)) {
95 // simple substitution
96 $attr[$attr_key] = $result;
99 // we'd also want slightly more complicated substitution
100 // involving an array as the return value,
101 // although we're not sure how colliding attributes would
102 // resolve (certain ones would be completely overriden,
103 // others would prepend themselves).
106 // post transforms
108 // ex. <x lang="fr"> to <x lang="fr" xml:lang="fr">
109 foreach ($definition->info_attr_transform_post as $transform) {
110 $attr = $transform->transform($attr, $config, $context);
113 // ex. <bdo> to <bdo dir="ltr">
114 foreach ($definition->info[$token->name]->attr_transform_post as $transform) {
115 $attr = $transform->transform($attr, $config, $context);
118 // commit changes
119 // could interfere with flyweight implementation
120 $tokens[$key]->attr = $attr;
122 $context->destroy('IDAccumulator');
124 return $tokens;