HTMLPurifier 4.4.0
|
00001 <?php 00002 00008 class HTMLPurifier_AttrValidator 00009 { 00010 00021 public function validateToken(&$token, &$config, $context) { 00022 00023 $definition = $config->getHTMLDefinition(); 00024 $e =& $context->get('ErrorCollector', true); 00025 00026 // initialize IDAccumulator if necessary 00027 $ok =& $context->get('IDAccumulator', true); 00028 if (!$ok) { 00029 $id_accumulator = HTMLPurifier_IDAccumulator::build($config, $context); 00030 $context->register('IDAccumulator', $id_accumulator); 00031 } 00032 00033 // initialize CurrentToken if necessary 00034 $current_token =& $context->get('CurrentToken', true); 00035 if (!$current_token) $context->register('CurrentToken', $token); 00036 00037 if ( 00038 !$token instanceof HTMLPurifier_Token_Start && 00039 !$token instanceof HTMLPurifier_Token_Empty 00040 ) return $token; 00041 00042 // create alias to global definition array, see also $defs 00043 // DEFINITION CALL 00044 $d_defs = $definition->info_global_attr; 00045 00046 // don't update token until the very end, to ensure an atomic update 00047 $attr = $token->attr; 00048 00049 // do global transformations (pre) 00050 // nothing currently utilizes this 00051 foreach ($definition->info_attr_transform_pre as $transform) { 00052 $attr = $transform->transform($o = $attr, $config, $context); 00053 if ($e) { 00054 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); 00055 } 00056 } 00057 00058 // do local transformations only applicable to this element (pre) 00059 // ex. <p align="right"> to <p style="text-align:right;"> 00060 foreach ($definition->info[$token->name]->attr_transform_pre as $transform) { 00061 $attr = $transform->transform($o = $attr, $config, $context); 00062 if ($e) { 00063 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); 00064 } 00065 } 00066 00067 // create alias to this element's attribute definition array, see 00068 // also $d_defs (global attribute definition array) 00069 // DEFINITION CALL 00070 $defs = $definition->info[$token->name]->attr; 00071 00072 $attr_key = false; 00073 $context->register('CurrentAttr', $attr_key); 00074 00075 // iterate through all the attribute keypairs 00076 // Watch out for name collisions: $key has previously been used 00077 foreach ($attr as $attr_key => $value) { 00078 00079 // call the definition 00080 if ( isset($defs[$attr_key]) ) { 00081 // there is a local definition defined 00082 if ($defs[$attr_key] === false) { 00083 // We've explicitly been told not to allow this element. 00084 // This is usually when there's a global definition 00085 // that must be overridden. 00086 // Theoretically speaking, we could have a 00087 // AttrDef_DenyAll, but this is faster! 00088 $result = false; 00089 } else { 00090 // validate according to the element's definition 00091 $result = $defs[$attr_key]->validate( 00092 $value, $config, $context 00093 ); 00094 } 00095 } elseif ( isset($d_defs[$attr_key]) ) { 00096 // there is a global definition defined, validate according 00097 // to the global definition 00098 $result = $d_defs[$attr_key]->validate( 00099 $value, $config, $context 00100 ); 00101 } else { 00102 // system never heard of the attribute? DELETE! 00103 $result = false; 00104 } 00105 00106 // put the results into effect 00107 if ($result === false || $result === null) { 00108 // this is a generic error message that should replaced 00109 // with more specific ones when possible 00110 if ($e) $e->send(E_ERROR, 'AttrValidator: Attribute removed'); 00111 00112 // remove the attribute 00113 unset($attr[$attr_key]); 00114 } elseif (is_string($result)) { 00115 // generally, if a substitution is happening, there 00116 // was some sort of implicit correction going on. We'll 00117 // delegate it to the attribute classes to say exactly what. 00118 00119 // simple substitution 00120 $attr[$attr_key] = $result; 00121 } else { 00122 // nothing happens 00123 } 00124 00125 // we'd also want slightly more complicated substitution 00126 // involving an array as the return value, 00127 // although we're not sure how colliding attributes would 00128 // resolve (certain ones would be completely overriden, 00129 // others would prepend themselves). 00130 } 00131 00132 $context->destroy('CurrentAttr'); 00133 00134 // post transforms 00135 00136 // global (error reporting untested) 00137 foreach ($definition->info_attr_transform_post as $transform) { 00138 $attr = $transform->transform($o = $attr, $config, $context); 00139 if ($e) { 00140 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); 00141 } 00142 } 00143 00144 // local (error reporting untested) 00145 foreach ($definition->info[$token->name]->attr_transform_post as $transform) { 00146 $attr = $transform->transform($o = $attr, $config, $context); 00147 if ($e) { 00148 if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr); 00149 } 00150 } 00151 00152 $token->attr = $attr; 00153 00154 // destroy CurrentToken if we made it ourselves 00155 if (!$current_token) $context->destroy('CurrentToken'); 00156 00157 } 00158 00159 00160 } 00161 00162 // vim: et sw=4 sts=4