1: <?php
2:
3: class HTMLPurifier_ConfigSchema_InterchangeBuilder
4: {
5:
6: 7: 8: 9:
10: protected $varParser;
11:
12: 13: 14:
15: public function __construct($varParser = null)
16: {
17: $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
18: }
19:
20: 21: 22: 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: 33: 34: 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: 65: 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: 78: 79: 80: 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');
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: 104: 105: 106:
107: public function buildDirective($interchange, $hash)
108: {
109: $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
110:
111:
112: $directive->id = $this->id($hash->offsetGet('ID'));
113: $id = $directive->id->toString();
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: 178: 179:
180: protected function evalArray($contents)
181: {
182: return eval('return array(' . $contents . ');');
183: }
184:
185: 186: 187: 188: 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: 201: 202: 203: 204:
205: protected function id($id)
206: {
207: return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
208: }
209:
210: 211: 212: 213: 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:
227: