| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 | <?phpclass 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
 |