[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/htmlpurifier/HTMLPurifier/ -> Config.php (source)

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


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7