[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 3 class HTMLPurifier_HTMLModuleManager 4 { 5 6 /** 7 * Instance of HTMLPurifier_DoctypeRegistry 8 */ 9 public $doctypes; 10 11 /** 12 * Instance of current doctype 13 */ 14 public $doctype; 15 16 /** 17 * Instance of HTMLPurifier_AttrTypes 18 */ 19 public $attrTypes; 20 21 /** 22 * Active instances of modules for the specified doctype are 23 * indexed, by name, in this array. 24 */ 25 public $modules = array(); 26 27 /** 28 * Array of recognized HTMLPurifier_Module instances, indexed by 29 * module's class name. This array is usually lazy loaded, but a 30 * user can overload a module by pre-emptively registering it. 31 */ 32 public $registeredModules = array(); 33 34 /** 35 * List of extra modules that were added by the user using addModule(). 36 * These get unconditionally merged into the current doctype, whatever 37 * it may be. 38 */ 39 public $userModules = array(); 40 41 /** 42 * Associative array of element name to list of modules that have 43 * definitions for the element; this array is dynamically filled. 44 */ 45 public $elementLookup = array(); 46 47 /** List of prefixes we should use for registering small names */ 48 public $prefixes = array('HTMLPurifier_HTMLModule_'); 49 50 public $contentSets; /**< Instance of HTMLPurifier_ContentSets */ 51 public $attrCollections; /**< Instance of HTMLPurifier_AttrCollections */ 52 53 /** If set to true, unsafe elements and attributes will be allowed */ 54 public $trusted = false; 55 56 public function __construct() { 57 58 // editable internal objects 59 $this->attrTypes = new HTMLPurifier_AttrTypes(); 60 $this->doctypes = new HTMLPurifier_DoctypeRegistry(); 61 62 // setup basic modules 63 $common = array( 64 'CommonAttributes', 'Text', 'Hypertext', 'List', 65 'Presentation', 'Edit', 'Bdo', 'Tables', 'Image', 66 'StyleAttribute', 67 // Unsafe: 68 'Scripting', 'Object', 'Forms', 69 // Sorta legacy, but present in strict: 70 'Name', 71 ); 72 $transitional = array('Legacy', 'Target'); 73 $xml = array('XMLCommonAttributes'); 74 $non_xml = array('NonXMLCommonAttributes'); 75 76 // setup basic doctypes 77 $this->doctypes->register( 78 'HTML 4.01 Transitional', false, 79 array_merge($common, $transitional, $non_xml), 80 array('Tidy_Transitional', 'Tidy_Proprietary'), 81 array(), 82 '-//W3C//DTD HTML 4.01 Transitional//EN', 83 'http://www.w3.org/TR/html4/loose.dtd' 84 ); 85 86 $this->doctypes->register( 87 'HTML 4.01 Strict', false, 88 array_merge($common, $non_xml), 89 array('Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'), 90 array(), 91 '-//W3C//DTD HTML 4.01//EN', 92 'http://www.w3.org/TR/html4/strict.dtd' 93 ); 94 95 $this->doctypes->register( 96 'XHTML 1.0 Transitional', true, 97 array_merge($common, $transitional, $xml, $non_xml), 98 array('Tidy_Transitional', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Name'), 99 array(), 100 '-//W3C//DTD XHTML 1.0 Transitional//EN', 101 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd' 102 ); 103 104 $this->doctypes->register( 105 'XHTML 1.0 Strict', true, 106 array_merge($common, $xml, $non_xml), 107 array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'), 108 array(), 109 '-//W3C//DTD XHTML 1.0 Strict//EN', 110 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd' 111 ); 112 113 $this->doctypes->register( 114 'XHTML 1.1', true, 115 array_merge($common, $xml, array('Ruby')), 116 array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Strict', 'Tidy_Name'), // Tidy_XHTML1_1 117 array(), 118 '-//W3C//DTD XHTML 1.1//EN', 119 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd' 120 ); 121 122 } 123 124 /** 125 * Registers a module to the recognized module list, useful for 126 * overloading pre-existing modules. 127 * @param $module Mixed: string module name, with or without 128 * HTMLPurifier_HTMLModule prefix, or instance of 129 * subclass of HTMLPurifier_HTMLModule. 130 * @param $overload Boolean whether or not to overload previous modules. 131 * If this is not set, and you do overload a module, 132 * HTML Purifier will complain with a warning. 133 * @note This function will not call autoload, you must instantiate 134 * (and thus invoke) autoload outside the method. 135 * @note If a string is passed as a module name, different variants 136 * will be tested in this order: 137 * - Check for HTMLPurifier_HTMLModule_$name 138 * - Check all prefixes with $name in order they were added 139 * - Check for literal object name 140 * - Throw fatal error 141 * If your object name collides with an internal class, specify 142 * your module manually. All modules must have been included 143 * externally: registerModule will not perform inclusions for you! 144 */ 145 public function registerModule($module, $overload = false) { 146 if (is_string($module)) { 147 // attempt to load the module 148 $original_module = $module; 149 $ok = false; 150 foreach ($this->prefixes as $prefix) { 151 $module = $prefix . $original_module; 152 if (class_exists($module)) { 153 $ok = true; 154 break; 155 } 156 } 157 if (!$ok) { 158 $module = $original_module; 159 if (!class_exists($module)) { 160 trigger_error($original_module . ' module does not exist', 161 E_USER_ERROR); 162 return; 163 } 164 } 165 $module = new $module(); 166 } 167 if (empty($module->name)) { 168 trigger_error('Module instance of ' . get_class($module) . ' must have name'); 169 return; 170 } 171 if (!$overload && isset($this->registeredModules[$module->name])) { 172 trigger_error('Overloading ' . $module->name . ' without explicit overload parameter', E_USER_WARNING); 173 } 174 $this->registeredModules[$module->name] = $module; 175 } 176 177 /** 178 * Adds a module to the current doctype by first registering it, 179 * and then tacking it on to the active doctype 180 */ 181 public function addModule($module) { 182 $this->registerModule($module); 183 if (is_object($module)) $module = $module->name; 184 $this->userModules[] = $module; 185 } 186 187 /** 188 * Adds a class prefix that registerModule() will use to resolve a 189 * string name to a concrete class 190 */ 191 public function addPrefix($prefix) { 192 $this->prefixes[] = $prefix; 193 } 194 195 /** 196 * Performs processing on modules, after being called you may 197 * use getElement() and getElements() 198 * @param $config Instance of HTMLPurifier_Config 199 */ 200 public function setup($config) { 201 202 $this->trusted = $config->get('HTML', 'Trusted'); 203 204 // generate 205 $this->doctype = $this->doctypes->make($config); 206 $modules = $this->doctype->modules; 207 208 // take out the default modules that aren't allowed 209 $lookup = $config->get('HTML', 'AllowedModules'); 210 $special_cases = $config->get('HTML', 'CoreModules'); 211 212 if (is_array($lookup)) { 213 foreach ($modules as $k => $m) { 214 if (isset($special_cases[$m])) continue; 215 if (!isset($lookup[$m])) unset($modules[$k]); 216 } 217 } 218 219 // add proprietary module (this gets special treatment because 220 // it is completely removed from doctypes, etc.) 221 if ($config->get('HTML', 'Proprietary')) { 222 $modules[] = 'Proprietary'; 223 } 224 225 // add SafeObject/Safeembed modules 226 if ($config->get('HTML', 'SafeObject')) { 227 $modules[] = 'SafeObject'; 228 } 229 if ($config->get('HTML', 'SafeEmbed')) { 230 $modules[] = 'SafeEmbed'; 231 } 232 233 // merge in custom modules 234 $modules = array_merge($modules, $this->userModules); 235 236 foreach ($modules as $module) { 237 $this->processModule($module); 238 $this->modules[$module]->setup($config); 239 } 240 241 foreach ($this->doctype->tidyModules as $module) { 242 $this->processModule($module); 243 $this->modules[$module]->setup($config); 244 } 245 246 // prepare any injectors 247 foreach ($this->modules as $module) { 248 $n = array(); 249 foreach ($module->info_injector as $i => $injector) { 250 if (!is_object($injector)) { 251 $class = "HTMLPurifier_Injector_$injector"; 252 $injector = new $class; 253 } 254 $n[$injector->name] = $injector; 255 } 256 $module->info_injector = $n; 257 } 258 259 // setup lookup table based on all valid modules 260 foreach ($this->modules as $module) { 261 foreach ($module->info as $name => $def) { 262 if (!isset($this->elementLookup[$name])) { 263 $this->elementLookup[$name] = array(); 264 } 265 $this->elementLookup[$name][] = $module->name; 266 } 267 } 268 269 // note the different choice 270 $this->contentSets = new HTMLPurifier_ContentSets( 271 // content set assembly deals with all possible modules, 272 // not just ones deemed to be "safe" 273 $this->modules 274 ); 275 $this->attrCollections = new HTMLPurifier_AttrCollections( 276 $this->attrTypes, 277 // there is no way to directly disable a global attribute, 278 // but using AllowedAttributes or simply not including 279 // the module in your custom doctype should be sufficient 280 $this->modules 281 ); 282 } 283 284 /** 285 * Takes a module and adds it to the active module collection, 286 * registering it if necessary. 287 */ 288 public function processModule($module) { 289 if (!isset($this->registeredModules[$module]) || is_object($module)) { 290 $this->registerModule($module); 291 } 292 $this->modules[$module] = $this->registeredModules[$module]; 293 } 294 295 /** 296 * Retrieves merged element definitions. 297 * @return Array of HTMLPurifier_ElementDef 298 */ 299 public function getElements() { 300 301 $elements = array(); 302 foreach ($this->modules as $module) { 303 if (!$this->trusted && !$module->safe) continue; 304 foreach ($module->info as $name => $v) { 305 if (isset($elements[$name])) continue; 306 $elements[$name] = $this->getElement($name); 307 } 308 } 309 310 // remove dud elements, this happens when an element that 311 // appeared to be safe actually wasn't 312 foreach ($elements as $n => $v) { 313 if ($v === false) unset($elements[$n]); 314 } 315 316 return $elements; 317 318 } 319 320 /** 321 * Retrieves a single merged element definition 322 * @param $name Name of element 323 * @param $trusted Boolean trusted overriding parameter: set to true 324 * if you want the full version of an element 325 * @return Merged HTMLPurifier_ElementDef 326 * @note You may notice that modules are getting iterated over twice (once 327 * in getElements() and once here). This 328 * is because 329 */ 330 public function getElement($name, $trusted = null) { 331 332 if (!isset($this->elementLookup[$name])) { 333 return false; 334 } 335 336 // setup global state variables 337 $def = false; 338 if ($trusted === null) $trusted = $this->trusted; 339 340 // iterate through each module that has registered itself to this 341 // element 342 foreach($this->elementLookup[$name] as $module_name) { 343 344 $module = $this->modules[$module_name]; 345 346 // refuse to create/merge from a module that is deemed unsafe-- 347 // pretend the module doesn't exist--when trusted mode is not on. 348 if (!$trusted && !$module->safe) { 349 continue; 350 } 351 352 // clone is used because, ideally speaking, the original 353 // definition should not be modified. Usually, this will 354 // make no difference, but for consistency's sake 355 $new_def = clone $module->info[$name]; 356 357 if (!$def && $new_def->standalone) { 358 $def = $new_def; 359 } elseif ($def) { 360 // This will occur even if $new_def is standalone. In practice, 361 // this will usually result in a full replacement. 362 $def->mergeIn($new_def); 363 } else { 364 // :TODO: 365 // non-standalone definitions that don't have a standalone 366 // to merge into could be deferred to the end 367 continue; 368 } 369 370 // attribute value expansions 371 $this->attrCollections->performInclusions($def->attr); 372 $this->attrCollections->expandIdentifiers($def->attr, $this->attrTypes); 373 374 // descendants_are_inline, for ChildDef_Chameleon 375 if (is_string($def->content_model) && 376 strpos($def->content_model, 'Inline') !== false) { 377 if ($name != 'del' && $name != 'ins') { 378 // this is for you, ins/del 379 $def->descendants_are_inline = true; 380 } 381 } 382 383 $this->contentSets->generateChildDef($def, $module); 384 } 385 386 // This can occur if there is a blank definition, but no base to 387 // mix it in with 388 if (!$def) return false; 389 390 // add information on required attributes 391 foreach ($def->attr as $attr_name => $attr_def) { 392 if ($attr_def->required) { 393 $def->required_attr[] = $attr_name; 394 } 395 } 396 397 return $def; 398 399 } 400 401 } 402 403 // vim: et sw=4 sts=4
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:08:37 2014 | Cross-referenced by PHPXref 0.7.1 |