ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Config.php
Go to the documentation of this file.
1 <?php
2 
18 {
19 
24  public $version = '4.13.0';
25 
31  public $autoFinalize = true;
32 
33  // protected member variables
34 
40  protected $serials = array();
41 
46  protected $serial;
47 
52  protected $parser = null;
53 
60  public $def;
61 
66  protected $definitions;
67 
72  protected $finalized = false;
73 
78  protected $plist;
79 
84  private $aliasMode;
85 
92  public $chatty = true;
93 
98  private $lock;
99 
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 
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) {
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 
145  public static function inherit(HTMLPurifier_Config $config)
146  {
147  return new HTMLPurifier_Config($config->def, $config->plist);
148  }
149 
154  public static function createDefault()
155  {
156  $definition = HTMLPurifier_ConfigSchema::instance();
157  $config = new HTMLPurifier_Config($definition);
158  return $config;
159  }
160 
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 
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 
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 
263  public function getSerial()
264  {
265  if (empty($this->serial)) {
266  $this->serial = sha1(serialize($this->getAll()));
267  }
268  return $this->serial;
269  }
270 
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 
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 ' .
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 
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 
413  public function getHTMLDefinition($raw = false, $optimized = false)
414  {
415  return $this->getDefinition('HTML', $raw, $optimized);
416  }
417 
432  public function getCSSDefinition($raw = false, $optimized = false)
433  {
434  return $this->getDefinition('CSS', $raw, $optimized);
435  }
436 
451  public function getURIDefinition($raw = false, $optimized = false)
452  {
453  return $this->getDefinition('URI', $raw, $optimized);
454  }
455 
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;
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 
626  private function initDefinition($type)
627  {
628  // quick checks failed, let's create the object
629  if ($type == 'HTML') {
631  } elseif ($type == 'CSS') {
633  } elseif ($type == 'URI') {
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 
652  public function maybeGetRawHTMLDefinition()
653  {
654  return $this->getDefinition('HTML', true, true);
655  }
656 
660  public function maybeGetRawCSSDefinition()
661  {
662  return $this->getDefinition('CSS', true, true);
663  }
664 
668  public function maybeGetRawURIDefinition()
669  {
670  return $this->getDefinition('URI', true, true);
671  }
672 
679  public function loadArray($config_array)
680  {
681  if ($this->isFinalized('Cannot load directives after finalization')) {
682  return;
683  }
684  foreach ($config_array as $key => $value) {
685  $key = str_replace('_', '.', $key);
686  if (strpos($key, '.') !== false) {
687  $this->set($key, $value);
688  } else {
689  $namespace = $key;
690  $namespace_values = $value;
691  foreach ($namespace_values as $directive => $value2) {
692  $this->set($namespace .'.'. $directive, $value2);
693  }
694  }
695  }
696  }
697 
708  public static function getAllowedDirectivesForForm($allowed, $schema = null)
709  {
710  if (!$schema) {
712  }
713  if ($allowed !== true) {
714  if (is_string($allowed)) {
715  $allowed = array($allowed);
716  }
717  $allowed_ns = array();
718  $allowed_directives = array();
719  $blacklisted_directives = array();
720  foreach ($allowed as $ns_or_directive) {
721  if (strpos($ns_or_directive, '.') !== false) {
722  // directive
723  if ($ns_or_directive[0] == '-') {
724  $blacklisted_directives[substr($ns_or_directive, 1)] = true;
725  } else {
726  $allowed_directives[$ns_or_directive] = true;
727  }
728  } else {
729  // namespace
730  $allowed_ns[$ns_or_directive] = true;
731  }
732  }
733  }
734  $ret = array();
735  foreach ($schema->info as $key => $def) {
736  list($ns, $directive) = explode('.', $key, 2);
737  if ($allowed !== true) {
738  if (isset($blacklisted_directives["$ns.$directive"])) {
739  continue;
740  }
741  if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) {
742  continue;
743  }
744  }
745  if (isset($def->isAlias)) {
746  continue;
747  }
748  if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') {
749  continue;
750  }
751  $ret[] = array($ns, $directive);
752  }
753  return $ret;
754  }
755 
768  public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null)
769  {
770  $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema);
772  return $config;
773  }
774 
783  public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true)
784  {
785  $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def);
786  $this->loadArray($ret);
787  }
788 
801  public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null)
802  {
803  if ($index !== false) {
804  $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
805  }
806  $mq = $mq_fix && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc();
807 
808  $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema);
809  $ret = array();
810  foreach ($allowed as $key) {
811  list($ns, $directive) = $key;
812  $skey = "$ns.$directive";
813  if (!empty($array["Null_$skey"])) {
814  $ret[$ns][$directive] = null;
815  continue;
816  }
817  if (!isset($array[$skey])) {
818  continue;
819  }
820  $value = $mq ? stripslashes($array[$skey]) : $array[$skey];
821  $ret[$ns][$directive] = $value;
822  }
823  return $ret;
824  }
825 
831  public function loadIni($filename)
832  {
833  if ($this->isFinalized('Cannot load directives after finalization')) {
834  return;
835  }
836  $array = parse_ini_file($filename, true);
837  $this->loadArray($array);
838  }
839 
847  public function isFinalized($error = false)
848  {
849  if ($this->finalized && $error) {
850  $this->triggerError($error, E_USER_ERROR);
851  }
852  return $this->finalized;
853  }
854 
859  public function autoFinalize()
860  {
861  if ($this->autoFinalize) {
862  $this->finalize();
863  } else {
864  $this->plist->squash(true);
865  }
866  }
867 
871  public function finalize()
872  {
873  $this->finalized = true;
874  $this->parser = null;
875  }
876 
884  protected function triggerError($msg, $no)
885  {
886  // determine previous stack frame
887  $extra = '';
888  if ($this->chatty) {
889  $trace = debug_backtrace();
890  // zip(tail(trace), trace) -- but PHP is not Haskell har har
891  for ($i = 0, $c = count($trace); $i < $c - 1; $i++) {
892  // XXX this is not correct on some versions of HTML Purifier
893  if (isset($trace[$i + 1]['class']) && $trace[$i + 1]['class'] === 'HTMLPurifier_Config') {
894  continue;
895  }
896  $frame = $trace[$i];
897  $extra = " invoked on line {$frame['line']} in file {$frame['file']}";
898  break;
899  }
900  }
901  trigger_error($msg . $extra, $no);
902  }
903 
910  public function serialize()
911  {
912  $this->getDefinition('HTML');
913  $this->getDefinition('CSS');
914  $this->getDefinition('URI');
915  return serialize($this);
916  }
917 
918 }
919 
920 // vim: et sw=4 sts=4
$chatty
Set to false if you do not want line and file numbers in errors.
Definition: Config.php:92
if($err=$client->getError()) $namespace
static prepareArrayFromForm($array, $index=false, $allowed=true, $mq_fix=true, $schema=null)
Prepares an array from a form into something usable for the more strict parts of HTMLPurifier_Config...
Definition: Config.php:801
Definition of the purified HTML that describes allowed children, attributes, and many other things...
if(isset($_REQUEST['delete'])) $list
Definition: registry.php:41
getDefinition($type, $raw=false, $optimized=false)
Retrieves a definition.
Definition: Config.php:473
isFinalized($error=false)
Checks whether or not the configuration object is finalized.
Definition: Config.php:847
$parser
Parser for variables.
Definition: Config.php:52
$config
Definition: bootstrap.php:15
$type
loadIni($filename)
Loads configuration values from an ini file.
Definition: Config.php:831
getHTMLDefinition($raw=false, $optimized=false)
Retrieves object reference to the HTML definition.
Definition: Config.php:413
__construct($definition, $parent=null)
Constructor.
Definition: Config.php:106
$autoFinalize
Whether or not to automatically finalize the object if a read operation is done.
Definition: Config.php:31
$factory
Definition: metadata.php:43
$lock
Current lock; only gets to this namespace are allowed.
Definition: Config.php:98
$index
Definition: metadata.php:60
Performs safe variable parsing based on types which can be used by users.
Definition: Flexible.php:8
Exception type for HTMLPurifier_VarParser.
static instance($prototype=null)
Retrieves an instance of global definition cache factory.
$serials
Namespace indexed array of serials for specific namespaces.
Definition: Config.php:40
_listify($lookup)
Convenience function for error reporting.
Definition: Config.php:390
static inherit(HTMLPurifier_Config $config)
Creates a new config object that inherits from a previous one.
Definition: Config.php:145
autoFinalize()
Finalizes configuration only if auto finalize is on and not already finalized.
Definition: Config.php:859
getURIDefinition($raw=false, $optimized=false)
Retrieves object reference to the URI definition.
Definition: Config.php:451
$version
HTML Purifier&#39;s version string.
Definition: Config.php:24
loadArray($config_array)
Loads configuration values from an array with the following structure: Namespace.Directive => Value...
Definition: Config.php:679
Generic property list implementation.
Definition: PropertyList.php:6
getBatch($namespace)
Retrieves an array of directives to values from a given namespace.
Definition: Config.php:220
$def
Reference HTMLPurifier_ConfigSchema for value checking.
Definition: Config.php:60
$finalized
Whether or not config is finalized.
Definition: Config.php:72
static create($config, $schema=null)
Convenience constructor that creates a config object based on a mixed var.
Definition: Config.php:123
triggerError($msg, $no)
Produces a nicely formatted error message by supplying the stack frame information OUTSIDE of HTMLPur...
Definition: Config.php:884
getSerial()
Returns a SHA-1 signature for the entire configuration object that uniquely identifies that particula...
Definition: Config.php:263
$serial
Serial for entire configuration object.
Definition: Config.php:46
static createDefault()
Convenience constructor that creates a default configuration object.
Definition: Config.php:154
getAll()
Retrieves all directives, organized by namespace.
Definition: Config.php:276
maybeGetRawDefinition($name)
Definition: Config.php:644
$filename
Definition: buildRTE.php:89
initDefinition($type)
Initialise definition.
Definition: Config.php:626
Global exception class for HTML Purifier; any exceptions we throw are from here.
Definition: Exception.php:7
static loadArrayFromForm($array, $index=false, $allowed=true, $mq_fix=true, $schema=null)
Loads configuration values from $_GET/$_POST that were posted via ConfigForm.
Definition: Config.php:768
Configuration object that triggers customizable behavior.
Definition: Config.php:17
static instance($prototype=null)
Retrieves an instance of the application-wide configuration definition.
$ret
Definition: parser.php:6
$i
Definition: disco.tpl.php:19
getCSSDefinition($raw=false, $optimized=false)
Retrieves object reference to the CSS definition.
Definition: Config.php:432
Defines allowed CSS attributes and what their values are.
finalize()
Finalizes a configuration object, prohibiting further change.
Definition: Config.php:871
$aliasMode
Whether or not a set is taking place due to an alias lookup.
Definition: Config.php:84
$definitions
Indexed array of definitions.
Definition: Config.php:66
getBatchSerial($namespace)
Returns a SHA-1 signature of a segment of the configuration object that uniquely identifies that part...
Definition: Config.php:247
mergeArrayFromForm($array, $index=false, $allowed=true, $mq_fix=true)
Merges in configuration values from $_GET/$_POST to object.
Definition: Config.php:783
static getAllowedDirectivesForForm($allowed, $schema=null)
Returns a list of array(namespace, directive) for all directives that are allowed in a web-form conte...
Definition: Config.php:708
serialize()
Returns a serialized form of the configuration object that can be reconstituted.
Definition: Config.php:910
$plist
Property list containing configuration directives.
Definition: Config.php:78
$key
Definition: croninfo.php:18
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
static getTypeName($type)
Definition: VarParser.php:184