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