[ Index ] |
PHP Cross Reference of vtigercrm-6.1.0 |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Configuration object that triggers customizable behavior. 5 * 6 * @warning This class is strongly defined: that means that the class 7 * will fail if an undefined directive is retrieved or set. 8 * 9 * @note Many classes that could (although many times don't) use the 10 * configuration object make it a mandatory parameter. This is 11 * because a configuration object should always be forwarded, 12 * otherwise, you run the risk of missing a parameter and then 13 * being stumped when a configuration directive doesn't work. 14 * 15 * @todo Reconsider some of the public member variables 16 */ 17 class HTMLPurifier_Config 18 { 19 20 /** 21 * HTML Purifier's version 22 */ 23 public $version = '3.3.0'; 24 25 /** 26 * Bool indicator whether or not to automatically finalize 27 * the object if a read operation is done 28 */ 29 public $autoFinalize = true; 30 31 // protected member variables 32 33 /** 34 * Namespace indexed array of serials for specific namespaces (see 35 * getSerial() for more info). 36 */ 37 protected $serials = array(); 38 39 /** 40 * Serial for entire configuration object 41 */ 42 protected $serial; 43 44 /** 45 * Parser for variables 46 */ 47 protected $parser; 48 49 /** 50 * Reference HTMLPurifier_ConfigSchema for value checking 51 * @note This is public for introspective purposes. Please don't 52 * abuse! 53 */ 54 public $def; 55 56 /** 57 * Indexed array of definitions 58 */ 59 protected $definitions; 60 61 /** 62 * Bool indicator whether or not config is finalized 63 */ 64 protected $finalized = false; 65 66 /** 67 * Property list containing configuration directives. 68 */ 69 protected $plist; 70 71 /** 72 * @param $definition HTMLPurifier_ConfigSchema that defines what directives 73 * are allowed. 74 */ 75 public function __construct($definition) { 76 $this->plist = new HTMLPurifier_PropertyList($definition->defaultPlist); 77 $this->def = $definition; // keep a copy around for checking 78 $this->parser = new HTMLPurifier_VarParser_Flexible(); 79 } 80 81 /** 82 * Convenience constructor that creates a config object based on a mixed var 83 * @param mixed $config Variable that defines the state of the config 84 * object. Can be: a HTMLPurifier_Config() object, 85 * an array of directives based on loadArray(), 86 * or a string filename of an ini file. 87 * @param HTMLPurifier_ConfigSchema Schema object 88 * @return Configured HTMLPurifier_Config object 89 */ 90 public static function create($config, $schema = null) { 91 if ($config instanceof HTMLPurifier_Config) { 92 // pass-through 93 return $config; 94 } 95 if (!$schema) { 96 $ret = HTMLPurifier_Config::createDefault(); 97 } else { 98 $ret = new HTMLPurifier_Config($schema); 99 } 100 if (is_string($config)) $ret->loadIni($config); 101 elseif (is_array($config)) $ret->loadArray($config); 102 return $ret; 103 } 104 105 /** 106 * Convenience constructor that creates a default configuration object. 107 * @return Default HTMLPurifier_Config object. 108 */ 109 public static function createDefault() { 110 $definition = HTMLPurifier_ConfigSchema::instance(); 111 $config = new HTMLPurifier_Config($definition); 112 return $config; 113 } 114 115 /** 116 * Retreives a value from the configuration. 117 * @param $namespace String namespace 118 * @param $key String key 119 */ 120 public function get($namespace, $key) { 121 if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); 122 if (!isset($this->def->info[$namespace][$key])) { 123 // can't add % due to SimpleTest bug 124 trigger_error('Cannot retrieve value of undefined directive ' . htmlspecialchars("$namespace.$key"), 125 E_USER_WARNING); 126 return; 127 } 128 if (isset($this->def->info[$namespace][$key]->isAlias)) { 129 $d = $this->def->info[$namespace][$key]; 130 trigger_error('Cannot get value from aliased directive, use real name ' . $d->namespace . '.' . $d->name, 131 E_USER_ERROR); 132 return; 133 } 134 return $this->plist->get("$namespace.$key"); 135 } 136 137 /** 138 * Retreives an array of directives to values from a given namespace 139 * @param $namespace String namespace 140 */ 141 public function getBatch($namespace) { 142 if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); 143 if (!isset($this->def->info[$namespace])) { 144 trigger_error('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace), 145 E_USER_WARNING); 146 return; 147 } 148 $full = $this->getAll(); 149 return $full[$namespace]; 150 } 151 152 /** 153 * Returns a md5 signature of a segment of the configuration object 154 * that uniquely identifies that particular configuration 155 * @note Revision is handled specially and is removed from the batch 156 * before processing! 157 * @param $namespace Namespace to get serial for 158 */ 159 public function getBatchSerial($namespace) { 160 if (empty($this->serials[$namespace])) { 161 $batch = $this->getBatch($namespace); 162 unset($batch['DefinitionRev']); 163 $this->serials[$namespace] = md5(serialize($batch)); 164 } 165 return $this->serials[$namespace]; 166 } 167 168 /** 169 * Returns a md5 signature for the entire configuration object 170 * that uniquely identifies that particular configuration 171 */ 172 public function getSerial() { 173 if (empty($this->serial)) { 174 $this->serial = md5(serialize($this->getAll())); 175 } 176 return $this->serial; 177 } 178 179 /** 180 * Retrieves all directives, organized by namespace 181 */ 182 public function getAll() { 183 if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); 184 $ret = array(); 185 foreach ($this->plist->squash() as $name => $value) { 186 list($ns, $key) = explode('.', $name, 2); 187 $ret[$ns][$key] = $value; 188 } 189 return $ret; 190 } 191 192 /** 193 * Sets a value to configuration. 194 * @param $namespace String namespace 195 * @param $key String key 196 * @param $value Mixed value 197 */ 198 public function set($namespace, $key, $value, $from_alias = false) { 199 if ($this->isFinalized('Cannot set directive after finalization')) return; 200 if (!isset($this->def->info[$namespace][$key])) { 201 trigger_error('Cannot set undefined directive ' . htmlspecialchars("$namespace.$key") . ' to value', 202 E_USER_WARNING); 203 return; 204 } 205 $def = $this->def->info[$namespace][$key]; 206 207 if (isset($def->isAlias)) { 208 if ($from_alias) { 209 trigger_error('Double-aliases not allowed, please fix '. 210 'ConfigSchema bug with' . "$namespace.$key", E_USER_ERROR); 211 return; 212 } 213 $this->set($new_ns = $def->namespace, 214 $new_dir = $def->name, 215 $value, true); 216 trigger_error("$namespace.$key is an alias, preferred directive name is $new_ns.$new_dir", E_USER_NOTICE); 217 return; 218 } 219 220 // Raw type might be negative when using the fully optimized form 221 // of stdclass, which indicates allow_null == true 222 $rtype = is_int($def) ? $def : $def->type; 223 if ($rtype < 0) { 224 $type = -$rtype; 225 $allow_null = true; 226 } else { 227 $type = $rtype; 228 $allow_null = isset($def->allow_null); 229 } 230 231 try { 232 $value = $this->parser->parse($value, $type, $allow_null); 233 } catch (HTMLPurifier_VarParserException $e) { 234 trigger_error('Value for ' . "$namespace.$key" . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING); 235 return; 236 } 237 if (is_string($value) && is_object($def)) { 238 // resolve value alias if defined 239 if (isset($def->aliases[$value])) { 240 $value = $def->aliases[$value]; 241 } 242 // check to see if the value is allowed 243 if (isset($def->allowed) && !isset($def->allowed[$value])) { 244 trigger_error('Value not supported, valid values are: ' . 245 $this->_listify($def->allowed), E_USER_WARNING); 246 return; 247 } 248 } 249 $this->plist->set("$namespace.$key", $value); 250 251 // reset definitions if the directives they depend on changed 252 // this is a very costly process, so it's discouraged 253 // with finalization 254 if ($namespace == 'HTML' || $namespace == 'CSS') { 255 $this->definitions[$namespace] = null; 256 } 257 258 $this->serials[$namespace] = false; 259 } 260 261 /** 262 * Convenience function for error reporting 263 */ 264 private function _listify($lookup) { 265 $list = array(); 266 foreach ($lookup as $name => $b) $list[] = $name; 267 return implode(', ', $list); 268 } 269 270 /** 271 * Retrieves object reference to the HTML definition. 272 * @param $raw Return a copy that has not been setup yet. Must be 273 * called before it's been setup, otherwise won't work. 274 */ 275 public function getHTMLDefinition($raw = false) { 276 return $this->getDefinition('HTML', $raw); 277 } 278 279 /** 280 * Retrieves object reference to the CSS definition 281 * @param $raw Return a copy that has not been setup yet. Must be 282 * called before it's been setup, otherwise won't work. 283 */ 284 public function getCSSDefinition($raw = false) { 285 return $this->getDefinition('CSS', $raw); 286 } 287 288 /** 289 * Retrieves a definition 290 * @param $type Type of definition: HTML, CSS, etc 291 * @param $raw Whether or not definition should be returned raw 292 */ 293 public function getDefinition($type, $raw = false) { 294 if (!$this->finalized) $this->autoFinalize ? $this->finalize() : $this->plist->squash(true); 295 $factory = HTMLPurifier_DefinitionCacheFactory::instance(); 296 $cache = $factory->create($type, $this); 297 if (!$raw) { 298 // see if we can quickly supply a definition 299 if (!empty($this->definitions[$type])) { 300 if (!$this->definitions[$type]->setup) { 301 $this->definitions[$type]->setup($this); 302 $cache->set($this->definitions[$type], $this); 303 } 304 return $this->definitions[$type]; 305 } 306 // memory check missed, try cache 307 $this->definitions[$type] = $cache->get($this); 308 if ($this->definitions[$type]) { 309 // definition in cache, return it 310 return $this->definitions[$type]; 311 } 312 } elseif ( 313 !empty($this->definitions[$type]) && 314 !$this->definitions[$type]->setup 315 ) { 316 // raw requested, raw in memory, quick return 317 return $this->definitions[$type]; 318 } 319 // quick checks failed, let's create the object 320 if ($type == 'HTML') { 321 $this->definitions[$type] = new HTMLPurifier_HTMLDefinition(); 322 } elseif ($type == 'CSS') { 323 $this->definitions[$type] = new HTMLPurifier_CSSDefinition(); 324 } elseif ($type == 'URI') { 325 $this->definitions[$type] = new HTMLPurifier_URIDefinition(); 326 } else { 327 throw new HTMLPurifier_Exception("Definition of $type type not supported"); 328 } 329 // quick abort if raw 330 if ($raw) { 331 if (is_null($this->get($type, 'DefinitionID'))) { 332 // fatally error out if definition ID not set 333 throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID"); 334 } 335 return $this->definitions[$type]; 336 } 337 // set it up 338 $this->definitions[$type]->setup($this); 339 // save in cache 340 $cache->set($this->definitions[$type], $this); 341 return $this->definitions[$type]; 342 } 343 344 /** 345 * Loads configuration values from an array with the following structure: 346 * Namespace.Directive => Value 347 * @param $config_array Configuration associative array 348 */ 349 public function loadArray($config_array) { 350 if ($this->isFinalized('Cannot load directives after finalization')) return; 351 foreach ($config_array as $key => $value) { 352 $key = str_replace('_', '.', $key); 353 if (strpos($key, '.') !== false) { 354 // condensed form 355 list($namespace, $directive) = explode('.', $key); 356 $this->set($namespace, $directive, $value); 357 } else { 358 $namespace = $key; 359 $namespace_values = $value; 360 foreach ($namespace_values as $directive => $value) { 361 $this->set($namespace, $directive, $value); 362 } 363 } 364 } 365 } 366 367 /** 368 * Returns a list of array(namespace, directive) for all directives 369 * that are allowed in a web-form context as per an allowed 370 * namespaces/directives list. 371 * @param $allowed List of allowed namespaces/directives 372 */ 373 public static function getAllowedDirectivesForForm($allowed, $schema = null) { 374 if (!$schema) { 375 $schema = HTMLPurifier_ConfigSchema::instance(); 376 } 377 if ($allowed !== true) { 378 if (is_string($allowed)) $allowed = array($allowed); 379 $allowed_ns = array(); 380 $allowed_directives = array(); 381 $blacklisted_directives = array(); 382 foreach ($allowed as $ns_or_directive) { 383 if (strpos($ns_or_directive, '.') !== false) { 384 // directive 385 if ($ns_or_directive[0] == '-') { 386 $blacklisted_directives[substr($ns_or_directive, 1)] = true; 387 } else { 388 $allowed_directives[$ns_or_directive] = true; 389 } 390 } else { 391 // namespace 392 $allowed_ns[$ns_or_directive] = true; 393 } 394 } 395 } 396 $ret = array(); 397 foreach ($schema->info as $ns => $keypairs) { 398 foreach ($keypairs as $directive => $def) { 399 if ($allowed !== true) { 400 if (isset($blacklisted_directives["$ns.$directive"])) continue; 401 if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue; 402 } 403 if (isset($def->isAlias)) continue; 404 if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue; 405 $ret[] = array($ns, $directive); 406 } 407 } 408 return $ret; 409 } 410 411 /** 412 * Loads configuration values from $_GET/$_POST that were posted 413 * via ConfigForm 414 * @param $array $_GET or $_POST array to import 415 * @param $index Index/name that the config variables are in 416 * @param $allowed List of allowed namespaces/directives 417 * @param $mq_fix Boolean whether or not to enable magic quotes fix 418 * @param $schema Instance of HTMLPurifier_ConfigSchema to use, if not global copy 419 */ 420 public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) { 421 $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema); 422 $config = HTMLPurifier_Config::create($ret, $schema); 423 return $config; 424 } 425 426 /** 427 * Merges in configuration values from $_GET/$_POST to object. NOT STATIC. 428 * @note Same parameters as loadArrayFromForm 429 */ 430 public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true) { 431 $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def); 432 $this->loadArray($ret); 433 } 434 435 /** 436 * Prepares an array from a form into something usable for the more 437 * strict parts of HTMLPurifier_Config 438 */ 439 public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) { 440 if ($index !== false) $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array(); 441 $mq = $mq_fix && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc(); 442 443 $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema); 444 $ret = array(); 445 foreach ($allowed as $key) { 446 list($ns, $directive) = $key; 447 $skey = "$ns.$directive"; 448 if (!empty($array["Null_$skey"])) { 449 $ret[$ns][$directive] = null; 450 continue; 451 } 452 if (!isset($array[$skey])) continue; 453 $value = $mq ? stripslashes($array[$skey]) : $array[$skey]; 454 $ret[$ns][$directive] = $value; 455 } 456 return $ret; 457 } 458 459 /** 460 * Loads configuration values from an ini file 461 * @param $filename Name of ini file 462 */ 463 public function loadIni($filename) { 464 if ($this->isFinalized('Cannot load directives after finalization')) return; 465 $array = parse_ini_file($filename, true); 466 $this->loadArray($array); 467 } 468 469 /** 470 * Checks whether or not the configuration object is finalized. 471 * @param $error String error message, or false for no error 472 */ 473 public function isFinalized($error = false) { 474 if ($this->finalized && $error) { 475 trigger_error($error, E_USER_ERROR); 476 } 477 return $this->finalized; 478 } 479 480 /** 481 * Finalizes configuration only if auto finalize is on and not 482 * already finalized 483 */ 484 public function autoFinalize() { 485 if (!$this->finalized && $this->autoFinalize) $this->finalize(); 486 } 487 488 /** 489 * Finalizes a configuration object, prohibiting further change 490 */ 491 public function finalize() { 492 $this->finalized = true; 493 } 494 495 } 496 497 // 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 |