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