Project

General

Profile

Download (10.9 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2
/*
3
	xmlparse.inc
4
	functions to parse/dump configuration files in XML format
5 528ae96e Scott Ullrich
6 09221bc3 Renato Botelho
	part of pfSense (https://www.pfsense.org)
7
	Copyright (c) 2004-2016 Electric Sheep Fencing, LLC.
8
	All rights reserved.
9
10
	originally part of m0n0wall (http://m0n0.ch/wall)
11 5b237745 Scott Ullrich
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
12
	All rights reserved.
13 528ae96e Scott Ullrich
14 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
15
	modification, are permitted provided that the following conditions are met:
16 528ae96e Scott Ullrich
17 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
18
	   this list of conditions and the following disclaimer.
19 528ae96e Scott Ullrich
20 5b237745 Scott Ullrich
	2. Redistributions in binary form must reproduce the above copyright
21 09221bc3 Renato Botelho
	   notice, this list of conditions and the following disclaimer in
22
	   the documentation and/or other materials provided with the
23
	   distribution.
24
25
	3. All advertising materials mentioning features or use of this software
26
	   must display the following acknowledgment:
27
	   "This product includes software developed by the pfSense Project
28
	   for use in the pfSense® software distribution. (http://www.pfsense.org/).
29
30
	4. The names "pfSense" and "pfSense Project" must not be used to
31
	   endorse or promote products derived from this software without
32
	   prior written permission. For written permission, please contact
33
	   coreteam@pfsense.org.
34
35
	5. Products derived from this software may not be called "pfSense"
36
	   nor may "pfSense" appear in their names without prior written
37
	   permission of the Electric Sheep Fencing, LLC.
38
39
	6. Redistributions of any form whatsoever must retain the following
40
	   acknowledgment:
41
42
	"This product includes software developed by the pfSense Project
43
	for use in the pfSense software distribution (http://www.pfsense.org/).
44
45
	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
46
	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47
	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
48
	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
49
	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50
	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51
	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
52
	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53
	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
54
	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
55
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
56
	OF THE POSSIBILITY OF SUCH DAMAGE.
57 5b237745 Scott Ullrich
*/
58
59 2e5ebf5d Scott Ullrich
/* The following items will be treated as arrays in config.xml */
60 eeb6c16e Bill Marquette
function listtags() {
61 72a8c829 Ermal
	/*
62
	 * Please keep this list alpha sorted and no longer than 80 characters
63
	 * I know it's a pain, but it's a pain to find stuff too if it's not
64
	 */
65
	$ret = array(
66 79262830 Phil Davis
		'acls', 'alias', 'aliasurl', 'allowedip', 'allowedhostname', 'authserver',
67
		'bridged', 'build_port_path',
68
		'ca', 'cacert', 'cert', 'crl', 'clone', 'config', 'container', 'columnitem',
69
		'depends_on_package', 'disk', 'dnsserver', 'dnsupdate', 'domainoverrides', 'dyndns',
70
		'earlyshellcmd', 'element', 'encryption-algorithm-option',
71
		'field', 'fieldname',
72
		'gateway_item', 'gateway_group', 'gif', 'gre', 'group',
73
		'hash-algorithm-option', 'hosts', 'member', 'ifgroupentry', 'igmpentry', 'interface_array', 'item', 'key',
74
		'lagg', 'lbaction', 'lbpool', 'l7rules', 'lbprotocol',
75
		'member', 'menu', 'tab', 'mobilekey', 'monitor_type', 'mount',
76 72a8c829 Ermal
		'npt', 'ntpserver',
77 79262830 Phil Davis
		'onetoone', 'openvpn-server', 'openvpn-client', 'openvpn-csc', 'option',
78
		'package', 'passthrumac', 'phase1', 'phase2', 'ppp', 'pppoe', 'priv', 'proxyarpnet', 'pool',
79 72a8c829 Ermal
		'qinqentry', 'queue',
80 79262830 Phil Davis
		'pages', 'pipe', 'radnsserver', 'roll', 'route', 'row', 'rrddatafile', 'rule',
81 72a8c829 Ermal
		'schedule', 'service', 'servernat', 'servers',
82 79262830 Phil Davis
		'serversdisabled', 'shellcmd', 'staticmap', 'subqueue',
83 72a8c829 Ermal
		'timerange', 'tunnel', 'user', 'vip', 'virtual_server', 'vlan',
84
		'winsserver', 'wolentry', 'widget'
85
	);
86 6d84c956 Ermal
	return array_flip($ret);
87 eeb6c16e Bill Marquette
}
88
89 79262830 Phil Davis
/* Package XML tags that should be treated as a list not as a traditional array */
90 eeb6c16e Bill Marquette
function listtags_pkg() {
91 72a8c829 Ermal
	$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');
92 eeb6c16e Bill Marquette
93 1c62178a Ermal
	return array_flip($ret);
94 eeb6c16e Bill Marquette
}
95
96 26433cb8 Scott Ullrich
function startElement($parser, $name, $attrs) {
97 1fb064e8 Erik Fonnesbeck
	global $parsedcfg, $depth, $curpath, $havedata, $listtags;
98 528ae96e Scott Ullrich
99 26433cb8 Scott Ullrich
	array_push($curpath, strtolower($name));
100
101
	$ptr =& $parsedcfg;
102
	foreach ($curpath as $path) {
103
		$ptr =& $ptr[$path];
104
	}
105
106
	/* is it an element that belongs to a list? */
107 6d84c956 Ermal
	if (isset($listtags[strtolower($name)])) {
108 26433cb8 Scott Ullrich
109
		/* is there an array already? */
110
		if (!is_array($ptr)) {
111
			/* make an array */
112
			$ptr = array();
113
		}
114
115
		array_push($curpath, count($ptr));
116
117
	} else if (isset($ptr)) {
118
		/* multiple entries not allowed for this element, bail out */
119 addc0439 Renato Botelho
		die(sprintf(gettext('XML error: %1$s at line %2$d cannot occur more than once') . "\n",
120 79262830 Phil Davis
		    $name,
121
		    xml_get_current_line_number($parser)));
122 26433cb8 Scott Ullrich
	}
123
124
	$depth++;
125
	$havedata = $depth;
126
}
127
128
function endElement($parser, $name) {
129
	global $depth, $curpath, $parsedcfg, $havedata, $listtags;
130
131
	if ($havedata == $depth) {
132
		$ptr =& $parsedcfg;
133
		foreach ($curpath as $path) {
134
			$ptr =& $ptr[$path];
135
		}
136
		$ptr = "";
137
	}
138
139
	array_pop($curpath);
140
141 79262830 Phil Davis
	if (isset($listtags[strtolower($name)])) {
142 26433cb8 Scott Ullrich
		array_pop($curpath);
143 79262830 Phil Davis
	}
144 26433cb8 Scott Ullrich
145
	$depth--;
146
}
147
148
function cData($parser, $data) {
149
	global $depth, $curpath, $parsedcfg, $havedata;
150
151
	$data = trim($data, "\t\n\r");
152
153
	if ($data != "") {
154
		$ptr =& $parsedcfg;
155
		foreach ($curpath as $path) {
156
			$ptr =& $ptr[$path];
157
		}
158
159
		if (is_string($ptr)) {
160 2e6a43a1 Ermal
			$ptr .= html_entity_decode($data);
161 26433cb8 Scott Ullrich
		} else {
162
			if (trim($data, " ") != "") {
163 2e6a43a1 Ermal
				$ptr = html_entity_decode($data);
164 26433cb8 Scott Ullrich
				$havedata++;
165
			}
166
		}
167
	}
168 5b237745 Scott Ullrich
}
169
170 48ca2dc9 Colin Smith
function parse_xml_config($cffile, $rootobj, $isstring = "false") {
171 cb980a2f Colin Smith
	global $listtags;
172 eeb6c16e Bill Marquette
	$listtags = listtags();
173 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags'])) {
174
		foreach ($GLOBALS['custom_listtags'] as $tag) {
175
			$listtags[$tag] = $tag;
176
		}
177
	}
178 26433cb8 Scott Ullrich
	return parse_xml_config_raw($cffile, $rootobj, $isstring);
179 cb980a2f Colin Smith
}
180
181 48ca2dc9 Colin Smith
function parse_xml_config_pkg($cffile, $rootobj, $isstring = "false") {
182 cb980a2f Colin Smith
	global $listtags;
183 eeb6c16e Bill Marquette
	$listtags = listtags_pkg();
184 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags_pkg'])) {
185
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
186
			$listtags[$tag] = $tag;
187
		}
