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