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