[ Index ] |
PHP Cross Reference of Unnamed Project |
[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 * @type string 23 */ 24 public $version = '4.6.0'; 25 26 /** 27 * Whether or not to automatically finalize 28 * the object if a read operation is done. 29 * @type bool 30 */ 31 public $autoFinalize = true; 32 33 // protected member variables 34 35 /** 36 * Namespace indexed array of serials for specific namespaces. 37 * @see getSerial() for more info. 38 * @type string[] 39 */ 40 protected $serials = array(); 41 42 /** 43 * Serial for entire configuration object. 44 * @type string 45 */ 46 protected $serial; 47 48 /** 49 * Parser for variables. 50 * @type HTMLPurifier_VarParser_Flexible 51 */ 52 protected $parser = null; 53 54 /** 55 * Reference HTMLPurifier_ConfigSchema for value checking. 56 * @type HTMLPurifier_ConfigSchema 57 * @note This is public for introspective purposes. Please don't 58 * abuse! 59 */ 60 public $def; 61 62 /** 63 * Indexed array of definitions. 64 * @type HTMLPurifier_Definition[] 65 */ 66 protected $definitions; 67 68 /** 69 * Whether or not config is finalized. 70 * @type bool 71 */ 72 protected $finalized = false; 73 74 /** 75 * Property list containing configuration directives. 76 * @type array 77 */ 78 protected $plist; 79 80 /** 81 * Whether or not a set is taking place due to an alias lookup. 82 * @type bool 83 */ 84 private $aliasMode; 85 86 /** 87 * Set to false if you do not want line and file numbers in errors. 88 * (useful when unit testing). This will also compress some errors 89 * and exceptions. 90 * @type bool 91 */ 92 public $chatty = true; 93 94 /** 95 * Current lock; only gets to this namespace are allowed. 96 * @type string 97 */ 98 private $lock; 99 100 /** 101 * Constructor 102 * @param HTMLPurifier_ConfigSchema $definition ConfigSchema that defines 103 * what directives are allowed. 104 * @param HTMLPurifier_PropertyList $parent 105 */ 106 public function __construct($definition, $parent = null) 107 { 108 $parent = $parent ? $parent : $definition->defaultPlist; 109 $this->plist = new HTMLPurifier_PropertyList($parent); 110 $this->def = $definition; // keep a copy around for checking 111 $this->parser = new HTMLPurifier_VarParser_Flexible(); 112 } 113 114 /** 115 * Convenience constructor that creates a config object based on a mixed var 116 * @param mixed $config Variable that defines the state of the config 117 * object. Can be: a HTMLPurifier_Config() object, 118 * an array of directives based on loadArray(), 119 * or a string filename of an ini file. 120 * @param HTMLPurifier_ConfigSchema $schema Schema object 121 * @return HTMLPurifier_Config Configured object 122 */ 123 public static function create($config, $schema = null) 124 { 125 if ($config instanceof HTMLPurifier_Config) { 126 // pass-through 127 return $config; 128 } 129 if (!$schema) { 130 $ret = HTMLPurifier_Config::createDefault(); 131 } else { 132 $ret = new HTMLPurifier_Config($schema); 133 } 134 if (is_string($config)) { 135 $ret->loadIni($config); 136 } elseif (is_array($config)) $ret->loadArray($config); 137 return $ret; 138 } 139 140 /** 141 * Creates a new config object that inherits from a previous one. 142 * @param HTMLPurifier_Config $config Configuration object to inherit from. 143 * @return HTMLPurifier_Config object with $config as its parent. 144 */ 145 public static function inherit(HTMLPurifier_Config $config) 146 { 147 return new HTMLPurifier_Config($config->def, $config->plist); 148 } 149 150 /** 151 * Convenience constructor that creates a default configuration object. 152 * @return HTMLPurifier_Config default object. 153 */ 154 public static function createDefault() 155 { 156 $definition = HTMLPurifier_ConfigSchema::instance(); 157 $config = new HTMLPurifier_Config($definition); 158 return $config; 159 } 160 161 /** 162 * Retrieves a value from the configuration. 163 * 164 * @param string $key String key 165 * @param mixed $a 166 * 167 * @return mixed 168 */ 169 public function get($key, $a = null) 170 { 171 if ($a !== null) { 172 $this->triggerError( 173 "Using deprecated API: use \$config->get('$key.$a') instead", 174 E_USER_WARNING 175 ); 176 $key = "$key.$a"; 177 } 178 if (!$this->finalized) { 179 $this->autoFinalize(); 180 } 181 if (!isset($this->def->info[$key])) { 182 // can't add % due to SimpleTest bug 183 $this->triggerError( 184 'Cannot retrieve value of undefined directive ' . htmlspecialchars($key), 185 E_USER_WARNING 186 ); 187 return; 188 } 189 if (isset($this->def->info[$key]->isAlias)) { 190 $d = $this->def->info[$key]; 191 $this->triggerError( 192 'Cannot get value from aliased directive, use real name ' . $d->key, 193 E_USER_ERROR 194 ); 195 return; 196 } 197 if ($this->lock) { 198 list($ns) = explode('.', $key); 199 if ($ns !== $this->lock) { 200 $this->triggerError( 201 'Cannot get value of namespace ' . $ns . ' when lock for ' . 202 $this->lock . 203 ' is active, this probably indicates a Definition setup method ' . 204 'is accessing directives that are not within its namespace', 205 E_USER_ERROR 206 ); 207 return; 208 } 209 } 210 return $this->plist->get($key); 211 } 212 213 /** 214 * Retrieves an array of directives to values from a given namespace 215 * 216 * @param string $namespace String namespace 217 * 218 * @return array 219 */ 220 public function getBatch($namespace) 221 { 222 if (!$this->finalized) { 223 $this->autoFinalize(); 224 } 225 $full = $this->getAll(); 226 if (!isset($full[$namespace])) { 227 $this->triggerError( 228 'Cannot retrieve undefined namespace ' . 229 htmlspecialchars($namespace), 230 E_USER_WARNING 231 ); 232 return; 233 } 234 return $full[$namespace]; 235 } 236 237 /** 238 * Returns a SHA-1 signature of a segment of the configuration object 239 * that uniquely identifies that particular configuration 240 * 241 * @param string $namespace Namespace to get serial for 242 * 243 * @return string 244 * @note Revision is handled specially and is removed from the batch 245 * before processing! 246 */ 247 public function getBatchSerial($namespace) 248 { 249 if (empty($this->serials[$namespace])) { 250 $batch = $this->getBatch($namespace); 251 unset($batch['DefinitionRev']); 252 $this->serials[$namespace] = sha1(serialize($batch)); 253 } 254 return $this->serials[$namespace]; 255 } 256 257 /** 258 * Returns a SHA-1 signature for the entire configuration object 259 * that uniquely identifies that particular configuration 260 * 261 * @return string 262 */ 263 public function getSerial() 264 { 265 if (empty($this->serial)) { 266 $this->serial = sha1(serialize($this->getAll())); 267 } 268 return $this->serial; 269 } 270 271 /** 272 * Retrieves all directives, organized by namespace 273 * 274 * @warning This is a pretty inefficient function, avoid if you can 275 */ 276 public function getAll() 277 { 278 if (!$this->finalized) { 279 $this->autoFinalize(); 280 } 281 $ret = array(); 282 foreach ($this->plist->squash() as $name => $value) { 283 list($ns, $key) = explode('.', $name, 2); 284 $ret[$ns][$key] = $value; 285 } 286 return $ret; 287 } 288 289 /** 290 * Sets a value to configuration. 291 * 292 * @param string $key key 293 * @param mixed $value value 294 * @param mixed $a 295 */ 296 public function set($key, $value, $a = null) 297 { 298 if (strpos($key, '.') === false) { 299 $namespace = $key; 300 $directive = $value; 301 $value = $a; 302 $key = "$key.$directive"; 303 $this->triggerError("Using deprecated API: use \$config->set('$key', ...) instead", E_USER_NOTICE); 304 } else { 305 list($namespace) = explode('.', $key); 306 } 307 if ($this->isFinalized('Cannot set directive after finalization')) { 308 return; 309 } 310 if (!isset($this->def->info[$key])) { 311 $this->triggerError( 312 'Cannot set undefined directive ' . htmlspecialchars($key) . ' to value', 313 E_USER_WARNING 314 ); 315 return; 316 } 317 $def = $this->def->info[$key]; 318 319 if (isset($def->isAlias)) { 320 if ($this->aliasMode) { 321 $this->triggerError( 322 'Double-aliases not allowed, please fix '. 323 'ConfigSchema bug with' . $key, 324 E_USER_ERROR 325 ); 326 return; 327 } 328 $this->aliasMode = true; 329 $this->set($def->key, $value); 330 $this->aliasMode = false; 331 $this->triggerError("$key is an alias, preferred directive name is {$def->key}", E_USER_NOTICE); 332 return; 333 } 334 335 // Raw type might be negative when using the fully optimized form 336 // of stdclass, which indicates allow_null == true 337 $rtype = is_int($def) ? $def : $def->type; 338 if ($rtype < 0) { 339 $type = -$rtype; 340 $allow_null = true; 341 } else { 342 $type = $rtype; 343 $allow_null = isset($def->allow_null); 344 } 345 346 try { 347 $value = $this->parser->parse($value, $type, $allow_null); 348 } catch (HTMLPurifier_VarParserException $e) { 349 $this->triggerError( 350 'Value for ' . $key . ' is of invalid type, should be ' . 351 HTMLPurifier_VarParser::getTypeName($type), 352 E_USER_WARNING 353 ); 354 return; 355 } 356 if (is_string($value) && is_object($def)) { 357 // resolve value alias if defined 358 if (isset($def->aliases[$value])) { 359 $value = $def->aliases[$value]; 360 } 361 // check to see if the value is allowed 362 if (isset($def->allowed) && !isset($def->allowed[$value])) { 363 $this->triggerError( 364 'Value not supported, valid values are: ' . 365 $this->_listify($def->allowed), 366 E_USER_WARNING 367 ); 368 return; 369 } 370 } 371 $this->plist->set($key, $value); 372 373 // reset definitions if the directives they depend on changed 374 // this is a very costly process, so it's discouraged 375 // with finalization 376 if ($namespace == 'HTML' || $namespace == 'CSS' || $namespace == 'URI') { 377 $this->definitions[$namespace] = null; 378 } 379 380 $this->serials[$namespace] = false; 381 } 382 383 /** 384 * Convenience function for error reporting 385 * 386 * @param array $lookup 387 * 388 * @return string 389 */ 390 private function _listify($lookup) 391 { 392 $list = array(); 393 foreach ($lookup as $name => $b) { 394 $list[] = $name; 395 } 396 return implode(', ', $list); 397 } 398 399 /** 400 * Retrieves object reference to the HTML definition. 401 * 402 * @param bool $raw Return a copy that has not been setup yet. Must be 403 * called before it's been setup, otherwise won't work. 404 * @param bool $optimized If true, this method may return null, to 405 * indicate that a cached version of the modified 406 * definition object is available and no further edits 407 * are necessary. Consider using 408 * maybeGetRawHTMLDefinition, which is more explicitly 409 * named, instead. 410 * 411 * @return HTMLPurifier_HTMLDefinition 412 */ 413 public function getHTMLDefinition($raw = false, $optimized = false) 414 { 415 return $this->getDefinition('HTML', $raw, $optimized); 416 } 417 418 /** 419 * Retrieves object reference to the CSS definition 420 * 421 * @param bool $raw Return a copy that has not been setup yet. Must be 422 * called before it's been setup, otherwise won't work. 423 * @param bool $optimized If true, this method may return null, to 424 * indicate that a cached version of the modified 425 * definition object is available and no further edits 426 * are necessary. Consider using 427 * maybeGetRawCSSDefinition, which is more explicitly 428 * named, instead. 429 * 430 * @return HTMLPurifier_CSSDefinition 431 */ 432 public function getCSSDefinition($raw = false, $optimized = false) 433 { 434 return $this->getDefinition('CSS', $raw, $optimized); 435 } 436 437 /** 438 * Retrieves object reference to the URI definition 439 * 440 * @param bool $raw Return a copy that has not been setup yet. Must be 441 * called before it's been setup, otherwise won't work. 442 * @param bool $optimized If true, this method may return null, to 443 * indicate that a cached version of the modified 444 * definition object is available and no further edits 445 * are necessary. Consider using 446 * maybeGetRawURIDefinition, which is more explicitly 447 * named, instead. 448 * 449 * @return HTMLPurifier_URIDefinition 450 */ 451 public function getURIDefinition($raw = false, $optimized = false) 452 { 453 return $this->getDefinition('URI', $raw, $optimized); 454 } 455 456 /** 457 * Retrieves a definition 458 * 459 * @param string $type Type of definition: HTML, CSS, etc 460 * @param bool $raw Whether or not definition should be returned raw 461 * @param bool $optimized Only has an effect when $raw is true. Whether 462 * or not to return null if the result is already present in 463 * the cache. This is off by default for backwards 464 * compatibility reasons, but you need to do things this 465 * way in order to ensure that caching is done properly. 466 * Check out enduser-customize.html for more details. 467 * We probably won't ever change this default, as much as the 468 * maybe semantics is the "right thing to do." 469 * 470 * @throws HTMLPurifier_Exception 471 * @return HTMLPurifier_Definition 472 */ 473 public function getDefinition($type, $raw = false, $optimized = false) 474 { 475 if ($optimized && !$raw) { 476 throw new HTMLPurifier_Exception("Cannot set optimized = true when raw = false"); 477 } 478 if (!$this->finalized) { 479 $this->autoFinalize(); 480 } 481 // temporarily suspend locks, so we can handle recursive definition calls 482 $lock = $this->lock; 483 $this->lock = null; 484 $factory = HTMLPurifier_DefinitionCacheFactory::instance(); 485 $cache = $factory->create($type, $this); 486 $this->lock = $lock; 487 if (!$raw) { 488 // full definition 489 // --------------- 490 // check if definition is in memory 491 if (!empty($this->definitions[$type])) { 492 $def = $this->definitions[$type]; 493 // check if the definition is setup 494 if ($def->setup) { 495 return $def; 496 } else { 497 $def->setup($this); 498 if ($def->optimized) { 499 $cache->add($def, $this); 500 } 501 return $def; 502 } 503 } 504 // check if definition is in cache 505 $def = $cache->get($this); 506 if ($def) { 507 // definition in cache, save to memory and return it 508 $this->definitions[$type] = $def; 509 return $def; 510 } 511 // initialize it 512 $def = $this->initDefinition($type); 513 // set it up 514 $this->lock = $type; 515 $def->setup($this); 516 $this->lock = null; 517 // save in cache 518 $cache->add($def, $this); 519 // return it 520 return $def; 521 } else { 522 // raw definition 523 // -------------- 524 // check preconditions 525 $def = null; 526 if ($optimized) { 527 if (is_null($this->get($type . '.DefinitionID'))) { 528 // fatally error out if definition ID not set 529 throw new HTMLPurifier_Exception( 530 "Cannot retrieve raw version without specifying %$type.DefinitionID" 531 ); 532 } 533 } 534 if (!empty($this->definitions[$type])) { 535 $def = $this->definitions[$type]; 536 if ($def->setup && !$optimized) { 537 $extra = $this->chatty ? 538 " (try moving this code block earlier in your initialization)" : 539 ""; 540 throw new HTMLPurifier_Exception( 541 "Cannot retrieve raw definition after it has already been setup" . 542 $extra 543 ); 544 } 545 if ($def->optimized === null) { 546 $extra = $this->chatty ? " (try flushing your cache)" : ""; 547 throw new HTMLPurifier_Exception( 548 "Optimization status of definition is unknown" . $extra 549 ); 550 } 551 if ($def->optimized !== $optimized) { 552 $msg = $optimized ? "optimized" : "unoptimized"; 553 $extra = $this->chatty ? 554 " (this backtrace is for the first inconsistent call, which was for a $msg raw definition)" 555 : ""; 556 throw new HTMLPurifier_Exception( 557 "Inconsistent use of optimized and unoptimized raw definition retrievals" . $extra 558 ); 559 } 560 } 561 // check if definition was in memory 562 if ($def) { 563 if ($def->setup) { 564 // invariant: $optimized === true (checked above) 565 return null; 566 } else { 567 return $def; 568 } 569 } 570 // if optimized, check if definition was in cache 571 // (because we do the memory check first, this formulation 572 // is prone to cache slamming, but I think 573 // guaranteeing that either /all/ of the raw 574 // setup code or /none/ of it is run is more important.) 575 if ($optimized) { 576 // This code path only gets run once; once we put 577 // something in $definitions (which is guaranteed by the 578 // trailing code), we always short-circuit above. 579 $def = $cache->get($this); 580 if ($def) { 581 // save the full definition for later, but don't 582 // return it yet 583 $this->definitions[$type] = $def; 584 return null; 585 } 586 } 587 // check invariants for creation 588 if (!$optimized) { 589 if (!is_null($this->get($type . '.DefinitionID'))) { 590 if ($this->chatty) { 591 $this->triggerError( 592 'Due to a documentation error in previous version of HTML Purifier, your ' . 593 'definitions are not being cached. If this is OK, you can remove the ' . 594 '%$type.DefinitionRev and %$type.DefinitionID declaration. Otherwise, ' . 595 'modify your code to use maybeGetRawDefinition, and test if the returned ' . 596 'value is null before making any edits (if it is null, that means that a ' . 597 'cached version is available, and no raw operations are necessary). See ' . 598 '<a href="http://htmlpurifier.org/docs/enduser-customize.html#optimized">' . 599 'Customize</a> for more details', 600 E_USER_WARNING 601 ); 602 } else { 603 $this->triggerError( 604 "Useless DefinitionID declaration", 605 E_USER_WARNING 606 ); 607 } 608 } 609 } 610 // initialize it 611 $def = $this->initDefinition($type); 612 $def->optimized = $optimized; 613 return $def; 614 } 615 throw new HTMLPurifier_Exception("The impossible happened!"); 616 } 617 618 /** 619 * Initialise definition 620 * 621 * @param string $type What type of definition to create 622 * 623 * @return HTMLPurifier_CSSDefinition|HTMLPurifier_HTMLDefinition|HTMLPurifier_URIDefinition 624 * @throws HTMLPurifier_Exception 625 */ 626 private function initDefinition($type) 627 { 628 // quick checks failed, let's create the object 629 if ($type == 'HTML') { 630 $def = new HTMLPurifier_HTMLDefinition(); 631 } elseif ($type == 'CSS') { 632 $def = new HTMLPurifier_CSSDefinition(); 633 } elseif ($type == 'URI') { 634 $def = new HTMLPurifier_URIDefinition(); 635 } else { 636 throw new HTMLPurifier_Exception( 637 "Definition of $type type not supported" 638 ); 639 } 640 $this->definitions[$type] = $def; 641 return $def; 642 } 643 644 public function maybeGetRawDefinition($name) 645 { 646 return $this->getDefinition($name, true, true); 647 } 648 649 public function maybeGetRawHTMLDefinition() 650 { 651 return $this->getDefinition('HTML', true, true); 652 } 653 654 public function maybeGetRawCSSDefinition() 655 { 656 return $this->getDefinition('CSS', true, true); 657 } 658 659 public function maybeGetRawURIDefinition() 660 { 661 return $this->getDefinition('URI', true, true); 662 } 663 664 /** 665 * Loads configuration values from an array with the following structure: 666 * Namespace.Directive => Value 667 * 668 * @param array $config_array Configuration associative array 669 */ 670 public function loadArray($config_array) 671 { 672 if ($this->isFinalized('Cannot load directives after finalization')) { 673 return; 674 } 675 foreach ($config_array as $key => $value) { 676 $key = str_replace('_', '.', $key); 677 if (strpos($key, '.') !== false) { 678 $this->set($key, $value); 679 } else { 680 $namespace = $key; 681 $namespace_values = $value; 682 foreach ($namespace_values as $directive => $value2) { 683 $this->set($namespace .'.'. $directive, $value2); 684 } 685 } 686 } 687 } 688 689 /** 690 * Returns a list of array(namespace, directive) for all directives 691 * that are allowed in a web-form context as per an allowed 692 * namespaces/directives list. 693 * 694 * @param array $allowed List of allowed namespaces/directives 695 * @param HTMLPurifier_ConfigSchema $schema Schema to use, if not global copy 696 * 697 * @return array 698 */ 699 public static function getAllowedDirectivesForForm($allowed, $schema = null) 700 { 701 if (!$schema) { 702 $schema = HTMLPurifier_ConfigSchema::instance(); 703 } 704 if ($allowed !== true) { 705 if (is_string($allowed)) { 706 $allowed = array($allowed); 707 } 708 $allowed_ns = array(); 709 $allowed_directives = array(); 710 $blacklisted_directives = array(); 711 foreach ($allowed as $ns_or_directive) { 712 if (strpos($ns_or_directive, '.') !== false) { 713 // directive 714 if ($ns_or_directive[0] == '-') { 715 $blacklisted_directives[substr($ns_or_directive, 1)] = true; 716 } else { 717 $allowed_directives[$ns_or_directive] = true; 718 } 719 } else { 720 // namespace 721 $allowed_ns[$ns_or_directive] = true; 722 } 723 } 724 } 725 $ret = array(); 726 foreach ($schema->info as $key => $def) { 727 list($ns, $directive) = explode('.', $key, 2); 728 if ($allowed !== true) { 729 if (isset($blacklisted_directives["$ns.$directive"])) { 730 continue; 731 } 732 if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) { 733 continue; 734 } 735 } 736 if (isset($def->isAlias)) { 737 continue; 738 } 739 if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') { 740 continue; 741 } 742 $ret[] = array($ns, $directive); 743 } 744 return $ret; 745 } 746 747 /** 748 * Loads configuration values from $_GET/$_POST that were posted 749 * via ConfigForm 750 * 751 * @param array $array $_GET or $_POST array to import 752 * @param string|bool $index Index/name that the config variables are in 753 * @param array|bool $allowed List of allowed namespaces/directives 754 * @param bool $mq_fix Boolean whether or not to enable magic quotes fix 755 * @param HTMLPurifier_ConfigSchema $schema Schema to use, if not global copy 756 * 757 * @return mixed 758 */ 759 public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) 760 { 761 $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema); 762 $config = HTMLPurifier_Config::create($ret, $schema); 763 return $config; 764 } 765 766 /** 767 * Merges in configuration values from $_GET/$_POST to object. NOT STATIC. 768 * 769 * @param array $array $_GET or $_POST array to import 770 * @param string|bool $index Index/name that the config variables are in 771 * @param array|bool $allowed List of allowed namespaces/directives 772 * @param bool $mq_fix Boolean whether or not to enable magic quotes fix 773 */ 774 public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true) 775 { 776 $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def); 777 $this->loadArray($ret); 778 } 779 780 /** 781 * Prepares an array from a form into something usable for the more 782 * strict parts of HTMLPurifier_Config 783 * 784 * @param array $array $_GET or $_POST array to import 785 * @param string|bool $index Index/name that the config variables are in 786 * @param array|bool $allowed List of allowed namespaces/directives 787 * @param bool $mq_fix Boolean whether or not to enable magic quotes fix 788 * @param HTMLPurifier_ConfigSchema $schema Schema to use, if not global copy 789 * 790 * @return array 791 */ 792 public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) 793 { 794 if ($index !== false) { 795 $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array(); 796 } 797 $mq = $mq_fix && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc(); 798 799 $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema); 800 $ret = array(); 801 foreach ($allowed as $key) { 802 list($ns, $directive) = $key; 803 $skey = "$ns.$directive"; 804 if (!empty($array["Null_$skey"])) { 805 $ret[$ns][$directive] = null; 806 continue; 807 } 808 if (!isset($array[$skey])) { 809 continue; 810 } 811 $value = $mq ? stripslashes($array[$skey]) : $array[$skey]; 812 $ret[$ns][$directive] = $value; 813 } 814 return $ret; 815 } 816 817 /** 818 * Loads configuration values from an ini file 819 * 820 * @param string $filename Name of ini file 821 */ 822 public function loadIni($filename) 823 { 824 if ($this->isFinalized('Cannot load directives after finalization')) { 825 return; 826 } 827 $array = parse_ini_file($filename, true); 828 $this->loadArray($array); 829 } 830 831 /** 832 * Checks whether or not the configuration object is finalized. 833 * 834 * @param string|bool $error String error message, or false for no error 835 * 836 * @return bool 837 */ 838 public function isFinalized($error = false) 839 { 840 if ($this->finalized && $error) { 841 $this->triggerError($error, E_USER_ERROR); 842 } 843 return $this->finalized; 844 } 845 846 /** 847 * Finalizes configuration only if auto finalize is on and not 848 * already finalized 849 */ 850 public function autoFinalize() 851 { 852 if ($this->autoFinalize) { 853 $this->finalize(); 854 } else { 855 $this->plist->squash(true); 856 } 857 } 858 859 /** 860 * Finalizes a configuration object, prohibiting further change 861 */ 862 public function finalize() 863 { 864 $this->finalized = true; 865 $this->parser = null; 866 } 867 868 /** 869 * Produces a nicely formatted error message by supplying the 870 * stack frame information OUTSIDE of HTMLPurifier_Config. 871 * 872 * @param string $msg An error message 873 * @param int $no An error number 874 */ 875 protected function triggerError($msg, $no) 876 { 877 // determine previous stack frame 878 $extra = ''; 879 if ($this->chatty) { 880 $trace = debug_backtrace(); 881 // zip(tail(trace), trace) -- but PHP is not Haskell har har 882 for ($i = 0, $c = count($trace); $i < $c - 1; $i++) { 883 // XXX this is not correct on some versions of HTML Purifier 884 if ($trace[$i + 1]['class'] === 'HTMLPurifier_Config') { 885 continue; 886 } 887 $frame = $trace[$i]; 888 $extra = " invoked on line {$frame['line']} in file {$frame['file']}"; 889 break; 890 } 891 } 892 trigger_error($msg . $extra, $no); 893 } 894 895 /** 896 * Returns a serialized form of the configuration object that can 897 * be reconstituted. 898 * 899 * @return string 900 */ 901 public function serialize() 902 { 903 $this->getDefinition('HTML'); 904 $this->getDefinition('CSS'); 905 $this->getDefinition('URI'); 906 return serialize($this); 907 } 908 909 } 910 911 // vim: et sw=4 sts=4
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |