[ Index ]

PHP Cross Reference of vtigercrm-6.1.0

title

Body

[close]

/libraries/htmlpurifier/library/HTMLPurifier/ -> Config.php (source)

   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


Generated: Fri Nov 28 20:08:37 2014 Cross-referenced by PHPXref 0.7.1