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