Project

General

Profile

Download (9.05 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
 * xmlreader.inc
4
 *
5
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2004-2016 Electric Sheep Fencing, LLC
7
 * All rights reserved.
8
 *
9
 * originally part of m0n0wall (http://m0n0.ch/wall)
10
 * Copyright (c) 2003-2004 Manuel Kasper <mk@neon1.net>.
11
 * All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *
16
 * 1. Redistributions of source code must retain the above copyright notice,
17
 *    this list of conditions and the following disclaimer.
18
 *
19
 * 2. Redistributions in binary form must reproduce the above copyright
20
 *    notice, this list of conditions and the following disclaimer in
21
 *    the documentation and/or other materials provided with the
22
 *    distribution.
23
 *
24
 * 3. All advertising materials mentioning features or use of this software
25
 *    must display the following acknowledgment:
26
 *    "This product includes software developed by the pfSense Project
27
 *    for use in the pfSense® software distribution. (http://www.pfsense.org/).
28
 *
29
 * 4. The names "pfSense" and "pfSense Project" must not be used to
30
 *    endorse or promote products derived from this software without
31
 *    prior written permission. For written permission, please contact
32
 *    coreteam@pfsense.org.
33
 *
34
 * 5. Products derived from this software may not be called "pfSense"
35
 *    nor may "pfSense" appear in their names without prior written
36
 *    permission of the Electric Sheep Fencing, LLC.
37
 *
38
 * 6. Redistributions of any form whatsoever must retain the following
39
 *    acknowledgment:
40
 *
41
 * "This product includes software developed by the pfSense Project
42
 * for use in the pfSense software distribution (http://www.pfsense.org/).
43
 *
44
 * THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
45
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
47
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
48
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
50
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
51
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
53
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
54
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
55
 * OF THE POSSIBILITY OF SUCH DAMAGE.
56
 */
57

    
58
/* The following items will be treated as arrays in config.xml */
59
function listtags() {
60
	/*
61
	 * Please keep this list alpha sorted and no longer than 80 characters
62
	 * I know it's a pain, but it's a pain to find stuff too if it's not
63
	 */
64
	$ret = array(
65
		'acls', 'alias', 'aliasurl', 'allowedip', 'allowedhostname', 'authserver',
66
		'bridged', 'build_port_path',
67
		'ca', 'cacert', 'cert', 'crl', 'clone', 'config', 'container', 'columnitem',
68
		'checkipservice',
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', '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)