1: <?php
2:
3: class HTMLPurifier_ConfigSchema_InterchangeBuilder
4: {
5:
6: 7: 8:
9: protected $varParser;
10:
11: public function __construct($varParser = null) {
12: $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
13: }
14:
15: public static function buildFromDirectory($dir = null) {
16: $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
17: $interchange = new HTMLPurifier_ConfigSchema_Interchange();
18: return $builder->buildDir($interchange, $dir);
19: }
20:
21: public function buildDir($interchange, $dir = null) {
22: if (!$dir) $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
23: if (file_exists($dir . '/info.ini')) {
24: $info = parse_ini_file($dir . '/info.ini');
25: $interchange->name = $info['name'];
26: }
27:
28: $files = array();
29: $dh = opendir($dir);
30: while (false !== ($file = readdir($dh))) {
31: if (!$file || $file[0] == '.' || strrchr($file, '.') !== '.txt') {
32: continue;
33: }
34: $files[] = $file;
35: }
36: closedir($dh);
37:
38: sort($files);
39: foreach ($files as $file) {
40: $this->buildFile($interchange, $dir . '/' . $file);
41: }
42:
43: return $interchange;
44: }
45:
46: public function buildFile($interchange, $file) {
47: $parser = new HTMLPurifier_StringHashParser();
48: $this->build(
49: $interchange,
50: new HTMLPurifier_StringHash( $parser->parseFile($file) )
51: );
52: }
53:
54: 55: 56: 57: 58:
59: public function build($interchange, $hash) {
60: if (!$hash instanceof HTMLPurifier_StringHash) {
61: $hash = new HTMLPurifier_StringHash($hash);
62: }
63: if (!isset($hash['ID'])) {
64: throw new HTMLPurifier_ConfigSchema_Exception('Hash does not have any ID');
65: }
66: if (strpos($hash['ID'], '.') === false) {
67: if (count($hash) == 2 && isset($hash['DESCRIPTION'])) {
68: $hash->offsetGet('DESCRIPTION');
69: } else {
70: throw new HTMLPurifier_ConfigSchema_Exception('All directives must have a namespace');
71: }
72: } else {
73: $this->buildDirective($interchange, $hash);
74: }
75: $this->_findUnused($hash);
76: }
77:
78: public function buildDirective($interchange, $hash) {
79: $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
80:
81:
82: $directive->id = $this->id($hash->offsetGet('ID'));
83: $id = $directive->id->toString();
84:
85: if (isset($hash['TYPE'])) {
86: $type = explode('/', $hash->offsetGet('TYPE'));
87: if (isset($type[1])) $directive->typeAllowsNull = true;
88: $directive->type = $type[0];
89: } else {
90: throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined");
91: }
92:
93: if (isset($hash['DEFAULT'])) {
94: try {
95: $directive->default = $this->varParser->parse($hash->offsetGet('DEFAULT'), $directive->type, $directive->typeAllowsNull);
96: } catch (HTMLPurifier_VarParserException $e) {
97: throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'");
98: }
99: }
100:
101: if (isset($hash['DESCRIPTION'])) {
102: $directive->description = $hash->offsetGet('DESCRIPTION');
103: }
104:
105: if (isset($hash['ALLOWED'])) {
106: $directive->allowed = $this->lookup($this->evalArray($hash->offsetGet('ALLOWED')));
107: }
108:
109: if (isset($hash['VALUE-ALIASES'])) {
110: $directive->valueAliases = $this->evalArray($hash->offsetGet('VALUE-ALIASES'));
111: }
112:
113: if (isset($hash['ALIASES'])) {
114: $raw_aliases = trim($hash->offsetGet('ALIASES'));
115: $aliases = preg_split('/\s*,\s*/', $raw_aliases);
116: foreach ($aliases as $alias) {
117: $directive->aliases[] = $this->id($alias);
118: }
119: }
120:
121: if (isset($hash['VERSION'])) {
122: $directive->version = $hash->offsetGet('VERSION');
123: }
124:
125: if (isset($hash['DEPRECATED-USE'])) {
126: $directive->deprecatedUse = $this->id($hash->offsetGet('DEPRECATED-USE'));
127: }
128:
129: if (isset($hash['DEPRECATED-VERSION'])) {
130: $directive->deprecatedVersion = $hash->offsetGet('DEPRECATED-VERSION');
131: }
132:
133: if (isset($hash['EXTERNAL'])) {
134: $directive->external = preg_split('/\s*,\s*/', trim($hash->offsetGet('EXTERNAL')));
135: }
136:
137: $interchange->addDirective($directive);
138: }
139:
140: 141: 142:
143: protected function evalArray($contents) {
144: return eval('return array('. $contents .');');
145: }
146:
147: 148: 149:
150: protected function lookup($array) {
151: $ret = array();
152: foreach ($array as $val) $ret[$val] = true;
153: return $ret;
154: }
155:
156: 157: 158: 159:
160: protected function id($id) {
161: return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
162: }
163:
164: 165: 166: 167: 168:
169: protected function _findUnused($hash) {
170: $accessed = $hash->getAccessed();
171: foreach ($hash as $k => $v) {
172: if (!isset($accessed[$k])) {
173: trigger_error("String hash key '$k' not used by builder", E_USER_NOTICE);
174: }
175: }
176: }
177:
178: }
179:
180:
181: