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