library/HTMLPurifier/Config.php

Go to the documentation of this file.
00001 <?php
00002 
00017 class HTMLPurifier_Config
00018 {
00019     
00023     public $version = '3.1.1';
00024     
00029     public $autoFinalize = true;
00030     
00031     // protected member variables
00032     
00037     protected $serials = array();
00038     
00042     protected $serial;
00043     
00047     protected $conf;
00048     
00052     protected $parser;
00053     
00059     public $def;
00060     
00064     protected $definitions;
00065     
00069     protected $finalized = false;
00070     
00075     public function __construct($definition) {
00076         $this->conf = $definition->defaults; // set up, copy in defaults
00077         $this->def  = $definition; // keep a copy around for checking
00078         $this->parser = new HTMLPurifier_VarParser_Flexible();
00079     }
00080     
00090     public static function create($config, $schema = null) {
00091         if ($config instanceof HTMLPurifier_Config) {
00092             // pass-through
00093             return $config;
00094         }
00095         if (!$schema) {
00096             $ret = HTMLPurifier_Config::createDefault();
00097         } else {
00098             $ret = new HTMLPurifier_Config($schema);
00099         }
00100         if (is_string($config)) $ret->loadIni($config);
00101         elseif (is_array($config)) $ret->loadArray($config);
00102         return $ret;
00103     }
00104     
00109     public static function createDefault() {
00110         $definition = HTMLPurifier_ConfigSchema::instance();
00111         $config = new HTMLPurifier_Config($definition);
00112         return $config;
00113     }
00114     
00120     public function get($namespace, $key) {
00121         if (!$this->finalized && $this->autoFinalize) $this->finalize();
00122         if (!isset($this->def->info[$namespace][$key])) {
00123             // can't add % due to SimpleTest bug
00124             trigger_error('Cannot retrieve value of undefined directive ' . htmlspecialchars("$namespace.$key"),
00125                 E_USER_WARNING);
00126             return;
00127         }
00128         if (isset($this->def->info[$namespace][$key]->isAlias)) {
00129             $d = $this->def->info[$namespace][$key];
00130             trigger_error('Cannot get value from aliased directive, use real name ' . $d->namespace . '.' . $d->name,
00131                 E_USER_ERROR);
00132             return;
00133         }
00134         return $this->conf[$namespace][$key];
00135     }
00136     
00141     public function getBatch($namespace) {
00142         if (!$this->finalized && $this->autoFinalize) $this->finalize();
00143         if (!isset($this->def->info[$namespace])) {
00144             trigger_error('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace),
00145                 E_USER_WARNING);
00146             return;
00147         }
00148         return $this->conf[$namespace];
00149     }
00150     
00158     public function getBatchSerial($namespace) {
00159         if (empty($this->serials[$namespace])) {
00160             $batch = $this->getBatch($namespace);
00161             unset($batch['DefinitionRev']);
00162             $this->serials[$namespace] = md5(serialize($batch));
00163         }
00164         return $this->serials[$namespace];
00165     }
00166     
00171     public function getSerial() {
00172         if (empty($this->serial)) {
00173             $this->serial = md5(serialize($this->getAll()));
00174         }
00175         return $this->serial;
00176     }
00177     
00181     public function getAll() {
00182         if (!$this->finalized && $this->autoFinalize) $this->finalize();
00183         return $this->conf;
00184     }
00185     
00192     public function set($namespace, $key, $value, $from_alias = false) {
00193         if ($this->isFinalized('Cannot set directive after finalization')) return;
00194         if (!isset($this->def->info[$namespace][$key])) {
00195             trigger_error('Cannot set undefined directive ' . htmlspecialchars("$namespace.$key") . ' to value',
00196                 E_USER_WARNING);
00197             return;
00198         }
00199         $def = $this->def->info[$namespace][$key];
00200         
00201         if (isset($def->isAlias)) {
00202             if ($from_alias) {
00203                 trigger_error('Double-aliases not allowed, please fix '.
00204                     'ConfigSchema bug with' . "$namespace.$key", E_USER_ERROR);
00205                 return;
00206             }
00207             $this->set($new_ns  = $def->namespace,
00208                        $new_dir = $def->name,
00209                        $value, true);
00210             trigger_error("$namespace.$key is an alias, preferred directive name is $new_ns.$new_dir", E_USER_NOTICE);
00211             return;
00212         }
00213         
00214         // Raw type might be negative when using the fully optimized form
00215         // of stdclass, which indicates allow_null == true
00216         $rtype = is_int($def) ? $def : $def->type;
00217         if ($rtype < 0) {
00218             $type = -$rtype;
00219             $allow_null = true;
00220         } else {
00221             $type = $rtype;
00222             $allow_null = isset($def->allow_null);
00223         }
00224         
00225         try {
00226             $value = $this->parser->parse($value, $type, $allow_null);
00227         } catch (HTMLPurifier_VarParserException $e) {
00228             trigger_error('Value for ' . "$namespace.$key" . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING);
00229             return;
00230         }
00231         if (is_string($value) && is_object($def)) {
00232             // resolve value alias if defined
00233             if (isset($def->aliases[$value])) {
00234                 $value = $def->aliases[$value];
00235             }
00236             // check to see if the value is allowed
00237             if (isset($def->allowed) && !isset($def->allowed[$value])) {
00238                 trigger_error('Value not supported, valid values are: ' .
00239                     $this->_listify($def->allowed), E_USER_WARNING);
00240                 return;
00241             }
00242         }
00243         $this->conf[$namespace][$key] = $value;
00244         
00245         // reset definitions if the directives they depend on changed
00246         // this is a very costly process, so it's discouraged 
00247         // with finalization
00248         if ($namespace == 'HTML' || $namespace == 'CSS') {
00249             $this->definitions[$namespace] = null;
00250         }
00251         
00252         $this->serials[$namespace] = false;
00253     }
00254     
00258     private function _listify($lookup) {
00259         $list = array();
00260         foreach ($lookup as $name => $b) $list[] = $name;
00261         return implode(', ', $list);
00262     }
00263     
00269     public function getHTMLDefinition($raw = false) {
00270         return $this->getDefinition('HTML', $raw);
00271     }
00272     
00278     public function getCSSDefinition($raw = false) {
00279         return $this->getDefinition('CSS', $raw);
00280     }
00281     
00287     public function getDefinition($type, $raw = false) {
00288         if (!$this->finalized && $this->autoFinalize) $this->finalize();
00289         $factory = HTMLPurifier_DefinitionCacheFactory::instance();
00290         $cache = $factory->create($type, $this);
00291         if (!$raw) {
00292             // see if we can quickly supply a definition
00293             if (!empty($this->definitions[$type])) {
00294                 if (!$this->definitions[$type]->setup) {
00295                     $this->definitions[$type]->setup($this);
00296                     $cache->set($this->definitions[$type], $this);
00297                 }
00298                 return $this->definitions[$type];
00299             }
00300             // memory check missed, try cache
00301             $this->definitions[$type] = $cache->get($this);
00302             if ($this->definitions[$type]) {
00303                 // definition in cache, return it
00304                 return $this->definitions[$type];
00305             }
00306         } elseif (
00307             !empty($this->definitions[$type]) &&
00308             !$this->definitions[$type]->setup
00309         ) {
00310             // raw requested, raw in memory, quick return
00311             return $this->definitions[$type];
00312         }
00313         // quick checks failed, let's create the object
00314         if ($type == 'HTML') {
00315             $this->definitions[$type] = new HTMLPurifier_HTMLDefinition();
00316         } elseif ($type == 'CSS') {
00317             $this->definitions[$type] = new HTMLPurifier_CSSDefinition();
00318         } elseif ($type == 'URI') {
00319             $this->definitions[$type] = new HTMLPurifier_URIDefinition();
00320         } else {
00321             throw new HTMLPurifier_Exception("Definition of $type type not supported");
00322         }
00323         // quick abort if raw
00324         if ($raw) {
00325             if (is_null($this->get($type, 'DefinitionID'))) {
00326                 // fatally error out if definition ID not set
00327                 throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID");
00328             }
00329             return $this->definitions[$type];
00330         }
00331         // set it up
00332         $this->definitions[$type]->setup($this);
00333         // save in cache
00334         $cache->set($this->definitions[$type], $this);
00335         return $this->definitions[$type];
00336     }
00337     
00343     public function loadArray($config_array) {
00344         if ($this->isFinalized('Cannot load directives after finalization')) return;
00345         foreach ($config_array as $key => $value) {
00346             $key = str_replace('_', '.', $key);
00347             if (strpos($key, '.') !== false) {
00348                 // condensed form
00349                 list($namespace, $directive) = explode('.', $key);
00350                 $this->set($namespace, $directive, $value);
00351             } else {
00352                 $namespace = $key;
00353                 $namespace_values = $value;
00354                 foreach ($namespace_values as $directive => $value) {
00355                     $this->set($namespace, $directive, $value);
00356                 }
00357             }
00358         }
00359     }
00360     
00367     public static function getAllowedDirectivesForForm($allowed, $schema = null) {
00368         if (!$schema) {
00369             $schema = HTMLPurifier_ConfigSchema::instance();
00370         }
00371         if ($allowed !== true) {
00372              if (is_string($allowed)) $allowed = array($allowed);
00373              $allowed_ns = array();
00374              $allowed_directives = array();
00375              $blacklisted_directives = array();
00376              foreach ($allowed as $ns_or_directive) {
00377                  if (strpos($ns_or_directive, '.') !== false) {
00378                      // directive
00379                      if ($ns_or_directive[0] == '-') {
00380                          $blacklisted_directives[substr($ns_or_directive, 1)] = true;
00381                      } else {
00382                          $allowed_directives[$ns_or_directive] = true;
00383                      }
00384                  } else {
00385                      // namespace
00386                      $allowed_ns[$ns_or_directive] = true;
00387                  }
00388              }
00389         }
00390         $ret = array();
00391         foreach ($schema->info as $ns => $keypairs) {
00392             foreach ($keypairs as $directive => $def) {
00393                 if ($allowed !== true) {
00394                     if (isset($blacklisted_directives["$ns.$directive"])) continue;
00395                     if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue;
00396                 }
00397                 if (isset($def->isAlias)) continue;
00398                 if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue;
00399                 $ret[] = array($ns, $directive);
00400             }
00401         }
00402         return $ret;
00403     }
00404     
00414     public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) {
00415         $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema);
00416         $config = HTMLPurifier_Config::create($ret, $schema);
00417         return $config;
00418     }
00419     
00424     public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true) {
00425          $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def);
00426          $this->loadArray($ret);
00427     }
00428     
00433     public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) {
00434         if ($index !== false) $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
00435         $mq = $mq_fix && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc();
00436         
00437         $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema);
00438         $ret = array();
00439         foreach ($allowed as $key) {
00440             list($ns, $directive) = $key;
00441             $skey = "$ns.$directive";
00442             if (!empty($array["Null_$skey"])) {
00443                 $ret[$ns][$directive] = null;
00444                 continue;
00445             }
00446             if (!isset($array[$skey])) continue;
00447             $value = $mq ? stripslashes($array[$skey]) : $array[$skey];
00448             $ret[$ns][$directive] = $value;
00449         }
00450         return $ret;
00451     }
00452     
00457     public function loadIni($filename) {
00458         if ($this->isFinalized('Cannot load directives after finalization')) return;
00459         $array = parse_ini_file($filename, true);
00460         $this->loadArray($array);
00461     }
00462     
00467     public function isFinalized($error = false) {
00468         if ($this->finalized && $error) {
00469             trigger_error($error, E_USER_ERROR);
00470         }
00471         return $this->finalized;
00472     }
00473     
00478     public function autoFinalize() {
00479         if (!$this->finalized && $this->autoFinalize) $this->finalize();
00480     }
00481     
00485     public function finalize() {
00486         $this->finalized = true;
00487     }
00488     
00489 }
00490 
00491 
00492 

Generated on Thu Jun 19 18:47:26 2008 for HTMLPurifier by  doxygen 1.5.3