xref: /PHP-8.1/ext/dom/element.c (revision 243fa9c1)
1 /*
2    +----------------------------------------------------------------------+
3    | Copyright (c) The PHP Group                                          |
4    +----------------------------------------------------------------------+
5    | This source file is subject to version 3.01 of the PHP license,      |
6    | that is bundled with this package in the file LICENSE, and is        |
7    | available through the world-wide-web at the following url:           |
8    | https://www.php.net/license/3_01.txt                                 |
9    | If you did not receive a copy of the PHP license and are unable to   |
10    | obtain it through the world-wide-web, please send a note to          |
11    | license@php.net so we can mail you a copy immediately.               |
12    +----------------------------------------------------------------------+
13    | Authors: Christian Stocker <chregu@php.net>                          |
14    |          Rob Richards <rrichards@php.net>                            |
15    +----------------------------------------------------------------------+
16 */
17 
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 
22 #include "php.h"
23 #if defined(HAVE_LIBXML) && defined(HAVE_DOM)
24 #include "php_dom.h"
25 
26 /*
27 * class DOMElement extends DOMNode
28 *
29 * URL: https://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-745549614
30 * Since:
31 */
32 
33 /* {{{ */
PHP_METHOD(DOMElement,__construct)34 PHP_METHOD(DOMElement, __construct)
35 {
36 	xmlNodePtr nodep = NULL, oldnode = NULL;
37 	dom_object *intern;
38 	char *name, *value = NULL, *uri = NULL;
39 	char *localname = NULL, *prefix = NULL;
40 	int errorcode = 0;
41 	size_t name_len, value_len = 0, uri_len = 0;
42 	int name_valid;
43 	xmlNsPtr nsptr = NULL;
44 
45 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!s", &name, &name_len, &value, &value_len, &uri, &uri_len) == FAILURE) {
46 		RETURN_THROWS();
47 	}
48 
49 	name_valid = xmlValidateName((xmlChar *) name, 0);
50 	if (name_valid != 0) {
51 		php_dom_throw_error(INVALID_CHARACTER_ERR, 1);
52 		RETURN_THROWS();
53 	}
54 
55 	/* Namespace logic is separate and only when uri passed in to insure no BC breakage */
56 	if (uri_len > 0) {
57 		errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
58 		if (errorcode == 0) {
59 			nodep = xmlNewNode (NULL, (xmlChar *)localname);
60 			if (nodep != NULL && uri != NULL) {
61 				nsptr = dom_get_ns(nodep, uri, &errorcode, prefix);
62 				xmlSetNs(nodep, nsptr);
63 			}
64 		}
65 		xmlFree(localname);
66 		if (prefix != NULL) {
67 			xmlFree(prefix);
68 		}
69 		if (errorcode != 0) {
70 			if (nodep != NULL) {
71 				xmlFreeNode(nodep);
72 			}
73 			php_dom_throw_error(errorcode, 1);
74 			RETURN_THROWS();
75 		}
76 	} else {
77 	    /* If you don't pass a namespace uri, then you can't set a prefix */
78 	    localname = (char *) xmlSplitQName2((xmlChar *) name, (xmlChar **) &prefix);
79 	    if (prefix != NULL) {
80 			xmlFree(localname);
81 			xmlFree(prefix);
82 	        php_dom_throw_error(NAMESPACE_ERR, 1);
83 	        RETURN_THROWS();
84 	    }
85 		nodep = xmlNewNode(NULL, (xmlChar *) name);
86 	}
87 
88 	if (!nodep) {
89 		php_dom_throw_error(INVALID_STATE_ERR, 1);
90 		RETURN_THROWS();
91 	}
92 
93 	if (value_len > 0) {
94 		xmlNodeSetContentLen(nodep, (xmlChar *) value, value_len);
95 	}
96 
97 	intern = Z_DOMOBJ_P(ZEND_THIS);
98 	oldnode = dom_object_get_node(intern);
99 	if (oldnode != NULL) {
100 		php_libxml_node_decrement_resource((php_libxml_node_object *)intern);
101 	}
102 	php_libxml_increment_node_ptr((php_libxml_node_object *)intern, nodep, (void *)intern);
103 }
104 /* }}} end DOMElement::__construct */
105 
106 /* {{{ tagName	string
107 readonly=yes
108 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-104682815
109 Since:
110 */
dom_element_tag_name_read(dom_object * obj,zval * retval)111 int dom_element_tag_name_read(dom_object *obj, zval *retval)
112 {
113 	xmlNodePtr nodep;
114 	xmlNsPtr ns;
115 	xmlChar *qname;
116 
117 	nodep = dom_object_get_node(obj);
118 
119 	if (nodep == NULL) {
120 		php_dom_throw_error(INVALID_STATE_ERR, 1);
121 		return FAILURE;
122 	}
123 
124 	ns = nodep->ns;
125 	if (ns != NULL && ns->prefix) {
126 		qname = xmlStrdup(ns->prefix);
127 		qname = xmlStrcat(qname, (xmlChar *)":");
128 		qname = xmlStrcat(qname, nodep->name);
129 		ZVAL_STRING(retval, (char *)qname);
130 		xmlFree(qname);
131 	} else {
132 		ZVAL_STRING(retval, (char *) nodep->name);
133 	}
134 
135 	return SUCCESS;
136 }
137 
138 /* }}} */
139 
140 /* {{{ schemaTypeInfo	typeinfo
141 readonly=yes
142 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Element-schemaTypeInfo
143 Since: DOM Level 3
144 */
dom_element_schema_type_info_read(dom_object * obj,zval * retval)145 int dom_element_schema_type_info_read(dom_object *obj, zval *retval)
146 {
147 	ZVAL_NULL(retval);
148 	return SUCCESS;
149 }
150 
151 /* }}} */
152 
153 /* Note: the object returned is not necessarily a node, but can be an attribute or a namespace declaration. */
dom_get_dom1_attribute(xmlNodePtr elem,xmlChar * name)154 static xmlNodePtr dom_get_dom1_attribute(xmlNodePtr elem, xmlChar *name) /* {{{ */
155 {
156 	int len;
157 	const xmlChar *nqname;
158 
159 	nqname = xmlSplitQName3(name, &len);
160 	if (nqname != NULL) {
161 		xmlNsPtr ns;
162 		xmlChar *prefix = xmlStrndup(name, len);
163 		if (prefix && xmlStrEqual(prefix, (xmlChar *)"xmlns")) {
164 			ns = elem->nsDef;
165 			while (ns) {
166 				if (xmlStrEqual(ns->prefix, nqname)) {
167 					break;
168 				}
169 				ns = ns->next;
170 			}
171 			xmlFree(prefix);
172 			return (xmlNodePtr)ns;
173 		}
174 		ns = xmlSearchNs(elem->doc, elem, prefix);
175 		if (prefix != NULL) {
176 			xmlFree(prefix);
177 		}
178 		if (ns != NULL) {
179 			return (xmlNodePtr)xmlHasNsProp(elem, nqname, ns->href);
180 		}
181 	} else {
182 		if (xmlStrEqual(name, (xmlChar *)"xmlns")) {
183 			xmlNsPtr nsPtr = elem->nsDef;
184 			while (nsPtr) {
185 				if (nsPtr->prefix == NULL) {
186 					return (xmlNodePtr)nsPtr;
187 				}
188 				nsPtr = nsPtr->next;
189 			}
190 			return NULL;
191 		}
192 	}
193 	return (xmlNodePtr)xmlHasNsProp(elem, name, NULL);
194 }
195 /* }}} */
196 
197 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-666EE0F9
198 Since:
199 */
PHP_METHOD(DOMElement,getAttribute)200 PHP_METHOD(DOMElement, getAttribute)
201 {
202 	zval *id;
203 	xmlNode *nodep;
204 	char *name;
205 	xmlChar *value = NULL;
206 	dom_object *intern;
207 	xmlNodePtr attr;
208 	size_t name_len;
209 
210 	id = ZEND_THIS;
211 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
212 		RETURN_THROWS();
213 	}
214 
215 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
216 
217 	attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
218 	if (attr) {
219 		switch (attr->type) {
220 			case XML_ATTRIBUTE_NODE:
221 				value = xmlNodeListGetString(attr->doc, attr->children, 1);
222 				break;
223 			case XML_NAMESPACE_DECL:
224 				value = xmlStrdup(((xmlNsPtr)attr)->href);
225 				break;
226 			default:
227 				value = xmlStrdup(((xmlAttributePtr)attr)->defaultValue);
228 		}
229 	}
230 
231 	if (value == NULL) {
232 		RETURN_EMPTY_STRING();
233 	} else {
234 		RETVAL_STRING((char *)value);
235 		xmlFree(value);
236 	}
237 }
238 /* }}} end dom_element_get_attribute */
239 
240 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68F082
241 Since:
242 */
PHP_METHOD(DOMElement,setAttribute)243 PHP_METHOD(DOMElement, setAttribute)
244 {
245 	zval *id;
246 	xmlNode *nodep;
247 	xmlNodePtr attr = NULL;
248 	int ret, name_valid;
249 	size_t name_len, value_len;
250 	dom_object *intern;
251 	char *name, *value;
252 
253 	id = ZEND_THIS;
254 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &name, &name_len, &value, &value_len) == FAILURE) {
255 		RETURN_THROWS();
256 	}
257 
258 	if (name_len == 0) {
259 		zend_argument_value_error(1, "cannot be empty");
260 		RETURN_THROWS();
261 	}
262 
263 	name_valid = xmlValidateName((xmlChar *) name, 0);
264 	if (name_valid != 0) {
265 		php_dom_throw_error(INVALID_CHARACTER_ERR, 1);
266 		RETURN_THROWS();
267 	}
268 
269 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
270 
271 	if (dom_node_is_read_only(nodep) == SUCCESS) {
272 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
273 		RETURN_FALSE;
274 	}
275 
276 	attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
277 	if (attr != NULL) {
278 		switch (attr->type) {
279 			case XML_ATTRIBUTE_NODE:
280 				node_list_unlink(attr->children);
281 				break;
282 			case XML_NAMESPACE_DECL:
283 				RETURN_FALSE;
284 			default:
285 				break;
286 		}
287 
288 	}
289 
290 	if (xmlStrEqual((xmlChar *)name, (xmlChar *)"xmlns")) {
291 		if (xmlNewNs(nodep, (xmlChar *)value, NULL)) {
292 			RETURN_TRUE;
293 		}
294 	} else {
295 		attr = (xmlNodePtr)xmlSetProp(nodep, (xmlChar *) name, (xmlChar *)value);
296 	}
297 	if (!attr) {
298 		zend_argument_value_error(1, "must be a valid XML attribute");
299 		RETURN_THROWS();
300 	}
301 
302 	DOM_RET_OBJ(attr, &ret, intern);
303 
304 }
305 /* }}} end dom_element_set_attribute */
306 
307 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6D6AC0F9
308 Since:
309 */
PHP_METHOD(DOMElement,removeAttribute)310 PHP_METHOD(DOMElement, removeAttribute)
311 {
312 	zval *id;
313 	xmlNodePtr nodep, attrp;
314 	dom_object *intern;
315 	size_t name_len;
316 	char *name;
317 
318 	id = ZEND_THIS;
319 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
320 		RETURN_THROWS();
321 	}
322 
323 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
324 
325 	if (dom_node_is_read_only(nodep) == SUCCESS) {
326 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
327 		RETURN_FALSE;
328 	}
329 
330 	attrp = dom_get_dom1_attribute(nodep, (xmlChar *)name);
331 	if (attrp == NULL) {
332 		RETURN_FALSE;
333 	}
334 
335 	switch (attrp->type) {
336 		case XML_ATTRIBUTE_NODE:
337 			if (php_dom_object_get_data(attrp) == NULL) {
338 			node_list_unlink(attrp->children);
339 				xmlUnlinkNode(attrp);
340 				xmlFreeProp((xmlAttrPtr)attrp);
341 		} else {
342 				xmlUnlinkNode(attrp);
343 		}
344 			break;
345 		case XML_NAMESPACE_DECL:
346 			RETURN_FALSE;
347 		default:
348 			break;
349 	}
350 
351 	RETURN_TRUE;
352 }
353 /* }}} end dom_element_remove_attribute */
354 
355 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-217A91B8
356 Since:
357 */
PHP_METHOD(DOMElement,getAttributeNode)358 PHP_METHOD(DOMElement, getAttributeNode)
359 {
360 	zval *id;
361 	xmlNodePtr nodep, attrp;
362 	size_t name_len;
363 	int ret;
364 	dom_object *intern;
365 	char *name;
366 
367 	id = ZEND_THIS;
368 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
369 		RETURN_THROWS();
370 	}
371 
372 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
373 
374 	attrp = dom_get_dom1_attribute(nodep, (xmlChar *)name);
375 	if (attrp == NULL) {
376 		RETURN_FALSE;
377 	}
378 
379 	if (attrp->type == XML_NAMESPACE_DECL) {
380 		xmlNsPtr original = (xmlNsPtr) attrp;
381 		/* Keep parent alive, because we're a fake child. */
382 		GC_ADDREF(&intern->std);
383 		(void) php_dom_create_fake_namespace_decl(nodep, original, return_value, intern);
384 	} else {
385 		DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
386 	}
387 }
388 /* }}} end dom_element_get_attribute_node */
389 
390 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-887236154
391 Since:
392 */
PHP_METHOD(DOMElement,setAttributeNode)393 PHP_METHOD(DOMElement, setAttributeNode)
394 {
395 	zval *id, *node;
396 	xmlNode *nodep;
397 	xmlAttr *attrp, *existattrp = NULL;
398 	dom_object *intern, *attrobj, *oldobj;
399 	int ret;
400 
401 	id = ZEND_THIS;
402 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_attr_class_entry) == FAILURE) {
403 		RETURN_THROWS();
404 	}
405 
406 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
407 
408 	if (dom_node_is_read_only(nodep) == SUCCESS) {
409 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
410 		RETURN_FALSE;
411 	}
412 
413 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
414 
415 	if (attrp->type != XML_ATTRIBUTE_NODE) {
416 		zend_argument_value_error(1, "must have the node attribute");
417 		RETURN_THROWS();
418 	}
419 
420 	if (!(attrp->doc == NULL || attrp->doc == nodep->doc)) {
421 		php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
422 		RETURN_FALSE;
423 	}
424 
425 	existattrp = xmlHasProp(nodep, attrp->name);
426 	if (existattrp != NULL && existattrp->type != XML_ATTRIBUTE_DECL) {
427 		if ((oldobj = php_dom_object_get_data((xmlNodePtr) existattrp)) != NULL &&
428 			((php_libxml_node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp)
429 		{
430 			RETURN_NULL();
431 		}
432 		xmlUnlinkNode((xmlNodePtr) existattrp);
433 	}
434 
435 	if (attrp->parent != NULL) {
436 		xmlUnlinkNode((xmlNodePtr) attrp);
437 	}
438 
439 	if (attrp->doc == NULL && nodep->doc != NULL) {
440 		attrobj->document = intern->document;
441 		php_libxml_increment_doc_ref((php_libxml_node_object *)attrobj, NULL);
442 	}
443 
444 	xmlAddChild(nodep, (xmlNodePtr) attrp);
445 
446 	/* Returns old property if removed otherwise NULL */
447 	if (existattrp != NULL) {
448 		DOM_RET_OBJ((xmlNodePtr) existattrp, &ret, intern);
449 	} else {
450 		RETVAL_NULL();
451 	}
452 
453 }
454 /* }}} end dom_element_set_attribute_node */
455 
456 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-D589198
457 Since:
458 */
PHP_METHOD(DOMElement,removeAttributeNode)459 PHP_METHOD(DOMElement, removeAttributeNode)
460 {
461 	zval *id, *node;
462 	xmlNode *nodep;
463 	xmlAttr *attrp;
464 	dom_object *intern, *attrobj;
465 	int ret;
466 
467 	id = ZEND_THIS;
468 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_attr_class_entry) == FAILURE) {
469 		RETURN_THROWS();
470 	}
471 
472 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
473 
474 	if (dom_node_is_read_only(nodep) == SUCCESS) {
475 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
476 		RETURN_FALSE;
477 	}
478 
479 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
480 
481 	if (attrp->type != XML_ATTRIBUTE_NODE || attrp->parent != nodep) {
482 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
483 		RETURN_FALSE;
484 	}
485 
486 	xmlUnlinkNode((xmlNodePtr) attrp);
487 
488 	DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
489 
490 }
491 /* }}} end dom_element_remove_attribute_node */
492 
493 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1938918D
494 Since:
495 */
PHP_METHOD(DOMElement,getElementsByTagName)496 PHP_METHOD(DOMElement, getElementsByTagName)
497 {
498 	zval *id;
499 	xmlNodePtr elemp;
500 	size_t name_len;
501 	dom_object *intern, *namednode;
502 	char *name;
503 	xmlChar *local;
504 
505 	id = ZEND_THIS;
506 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
507 		RETURN_THROWS();
508 	}
509 
510 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
511 
512 	php_dom_create_iterator(return_value, DOM_NODELIST);
513 	namednode = Z_DOMOBJ_P(return_value);
514 	local = xmlCharStrndup(name, name_len);
515 	dom_namednode_iter(intern, 0, namednode, NULL, local, NULL);
516 }
517 /* }}} end dom_element_get_elements_by_tag_name */
518 
519 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElGetAttrNS
520 Since: DOM Level 2
521 */
PHP_METHOD(DOMElement,getAttributeNS)522 PHP_METHOD(DOMElement, getAttributeNS)
523 {
524 	zval *id;
525 	xmlNodePtr elemp;
526 	xmlNsPtr nsptr;
527 	dom_object *intern;
528 	size_t uri_len = 0, name_len = 0;
529 	char *uri, *name;
530 	xmlChar *strattr;
531 
532 	id = ZEND_THIS;
533 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
534 		RETURN_THROWS();
535 	}
536 
537 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
538 
539 	strattr = xmlGetNsProp(elemp, (xmlChar *) name, (xmlChar *) uri);
540 
541 	if (strattr != NULL) {
542 		RETVAL_STRING((char *)strattr);
543 		xmlFree(strattr);
544 	} else {
545 		if (xmlStrEqual((xmlChar *) uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
546 			nsptr = dom_get_nsdecl(elemp, (xmlChar *)name);
547 			if (nsptr != NULL) {
548 				RETVAL_STRING((char *) nsptr->href);
549 			} else {
550 				RETVAL_EMPTY_STRING();
551 			}
552 		} else {
553 			RETVAL_EMPTY_STRING();
554 		}
555 	}
556 
557 }
558 /* }}} end dom_element_get_attribute_ns */
559 
_dom_new_reconNs(xmlDocPtr doc,xmlNodePtr tree,xmlNsPtr ns)560 static xmlNsPtr _dom_new_reconNs(xmlDocPtr doc, xmlNodePtr tree, xmlNsPtr ns) /* {{{ */
561 {
562 	xmlNsPtr def;
563 	xmlChar prefix[50];
564 	int counter = 1;
565 
566 	if ((tree == NULL) || (ns == NULL) || (ns->type != XML_NAMESPACE_DECL)) {
567 		return NULL;
568 	}
569 
570 	/* Code taken from libxml2 (2.6.20) xmlNewReconciliedNs
571 	 *
572 	 * Find a close prefix which is not already in use.
573 	 * Let's strip namespace prefixes longer than 20 chars !
574 	 */
575 	if (ns->prefix == NULL)
576 		snprintf((char *) prefix, sizeof(prefix), "default");
577 	else
578 		snprintf((char *) prefix, sizeof(prefix), "%.20s", (char *)ns->prefix);
579 
580 	def = xmlSearchNs(doc, tree, prefix);
581 	while (def != NULL) {
582 		if (counter > 1000) return(NULL);
583 		if (ns->prefix == NULL)
584 			snprintf((char *) prefix, sizeof(prefix), "default%d", counter++);
585 		else
586 			snprintf((char *) prefix, sizeof(prefix), "%.20s%d",
587 			(char *)ns->prefix, counter++);
588 		def = xmlSearchNs(doc, tree, prefix);
589 	}
590 
591 	/*
592 	 * OK, now we are ready to create a new one.
593 	 */
594 	def = xmlNewNs(tree, ns->href, prefix);
595 	return(def);
596 }
597 /* }}} */
598 
599 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetAttrNS
600 Since: DOM Level 2
601 */
PHP_METHOD(DOMElement,setAttributeNS)602 PHP_METHOD(DOMElement, setAttributeNS)
603 {
604 	zval *id;
605 	xmlNodePtr elemp, nodep = NULL;
606 	xmlNsPtr nsptr;
607 	xmlAttr *attr;
608 	size_t uri_len = 0, name_len = 0, value_len = 0;
609 	char *uri, *name, *value;
610 	char *localname = NULL, *prefix = NULL;
611 	dom_object *intern;
612 	int errorcode = 0, stricterror, is_xmlns = 0, name_valid;
613 
614 	id = ZEND_THIS;
615 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!ss", &uri, &uri_len, &name, &name_len, &value, &value_len) == FAILURE) {
616 		RETURN_THROWS();
617 	}
618 
619 	if (name_len == 0) {
620 		zend_argument_value_error(2, "cannot be empty");
621 		RETURN_THROWS();
622 	}
623 
624 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
625 
626 	stricterror = dom_get_strict_error(intern->document);
627 
628 	if (dom_node_is_read_only(elemp) == SUCCESS) {
629 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror);
630 		RETURN_NULL();
631 	}
632 
633 	errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len);
634 
635 	if (errorcode == 0) {
636 		if (uri_len > 0) {
637 			nodep = (xmlNodePtr) xmlHasNsProp(elemp, (xmlChar *) localname, (xmlChar *) uri);
638 			if (nodep != NULL && nodep->type != XML_ATTRIBUTE_DECL) {
639 				node_list_unlink(nodep->children);
640 			}
641 
642 			if ((xmlStrEqual((xmlChar *) prefix, (xmlChar *)"xmlns") ||
643 				(prefix == NULL && xmlStrEqual((xmlChar *) localname, (xmlChar *)"xmlns"))) &&
644 				xmlStrEqual((xmlChar *) uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
645 				is_xmlns = 1;
646 				if (prefix == NULL) {
647 					nsptr = dom_get_nsdecl(elemp, NULL);
648 				} else {
649 					nsptr = dom_get_nsdecl(elemp, (xmlChar *)localname);
650 				}
651 			} else {
652 				nsptr = xmlSearchNsByHref(elemp->doc, elemp, (xmlChar *)uri);
653 				if (nsptr && nsptr->prefix == NULL) {
654 					xmlNsPtr tmpnsptr;
655 
656 					tmpnsptr = nsptr->next;
657 					while (tmpnsptr) {
658 						if ((tmpnsptr->prefix != NULL) && (tmpnsptr->href != NULL) &&
659 							(xmlStrEqual(tmpnsptr->href, (xmlChar *) uri))) {
660 							nsptr = tmpnsptr;
661 							break;
662 						}
663 						tmpnsptr = tmpnsptr->next;
664 					}
665 					if (tmpnsptr == NULL) {
666 						nsptr = _dom_new_reconNs(elemp->doc, elemp, nsptr);
667 					}
668 				}
669 			}
670 
671 			if (nsptr == NULL) {
672 				if (prefix == NULL) {
673 					if (is_xmlns == 1) {
674 						xmlNewNs(elemp, (xmlChar *)value, NULL);
675 						xmlReconciliateNs(elemp->doc, elemp);
676 					} else {
677 						errorcode = NAMESPACE_ERR;
678 					}
679 				} else {
680 					if (is_xmlns == 1) {
681 						xmlNewNs(elemp, (xmlChar *)value, (xmlChar *)localname);
682 					} else {
683 						nsptr = dom_get_ns(elemp, uri, &errorcode, prefix);
684 					}
685 					xmlReconciliateNs(elemp->doc, elemp);
686 				}
687 			} else {
688 				if (is_xmlns == 1) {
689 					if (nsptr->href) {
690 						xmlFree((xmlChar *) nsptr->href);
691 					}
692 					nsptr->href = xmlStrdup((xmlChar *)value);
693 				}
694 			}
695 
696 			if (errorcode == 0 && is_xmlns == 0) {
697 				xmlSetNsProp(elemp, nsptr, (xmlChar *)localname, (xmlChar *)value);
698 			}
699 		} else {
700 			name_valid = xmlValidateName((xmlChar *) localname, 0);
701 			if (name_valid != 0) {
702 				errorcode = INVALID_CHARACTER_ERR;
703 				stricterror = 1;
704 			} else {
705 				attr = xmlHasProp(elemp, (xmlChar *)localname);
706 				if (attr != NULL && attr->type != XML_ATTRIBUTE_DECL) {
707 					node_list_unlink(attr->children);
708 				}
709 				xmlSetProp(elemp, (xmlChar *)localname, (xmlChar *)value);
710 			}
711 		}
712 	}
713 
714 	xmlFree(localname);
715 	if (prefix != NULL) {
716 		xmlFree(prefix);
717 	}
718 
719 	if (errorcode != 0) {
720 		php_dom_throw_error(errorcode, stricterror);
721 	}
722 
723 	RETURN_NULL();
724 }
725 /* }}} end dom_element_set_attribute_ns */
726 
dom_remove_eliminated_ns_single_element(xmlNodePtr node,xmlNsPtr eliminatedNs)727 static void dom_remove_eliminated_ns_single_element(xmlNodePtr node, xmlNsPtr eliminatedNs)
728 {
729 	ZEND_ASSERT(node->type == XML_ELEMENT_NODE);
730 	if (node->ns == eliminatedNs) {
731 		node->ns = NULL;
732 	}
733 
734 	for (xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) {
735 		if (attr->ns == eliminatedNs) {
736 			attr->ns = NULL;
737 		}
738 	}
739 }
740 
dom_remove_eliminated_ns(xmlNodePtr node,xmlNsPtr eliminatedNs)741 static void dom_remove_eliminated_ns(xmlNodePtr node, xmlNsPtr eliminatedNs)
742 {
743 	dom_remove_eliminated_ns_single_element(node, eliminatedNs);
744 
745 	xmlNodePtr base = node;
746 	node = node->children;
747 	while (node != NULL) {
748 		ZEND_ASSERT(node != base);
749 
750 		if (node->type == XML_ELEMENT_NODE) {
751 			dom_remove_eliminated_ns_single_element(node, eliminatedNs);
752 
753 			if (node->children) {
754 				node = node->children;
755 				continue;
756 			}
757 		}
758 
759 		if (node->next) {
760 			node = node->next;
761 		} else {
762 			/* Go upwards, until we find a parent node with a next sibling, or until we hit the base. */
763 			do {
764 				node = node->parent;
765 				if (node == base) {
766 					return;
767 				}
768 			} while (node->next == NULL);
769 			node = node->next;
770 		}
771 	}
772 }
773 
dom_eliminate_ns(xmlNodePtr nodep,xmlNsPtr nsptr)774 static void dom_eliminate_ns(xmlNodePtr nodep, xmlNsPtr nsptr)
775 {
776 	if (nsptr->href != NULL) {
777 		xmlFree((char *) nsptr->href);
778 		nsptr->href = NULL;
779 	}
780 	if (nsptr->prefix != NULL) {
781 		xmlFree((char *) nsptr->prefix);
782 		nsptr->prefix = NULL;
783 	}
784 
785 	/* Remove it from the list and move it to the old ns list */
786 	xmlNsPtr current_ns = nodep->nsDef;
787 	if (current_ns == nsptr) {
788 		nodep->nsDef = nsptr->next;
789 	} else {
790 		do {
791 			if (current_ns->next == nsptr) {
792 				current_ns->next = nsptr->next;
793 				break;
794 			}
795 			current_ns = current_ns->next;
796 		} while (current_ns != NULL);
797 	}
798 	nsptr->next = NULL;
799 	dom_set_old_ns(nodep->doc, nsptr);
800 
801 	dom_remove_eliminated_ns(nodep, nsptr);
802 }
803 
804 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElRemAtNS
805 Since: DOM Level 2
806 */
PHP_METHOD(DOMElement,removeAttributeNS)807 PHP_METHOD(DOMElement, removeAttributeNS)
808 {
809 	zval *id;
810 	xmlNode *nodep;
811 	xmlAttr *attrp;
812 	xmlNsPtr nsptr;
813 	dom_object *intern;
814 	size_t name_len, uri_len;
815 	char *name, *uri;
816 
817 	id = ZEND_THIS;
818 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
819 		RETURN_THROWS();
820 	}
821 
822 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
823 
824 	if (dom_node_is_read_only(nodep) == SUCCESS) {
825 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
826 		RETURN_NULL();
827 	}
828 
829 	attrp = xmlHasNsProp(nodep, (xmlChar *)name, (xmlChar *)uri);
830 
831 	nsptr = dom_get_nsdecl(nodep, (xmlChar *)name);
832 	if (nsptr != NULL) {
833 		if (xmlStrEqual((xmlChar *)uri, nsptr->href)) {
834 			dom_eliminate_ns(nodep, nsptr);
835 		} else {
836 			RETURN_NULL();
837 		}
838 	}
839 
840 	if (attrp && attrp->type != XML_ATTRIBUTE_DECL) {
841 		if (php_dom_object_get_data((xmlNodePtr) attrp) == NULL) {
842 			node_list_unlink(attrp->children);
843 			xmlUnlinkNode((xmlNodePtr) attrp);
844 			xmlFreeProp(attrp);
845 		} else {
846 			xmlUnlinkNode((xmlNodePtr) attrp);
847 		}
848 	}
849 
850 	RETURN_NULL();
851 }
852 /* }}} end dom_element_remove_attribute_ns */
853 
854 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElGetAtNodeNS
855 Since: DOM Level 2
856 */
PHP_METHOD(DOMElement,getAttributeNodeNS)857 PHP_METHOD(DOMElement, getAttributeNodeNS)
858 {
859 	zval *id;
860 	xmlNodePtr elemp;
861 	xmlAttrPtr attrp;
862 	dom_object *intern;
863 	size_t uri_len, name_len;
864 	int ret;
865 	char *uri, *name;
866 
867 	id = ZEND_THIS;
868 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
869 		RETURN_THROWS();
870 	}
871 
872 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
873 
874 	attrp = xmlHasNsProp(elemp, (xmlChar *)name, (xmlChar *)uri);
875 
876 	if (attrp == NULL) {
877 		if (xmlStrEqual((xmlChar *) uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
878 			xmlNsPtr nsptr;
879 			nsptr = dom_get_nsdecl(elemp, (xmlChar *)name);
880 			if (nsptr != NULL) {
881 				/* Keep parent alive, because we're a fake child. */
882 				GC_ADDREF(&intern->std);
883 				(void) php_dom_create_fake_namespace_decl(elemp, nsptr, return_value, intern);
884 			} else {
885 				RETURN_NULL();
886 			}
887 		} else {
888 		   RETURN_NULL();
889 		}
890 	} else {
891 		DOM_RET_OBJ((xmlNodePtr) attrp, &ret, intern);
892 	}
893 
894 }
895 /* }}} end dom_element_get_attribute_node_ns */
896 
897 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetAtNodeNS
898 Since: DOM Level 2
899 */
PHP_METHOD(DOMElement,setAttributeNodeNS)900 PHP_METHOD(DOMElement, setAttributeNodeNS)
901 {
902 	zval *id, *node;
903 	xmlNode *nodep;
904 	xmlNs *nsp;
905 	xmlAttr *attrp, *existattrp = NULL;
906 	dom_object *intern, *attrobj, *oldobj;
907 	int ret;
908 
909 	id = ZEND_THIS;
910 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &node, dom_attr_class_entry) == FAILURE) {
911 		RETURN_THROWS();
912 	}
913 
914 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
915 
916 	if (dom_node_is_read_only(nodep) == SUCCESS) {
917 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
918 		RETURN_FALSE;
919 	}
920 
921 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
922 
923 	/* ZPP Guarantees that a DOMAttr class is given, as it is converted to a xmlAttr
924 	 * to pass to libxml (see http://www.xmlsoft.org/html/libxml-tree.html#xmlAttr)
925 	 * if it is not of type XML_ATTRIBUTE_NODE it indicates a bug somewhere */
926 	ZEND_ASSERT(attrp->type == XML_ATTRIBUTE_NODE);
927 
928 	if (!(attrp->doc == NULL || attrp->doc == nodep->doc)) {
929 		php_dom_throw_error(WRONG_DOCUMENT_ERR, dom_get_strict_error(intern->document));
930 		RETURN_FALSE;
931 	}
932 
933 	nsp = attrp->ns;
934 	if (nsp != NULL) {
935 		existattrp = xmlHasNsProp(nodep, attrp->name, nsp->href);
936 	} else {
937 		existattrp = xmlHasProp(nodep, attrp->name);
938 	}
939 
940 	if (existattrp != NULL && existattrp->type != XML_ATTRIBUTE_DECL) {
941 		if ((oldobj = php_dom_object_get_data((xmlNodePtr) existattrp)) != NULL &&
942 			((php_libxml_node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp)
943 		{
944 			RETURN_NULL();
945 		}
946 		xmlUnlinkNode((xmlNodePtr) existattrp);
947 	}
948 
949 	if (attrp->parent != NULL) {
950 		xmlUnlinkNode((xmlNodePtr) attrp);
951 	}
952 
953 	if (attrp->doc == NULL && nodep->doc != NULL) {
954 		attrobj->document = intern->document;
955 		php_libxml_increment_doc_ref((php_libxml_node_object *)attrobj, NULL);
956 	}
957 
958 	xmlAddChild(nodep, (xmlNodePtr) attrp);
959 
960 	/* Returns old property if removed otherwise NULL */
961 	if (existattrp != NULL) {
962 		DOM_RET_OBJ((xmlNodePtr) existattrp, &ret, intern);
963 	} else {
964 		RETVAL_NULL();
965 	}
966 
967 }
968 /* }}} end dom_element_set_attribute_node_ns */
969 
970 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-A6C90942
971 Since: DOM Level 2
972 */
PHP_METHOD(DOMElement,getElementsByTagNameNS)973 PHP_METHOD(DOMElement, getElementsByTagNameNS)
974 {
975 	zval *id;
976 	xmlNodePtr elemp;
977 	size_t uri_len, name_len;
978 	dom_object *intern, *namednode;
979 	char *uri, *name;
980 	xmlChar *local, *nsuri;
981 
982 	id = ZEND_THIS;
983 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
984 		RETURN_THROWS();
985 	}
986 
987 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
988 
989 	php_dom_create_iterator(return_value, DOM_NODELIST);
990 	namednode = Z_DOMOBJ_P(return_value);
991 	local = xmlCharStrndup(name, name_len);
992 	nsuri = xmlCharStrndup(uri ? uri : "", uri_len);
993 	dom_namednode_iter(intern, 0, namednode, NULL, local, nsuri);
994 
995 }
996 /* }}} end dom_element_get_elements_by_tag_name_ns */
997 
998 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElHasAttr
999 Since: DOM Level 2
1000 */
PHP_METHOD(DOMElement,hasAttribute)1001 PHP_METHOD(DOMElement, hasAttribute)
1002 {
1003 	zval *id;
1004 	xmlNode *nodep;
1005 	dom_object *intern;
1006 	char *name;
1007 	size_t name_len;
1008 	xmlNodePtr attr;
1009 
1010 	id = ZEND_THIS;
1011 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &name, &name_len) == FAILURE) {
1012 		RETURN_THROWS();
1013 	}
1014 
1015 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1016 
1017 	attr = dom_get_dom1_attribute(nodep, (xmlChar *)name);
1018 	if (attr == NULL) {
1019 		RETURN_FALSE;
1020 	} else {
1021 		RETURN_TRUE;
1022 	}
1023 }
1024 /* }}} end dom_element_has_attribute */
1025 
1026 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElHasAttrNS
1027 Since: DOM Level 2
1028 */
PHP_METHOD(DOMElement,hasAttributeNS)1029 PHP_METHOD(DOMElement, hasAttributeNS)
1030 {
1031 	zval *id;
1032 	xmlNodePtr elemp;
1033 	xmlNs *nsp;
1034 	dom_object *intern;
1035 	size_t uri_len, name_len;
1036 	char *uri, *name;
1037 	xmlChar *value;
1038 
1039 	id = ZEND_THIS;
1040 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!s", &uri, &uri_len, &name, &name_len) == FAILURE) {
1041 		RETURN_THROWS();
1042 	}
1043 
1044 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
1045 
1046 	value = xmlGetNsProp(elemp, (xmlChar *)name, (xmlChar *)uri);
1047 
1048 	if (value != NULL) {
1049 		xmlFree(value);
1050 		RETURN_TRUE;
1051 	} else {
1052 		if (xmlStrEqual((xmlChar *)uri, (xmlChar *)DOM_XMLNS_NAMESPACE)) {
1053 			nsp = dom_get_nsdecl(elemp, (xmlChar *)name);
1054 			if (nsp != NULL) {
1055 				RETURN_TRUE;
1056 			}
1057 		}
1058 	}
1059 
1060 	RETURN_FALSE;
1061 }
1062 /* }}} end dom_element_has_attribute_ns */
1063 
php_set_attribute_id(xmlAttrPtr attrp,bool is_id)1064 static void php_set_attribute_id(xmlAttrPtr attrp, bool is_id) /* {{{ */
1065 {
1066 	if (is_id == 1 && attrp->atype != XML_ATTRIBUTE_ID) {
1067 		xmlChar *id_val;
1068 
1069 		id_val = xmlNodeListGetString(attrp->doc, attrp->children, 1);
1070 		if (id_val != NULL) {
1071 			xmlAddID(NULL, attrp->doc, id_val, attrp);
1072 			xmlFree(id_val);
1073 		}
1074 	} else if (is_id == 0 && attrp->atype == XML_ATTRIBUTE_ID) {
1075 		xmlRemoveID(attrp->doc, attrp);
1076 		attrp->atype = 0;
1077 	}
1078 }
1079 /* }}} */
1080 
1081 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttr
1082 Since: DOM Level 3
1083 */
PHP_METHOD(DOMElement,setIdAttribute)1084 PHP_METHOD(DOMElement, setIdAttribute)
1085 {
1086 	zval *id;
1087 	xmlNode *nodep;
1088 	xmlAttrPtr attrp;
1089 	dom_object *intern;
1090 	char *name;
1091 	size_t name_len;
1092 	bool is_id;
1093 
1094 	id = ZEND_THIS;
1095 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "sb", &name, &name_len, &is_id) == FAILURE) {
1096 		RETURN_THROWS();
1097 	}
1098 
1099 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1100 
1101 	if (dom_node_is_read_only(nodep) == SUCCESS) {
1102 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
1103 		RETURN_NULL();
1104 	}
1105 
1106 	attrp = xmlHasNsProp(nodep, (xmlChar *)name, NULL);
1107 	if (attrp == NULL || attrp->type == XML_ATTRIBUTE_DECL) {
1108 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
1109 	} else {
1110 		php_set_attribute_id(attrp, is_id);
1111 	}
1112 
1113 	RETURN_NULL();
1114 }
1115 /* }}} end dom_element_set_id_attribute */
1116 
1117 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttrNS
1118 Since: DOM Level 3
1119 */
PHP_METHOD(DOMElement,setIdAttributeNS)1120 PHP_METHOD(DOMElement, setIdAttributeNS)
1121 {
1122 	zval *id;
1123 	xmlNodePtr elemp;
1124 	xmlAttrPtr attrp;
1125 	dom_object *intern;
1126 	size_t uri_len, name_len;
1127 	char *uri, *name;
1128 	bool is_id;
1129 
1130 	id = ZEND_THIS;
1131 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssb", &uri, &uri_len, &name, &name_len, &is_id) == FAILURE) {
1132 		RETURN_THROWS();
1133 	}
1134 
1135 	DOM_GET_OBJ(elemp, id, xmlNodePtr, intern);
1136 
1137 	if (dom_node_is_read_only(elemp) == SUCCESS) {
1138 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
1139 		RETURN_NULL();
1140 	}
1141 
1142 	attrp = xmlHasNsProp(elemp, (xmlChar *)name, (xmlChar *)uri);
1143 	if (attrp == NULL || attrp->type == XML_ATTRIBUTE_DECL) {
1144 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
1145 	} else {
1146 		php_set_attribute_id(attrp, is_id);
1147 	}
1148 
1149 	RETURN_NULL();
1150 }
1151 /* }}} end dom_element_set_id_attribute_ns */
1152 
1153 /* {{{ URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-ElSetIdAttrNode
1154 Since: DOM Level 3
1155 */
PHP_METHOD(DOMElement,setIdAttributeNode)1156 PHP_METHOD(DOMElement, setIdAttributeNode)
1157 {
1158 	zval *id, *node;
1159 	xmlNode *nodep;
1160 	xmlAttrPtr attrp;
1161 	dom_object *intern, *attrobj;
1162 	bool is_id;
1163 
1164 	id = ZEND_THIS;
1165 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ob", &node, dom_attr_class_entry, &is_id) == FAILURE) {
1166 		RETURN_THROWS();
1167 	}
1168 
1169 	DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1170 
1171 	if (dom_node_is_read_only(nodep) == SUCCESS) {
1172 		php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, dom_get_strict_error(intern->document));
1173 		RETURN_NULL();
1174 	}
1175 
1176 	DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj);
1177 
1178 	if (attrp->parent != nodep) {
1179 		php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document));
1180 	} else {
1181 		php_set_attribute_id(attrp, is_id);
1182 	}
1183 
1184 	RETURN_NULL();
1185 }
1186 /* }}} end dom_element_set_id_attribute_node */
1187 
1188 /* {{{ URL:
1189 Since:
1190 */
PHP_METHOD(DOMElement,remove)1191 PHP_METHOD(DOMElement, remove)
1192 {
1193 	zval *id;
1194 	xmlNodePtr child;
1195 	dom_object *intern;
1196 
1197 	if (zend_parse_parameters_none() == FAILURE) {
1198 		RETURN_THROWS();
1199 	}
1200 
1201 	id = ZEND_THIS;
1202 	DOM_GET_OBJ(child, id, xmlNodePtr, intern);
1203 
1204 	dom_child_node_remove(intern);
1205 }
1206 /* }}} end DOMElement::remove */
1207 
PHP_METHOD(DOMElement,after)1208 PHP_METHOD(DOMElement, after)
1209 {
1210 	int argc = 0;
1211 	zval *args, *id;
1212 	dom_object *intern;
1213 	xmlNode *context;
1214 
1215 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &args, &argc) == FAILURE) {
1216 		RETURN_THROWS();
1217 	}
1218 
1219 	id = ZEND_THIS;
1220 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1221 
1222 	dom_parent_node_after(intern, args, argc);
1223 }
1224 
PHP_METHOD(DOMElement,before)1225 PHP_METHOD(DOMElement, before)
1226 {
1227 	int argc = 0;
1228 	zval *args, *id;
1229 	dom_object *intern;
1230 	xmlNode *context;
1231 
1232 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &args, &argc) == FAILURE) {
1233 		RETURN_THROWS();
1234 	}
1235 
1236 	id = ZEND_THIS;
1237 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1238 
1239 	dom_parent_node_before(intern, args, argc);
1240 }
1241 
1242 /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-append
1243 Since: DOM Living Standard (DOM4)
1244 */
PHP_METHOD(DOMElement,append)1245 PHP_METHOD(DOMElement, append)
1246 {
1247 	int argc = 0;
1248 	zval *args, *id;
1249 	dom_object *intern;
1250 	xmlNode *context;
1251 
1252 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &args, &argc) == FAILURE) {
1253 		RETURN_THROWS();
1254 	}
1255 
1256 	id = ZEND_THIS;
1257 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1258 
1259 	dom_parent_node_append(intern, args, argc);
1260 }
1261 /* }}} end DOMElement::append */
1262 
1263 /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-prepend
1264 Since: DOM Living Standard (DOM4)
1265 */
PHP_METHOD(DOMElement,prepend)1266 PHP_METHOD(DOMElement, prepend)
1267 {
1268 	int argc = 0;
1269 	zval *args, *id;
1270 	dom_object *intern;
1271 	xmlNode *context;
1272 
1273 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &args, &argc) == FAILURE) {
1274 		RETURN_THROWS();
1275 	}
1276 
1277 	id = ZEND_THIS;
1278 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1279 
1280 	dom_parent_node_prepend(intern, args, argc);
1281 }
1282 /* }}} end DOMElement::prepend */
1283 
1284 /* {{{ URL: https://dom.spec.whatwg.org/#dom-parentnode-replacechildren
1285 Since: DOM Living Standard (DOM4)
1286 */
PHP_METHOD(DOMElement,replaceWith)1287 PHP_METHOD(DOMElement, replaceWith)
1288 {
1289 	int argc = 0;
1290 	zval *args, *id;
1291 	dom_object *intern;
1292 	xmlNode *context;
1293 
1294 	if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &args, &argc) == FAILURE) {
1295 		RETURN_THROWS();
1296 	}
1297 
1298 	id = ZEND_THIS;
1299 	DOM_GET_OBJ(context, id, xmlNodePtr, intern);
1300 
1301 	dom_child_replace_with(intern, args, argc);
1302 }
1303 /* }}} end DOMElement::prepend */
1304 
1305 #endif
1306