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