227 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			PHP
		
	
	
		
		
			
		
	
	
			227 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			PHP
		
	
	
| 
								 | 
							
								<?php
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class HTMLPurifier_ConfigSchema_InterchangeBuilder
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Used for processing DEFAULT, nothing else.
							 | 
						||
| 
								 | 
							
								     * @type HTMLPurifier_VarParser
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected $varParser;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_VarParser $varParser
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function __construct($varParser = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @param string $dir
							 | 
						||
| 
								 | 
							
								     * @return HTMLPurifier_ConfigSchema_Interchange
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public static function buildFromDirectory($dir = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
							 | 
						||
| 
								 | 
							
								        $interchange = new HTMLPurifier_ConfigSchema_Interchange();
							 | 
						||
| 
								 | 
							
								        return $builder->buildDir($interchange, $dir);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
							 | 
						||
| 
								 | 
							
								     * @param string $dir
							 | 
						||
| 
								 | 
							
								     * @return HTMLPurifier_ConfigSchema_Interchange
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function buildDir($interchange, $dir = null)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!$dir) {
							 | 
						||
| 
								 | 
							
								            $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (file_exists($dir . '/info.ini')) {
							 | 
						||
| 
								 | 
							
								            $info = parse_ini_file($dir . '/info.ini');
							 | 
						||
| 
								 | 
							
								            $interchange->name = $info['name'];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $files = array();
							 | 
						||
| 
								 | 
							
								        $dh = opendir($dir);
							 | 
						||
| 
								 | 
							
								        while (false !== ($file = readdir($dh))) {
							 | 
						||
| 
								 | 
							
								            if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') {
							 | 
						||
| 
								 | 
							
								                continue;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $files[] = $file;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        closedir($dh);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        sort($files);
							 | 
						||
| 
								 | 
							
								        foreach ($files as $file) {
							 | 
						||
| 
								 | 
							
								            $this->buildFile($interchange, $dir . '/' . $file);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return $interchange;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
							 | 
						||
| 
								 | 
							
								     * @param string $file
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function buildFile($interchange, $file)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $parser = new HTMLPurifier_StringHashParser();
							 | 
						||
| 
								 | 
							
								        $this->build(
							 | 
						||
| 
								 | 
							
								            $interchange,
							 | 
						||
| 
								 | 
							
								            new HTMLPurifier_StringHash($parser->parseFile($file))
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Builds an interchange object based on a hash.
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_ConfigSchema_Interchange $interchange HTMLPurifier_ConfigSchema_Interchange object to build
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_StringHash $hash source data
							 | 
						||
| 
								 | 
							
								     * @throws HTMLPurifier_ConfigSchema_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function build($interchange, $hash)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        if (!$hash instanceof HTMLPurifier_StringHash) {
							 | 
						||
| 
								 | 
							
								            $hash = new HTMLPurifier_StringHash($hash);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (!isset($hash['ID'])) {
							 | 
						||
| 
								 | 
							
								            throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (strpos($hash['ID'], '.') === false) {
							 | 
						||
| 
								 | 
							
								            if (count($hash) == 2 && isset($hash['DESCRIPTION'])) {
							 | 
						||
| 
								 | 
							
								                $hash->offsetGet('DESCRIPTION'); // prevent complaining
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								                throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace');
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            $this->buildDirective($interchange, $hash);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        $this->_findUnused($hash);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_StringHash $hash
							 | 
						||
| 
								 | 
							
								     * @throws HTMLPurifier_ConfigSchema_Exception
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    public function buildDirective($interchange, $hash)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // These are required elements:
							 | 
						||
| 
								 | 
							
								        $directive->id = $this->id($hash->offsetGet('ID'));
							 | 
						||
| 
								 | 
							
								        $id = $directive->id->toString(); // convenience
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['TYPE'])) {
							 | 
						||
| 
								 | 
							
								            $type = explode('/', $hash->offsetGet('TYPE'));
							 | 
						||
| 
								 | 
							
								            if (isset($type[1])) {
							 | 
						||
| 
								 | 
							
								                $directive->typeAllowsNull = true;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            $directive->type = $type[0];
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined");
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['DEFAULT'])) {
							 | 
						||
| 
								 | 
							
								            try {
							 | 
						||
| 
								 | 
							
								                $directive->default = $this->varParser->parse(
							 | 
						||
| 
								 | 
							
								                    $hash->offsetGet('DEFAULT'),
							 | 
						||
| 
								 | 
							
								                    $directive->type,
							 | 
						||
| 
								 | 
							
								                    $directive->typeAllowsNull
							 | 
						||
| 
								 | 
							
								                );
							 | 
						||
| 
								 | 
							
								            } catch (HTMLPurifier_VarParserException $e) {
							 | 
						||
| 
								 | 
							
								                throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'");
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['DESCRIPTION'])) {
							 | 
						||
| 
								 | 
							
								            $directive->description = $hash->offsetGet('DESCRIPTION');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['ALLOWED'])) {
							 | 
						||
| 
								 | 
							
								            $directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED')));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['VALUE-ALIASES'])) {
							 | 
						||
| 
								 | 
							
								            $directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['ALIASES'])) {
							 | 
						||
| 
								 | 
							
								            $raw_aliases = trim($hash->offsetGet('ALIASES'));
							 | 
						||
| 
								 | 
							
								            $aliases = preg_split('/\s*,\s*/', $raw_aliases);
							 | 
						||
| 
								 | 
							
								            foreach ($aliases as $alias) {
							 | 
						||
| 
								 | 
							
								                $directive->aliases[] = $this->id($alias);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['VERSION'])) {
							 | 
						||
| 
								 | 
							
								            $directive->version = $hash->offsetGet('VERSION');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['DEPRECATED-USE'])) {
							 | 
						||
| 
								 | 
							
								            $directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE'));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['DEPRECATED-VERSION'])) {
							 | 
						||
| 
								 | 
							
								            $directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (isset($hash['EXTERNAL'])) {
							 | 
						||
| 
								 | 
							
								            $directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL')));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        $interchange->addDirective($directive);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Evaluates an array PHP code string without array() wrapper
							 | 
						||
| 
								 | 
							
								     * @param string $contents
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function evalArray($contents)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return eval('return array(' . $contents . ');');
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Converts an array list into a lookup array.
							 | 
						||
| 
								 | 
							
								     * @param array $array
							 | 
						||
| 
								 | 
							
								     * @return array
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function lookup($array)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $ret = array();
							 | 
						||
| 
								 | 
							
								        foreach ($array as $val) {
							 | 
						||
| 
								 | 
							
								            $ret[$val] = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return $ret;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id
							 | 
						||
| 
								 | 
							
								     * object based on a string Id.
							 | 
						||
| 
								 | 
							
								     * @param string $id
							 | 
						||
| 
								 | 
							
								     * @return HTMLPurifier_ConfigSchema_Interchange_Id
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function id($id)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Triggers errors for any unused keys passed in the hash; such keys
							 | 
						||
| 
								 | 
							
								     * may indicate typos, missing values, etc.
							 | 
						||
| 
								 | 
							
								     * @param HTMLPurifier_StringHash $hash Hash to check.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    protected function _findUnused($hash)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								        $accessed = $hash->getAccessed();
							 | 
						||
| 
								 | 
							
								        foreach ($hash as $k => $v) {
							 | 
						||
| 
								 | 
							
								            if (!isset($accessed[$k])) {
							 | 
						||
| 
								 | 
							
								                trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// vim: et sw=4 sts=4
							 |