Project

General

Profile

Download (8.99 KB) Statistics
| Branch: | Tag: | Revision:
1 26433cb8 Scott Ullrich
<?php
2
/*
3 ce77a9c4 Phil Davis
	xmlreader.inc
4 26433cb8 Scott Ullrich
	functions to parse/dump configuration files in XML format
5
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 26433cb8 Scott Ullrich
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
12
	All rights reserved.
13
14
	Redistribution and use in source and binary forms, with or without
15
	modification, are permitted provided that the following conditions are met:
16
17
	1. Redistributions of source code must retain the above copyright notice,
18
	   this list of conditions and the following disclaimer.
19
20
	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 26433cb8 Scott Ullrich
*/
58
59
/* The following items will be treated as arrays in config.xml */
60
function listtags() {
61 72a8c829 Ermal
	/*
62 79262830 Phil Davis
	 * 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 b79ea46a Ermal
	$ret = array(
66 72a8c829 Ermal
		'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
		'npt', 'ntpserver',
77
		'onetoone', 'openvpn-server', 'openvpn-client', 'openvpn-csc', 'option',
78
		'package', 'passthrumac', 'phase1', 'phase2', 'ppp', 'pppoe', 'priv', 'proxyarpnet', 'pool',
79
		'qinqentry', 'queue',
80
		'pages', 'pipe', 'radnsserver', 'roll', 'route', 'row', 'rrddatafile', 'rule',
81
		'schedule', 'service', 'servernat', 'servers',
82
		'serversdisabled', 'shellcmd', 'staticmap', 'subqueue',
83
		'timerange', 'tunnel', 'user', 'vip', 'virtual_server', 'vlan',
84
		'winsserver', 'wolentry', 'widget'
85
	);
86 26433cb8 Scott Ullrich
	return array_flip($ret);
87
}
88
89
/* Package XML tags that should be treat as a list not as a traditional array */
90
function listtags_pkg() {
91 b79ea46a Ermal
	$ret = array('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 26433cb8 Scott Ullrich
93
	return array_flip($ret);
94
}
95
96
function add_elements(&$cfgarray, &$parser) {
97 79262830 Phil Davis
	global $listtags;
98
99
	while ($parser->read()) {
100
		switch ($parser->nodeType) {
101
			case XMLReader::WHITESPACE:
102
			case XMLReader::SIGNIFICANT_WHITESPACE:
103
				break;
104
			case XMLReader::ELEMENT:
105
				if (isset($listtags[strtolower($parser->name)])) {
106
					$cfgref =& $cfgarray[$parser->name][count($cfgarray[$parser->name])];
107
					if (!$parser->isEmptyElement) {
108 ddfe5e43 Ermal
						add_elements($cfgref, $parser);
109 79262830 Phil Davis
					} else {
110
						$cfgref = array();
111
					}
112
				} else {
113
					if (isset($cfgarray[$parser->name]) && (!is_array($cfgarray[$parser->name]) || !isset($cfgarray[$parser->name][0]))) {
114
						$nodebkp = $cfgarray[$parser->name];
115
						$cfgarray[$parser->name] = array();
116
						$cfgarray[$parser->name][] = $nodebkp;
117
						$cfgref =& $cfgarray[$parser->name][0];
118
						unset($nodebkp);
119
					} else {
120
						$cfgref =& $cfgarray[$parser->name];
121
					}
122
123
					if ($parser->isEmptyElement) {
124
						if (is_array($cfgref)) {
125
							$cfgref[] = array();
126
						} else {
127
							$cfgref = "";
128
						}
129
					} else {
130
						if (is_array($cfgref)) {
131
							$cfgref =& $cfgarray[$parser->name][count($cfgarray[$parser->name])];
132
							add_elements($cfgref, $parser);
133
						} else {
134
							add_elements($cfgref, $parser);
135
						}
136
					}
137 ddfe5e43 Ermal
				}
138 8ffb5ccd Ermal
139 79262830 Phil Davis
				$i = 0;
140
				while ($parser->moveToAttributeNo($i)) {
141
					$cfgref[$parser->name] = $parser->value;
142
					$i++;
143
				}
144
				break;
145
			case XMLReader::TEXT:
146
			case XMLReader::CDATA:
147
				$cfgarray = $parser->value;
148
				break;
149
			case XMLReader::END_ELEMENT:
150
				return;
151
				break;
152
			default:
153
				break;
154
		}
155 ab83fce0 Ermal
	}
156 26433cb8 Scott Ullrich
}
157
158
function parse_xml_config($cffile, $rootobj, $isstring = "false") {
159
	global $listtags;
160 b79ea46a Ermal
161 26433cb8 Scott Ullrich
	$listtags = listtags();
162 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags'])) {
163
		foreach ($GLOBALS['custom_listtags'] as $tag) {
164
			$listtags[$tag] = $tag;
165
		}
166
	}
167 ab83fce0 Ermal
168 26433cb8 Scott Ullrich
	return parse_xml_config_raw($cffile, $rootobj);
169
}
170
171
function parse_xml_config_pkg($cffile, $rootobj, $isstring = "false") {
172
	global $listtags;
173 b79ea46a Ermal
174 26433cb8 Scott Ullrich
	$listtags = listtags_pkg();
175 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags_pkg'])) {
176
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
177
			$listtags[$tag] = $tag;
178
		}
179
	}
