1 <?php 2 3 class HTMLPurifier_ConfigSchema_InterchangeBuilder 4 { 5 6 /** 7 * Used for processing DEFAULT, nothing else. 8 * @type HTMLPurifier_VarParser 9 */ 10 protected $varParser; 11 12 /** 13 * @param HTMLPurifier_VarParser $varParser 14 */ 15 public function __construct($varParser = null) 16 { 17 $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native(); 18 } 19 20 /** 21 * @param string $dir 22 * @return HTMLPurifier_ConfigSchema_Interchange 23 */ 24 public static function buildFromDirectory($dir = null) 25 { 26 $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder(); 27 $interchange = new HTMLPurifier_ConfigSchema_Interchange(); 28 return $builder->buildDir($interchange, $dir); 29 } 30 31 /** 32 * @param HTMLPurifier_ConfigSchema_Interchange $interchange 33 * @param string $dir 34 * @return HTMLPurifier_ConfigSchema_Interchange 35 */ 36 public function buildDir($interchange, $dir = null) 37 { 38 if (!$dir) { 39 $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema'; 40 } 41 if (file_exists($dir . '/info.ini')) { 42 $info = parse_ini_file($dir . '/info.ini'); 43 $interchange->name = $info['name']; 44 } 45 46 $files = array(); 47 $dh = opendir($dir); 48 while (false !== ($file = readdir($dh))) { 49 if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') { 50 continue; 51 } 52 $files[] = $file; 53 } 54 closedir($dh); 55 56 sort($files); 57 foreach ($files as $file) { 58 $this->buildFile($interchange, $dir . '/' . $file); 59 } 60 return $interchange; 61 } 62 63 /** 64 * @param HTMLPurifier_ConfigSchema_Interchange $interchange 65 * @param string $file 66 */ 67 public function buildFile($interchange, $file) 68 { 69 $parser = new HTMLPurifier_StringHashParser(); 70 $this->build( 71 $interchange, 72 new HTMLPurifier_StringHash($parser->parseFile($file)) 73 ); 74 } 75 76 /** 77 * Builds an interchange object based on a hash. 78 * @param HTMLPurifier_ConfigSchema_Interchange $interchange HTMLPurifier_ConfigSchema_Interchange object to build 79 * @param HTMLPurifier_StringHash $hash source data 80 * @throws HTMLPurifier_ConfigSchema_Exception 81 */ 82 public function build($interchange, $hash) 83 { 84 if (!$hash instanceof HTMLPurifier_StringHash) { 85 $hash = new HTMLPurifier_StringHash($hash); 86 } 87 if (!isset($hash['ID'])) { 88 throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID'); 89 } 90 if (strpos($hash['ID'], '.') === false) { 91 if (count($hash) == 2 && isset($hash['DESCRIPTION'])) { 92 $hash->offsetGet('DESCRIPTION'); // prevent complaining 93 } else { 94 throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace'); 95 } 96 } else { 97 $this->buildDirective($interchange, $hash); 98 } 99 $this->_findUnused($hash); 100 } 101 102 /** 103 * @param HTMLPurifier_ConfigSchema_Interchange $interchange 104 * @param HTMLPurifier_StringHash $hash 105 * @throws HTMLPurifier_ConfigSchema_Exception 106 */ 107 public function buildDirective($interchange, $hash) 108 { 109 $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive(); 110 111 // These are required elements: 112 $directive->id = $this->id($hash->offsetGet('ID')); 113 $id = $directive->id->toString(); // convenience 114 115 if (isset($hash['TYPE'])) { 116 $type = explode('/', $hash->offsetGet('TYPE')); 117 if (isset($type[1])) { 118 $directive->typeAllowsNull = true; 119 } 120 $directive->type = $type[0]; 121 } else { 122 throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined"); 123 } 124 125 if (isset($hash['DEFAULT'])) { 126 try { 127 $directive->default = $this->varParser->parse( 128 $hash->offsetGet('DEFAULT'), 129 $directive->type, 130 $directive->typeAllowsNull 131 ); 132 } catch (HTMLPurifier_VarParserException $e) { 133 throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'"); 134 } 135 } 136 137 if (isset($hash['DESCRIPTION'])) { 138 $directive->description = $hash->offsetGet('DESCRIPTION'); 139 } 140 141 if (isset($hash['ALLOWED'])) { 142 $directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED'))); 143 } 144 145 if (isset($hash['VALUE-ALIASES'])) { 146 $directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES')); 147 } 148 149 if (isset($hash['ALIASES'])) { 150 $raw_aliases = trim($hash->offsetGet('ALIASES')); 151 $aliases = preg_split('/\s*,\s*/', $raw_aliases); 152 foreach ($aliases as $alias) { 153 $directive->aliases[] = $this->id($alias); 154 } 155 } 156 157 if (isset($hash['VERSION'])) { 158 $directive->version = $hash->offsetGet('VERSION'); 159 } 160 161 if (isset($hash['DEPRECATED-USE'])) { 162 $directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE')); 163 } 164 165 if (isset($hash['DEPRECATED-VERSION'])) { 166 $directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION'); 167 } 168 169 if (isset($hash['EXTERNAL'])) { 170 $directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL'))); 171 } 172 173 $interchange->addDirective($directive); 174 } 175 176 /** 177 * Evaluates an array PHP code string without array() wrapper 178 * @param string $contents 179 */ 180 protected function evalArray($contents) 181 { 182 return eval('return array(' . $contents . ');'); 183 } 184 185 /** 186 * Converts an array list into a lookup array. 187 * @param array $array 188 * @return array 189 */ 190 protected function lookup($array) 191 { 192 $ret = array(); 193 foreach ($array as $val) { 194 $ret[$val] = true; 195 } 196 return $ret; 197 } 198 199 /** 200 * Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id 201 * object based on a string Id. 202 * @param string $id 203 * @return HTMLPurifier_ConfigSchema_Interchange_Id 204 */ 205 protected function id($id) 206 { 207 return HTMLPurifier_ConfigSchema_Interchange_Id::make($id); 208 } 209 210 /** 211 * Triggers errors for any unused keys passed in the hash; such keys 212 * may indicate typos, missing values, etc. 213 * @param HTMLPurifier_StringHash $hash Hash to check. 214 */ 215 protected function _findUnused($hash) 216 { 217 $accessed = $hash->getAccessed(); 218 foreach ($hash as $k => $v) { 219 if (!isset($accessed[$k])) { 220 trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE); 221 } 222 } 223 } 224 } 225 226 // vim: et sw=4 sts=4
title
Description
Body
title
Description
Body
title
Description
Body
title
Body