xref: /PHP-7.4/ext/dom/node.c (revision 09669411)
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 
28 /* {{{ arginfo */
29 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_insert_before, 0, 0, 1)
30 	ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
31 	ZEND_ARG_OBJ_INFO(0, refChild, DOMNode, 1)
32 ZEND_END_ARG_INFO();
33 
34 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_replace_child, 0, 0, 2)
35 	ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
36 	ZEND_ARG_OBJ_INFO(0, oldChild, DOMNode, 0)
37 ZEND_END_ARG_INFO();
38 
39 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_remove_child, 0, 0, 1)
40 	ZEND_ARG_OBJ_INFO(0, oldChild, DOMNode, 0)
41 ZEND_END_ARG_INFO();
42 
43 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_append_child, 0, 0, 1)
44 	ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
45 ZEND_END_ARG_INFO();
46 
47 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_has_child_nodes, 0, 0, 0)
48 ZEND_END_ARG_INFO();
49 
50 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_clone_node, 0, 0, 0)
51 	ZEND_ARG_INFO(0, deep)
52 ZEND_END_ARG_INFO();
53 
54 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_normalize, 0, 0, 0)
55 ZEND_END_ARG_INFO();
56 
57 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_supported, 0, 0, 2)
58 	ZEND_ARG_INFO(0, feature)
59 	ZEND_ARG_INFO(0, version)
60 ZEND_END_ARG_INFO();
61 
62 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_has_attributes, 0, 0, 0)
63 ZEND_END_ARG_INFO();
64 
65 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_compare_document_position, 0, 0, 1)
66 	ZEND_ARG_OBJ_INFO(0, other, DOMNode, 0)
67 ZEND_END_ARG_INFO();
68 
69 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_same_node, 0, 0, 1)
70 	ZEND_ARG_OBJ_INFO(0, other, DOMNode, 0)
71 ZEND_END_ARG_INFO();
72 
73 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_lookup_prefix, 0, 0, 1)
74 	ZEND_ARG_INFO(0, namespaceURI)
75 ZEND_END_ARG_INFO();
76 
77 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_default_namespace, 0, 0, 1)
78 	ZEND_ARG_INFO(0, namespaceURI)
79 ZEND_END_ARG_INFO();
80 
81 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_lookup_namespace_uri, 0, 0, 1)
82 	ZEND_ARG_INFO(0, prefix)
83 ZEND_END_ARG_INFO();
84 
85 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_equal_node, 0, 0, 1)
86 	ZEND_ARG_OBJ_INFO(0, arg, DOMNode, 0)
87 ZEND_END_ARG_INFO();
88 
89 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_get_feature, 0, 0, 2)
90 	ZEND_ARG_INFO(0, feature)
91 	ZEND_ARG_INFO(0, version)
92 ZEND_END_ARG_INFO();
93 
94 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_set_user_data, 0, 0, 3)
95 	ZEND_ARG_INFO(0, key)
96 	ZEND_ARG_INFO(0, data)
97 	ZEND_ARG_INFO(0, handler)
98 ZEND_END_ARG_INFO();
99 
100 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_get_user_data, 0, 0, 1)
101 	ZEND_ARG_INFO(0, key)
102 ZEND_END_ARG_INFO();
103 
104 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_getNodePath, 0, 0, 0)
105 ZEND_END_ARG_INFO();
106 
107 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_getLineNo, 0, 0, 0)
108 ZEND_END_ARG_INFO();
109 
110 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_C14N, 0, 0, 0)
111 	ZEND_ARG_INFO(0, exclusive)
112 	ZEND_ARG_INFO(0, with_comments)
113 	ZEND_ARG_ARRAY_INFO(0, xpath, 1)
114 	ZEND_ARG_ARRAY_INFO(0, ns_prefixes, 1)
115 ZEND_END_ARG_INFO();
116 
117 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_C14NFile, 0, 0, 1)
118 	ZEND_ARG_INFO(0, uri)
119 	ZEND_ARG_INFO(0, exclusive)
120 	ZEND_ARG_INFO(0, with_comments)
121 	ZEND_ARG_ARRAY_INFO(0, xpath, 1)
122 	ZEND_ARG_ARRAY_INFO(0, ns_prefixes, 1)
123 ZEND_END_ARG_INFO();
124 /* }}} */
125 
126 /*
127 * class DOMNode
128 *
129 * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1950641247
130 * Since:
131 */
132 
133 const zend_function_entry php_dom_node_class_functions[] = { /* {{{ */
134 	PHP_FALIAS(insertBefore, dom_node_insert_before, arginfo_dom_node_insert_before)
135 	PHP_FALIAS(replaceChild, dom_node_replace_child, arginfo_dom_node_replace_child)
136 	PHP_FALIAS(removeChild, dom_node_remove_child, arginfo_dom_node_remove_child)
137 	PHP_FALIAS(appendChild, dom_node_append_child, arginfo_dom_node_append_child)
138 	PHP_FALIAS(hasChildNodes, dom_node_has_child_nodes, arginfo_dom_node_has_child_nodes)
139 	PHP_FALIAS(cloneNode, dom_node_clone_node, arginfo_dom_node_clone_node)
140 	PHP_FALIAS(normalize, dom_node_normalize, arginfo_dom_node_normalize)
141 	PHP_FALIAS(isSupported, dom_node_is_supported, arginfo_dom_node_is_supported)
142 	PHP_FALIAS(hasAttributes, dom_node_has_attributes, arginfo_dom_node_has_attributes)
143 	PHP_FALIAS(compareDocumentPosition, dom_node_compare_document_position, arginfo_dom_node_compare_document_position)
144 	PHP_FALIAS(isSameNode, dom_node_is_same_node, arginfo_dom_node_is_same_node)
145 	PHP_FALIAS(lookupPrefix, dom_node_lookup_prefix, arginfo_dom_node_lookup_prefix)
146 	PHP_FALIAS(isDefaultNamespace, dom_node_is_default_namespace, arginfo_dom_node_is_default_namespace)
147 	PHP_FALIAS(lookupNamespaceUri, dom_node_lookup_namespace_uri, arginfo_dom_node_lookup_namespace_uri)
148 	PHP_FALIAS(isEqualNode, dom_node_is_equal_node, arginfo_dom_node_is_equal_node)
149 	PHP_FALIAS(getFeature, dom_node_get_feature, arginfo_dom_node_get_feature)
150 	PHP_FALIAS(setUserData, dom_node_set_user_data, arginfo_dom_node_set_user_data)
151 	PHP_FALIAS(getUserData, dom_node_get_user_data, arginfo_dom_node_get_user_data)
152 	PHP_ME(domnode, getNodePath, arginfo_dom_node_getNodePath, ZEND_ACC_PUBLIC)
153 	PHP_ME(domnode, getLineNo, arginfo_dom_node_getLineNo, ZEND_ACC_PUBLIC)
154 	PHP_ME(domnode, C14N, arginfo_dom_node_C14N, ZEND_ACC_PUBLIC)
155 	PHP_ME(domnode, C14NFile, arginfo_dom_node_C14NFile, ZEND_ACC_PUBLIC)
156 	PHP_FE_END
157 };
158 /* }}} */
159 
dom_reconcile_ns(xmlDocPtr doc,xmlNodePtr nodep)160 static void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
161 {
162 	xmlNsPtr nsptr, nsdftptr, curns, prevns = NULL;
163 
164 	if (nodep->type == XML_ELEMENT_NODE) {
165 		/* Following if block primarily used for inserting nodes created via createElementNS */
166 		if (nodep->nsDef != NULL) {
167 			curns = nodep->nsDef;
168 			while (curns) {
169 				nsdftptr = curns->next;
170 				if (curns->href != NULL) {
171 					if((nsptr = xmlSearchNsByHref(doc, nodep->parent, curns->href)) &&
172 						(curns->prefix == NULL || xmlStrEqual(nsptr->prefix, curns->prefix))) {
173 						curns->next = NULL;
174 						if (prevns == NULL) {
175 							nodep->nsDef = nsdftptr;
176 						} else {
177 							prevns->next = nsdftptr;
178 						}
179 						dom_set_old_ns(doc, curns);
180 						curns = prevns;
181 					}
182 				}
183 				prevns = curns;
184 				curns = nsdftptr;
185 			}
186 		}
187 		xmlReconciliateNs(doc, nodep);
188 	}
189 }
190 /* }}} */
191 
192 /* {{{ nodeName	string
193 readonly=yes
194 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D095
195 Since:
196 */
dom_node_node_name_read(dom_object * obj,zval * retval)197 int dom_node_node_name_read(dom_object *obj, zval *retval)
198 {
199 	xmlNode *nodep;
200 	xmlNsPtr ns;
201 	char *str = NULL;
202 	xmlChar *qname = NULL;
203 
204 	nodep = dom_object_get_node(obj);
205 
206 	if (nodep == NULL) {
207 		php_dom_throw_error(INVALID_STATE_ERR, 0);
208 		return FAILURE;
209 	}
210 
211 	switch (nodep->type) {
212 		case XML_ATTRIBUTE_NODE:
213 		case XML_ELEMENT_NODE:
214 			ns = nodep->ns;
215 			if (ns != NULL && ns->prefix) {
216 				qname = xmlStrdup(ns->prefix);
217 				qname = xmlStrcat(qname, (xmlChar *) ":");
218 				qname = xmlStrcat(qname, nodep->name);
219 				str = (char *) qname;
220 			} else {
221 				str = (char *) nodep->name;
222 			}
223 			break;
224 		case XML_NAMESPACE_DECL:
225 			ns = nodep->ns;
226 			if (ns != NULL && ns->prefix) {
227 				qname = xmlStrdup((xmlChar *) "xmlns");
228 				qname = xmlStrcat(qname, (xmlChar *) ":");
229 				qname = xmlStrcat(qname, nodep->name);
230 				str = (char *) qname;
231 			} else {
232 				str = (char *) nodep->name;
233 			}
234 			break;
235 		case XML_DOCUMENT_TYPE_NODE:
236 		case XML_DTD_NODE:
237 		case XML_PI_NODE:
238 		case XML_ENTITY_DECL:
239 		case XML_ENTITY_REF_NODE:
240 		case XML_NOTATION_NODE:
241 			str = (char *) nodep->name;
242 			break;
243 		case XML_CDATA_SECTION_NODE:
244 			str = "#cdata-section";
245 			break;
246 		case XML_COMMENT_NODE:
247 			str = "#comment";
248 			break;
249 		case XML_HTML_DOCUMENT_NODE:
250 		case XML_DOCUMENT_NODE:
251 			str = "#document";
252 			break;
253 		case XML_DOCUMENT_FRAG_NODE:
254 			str = "#document-fragment";
255 			break;
256 		case XML_TEXT_NODE:
257 			str = "#text";
258 			break;
259 		default:
260 			php_error_docref(NULL, E_WARNING, "Invalid Node Type");
261 	}
262 
263 	if (str != NULL) {
264 		ZVAL_STRING(retval, str);
265 	} else {
266 		ZVAL_EMPTY_STRING(retval);
267 	}
268 
269 	if (qname != NULL) {
270 		xmlFree(qname);
271 	}
272 
273 	return SUCCESS;
274 
275 }
276 
277 /* }}} */
278 
279 /* {{{ nodeValue	string
280 readonly=no
281 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D080
282 Since:
283 */
dom_node_node_value_read(dom_object * obj,zval * retval)284 int dom_node_node_value_read(dom_object *obj, zval *retval)
285 {
286 	xmlNode *nodep = dom_object_get_node(obj);
287 	char *str = NULL;
288 
289 	if (nodep == NULL) {
290 		php_dom_throw_error(INVALID_STATE_ERR, 0);
291 		return FAILURE;
292 	}
293 
294 	/* Access to Element node is implemented as a convenience method */
295 	switch (nodep->type) {
296 		case XML_ATTRIBUTE_NODE:
297 		case XML_TEXT_NODE:
298 		case XML_ELEMENT_NODE:
299 		case XML_COMMENT_NODE:
300 		case XML_CDATA_SECTION_NODE:
301 		case XML_PI_NODE:
302 			str = (char *) xmlNodeGetContent(nodep);
303 			break;
304 		case XML_NAMESPACE_DECL:
305 			str = (char *) xmlNodeGetContent(nodep->children);
306 			break;
307 		default:
308 			str = NULL;
309 			break;
310 	}
311 
312 	if(str != NULL) {
313 		ZVAL_STRING(retval, str);
314 		xmlFree(str);
315 	} else {
316 		ZVAL_NULL(retval);
317 	}
318 
319 	return SUCCESS;
320 
321 }
322 
dom_node_node_value_write(dom_object * obj,zval * newval)323 int dom_node_node_value_write(dom_object *obj, zval *newval)
324 {
325 	xmlNode *nodep = dom_object_get_node(obj);
326 	zend_string *str;
327 
328 	if (nodep == NULL) {
329 		php_dom_throw_error(INVALID_STATE_ERR, 0);
330 		return FAILURE;
331 	}
332 
333 	str = zval_try_get_string(newval);
334 	if (UNEXPECTED(!str)) {
335 		return FAILURE;
336 	}
337 
338 	/* Access to Element node is implemented as a convenience method */
339 	switch (nodep->type) {
340 		case XML_ELEMENT_NODE:
341 		case XML_ATTRIBUTE_NODE:
342 			if (nodep->children) {
343 				node_list_unlink(nodep->children);
344 				php_libxml_node_free_list((xmlNodePtr) nodep->children);
345 				nodep->children = NULL;
346 			}
347 		case XML_TEXT_NODE:
348 		case XML_COMMENT_NODE:
349 		case XML_CDATA_SECTION_NODE:
350 		case XML_PI_NODE:
351 			xmlNodeSetContentLen(nodep, (xmlChar *) ZSTR_VAL(str), ZSTR_LEN(str) + 1);
352 			break;
353 		default:
354 			break;
355 	}
356 
357 	zend_string_release_ex(str, 0);
358 	return SUCCESS;
359 }
360 
361 /* }}} */
362 
363 /* {{{ nodeType	int
364 readonly=yes
365 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-111237558
366 Since:
367 */
dom_node_node_type_read(dom_object * obj,zval * retval)368 int dom_node_node_type_read(dom_object *obj, zval *retval)
369 {
370 	xmlNode *nodep;
371 
372 	nodep = dom_object_get_node(obj);
373 
374 	if (nodep == NULL) {
375 		php_dom_throw_error(INVALID_STATE_ERR, 0);
376 		return FAILURE;
377 	}
378 
379 	/* Specs dictate that they are both type XML_DOCUMENT_TYPE_NODE */
380 	if (nodep->type == XML_DTD_NODE) {
381 		ZVAL_LONG(retval, XML_DOCUMENT_TYPE_NODE);
382 	} else {
383 		ZVAL_LONG(retval, nodep->type);
384 	}
385 
386 	return SUCCESS;
387 }
388 
389 /* }}} */
390 
391 /* {{{ parentNode	DomNode
392 readonly=yes
393 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1060184317
394 Since:
395 */
dom_node_parent_node_read(dom_object * obj,zval * retval)396 int dom_node_parent_node_read(dom_object *obj, zval *retval)
397 {
398 	xmlNode *nodep, *nodeparent;
399 
400 	nodep = dom_object_get_node(obj);
401 
402 	if (nodep == NULL) {
403 		php_dom_throw_error(INVALID_STATE_ERR, 0);
404 		return FAILURE;
405 	}
406 
407 	nodeparent = nodep->parent;
408 	if (!nodeparent) {
409 		ZVAL_NULL(retval);
410 		return SUCCESS;
411 	}
412 
413 	php_dom_create_object(nodeparent, retval, obj);
414 	return SUCCESS;
415 }
416 
417 /* }}} */
418 
419 /* {{{ childNodes	DomNodeList
420 readonly=yes
421 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1451460987
422 Since:
423 */
dom_node_child_nodes_read(dom_object * obj,zval * retval)424 int dom_node_child_nodes_read(dom_object *obj, zval *retval)
425 {
426 	xmlNode *nodep = dom_object_get_node(obj);
427 	dom_object *intern;
428 
429 	if (nodep == NULL) {
430 		php_dom_throw_error(INVALID_STATE_ERR, 0);
431 		return FAILURE;
432 	}
433 
434 	php_dom_create_interator(retval, DOM_NODELIST);
435 	intern = Z_DOMOBJ_P(retval);
436 	dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, NULL);
437 
438 	return SUCCESS;
439 }
440 
441 /* }}} */
442 
443 /* {{{ firstChild DomNode
444 readonly=yes
445 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-169727388
446 Since:
447 */
dom_node_first_child_read(dom_object * obj,zval * retval)448 int dom_node_first_child_read(dom_object *obj, zval *retval)
449 {
450 	xmlNode *nodep, *first = NULL;
451 
452 	nodep = dom_object_get_node(obj);
453 
454 	if (nodep == NULL) {
455 		php_dom_throw_error(INVALID_STATE_ERR, 0);
456 		return FAILURE;
457 	}
458 
459 	if (dom_node_children_valid(nodep) == SUCCESS) {
460 		first = nodep->children;
461 	}
462 
463 	if (!first) {
464 		ZVAL_NULL(retval);
465 		return SUCCESS;
466 	}
467 
468 	php_dom_create_object(first, retval, obj);
469 	return SUCCESS;
470 }
471 
472 /* }}} */
473 
474 /* {{{ lastChild	DomNode
475 readonly=yes
476 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-61AD09FB
477 Since:
478 */
dom_node_last_child_read(dom_object * obj,zval * retval)479 int dom_node_last_child_read(dom_object *obj, zval *retval)
480 {
481 	xmlNode *nodep, *last = NULL;
482 
483 	nodep = dom_object_get_node(obj);
484 
485 	if (nodep == NULL) {
486 		php_dom_throw_error(INVALID_STATE_ERR, 0);
487 		return FAILURE;
488 	}
489 
490 	if (dom_node_children_valid(nodep) == SUCCESS) {
491 		last = nodep->last;
492 	}
493 
494 	if (!last) {
495 		ZVAL_NULL(retval);
496 		return SUCCESS;
497 	}
498 
499 	php_dom_create_object(last, retval, obj);
500 	return SUCCESS;
501 }
502 
503 /* }}} */
504 
505 /* {{{ previousSibling	DomNode
506 readonly=yes
507 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-640FB3C8
508 Since:
509 */
dom_node_previous_sibling_read(dom_object * obj,zval * retval)510 int dom_node_previous_sibling_read(dom_object *obj, zval *retval)
511 {
512 	xmlNode *nodep, *prevsib;
513 
514 	nodep = dom_object_get_node(obj);
515 
516 	if (nodep == NULL) {
517 		php_dom_throw_error(INVALID_STATE_ERR, 0);
518 		return FAILURE;
519 	}
520 
521 	prevsib = nodep->prev;
522 	if (!prevsib) {
523 		ZVAL_NULL(retval);
524 		return SUCCESS;
525 	}
526 
527 	php_dom_create_object(prevsib, retval, obj);
528 	return SUCCESS;
529 }
530 
531 /* }}} */
532 
533 /* {{{ nextSibling	DomNode
534 readonly=yes
535 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6AC54C2F
536 Since:
537 */
dom_node_next_sibling_read(dom_object * obj,zval * retval)538 int dom_node_next_sibling_read(dom_object *obj, zval *retval)
539 {
540 	xmlNode *nodep, *nextsib;
541 
542 	nodep = dom_object_get_node(obj);
543 
544 	if (nodep == NULL) {
545 		php_dom_throw_error(INVALID_STATE_ERR, 0);
546 		return FAILURE;
547 	}
548 
549 	nextsib = nodep->next;
550 	if (!nextsib) {
551 		ZVAL_NULL(retval);
552 		return SUCCESS;
553 	}
554 
555 	php_dom_create_object(nextsib, retval, obj);
556 	return SUCCESS;
557 }
558 
559 /* }}} */
560 
561 /* {{{ attributes	DomNamedNodeMap
562 readonly=yes
563 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-84CF096
564 Since:
565 */
dom_node_attributes_read(dom_object * obj,zval * retval)566 int dom_node_attributes_read(dom_object *obj, zval *retval)
567 {
568 	xmlNode *nodep = dom_object_get_node(obj);
569 	dom_object *intern;
570 
571 	if (nodep == NULL) {
572 		php_dom_throw_error(INVALID_STATE_ERR, 0);
573 		return FAILURE;
574 	}
575 
576 	if (nodep->type == XML_ELEMENT_NODE) {
577 		php_dom_create_interator(retval, DOM_NAMEDNODEMAP);
578 		intern = Z_DOMOBJ_P(retval);
579 		dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, NULL);
580 	} else {
581 		ZVAL_NULL(retval);
582 	}
583 
584 	return SUCCESS;
585 }
586 
587 /* }}} */
588 
589 /* {{{ ownerDocument	DomDocument
590 readonly=yes
591 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-node-ownerDoc
592 Since:
593 */
dom_node_owner_document_read(dom_object * obj,zval * retval)594 int dom_node_owner_document_read(dom_object *obj, zval *retval)
595 {
596 	xmlNode *nodep = dom_object_get_node(obj);
597 	xmlDocPtr docp;
598 
599 	if (nodep == NULL) {
600 		php_dom_throw_error(INVALID_STATE_ERR, 0);
601 		return FAILURE;
602 	}
603 
604 	if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
605 		ZVAL_NULL(retval);
606 		return SUCCESS;
607 	}
608 
609 	docp = nodep->doc;
610 	if (!docp) {
611 		return FAILURE;
612 	}
613 
614 	php_dom_create_object((xmlNodePtr) docp, retval, obj);
615 	return SUCCESS;
616 }
617 
618 /* }}} */
619 
620 /* {{{ namespaceUri	string
621 readonly=yes
622 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSname
623 Since: DOM Level 2
624 */
dom_node_namespace_uri_read(dom_object * obj,zval * retval)625 int dom_node_namespace_uri_read(dom_object *obj, zval *retval)
626 {
627 	xmlNode *nodep = dom_object_get_node(obj);
628 	char *str = NULL;
629 
630 	if (nodep == NULL) {
631 		php_dom_throw_error(INVALID_STATE_ERR, 0);
632 		return FAILURE;
633 	}
634 
635 	switch (nodep->type) {
636 		case XML_ELEMENT_NODE:
637 		case XML_ATTRIBUTE_NODE:
638 		case XML_NAMESPACE_DECL:
639 			if (nodep->ns != NULL) {
640 				str = (char *) nodep->ns->href;
641 			}
642 			break;
643 		default:
644 			str = NULL;
645 			break;
646 	}
647 
648 	if (str != NULL) {
649 		ZVAL_STRING(retval, str);
650 	} else {
651 		ZVAL_NULL(retval);
652 	}
653 
654 	return SUCCESS;
655 }
656 
657 /* }}} */
658 
659 /* {{{ prefix	string
660 readonly=no
661 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSPrefix
662 Since: DOM Level 2
663 */
dom_node_prefix_read(dom_object * obj,zval * retval)664 int dom_node_prefix_read(dom_object *obj, zval *retval)
665 {
666 	xmlNode *nodep = dom_object_get_node(obj);
667 	xmlNsPtr ns;
668 	char *str = NULL;
669 
670 	if (nodep == NULL) {
671 		php_dom_throw_error(INVALID_STATE_ERR, 0);
672 		return FAILURE;
673 	}
674 
675 	switch (nodep->type) {
676 		case XML_ELEMENT_NODE:
677 		case XML_ATTRIBUTE_NODE:
678 		case XML_NAMESPACE_DECL:
679 			ns = nodep->ns;
680 			if (ns != NULL && ns->prefix) {
681 				str = (char *) ns->prefix;
682 			}
683 			break;
684 		default:
685 			str = NULL;
686 			break;
687 	}
688 
689 	if (str == NULL) {
690 		ZVAL_EMPTY_STRING(retval);
691 	} else {
692 		ZVAL_STRING(retval, str);
693 	}
694 	return SUCCESS;
695 
696 }
697 
dom_node_prefix_write(dom_object * obj,zval * newval)698 int dom_node_prefix_write(dom_object *obj, zval *newval)
699 {
700 	zend_string *str;
701 	xmlNode *nodep, *nsnode = NULL;
702 	xmlNsPtr ns = NULL, curns;
703 	char *strURI;
704 	char *prefix;
705 
706 	nodep = dom_object_get_node(obj);
707 
708 	if (nodep == NULL) {
709 		php_dom_throw_error(INVALID_STATE_ERR, 0);
710 		return FAILURE;
711 	}
712 
713 	switch (nodep->type) {
714 		case XML_ELEMENT_NODE:
715 			nsnode = nodep;
716 		case XML_ATTRIBUTE_NODE:
717 			if (nsnode == NULL) {
718 				nsnode = nodep->parent;
719 				if (nsnode == NULL) {
720 					nsnode = xmlDocGetRootElement(nodep->doc);
721 				}
722 			}
723 			str = zval_try_get_string(newval);
724 			if (UNEXPECTED(!str)) {
725 				return FAILURE;
726 			}
727 
728 			prefix = ZSTR_VAL(str);
729 			if (nsnode && nodep->ns != NULL && !xmlStrEqual(nodep->ns->prefix, (xmlChar *)prefix)) {
730 				strURI = (char *) nodep->ns->href;
731 				if (strURI == NULL ||
732 					(!strcmp(prefix, "xml") && strcmp(strURI, (char *) XML_XML_NAMESPACE)) ||
733 					(nodep->type == XML_ATTRIBUTE_NODE && !strcmp(prefix, "xmlns") &&
734 					 strcmp(strURI, (char *) DOM_XMLNS_NAMESPACE)) ||
735 					(nodep->type == XML_ATTRIBUTE_NODE && !strcmp((char *) nodep->name, "xmlns"))) {
736 					ns = NULL;
737 				} else {
738 					curns = nsnode->nsDef;
739 					while (curns != NULL) {
740 						if (xmlStrEqual((xmlChar *)prefix, curns->prefix) && xmlStrEqual(nodep->ns->href, curns->href)) {
741 							ns = curns;
742 							break;
743 						}
744 						curns = curns->next;
745 					}
746 					if (ns == NULL) {
747 						ns = xmlNewNs(nsnode, nodep->ns->href, (xmlChar *)prefix);
748 					}
749 				}
750 
751 				if (ns == NULL) {
752 					zend_string_release_ex(str, 0);
753 					php_dom_throw_error(NAMESPACE_ERR, dom_get_strict_error(obj->document));
754 					return FAILURE;
755 				}
756 
757 				xmlSetNs(nodep, ns);
758 			}
759 			zend_string_release_ex(str, 0);
760 			break;
761 		default:
762 			break;
763 	}
764 
765 	return SUCCESS;
766 }
767 
768 /* }}} */
769 
770 /* {{{ localName	string
771 readonly=yes
772 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSLocalN
773 Since: DOM Level 2
774 */
dom_node_local_name_read(dom_object * obj,zval * retval)775 int dom_node_local_name_read(dom_object *obj, zval *retval)
776 {
777 	xmlNode *nodep = dom_object_get_node(obj);
778 
779 	if (nodep == NULL) {
780 		php_dom_throw_error(INVALID_STATE_ERR, 0);
781 		return FAILURE;
782 	}
783 
784 	if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE || nodep->type == XML_NAMESPACE_DECL) {
785 		ZVAL_STRING(retval, (char *) (nodep->name));
786 	} else {
787 		ZVAL_NULL(retval);
788 	}
789 
790 	return SUCCESS;
791 }
792 
793 /* }}} */
794 
795 /* {{{ baseURI	string
796 readonly=yes
797 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-baseURI
798 Since: DOM Level 3
799 */
dom_node_base_uri_read(dom_object * obj,zval * retval)800 int dom_node_base_uri_read(dom_object *obj, zval *retval)
801 {
802 	xmlNode *nodep = dom_object_get_node(obj);
803 	xmlChar *baseuri;
804 
805 	if (nodep == NULL) {
806 		php_dom_throw_error(INVALID_STATE_ERR, 0);
807 		return FAILURE;
808 	}
809 
810 	baseuri = xmlNodeGetBase(nodep->doc, nodep);
811 	if (baseuri) {
812 		ZVAL_STRING(retval, (char *) (baseuri));
813 		xmlFree(baseuri);
814 	} else {
815 		ZVAL_NULL(retval);
816 	}
817 
818 	return SUCCESS;
819 }
820 
821 /* }}} */
822 
823 /* {{{ textContent	string
824 readonly=no
825 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-textContent
826 Since: DOM Level 3
827 */
dom_node_text_content_read(dom_object * obj,zval * retval)828 int dom_node_text_content_read(dom_object *obj, zval *retval)
829 {
830 	xmlNode *nodep = dom_object_get_node(obj);
831 	char *str = NULL;
832 
833 	if (nodep == NULL) {
834 		php_dom_throw_error(INVALID_STATE_ERR, 0);
835 		return FAILURE;
836 	}
837 
838 	str = (char *) xmlNodeGetContent(nodep);
839 
840 	if (str != NULL) {
841 		ZVAL_STRING(retval, str);
842 		xmlFree(str);
843 	} else {
844 		ZVAL_EMPTY_STRING(retval);
845 	}
846 
847 	return SUCCESS;
848 }
849 
dom_node_text_content_write(dom_object * obj,zval * newval)850 int dom_node_text_content_write(dom_object *obj, zval *newval)
851 {
852 	xmlNode *nodep = dom_object_get_node(obj);
853 	zend_string *str;
854 
855 	if (nodep == NULL) {
856 		php_dom_throw_error(INVALID_STATE_ERR, 0);
857 		return FAILURE;
858 	}
859 
860 	str = zval_try_get_string(newval);
861 	if (UNEXPECTED(!str)) {
862 		return FAILURE;
863 	}
864 
865 	if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE) {
866 		if (nodep->children) {
867 			node_list_unlink(nodep->children);
868 			php_libxml_node_free_list((xmlNodePtr) nodep->children);
869 			nodep->children = NULL;
870 		}
871 	}
872 
873 	/* we have to use xmlNodeAddContent() to get the same behavior as with xmlNewText() */
874 	xmlNodeSetContent(nodep, (xmlChar *) "");
875 	xmlNodeAddContent(nodep, (xmlChar *) ZSTR_VAL(str));
876 	zend_string_release_ex(str, 0);
877 
878 	return SUCCESS;
879 }
880 
881 /* }}} */
882 
_php_dom_insert_fragment(xmlNodePtr nodep,xmlNodePtr prevsib,xmlNodePtr nextsib,xmlNodePtr fragment,dom_object * intern,dom_object * childobj)883 static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib, xmlNodePtr nextsib, xmlNodePtr fragment, dom_object *intern, dom_object *childobj) /* {{{ */
884 {
885 	xmlNodePtr newchild, node;
886 
887 	newchild = fragment->children;
888 
889 	if (newchild) {
890 		if (prevsib == NULL) {
891 			nodep->children = newchild;
892 		} else {
893 			prevsib->next = newchild;
894 		}
895 		newchild->prev = prevsib;
896 		if (nextsib == NULL) {
897 			nodep->last = fragment->last;
898 		} else {
899 			fragment->last->next = nextsib;
900 			nextsib->prev = fragment->last;
901 		}
902 
903 		node = newchild;
904 		while (node != NULL) {
905 			node->parent = nodep;
906 			if (node->doc != nodep->doc) {
907 				xmlSetTreeDoc(node, nodep->doc);
908 				if (node->_private != NULL) {
909 					childobj = node->_private;
910 					childobj->document = intern->document;
911 					php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL);
912 				}
913 			}
914 			if (node == fragment->last) {
915 				break;
916 			}
917 			node = node->next;
918 		}
919 
920 		fragment->children = NULL;
921 		fragment->last = NULL;
922 	}
923 
924 	return newchild;
925 }
926 /* }}} */
927 
928 /* {{{ proto domnode dom_node_insert_before(DomNode newChild, DomNode refChild);
929 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727
930 Since:
931 */
PHP_FUNCTION(dom_node_insert_before)932 PHP_FUNCTION(dom_node_insert_before)
933 {
934 	zval *id, *node, *ref = NULL;
935 	xmlNodePtr child, new_child, parentp, refp;
936 	dom_object *intern, *childobj, *refpobj;
937 	int ret, stricterror;
938 
939 	id = ZEND_THIS;
940 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|O!", &node, dom_node_class_entry, &ref, dom_node_class_entry) == FAILURE) {
941 		return;
942 	}
943 
944 	DOM_GET_OBJ(parentp, id, xmlNodePtr, intern);
945 
946 	if (dom_node_children_valid(parentp) == FAILURE) {
947 		RETURN_FALSE;
948 	}
949 
950 	DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
951 
952 	new_child = NULL;
953 
954 	stricterror = dom_get_strict_error(intern->document);
955 
956 	if (dom_node_is_read_only(parentp) == SUCCESS ||
957 		(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
958 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
959 		RETURN_FALSE;
960 	}
961 
962 	if (dom_hierarchy(parentp, child) == FAILURE) {
963 		php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
964 		RETURN_FALSE;
965 	}
966 
967 	if (child->doc != parentp->doc && child->doc != NULL) {
968 		php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
969 		RETURN_FALSE;
970 	}
971 
972 	if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
973 		php_error_docref(NULL, E_WARNING, "Document Fragment is empty");
974 		RETURN_FALSE;
975 	}
976 
977 	if (child->doc == NULL && parentp->doc != NULL) {
978 		childobj->document = intern->document;
979 		php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL);
980 	}
981 
982 	if (ref != NULL) {
983 		DOM_GET_OBJ(refp, ref, xmlNodePtr, refpobj);
984 		if (refp->parent != parentp) {
985 			php_dom_throw_error(NOT_FOUND_ERR, stricterror);
986 			RETURN_FALSE;
987 		}
988 
989 		if (child->parent != NULL) {
990 			xmlUnlinkNode(child);
991 		}
992 
993 		if (child->type == XML_TEXT_NODE && (refp->type == XML_TEXT_NODE ||
994 			(refp->prev != NULL && refp->prev->type == XML_TEXT_NODE))) {
995 			if (child->doc == NULL) {
996 				xmlSetTreeDoc(child, parentp->doc);
997 			}
998 			new_child = child;
999 			new_child->parent = refp->parent;
1000 			new_child->next = refp;
1001 			new_child->prev = refp->prev;
1002 			refp->prev = new_child;
1003 			if (new_child->prev != NULL) {
1004 				new_child->prev->next = new_child;
1005 			}
1006 			if (new_child->parent != NULL) {
1007 				if (new_child->parent->children == refp) {
1008 					new_child->parent->children = new_child;
1009 				}
1010 			}
1011 
1012 		} else if (child->type == XML_ATTRIBUTE_NODE) {
1013 			xmlAttrPtr lastattr;
1014 
1015 			if (child->ns == NULL)
1016 				lastattr = xmlHasProp(refp->parent, child->name);
1017 			else
1018 				lastattr = xmlHasNsProp(refp->parent, child->name, child->ns->href);
1019 			if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
1020 				if (lastattr != (xmlAttrPtr) child) {
1021 					xmlUnlinkNode((xmlNodePtr) lastattr);
1022 					php_libxml_node_free_resource((xmlNodePtr) lastattr);
1023 				} else {
1024 					DOM_RET_OBJ(child, &ret, intern);
1025 					return;
1026 				}
1027 			}
1028 		} else if (child->type == XML_DOCUMENT_FRAG_NODE) {
1029 			new_child = _php_dom_insert_fragment(parentp, refp->prev, refp, child, intern, childobj);
1030 		}
1031 
1032 		if (new_child == NULL) {
1033 			new_child = xmlAddPrevSibling(refp, child);
1034 		}
1035 	} else {
1036 		if (child->parent != NULL){
1037 			xmlUnlinkNode(child);
1038 		}
1039 		if (child->type == XML_TEXT_NODE && parentp->last != NULL && parentp->last->type == XML_TEXT_NODE) {
1040 			child->parent = parentp;
1041 			if (child->doc == NULL) {
1042 				xmlSetTreeDoc(child, parentp->doc);
1043 			}
1044 			new_child = child;
1045 			if (parentp->children == NULL) {
1046 				parentp->children = child;
1047 				parentp->last = child;
1048 			} else {
1049 				child = parentp->last;
1050 				child->next = new_child;
1051 				new_child->prev = child;
1052 				parentp->last = new_child;
1053 			}
1054 		} else 	if (child->type == XML_ATTRIBUTE_NODE) {
1055 			xmlAttrPtr lastattr;
1056 
1057 			if (child->ns == NULL)
1058 				lastattr = xmlHasProp(parentp, child->name);
1059 			else
1060 				lastattr = xmlHasNsProp(parentp, child->name, child->ns->href);
1061 			if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
1062 				if (lastattr != (xmlAttrPtr) child) {
1063 					xmlUnlinkNode((xmlNodePtr) lastattr);
1064 					php_libxml_node_free_resource((xmlNodePtr) lastattr);
1065 				} else {
1066 					DOM_RET_OBJ(child, &ret, intern);
1067 					return;
1068 				}
1069 			}
1070 		} else if (child->type == XML_DOCUMENT_FRAG_NODE) {
1071 			new_child = _php_dom_insert_fragment(parentp, parentp->last, NULL, child, intern, childobj);
1072 		}
1073 		if (new_child == NULL) {
1074 			new_child = xmlAddChild(parentp, child);
1075 		}
1076 	}
1077 
1078 	if (NULL == new_child) {
1079 		php_error_docref(NULL, E_WARNING, "Couldn't add newnode as the previous sibling of refnode");
1080 		RETURN_FALSE;
1081 	}
1082 
1083 	dom_reconcile_ns(parentp->doc, new_child);
1084 
1085 	DOM_RET_OBJ(new_child, &ret, intern);
1086 
1087 }
1088 /* }}} end dom_node_insert_before */
1089 
1090 /* {{{ proto DomNode dom_node_replace_child(DomNode newChild, DomNode oldChild);
1091 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-785887307
1092 Since:
1093 */
PHP_FUNCTION(dom_node_replace_child)1094 PHP_FUNCTION(dom_node_replace_child)
1095 {
1096 	zval *id, *newnode, *oldnode;
1097 	xmlNodePtr children, newchild, oldchild, nodep;
1098 	dom_object *intern, *newchildobj, *oldchildobj;
1099 	int foundoldchild = 0, stricterror;
1100 
1101 	int ret;
1102 
1103 	id = ZEND_THIS;
1104 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "OO", &newnode, dom_node_class_entry, &oldnode, dom_node_class_entry) == FAILURE) {
1105 		return;
1106 	}
1107 
1108 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1109 
1110 	if (dom_node_children_valid(nodep) == FAILURE) {
1111 		RETURN_FALSE;
1112 	}
1113 
1114 	DOM_GET_OBJ(newchild, newnode, xmlNodePtr, newchildobj);
1115 	DOM_GET_OBJ(oldchild, oldnode, xmlNodePtr, oldchildobj);
1116 
1117 	children = nodep->children;
1118 	if (!children) {
1119 		RETURN_FALSE;
1120 	}
1121 
1122 	stricterror = dom_get_strict_error(intern->document);
1123 
1124 	if (dom_node_is_read_only(nodep) == SUCCESS ||
1125 		(newchild->parent != NULL && dom_node_is_read_only(newchild->parent) == SUCCESS)) {
1126 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
1127 		RETURN_FALSE;
1128 	}
1129 
1130 	if (newchild->doc != nodep->doc && newchild->doc != NULL) {
1131 		php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
1132 		RETURN_FALSE;
1133 	}
1134 
1135 	if (dom_hierarchy(nodep, newchild) == FAILURE) {
1136 		php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
1137 		RETURN_FALSE;
1138 	}
1139 
1140 	/* check for the old child and whether the new child is already a child */
1141 	while (children) {
1142 		if (children == oldchild) {
1143 			foundoldchild = 1;
1144 			break;
1145 		}
1146 		children = children->next;
1147 	}
1148 
1149 	if (foundoldchild) {
1150 		if (newchild->type == XML_DOCUMENT_FRAG_NODE) {
1151 			xmlNodePtr prevsib, nextsib;
1152 			prevsib = oldchild->prev;
1153 			nextsib = oldchild->next;
1154 
1155 			xmlUnlinkNode(oldchild);
1156 
1157 			newchild = _php_dom_insert_fragment(nodep, prevsib, nextsib, newchild, intern, newchildobj);
1158 			if (newchild) {
1159 				dom_reconcile_ns(nodep->doc, newchild);
1160 			}
1161 		} else if (oldchild != newchild) {
1162 			if (newchild->doc == NULL && nodep->doc != NULL) {
1163 				xmlSetTreeDoc(newchild, nodep->doc);
1164 				newchildobj->document = intern->document;
1165 				php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL);
1166 			}
1167 			xmlReplaceNode(oldchild, newchild);
1168 			dom_reconcile_ns(nodep->doc, newchild);
1169 		}
1170 		DOM_RET_OBJ(oldchild, &ret, intern);
1171 		return;
1172 	} else {
1173 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
1174 		RETURN_FALSE;
1175 	}
1176 }
1177 /* }}} end dom_node_replace_child */
1178 
1179 /* {{{ proto DomNode dom_node_remove_child(DomNode oldChild);
1180 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1734834066
1181 Since:
1182 */
PHP_FUNCTION(dom_node_remove_child)1183 PHP_FUNCTION(dom_node_remove_child)
1184 {
1185 	zval *id, *node;
1186 	xmlNodePtr children, child, nodep;
1187 	dom_object *intern, *childobj;
1188 	int ret, stricterror;
1189 
1190 	id = ZEND_THIS;
1191 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_node_class_entry) == FAILURE) {
1192 		return;
1193 	}
1194 
1195 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1196 
1197 	if (dom_node_children_valid(nodep) == FAILURE) {
1198 		RETURN_FALSE;
1199 	}
1200 
1201 	DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
1202 
1203 	stricterror = dom_get_strict_error(intern->document);
1204 
1205 	if (dom_node_is_read_only(nodep) == SUCCESS ||
1206 		(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
1207 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
1208 		RETURN_FALSE;
1209 	}
1210 
1211 	children = nodep->children;
1212 	if (!children) {
1213 		php_dom_throw_error(NOT_FOUND_ERR, stricterror);
1214 		RETURN_FALSE;
1215 	}
1216 
1217 	while (children) {
1218 		if (children == child) {
1219 			xmlUnlinkNode(child);
1220 			DOM_RET_OBJ(child, &ret, intern);
1221 			return;
1222 		}
1223 		children = children->next;
1224 	}
1225 
1226 	php_dom_throw_error(NOT_FOUND_ERR, stricterror);
1227 	RETURN_FALSE
1228 }
1229 /* }}} end dom_node_remove_child */
1230 
1231 /* {{{ proto DomNode dom_node_append_child(DomNode newChild);
1232 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-184E7107
1233 Since:
1234 */
PHP_FUNCTION(dom_node_append_child)1235 PHP_FUNCTION(dom_node_append_child)
1236 {
1237 	zval *id, *node;
1238 	xmlNodePtr child, nodep, new_child = NULL;
1239 	dom_object *intern, *childobj;
1240 	int ret, stricterror;
1241 
1242 	id = ZEND_THIS;
1243 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_node_class_entry) == FAILURE) {
1244 		return;
1245 	}
1246 
1247 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1248 
1249 	if (dom_node_children_valid(nodep) == FAILURE) {
1250 		RETURN_FALSE;
1251 	}
1252 
1253 	DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
1254 
1255 	stricterror = dom_get_strict_error(intern->document);
1256 
1257 	if (dom_node_is_read_only(nodep) == SUCCESS ||
1258 		(child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
1259 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
1260 		RETURN_FALSE;
1261 	}
1262 
1263 	if (dom_hierarchy(nodep, child) == FAILURE) {
1264 		php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror);
1265 		RETURN_FALSE;
1266 	}
1267 
1268 	if (!(child->doc == NULL || child->doc == nodep->doc)) {
1269 		php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror);
1270 		RETURN_FALSE;
1271 	}
1272 
1273 	if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
1274 		php_error_docref(NULL, E_WARNING, "Document Fragment is empty");
1275 		RETURN_FALSE;
1276 	}
1277 
1278 	if (child->doc == NULL && nodep->doc != NULL) {
1279 		childobj->document = intern->document;
1280 		php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL);
1281 	}
1282 
1283 	if (child->parent != NULL){
1284 		xmlUnlinkNode(child);
1285 	}
1286 
1287 	if (child->type == XML_TEXT_NODE && nodep->last != NULL && nodep->last->type == XML_TEXT_NODE) {
1288 		child->parent = nodep;
1289 		if (child->doc == NULL) {
1290 			xmlSetTreeDoc(child, nodep->doc);
1291 		}
1292 		new_child = child;
1293 		if (nodep->children == NULL) {
1294 			nodep->children = child;
1295 			nodep->last = child;
1296 		} else {
1297 			child = nodep->last;
1298 			child->next = new_child;
1299 			new_child->prev = child;
1300 			nodep->last = new_child;
1301 		}
1302 	} else 	if (child->type == XML_ATTRIBUTE_NODE) {
1303 		xmlAttrPtr lastattr;
1304 
1305 		if (child->ns == NULL)
1306 			lastattr = xmlHasProp(nodep, child->name);
1307 		else
1308 			lastattr = xmlHasNsProp(nodep, child->name, child->ns->href);
1309 		if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
1310 			if (lastattr != (xmlAttrPtr) child) {
1311 				xmlUnlinkNode((xmlNodePtr) lastattr);
1312 				php_libxml_node_free_resource((xmlNodePtr) lastattr);
1313 			}
1314 		}
1315 	} else if (child->type == XML_DOCUMENT_FRAG_NODE) {
1316 		new_child = _php_dom_insert_fragment(nodep, nodep->last, NULL, child, intern, childobj);
1317 	}
1318 
1319 	if (new_child == NULL) {
1320 		new_child = xmlAddChild(nodep, child);
1321 		if (new_child == NULL) {
1322 			php_error_docref(NULL, E_WARNING, "Couldn't append node");
1323 			RETURN_FALSE;
1324 		}
1325 	}
1326 
1327 	dom_reconcile_ns(nodep->doc, new_child);
1328 
1329 	DOM_RET_OBJ(new_child, &ret, intern);
1330 }
1331 /* }}} end dom_node_append_child */
1332 
1333 /* {{{ proto bool dom_node_has_child_nodes();
1334 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-810594187
1335 Since:
1336 */
PHP_FUNCTION(dom_node_has_child_nodes)1337 PHP_FUNCTION(dom_node_has_child_nodes)
1338 {
1339 	zval *id;
1340 	xmlNode *nodep;
1341 	dom_object *intern;
1342 
1343 	id = ZEND_THIS;
1344 	if (zend_parse_parameters_none() == FAILURE) {
1345 		return;
1346 	}
1347 
1348 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1349 
1350 	if (dom_node_children_valid(nodep) == FAILURE) {
1351 		RETURN_FALSE;
1352 	}
1353 
1354 	if (nodep->children) {
1355 		RETURN_TRUE;
1356 	} else {
1357 		RETURN_FALSE;
1358 	}
1359 }
1360 /* }}} end dom_node_has_child_nodes */
1361 
1362 /* {{{ proto DomNode dom_node_clone_node(bool deep);
1363 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3A0ED0A4
1364 Since:
1365 */
PHP_FUNCTION(dom_node_clone_node)1366 PHP_FUNCTION(dom_node_clone_node)
1367 {
1368 	zval *id;
1369 	xmlNode *n, *node;
1370 	int ret;
1371 	dom_object *intern;
1372 	zend_bool recursive = 0;
1373 
1374 	id = ZEND_THIS;
1375 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &recursive) == FAILURE) {
1376 		return;
1377 	}
1378 
1379 	DOM_GET_OBJ(n, id, xmlNodePtr, intern);
1380 
1381 	node = xmlDocCopyNode(n, n->doc, recursive);
1382 
1383 	if (!node) {
1384 		RETURN_FALSE;
1385 	}
1386 
1387 	/* When deep is false Element nodes still require the attributes
1388 	Following taken from libxml as xmlDocCopyNode doesn't do this */
1389 	if (n->type == XML_ELEMENT_NODE && recursive == 0) {
1390 		if (n->nsDef != NULL) {
1391 			node->nsDef = xmlCopyNamespaceList(n->nsDef);
1392 		}
1393 		if (n->ns != NULL) {
1394 			xmlNsPtr ns;
1395 			ns = xmlSearchNs(n->doc, node, n->ns->prefix);
1396 			if (ns == NULL) {
1397 				ns = xmlSearchNs(n->doc, n, n->ns->prefix);
1398 				if (ns != NULL) {
1399 					xmlNodePtr root = node;
1400 
1401 					while (root->parent != NULL) {
1402 						root = root->parent;
1403 					}
1404 					node->ns = xmlNewNs(root, ns->href, ns->prefix);
1405 				}
1406 			} else {
1407 				node->ns = ns;
1408 			}
1409 		}
1410 		if (n->properties != NULL) {
1411 			node->properties = xmlCopyPropList(node, n->properties);
1412 		}
1413 	}
1414 
1415 	/* If document cloned we want a new document proxy */
1416 	if (node->doc != n->doc) {
1417 		intern = NULL;
1418 	}
1419 
1420 	DOM_RET_OBJ(node, &ret, intern);
1421 }
1422 /* }}} end dom_node_clone_node */
1423 
1424 /* {{{ proto void dom_node_normalize();
1425 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-normalize
1426 Since:
1427 */
PHP_FUNCTION(dom_node_normalize)1428 PHP_FUNCTION(dom_node_normalize)
1429 {
1430 	zval *id;
1431 	xmlNode *nodep;
1432 	dom_object *intern;
1433 
1434 	id = ZEND_THIS;
1435 	if (zend_parse_parameters_none() == FAILURE) {
1436 		return;
1437 	}
1438 
1439 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1440 
1441 	dom_normalize(nodep);
1442 
1443 }
1444 /* }}} end dom_node_normalize */
1445 
1446 /* {{{ proto bool dom_node_is_supported(string feature, string version);
1447 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Level-2-Core-Node-supports
1448 Since: DOM Level 2
1449 */
PHP_FUNCTION(dom_node_is_supported)1450 PHP_FUNCTION(dom_node_is_supported)
1451 {
1452 	size_t feature_len, version_len;
1453 	char *feature, *version;
1454 
1455 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &feature, &feature_len, &version, &version_len) == FAILURE) {
1456 		return;
1457 	}
1458 
1459 	if (dom_has_feature(feature, version)) {
1460 		RETURN_TRUE;
1461 	} else {
1462 		RETURN_FALSE;
1463 	}
1464 }
1465 /* }}} end dom_node_is_supported */
1466 
1467 /* {{{ proto bool dom_node_has_attributes();
1468 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeHasAttrs
1469 Since: DOM Level 2
1470 */
PHP_FUNCTION(dom_node_has_attributes)1471 PHP_FUNCTION(dom_node_has_attributes)
1472 {
1473 	zval *id;
1474 	xmlNode *nodep;
1475 	dom_object *intern;
1476 
1477 	id = ZEND_THIS;
1478 	if (zend_parse_parameters_none() == FAILURE) {
1479 		return;
1480 	}
1481 
1482 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1483 
1484 	if (nodep->type != XML_ELEMENT_NODE)
1485 		RETURN_FALSE;
1486 
1487 	if (nodep->properties) {
1488 		RETURN_TRUE;
1489 	} else {
1490 		RETURN_FALSE;
1491 	}
1492 }
1493 /* }}} end dom_node_has_attributes */
1494 
1495 /* {{{ proto short dom_node_compare_document_position(DomNode other);
1496 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-compareDocumentPosition
1497 Since: DOM Level 3
1498 */
PHP_FUNCTION(dom_node_compare_document_position)1499 PHP_FUNCTION(dom_node_compare_document_position)
1500 {
1501  DOM_NOT_IMPLEMENTED();
1502 }
1503 /* }}} end dom_node_compare_document_position */
1504 
1505 /* {{{ proto bool dom_node_is_same_node(DomNode other);
1506 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isSameNode
1507 Since: DOM Level 3
1508 */
PHP_FUNCTION(dom_node_is_same_node)1509 PHP_FUNCTION(dom_node_is_same_node)
1510 {
1511 	zval *id, *node;
1512 	xmlNodePtr nodeotherp, nodep;
1513 	dom_object *intern, *nodeotherobj;
1514 
1515 	id = ZEND_THIS;
1516 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_node_class_entry) == FAILURE) {
1517 		return;
1518 	}
1519 
1520 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1521 
1522 	DOM_GET_OBJ(nodeotherp, node, xmlNodePtr, nodeotherobj);
1523 
1524 	if (nodep == nodeotherp) {
1525 		RETURN_TRUE;
1526 	} else {
1527 		RETURN_FALSE;
1528 	}
1529 }
1530 /* }}} end dom_node_is_same_node */
1531 
1532 /* {{{ proto string dom_node_lookup_prefix(string namespaceURI);
1533 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-lookupNamespacePrefix
1534 Since: DOM Level 3
1535 */
PHP_FUNCTION(dom_node_lookup_prefix)1536 PHP_FUNCTION(dom_node_lookup_prefix)
1537 {
1538 	zval *id;
1539 	xmlNodePtr nodep, lookupp = NULL;
1540 	dom_object *intern;
1541 	xmlNsPtr nsptr;
1542 	size_t uri_len = 0;
1543 	char *uri;
1544 
1545 	id = ZEND_THIS;
1546 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &uri, &uri_len) == FAILURE) {
1547 		return;
1548 	}
1549 
1550 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1551 
1552 	if (uri_len > 0) {
1553 		switch (nodep->type) {
1554 			case XML_ELEMENT_NODE:
1555 				lookupp = nodep;
1556 				break;
1557 			case XML_DOCUMENT_NODE:
1558 			case XML_HTML_DOCUMENT_NODE:
1559 				lookupp = xmlDocGetRootElement((xmlDocPtr) nodep);
1560 				break;
1561 			case XML_ENTITY_NODE :
1562 			case XML_NOTATION_NODE:
1563 			case XML_DOCUMENT_FRAG_NODE:
1564 			case XML_DOCUMENT_TYPE_NODE:
1565 			case XML_DTD_NODE:
1566 				RETURN_NULL();
1567 				break;
1568 			default:
1569 				lookupp =  nodep->parent;
1570 		}
1571 
1572 		if (lookupp != NULL) {
1573 			nsptr = xmlSearchNsByHref(lookupp->doc, lookupp, (xmlChar *) uri);
1574 			if (nsptr && nsptr->prefix != NULL) {
1575 				RETURN_STRING((char *) nsptr->prefix);
1576 			}
1577 		}
1578 	}
1579 
1580 	RETURN_NULL();
1581 }
1582 /* }}} end dom_node_lookup_prefix */
1583 
1584 /* {{{ proto bool dom_node_is_default_namespace(string namespaceURI);
1585 URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isDefaultNamespace
1586 Since: DOM Level 3
1587 */
PHP_FUNCTION(dom_node_is_default_namespace)1588 PHP_FUNCTION(dom_node_is_default_namespace)
1589 {
1590 	zval *id;
1591 	xmlNodePtr nodep;
1592 	dom_object *intern;
1593 	xmlNsPtr nsptr;
1594 	size_t uri_len = 0;
1595 	char *uri;
1596 
1597 	id = ZEND_THIS;
1598 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &uri, &uri_len) == FAILURE) {
1599 		return;
1600 	}
1601 
1602 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1603 	if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
1604 		nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
1605 	}
1606 
1607 	if (nodep && uri_len > 0) {
1608 		nsptr = xmlSearchNs(nodep->doc, nodep, NULL);
1609 		if (nsptr && xmlStrEqual(nsptr->href, (xmlChar *) uri)) {
1610 			RETURN_TRUE;
1611 		}
1612 	}
1613 
1614 	RETURN_FALSE;
1615 }
1616 /* }}} end dom_node_is_default_namespace */
1617 
1618 /* {{{ proto string dom_node_lookup_namespace_uri(string prefix);
1619 URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI
1620 Since: DOM Level 3
1621 */
PHP_FUNCTION(dom_node_lookup_namespace_uri)1622 PHP_FUNCTION(dom_node_lookup_namespace_uri)
1623 {
1624 	zval *id;
1625 	xmlNodePtr nodep;
1626 	dom_object *intern;
1627 	xmlNsPtr nsptr;
1628 	size_t prefix_len;
1629 	char *prefix;
1630 
1631 	id = ZEND_THIS;
1632 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!", &prefix, &prefix_len) == FAILURE) {
1633 		return;
1634 	}
1635 
1636 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1637 	if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
1638 		nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
1639 		if (nodep == NULL) {
1640 			RETURN_NULL();
1641 		}
1642 	}
1643 
1644 	nsptr = xmlSearchNs(nodep->doc, nodep, (xmlChar *) prefix);
1645 	if (nsptr && nsptr->href != NULL) {
1646 		RETURN_STRING((char *) nsptr->href);
1647 	}
1648 
1649 	RETURN_NULL();
1650 }
1651 /* }}} end dom_node_lookup_namespace_uri */
1652 
1653 /* {{{ proto bool dom_node_is_equal_node(DomNode arg);
1654 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isEqualNode
1655 Since: DOM Level 3
1656 */
PHP_FUNCTION(dom_node_is_equal_node)1657 PHP_FUNCTION(dom_node_is_equal_node)
1658 {
1659  DOM_NOT_IMPLEMENTED();
1660 }
1661 /* }}} end dom_node_is_equal_node */
1662 
1663 /* {{{ proto DomNode dom_node_get_feature(string feature, string version);
1664 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getFeature
1665 Since: DOM Level 3
1666 */
PHP_FUNCTION(dom_node_get_feature)1667 PHP_FUNCTION(dom_node_get_feature)
1668 {
1669  DOM_NOT_IMPLEMENTED();
1670 }
1671 /* }}} end dom_node_get_feature */
1672 
1673 /* {{{ proto mixed dom_node_set_user_data(string key, mixed data, userdatahandler handler);
1674 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-setUserData
1675 Since: DOM Level 3
1676 */
PHP_FUNCTION(dom_node_set_user_data)1677 PHP_FUNCTION(dom_node_set_user_data)
1678 {
1679  DOM_NOT_IMPLEMENTED();
1680 }
1681 /* }}} end dom_node_set_user_data */
1682 
1683 /* {{{ proto mixed dom_node_get_user_data(string key);
1684 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getUserData
1685 Since: DOM Level 3
1686 */
PHP_FUNCTION(dom_node_get_user_data)1687 PHP_FUNCTION(dom_node_get_user_data)
1688 {
1689  DOM_NOT_IMPLEMENTED();
1690 }
1691 /* }}} end dom_node_get_user_data */
1692 
dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS,int mode)1693 static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
1694 {
1695 	zval *id;
1696 	zval *xpath_array=NULL, *ns_prefixes=NULL;
1697 	xmlNodePtr nodep;
1698 	xmlDocPtr docp;
1699 	xmlNodeSetPtr nodeset = NULL;
1700 	dom_object *intern;
1701 	zend_bool exclusive=0, with_comments=0;
1702 	xmlChar **inclusive_ns_prefixes = NULL;
1703 	char *file = NULL;
1704 	int ret = -1;
1705 	size_t file_len = 0;
1706 	xmlOutputBufferPtr buf;
1707 	xmlXPathContextPtr ctxp=NULL;
1708 	xmlXPathObjectPtr xpathobjp=NULL;
1709 
1710 	id = ZEND_THIS;
1711 	if (mode == 0) {
1712 		if (zend_parse_parameters(ZEND_NUM_ARGS(),
1713 			"|bba!a!", &exclusive, &with_comments,
1714 			&xpath_array, &ns_prefixes) == FAILURE) {
1715 			return;
1716 		}
1717 	} else {
1718 		if (zend_parse_parameters(ZEND_NUM_ARGS(),
1719 			"s|bba!a!", &file, &file_len, &exclusive,
1720 			&with_comments, &xpath_array, &ns_prefixes) == FAILURE) {
1721 			return;
1722 		}
1723 	}
1724 
1725 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1726 
1727 	docp = nodep->doc;
1728 
1729 	if (! docp) {
1730 		php_error_docref(NULL, E_WARNING, "Node must be associated with a document");
1731 		RETURN_FALSE;
1732 	}
1733 
1734 	if (xpath_array == NULL) {
1735 		if (nodep->type != XML_DOCUMENT_NODE) {
1736 			ctxp = xmlXPathNewContext(docp);
1737 			ctxp->node = nodep;
1738 			xpathobjp = xmlXPathEvalExpression((xmlChar *) "(.//. | .//@* | .//namespace::*)", ctxp);
1739 			ctxp->node = NULL;
1740 			if (xpathobjp && xpathobjp->type == XPATH_NODESET) {
1741 				nodeset = xpathobjp->nodesetval;
1742 			} else {
1743 				if (xpathobjp) {
1744 					xmlXPathFreeObject(xpathobjp);
1745 				}
1746 				xmlXPathFreeContext(ctxp);
1747 				php_error_docref(NULL, E_WARNING, "XPath query did not return a nodeset.");
1748 				RETURN_FALSE;
1749 			}
1750 		}
1751 	} else {
1752 		/*xpath query from xpath_array */
1753 		HashTable *ht = Z_ARRVAL_P(xpath_array);
1754 		zval *tmp;
1755 		char *xquery;
1756 
1757 		tmp = zend_hash_str_find(ht, "query", sizeof("query")-1);
1758 		if (tmp && Z_TYPE_P(tmp) == IS_STRING) {
1759 			xquery = Z_STRVAL_P(tmp);
1760 		} else {
1761 			php_error_docref(NULL, E_WARNING, "'query' missing from xpath array or is not a string");
1762 			RETURN_FALSE;
1763 		}
1764 
1765 		ctxp = xmlXPathNewContext(docp);
1766 		ctxp->node = nodep;
1767 
1768 		tmp = zend_hash_str_find(ht, "namespaces", sizeof("namespaces")-1);
1769 		if (tmp && Z_TYPE_P(tmp) == IS_ARRAY) {
1770 			zval *tmpns;
1771 			zend_string *prefix;
1772 
1773 			ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(tmp), prefix, tmpns) {
1774 				if (Z_TYPE_P(tmpns) == IS_STRING) {
1775 					if (prefix) {
1776 						xmlXPathRegisterNs(ctxp, (xmlChar *) ZSTR_VAL(prefix), (xmlChar *) Z_STRVAL_P(tmpns));
1777 					}
1778 				}
1779 			} ZEND_HASH_FOREACH_END();
1780 		}
1781 
1782 		xpathobjp = xmlXPathEvalExpression((xmlChar *) xquery, ctxp);
1783 		ctxp->node = NULL;
1784 		if (xpathobjp && xpathobjp->type == XPATH_NODESET) {
1785 			nodeset = xpathobjp->nodesetval;
1786 		} else {
1787 			if (xpathobjp) {
1788 				xmlXPathFreeObject(xpathobjp);
1789 			}
1790 			xmlXPathFreeContext(ctxp);
1791 			php_error_docref(NULL, E_WARNING, "XPath query did not return a nodeset.");
1792 			RETURN_FALSE;
1793 		}
1794 	}
1795 
1796 	if (ns_prefixes != NULL) {
1797 		if (exclusive) {
1798 			zval *tmpns;
1799 			int nscount = 0;
1800 
1801 			inclusive_ns_prefixes = safe_emalloc(zend_hash_num_elements(Z_ARRVAL_P(ns_prefixes)) + 1,
1802 				sizeof(xmlChar *), 0);
1803 			ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(ns_prefixes), tmpns) {
1804 				if (Z_TYPE_P(tmpns) == IS_STRING) {
1805 					inclusive_ns_prefixes[nscount++] = (xmlChar *) Z_STRVAL_P(tmpns);
1806 				}
1807 			} ZEND_HASH_FOREACH_END();
1808 			inclusive_ns_prefixes[nscount] = NULL;
1809 		} else {
1810 			php_error_docref(NULL, E_NOTICE,
1811 				"Inclusive namespace prefixes only allowed in exclusive mode.");
1812 		}
1813 	}
1814 
1815 	if (mode == 1) {
1816 		buf = xmlOutputBufferCreateFilename(file, NULL, 0);
1817 	} else {
1818 		buf = xmlAllocOutputBuffer(NULL);
1819 	}
1820 
1821     if (buf != NULL) {
1822 		ret = xmlC14NDocSaveTo(docp, nodeset, exclusive, inclusive_ns_prefixes,
1823 			with_comments, buf);
1824 	}
1825 
1826 	if (inclusive_ns_prefixes != NULL) {
1827 		efree(inclusive_ns_prefixes);
1828 	}
1829 	if (xpathobjp != NULL) {
1830 		xmlXPathFreeObject(xpathobjp);
1831 	}
1832 	if (ctxp != NULL) {
1833 		xmlXPathFreeContext(ctxp);
1834 	}
1835 
1836     if (buf == NULL || ret < 0) {
1837         RETVAL_FALSE;
1838     } else {
1839 		if (mode == 0) {
1840 #ifdef LIBXML2_NEW_BUFFER
1841 			ret = xmlOutputBufferGetSize(buf);
1842 #else
1843 			ret = buf->buffer->use;
1844 #endif
1845 			if (ret > 0) {
1846 #ifdef LIBXML2_NEW_BUFFER
1847 				RETVAL_STRINGL((char *) xmlOutputBufferGetContent(buf), ret);
1848 #else
1849 				RETVAL_STRINGL((char *) buf->buffer->content, ret);
1850 #endif
1851 			} else {
1852 				RETVAL_EMPTY_STRING();
1853 			}
1854 		}
1855     }
1856 
1857 	if (buf) {
1858 		int bytes;
1859 
1860 		bytes = xmlOutputBufferClose(buf);
1861 		if (mode == 1 && (ret >= 0)) {
1862 			RETURN_LONG(bytes);
1863 		}
1864 	}
1865 }
1866 /* }}} */
1867 
1868 /* {{{ proto string DOMNode::C14N([bool exclusive [, bool with_comments [, array xpath [, array ns_prefixes]]]])
1869    Canonicalize nodes to a string */
PHP_METHOD(domnode,C14N)1870 PHP_METHOD(domnode, C14N)
1871 {
1872 	dom_canonicalization(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1873 }
1874 /* }}} */
1875 
1876 /* {{{ proto int DOMNode::C14NFile(string uri [, bool exclusive [, bool with_comments [, array xpath [, array ns_prefixes]]]])
1877    Canonicalize nodes to a file */
PHP_METHOD(domnode,C14NFile)1878 PHP_METHOD(domnode, C14NFile)
1879 {
1880 	dom_canonicalization(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1881 }
1882 /* }}} */
1883 
1884 /* {{{ proto int DOMNode::getNodePath()
1885    Gets an xpath for a node */
PHP_METHOD(domnode,getNodePath)1886 PHP_METHOD(domnode, getNodePath)
1887 {
1888 	zval *id;
1889 	xmlNode *nodep;
1890 	dom_object *intern;
1891 	char *value;
1892 
1893 	DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern);
1894 
1895 	value = (char *) xmlGetNodePath(nodep);
1896 	if (value == NULL) {
1897 		RETURN_NULL();
1898 	} else {
1899 		RETVAL_STRING(value);
1900 		xmlFree(value);
1901 	}
1902 }
1903 /* }}} */
1904 
1905 /* {{{ proto int DOMNode::getLineNo()
1906    Gets line number for a node */
PHP_METHOD(domnode,getLineNo)1907 PHP_METHOD(domnode, getLineNo)
1908 {
1909 	zval *id;
1910 	xmlNode *nodep;
1911 	dom_object *intern;
1912 
1913 	if (zend_parse_parameters_none() == FAILURE) {
1914 		return;
1915 	}
1916 
1917 	DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern);
1918 
1919 	RETURN_LONG(xmlGetLineNo(nodep));
1920 }
1921 /* }}} */
1922 
1923 #endif
1924