Project

General

Profile

Download (9.86 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	xmlparse.inc
5
	functions to parse/dump configuration files in XML format
6
	part of m0n0wall (http://m0n0.ch/wall)
7

    
8
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
9
	All rights reserved.
10

    
11
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13

    
14
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16

    
17
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20

    
21
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32

    
33
/* The following items will be treated as arrays in config.xml */
34
function listtags() {
35
	/*
36
	 * Please keep this list alpha sorted and no longer than 80 characters
37
	 * I know it's a pain, but it's a pain to find stuff too if it's not
38
	 */
39
	$ret = array(
40
		'acls', 'alias', 'aliasurl', 'allowedip', 'allowedhostname', 'authserver',
41
		'bridged', 'build_port_path',
42
		'ca', 'cacert', 'cert', 'crl', 'clone', 'config', 'container', 'columnitem',
43
		'depends_on_package', 'disk', 'dnsserver', 'dnsupdate', 'domainoverrides', 'dyndns',
44
		'earlyshellcmd', 'element', 'encryption-algorithm-option',
45
		'field', 'fieldname',
46
		'gateway_item', 'gateway_group', 'gif', 'gre', 'group',
47
		'hash-algorithm-option', 'hosts', 'member', 'ifgroupentry', 'igmpentry', 'interface_array', 'item', 'key',
48
		'lagg', 'lbaction', 'lbpool', 'l7rules', 'lbprotocol',
49
		'member', 'menu', 'tab', 'mobilekey', 'monitor_type', 'mount',
50
		'npt', 'ntpserver',
51
		'onetoone', 'openvpn-server', 'openvpn-client', 'openvpn-csc', 'option',
52
		'package', 'passthrumac', 'phase1', 'phase2', 'ppp', 'pppoe', 'priv', 'proxyarpnet', 'pool',
53
		'qinqentry', 'queue',
54
		'pages', 'pipe', 'radnsserver', 'roll', 'route', 'row', 'rrddatafile', 'rule',
55
		'schedule', 'service', 'servernat', 'servers',
56
		'serversdisabled', 'shellcmd', 'staticmap', 'subqueue',
57
		'timerange', 'tunnel', 'user', 'vip', 'virtual_server', 'vlan',
58
		'winsserver', 'wolentry', 'widget'
59
	);
60
	return array_flip($ret);
61
}
62

    
63
/* Package XML tags that should be treated as a list not as a traditional array */
64
function listtags_pkg() {
65
	$ret = array('build_port_path', 'depends_on_package', 'onetoone', 'queue', 'rule', 'servernat', 'alias', 'additional_files_needed', 'tab', 'template', 'menu', 'rowhelperfield', 'service', 'step', 'package', 'columnitem', 'option', 'item', 'field', 'package', 'file');
66

    
67
	return array_flip($ret);
68
}
69

    
70
function startElement($parser, $name, $attrs) {
71
	global $parsedcfg, $depth, $curpath, $havedata, $listtags;
72

    
73
	array_push($curpath, strtolower($name));
74

    
75
	$ptr =& $parsedcfg;
76
	foreach ($curpath as $path) {
77
		$ptr =& $ptr[$path];
78
	}
79

    
80
	/* is it an element that belongs to a list? */
81
	if (isset($listtags[strtolower($name)])) {
82

    
83
		/* is there an array already? */
84
		if (!is_array($ptr)) {
85
			/* make an array */
86
			$ptr = array();
87
		}
88

    
89
		array_push($curpath, count($ptr));
90

    
91
	} else if (isset($ptr)) {
92
		/* multiple entries not allowed for this element, bail out */
93
		die(sprintf(gettext('XML error: %1$s at line %2$d cannot occur more than once') . "\n",
94
		    $name,
95
		    xml_get_current_line_number($parser)));
96
	}
97

    
98
	$depth++;
99
	$havedata = $depth;
100
}
101

    
102
function endElement($parser, $name) {
103
	global $depth, $curpath, $parsedcfg, $havedata, $listtags;
104

    
105
	if ($havedata == $depth) {
106
		$ptr =& $parsedcfg;
107
		foreach ($curpath as $path) {
108
			$ptr =& $ptr[$path];
109
		}
110
		$ptr = "";
111
	}
112

    
113
	array_pop($curpath);
114

    
115
	if (isset($listtags[strtolower($name)])) {
116
		array_pop($curpath);
117
	}
118

    
119
	$depth--;
120
}
121

    
122
function cData($parser, $data) {
123
	global $depth, $curpath, $parsedcfg, $havedata;
124

    
125
	$data = trim($data, "\t\n\r");
126

    
127
	if ($data != "") {
128
		$ptr =& $parsedcfg;
129
		foreach ($curpath as $path) {
130
			$ptr =& $ptr[$path];
131
		}
132

    
133
		if (is_string($ptr)) {
134
			$ptr .= html_entity_decode($data);
135
		} else {
136
			if (trim($data, " ") != "") {
137
				$ptr = html_entity_decode($data);
138
				$havedata++;
139
			}
140
		}
141
	}
142
}
143

    
144
function parse_xml_config($cffile, $rootobj, $isstring = "false") {
145
	global $listtags;
146
	$listtags = listtags();
147
	if (isset($GLOBALS['custom_listtags'])) {
148
		foreach ($GLOBALS['custom_listtags'] as $tag) {
149
			$listtags[$tag] = $tag;
150
		}
151
	}
152
	return parse_xml_config_raw($cffile, $rootobj, $isstring);
153
}
154

    
155
function parse_xml_config_pkg($cffile, $rootobj, $isstring = "false") {
156
	global $listtags;
157
	$listtags = listtags_pkg();
158
	if (isset($GLOBALS['custom_listtags_pkg'])) {
159
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
160
			$listtags[$tag] = $tag;
161
		}
162
	}
163
	$cfg =parse_xml_config_raw($cffile, $rootobj, $isstring);
164
	if ($cfg == -1) {
165
		return array();
166
	}
167

    
168
	return $cfg;
169
}
170

    
171
function parse_xml_config_raw($cffile, $rootobj, $isstring = "false") {
172

    
173
	global $depth, $curpath, $parsedcfg, $havedata, $listtags;
174
	$parsedcfg = array();
175
	$curpath = array();
176
	$depth = 0;
177
	$havedata = 0;
178

    
179
	$xml_parser = xml_parser_create();
180

    
181
	xml_set_element_handler($xml_parser, "startElement", "endElement");
182
	xml_set_character_data_handler($xml_parser, "cdata");
183
	xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 1);
184

    
185
	if (!($fp = fopen($cffile, "r"))) {
186
		log_error(gettext("Error: could not open XML input") . "\n");
187
		return -1;
188
	}
189

    
190
	while ($data = fread($fp, 4096)) {
191
		if (!xml_parse($xml_parser, $data, feof($fp))) {
192
			log_error(sprintf(gettext('XML error: %1$s at line %2$d in %3$s') . "\n",
193
				xml_error_string(xml_get_error_code($xml_parser)),
194
				xml_get_current_line_number($xml_parser),
195
				$cffile));
196
			return -1;
197
		}
198
	}
199
	xml_parser_free($xml_parser);
200

    
201
	if ($rootobj) {
202
		if (!is_array($rootobj)) {
203
			$rootobj = array($rootobj);
204
		}
205
		foreach ($rootobj as $rootobj_name) {
206
			if ($parsedcfg[$rootobj_name]) {
207
				break;
208
			}
209
		}
210

    
211
		if (!$parsedcfg[$rootobj_name]) {
212
			log_error(sprintf(gettext("XML error: no %s object found!") . "\n", implode(" or ", $rootobj)));
213
			return -1;
214
		}
215
		return $parsedcfg[$rootobj_name];
216
	} else {
217
		return $parsedcfg;
218
	}
219
}
220

    
221
function dump_xml_config_sub($arr, $indent) {
222

    
223
	global $listtags;
224

    
225
	$xmlconfig = "";
226

    
227
	foreach ($arr as $ent => $val) {
228
		if (is_array($val)) {
229
			/* is it just a list of multiple values? */
230
			if (isset($listtags[strtolower($ent)])) {
231
				foreach ($val as $cval) {
232
					if (is_array($cval)) {
233
						if (empty($cval)) {
234
							$xmlconfig .= str_repeat("\t", $indent);
235
							$xmlconfig .= "<$ent/>\n";
236
						} else {
237
							$xmlconfig .= str_repeat("\t", $indent);
238
							$xmlconfig .= "<$ent>\n";
239
							$xmlconfig .= dump_xml_config_sub($cval, $indent + 1);
240
							$xmlconfig .= str_repeat("\t", $indent);
241
							$xmlconfig .= "</$ent>\n";
242
						}
243
					} else {
244
						if ($cval === false) {
245
							continue;
246
						}
247
						$xmlconfig .= str_repeat("\t", $indent);
248
						if ((is_bool($cval) && $cval == true) || ($cval === "")) {
249
							$xmlconfig .= "<$ent/>\n";
250
						} else if ((substr($ent, 0, 5) == "descr") ||
251
						    (substr($ent, 0, 6) == "detail") ||
252
						    (substr($ent, 0, 12) == "login_banner") ||
253
						    (substr($ent, 0, 9) == "ldap_attr") ||
254
						    (substr($ent, 0, 9) == "ldap_bind") ||
255
						    (substr($ent, 0, 11) == "ldap_basedn") ||
256
						    (substr($ent, 0, 18) == "ldap_authcn") ||
257
						    (substr($ent, 0, 19) == "ldap_extended_query")) {
258
							$xmlconfig .= "<$ent><![CDATA[" . htmlentities($cval) . "]]></$ent>\n";
259
						} else {
260
							$xmlconfig .= "<$ent>" . htmlentities($cval) . "</$ent>\n";
261
						}
262
					}
263
				}
264
			} else if (empty($val)) {
265
				$xmlconfig .= str_repeat("\t", $indent);
266
				$xmlconfig .= "<$ent/>\n";
267
			} else {
268
				/* it's an array */
269
				$xmlconfig .= str_repeat("\t", $indent);
270
				$xmlconfig .= "<$ent>\n";
271
				$xmlconfig .= dump_xml_config_sub($val, $indent + 1);
272
				$xmlconfig .= str_repeat("\t", $indent);
273
				$xmlconfig .= "</$ent>\n";
274
			}
275
		} else {
276
			if ((is_bool($val) && ($val == true)) || ($val === "")) {
277
				$xmlconfig .= str_repeat("\t", $indent);
278
				$xmlconfig .= "<$ent/>\n";
279
			} else if (!is_bool($val)) {
280
				$xmlconfig .= str_repeat("\t", $indent);
281
				if ((substr($ent, 0, 5) == "descr") ||
282
				    (substr($ent, 0, 6) == "detail") ||
283
				    (substr($ent, 0, 12) == "login_banner") ||
284
				    (substr($ent, 0, 9) == "ldap_attr") ||
285
				    (substr($ent, 0, 9) == "ldap_bind") ||
286
				    (substr($ent, 0, 11) == "ldap_basedn") ||
287
				    (substr($ent, 0, 18) == "ldap_authcn") ||
288
				    (substr($ent, 0, 19) == "ldap_extended_query")) {
289
					$xmlconfig .= "<$ent><![CDATA[" . htmlentities($val) . "]]></$ent>\n";
290
				} else {
291
					$xmlconfig .= "<$ent>" . htmlentities($val) . "</$ent>\n";
292
				}
293
			}
294
		}
295
	}
296

    
297
	return $xmlconfig;
298
}
299

    
300
function dump_xml_config($arr, $rootobj) {
301
	global $listtags;
302
	$listtags = listtags();
303
	if (isset($GLOBALS['custom_listtags'])) {
304
		foreach ($GLOBALS['custom_listtags'] as $tag) {
305
			$listtags[$tag] = $tag;
306
		}
307
	}
308
	return dump_xml_config_raw($arr, $rootobj);
309
}
310

    
311
function dump_xml_config_pkg($arr, $rootobj) {
312
	global $listtags;
313
	$listtags = listtags_pkg();
314
	if (isset($GLOBALS['custom_listtags_pkg'])) {
315
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
316
			$listtags[$tag] = $tag;
317
		}
318
	}
319
	return dump_xml_config_raw($arr, $rootobj);
320
}
321

    
322
function dump_xml_config_raw($arr, $rootobj) {
323

    
324
	$xmlconfig = "<?xml version=\"1.0\"?" . ">\n";
325
	$xmlconfig .= "<$rootobj>\n";
326

    
327
	$xmlconfig .= dump_xml_config_sub($arr, 1);
328

    
329
	$xmlconfig .= "</$rootobj>\n";
330

    
331
	return $xmlconfig;
332
}
333

    
334
?>
(62-62/68)