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