2006-08-04 01:47:48 +00:00
< ? php
2006-08-17 20:29:34 +00:00
/**
2006-08-19 23:06:59 +00:00
* Configuration object that triggers customizable behavior .
*
* @ warning This class is strongly defined : that means that the class
* will fail if an undefined directive is retrieved or set .
2008-12-06 07:28:20 +00:00
*
2006-08-17 20:29:34 +00:00
* @ note Many classes that could ( although many times don ' t ) use the
* configuration object make it a mandatory parameter . This is
* because a configuration object should always be forwarded ,
* otherwise , you run the risk of missing a parameter and then
* being stumped when a configuration directive doesn ' t work .
2008-12-06 07:28:20 +00:00
*
2007-11-25 02:24:39 +00:00
* @ todo Reconsider some of the public member variables
2006-08-17 20:29:34 +00:00
*/
2006-08-04 01:47:48 +00:00
class HTMLPurifier_Config
{
2008-12-06 07:28:20 +00:00
2007-05-27 13:25:54 +00:00
/**
* HTML Purifier ' s version
*/
2013-02-18 00:04:08 +00:00
public $version = '4.5.0' ;
2008-12-06 07:28:20 +00:00
2006-08-19 23:06:59 +00:00
/**
2013-07-16 12:20:01 +00:00
* @ var bool indicator whether or not to automatically finalize
2007-11-25 02:24:39 +00:00
* the object if a read operation is done
2006-08-19 23:06:59 +00:00
*/
2007-11-25 02:24:39 +00:00
public $autoFinalize = true ;
2008-12-06 07:28:20 +00:00
2007-11-25 02:24:39 +00:00
// protected member variables
2008-12-06 07:28:20 +00:00
2006-08-27 18:49:16 +00:00
/**
2007-11-25 02:24:39 +00:00
* Namespace indexed array of serials for specific namespaces ( see
* getSerial () for more info ) .
2006-08-27 18:49:16 +00:00
*/
2007-11-25 02:24:39 +00:00
protected $serials = array ();
2008-12-06 07:28:20 +00:00
2006-08-31 20:33:07 +00:00
/**
2007-11-25 02:24:39 +00:00
* Serial for entire configuration object
2006-08-31 20:33:07 +00:00
*/
2007-11-25 02:24:39 +00:00
protected $serial ;
2008-12-06 07:28:20 +00:00
2008-03-04 15:06:00 +00:00
/**
* Parser for variables
*/
2011-09-22 15:10:12 +00:00
protected $parser = null ;
2008-12-06 07:28:20 +00:00
2007-05-20 18:06:51 +00:00
/**
2007-11-25 02:24:39 +00:00
* Reference HTMLPurifier_ConfigSchema for value checking
* @ note This is public for introspective purposes . Please don ' t
* abuse !
2007-05-20 18:06:51 +00:00
*/
2007-11-25 02:24:39 +00:00
public $def ;
2008-12-06 07:28:20 +00:00
2007-05-29 20:21:33 +00:00
/**
2013-07-16 12:20:01 +00:00
* @ var HTMLPurifier_Definition [] Indexed array of definitions
2007-05-29 20:21:33 +00:00
*/
2007-11-25 02:24:39 +00:00
protected $definitions ;
2008-12-06 07:28:20 +00:00
2007-06-28 23:01:27 +00:00
/**
2007-11-25 02:24:39 +00:00
* Bool indicator whether or not config is finalized
2007-06-28 23:01:27 +00:00
*/
2007-11-25 02:24:39 +00:00
protected $finalized = false ;
2008-12-06 07:28:20 +00:00
2009-02-02 23:42:23 +00:00
/**
* Property list containing configuration directives .
*/
protected $plist ;
2009-02-20 00:17:49 +00:00
/**
* Whether or not a set is taking place due to an
* alias lookup .
*/
private $aliasMode ;
/**
* Set to false if you do not want line and file numbers in errors
2010-12-30 23:51:53 +00:00
* ( useful when unit testing ) . This will also compress some errors
* and exceptions .
2009-02-20 00:17:49 +00:00
*/
public $chatty = true ;
2009-05-26 03:38:49 +00:00
/**
* Current lock ; only gets to this namespace are allowed .
*/
private $lock ;
2006-08-19 23:06:59 +00:00
/**
2013-07-16 12:20:01 +00:00
* Constructor
*
* @ param HTMLPurifier_ConfigSchema $definition ConfigSchema that defines
* what directives are allowed .
* @ param mixed $parent
2006-08-19 23:06:59 +00:00
*/
2013-07-16 12:20:01 +00:00
public function __construct ( $definition , $parent = null )
{
2009-02-20 05:13:09 +00:00
$parent = $parent ? $parent : $definition -> defaultPlist ;
$this -> plist = new HTMLPurifier_PropertyList ( $parent );
2009-02-02 23:42:23 +00:00
$this -> def = $definition ; // keep a copy around for checking
2008-03-05 03:51:09 +00:00
$this -> parser = new HTMLPurifier_VarParser_Flexible ();
2006-08-11 20:23:41 +00:00
}
2008-12-06 07:28:20 +00:00
2006-12-15 02:12:03 +00:00
/**
* Convenience constructor that creates a config object based on a mixed var
2013-07-16 12:20:01 +00:00
*
2006-12-15 02:12:03 +00:00
* @ param mixed $config Variable that defines the state of the config
2007-01-21 14:29:46 +00:00
* object . Can be : a HTMLPurifier_Config () object ,
* an array of directives based on loadArray (),
* or a string filename of an ini file .
2013-07-16 12:20:01 +00:00
* @ param HTMLPurifier_ConfigSchema $schema Schema object
*
* @ return HTMLPurifier_Config Configured object
2006-12-15 02:12:03 +00:00
*/
2013-07-16 12:20:01 +00:00
public static function create ( $config , $schema = null )
{
2007-11-25 02:24:39 +00:00
if ( $config instanceof HTMLPurifier_Config ) {
2007-06-19 01:29:50 +00:00
// pass-through
return $config ;
2007-05-21 01:36:15 +00:00
}
2008-02-16 00:40:30 +00:00
if ( ! $schema ) {
$ret = HTMLPurifier_Config :: createDefault ();
} else {
$ret = new HTMLPurifier_Config ( $schema );
}
2013-07-16 12:20:01 +00:00
if ( is_string ( $config )) {
$ret -> loadIni ( $config );
}
2007-01-21 14:29:46 +00:00
elseif ( is_array ( $config )) $ret -> loadArray ( $config );
2006-12-15 02:12:03 +00:00
return $ret ;
}
2008-12-06 07:28:20 +00:00
2009-02-20 05:13:09 +00:00
/**
* Creates a new config object that inherits from a previous one .
2013-07-16 12:20:01 +00:00
*
2009-02-20 05:13:09 +00:00
* @ param HTMLPurifier_Config $config Configuration object to inherit
* from .
2013-07-16 12:20:01 +00:00
*
2009-02-20 05:13:09 +00:00
* @ return HTMLPurifier_Config object with $config as its parent .
*/
2013-07-16 12:20:01 +00:00
public static function inherit ( HTMLPurifier_Config $config )
{
2009-02-20 05:13:09 +00:00
return new HTMLPurifier_Config ( $config -> def , $config -> plist );
}
2006-08-19 23:06:59 +00:00
/**
* Convenience constructor that creates a default configuration object .
2013-05-18 15:48:47 +00:00
* @ return HTMLPurifier_Config default object .
2006-08-19 23:06:59 +00:00
*/
2013-07-16 12:20:01 +00:00
public static function createDefault ()
{
2008-04-23 02:40:17 +00:00
$definition = HTMLPurifier_ConfigSchema :: instance ();
2006-08-11 20:23:41 +00:00
$config = new HTMLPurifier_Config ( $definition );
2006-08-04 01:47:48 +00:00
return $config ;
}
2008-12-06 07:28:20 +00:00
2006-08-19 23:06:59 +00:00
/**
2013-07-16 12:20:01 +00:00
* Retrieves a value from the configuration .
*
* @ param string $key String key
* @ param mixed $a
*
* @ return mixed
2006-08-19 23:06:59 +00:00
*/
2013-07-16 12:20:01 +00:00
public function get ( $key , $a = null )
{
2009-02-20 00:17:49 +00:00
if ( $a !== null ) {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
" Using deprecated API: use \$ config->get(' $key . $a ') instead " ,
E_USER_WARNING
);
2009-02-20 00:17:49 +00:00
$key = " $key . $a " ;
}
2013-07-16 12:20:01 +00:00
if ( ! $this -> finalized ) {
$this -> autoFinalize ();
}
2009-02-07 07:53:20 +00:00
if ( ! isset ( $this -> def -> info [ $key ])) {
2007-06-16 20:21:00 +00:00
// can't add % due to SimpleTest bug
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Cannot retrieve value of undefined directive ' . htmlspecialchars ( $key ),
E_USER_WARNING
);
2006-08-11 20:23:41 +00:00
return ;
}
2009-02-07 07:53:20 +00:00
if ( isset ( $this -> def -> info [ $key ] -> isAlias )) {
$d = $this -> def -> info [ $key ];
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Cannot get value from aliased directive, use real name ' . $d -> key ,
E_USER_ERROR
);
2007-01-20 18:43:58 +00:00
return ;
}
2009-05-26 03:38:49 +00:00
if ( $this -> lock ) {
list ( $ns ) = explode ( '.' , $key );
if ( $ns !== $this -> lock ) {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Cannot get value of namespace ' . $ns . ' when lock for ' .
$this -> lock . ' is active, this probably indicates a Definition setup method is accessing directives that are not within its namespace' ,
E_USER_ERROR
);
2009-05-26 03:38:49 +00:00
return ;
}
}
2009-02-07 07:53:20 +00:00
return $this -> plist -> get ( $key );
2006-08-11 20:23:41 +00:00
}
2008-12-06 07:28:20 +00:00
2006-11-24 06:26:02 +00:00
/**
2013-07-16 12:20:01 +00:00
* Retrieves an array of directives to values from a given namespace
*
* @ param string $namespace String namespace
*
* @ return array
2006-11-24 06:26:02 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getBatch ( $namespace )
{
if ( ! $this -> finalized ) {
$this -> autoFinalize ();
}
2009-02-07 07:53:20 +00:00
$full = $this -> getAll ();
if ( ! isset ( $full [ $namespace ])) {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Cannot retrieve undefined namespace ' .
htmlspecialchars ( $namespace ),
E_USER_WARNING
);
2006-11-24 06:26:02 +00:00
return ;
}
2009-02-02 23:42:23 +00:00
return $full [ $namespace ];
2006-11-24 06:26:02 +00:00
}
2008-12-06 07:28:20 +00:00
2007-05-29 20:21:33 +00:00
/**
2012-10-27 09:33:22 +00:00
* Returns a SHA - 1 signature of a segment of the configuration object
2007-05-29 20:21:33 +00:00
* that uniquely identifies that particular configuration
2013-07-16 12:20:01 +00:00
*
* @ param string $namespace Namespace to get serial for
*
* @ return string
2007-06-23 14:05:09 +00:00
* @ note Revision is handled specially and is removed from the batch
* before processing !
2007-05-29 20:21:33 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getBatchSerial ( $namespace )
{
2007-05-29 20:21:33 +00:00
if ( empty ( $this -> serials [ $namespace ])) {
2007-06-23 14:05:09 +00:00
$batch = $this -> getBatch ( $namespace );
unset ( $batch [ 'DefinitionRev' ]);
2012-10-27 09:33:22 +00:00
$this -> serials [ $namespace ] = sha1 ( serialize ( $batch ));
2007-05-29 20:21:33 +00:00
}
return $this -> serials [ $namespace ];
}
2008-12-06 07:28:20 +00:00
2007-06-28 23:01:27 +00:00
/**
2012-10-27 09:33:22 +00:00
* Returns a SHA - 1 signature for the entire configuration object
2007-06-28 23:01:27 +00:00
* that uniquely identifies that particular configuration
2013-07-16 12:20:01 +00:00
*
* @ return string
2007-06-28 23:01:27 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getSerial ()
{
2007-06-28 23:01:27 +00:00
if ( empty ( $this -> serial )) {
2012-10-27 09:33:22 +00:00
$this -> serial = sha1 ( serialize ( $this -> getAll ()));
2007-06-28 23:01:27 +00:00
}
return $this -> serial ;
}
2008-12-06 07:28:20 +00:00
2007-05-28 02:20:55 +00:00
/**
* Retrieves all directives , organized by namespace
2013-07-16 12:20:01 +00:00
*
2009-05-30 02:10:47 +00:00
* @ warning This is a pretty inefficient function , avoid if you can
2007-05-28 02:20:55 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getAll ()
{
if ( ! $this -> finalized ) {
$this -> autoFinalize ();
}
2009-02-02 23:42:23 +00:00
$ret = array ();
foreach ( $this -> plist -> squash () as $name => $value ) {
list ( $ns , $key ) = explode ( '.' , $name , 2 );
$ret [ $ns ][ $key ] = $value ;
}
return $ret ;
2007-05-28 02:20:55 +00:00
}
2008-12-06 07:28:20 +00:00
2006-08-19 23:06:59 +00:00
/**
* Sets a value to configuration .
2013-07-16 12:20:01 +00:00
*
* @ param string $key key
* @ param mixed $value value
* @ param mixed $a
2006-08-19 23:06:59 +00:00
*/
2013-07-16 12:20:01 +00:00
public function set ( $key , $value , $a = null )
{
2009-02-20 00:17:49 +00:00
if ( strpos ( $key , '.' ) === false ) {
$namespace = $key ;
$directive = $value ;
$value = $a ;
$key = " $key . $directive " ;
$this -> triggerError ( " Using deprecated API: use \$ config->set(' $key ', ...) instead " , E_USER_NOTICE );
} else {
list ( $namespace ) = explode ( '.' , $key );
}
2013-07-16 12:20:01 +00:00
if ( $this -> isFinalized ( 'Cannot set directive after finalization' )) {
return ;
}
2009-02-07 07:53:20 +00:00
if ( ! isset ( $this -> def -> info [ $key ])) {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Cannot set undefined directive ' . htmlspecialchars ( $key ) . ' to value' ,
E_USER_WARNING
);
2006-08-27 18:49:16 +00:00
return ;
}
2009-02-07 07:53:20 +00:00
$def = $this -> def -> info [ $key ];
2008-12-06 07:28:20 +00:00
2008-05-26 04:35:12 +00:00
if ( isset ( $def -> isAlias )) {
2009-02-20 00:17:49 +00:00
if ( $this -> aliasMode ) {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Double-aliases not allowed, please fix ' .
'ConfigSchema bug with' . $key ,
E_USER_ERROR
);
2008-04-03 21:53:06 +00:00
return ;
2007-01-20 18:43:58 +00:00
}
2009-02-20 00:17:49 +00:00
$this -> aliasMode = true ;
$this -> set ( $def -> key , $value );
$this -> aliasMode = false ;
$this -> triggerError ( " $key is an alias, preferred directive name is { $def -> key } " , E_USER_NOTICE );
2007-01-20 18:43:58 +00:00
return ;
}
2008-12-06 07:28:20 +00:00
2008-05-23 17:10:26 +00:00
// Raw type might be negative when using the fully optimized form
// of stdclass, which indicates allow_null == true
2008-05-26 04:35:12 +00:00
$rtype = is_int ( $def ) ? $def : $def -> type ;
2008-05-23 17:10:26 +00:00
if ( $rtype < 0 ) {
$type = - $rtype ;
$allow_null = true ;
} else {
$type = $rtype ;
2008-05-26 04:35:12 +00:00
$allow_null = isset ( $def -> allow_null );
2008-05-23 17:10:26 +00:00
}
2008-12-06 07:28:20 +00:00
2008-03-04 15:06:00 +00:00
try {
2008-05-23 17:10:26 +00:00
$value = $this -> parser -> parse ( $value , $type , $allow_null );
2008-03-04 15:06:00 +00:00
} catch ( HTMLPurifier_VarParserException $e ) {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Value for ' . $key . ' is of invalid type, should be ' .
HTMLPurifier_VarParser :: getTypeName ( $type ),
E_USER_WARNING
);
2008-03-04 15:06:00 +00:00
return ;
}
2008-05-26 04:35:12 +00:00
if ( is_string ( $value ) && is_object ( $def )) {
2006-08-27 18:49:16 +00:00
// resolve value alias if defined
2008-05-26 04:35:12 +00:00
if ( isset ( $def -> aliases [ $value ])) {
$value = $def -> aliases [ $value ];
2006-08-27 18:49:16 +00:00
}
2008-05-26 04:35:12 +00:00
// check to see if the value is allowed
if ( isset ( $def -> allowed ) && ! isset ( $def -> allowed [ $value ])) {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
'Value not supported, valid values are: ' .
$this -> _listify ( $def -> allowed ),
E_USER_WARNING
);
2008-05-26 04:35:12 +00:00
return ;
2006-08-27 18:49:16 +00:00
}
}
2009-02-07 07:53:20 +00:00
$this -> plist -> set ( $key , $value );
2008-12-06 07:28:20 +00:00
2007-05-20 19:29:05 +00:00
// reset definitions if the directives they depend on changed
2008-12-06 07:28:20 +00:00
// this is a very costly process, so it's discouraged
2007-05-20 19:29:05 +00:00
// with finalization
2009-05-26 03:38:49 +00:00
if ( $namespace == 'HTML' || $namespace == 'CSS' || $namespace == 'URI' ) {
2007-05-29 18:19:42 +00:00
$this -> definitions [ $namespace ] = null ;
2007-02-14 01:44:06 +00:00
}
2008-12-06 07:28:20 +00:00
2007-05-29 20:21:33 +00:00
$this -> serials [ $namespace ] = false ;
2006-08-11 20:23:41 +00:00
}
2008-12-06 07:28:20 +00:00
2007-06-16 20:21:00 +00:00
/**
* Convenience function for error reporting
2013-07-16 12:20:01 +00:00
*
* @ param array $lookup
*
* @ return string
2007-06-16 20:21:00 +00:00
*/
2013-07-16 12:20:01 +00:00
private function _listify ( $lookup )
{
2007-06-16 20:21:00 +00:00
$list = array ();
foreach ( $lookup as $name => $b ) $list [] = $name ;
return implode ( ', ' , $list );
}
2008-12-06 07:28:20 +00:00
2006-08-31 20:33:07 +00:00
/**
2008-04-23 02:40:17 +00:00
* Retrieves object reference to the HTML definition .
2013-07-16 12:20:01 +00:00
*
* @ param bool $raw Return a copy that has not been setup yet . Must be
2007-02-04 23:10:10 +00:00
* called before it 's been setup, otherwise won' t work .
2013-07-16 12:20:01 +00:00
* @ param bool $optimized If true , this method may return null , to
2010-12-30 23:51:53 +00:00
* indicate that a cached version of the modified
* definition object is available and no further edits
* are necessary . Consider using
* maybeGetRawHTMLDefinition , which is more explicitly
* named , instead .
2013-07-16 12:20:01 +00:00
*
* @ return mixed
2010-12-30 23:51:53 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getHTMLDefinition ( $raw = false , $optimized = false )
{
2010-12-30 23:51:53 +00:00
return $this -> getDefinition ( 'HTML' , $raw , $optimized );
2006-08-31 20:33:07 +00:00
}
2008-12-06 07:28:20 +00:00
2006-08-31 20:33:07 +00:00
/**
2008-04-23 02:40:17 +00:00
* Retrieves object reference to the CSS definition
2013-07-16 12:20:01 +00:00
*
* @ param bool $raw Return a copy that has not been setup yet . Must be
2008-04-23 02:40:17 +00:00
* called before it 's been setup, otherwise won' t work .
2013-07-16 12:20:01 +00:00
* @ param bool $optimized If true , this method may return null , to
2010-12-30 23:51:53 +00:00
* indicate that a cached version of the modified
* definition object is available and no further edits
* are necessary . Consider using
* maybeGetRawCSSDefinition , which is more explicitly
* named , instead .
2013-07-16 12:20:01 +00:00
*
* @ return mixed
2010-12-30 23:51:53 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getCSSDefinition ( $raw = false , $optimized = false )
{
2010-12-30 23:51:53 +00:00
return $this -> getDefinition ( 'CSS' , $raw , $optimized );
}
/**
* Retrieves object reference to the URI definition
2013-07-16 12:20:01 +00:00
*
* @ param bool $raw Return a copy that has not been setup yet . Must be
2010-12-30 23:51:53 +00:00
* called before it 's been setup, otherwise won' t work .
2013-07-16 12:20:01 +00:00
* @ param bool $optimized If true , this method may return null , to
2010-12-30 23:51:53 +00:00
* indicate that a cached version of the modified
* definition object is available and no further edits
* are necessary . Consider using
* maybeGetRawURIDefinition , which is more explicitly
* named , instead .
2013-07-16 12:20:01 +00:00
*
* @ return mixed
2010-12-30 23:51:53 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getURIDefinition ( $raw = false , $optimized = false )
{
2010-12-30 23:51:53 +00:00
return $this -> getDefinition ( 'URI' , $raw , $optimized );
2007-05-25 01:32:29 +00:00
}
2008-12-06 07:28:20 +00:00
2007-05-25 01:32:29 +00:00
/**
2007-05-29 18:19:42 +00:00
* Retrieves a definition
2013-07-16 12:20:01 +00:00
*
* @ param string $type Type of definition : HTML , CSS , etc
* @ param bool $raw Whether or not definition should be returned raw
* @ param bool $optimized Only has an effect when $raw is true . Whether
2010-12-30 23:51:53 +00:00
* or not to return null if the result is already present in
* the cache . This is off by default for backwards
* compatibility reasons , but you need to do things this
* way in order to ensure that caching is done properly .
* Check out enduser - customize . html for more details .
* We probably won ' t ever change this default , as much as the
* maybe semantics is the " right thing to do. "
2013-07-16 12:20:01 +00:00
*
* @ throws HTMLPurifier_Exception
* @ return mixed
2010-12-30 23:51:53 +00:00
*/
2013-07-16 12:20:01 +00:00
public function getDefinition ( $type , $raw = false , $optimized = false )
{
2010-12-30 23:51:53 +00:00
if ( $optimized && ! $raw ) {
throw new HTMLPurifier_Exception ( " Cannot set optimized = true when raw = false " );
}
2013-07-16 12:20:01 +00:00
if ( ! $this -> finalized ) {
$this -> autoFinalize ();
}
2009-05-26 03:38:49 +00:00
// temporarily suspend locks, so we can handle recursive definition calls
$lock = $this -> lock ;
$this -> lock = null ;
2007-05-29 20:21:33 +00:00
$factory = HTMLPurifier_DefinitionCacheFactory :: instance ();
$cache = $factory -> create ( $type , $this );
2009-05-26 03:38:49 +00:00
$this -> lock = $lock ;
2007-05-29 18:19:42 +00:00
if ( ! $raw ) {
2010-12-30 23:51:53 +00:00
// full definition
// ---------------
// check if definition is in memory
if ( ! empty ( $this -> definitions [ $type ])) {
$def = $this -> definitions [ $type ];
// check if the definition is setup
if ( $def -> setup ) {
return $def ;
} else {
$def -> setup ( $this );
2013-07-16 12:20:01 +00:00
if ( $def -> optimized ) {
$cache -> add ( $def , $this );
}
2010-12-30 23:51:53 +00:00
return $def ;
}
}
// check if definition is in cache
$def = $cache -> get ( $this );
if ( $def ) {
// definition in cache, save to memory and return it
$this -> definitions [ $type ] = $def ;
return $def ;
}
// initialize it
$def = $this -> initDefinition ( $type );
// set it up
$this -> lock = $type ;
$def -> setup ( $this );
$this -> lock = null ;
// save in cache
$cache -> add ( $def , $this );
// return it
return $def ;
} else {
// raw definition
// --------------
// check preconditions
$def = null ;
if ( $optimized ) {
if ( is_null ( $this -> get ( $type . '.DefinitionID' ))) {
// fatally error out if definition ID not set
2013-07-16 12:20:01 +00:00
throw new HTMLPurifier_Exception (
" Cannot retrieve raw version without specifying % $type .DefinitionID "
);
2010-12-30 23:51:53 +00:00
}
}
2007-05-29 18:19:42 +00:00
if ( ! empty ( $this -> definitions [ $type ])) {
2010-12-30 23:51:53 +00:00
$def = $this -> definitions [ $type ];
if ( $def -> setup && ! $optimized ) {
2013-07-16 12:20:01 +00:00
$extra = $this -> chatty ?
" (try moving this code block earlier in your initialization) " :
" " ;
throw new HTMLPurifier_Exception (
" Cannot retrieve raw definition after it has already been setup " .
$extra
);
2010-12-30 23:51:53 +00:00
}
if ( $def -> optimized === null ) {
$extra = $this -> chatty ? " (try flushing your cache) " : " " ;
2013-07-16 12:20:01 +00:00
throw new HTMLPurifier_Exception (
" Optimization status of definition is unknown " . $extra
);
2010-12-30 23:51:53 +00:00
}
if ( $def -> optimized !== $optimized ) {
$msg = $optimized ? " optimized " : " unoptimized " ;
$extra = $this -> chatty ? " (this backtrace is for the first inconsistent call, which was for a $msg raw definition) " : " " ;
throw new HTMLPurifier_Exception ( " Inconsistent use of optimized and unoptimized raw definition retrievals " . $extra );
2007-05-29 18:19:42 +00:00
}
}
2010-12-30 23:51:53 +00:00
// check if definition was in memory
if ( $def ) {
if ( $def -> setup ) {
// invariant: $optimized === true (checked above)
return null ;
} else {
return $def ;
}
2007-05-29 18:19:42 +00:00
}
2010-12-30 23:51:53 +00:00
// if optimized, check if definition was in cache
// (because we do the memory check first, this formulation
// is prone to cache slamming, but I think
// guaranteeing that either /all/ of the raw
// setup code or /none/ of it is run is more important.)
if ( $optimized ) {
// This code path only gets run once; once we put
// something in $definitions (which is guaranteed by the
// trailing code), we always short-circuit above.
$def = $cache -> get ( $this );
if ( $def ) {
// save the full definition for later, but don't
// return it yet
$this -> definitions [ $type ] = $def ;
return null ;
}
}
// check invariants for creation
if ( ! $optimized ) {
if ( ! is_null ( $this -> get ( $type . '.DefinitionID' ))) {
if ( $this -> chatty ) {
$this -> triggerError ( " Due to a documentation error in previous version of HTML Purifier, your definitions are not being cached. If this is OK, you can remove the % $type .DefinitionRev and % $type .DefinitionID declaration. Otherwise, modify your code to use maybeGetRawDefinition, and test if the returned value is null before making any edits (if it is null, that means that a cached version is available, and no raw operations are necessary). See <a href='http://htmlpurifier.org/docs/enduser-customize.html#optimized'>Customize</a> for more details " , E_USER_WARNING );
} else {
2013-07-16 12:20:01 +00:00
$this -> triggerError (
" Useless DefinitionID declaration " ,
E_USER_WARNING
);
2010-12-30 23:51:53 +00:00
}
}
}
// initialize it
$def = $this -> initDefinition ( $type );
$def -> optimized = $optimized ;
return $def ;
2007-05-25 01:32:29 +00:00
}
2010-12-30 23:51:53 +00:00
throw new HTMLPurifier_Exception ( " The impossible happened! " );
}
2013-07-16 12:20:01 +00:00
/**
* Initialise definition
*
* @ param string $type What type of definition to create
*
* @ return HTMLPurifier_CSSDefinition | HTMLPurifier_HTMLDefinition | HTMLPurifier_URIDefinition
* @ throws HTMLPurifier_Exception
*/
private function initDefinition ( $type )
{
2007-05-29 18:19:42 +00:00
// quick checks failed, let's create the object
if ( $type == 'HTML' ) {
2010-12-30 23:51:53 +00:00
$def = new HTMLPurifier_HTMLDefinition ();
2007-05-29 18:19:42 +00:00
} elseif ( $type == 'CSS' ) {
2010-12-30 23:51:53 +00:00
$def = new HTMLPurifier_CSSDefinition ();
2007-08-02 01:12:27 +00:00
} elseif ( $type == 'URI' ) {
2010-12-30 23:51:53 +00:00
$def = new HTMLPurifier_URIDefinition ();
2007-05-29 18:19:42 +00:00
} else {
2013-07-16 12:20:01 +00:00
throw new HTMLPurifier_Exception (
" Definition of $type type not supported "
);
2007-05-29 18:19:42 +00:00
}
2010-12-30 23:51:53 +00:00
$this -> definitions [ $type ] = $def ;
return $def ;
}
2013-07-16 12:20:01 +00:00
public function maybeGetRawDefinition ( $name )
{
2010-12-30 23:51:53 +00:00
return $this -> getDefinition ( $name , true , true );
}
2013-07-16 12:20:01 +00:00
public function maybeGetRawHTMLDefinition ()
{
2010-12-30 23:51:53 +00:00
return $this -> getDefinition ( 'HTML' , true , true );
}
2013-07-16 12:20:01 +00:00
public function maybeGetRawCSSDefinition ()
{
2010-12-30 23:51:53 +00:00
return $this -> getDefinition ( 'CSS' , true , true );
}
2013-07-16 12:20:01 +00:00
public function maybeGetRawURIDefinition ()
{
2010-12-30 23:51:53 +00:00
return $this -> getDefinition ( 'URI' , true , true );
2006-08-31 20:33:07 +00:00
}
2008-12-06 07:28:20 +00:00
2006-10-21 18:18:36 +00:00
/**
* Loads configuration values from an array with the following structure :
* Namespace . Directive => Value
2013-07-16 12:20:01 +00:00
*
* @ param array $config_array Configuration associative array
2006-10-21 18:18:36 +00:00
*/
2013-07-16 12:20:01 +00:00
public function loadArray ( $config_array )
{
if ( $this -> isFinalized ( 'Cannot load directives after finalization' )) {
return ;
}
2006-10-21 18:18:36 +00:00
foreach ( $config_array as $key => $value ) {
2006-11-24 06:26:02 +00:00
$key = str_replace ( '_' , '.' , $key );
2006-10-21 18:18:36 +00:00
if ( strpos ( $key , '.' ) !== false ) {
2009-02-20 00:17:49 +00:00
$this -> set ( $key , $value );
2006-10-21 18:18:36 +00:00
} else {
$namespace = $key ;
$namespace_values = $value ;
foreach ( $namespace_values as $directive => $value ) {
2009-02-20 00:17:49 +00:00
$this -> set ( $namespace . '.' . $directive , $value );
2006-10-21 18:18:36 +00:00
}
}
}
}
2008-12-06 07:28:20 +00:00
2007-06-25 18:38:39 +00:00
/**
* Returns a list of array ( namespace , directive ) for all directives
* that are allowed in a web - form context as per an allowed
* namespaces / directives list .
2013-07-16 12:20:01 +00:00
*
* @ param array $allowed List of allowed namespaces / directives
* @ param HTMLPurifier_ConfigSchema $schema Schema to use , if not global copy
*
* @ return array
*/
public static function getAllowedDirectivesForForm ( $allowed , $schema = null )
{
2008-02-16 00:40:30 +00:00
if ( ! $schema ) {
$schema = HTMLPurifier_ConfigSchema :: instance ();
}
2007-06-25 18:38:39 +00:00
if ( $allowed !== true ) {
2013-07-16 12:20:01 +00:00
if ( is_string ( $allowed )) {
$allowed = array ( $allowed );
}
$allowed_ns = array ();
$allowed_directives = array ();
$blacklisted_directives = array ();
foreach ( $allowed as $ns_or_directive ) {
if ( strpos ( $ns_or_directive , '.' ) !== false ) {
// directive
if ( $ns_or_directive [ 0 ] == '-' ) {
$blacklisted_directives [ substr ( $ns_or_directive , 1 )] = true ;
} else {
$allowed_directives [ $ns_or_directive ] = true ;
}
} else {
// namespace
$allowed_ns [ $ns_or_directive ] = true ;
}
}
2007-06-25 18:38:39 +00:00
}
$ret = array ();
2009-02-07 07:53:20 +00:00
foreach ( $schema -> info as $key => $def ) {
list ( $ns , $directive ) = explode ( '.' , $key , 2 );
if ( $allowed !== true ) {
2013-07-16 12:20:01 +00:00
if ( isset ( $blacklisted_directives [ " $ns . $directive " ])) {
continue ;
}
if ( ! isset ( $allowed_directives [ " $ns . $directive " ]) && ! isset ( $allowed_ns [ $ns ])) {
continue ;
}
}
if ( isset ( $def -> isAlias )) {
continue ;
}
if ( $directive == 'DefinitionID' || $directive == 'DefinitionRev' ) {
continue ;
2007-06-25 18:38:39 +00:00
}
2009-02-07 07:53:20 +00:00
$ret [] = array ( $ns , $directive );
2007-06-25 18:38:39 +00:00
}
return $ret ;
}
2008-12-06 07:28:20 +00:00
2007-05-28 03:33:12 +00:00
/**
* Loads configuration values from $_GET / $_POST that were posted
* via ConfigForm
2013-07-16 12:20:01 +00:00
*
* @ param array $array $_GET or $_POST array to import
* @ param string | bool $index Index / name that the config variables are in
* @ param array | bool $allowed List of allowed namespaces / directives
* @ param bool $mq_fix Boolean whether or not to enable magic quotes fix
* @ param HTMLPurifier_ConfigSchema $schema Schema to use , if not global copy
*
* @ return mixed
*/
public static function loadArrayFromForm ( $array , $index = false , $allowed = true , $mq_fix = true , $schema = null )
{
2008-02-16 00:40:30 +00:00
$ret = HTMLPurifier_Config :: prepareArrayFromForm ( $array , $index , $allowed , $mq_fix , $schema );
$config = HTMLPurifier_Config :: create ( $ret , $schema );
2007-06-28 23:01:27 +00:00
return $config ;
}
2008-12-06 07:28:20 +00:00
2007-06-28 23:01:27 +00:00
/**
* Merges in configuration values from $_GET / $_POST to object . NOT STATIC .
2013-07-16 12:20:01 +00:00
*
* @ param array $array $_GET or $_POST array to import
* @ param string | bool $index Index / name that the config variables are in
* @ param array | bool $allowed List of allowed namespaces / directives
* @ param bool $mq_fix Boolean whether or not to enable magic quotes fix
*/
public function mergeArrayFromForm ( $array , $index = false , $allowed = true , $mq_fix = true )
{
2008-02-16 00:40:30 +00:00
$ret = HTMLPurifier_Config :: prepareArrayFromForm ( $array , $index , $allowed , $mq_fix , $this -> def );
2007-06-28 23:01:27 +00:00
$this -> loadArray ( $ret );
}
2008-12-06 07:28:20 +00:00
2007-06-28 23:01:27 +00:00
/**
* Prepares an array from a form into something usable for the more
* strict parts of HTMLPurifier_Config
2013-07-16 12:20:01 +00:00
*
* @ param array $array $_GET or $_POST array to import
* @ param string | bool $index Index / name that the config variables are in
* @ param array | bool $allowed List of allowed namespaces / directives
* @ param bool $mq_fix Boolean whether or not to enable magic quotes fix
* @ param HTMLPurifier_ConfigSchema $schema Schema to use , if not global copy
*
* @ return array
*/
public static function prepareArrayFromForm ( $array , $index = false , $allowed = true , $mq_fix = true , $schema = null )
{
if ( $index !== false ) {
$array = ( isset ( $array [ $index ]) && is_array ( $array [ $index ])) ? $array [ $index ] : array ();
}
2008-03-01 18:09:52 +00:00
$mq = $mq_fix && function_exists ( 'get_magic_quotes_gpc' ) && get_magic_quotes_gpc ();
2008-12-06 07:28:20 +00:00
2008-02-16 00:40:30 +00:00
$allowed = HTMLPurifier_Config :: getAllowedDirectivesForForm ( $allowed , $schema );
2007-06-25 18:38:39 +00:00
$ret = array ();
foreach ( $allowed as $key ) {
list ( $ns , $directive ) = $key ;
$skey = " $ns . $directive " ;
if ( ! empty ( $array [ " Null_ $skey " ])) {
$ret [ $ns ][ $directive ] = null ;
continue ;
2007-05-28 03:33:12 +00:00
}
2013-07-16 12:20:01 +00:00
if ( ! isset ( $array [ $skey ])) {
continue ;
}
2007-06-25 18:38:39 +00:00
$value = $mq ? stripslashes ( $array [ $skey ]) : $array [ $skey ];
$ret [ $ns ][ $directive ] = $value ;
2007-05-28 03:33:12 +00:00
}
2007-06-28 23:01:27 +00:00
return $ret ;
2007-05-28 03:33:12 +00:00
}
2008-12-06 07:28:20 +00:00
2007-01-21 14:29:46 +00:00
/**
* Loads configuration values from an ini file
2013-07-16 12:20:01 +00:00
*
* @ param string $filename Name of ini file
2007-01-21 14:29:46 +00:00
*/
2013-07-16 12:20:01 +00:00
public function loadIni ( $filename )
{
if ( $this -> isFinalized ( 'Cannot load directives after finalization' )) {
return ;
}
2007-01-21 14:29:46 +00:00
$array = parse_ini_file ( $filename , true );
$this -> loadArray ( $array );
}
2008-12-06 07:28:20 +00:00
2007-05-20 18:06:51 +00:00
/**
* Checks whether or not the configuration object is finalized .
2013-07-16 12:20:01 +00:00
*
* @ param string | bool $error String error message , or false for no error
*
* @ return bool
2007-05-20 18:06:51 +00:00
*/
2013-07-16 12:20:01 +00:00
public function isFinalized ( $error = false )
{
2007-05-20 18:06:51 +00:00
if ( $this -> finalized && $error ) {
2009-02-20 00:17:49 +00:00
$this -> triggerError ( $error , E_USER_ERROR );
2007-05-20 18:06:51 +00:00
}
return $this -> finalized ;
}
2008-12-06 07:28:20 +00:00
2007-05-25 01:32:29 +00:00
/**
* Finalizes configuration only if auto finalize is on and not
* already finalized
*/
2013-07-16 12:20:01 +00:00
public function autoFinalize ()
{
2009-02-20 05:13:09 +00:00
if ( $this -> autoFinalize ) {
$this -> finalize ();
} else {
$this -> plist -> squash ( true );
}
2007-05-25 01:32:29 +00:00
}
2008-12-06 07:28:20 +00:00
2007-05-20 18:06:51 +00:00
/**
* Finalizes a configuration object , prohibiting further change
*/
2013-07-16 12:20:01 +00:00
public function finalize ()
{
2007-05-20 18:06:51 +00:00
$this -> finalized = true ;
2011-09-22 15:10:12 +00:00
$this -> parser = null ;
2007-05-20 18:06:51 +00:00
}
2008-12-06 07:28:20 +00:00
2009-02-20 00:17:49 +00:00
/**
* Produces a nicely formatted error message by supplying the
2010-12-30 23:51:53 +00:00
* stack frame information OUTSIDE of HTMLPurifier_Config .
2013-07-16 12:20:01 +00:00
*
* @ param string $msg An error message
* @ param int $no An error number
2009-02-20 00:17:49 +00:00
*/
2013-07-16 12:20:01 +00:00
protected function triggerError ( $msg , $no )
{
2009-02-20 00:17:49 +00:00
// determine previous stack frame
2010-12-30 23:51:53 +00:00
$extra = '' ;
if ( $this -> chatty ) {
$trace = debug_backtrace ();
// zip(tail(trace), trace) -- but PHP is not Haskell har har
for ( $i = 0 , $c = count ( $trace ); $i < $c - 1 ; $i ++ ) {
2012-10-11 18:40:02 +00:00
// XXX this is not correct on some versions of HTML Purifier
2010-12-30 23:51:53 +00:00
if ( $trace [ $i + 1 ][ 'class' ] === 'HTMLPurifier_Config' ) {
continue ;
}
$frame = $trace [ $i ];
$extra = " invoked on line { $frame [ 'line' ] } in file { $frame [ 'file' ] } " ;
break ;
}
2009-02-20 00:17:49 +00:00
}
trigger_error ( $msg . $extra , $no );
}
2009-05-30 04:25:14 +00:00
/**
* Returns a serialized form of the configuration object that can
* be reconstituted .
2013-07-16 12:20:01 +00:00
*
* @ return string
2009-05-30 04:25:14 +00:00
*/
2013-07-16 12:20:01 +00:00
public function serialize ()
{
2009-05-30 04:25:14 +00:00
$this -> getDefinition ( 'HTML' );
$this -> getDefinition ( 'CSS' );
$this -> getDefinition ( 'URI' );
return serialize ( $this );
}
2006-08-04 01:47:48 +00:00
}
2008-12-06 09:24:59 +00:00
// vim: et sw=4 sts=4