xref: /PHP-7.2/ext/dom/document.c (revision cec8b24c)
1 /*
2    +----------------------------------------------------------------------+
3    | PHP Version 7                                                        |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1997-2018 The PHP Group                                |
6    +----------------------------------------------------------------------+
7    | This source file is subject to version 3.01 of the PHP license,      |
8    | that is bundled with this package in the file LICENSE, and is        |
9    | available through the world-wide-web at the following url:           |
10    | http://www.php.net/license/3_01.txt                                  |
11    | If you did not receive a copy of the PHP license and are unable to   |
12    | obtain it through the world-wide-web, please send a note to          |
13    | license@php.net so we can mail you a copy immediately.               |
14    +----------------------------------------------------------------------+
15    | Authors: Christian Stocker <chregu@php.net>                          |
16    |          Rob Richards <rrichards@php.net>                            |
17    +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "php.h"
27 #if HAVE_LIBXML && HAVE_DOM
28 #include "php_dom.h"
29 #include <libxml/SAX.h>
30 #ifdef LIBXML_SCHEMAS_ENABLED
31 #include <libxml/relaxng.h>
32 #include <libxml/xmlschemas.h>
33 #endif
34 
35 typedef struct _idsIterator idsIterator;
36 struct _idsIterator {
37 	xmlChar *elementId;
38 	xmlNode *element;
39 };
40 
41 #define DOM_LOAD_STRING 0
42 #define DOM_LOAD_FILE 1
43 
44 /* {{{ arginfo */
45 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_element, 0, 0, 1)
46 	ZEND_ARG_INFO(0, tagName)
47 	ZEND_ARG_INFO(0, value)
48 ZEND_END_ARG_INFO();
49 
50 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_document_fragment, 0, 0, 0)
51 ZEND_END_ARG_INFO();
52 
53 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_text_node, 0, 0, 1)
54 	ZEND_ARG_INFO(0, data)
55 ZEND_END_ARG_INFO();
56 
57 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_comment, 0, 0, 1)
58 	ZEND_ARG_INFO(0, data)
59 ZEND_END_ARG_INFO();
60 
61 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_cdatasection, 0, 0, 1)
62 	ZEND_ARG_INFO(0, data)
63 ZEND_END_ARG_INFO();
64 
65 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_processing_instruction, 0, 0, 2)
66 	ZEND_ARG_INFO(0, target)
67 	ZEND_ARG_INFO(0, data)
68 ZEND_END_ARG_INFO();
69 
70 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_attribute, 0, 0, 1)
71 	ZEND_ARG_INFO(0, name)
72 ZEND_END_ARG_INFO();
73 
74 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_entity_reference, 0, 0, 1)
75 	ZEND_ARG_INFO(0, name)
76 ZEND_END_ARG_INFO();
77 
78 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_get_elements_by_tag_name, 0, 0, 1)
79 	ZEND_ARG_INFO(0, tagName)
80 ZEND_END_ARG_INFO();
81 
82 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_import_node, 0, 0, 2)
83 	ZEND_ARG_OBJ_INFO(0, importedNode, DOMNode, 0)
84 	ZEND_ARG_INFO(0, deep)
85 ZEND_END_ARG_INFO();
86 
87 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_element_ns, 0, 0, 2)
88 	ZEND_ARG_INFO(0, namespaceURI)
89 	ZEND_ARG_INFO(0, qualifiedName)
90 	ZEND_ARG_INFO(0, value)
91 ZEND_END_ARG_INFO();
92 
93 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_create_attribute_ns, 0, 0, 2)
94 	ZEND_ARG_INFO(0, namespaceURI)
95 	ZEND_ARG_INFO(0, qualifiedName)
96 ZEND_END_ARG_INFO();
97 
98 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_get_elements_by_tag_name_ns, 0, 0, 2)
99 	ZEND_ARG_INFO(0, namespaceURI)
100 	ZEND_ARG_INFO(0, localName)
101 ZEND_END_ARG_INFO();
102 
103 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_get_element_by_id, 0, 0, 1)
104 	ZEND_ARG_INFO(0, elementId)
105 ZEND_END_ARG_INFO();
106 
107 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_adopt_node, 0, 0, 1)
108 	ZEND_ARG_OBJ_INFO(0, source, DOMNode, 0)
109 ZEND_END_ARG_INFO();
110 
111 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_normalize_document, 0, 0, 0)
112 ZEND_END_ARG_INFO();
113 
114 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_rename_node, 0, 0, 3)
115 	ZEND_ARG_OBJ_INFO(0, node, DOMNode, 0)
116 	ZEND_ARG_INFO(0, namespaceURI)
117 	ZEND_ARG_INFO(0, qualifiedName)
118 ZEND_END_ARG_INFO();
119 
120 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_load, 0, 0, 1)
121 	ZEND_ARG_INFO(0, source)
122 	ZEND_ARG_INFO(0, options)
123 ZEND_END_ARG_INFO();
124 
125 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_save, 0, 0, 1)
126 	ZEND_ARG_INFO(0, file)
127 ZEND_END_ARG_INFO();
128 
129 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadxml, 0, 0, 1)
130 	ZEND_ARG_INFO(0, source)
131 	ZEND_ARG_INFO(0, options)
132 ZEND_END_ARG_INFO();
133 
134 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_savexml, 0, 0, 0)
135 	ZEND_ARG_OBJ_INFO(0, node, DOMNode, 1)
136 	ZEND_ARG_INFO(0, options)
137 ZEND_END_ARG_INFO();
138 
139 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_construct, 0, 0, 0)
140 	ZEND_ARG_INFO(0, version)
141 	ZEND_ARG_INFO(0, encoding)
142 ZEND_END_ARG_INFO();
143 
144 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_validate, 0, 0, 0)
145 ZEND_END_ARG_INFO();
146 
147 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_xinclude, 0, 0, 0)
148 	ZEND_ARG_INFO(0, options)
149 ZEND_END_ARG_INFO();
150 
151 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadhtml, 0, 0, 1)
152 	ZEND_ARG_INFO(0, source)
153 	ZEND_ARG_INFO(0, options)
154 ZEND_END_ARG_INFO();
155 
156 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_loadhtmlfile, 0, 0, 1)
157 	ZEND_ARG_INFO(0, source)
158 	ZEND_ARG_INFO(0, options)
159 ZEND_END_ARG_INFO();
160 
161 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_savehtml, 0, 0, 0)
162 ZEND_END_ARG_INFO();
163 
164 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_savehtmlfile, 0, 0, 1)
165 	ZEND_ARG_INFO(0, file)
166 ZEND_END_ARG_INFO();
167 
168 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_schema_validate_file, 0, 0, 1)
169 	ZEND_ARG_INFO(0, filename)
170 ZEND_END_ARG_INFO();
171 
172 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_schema_validate_xml, 0, 0, 1)
173 	ZEND_ARG_INFO(0, source)
174 ZEND_END_ARG_INFO();
175 
176 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_relaxNG_validate_file, 0, 0, 1)
177 	ZEND_ARG_INFO(0, filename)
178 ZEND_END_ARG_INFO();
179 
180 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_relaxNG_validate_xml, 0, 0, 1)
181 	ZEND_ARG_INFO(0, source)
182 ZEND_END_ARG_INFO();
183 
184 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_document_registernodeclass, 0, 0, 2)
185 	ZEND_ARG_INFO(0, baseClass)
186 	ZEND_ARG_INFO(0, extendedClass)
187 ZEND_END_ARG_INFO();
188 /* }}} */
189 
190 /*
191 * class DOMDocument extends DOMNode
192 *
193 * URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-i-Document
194 * Since:
195 */
196 
197 const zend_function_entry php_dom_document_class_functions[] = { /* {{{ */
198 	PHP_FALIAS(createElement, dom_document_create_element, arginfo_dom_document_create_element)
199 	PHP_FALIAS(createDocumentFragment, dom_document_create_document_fragment, arginfo_dom_document_create_document_fragment)
200 	PHP_FALIAS(createTextNode, dom_document_create_text_node, arginfo_dom_document_create_text_node)
201 	PHP_FALIAS(createComment, dom_document_create_comment, arginfo_dom_document_create_comment)
202 	PHP_FALIAS(createCDATASection, dom_document_create_cdatasection, arginfo_dom_document_create_cdatasection)
203 	PHP_FALIAS(createProcessingInstruction, dom_document_create_processing_instruction, arginfo_dom_document_create_processing_instruction)
204 	PHP_FALIAS(createAttribute, dom_document_create_attribute, arginfo_dom_document_create_attribute)
205 	PHP_FALIAS(createEntityReference, dom_document_create_entity_reference, arginfo_dom_document_create_entity_reference)
206 	PHP_FALIAS(getElementsByTagName, dom_document_get_elements_by_tag_name, arginfo_dom_document_get_elements_by_tag_name)
207 	PHP_FALIAS(importNode, dom_document_import_node, arginfo_dom_document_import_node)
208 	PHP_FALIAS(createElementNS, dom_document_create_element_ns, arginfo_dom_document_create_element_ns)
209 	PHP_FALIAS(createAttributeNS, dom_document_create_attribute_ns, arginfo_dom_document_create_attribute_ns)
210 	PHP_FALIAS(getElementsByTagNameNS, dom_document_get_elements_by_tag_name_ns, arginfo_dom_document_get_elements_by_tag_name_ns)
211 	PHP_FALIAS(getElementById, dom_document_get_element_by_id, arginfo_dom_document_get_element_by_id)
212 	PHP_FALIAS(adoptNode, dom_document_adopt_node, arginfo_dom_document_adopt_node)
213 	PHP_FALIAS(normalizeDocument, dom_document_normalize_document, arginfo_dom_document_normalize_document)
214 	PHP_FALIAS(renameNode, dom_document_rename_node, arginfo_dom_document_rename_node)
215 	PHP_ME(domdocument, load, arginfo_dom_document_load, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
216 	PHP_FALIAS(save, dom_document_save, arginfo_dom_document_save)
217 	PHP_ME(domdocument, loadXML, arginfo_dom_document_loadxml, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
218 	PHP_FALIAS(saveXML, dom_document_savexml, arginfo_dom_document_savexml)
219 	PHP_ME(domdocument, __construct, arginfo_dom_document_construct, ZEND_ACC_PUBLIC)
220 	PHP_FALIAS(validate, dom_document_validate, arginfo_dom_document_validate)
221 	PHP_FALIAS(xinclude, dom_document_xinclude, arginfo_dom_document_xinclude)
222 #if defined(LIBXML_HTML_ENABLED)
223 	PHP_ME(domdocument, loadHTML, arginfo_dom_document_loadhtml, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
224 	PHP_ME(domdocument, loadHTMLFile, arginfo_dom_document_loadhtmlfile, ZEND_ACC_PUBLIC|ZEND_ACC_ALLOW_STATIC)
225 	PHP_FALIAS(saveHTML, dom_document_save_html, arginfo_dom_document_savehtml)
226 	PHP_FALIAS(saveHTMLFile, dom_document_save_html_file, arginfo_dom_document_savehtmlfile)
227 #endif  /* defined(LIBXML_HTML_ENABLED) */
228 #if defined(LIBXML_SCHEMAS_ENABLED)
229 	PHP_FALIAS(schemaValidate, dom_document_schema_validate_file, arginfo_dom_document_schema_validate_file)
230 	PHP_FALIAS(schemaValidateSource, dom_document_schema_validate_xml, arginfo_dom_document_schema_validate_xml)
231 	PHP_FALIAS(relaxNGValidate, dom_document_relaxNG_validate_file, arginfo_dom_document_relaxNG_validate_file)
232 	PHP_FALIAS(relaxNGValidateSource, dom_document_relaxNG_validate_xml, arginfo_dom_document_relaxNG_validate_xml)
233 #endif
234 	PHP_ME(domdocument, registerNodeClass, arginfo_dom_document_registernodeclass, ZEND_ACC_PUBLIC)
235 	PHP_FE_END
236 };
237 /* }}} */
238 
239 /* {{{ docType	DOMDocumentType
240 readonly=yes
241 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-B63ED1A31
242 Since:
243 */
dom_document_doctype_read(dom_object * obj,zval * retval)244 int dom_document_doctype_read(dom_object *obj, zval *retval)
245 {
246 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
247 	xmlDtdPtr dtdptr;
248 
249 	if (docp == NULL) {
250 		php_dom_throw_error(INVALID_STATE_ERR, 0);
251 		return FAILURE;
252 	}
253 
254 	dtdptr = xmlGetIntSubset(docp);
255 	if (!dtdptr) {
256 		ZVAL_NULL(retval);
257 		return SUCCESS;
258 	}
259 
260 	php_dom_create_object((xmlNodePtr) dtdptr, retval, obj);
261 	return SUCCESS;
262 }
263 
264 /* }}} */
265 
266 /* {{{ implementation	DOMImplementation
267 readonly=yes
268 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1B793EBA
269 Since:
270 */
dom_document_implementation_read(dom_object * obj,zval * retval)271 int dom_document_implementation_read(dom_object *obj, zval *retval)
272 {
273 	php_dom_create_implementation(retval);
274 	return SUCCESS;
275 }
276 
277 /* }}} */
278 
279 /* {{{ documentElement	DOMElement
280 readonly=yes
281 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-87CD092
282 Since:
283 */
dom_document_document_element_read(dom_object * obj,zval * retval)284 int dom_document_document_element_read(dom_object *obj, zval *retval)
285 {
286 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
287 	xmlNode *root;
288 
289 	if (docp == NULL) {
290 		php_dom_throw_error(INVALID_STATE_ERR, 0);
291 		return FAILURE;
292 	}
293 
294 	root = xmlDocGetRootElement(docp);
295 	if (!root) {
296 		ZVAL_NULL(retval);
297 		return SUCCESS;
298 	}
299 
300 	php_dom_create_object(root, retval, obj);
301 	return SUCCESS;
302 }
303 
304 /* }}} */
305 
306 /* {{{ encoding	string
307 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-encoding
308 Since: DOM Level 3
309 */
dom_document_encoding_read(dom_object * obj,zval * retval)310 int dom_document_encoding_read(dom_object *obj, zval *retval)
311 {
312 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
313 	char *encoding;
314 
315 	if (docp == NULL) {
316 		php_dom_throw_error(INVALID_STATE_ERR, 0);
317 		return FAILURE;
318 	}
319 
320 	encoding = (char *) docp->encoding;
321 
322 	if (encoding != NULL) {
323 		ZVAL_STRING(retval, encoding);
324 	} else {
325 		ZVAL_NULL(retval);
326 	}
327 
328 	return SUCCESS;
329 }
330 
dom_document_encoding_write(dom_object * obj,zval * newval)331 int dom_document_encoding_write(dom_object *obj, zval *newval)
332 {
333 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
334 	zend_string *str;
335 	xmlCharEncodingHandlerPtr handler;
336 
337 	if (docp == NULL) {
338 		php_dom_throw_error(INVALID_STATE_ERR, 0);
339 		return FAILURE;
340 	}
341 
342 	str = zval_get_string(newval);
343 
344 	handler = xmlFindCharEncodingHandler(ZSTR_VAL(str));
345 
346     if (handler != NULL) {
347 		xmlCharEncCloseFunc(handler);
348 		if (docp->encoding != NULL) {
349 			xmlFree((xmlChar *)docp->encoding);
350 		}
351 		docp->encoding = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
352     } else {
353 		php_error_docref(NULL, E_WARNING, "Invalid Document Encoding");
354     }
355 
356 	zend_string_release(str);
357 	return SUCCESS;
358 }
359 
360 /* }}} */
361 
362 /* {{{ standalone	boolean
363 readonly=no
364 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-standalone
365 Since: DOM Level 3
366 */
dom_document_standalone_read(dom_object * obj,zval * retval)367 int dom_document_standalone_read(dom_object *obj, zval *retval)
368 {
369 	xmlDoc *docp;
370 
371 	docp = (xmlDocPtr) dom_object_get_node(obj);
372 
373 	if (docp == NULL) {
374 		php_dom_throw_error(INVALID_STATE_ERR, 0);
375 		return FAILURE;
376 	}
377 
378 	ZVAL_BOOL(retval, docp->standalone);
379 	return SUCCESS;
380 }
381 
dom_document_standalone_write(dom_object * obj,zval * newval)382 int dom_document_standalone_write(dom_object *obj, zval *newval)
383 {
384 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
385 	zend_long standalone;
386 
387 	if (docp == NULL) {
388 		php_dom_throw_error(INVALID_STATE_ERR, 0);
389 		return FAILURE;
390 	}
391 
392 	standalone = zval_get_long(newval);
393 	docp->standalone = ZEND_NORMALIZE_BOOL(standalone);
394 
395 	return SUCCESS;
396 }
397 
398 /* }}} */
399 
400 /* {{{ version	string
401 readonly=no
402 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-version
403 Since: DOM Level 3
404 */
dom_document_version_read(dom_object * obj,zval * retval)405 int dom_document_version_read(dom_object *obj, zval *retval)
406 {
407 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
408 	char *version;
409 
410 	if (docp == NULL) {
411 		php_dom_throw_error(INVALID_STATE_ERR, 0);
412 		return FAILURE;
413 	}
414 
415 	version = (char *) docp->version;
416 
417 	if (version != NULL) {
418 		ZVAL_STRING(retval, version);
419 	} else {
420 		ZVAL_NULL(retval);
421 	}
422 
423 	return SUCCESS;
424 }
425 
dom_document_version_write(dom_object * obj,zval * newval)426 int dom_document_version_write(dom_object *obj, zval *newval)
427 {
428 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
429 	zend_string *str;
430 
431 	if (docp == NULL) {
432 		php_dom_throw_error(INVALID_STATE_ERR, 0);
433 		return FAILURE;
434 	}
435 
436 	if (docp->version != NULL) {
437 		xmlFree((xmlChar *) docp->version );
438 	}
439 
440 	str = zval_get_string(newval);
441 
442 	docp->version = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
443 
444 	zend_string_release(str);
445 	return SUCCESS;
446 }
447 
448 /* }}} */
449 
450 /* {{{ strictErrorChecking	boolean
451 readonly=no
452 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-strictErrorChecking
453 Since: DOM Level 3
454 */
dom_document_strict_error_checking_read(dom_object * obj,zval * retval)455 int dom_document_strict_error_checking_read(dom_object *obj, zval *retval)
456 {
457 	if (obj->document) {
458 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
459 		ZVAL_BOOL(retval, doc_prop->stricterror);
460 	} else {
461 		ZVAL_FALSE(retval);
462 	}
463 	return SUCCESS;
464 }
465 
dom_document_strict_error_checking_write(dom_object * obj,zval * newval)466 int dom_document_strict_error_checking_write(dom_object *obj, zval *newval)
467 {
468 
469 	if (obj->document) {
470 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
471 		doc_prop->stricterror = zend_is_true(newval);
472 	}
473 
474 	return SUCCESS;
475 }
476 
477 /* }}} */
478 
479 /* {{{ formatOutput	boolean
480 readonly=no
481 */
dom_document_format_output_read(dom_object * obj,zval * retval)482 int dom_document_format_output_read(dom_object *obj, zval *retval)
483 {
484 	if (obj->document) {
485 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
486 		ZVAL_BOOL(retval, doc_prop->formatoutput);
487 	} else {
488 		ZVAL_FALSE(retval);
489 	}
490 	return SUCCESS;
491 }
492 
dom_document_format_output_write(dom_object * obj,zval * newval)493 int dom_document_format_output_write(dom_object *obj, zval *newval)
494 {
495 	if (obj->document) {
496 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
497 		doc_prop->formatoutput = zend_is_true(newval);
498 	}
499 
500 	return SUCCESS;
501 }
502 /* }}} */
503 
504 /* {{{ validateOnParse	boolean
505 readonly=no
506 */
dom_document_validate_on_parse_read(dom_object * obj,zval * retval)507 int	dom_document_validate_on_parse_read(dom_object *obj, zval *retval)
508 {
509 	if (obj->document) {
510 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
511 		ZVAL_BOOL(retval, doc_prop->validateonparse);
512 	} else {
513 		ZVAL_FALSE(retval);
514 	}
515 	return SUCCESS;
516 }
517 
dom_document_validate_on_parse_write(dom_object * obj,zval * newval)518 int dom_document_validate_on_parse_write(dom_object *obj, zval *newval)
519 {
520 	if (obj->document) {
521 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
522 		doc_prop->validateonparse = zend_is_true(newval);
523 	}
524 
525 	return SUCCESS;
526 }
527 /* }}} */
528 
529 /* {{{ resolveExternals	boolean
530 readonly=no
531 */
dom_document_resolve_externals_read(dom_object * obj,zval * retval)532 int dom_document_resolve_externals_read(dom_object *obj, zval *retval)
533 {
534 	if (obj->document) {
535 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
536 		ZVAL_BOOL(retval, doc_prop->resolveexternals);
537 	} else {
538 		ZVAL_FALSE(retval);
539 	}
540 	return SUCCESS;
541 }
542 
dom_document_resolve_externals_write(dom_object * obj,zval * newval)543 int dom_document_resolve_externals_write(dom_object *obj, zval *newval)
544 {
545 	if (obj->document) {
546 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
547 		doc_prop->resolveexternals = zend_is_true(newval);
548 	}
549 
550 	return SUCCESS;
551 }
552 /* }}} */
553 
554 /* {{{ preserveWhiteSpace	boolean
555 readonly=no
556 */
dom_document_preserve_whitespace_read(dom_object * obj,zval * retval)557 int dom_document_preserve_whitespace_read(dom_object *obj, zval *retval)
558 {
559 	if (obj->document) {
560 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
561 		ZVAL_BOOL(retval, doc_prop->preservewhitespace);
562 	} else {
563 		ZVAL_FALSE(retval);
564 	}
565 	return SUCCESS;
566 }
567 
dom_document_preserve_whitespace_write(dom_object * obj,zval * newval)568 int dom_document_preserve_whitespace_write(dom_object *obj, zval *newval)
569 {
570 	if (obj->document) {
571 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
572 		doc_prop->preservewhitespace = zend_is_true(newval);
573 	}
574 
575 	return SUCCESS;
576 }
577 /* }}} */
578 
579 /* {{{ recover	boolean
580 readonly=no
581 */
dom_document_recover_read(dom_object * obj,zval * retval)582 int dom_document_recover_read(dom_object *obj, zval *retval)
583 {
584 	if (obj->document) {
585 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
586 		ZVAL_BOOL(retval, doc_prop->recover);
587 	} else {
588 		ZVAL_FALSE(retval);
589 	}
590 	return SUCCESS;
591 }
592 
dom_document_recover_write(dom_object * obj,zval * newval)593 int dom_document_recover_write(dom_object *obj, zval *newval)
594 {
595 	if (obj->document) {
596 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
597 		doc_prop->recover = zend_is_true(newval);
598 	}
599 
600 	return SUCCESS;
601 }
602 /* }}} */
603 
604 /* {{{ substituteEntities	boolean
605 readonly=no
606 */
dom_document_substitue_entities_read(dom_object * obj,zval * retval)607 int dom_document_substitue_entities_read(dom_object *obj, zval *retval)
608 {
609 	if (obj->document) {
610 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
611 		ZVAL_BOOL(retval, doc_prop->substituteentities);
612 	} else {
613 		ZVAL_FALSE(retval);
614 	}
615 	return SUCCESS;
616 }
617 
dom_document_substitue_entities_write(dom_object * obj,zval * newval)618 int dom_document_substitue_entities_write(dom_object *obj, zval *newval)
619 {
620 	if (obj->document) {
621 		dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document);
622 		doc_prop->substituteentities = zend_is_true(newval);
623 	}
624 
625 	return SUCCESS;
626 }
627 /* }}} */
628 
629 /* {{{ documentURI	string
630 readonly=no
631 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-documentURI
632 Since: DOM Level 3
633 */
dom_document_document_uri_read(dom_object * obj,zval * retval)634 int dom_document_document_uri_read(dom_object *obj, zval *retval)
635 {
636 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
637 	char *url;
638 
639 	if (docp == NULL) {
640 		php_dom_throw_error(INVALID_STATE_ERR, 0);
641 		return FAILURE;
642 	}
643 
644 	url = (char *) docp->URL;
645 	if (url != NULL) {
646 		ZVAL_STRING(retval, url);
647 	} else {
648 		ZVAL_NULL(retval);
649 	}
650 
651 	return SUCCESS;
652 }
653 
dom_document_document_uri_write(dom_object * obj,zval * newval)654 int dom_document_document_uri_write(dom_object *obj, zval *newval)
655 {
656 	xmlDoc *docp = (xmlDocPtr) dom_object_get_node(obj);
657 	zend_string *str;
658 
659 	if (docp == NULL) {
660 		php_dom_throw_error(INVALID_STATE_ERR, 0);
661 		return FAILURE;
662 	}
663 
664 	if (docp->URL != NULL) {
665 		xmlFree((xmlChar *) docp->URL);
666 	}
667 
668 	str = zval_get_string(newval);
669 
670 	docp->URL = xmlStrdup((const xmlChar *) ZSTR_VAL(str));
671 
672 	zend_string_release(str);
673 	return SUCCESS;
674 }
675 
676 /* }}} */
677 
678 /* {{{ config	DOMConfiguration
679 readonly=yes
680 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-config
681 Since: DOM Level 3
682 */
dom_document_config_read(dom_object * obj,zval * retval)683 int dom_document_config_read(dom_object *obj, zval *retval)
684 {
685 	ZVAL_NULL(retval);
686 	return SUCCESS;
687 }
688 
689 /* }}} */
690 
691 /* {{{ proto DOMElement dom_document_create_element(string tagName [, string value])
692 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-2141741547
693 Since:
694 */
PHP_FUNCTION(dom_document_create_element)695 PHP_FUNCTION(dom_document_create_element)
696 {
697 	zval *id;
698 	xmlNode *node;
699 	xmlDocPtr docp;
700 	dom_object *intern;
701 	int ret;
702 	size_t name_len, value_len;
703 	char *name, *value = NULL;
704 
705 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|s", &id, dom_document_class_entry, &name, &name_len, &value, &value_len) == FAILURE) {
706 		return;
707 	}
708 
709 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
710 
711 	if (xmlValidateName((xmlChar *) name, 0) != 0) {
712 		php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
713 		RETURN_FALSE;
714 	}
715 
716 	node = xmlNewDocNode(docp, NULL, (xmlChar *) name, (xmlChar *) value);
717 	if (!node) {
718 		RETURN_FALSE;
719 	}
720 
721 	DOM_RET_OBJ(node, &ret, intern);
722 }
723 /* }}} end dom_document_create_element */
724 
725 /* {{{ proto DOMDocumentFragment dom_document_create_document_fragment()
726 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-35CB04B5
727 Since:
728 */
PHP_FUNCTION(dom_document_create_document_fragment)729 PHP_FUNCTION(dom_document_create_document_fragment)
730 {
731 	zval *id;
732 	xmlNode *node;
733 	xmlDocPtr docp;
734 	dom_object *intern;
735 	int ret;
736 
737 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &id, dom_document_class_entry) == FAILURE) {
738 		return;
739 	}
740 
741 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
742 
743 	node =  xmlNewDocFragment(docp);
744 	if (!node) {
745 		RETURN_FALSE;
746 	}
747 
748 	DOM_RET_OBJ(node, &ret, intern);
749 }
750 /* }}} end dom_document_create_document_fragment */
751 
752 /* {{{ proto DOMText dom_document_create_text_node(string data)
753 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1975348127
754 Since:
755 */
PHP_FUNCTION(dom_document_create_text_node)756 PHP_FUNCTION(dom_document_create_text_node)
757 {
758 	zval *id;
759 	xmlNode *node;
760 	xmlDocPtr docp;
761 	int ret;
762 	size_t value_len;
763 	dom_object *intern;
764 	char *value;
765 
766 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &value, &value_len) == FAILURE) {
767 		return;
768 	}
769 
770 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
771 
772 	node = xmlNewDocText(docp, (xmlChar *) value);
773 	if (!node) {
774 		RETURN_FALSE;
775 	}
776 
777 	DOM_RET_OBJ(node, &ret, intern);
778 }
779 /* }}} end dom_document_create_text_node */
780 
781 /* {{{ proto DOMComment dom_document_create_comment(string data)
782 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1334481328
783 Since:
784 */
PHP_FUNCTION(dom_document_create_comment)785 PHP_FUNCTION(dom_document_create_comment)
786 {
787 	zval *id;
788 	xmlNode *node;
789 	xmlDocPtr docp;
790 	int ret;
791 	size_t value_len;
792 	dom_object *intern;
793 	char *value;
794 
795 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &value, &value_len) == FAILURE) {
796 		return;
797 	}
798 
799 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
800 
801 	node = xmlNewDocComment(docp, (xmlChar *) value);
802 	if (!node) {
803 		RETURN_FALSE;
804 	}
805 
806 	DOM_RET_OBJ(node, &ret, intern);
807 }
808 /* }}} end dom_document_create_comment */
809 
810 /* {{{ proto DOMCdataSection dom_document_create_cdatasection(string data)
811 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D26C0AF8
812 Since:
813 */
PHP_FUNCTION(dom_document_create_cdatasection)814 PHP_FUNCTION(dom_document_create_cdatasection)
815 {
816 	zval *id;
817 	xmlNode *node;
818 	xmlDocPtr docp;
819 	int ret;
820 	size_t value_len;
821 	dom_object *intern;
822 	char *value;
823 
824 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &value, &value_len) == FAILURE) {
825 		return;
826 	}
827 
828 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
829 
830 	node = xmlNewCDataBlock(docp, (xmlChar *) value, value_len);
831 	if (!node) {
832 		RETURN_FALSE;
833 	}
834 
835 	DOM_RET_OBJ(node, &ret, intern);
836 }
837 /* }}} end dom_document_create_cdatasection */
838 
839 /* {{{ proto DOMProcessingInstruction dom_document_create_processing_instruction(string target, string data)
840 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-135944439
841 Since:
842 */
PHP_FUNCTION(dom_document_create_processing_instruction)843 PHP_FUNCTION(dom_document_create_processing_instruction)
844 {
845 	zval *id;
846 	xmlNode *node;
847 	xmlDocPtr docp;
848 	int ret;
849 	size_t value_len, name_len = 0;
850 	dom_object *intern;
851 	char *name, *value = NULL;
852 
853 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|s", &id, dom_document_class_entry, &name, &name_len, &value, &value_len) == FAILURE) {
854 		return;
855 	}
856 
857 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
858 
859 	if (xmlValidateName((xmlChar *) name, 0) != 0) {
860 		php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
861 		RETURN_FALSE;
862 	}
863 
864 	node = xmlNewPI((xmlChar *) name, (xmlChar *) value);
865 	if (!node) {
866 		RETURN_FALSE;
867 	}
868 
869 	node->doc = docp;
870 
871 	DOM_RET_OBJ(node, &ret, intern);
872 }
873 /* }}} end dom_document_create_processing_instruction */
874 
875 /* {{{ proto DOMAttr dom_document_create_attribute(string name)
876 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1084891198
877 Since:
878 */
PHP_FUNCTION(dom_document_create_attribute)879 PHP_FUNCTION(dom_document_create_attribute)
880 {
881 	zval *id;
882 	xmlAttrPtr node;
883 	xmlDocPtr docp;
884 	int ret;
885 	size_t name_len;
886 	dom_object *intern;
887 	char *name;
888 
889 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &name, &name_len) == FAILURE) {
890 		return;
891 	}
892 
893 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
894 
895 	if (xmlValidateName((xmlChar *) name, 0) != 0) {
896 		php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
897 		RETURN_FALSE;
898 	}
899 
900 	node = xmlNewDocProp(docp, (xmlChar *) name, NULL);
901 	if (!node) {
902 		RETURN_FALSE;
903 	}
904 
905 	DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
906 
907 }
908 /* }}} end dom_document_create_attribute */
909 
910 /* {{{ proto DOMEntityReference dom_document_create_entity_reference(string name)
911 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-392B75AE
912 Since:
913 */
PHP_FUNCTION(dom_document_create_entity_reference)914 PHP_FUNCTION(dom_document_create_entity_reference)
915 {
916 	zval *id;
917 	xmlNode *node;
918 	xmlDocPtr docp = NULL;
919 	dom_object *intern;
920 	int ret;
921 	size_t name_len;
922 	char *name;
923 
924 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &name, &name_len) == FAILURE) {
925 		return;
926 	}
927 
928 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
929 
930 	if (xmlValidateName((xmlChar *) name, 0) != 0) {
931 		php_dom_throw_error(INVALID_CHARACTER_ERR, dom_get_strict_error(intern->document));
932 		RETURN_FALSE;
933 	}
934 
935 	node = xmlNewReference(docp, (xmlChar *) name);
936 	if (!node) {
937 		RETURN_FALSE;
938 	}
939 
940 	DOM_RET_OBJ((xmlNodePtr) node, &ret, intern);
941 }
942 /* }}} end dom_document_create_entity_reference */
943 
944 /* {{{ proto DOMNodeList dom_document_get_elements_by_tag_name(string tagname)
945 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-A6C9094
946 Since:
947 */
PHP_FUNCTION(dom_document_get_elements_by_tag_name)948 PHP_FUNCTION(dom_document_get_elements_by_tag_name)
949 {
950 	zval *id;
951 	xmlDocPtr docp;
952 	size_t name_len;
953 	dom_object *intern, *namednode;
954 	char *name;
955 	xmlChar *local;
956 
957 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &name, &name_len) == FAILURE) {
958 		return;
959 	}
960 
961 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
962 
963 	php_dom_create_interator(return_value, DOM_NODELIST);
964 	namednode = Z_DOMOBJ_P(return_value);
965 	local = xmlCharStrndup(name, name_len);
966 	dom_namednode_iter(intern, 0, namednode, NULL, local, NULL);
967 }
968 /* }}} end dom_document_get_elements_by_tag_name */
969 
970 /* {{{ proto DOMNode dom_document_import_node(DOMNode importedNode, boolean deep)
971 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Core-Document-importNode
972 Since: DOM Level 2
973 */
PHP_FUNCTION(dom_document_import_node)974 PHP_FUNCTION(dom_document_import_node)
975 {
976 	zval *id, *node;
977 	xmlDocPtr docp;
978 	xmlNodePtr nodep, retnodep;
979 	dom_object *intern, *nodeobj;
980 	int ret;
981 	zend_bool recursive = 0;
982 
983 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OO|b", &id, dom_document_class_entry, &node, dom_node_class_entry, &recursive) == FAILURE) {
984 		return;
985 	}
986 
987 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
988 
989 	DOM_GET_OBJ(nodep, node, xmlNodePtr, nodeobj);
990 
991 	if (nodep->type == XML_HTML_DOCUMENT_NODE || nodep->type == XML_DOCUMENT_NODE
992 		|| nodep->type == XML_DOCUMENT_TYPE_NODE) {
993 		php_error_docref(NULL, E_WARNING, "Cannot import: Node Type Not Supported");
994 		RETURN_FALSE;
995 	}
996 
997 	if (nodep->doc == docp) {
998 		retnodep = nodep;
999 	} else {
1000 		if ((recursive == 0) && (nodep->type == XML_ELEMENT_NODE)) {
1001 			recursive = 2;
1002 		}
1003 		retnodep = xmlDocCopyNode(nodep, docp, recursive);
1004 		if (!retnodep) {
1005 			RETURN_FALSE;
1006 		}
1007 
1008 		if ((retnodep->type == XML_ATTRIBUTE_NODE) && (nodep->ns != NULL)) {
1009 			xmlNsPtr nsptr = NULL;
1010 			xmlNodePtr root = xmlDocGetRootElement(docp);
1011 
1012 			nsptr = xmlSearchNsByHref (nodep->doc, root, nodep->ns->href);
1013 			if (nsptr == NULL) {
1014 				int errorcode;
1015 				nsptr = dom_get_ns(root, (char *) nodep->ns->href, &errorcode, (char *) nodep->ns->prefix);
1016 			}
1017 			xmlSetNs(retnodep, nsptr);
1018 		}
1019 	}
1020 
1021 	DOM_RET_OBJ((xmlNodePtr) retnodep, &ret, intern);
1022 }
1023 /* }}} end dom_document_import_node */
1024 
1025 /* {{{ proto DOMElement dom_document_create_element_ns(string namespaceURI, string qualifiedName [,string value])
1026 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrElNS
1027 Since: DOM Level 2
1028 */
PHP_FUNCTION(dom_document_create_element_ns)1029 PHP_FUNCTION(dom_document_create_element_ns)
1030 {
1031 	zval *id;
1032 	xmlDocPtr docp;
1033 	xmlNodePtr nodep = NULL;
1034 	xmlNsPtr nsptr = NULL;
1035 	int ret;
1036 	size_t uri_len = 0, name_len = 0, value_len = 0;
1037 	char *uri, *name, *value = NULL;
1038 	char *localname = NULL, *prefix = NULL;
1039 	int errorcode;
1040 	dom_object *intern;
1041 
1042 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!s|s", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len, &value, &value_len) == FAILURE) {
1043 		return;
1044 	}
1045 
1046 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1047 
1048 	errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
1049 
1050 	if (errorcode == 0) {
1051 		if (xmlValidateName((xmlChar *) localname, 0) == 0) {
1052 			nodep = xmlNewDocNode(docp, NULL, (xmlChar *) localname, (xmlChar *) value);
1053 			if (nodep != NULL && uri != NULL) {
1054 				nsptr = xmlSearchNsByHref(nodep->doc, nodep, (xmlChar *) uri);
1055 				if (nsptr == NULL) {
1056 					nsptr = dom_get_ns(nodep, uri, &errorcode, prefix);
1057 				}
1058 				xmlSetNs(nodep, nsptr);
1059 			}
1060 		} else {
1061 			errorcode = INVALID_CHARACTER_ERR;
1062 		}
1063 	}
1064 
1065 	xmlFree(localname);
1066 	if (prefix != NULL) {
1067 		xmlFree(prefix);
1068 	}
1069 
1070 	if (errorcode != 0) {
1071 		if (nodep != NULL) {
1072 			xmlFreeNode(nodep);
1073 		}
1074 		php_dom_throw_error(errorcode, dom_get_strict_error(intern->document));
1075 		RETURN_FALSE;
1076 	}
1077 
1078 	if (nodep == NULL) {
1079 		RETURN_FALSE;
1080 	}
1081 
1082 
1083 	nodep->ns = nsptr;
1084 
1085 	DOM_RET_OBJ(nodep, &ret, intern);
1086 }
1087 /* }}} end dom_document_create_element_ns */
1088 
1089 /* {{{ proto DOMAttr dom_document_create_attribute_ns(string namespaceURI, string qualifiedName)
1090 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-DocCrAttrNS
1091 Since: DOM Level 2
1092 */
PHP_FUNCTION(dom_document_create_attribute_ns)1093 PHP_FUNCTION(dom_document_create_attribute_ns)
1094 {
1095 	zval *id;
1096 	xmlDocPtr docp;
1097 	xmlNodePtr nodep = NULL, root;
1098 	xmlNsPtr nsptr;
1099 	int ret;
1100 	size_t uri_len = 0, name_len = 0;
1101 	char *uri, *name;
1102 	char *localname = NULL, *prefix = NULL;
1103 	dom_object *intern;
1104 	int errorcode;
1105 
1106 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!s", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len) == FAILURE) {
1107 		return;
1108 	}
1109 
1110 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1111 
1112 	root = xmlDocGetRootElement(docp);
1113 	if (root != NULL) {
1114 		errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
1115 		if (errorcode == 0) {
1116 			if (xmlValidateName((xmlChar *) localname, 0) == 0) {
1117 				nodep = (xmlNodePtr) xmlNewDocProp(docp, (xmlChar *) localname, NULL);
1118 				if (nodep != NULL && uri_len > 0) {
1119 					nsptr = xmlSearchNsByHref(nodep->doc, root, (xmlChar *) uri);
1120 					if (nsptr == NULL) {
1121 						nsptr = dom_get_ns(root, uri, &errorcode, prefix);
1122 					}
1123 					xmlSetNs(nodep, nsptr);
1124 				}
1125 			} else {
1126 				errorcode = INVALID_CHARACTER_ERR;
1127 			}
1128 		}
1129 	} else {
1130 		php_error_docref(NULL, E_WARNING, "Document Missing Root Element");
1131 		RETURN_FALSE;
1132 	}
1133 
1134 	xmlFree(localname);
1135 	if (prefix != NULL) {
1136 		xmlFree(prefix);
1137 	}
1138 
1139 	if (errorcode != 0) {
1140 		if (nodep != NULL) {
1141 			xmlFreeProp((xmlAttrPtr) nodep);
1142 		}
1143 		php_dom_throw_error(errorcode, dom_get_strict_error(intern->document));
1144 		RETURN_FALSE;
1145 	}
1146 
1147 	if (nodep == NULL) {
1148 		RETURN_FALSE;
1149 	}
1150 
1151 	DOM_RET_OBJ(nodep, &ret, intern);
1152 }
1153 /* }}} end dom_document_create_attribute_ns */
1154 
1155 /* {{{ proto DOMNodeList dom_document_get_elements_by_tag_name_ns(string namespaceURI, string localName)
1156 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBTNNS
1157 Since: DOM Level 2
1158 */
PHP_FUNCTION(dom_document_get_elements_by_tag_name_ns)1159 PHP_FUNCTION(dom_document_get_elements_by_tag_name_ns)
1160 {
1161 	zval *id;
1162 	xmlDocPtr docp;
1163 	size_t uri_len, name_len;
1164 	dom_object *intern, *namednode;
1165 	char *uri, *name;
1166 	xmlChar *local, *nsuri;
1167 
1168 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oss", &id, dom_document_class_entry, &uri, &uri_len, &name, &name_len) == FAILURE) {
1169 		return;
1170 	}
1171 
1172 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1173 
1174 	php_dom_create_interator(return_value, DOM_NODELIST);
1175 	namednode = Z_DOMOBJ_P(return_value);
1176 	local = xmlCharStrndup(name, name_len);
1177 	nsuri = xmlCharStrndup(uri, uri_len);
1178 	dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri);
1179 }
1180 /* }}} end dom_document_get_elements_by_tag_name_ns */
1181 
1182 /* {{{ proto DOMElement dom_document_get_element_by_id(string elementId)
1183 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-getElBId
1184 Since: DOM Level 2
1185 */
PHP_FUNCTION(dom_document_get_element_by_id)1186 PHP_FUNCTION(dom_document_get_element_by_id)
1187 {
1188 	zval *id;
1189 	xmlDocPtr docp;
1190 	xmlAttrPtr  attrp;
1191 	int ret;
1192 	size_t idname_len;
1193 	dom_object *intern;
1194 	char *idname;
1195 
1196 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &idname, &idname_len) == FAILURE) {
1197 		return;
1198 	}
1199 
1200 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1201 
1202 	attrp = xmlGetID(docp, (xmlChar *) idname);
1203 
1204 	if (attrp && attrp->parent) {
1205 		DOM_RET_OBJ((xmlNodePtr) attrp->parent, &ret, intern);
1206 	} else {
1207 		RETVAL_NULL();
1208 	}
1209 
1210 }
1211 /* }}} end dom_document_get_element_by_id */
1212 
1213 /* {{{ proto DOMNode dom_document_adopt_node(DOMNode source)
1214 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-adoptNode
1215 Since: DOM Level 3
1216 */
PHP_FUNCTION(dom_document_adopt_node)1217 PHP_FUNCTION(dom_document_adopt_node)
1218 {
1219  DOM_NOT_IMPLEMENTED();
1220 }
1221 /* }}} end dom_document_adopt_node */
1222 
1223 /* {{{ proto void dom_document_normalize_document()
1224 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-normalizeDocument
1225 Since: DOM Level 3
1226 */
PHP_FUNCTION(dom_document_normalize_document)1227 PHP_FUNCTION(dom_document_normalize_document)
1228 {
1229 	zval *id;
1230 	xmlDocPtr docp;
1231 	dom_object *intern;
1232 
1233 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &id, dom_document_class_entry) == FAILURE) {
1234 		return;
1235 	}
1236 
1237 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1238 
1239 	dom_normalize((xmlNodePtr) docp);
1240 }
1241 /* }}} end dom_document_normalize_document */
1242 
1243 /* {{{ proto DOMNode dom_document_rename_node(node n, string namespaceURI, string qualifiedName)
1244 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Document3-renameNode
1245 Since: DOM Level 3
1246 */
PHP_FUNCTION(dom_document_rename_node)1247 PHP_FUNCTION(dom_document_rename_node)
1248 {
1249  DOM_NOT_IMPLEMENTED();
1250 }
1251 /* }}} end dom_document_rename_node */
1252 
1253 /* {{{ proto void DOMDocument::__construct([string version], [string encoding]); */
PHP_METHOD(domdocument,__construct)1254 PHP_METHOD(domdocument, __construct)
1255 {
1256 
1257 	zval *id = getThis();
1258 	xmlDoc *docp = NULL, *olddoc;
1259 	dom_object *intern;
1260 	char *encoding, *version = NULL;
1261 	size_t encoding_len = 0, version_len = 0;
1262 	int refcount;
1263 
1264 	if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "|ss", &version, &version_len, &encoding, &encoding_len) == FAILURE) {
1265 		return;
1266 	}
1267 
1268 	docp = xmlNewDoc((xmlChar *) version);
1269 
1270 	if (!docp) {
1271 		php_dom_throw_error(INVALID_STATE_ERR, 1);
1272 		RETURN_FALSE;
1273 	}
1274 
1275 	if (encoding_len > 0) {
1276 		docp->encoding = (const xmlChar *) xmlStrdup((xmlChar *) encoding);
1277 	}
1278 
1279 	intern = Z_DOMOBJ_P(id);
1280 	if (intern != NULL) {
1281 		olddoc = (xmlDocPtr) dom_object_get_node(intern);
1282 		if (olddoc != NULL) {
1283 			php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
1284 			refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
1285 			if (refcount != 0) {
1286 				olddoc->_private = NULL;
1287 			}
1288 		}
1289 		intern->document = NULL;
1290 		if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, docp) == -1) {
1291 			RETURN_FALSE;
1292 		}
1293 		php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)docp, (void *)intern);
1294 	}
1295 }
1296 /* }}} end DOMDocument::__construct */
1297 
_dom_get_valid_file_path(char * source,char * resolved_path,int resolved_path_len)1298 char *_dom_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len ) /* {{{ */
1299 {
1300 	xmlURI *uri;
1301 	xmlChar *escsource;
1302 	char *file_dest;
1303 	int isFileUri = 0;
1304 
1305 	uri = xmlCreateURI();
1306 	escsource = xmlURIEscapeStr((xmlChar *) source, (xmlChar *) ":");
1307 	xmlParseURIReference(uri, (char *) escsource);
1308 	xmlFree(escsource);
1309 
1310 	if (uri->scheme != NULL) {
1311 		/* absolute file uris - libxml only supports localhost or empty host */
1312 #ifdef PHP_WIN32
1313 		if (strncasecmp(source, "file://",7) == 0 && ':' == source[8]) {
1314 			isFileUri = 1;
1315 			source += 7;
1316 		} else
1317 #endif
1318 		if (strncasecmp(source, "file:///",8) == 0) {
1319 			isFileUri = 1;
1320 #ifdef PHP_WIN32
1321 			source += 8;
1322 #else
1323 			source += 7;
1324 #endif
1325 		} else if (strncasecmp(source, "file://localhost/",17) == 0) {
1326 			isFileUri = 1;
1327 #ifdef PHP_WIN32
1328 			source += 17;
1329 #else
1330 			source += 16;
1331 #endif
1332 		}
1333 	}
1334 
1335 	file_dest = source;
1336 
1337 	if ((uri->scheme == NULL || isFileUri)) {
1338 		/* XXX possible buffer overflow if VCWD_REALPATH does not know size of resolved_path */
1339 		if (!VCWD_REALPATH(source, resolved_path) && !expand_filepath(source, resolved_path)) {
1340 			xmlFreeURI(uri);
1341 			return NULL;
1342 		}
1343 		file_dest = resolved_path;
1344 	}
1345 
1346 	xmlFreeURI(uri);
1347 
1348 	return file_dest;
1349 }
1350 /* }}} */
1351 
dom_document_parser(zval * id,int mode,char * source,size_t source_len,size_t options)1352 static xmlDocPtr dom_document_parser(zval *id, int mode, char *source, size_t source_len, size_t options) /* {{{ */
1353 {
1354     xmlDocPtr ret;
1355     xmlParserCtxtPtr ctxt = NULL;
1356 	dom_doc_propsptr doc_props;
1357 	dom_object *intern;
1358 	php_libxml_ref_obj *document = NULL;
1359 	int validate, recover, resolve_externals, keep_blanks, substitute_ent;
1360 	int resolved_path_len;
1361 	int old_error_reporting = 0;
1362 	char *directory=NULL, resolved_path[MAXPATHLEN];
1363 
1364 	if (id != NULL) {
1365 		intern = Z_DOMOBJ_P(id);
1366 		document = intern->document;
1367 	}
1368 
1369 	doc_props = dom_get_doc_props(document);
1370 	validate = doc_props->validateonparse;
1371 	resolve_externals = doc_props->resolveexternals;
1372 	keep_blanks = doc_props->preservewhitespace;
1373 	substitute_ent = doc_props->substituteentities;
1374 	recover = doc_props->recover;
1375 
1376 	if (document == NULL) {
1377 		efree(doc_props);
1378 	}
1379 
1380 	xmlInitParser();
1381 
1382 	if (mode == DOM_LOAD_FILE) {
1383 		char *file_dest;
1384 		if (CHECK_NULL_PATH(source, source_len)) {
1385 			return NULL;
1386 		}
1387 		file_dest = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
1388 		if (file_dest) {
1389 			ctxt = xmlCreateFileParserCtxt(file_dest);
1390 		}
1391 
1392 	} else {
1393 		ctxt = xmlCreateMemoryParserCtxt(source, source_len);
1394 	}
1395 
1396 	if (ctxt == NULL) {
1397 		return(NULL);
1398 	}
1399 
1400 	/* If loading from memory, we need to set the base directory for the document */
1401 	if (mode != DOM_LOAD_FILE) {
1402 #if HAVE_GETCWD
1403 		directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
1404 #elif HAVE_GETWD
1405 		directory = VCWD_GETWD(resolved_path);
1406 #endif
1407 		if (directory) {
1408 			if(ctxt->directory != NULL) {
1409 				xmlFree((char *) ctxt->directory);
1410 			}
1411 			resolved_path_len = strlen(resolved_path);
1412 			if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) {
1413 				resolved_path[resolved_path_len] = DEFAULT_SLASH;
1414 				resolved_path[++resolved_path_len] = '\0';
1415 			}
1416 			ctxt->directory = (char *) xmlCanonicPath((const xmlChar *) resolved_path);
1417 		}
1418 	}
1419 
1420 	ctxt->vctxt.error = php_libxml_ctx_error;
1421 	ctxt->vctxt.warning = php_libxml_ctx_warning;
1422 
1423 	if (ctxt->sax != NULL) {
1424 		ctxt->sax->error = php_libxml_ctx_error;
1425 		ctxt->sax->warning = php_libxml_ctx_warning;
1426 	}
1427 
1428 	if (validate && ! (options & XML_PARSE_DTDVALID)) {
1429 		options |= XML_PARSE_DTDVALID;
1430 	}
1431 	if (resolve_externals && ! (options & XML_PARSE_DTDATTR)) {
1432 		options |= XML_PARSE_DTDATTR;
1433 	}
1434 	if (substitute_ent && ! (options & XML_PARSE_NOENT)) {
1435 		options |= XML_PARSE_NOENT;
1436 	}
1437 	if (keep_blanks == 0 && ! (options & XML_PARSE_NOBLANKS)) {
1438 		options |= XML_PARSE_NOBLANKS;
1439 	}
1440 
1441 	xmlCtxtUseOptions(ctxt, options);
1442 
1443 	ctxt->recovery = recover;
1444 	if (recover) {
1445 		old_error_reporting = EG(error_reporting);
1446 		EG(error_reporting) = old_error_reporting | E_WARNING;
1447 	}
1448 
1449 	xmlParseDocument(ctxt);
1450 
1451 	if (ctxt->wellFormed || recover) {
1452 		ret = ctxt->myDoc;
1453 		if (ctxt->recovery) {
1454 			EG(error_reporting) = old_error_reporting;
1455 		}
1456 		/* If loading from memory, set the base reference uri for the document */
1457 		if (ret && ret->URL == NULL && ctxt->directory != NULL) {
1458 			ret->URL = xmlStrdup((xmlChar *) ctxt->directory);
1459 		}
1460 	} else {
1461 		ret = NULL;
1462 		xmlFreeDoc(ctxt->myDoc);
1463 		ctxt->myDoc = NULL;
1464 	}
1465 
1466 	xmlFreeParserCtxt(ctxt);
1467 
1468 	return(ret);
1469 }
1470 /* }}} */
1471 
1472 /* {{{ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) */
dom_parse_document(INTERNAL_FUNCTION_PARAMETERS,int mode)1473 static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) {
1474 	zval *id;
1475 	xmlDoc *docp = NULL, *newdoc;
1476 	dom_doc_propsptr doc_prop;
1477 	dom_object *intern;
1478 	char *source;
1479 	size_t source_len;
1480 	int refcount, ret;
1481 	zend_long options = 0;
1482 
1483 	id = getThis();
1484 	if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), dom_document_class_entry)) {
1485 		id = NULL;
1486 	}
1487 
1488 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &options) == FAILURE) {
1489 		return;
1490 	}
1491 
1492 	if (!source_len) {
1493 		php_error_docref(NULL, E_WARNING, "Empty string supplied as input");
1494 		RETURN_FALSE;
1495 	}
1496 	if (ZEND_SIZE_T_INT_OVFL(source_len)) {
1497 		php_error_docref(NULL, E_WARNING, "Input string is too long");
1498 		RETURN_FALSE;
1499 	}
1500 	if (ZEND_LONG_EXCEEDS_INT(options)) {
1501 		php_error_docref(NULL, E_WARNING, "Invalid options");
1502 		RETURN_FALSE;
1503 	}
1504 
1505 	newdoc = dom_document_parser(id, mode, source, source_len, options);
1506 
1507 	if (!newdoc)
1508 		RETURN_FALSE;
1509 
1510 	if (id != NULL) {
1511 		intern = Z_DOMOBJ_P(id);
1512 		if (intern != NULL) {
1513 			docp = (xmlDocPtr) dom_object_get_node(intern);
1514 			doc_prop = NULL;
1515 			if (docp != NULL) {
1516 				php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
1517 				doc_prop = intern->document->doc_props;
1518 				intern->document->doc_props = NULL;
1519 				refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
1520 				if (refcount != 0) {
1521 					docp->_private = NULL;
1522 				}
1523 			}
1524 			intern->document = NULL;
1525 			if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
1526 				RETURN_FALSE;
1527 			}
1528 			intern->document->doc_props = doc_prop;
1529 		}
1530 
1531 		php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
1532 
1533 		RETURN_TRUE;
1534 	} else {
1535 		DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
1536 	}
1537 }
1538 /* }}} end dom_parser_document */
1539 
1540 /* {{{ proto DOMNode dom_document_load(string source [, int options])
1541 URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-load
1542 Since: DOM Level 3
1543 */
PHP_METHOD(domdocument,load)1544 PHP_METHOD(domdocument, load)
1545 {
1546 	dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
1547 }
1548 /* }}} end dom_document_load */
1549 
1550 /* {{{ proto DOMNode dom_document_loadxml(string source [, int options])
1551 URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-loadXML
1552 Since: DOM Level 3
1553 */
PHP_METHOD(domdocument,loadXML)1554 PHP_METHOD(domdocument, loadXML)
1555 {
1556 	dom_parse_document(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
1557 }
1558 /* }}} end dom_document_loadxml */
1559 
1560 /* {{{ proto int dom_document_save(string file)
1561 Convenience method to save to file
1562 */
PHP_FUNCTION(dom_document_save)1563 PHP_FUNCTION(dom_document_save)
1564 {
1565 	zval *id;
1566 	xmlDoc *docp;
1567 	size_t file_len = 0;
1568 	int bytes, format, saveempty = 0;
1569 	dom_object *intern;
1570 	dom_doc_propsptr doc_props;
1571 	char *file;
1572 	zend_long options = 0;
1573 
1574 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Op|l", &id, dom_document_class_entry, &file, &file_len, &options) == FAILURE) {
1575 		return;
1576 	}
1577 
1578 	if (file_len == 0) {
1579 		php_error_docref(NULL, E_WARNING, "Invalid Filename");
1580 		RETURN_FALSE;
1581 	}
1582 
1583 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1584 
1585 	/* encoding handled by property on doc */
1586 
1587 	doc_props = dom_get_doc_props(intern->document);
1588 	format = doc_props->formatoutput;
1589 	if (options & LIBXML_SAVE_NOEMPTYTAG) {
1590 		saveempty = xmlSaveNoEmptyTags;
1591 		xmlSaveNoEmptyTags = 1;
1592 	}
1593 	bytes = xmlSaveFormatFileEnc(file, docp, NULL, format);
1594 	if (options & LIBXML_SAVE_NOEMPTYTAG) {
1595 		xmlSaveNoEmptyTags = saveempty;
1596 	}
1597 	if (bytes == -1) {
1598 		RETURN_FALSE;
1599 	}
1600 	RETURN_LONG(bytes);
1601 }
1602 /* }}} end dom_document_save */
1603 
1604 /* {{{ proto string dom_document_savexml([node n])
1605 URL: http://www.w3.org/TR/DOM-Level-3-LS/load-save.html#LS-DocumentLS-saveXML
1606 Since: DOM Level 3
1607 */
PHP_FUNCTION(dom_document_savexml)1608 PHP_FUNCTION(dom_document_savexml)
1609 {
1610 	zval *id, *nodep = NULL;
1611 	xmlDoc *docp;
1612 	xmlNode *node;
1613 	xmlBufferPtr buf;
1614 	xmlChar *mem;
1615 	dom_object *intern, *nodeobj;
1616 	dom_doc_propsptr doc_props;
1617 	int size, format, saveempty = 0;
1618 	zend_long options = 0;
1619 
1620 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|O!l", &id, dom_document_class_entry, &nodep, dom_node_class_entry, &options) == FAILURE) {
1621 		return;
1622 	}
1623 
1624 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1625 
1626 	doc_props = dom_get_doc_props(intern->document);
1627 	format = doc_props->formatoutput;
1628 
1629 	if (nodep != NULL) {
1630 		/* Dump contents of Node */
1631 		DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
1632 		if (node->doc != docp) {
1633 			php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
1634 			RETURN_FALSE;
1635 		}
1636 		buf = xmlBufferCreate();
1637 		if (!buf) {
1638 			php_error_docref(NULL, E_WARNING, "Could not fetch buffer");
1639 			RETURN_FALSE;
1640 		}
1641 		if (options & LIBXML_SAVE_NOEMPTYTAG) {
1642 			saveempty = xmlSaveNoEmptyTags;
1643 			xmlSaveNoEmptyTags = 1;
1644 		}
1645 		xmlNodeDump(buf, docp, node, 0, format);
1646 		if (options & LIBXML_SAVE_NOEMPTYTAG) {
1647 			xmlSaveNoEmptyTags = saveempty;
1648 		}
1649 		mem = (xmlChar*) xmlBufferContent(buf);
1650 		if (!mem) {
1651 			xmlBufferFree(buf);
1652 			RETURN_FALSE;
1653 		}
1654 		RETVAL_STRING((char *) mem);
1655 		xmlBufferFree(buf);
1656 	} else {
1657 		if (options & LIBXML_SAVE_NOEMPTYTAG) {
1658 			saveempty = xmlSaveNoEmptyTags;
1659 			xmlSaveNoEmptyTags = 1;
1660 		}
1661 		/* Encoding is handled from the encoding property set on the document */
1662 		xmlDocDumpFormatMemory(docp, &mem, &size, format);
1663 		if (options & LIBXML_SAVE_NOEMPTYTAG) {
1664 			xmlSaveNoEmptyTags = saveempty;
1665 		}
1666 		if (!size || !mem) {
1667 			RETURN_FALSE;
1668 		}
1669 		RETVAL_STRINGL((char *) mem, size);
1670 		xmlFree(mem);
1671 	}
1672 }
1673 /* }}} end dom_document_savexml */
1674 
php_dom_free_xinclude_node(xmlNodePtr cur)1675 static xmlNodePtr php_dom_free_xinclude_node(xmlNodePtr cur) /* {{{ */
1676 {
1677 	xmlNodePtr xincnode;
1678 
1679 	xincnode = cur;
1680 	cur = cur->next;
1681 	xmlUnlinkNode(xincnode);
1682 	php_libxml_node_free_resource(xincnode);
1683 
1684 	return cur;
1685 }
1686 /* }}} */
1687 
php_dom_remove_xinclude_nodes(xmlNodePtr cur)1688 static void php_dom_remove_xinclude_nodes(xmlNodePtr cur) /* {{{ */
1689 {
1690 	while(cur) {
1691 		if (cur->type == XML_XINCLUDE_START) {
1692 			cur = php_dom_free_xinclude_node(cur);
1693 
1694 			/* XML_XINCLUDE_END node will be a sibling of XML_XINCLUDE_START */
1695 			while(cur && cur->type != XML_XINCLUDE_END) {
1696 				/* remove xinclude processing nodes from recursive xincludes */
1697 				if (cur->type == XML_ELEMENT_NODE) {
1698 					   php_dom_remove_xinclude_nodes(cur->children);
1699 				}
1700 				cur = cur->next;
1701 			}
1702 
1703 			if (cur && cur->type == XML_XINCLUDE_END) {
1704 				cur = php_dom_free_xinclude_node(cur);
1705 			}
1706 		} else {
1707 			if (cur->type == XML_ELEMENT_NODE) {
1708 				php_dom_remove_xinclude_nodes(cur->children);
1709 			}
1710 			cur = cur->next;
1711 		}
1712 	}
1713 }
1714 /* }}} */
1715 
1716 /* {{{ proto int dom_document_xinclude([int options])
1717    Substitutues xincludes in a DomDocument */
PHP_FUNCTION(dom_document_xinclude)1718 PHP_FUNCTION(dom_document_xinclude)
1719 {
1720 	zval *id;
1721 	xmlDoc *docp;
1722 	xmlNodePtr root;
1723 	zend_long flags = 0;
1724 	int err;
1725 	dom_object *intern;
1726 
1727 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &id, dom_document_class_entry, &flags) == FAILURE) {
1728 		return;
1729 	}
1730 
1731 	if (ZEND_LONG_EXCEEDS_INT(flags)) {
1732 		php_error_docref(NULL, E_WARNING, "Invalid flags");
1733 		RETURN_FALSE;
1734 	}
1735 
1736 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1737 
1738 	err = xmlXIncludeProcessFlags(docp, (int)flags);
1739 
1740 	/* XML_XINCLUDE_START and XML_XINCLUDE_END nodes need to be removed as these
1741 	are added via xmlXIncludeProcess to mark beginning and ending of xincluded document
1742 	but are not wanted in resulting document - must be done even if err as it could fail after
1743 	having processed some xincludes */
1744 	root = (xmlNodePtr) docp->children;
1745 	while(root && root->type != XML_ELEMENT_NODE && root->type != XML_XINCLUDE_START) {
1746 		root = root->next;
1747 	}
1748 	if (root) {
1749 		php_dom_remove_xinclude_nodes(root);
1750 	}
1751 
1752 	if (err) {
1753 		RETVAL_LONG(err);
1754 	} else {
1755 		RETVAL_FALSE;
1756 	}
1757 
1758 }
1759 /* }}} */
1760 
1761 /* {{{ proto boolean dom_document_validate()
1762 Since: DOM extended
1763 */
PHP_FUNCTION(dom_document_validate)1764 PHP_FUNCTION(dom_document_validate)
1765 {
1766 	zval *id;
1767 	xmlDoc *docp;
1768 	dom_object *intern;
1769 	xmlValidCtxt *cvp;
1770 
1771 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &id, dom_document_class_entry) == FAILURE) {
1772 		return;
1773 	}
1774 
1775 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1776 
1777 	cvp = xmlNewValidCtxt();
1778 
1779 	cvp->userData = NULL;
1780 	cvp->error    = (xmlValidityErrorFunc) php_libxml_error_handler;
1781 	cvp->warning  = (xmlValidityErrorFunc) php_libxml_error_handler;
1782 
1783 	if (xmlValidateDocument(cvp, docp)) {
1784 		RETVAL_TRUE;
1785 	} else {
1786 		RETVAL_FALSE;
1787 	}
1788 
1789 	xmlFreeValidCtxt(cvp);
1790 
1791 }
1792 /* }}} */
1793 
1794 #if defined(LIBXML_SCHEMAS_ENABLED)
_dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS,int type)1795 static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1796 {
1797 	zval *id;
1798 	xmlDoc *docp;
1799 	dom_object *intern;
1800 	char *source = NULL, *valid_file = NULL;
1801 	size_t source_len = 0;
1802 	int valid_opts = 0;
1803 	zend_long flags = 0;
1804 	xmlSchemaParserCtxtPtr  parser;
1805 	xmlSchemaPtr            sptr;
1806 	xmlSchemaValidCtxtPtr   vptr;
1807 	int                     is_valid;
1808 	char resolved_path[MAXPATHLEN + 1];
1809 
1810 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|l", &id, dom_document_class_entry, &source, &source_len, &flags) == FAILURE) {
1811 		return;
1812 	}
1813 
1814 	if (source_len == 0) {
1815 		php_error_docref(NULL, E_WARNING, "Invalid Schema source");
1816 		RETURN_FALSE;
1817 	}
1818 
1819 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1820 
1821 	switch (type) {
1822 	case DOM_LOAD_FILE:
1823 		if (CHECK_NULL_PATH(source, source_len)) {
1824 			php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
1825 			RETURN_FALSE;
1826 		}
1827 		valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
1828 		if (!valid_file) {
1829 			php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
1830 			RETURN_FALSE;
1831 		}
1832 		parser = xmlSchemaNewParserCtxt(valid_file);
1833 		break;
1834 	case DOM_LOAD_STRING:
1835 		parser = xmlSchemaNewMemParserCtxt(source, source_len);
1836 		/* If loading from memory, we need to set the base directory for the document
1837 		   but it is not apparent how to do that for schema's */
1838 		break;
1839 	default:
1840 		return;
1841 	}
1842 
1843 	xmlSchemaSetParserErrors(parser,
1844 		(xmlSchemaValidityErrorFunc) php_libxml_error_handler,
1845 		(xmlSchemaValidityWarningFunc) php_libxml_error_handler,
1846 		parser);
1847 	sptr = xmlSchemaParse(parser);
1848 	xmlSchemaFreeParserCtxt(parser);
1849 	if (!sptr) {
1850 		php_error_docref(NULL, E_WARNING, "Invalid Schema");
1851 		RETURN_FALSE;
1852 	}
1853 
1854 	docp = (xmlDocPtr) dom_object_get_node(intern);
1855 
1856 	vptr = xmlSchemaNewValidCtxt(sptr);
1857 	if (!vptr) {
1858 		xmlSchemaFree(sptr);
1859 		zend_throw_error(NULL, "Invalid Schema Validation Context");
1860 		RETURN_FALSE;
1861 	}
1862 
1863 #if LIBXML_VERSION >= 20614
1864 	if (flags & XML_SCHEMA_VAL_VC_I_CREATE) {
1865 		valid_opts |= XML_SCHEMA_VAL_VC_I_CREATE;
1866 	}
1867 #endif
1868 
1869 	xmlSchemaSetValidOptions(vptr, valid_opts);
1870 	xmlSchemaSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
1871 	is_valid = xmlSchemaValidateDoc(vptr, docp);
1872 	xmlSchemaFree(sptr);
1873 	xmlSchemaFreeValidCtxt(vptr);
1874 
1875 	if (is_valid == 0) {
1876 		RETURN_TRUE;
1877 	} else {
1878 		RETURN_FALSE;
1879 	}
1880 }
1881 /* }}} */
1882 
1883 /* {{{ proto boolean dom_document_schema_validate_file(string filename, int flags); */
PHP_FUNCTION(dom_document_schema_validate_file)1884 PHP_FUNCTION(dom_document_schema_validate_file)
1885 {
1886 	_dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
1887 }
1888 /* }}} end dom_document_schema_validate_file */
1889 
1890 /* {{{ proto boolean dom_document_schema_validate(string source, int flags); */
PHP_FUNCTION(dom_document_schema_validate_xml)1891 PHP_FUNCTION(dom_document_schema_validate_xml)
1892 {
1893 	_dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
1894 }
1895 /* }}} end dom_document_schema_validate */
1896 
_dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS,int type)1897 static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */
1898 {
1899 	zval *id;
1900 	xmlDoc *docp;
1901 	dom_object *intern;
1902 	char *source = NULL, *valid_file = NULL;
1903 	size_t source_len = 0;
1904 	xmlRelaxNGParserCtxtPtr parser;
1905 	xmlRelaxNGPtr           sptr;
1906 	xmlRelaxNGValidCtxtPtr  vptr;
1907 	int                     is_valid;
1908 	char resolved_path[MAXPATHLEN + 1];
1909 
1910 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
1911 		return;
1912 	}
1913 
1914 	if (source_len == 0) {
1915 		php_error_docref(NULL, E_WARNING, "Invalid Schema source");
1916 		RETURN_FALSE;
1917 	}
1918 
1919 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
1920 
1921 	switch (type) {
1922 	case DOM_LOAD_FILE:
1923 		if (CHECK_NULL_PATH(source, source_len)) {
1924 			php_error_docref(NULL, E_WARNING, "Invalid RelaxNG file source");
1925 			RETURN_FALSE;
1926 		}
1927 		valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN);
1928 		if (!valid_file) {
1929 			php_error_docref(NULL, E_WARNING, "Invalid RelaxNG file source");
1930 			RETURN_FALSE;
1931 		}
1932 		parser = xmlRelaxNGNewParserCtxt(valid_file);
1933 		break;
1934 	case DOM_LOAD_STRING:
1935 		parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
1936 		/* If loading from memory, we need to set the base directory for the document
1937 		   but it is not apparent how to do that for schema's */
1938 		break;
1939 	default:
1940 		return;
1941 	}
1942 
1943 	xmlRelaxNGSetParserErrors(parser,
1944 		(xmlRelaxNGValidityErrorFunc) php_libxml_error_handler,
1945 		(xmlRelaxNGValidityWarningFunc) php_libxml_error_handler,
1946 		parser);
1947 	sptr = xmlRelaxNGParse(parser);
1948 	xmlRelaxNGFreeParserCtxt(parser);
1949 	if (!sptr) {
1950 		php_error_docref(NULL, E_WARNING, "Invalid RelaxNG");
1951 		RETURN_FALSE;
1952 	}
1953 
1954 	docp = (xmlDocPtr) dom_object_get_node(intern);
1955 
1956 	vptr = xmlRelaxNGNewValidCtxt(sptr);
1957 	if (!vptr) {
1958 		xmlRelaxNGFree(sptr);
1959 		zend_throw_error(NULL, "Invalid RelaxNG Validation Context");
1960 		RETURN_FALSE;
1961 	}
1962 
1963 	xmlRelaxNGSetValidErrors(vptr, php_libxml_error_handler, php_libxml_error_handler, vptr);
1964 	is_valid = xmlRelaxNGValidateDoc(vptr, docp);
1965 	xmlRelaxNGFree(sptr);
1966 	xmlRelaxNGFreeValidCtxt(vptr);
1967 
1968 	if (is_valid == 0) {
1969 		RETURN_TRUE;
1970 	} else {
1971 		RETURN_FALSE;
1972 	}
1973 }
1974 /* }}} */
1975 
1976 /* {{{ proto boolean dom_document_relaxNG_validate_file(string filename); */
PHP_FUNCTION(dom_document_relaxNG_validate_file)1977 PHP_FUNCTION(dom_document_relaxNG_validate_file)
1978 {
1979 	_dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
1980 }
1981 /* }}} end dom_document_relaxNG_validate_file */
1982 
1983 /* {{{ proto boolean dom_document_relaxNG_validate_xml(string source); */
PHP_FUNCTION(dom_document_relaxNG_validate_xml)1984 PHP_FUNCTION(dom_document_relaxNG_validate_xml)
1985 {
1986 	_dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
1987 }
1988 /* }}} end dom_document_relaxNG_validate_xml */
1989 
1990 #endif
1991 
1992 #if defined(LIBXML_HTML_ENABLED)
1993 
dom_load_html(INTERNAL_FUNCTION_PARAMETERS,int mode)1994 static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
1995 {
1996 	zval *id;
1997 	xmlDoc *docp = NULL, *newdoc;
1998 	dom_object *intern;
1999 	dom_doc_propsptr doc_prop;
2000 	char *source;
2001 	size_t source_len;
2002 	int refcount, ret;
2003 	zend_long options = 0;
2004 	htmlParserCtxtPtr ctxt;
2005 
2006 	id = getThis();
2007 
2008 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &options) == FAILURE) {
2009 		return;
2010 	}
2011 
2012 	if (!source_len) {
2013 		php_error_docref(NULL, E_WARNING, "Empty string supplied as input");
2014 		RETURN_FALSE;
2015 	}
2016 
2017 	if (ZEND_LONG_EXCEEDS_INT(options)) {
2018 		php_error_docref(NULL, E_WARNING, "Invalid options");
2019 		RETURN_FALSE;
2020 	}
2021 
2022 	if (mode == DOM_LOAD_FILE) {
2023 		if (CHECK_NULL_PATH(source, source_len)) {
2024 			php_error_docref(NULL, E_WARNING, "Invalid file source");
2025 			RETURN_FALSE;
2026 		}
2027 		ctxt = htmlCreateFileParserCtxt(source, NULL);
2028 	} else {
2029 		source_len = xmlStrlen((xmlChar *) source);
2030 		if (ZEND_SIZE_T_INT_OVFL(source_len)) {
2031 			php_error_docref(NULL, E_WARNING, "Input string is too long");
2032 			RETURN_FALSE;
2033 		}
2034 		ctxt = htmlCreateMemoryParserCtxt(source, (int)source_len);
2035 	}
2036 
2037 	if (!ctxt) {
2038 		RETURN_FALSE;
2039 	}
2040 
2041 
2042 	ctxt->vctxt.error = php_libxml_ctx_error;
2043 	ctxt->vctxt.warning = php_libxml_ctx_warning;
2044 	if (ctxt->sax != NULL) {
2045 		ctxt->sax->error = php_libxml_ctx_error;
2046 		ctxt->sax->warning = php_libxml_ctx_warning;
2047 	}
2048 	if (options) {
2049 		htmlCtxtUseOptions(ctxt, (int)options);
2050 	}
2051 	htmlParseDocument(ctxt);
2052 	newdoc = ctxt->myDoc;
2053 	htmlFreeParserCtxt(ctxt);
2054 
2055 	if (!newdoc)
2056 		RETURN_FALSE;
2057 
2058 	if (id != NULL && instanceof_function(Z_OBJCE_P(id), dom_document_class_entry)) {
2059 		intern = Z_DOMOBJ_P(id);
2060 		if (intern != NULL) {
2061 			docp = (xmlDocPtr) dom_object_get_node(intern);
2062 			doc_prop = NULL;
2063 			if (docp != NULL) {
2064 				php_libxml_decrement_node_ptr((php_libxml_node_object *) intern);
2065 				doc_prop = intern->document->doc_props;
2066 				intern->document->doc_props = NULL;
2067 				refcount = php_libxml_decrement_doc_ref((php_libxml_node_object *)intern);
2068 				if (refcount != 0) {
2069 					docp->_private = NULL;
2070 				}
2071 			}
2072 			intern->document = NULL;
2073 			if (php_libxml_increment_doc_ref((php_libxml_node_object *)intern, newdoc) == -1) {
2074 				RETURN_FALSE;
2075 			}
2076 			intern->document->doc_props = doc_prop;
2077 		}
2078 
2079 		php_libxml_increment_node_ptr((php_libxml_node_object *)intern, (xmlNodePtr)newdoc, (void *)intern);
2080 
2081 		RETURN_TRUE;
2082 	} else {
2083 		DOM_RET_OBJ((xmlNodePtr) newdoc, &ret, NULL);
2084 	}
2085 }
2086 /* }}} */
2087 
2088 /* {{{ proto DOMNode dom_document_load_html_file(string source)
2089 Since: DOM extended
2090 */
PHP_METHOD(domdocument,loadHTMLFile)2091 PHP_METHOD(domdocument, loadHTMLFile)
2092 {
2093 	dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
2094 }
2095 /* }}} end dom_document_load_html_file */
2096 
2097 /* {{{ proto DOMNode dom_document_load_html(string source)
2098 Since: DOM extended
2099 */
PHP_METHOD(domdocument,loadHTML)2100 PHP_METHOD(domdocument, loadHTML)
2101 {
2102 	dom_load_html(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_STRING);
2103 }
2104 /* }}} end dom_document_load_html */
2105 
2106 /* {{{ proto int dom_document_save_html_file(string file)
2107 Convenience method to save to file as html
2108 */
PHP_FUNCTION(dom_document_save_html_file)2109 PHP_FUNCTION(dom_document_save_html_file)
2110 {
2111 	zval *id;
2112 	xmlDoc *docp;
2113 	size_t file_len;
2114 	int bytes, format;
2115 	dom_object *intern;
2116 	dom_doc_propsptr doc_props;
2117 	char *file;
2118 	const char *encoding;
2119 
2120 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Op", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
2121 		return;
2122 	}
2123 
2124 	if (file_len == 0) {
2125 		php_error_docref(NULL, E_WARNING, "Invalid Filename");
2126 		RETURN_FALSE;
2127 	}
2128 
2129 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2130 
2131 
2132 	encoding = (const char *) htmlGetMetaEncoding(docp);
2133 
2134 	doc_props = dom_get_doc_props(intern->document);
2135 	format = doc_props->formatoutput;
2136 	bytes = htmlSaveFileFormat(file, docp, encoding, format);
2137 
2138 	if (bytes == -1) {
2139 		RETURN_FALSE;
2140 	}
2141 	RETURN_LONG(bytes);
2142 }
2143 /* }}} end dom_document_save_html_file */
2144 
2145 /* {{{ proto string dom_document_save_html()
2146 Convenience method to output as html
2147 */
PHP_FUNCTION(dom_document_save_html)2148 PHP_FUNCTION(dom_document_save_html)
2149 {
2150 	zval *id, *nodep = NULL;
2151 	xmlDoc *docp;
2152 	xmlNode *node;
2153 	xmlBufferPtr buf;
2154 	dom_object *intern, *nodeobj;
2155 	xmlChar *mem = NULL;
2156 	int size = 0, format;
2157 	dom_doc_propsptr doc_props;
2158 
2159 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
2160 		"O|O!", &id, dom_document_class_entry, &nodep, dom_node_class_entry)
2161 		== FAILURE) {
2162 		return;
2163 	}
2164 
2165 	DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2166 
2167 	doc_props = dom_get_doc_props(intern->document);
2168 	format = doc_props->formatoutput;
2169 
2170 	if (nodep != NULL) {
2171 		/* Dump contents of Node */
2172 		DOM_GET_OBJ(node, nodep, xmlNodePtr, nodeobj);
2173 		if (node->doc != docp) {
2174 			php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
2175 			RETURN_FALSE;
2176 		}
2177 
2178 		buf = xmlBufferCreate();
2179 		if (!buf) {
2180 			php_error_docref(NULL, E_WARNING, "Could not fetch buffer");
2181 			RETURN_FALSE;
2182 		}
2183 
2184 		if (node->type == XML_DOCUMENT_FRAG_NODE) {
2185 			int one_size;
2186 
2187 			for (node = node->children; node; node = node->next) {
2188 				one_size = htmlNodeDump(buf, docp, node);
2189 
2190 				if (one_size >= 0) {
2191 					size += one_size;
2192 				} else {
2193 					size = -1;
2194 					break;
2195 				}
2196 			}
2197 		} else {
2198 			size = htmlNodeDump(buf, docp, node);
2199 		}
2200 		if (size >= 0) {
2201 			mem = (xmlChar*) xmlBufferContent(buf);
2202 			if (!mem) {
2203 				RETVAL_FALSE;
2204 			} else {
2205 				RETVAL_STRINGL((const char*) mem, size);
2206 			}
2207 		} else {
2208 			php_error_docref(NULL, E_WARNING, "Error dumping HTML node");
2209 			RETVAL_FALSE;
2210 		}
2211 		xmlBufferFree(buf);
2212 	} else {
2213 #if LIBXML_VERSION >= 20623
2214 		htmlDocDumpMemoryFormat(docp, &mem, &size, format);
2215 #else
2216 		htmlDocDumpMemory(docp, &mem, &size);
2217 #endif
2218 		if (!size || !mem) {
2219 			RETVAL_FALSE;
2220 		} else {
2221 			RETVAL_STRINGL((const char*) mem, size);
2222 		}
2223 		if (mem)
2224 			xmlFree(mem);
2225 	}
2226 
2227 }
2228 /* }}} end dom_document_save_html */
2229 
2230 #endif  /* defined(LIBXML_HTML_ENABLED) */
2231 
2232 /* {{{ proto boolean DOMDocument::registerNodeClass(string baseclass, string extendedclass)
2233    Register extended class used to create base node type */
PHP_METHOD(domdocument,registerNodeClass)2234 PHP_METHOD(domdocument, registerNodeClass)
2235 {
2236 	zval *id;
2237 	xmlDoc *docp;
2238 	zend_class_entry *basece = dom_node_class_entry, *ce = NULL;
2239 	dom_object *intern;
2240 
2241 	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OCC!", &id, dom_document_class_entry, &basece, &ce) == FAILURE) {
2242 		return;
2243 	}
2244 
2245 	if (ce == NULL || instanceof_function(ce, basece)) {
2246 		DOM_GET_OBJ(docp, id, xmlDocPtr, intern);
2247 		dom_set_doc_classmap(intern->document, basece, ce);
2248 		RETURN_TRUE;
2249 	}
2250 
2251 	zend_throw_error(NULL, "Class %s is not derived from %s.", ZSTR_VAL(ce->name), ZSTR_VAL(basece->name));
2252 	RETURN_FALSE;
2253 }
2254 /* }}} */
2255 
2256 #endif  /* HAVE_LIBXML && HAVE_DOM */
2257 
2258 /*
2259  * Local variables:
2260  * tab-width: 4
2261  * c-basic-offset: 4
2262  * End:
2263  * vim600: noet sw=4 ts=4 fdm=marker
2264  * vim<600: noet sw=4 ts=4
2265  */
2266