HTMLPurifier 4.4.0
/home/ezyang/Dev/htmlpurifier/library/HTMLPurifier/AttrValidator.php
Go to the documentation of this file.
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