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