Project

General

Profile

Download (8.99 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	xmlreader.inc
4
	functions to parse/dump configuration files in XML format
5

    
6
	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
	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
	   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
*/
58

    
59
/* The following items will be treated as arrays in config.xml */
60
function listtags() {
61
	/*
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
		'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
	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
	$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

    
93
	return array_flip($ret);
94
}
95

    
96
function add_elements(&$cfgarray, &$parser) {
97
	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
						add_elements($cfgref, $parser);
109
					} 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
				}
138

    
139
				$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
	}
156
}
157

    
158
function parse_xml_config($cffile, $rootobj, $isstring = "false") {
159
	global $listtags;
160

    
161
	$listtags = listtags();
162
	if (isset($GLOBALS['custom_listtags'])) {
163
		foreach ($GLOBALS['custom_listtags'] as $tag) {
164
			$listtags[$tag] = $tag;
165
		}
166
	}
167

    
168
	return parse_xml_config_raw($cffile, $rootobj);
169
}
170

    
171
function parse_xml_config_pkg($cffile, $rootobj, $isstring = "false") {
172
	global $listtags;
173

    
174
	$listtags = listtags_pkg();
175
	if (isset($GLOBALS['custom_listtags_pkg'])) {
176
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
177
			$listtags[$tag] = $tag;
178
		}
179
	}
180
	return parse_xml_config_raw($cffile, $rootobj, $isstring);
181
}
182

    
183
function parse_xml_config_raw($cffile, $rootobj, $isstring = "false") {
184
	global $listtags;
185

    
186
	$parsedcfg = array();
187

    
188
	$par = new XMLReader();
189
	if ($par->open($cffile, "UTF-8", LIBXML_NOERROR | LIBXML_NOWARNING)) {
190
		add_elements($parsedcfg, $par);
191
		$par->close();
192
	} else {
193
		log_error(sprintf(gettext("Error returned while trying to parse %s"), $cffile));
194
	}
195

    
196
	if ($rootobj) {
197
		if (!is_array($rootobj)) {
198
			$rootobj = array($rootobj);
199
		}
200
		foreach ($rootobj as $rootobj_name) {
201
			if ($parsedcfg[$rootobj_name]) {
202
				break;
203
			}
204
		}
205

    
206
		return $parsedcfg[$rootobj_name];
207
	} else {
208
		return $parsedcfg;
209
	}
210
}
211

    
212
function dump_xml_config_sub(& $writer, $arr) {
213
	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
							$writer->writeElement($ent, $cval);
236
						}
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
}
256

    
257
function dump_xml_config($arr, $rootobj) {
258
	global $listtags;
259

    
260
	$listtags = listtags();
261
	if (isset($GLOBALS['custom_listtags'])) {
262
		foreach ($GLOBALS['custom_listtags'] as $tag) {
263
			$listtags[$tag] = $tag;
264
		}
265
	}
266
	return dump_xml_config_raw($arr, $rootobj);
267
}
268

    
269
function dump_xml_config_pkg($arr, $rootobj) {
270
	global $listtags;
271

    
272
	$listtags = listtags_pkg();
273
	if (isset($GLOBALS['custom_listtags_pkg'])) {
274
		foreach ($GLOBALS['custom_listtags_pkg'] as $tag) {
275
			$listtags[$tag] = $tag;
276
		}
277
	}
278
	return dump_xml_config_raw($arr, $rootobj);
279
}
280

    
281
function dump_xml_config_raw($arr, $rootobj) {
282

    
283
	$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

    
290
	dump_xml_config_sub($writer, $arr);
291

    
292
	$writer->endElement();
293
	$writer->endDocument();
294
	$xmlconfig = $writer->outputMemory(true);
295

    
296
	return $xmlconfig;
297
}
298

    
299
?>
(62-62/65)