188
	}
189 bef6cb99 Ermal
	$cfg =parse_xml_config_raw($cffile, $rootobj, $isstring);
190 79262830 Phil Davis
	if ($cfg == -1) {
191 187ce62b Ermal
		return array();
192 79262830 Phil Davis
	}
193
194 bef6cb99 Ermal
	return $cfg;
195 cb980a2f Colin Smith
}
196
197 48ca2dc9 Colin Smith
function parse_xml_config_raw($cffile, $rootobj, $isstring = "false") {
198 5b237745 Scott Ullrich
199 26433cb8 Scott Ullrich
	global $depth, $curpath, $parsedcfg, $havedata, $listtags;
200 08c3872d Colin Smith
	$parsedcfg = array();
201 26433cb8 Scott Ullrich
	$curpath = array();
202
	$depth = 0;
203
	$havedata = 0;
204
205
	$xml_parser = xml_parser_create();
206
207
	xml_set_element_handler($xml_parser, "startElement", "endElement");
208
	xml_set_character_data_handler($xml_parser, "cdata");
209 086cf944 Phil Davis
	xml_parser_set_option($xml_parser, XML_OPTION_SKIP_WHITE, 1);
210 26433cb8 Scott Ullrich
211
	if (!($fp = fopen($cffile, "r"))) {
212 ada992bd Renato Botelho
		log_error(gettext("Error: could not open XML input") . "\n");
213 541989d5 Ermal
		return -1;
214 26433cb8 Scott Ullrich
	}
215 d7b6c842 Ermal Lu?i
216 26433cb8 Scott Ullrich
	while ($data = fread($fp, 4096)) {
217
		if (!xml_parse($xml_parser, $data, feof($fp))) {
218 c92ccac7 Vinicius Coque
			log_error(sprintf(gettext('XML error: %1$s at line %2$d in %3$s') . "\n",
219 79262830 Phil Davis
				xml_error_string(xml_get_error_code($xml_parser)),
220
				xml_get_current_line_number($xml_parser),
221
				$cffile));
222 26433cb8 Scott Ullrich
			return -1;
223
		}
224
	}
225
	xml_parser_free($xml_parser);
226
227 428c289f Darren Embry
	if ($rootobj) {
228 79262830 Phil Davis
		if (!is_array($rootobj)) {
229 428c289f Darren Embry
			$rootobj = array($rootobj);
230 79262830 Phil Davis
		}
231
		foreach ($rootobj as $rootobj_name) {
232
			if ($parsedcfg[$rootobj_name]) {
233 428c289f Darren Embry
				break;
234 79262830 Phil Davis
			}
235
		}
236
237 428c289f Darren Embry
		if (!$parsedcfg[$rootobj_name]) {
238
			log_error(sprintf(gettext("XML error: no %s object found!") . "\n", implode(" or ", $rootobj)));
239
			return -1;
240
		}
241
		return $parsedcfg[$rootobj_name];
242
	} else {
243
		return $parsedcfg;
244 26433cb8 Scott Ullrich
	}
245 5b237745 Scott Ullrich
}
246
247
function dump_xml_config_sub($arr, $indent) {
248
249
	global $listtags;
250 528ae96e Scott Ullrich
251 5b237745 Scott Ullrich
	$xmlconfig = "";
252
253
	foreach ($arr as $ent => $val) {
254
		if (is_array($val)) {
255
			/* is it just a list of multiple values? */
256 6d84c956 Ermal
			if (isset($listtags[strtolower($ent)])) {
257 5b237745 Scott Ullrich
				foreach ($val as $cval) {
258
					if (is_array($cval)) {
259 70d6b5c4 Ermal
						if (empty($cval)) {
260
							$xmlconfig .= str_repeat("\t", $indent);
261
							$xmlconfig .= "<$ent/>\n";
262
						} else {
263
							$xmlconfig .= str_repeat("\t", $indent);
264
							$xmlconfig .= "<$ent>\n";
265
							$xmlconfig .= dump_xml_config_sub($cval, $indent + 1);
266
							$xmlconfig .= str_repeat("\t", $indent);
267
							$xmlconfig .= "</$ent>\n";
268
						}
269 5b237745 Scott Ullrich
					} else {
270 79262830 Phil Davis
						if ($cval === false) {
271
							continue;
272
						}
273 70d6b5c4 Ermal
						$xmlconfig .= str_repeat("\t", $indent);
274 79262830 Phil Davis
						if ((is_bool($cval) && $cval == true) || ($cval === "")) {
275 5b237745 Scott Ullrich
							$xmlconfig .= "<$ent/>\n";
276 79262830 Phil Davis
						} else if ((substr($ent, 0, 5) == "descr") ||
277
						    (substr($ent, 0, 6) == "detail") ||
278
						    (substr($ent, 0, 12) == "login_banner") ||
279
						    (substr($ent, 0, 9) == "ldap_attr") ||
280
						    (substr($ent, 0, 9) == "ldap_bind") ||
281
						    (substr($ent, 0, 11) == "ldap_basedn") ||
282
						    (substr($ent, 0, 18) == "ldap_authcn") ||
283
						    (substr($ent, 0, 19) == "ldap_extended_query")) {
284 02611466 Ermal
							$xmlconfig .= "<$ent><![CDATA[" . htmlentities($cval) . "]]></$ent>\n";
285 0d57f5f3 Scott Ullrich
						} else {
286 2e6a43a1 Ermal
							$xmlconfig .= "<$ent>" . htmlentities($cval) . "</$ent>\n";
287 70d6b5c4 Ermal
						}
288 5b237745 Scott Ullrich
					}
289
				}
290 78dd5020 Ermal Lu?i
			} else if (empty($val)) {
291
				$xmlconfig .= str_repeat("\t", $indent);
292
				$xmlconfig .= "<$ent/>\n";
293 5b237745 Scott Ullrich
			} else {
294
				/* it's an array */
295
				$xmlconfig .= str_repeat("\t", $indent);
296
				$xmlconfig .= "<$ent>\n";
297
				$xmlconfig .= dump_xml_config_sub($val, $indent + 1);
298
				$xmlconfig .= str_repeat("\t", $indent);
299
				$xmlconfig .= "</$ent>\n";
300
			}
301
		} else {
302
			if ((is_bool($val) && ($val == true)) || ($val === "")) {
303
				$xmlconfig .= str_repeat("\t", $indent);
304
				$xmlconfig .= "<$ent/>\n";
305
			} else if (!is_bool($val)) {
306
				$xmlconfig .= str_repeat("\t", $indent);
307 79262830 Phil Davis
				if ((substr($ent, 0, 5) == "descr") ||
308
				    (substr($ent, 0, 6) == "detail") ||
309
				    (substr($ent, 0, 12) == "login_banner") ||
310
				    (substr($ent, 0, 9) == "ldap_attr") ||
311
				    (substr($ent, 0, 9) == "ldap_bind") ||
312
				    (substr($ent, 0, 11) == "ldap_basedn") ||
313
				    (substr($ent, 0, 18) == "ldap_authcn") ||
314 086cf944 Phil Davis
				    (substr($ent, 0, 19) == "ldap_extended_query")) {
315 02611466 Ermal
					$xmlconfig .= "<$ent><![CDATA[" . htmlentities($val) . "]]></$ent>\n";
316 086cf944 Phil Davis
				} else {
317 2e6a43a1 Ermal
					$xmlconfig .= "<$ent>" . htmlentities($val) . "</$ent>\n";
318 79262830 Phil Davis
				}
319 5b237745 Scott Ullrich
			}
320
		}
321
	}
322 528ae96e Scott Ullrich
323 5b237745 Scott Ullrich
	return $xmlconfig;
324
}
325
326
function dump_xml_config($arr, $rootobj) {
327 ba6882bf Colin Smith
	global $listtags;
328 eeb6c16e Bill Marquette
	$listtags = listtags();
329 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags'])) {
330
		foreach ($GLOBALS['custom_listtags'] as $tag) {
331
			$listtags[$tag] = $tag;
332
		}
333
	}
334 ba6882bf Colin Smith
	return dump_xml_config_raw($arr, $rootobj);
335
}
336
337
function dump_xml_config_pkg($arr, $rootobj) {
338
	global $listtags;
339 eeb6c16e Bill Marquette
	$listtags = listtags_pkg();
340 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags_pkg'])) {
341
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
342
			$listtags[$tag] = $tag;
343
		}
344
	}
345 ba6882bf Colin Smith
	return dump_xml_config_raw($arr, $rootobj);
346
}
347
348
function dump_xml_config_raw($arr, $rootobj) {
349 5b237745 Scott Ullrich
350
	$xmlconfig = "<?xml version=\"1.0\"?" . ">\n";
351
	$xmlconfig .= "<$rootobj>\n";
352 528ae96e Scott Ullrich
353 5b237745 Scott Ullrich
	$xmlconfig .= dump_xml_config_sub($arr, 1);
354 528ae96e Scott Ullrich
355 5b237745 Scott Ullrich
	$xmlconfig .= "</$rootobj>\n";
356 528ae96e Scott Ullrich
357 5b237745 Scott Ullrich
	return $xmlconfig;
358
}
359
360 187ce62b Ermal
?>