180 26433cb8 Scott Ullrich
	return parse_xml_config_raw($cffile, $rootobj, $isstring);
181
}
182
183
function parse_xml_config_raw($cffile, $rootobj, $isstring = "false") {
184 b79ea46a Ermal
	global $listtags;
185 26433cb8 Scott Ullrich
186
	$parsedcfg = array();
187
188
	$par = new XMLReader();
189 ab83fce0 Ermal
	if ($par->open($cffile, "UTF-8", LIBXML_NOERROR | LIBXML_NOWARNING)) {
190 26433cb8 Scott Ullrich
		add_elements($parsedcfg, $par);
191
		$par->close();
192 79262830 Phil Davis
	} else {
193 5cfa35df Renato Botelho
		log_error(sprintf(gettext("Error returned while trying to parse %s"), $cffile));
194 79262830 Phil Davis
	}
195 26433cb8 Scott Ullrich
196 428c289f Darren Embry
	if ($rootobj) {
197 79262830 Phil Davis
		if (!is_array($rootobj)) {
198 428c289f Darren Embry
			$rootobj = array($rootobj);
199 79262830 Phil Davis
		}
200
		foreach ($rootobj as $rootobj_name) {
201
			if ($parsedcfg[$rootobj_name]) {
202 428c289f Darren Embry
				break;
203 79262830 Phil Davis
			}
204
		}
205
206 428c289f Darren Embry
		return $parsedcfg[$rootobj_name];
207
	} else {
208
		return $parsedcfg;
209
	}
210 26433cb8 Scott Ullrich
}
211
212 ab83fce0 Ermal
function dump_xml_config_sub(& $writer, $arr) {
213 79262830 Phil Davis
	global $listtags;
214
215
	foreach ($arr as $ent => $val) {
216
		if (is_array($val)) {
217
			/* is it just a list of multiple values? */
218
			if (isset($listtags[strtolower($ent)])) {
219
				foreach ($val as $cval) {
220
					if (is_array($cval)) {
221
						if (empty($cval)) {
222
							$writer->writeElement($ent);
223
						} else {
224
							$writer->startElement($ent);
225
							dump_xml_config_sub($writer, $cval);
226
							$writer->endElement();
227
						}
228
					} else {
229
						if ($cval === false) {
230
							continue;
231
						}
232
						if ((is_bool($val) && ($val == true)) || ($val === "")) {
233
							$writer->writeElement($ent);
234
						} else if (!is_bool($val)) {
235 ab83fce0 Ermal
							$writer->writeElement($ent, $cval);
236 79262830 Phil Davis
						}
237
					}
238
				}
239
			} else if (empty($val)) {
240
				$writer->writeElement($ent);
241
			} else {
242
				/* it's an array */
243
				$writer->startElement($ent);
244
				dump_xml_config_sub($writer, $val);
245
				$writer->endElement();
246
			}
247
		} else {
248
			if ((is_bool($val) && ($val == true)) || ($val === "")) {
249
				$writer->writeElement($ent);
250
			} else if (!is_bool($val)) {
251
				$writer->writeElement($ent, $val);
252
			}
253
		}
254
	}
255 26433cb8 Scott Ullrich
}
256
257
function dump_xml_config($arr, $rootobj) {
258
	global $listtags;
259 b79ea46a Ermal
260 26433cb8 Scott Ullrich
	$listtags = listtags();
261 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags'])) {
262
		foreach ($GLOBALS['custom_listtags'] as $tag) {
263
			$listtags[$tag] = $tag;
264
		}
265
	}
266 26433cb8 Scott Ullrich
	return dump_xml_config_raw($arr, $rootobj);
267
}
268
269
function dump_xml_config_pkg($arr, $rootobj) {
270
	global $listtags;
271 b79ea46a Ermal
272 26433cb8 Scott Ullrich
	$listtags = listtags_pkg();
273 79262830 Phil Davis
	if (isset($GLOBALS['custom_listtags_pkg'])) {
274
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
275
			$listtags[$tag] = $tag;
276
		}
277
	}
278 26433cb8 Scott Ullrich
	return dump_xml_config_raw($arr, $rootobj);
279
}
280
281
function dump_xml_config_raw($arr, $rootobj) {
282
283 79262830 Phil Davis
	$writer = new XMLWriter();
284
	$writer->openMemory();
285
	$writer->setIndent(true);
286
	$writer->setIndentString("\t");
287
	$writer->startDocument("1.0", "UTF-8");
288
	$writer->startElement($rootobj);
289 26433cb8 Scott Ullrich
290 79262830 Phil Davis
	dump_xml_config_sub($writer, $arr);
291 26433cb8 Scott Ullrich
292 79262830 Phil Davis
	$writer->endElement();
293
	$writer->endDocument();
294
	$xmlconfig = $writer->outputMemory(true);
295 b79ea46a Ermal
296 79262830 Phil Davis
	return $xmlconfig;
297 26433cb8 Scott Ullrich
}
298
299
?>