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