1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2016 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_node_insert_before, 0, 0, 1)
32 ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
33 ZEND_ARG_OBJ_INFO(0, refChild, DOMNode, 1)
34 ZEND_END_ARG_INFO();
35
36 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_replace_child, 0, 0, 2)
37 ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
38 ZEND_ARG_OBJ_INFO(0, oldChild, DOMNode, 0)
39 ZEND_END_ARG_INFO();
40
41 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_remove_child, 0, 0, 1)
42 ZEND_ARG_OBJ_INFO(0, oldChild, DOMNode, 0)
43 ZEND_END_ARG_INFO();
44
45 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_append_child, 0, 0, 1)
46 ZEND_ARG_OBJ_INFO(0, newChild, DOMNode, 0)
47 ZEND_END_ARG_INFO();
48
49 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_has_child_nodes, 0, 0, 0)
50 ZEND_END_ARG_INFO();
51
52 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_clone_node, 0, 0, 1)
53 ZEND_ARG_INFO(0, deep)
54 ZEND_END_ARG_INFO();
55
56 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_normalize, 0, 0, 0)
57 ZEND_END_ARG_INFO();
58
59 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_supported, 0, 0, 2)
60 ZEND_ARG_INFO(0, feature)
61 ZEND_ARG_INFO(0, version)
62 ZEND_END_ARG_INFO();
63
64 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_has_attributes, 0, 0, 0)
65 ZEND_END_ARG_INFO();
66
67 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_compare_document_position, 0, 0, 1)
68 ZEND_ARG_OBJ_INFO(0, other, DOMNode, 0)
69 ZEND_END_ARG_INFO();
70
71 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_same_node, 0, 0, 1)
72 ZEND_ARG_OBJ_INFO(0, other, DOMNode, 0)
73 ZEND_END_ARG_INFO();
74
75 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_lookup_prefix, 0, 0, 1)
76 ZEND_ARG_INFO(0, namespaceURI)
77 ZEND_END_ARG_INFO();
78
79 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_default_namespace, 0, 0, 1)
80 ZEND_ARG_INFO(0, namespaceURI)
81 ZEND_END_ARG_INFO();
82
83 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_lookup_namespace_uri, 0, 0, 1)
84 ZEND_ARG_INFO(0, prefix)
85 ZEND_END_ARG_INFO();
86
87 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_is_equal_node, 0, 0, 1)
88 ZEND_ARG_OBJ_INFO(0, arg, DOMNode, 0)
89 ZEND_END_ARG_INFO();
90
91 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_get_feature, 0, 0, 2)
92 ZEND_ARG_INFO(0, feature)
93 ZEND_ARG_INFO(0, version)
94 ZEND_END_ARG_INFO();
95
96 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_set_user_data, 0, 0, 3)
97 ZEND_ARG_INFO(0, key)
98 ZEND_ARG_INFO(0, data)
99 ZEND_ARG_INFO(0, handler)
100 ZEND_END_ARG_INFO();
101
102 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_get_user_data, 0, 0, 1)
103 ZEND_ARG_INFO(0, key)
104 ZEND_END_ARG_INFO();
105
106 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_getNodePath, 0, 0, 0)
107 ZEND_END_ARG_INFO();
108
109 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_getLineNo, 0, 0, 0)
110 ZEND_END_ARG_INFO();
111
112 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_C14N, 0, 0, 0)
113 ZEND_ARG_INFO(0, exclusive)
114 ZEND_ARG_INFO(0, with_comments)
115 ZEND_ARG_ARRAY_INFO(0, xpath, 1)
116 ZEND_ARG_ARRAY_INFO(0, ns_prefixes, 1)
117 ZEND_END_ARG_INFO();
118
119 ZEND_BEGIN_ARG_INFO_EX(arginfo_dom_node_C14NFile, 0, 0, 1)
120 ZEND_ARG_INFO(0, uri)
121 ZEND_ARG_INFO(0, exclusive)
122 ZEND_ARG_INFO(0, with_comments)
123 ZEND_ARG_ARRAY_INFO(0, xpath, 1)
124 ZEND_ARG_ARRAY_INFO(0, ns_prefixes, 1)
125 ZEND_END_ARG_INFO();
126 /* }}} */
127
128 /*
129 * class DOMNode
130 *
131 * URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1950641247
132 * Since:
133 */
134
135 const zend_function_entry php_dom_node_class_functions[] = { /* {{{ */
136 PHP_FALIAS(insertBefore, dom_node_insert_before, arginfo_dom_node_insert_before)
137 PHP_FALIAS(replaceChild, dom_node_replace_child, arginfo_dom_node_replace_child)
138 PHP_FALIAS(removeChild, dom_node_remove_child, arginfo_dom_node_remove_child)
139 PHP_FALIAS(appendChild, dom_node_append_child, arginfo_dom_node_append_child)
140 PHP_FALIAS(hasChildNodes, dom_node_has_child_nodes, arginfo_dom_node_has_child_nodes)
141 PHP_FALIAS(cloneNode, dom_node_clone_node, arginfo_dom_node_clone_node)
142 PHP_FALIAS(normalize, dom_node_normalize, arginfo_dom_node_normalize)
143 PHP_FALIAS(isSupported, dom_node_is_supported, arginfo_dom_node_is_supported)
144 PHP_FALIAS(hasAttributes, dom_node_has_attributes, arginfo_dom_node_has_attributes)
145 PHP_FALIAS(compareDocumentPosition, dom_node_compare_document_position, arginfo_dom_node_compare_document_position)
146 PHP_FALIAS(isSameNode, dom_node_is_same_node, arginfo_dom_node_is_same_node)
147 PHP_FALIAS(lookupPrefix, dom_node_lookup_prefix, arginfo_dom_node_lookup_prefix)
148 PHP_FALIAS(isDefaultNamespace, dom_node_is_default_namespace, arginfo_dom_node_is_default_namespace)
149 PHP_FALIAS(lookupNamespaceUri, dom_node_lookup_namespace_uri, arginfo_dom_node_lookup_namespace_uri)
150 PHP_FALIAS(isEqualNode, dom_node_is_equal_node, arginfo_dom_node_is_equal_node)
151 PHP_FALIAS(getFeature, dom_node_get_feature, arginfo_dom_node_get_feature)
152 PHP_FALIAS(setUserData, dom_node_set_user_data, arginfo_dom_node_set_user_data)
153 PHP_FALIAS(getUserData, dom_node_get_user_data, arginfo_dom_node_get_user_data)
154 PHP_ME(domnode, getNodePath, arginfo_dom_node_getNodePath, ZEND_ACC_PUBLIC)
155 PHP_ME(domnode, getLineNo, arginfo_dom_node_getLineNo, ZEND_ACC_PUBLIC)
156 PHP_ME(domnode, C14N, arginfo_dom_node_C14N, ZEND_ACC_PUBLIC)
157 PHP_ME(domnode, C14NFile, arginfo_dom_node_C14NFile, ZEND_ACC_PUBLIC)
158 PHP_FE_END
159 };
160 /* }}} */
161
dom_reconcile_ns(xmlDocPtr doc,xmlNodePtr nodep)162 static void dom_reconcile_ns(xmlDocPtr doc, xmlNodePtr nodep) /* {{{ */
163 {
164 xmlNsPtr nsptr, nsdftptr, curns, prevns = NULL;
165
166 if (nodep->type == XML_ELEMENT_NODE) {
167 /* Following if block primarily used for inserting nodes created via createElementNS */
168 if (nodep->nsDef != NULL) {
169 curns = nodep->nsDef;
170 while (curns) {
171 nsdftptr = curns->next;
172 if (curns->href != NULL) {
173 if((nsptr = xmlSearchNsByHref(doc, nodep->parent, curns->href)) &&
174 (curns->prefix == NULL || xmlStrEqual(nsptr->prefix, curns->prefix))) {
175 curns->next = NULL;
176 if (prevns == NULL) {
177 nodep->nsDef = nsdftptr;
178 } else {
179 prevns->next = nsdftptr;
180 }
181 dom_set_old_ns(doc, curns);
182 curns = prevns;
183 }
184 }
185 prevns = curns;
186 curns = nsdftptr;
187 }
188 }
189 xmlReconciliateNs(doc, nodep);
190 }
191 }
192 /* }}} */
193
194 /* {{{ nodeName string
195 readonly=yes
196 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D095
197 Since:
198 */
dom_node_node_name_read(dom_object * obj,zval ** retval TSRMLS_DC)199 int dom_node_node_name_read(dom_object *obj, zval **retval TSRMLS_DC)
200 {
201 xmlNode *nodep;
202 xmlNsPtr ns;
203 char *str = NULL;
204 xmlChar *qname = NULL;
205
206 nodep = dom_object_get_node(obj);
207
208 if (nodep == NULL) {
209 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
210 return FAILURE;
211 }
212
213 switch (nodep->type) {
214 case XML_ATTRIBUTE_NODE:
215 case XML_ELEMENT_NODE:
216 ns = nodep->ns;
217 if (ns != NULL && ns->prefix) {
218 qname = xmlStrdup(ns->prefix);
219 qname = xmlStrcat(qname, ":");
220 qname = xmlStrcat(qname, nodep->name);
221 str = qname;
222 } else {
223 str = (char *) nodep->name;
224 }
225 break;
226 case XML_NAMESPACE_DECL:
227 ns = nodep->ns;
228 if (ns != NULL && ns->prefix) {
229 qname = xmlStrdup("xmlns");
230 qname = xmlStrcat(qname, ":");
231 qname = xmlStrcat(qname, nodep->name);
232 str = qname;
233 } else {
234 str = (char *) nodep->name;
235 }
236 break;
237 case XML_DOCUMENT_TYPE_NODE:
238 case XML_DTD_NODE:
239 case XML_PI_NODE:
240 case XML_ENTITY_DECL:
241 case XML_ENTITY_REF_NODE:
242 case XML_NOTATION_NODE:
243 str = (char *) nodep->name;
244 break;
245 case XML_CDATA_SECTION_NODE:
246 str = "#cdata-section";
247 break;
248 case XML_COMMENT_NODE:
249 str = "#comment";
250 break;
251 case XML_HTML_DOCUMENT_NODE:
252 case XML_DOCUMENT_NODE:
253 str = "#document";
254 break;
255 case XML_DOCUMENT_FRAG_NODE:
256 str = "#document-fragment";
257 break;
258 case XML_TEXT_NODE:
259 str = "#text";
260 break;
261 default:
262 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Node Type");
263 }
264
265 ALLOC_ZVAL(*retval);
266
267 if(str != NULL) {
268 ZVAL_STRING(*retval, str, 1);
269 } else {
270 ZVAL_EMPTY_STRING(*retval);
271 }
272
273 if (qname != NULL) {
274 xmlFree(qname);
275 }
276
277 return SUCCESS;
278
279 }
280
281 /* }}} */
282
283 /* {{{ nodeValue string
284 readonly=no
285 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-F68D080
286 Since:
287 */
dom_node_node_value_read(dom_object * obj,zval ** retval TSRMLS_DC)288 int dom_node_node_value_read(dom_object *obj, zval **retval TSRMLS_DC)
289 {
290 xmlNode *nodep;
291 char *str = NULL;
292
293 nodep = dom_object_get_node(obj);
294
295 if (nodep == NULL) {
296 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
297 return FAILURE;
298 }
299
300 /* Access to Element node is implemented as a convience method */
301 switch (nodep->type) {
302 case XML_ATTRIBUTE_NODE:
303 case XML_TEXT_NODE:
304 case XML_ELEMENT_NODE:
305 case XML_COMMENT_NODE:
306 case XML_CDATA_SECTION_NODE:
307 case XML_PI_NODE:
308 str = xmlNodeGetContent(nodep);
309 break;
310 case XML_NAMESPACE_DECL:
311 str = xmlNodeGetContent(nodep->children);
312 break;
313 default:
314 str = NULL;
315 break;
316 }
317
318 ALLOC_ZVAL(*retval);
319
320 if(str != NULL) {
321 ZVAL_STRING(*retval, str, 1);
322 xmlFree(str);
323 } else {
324 ZVAL_NULL(*retval);
325 }
326
327
328 return SUCCESS;
329
330 }
331
dom_node_node_value_write(dom_object * obj,zval * newval TSRMLS_DC)332 int dom_node_node_value_write(dom_object *obj, zval *newval TSRMLS_DC)
333 {
334 xmlNode *nodep;
335 zval value_copy;
336
337 nodep = dom_object_get_node(obj);
338
339 if (nodep == NULL) {
340 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
341 return FAILURE;
342 }
343
344 /* Access to Element node is implemented as a convience method */
345 switch (nodep->type) {
346 case XML_ELEMENT_NODE:
347 case XML_ATTRIBUTE_NODE:
348 if (nodep->children) {
349 node_list_unlink(nodep->children TSRMLS_CC);
350 }
351 case XML_TEXT_NODE:
352 case XML_COMMENT_NODE:
353 case XML_CDATA_SECTION_NODE:
354 case XML_PI_NODE:
355 convert_to_string_copy(newval, value_copy);
356 xmlNodeSetContentLen(nodep, Z_STRVAL_P(newval), Z_STRLEN_P(newval) + 1);
357 if (newval == &value_copy) {
358 zval_dtor(newval);
359 }
360 break;
361 default:
362 break;
363 }
364
365 return SUCCESS;
366 }
367
368 /* }}} */
369
370 /* {{{ nodeType int
371 readonly=yes
372 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-111237558
373 Since:
374 */
dom_node_node_type_read(dom_object * obj,zval ** retval TSRMLS_DC)375 int dom_node_node_type_read(dom_object *obj, zval **retval TSRMLS_DC)
376 {
377 xmlNode *nodep;
378
379 nodep = dom_object_get_node(obj);
380
381 if (nodep == NULL) {
382 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
383 return FAILURE;
384 }
385
386 ALLOC_ZVAL(*retval);
387
388 /* Specs dictate that they are both type XML_DOCUMENT_TYPE_NODE */
389 if (nodep->type == XML_DTD_NODE) {
390 ZVAL_LONG(*retval, XML_DOCUMENT_TYPE_NODE);
391 } else {
392 ZVAL_LONG(*retval, nodep->type);
393 }
394
395 return SUCCESS;
396 }
397
398 /* }}} */
399
400 /* {{{ parentNode DomNode
401 readonly=yes
402 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1060184317
403 Since:
404 */
dom_node_parent_node_read(dom_object * obj,zval ** retval TSRMLS_DC)405 int dom_node_parent_node_read(dom_object *obj, zval **retval TSRMLS_DC)
406 {
407 xmlNode *nodep, *nodeparent;
408 int ret;
409
410 nodep = dom_object_get_node(obj);
411
412 if (nodep == NULL) {
413 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
414 return FAILURE;
415 }
416
417 ALLOC_ZVAL(*retval);
418
419 nodeparent = nodep->parent;
420 if (!nodeparent) {
421 ZVAL_NULL(*retval);
422 return SUCCESS;
423 }
424
425 if (NULL == (*retval = php_dom_create_object(nodeparent, &ret, *retval, obj TSRMLS_CC))) {
426 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
427 return FAILURE;
428 }
429 return SUCCESS;
430 }
431
432 /* }}} */
433
434 /* {{{ childNodes DomNodeList
435 readonly=yes
436 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1451460987
437 Since:
438 */
dom_node_child_nodes_read(dom_object * obj,zval ** retval TSRMLS_DC)439 int dom_node_child_nodes_read(dom_object *obj, zval **retval TSRMLS_DC)
440 {
441 xmlNode *nodep;
442 dom_object *intern;
443
444 nodep = dom_object_get_node(obj);
445
446 if (nodep == NULL) {
447 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
448 return FAILURE;
449 }
450
451 ALLOC_ZVAL(*retval);
452
453 if (dom_node_children_valid(nodep) == FAILURE) {
454 ZVAL_NULL(*retval);
455 } else {
456 php_dom_create_interator(*retval, DOM_NODELIST TSRMLS_CC);
457 intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC);
458 dom_namednode_iter(obj, XML_ELEMENT_NODE, intern, NULL, NULL, NULL TSRMLS_CC);
459 }
460
461 return SUCCESS;
462 }
463
464 /* }}} */
465
466 /* {{{ firstChild DomNode
467 readonly=yes
468 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-169727388
469 Since:
470 */
dom_node_first_child_read(dom_object * obj,zval ** retval TSRMLS_DC)471 int dom_node_first_child_read(dom_object *obj, zval **retval TSRMLS_DC)
472 {
473 xmlNode *nodep, *first = NULL;
474 int ret;
475
476 nodep = dom_object_get_node(obj);
477
478 if (nodep == NULL) {
479 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
480 return FAILURE;
481 }
482
483 if (dom_node_children_valid(nodep) == SUCCESS) {
484 first = nodep->children;
485 }
486
487 ALLOC_ZVAL(*retval);
488
489 if (!first) {
490 ZVAL_NULL(*retval);
491 return SUCCESS;
492 }
493
494 if (NULL == (*retval = php_dom_create_object(first, &ret, *retval, obj TSRMLS_CC))) {
495 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
496 return FAILURE;
497 }
498 return SUCCESS;
499 }
500
501 /* }}} */
502
503 /* {{{ lastChild DomNode
504 readonly=yes
505 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-61AD09FB
506 Since:
507 */
dom_node_last_child_read(dom_object * obj,zval ** retval TSRMLS_DC)508 int dom_node_last_child_read(dom_object *obj, zval **retval TSRMLS_DC)
509 {
510 xmlNode *nodep, *last = NULL;
511 int ret;
512
513 nodep = dom_object_get_node(obj);
514
515 if (nodep == NULL) {
516 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
517 return FAILURE;
518 }
519
520 if (dom_node_children_valid(nodep) == SUCCESS) {
521 last = nodep->last;
522 }
523
524 ALLOC_ZVAL(*retval);
525
526 if (!last) {
527 ZVAL_NULL(*retval);
528 return SUCCESS;
529 }
530
531 if (NULL == (*retval = php_dom_create_object(last, &ret, *retval, obj TSRMLS_CC))) {
532 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
533 return FAILURE;
534 }
535 return SUCCESS;
536 }
537
538 /* }}} */
539
540 /* {{{ previousSibling DomNode
541 readonly=yes
542 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-640FB3C8
543 Since:
544 */
dom_node_previous_sibling_read(dom_object * obj,zval ** retval TSRMLS_DC)545 int dom_node_previous_sibling_read(dom_object *obj, zval **retval TSRMLS_DC)
546 {
547 xmlNode *nodep, *prevsib;
548 int ret;
549
550 nodep = dom_object_get_node(obj);
551
552 if (nodep == NULL) {
553 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
554 return FAILURE;
555 }
556
557 ALLOC_ZVAL(*retval);
558
559 prevsib = nodep->prev;
560 if (!prevsib) {
561 ZVAL_NULL(*retval);
562 return SUCCESS;
563 }
564
565 if (NULL == (*retval = php_dom_create_object(prevsib, &ret, *retval, obj TSRMLS_CC))) {
566 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
567 return FAILURE;
568 }
569 return SUCCESS;
570 }
571
572 /* }}} */
573
574 /* {{{ nextSibling DomNode
575 readonly=yes
576 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-6AC54C2F
577 Since:
578 */
dom_node_next_sibling_read(dom_object * obj,zval ** retval TSRMLS_DC)579 int dom_node_next_sibling_read(dom_object *obj, zval **retval TSRMLS_DC)
580 {
581 xmlNode *nodep, *nextsib;
582 int ret;
583
584 nodep = dom_object_get_node(obj);
585
586 if (nodep == NULL) {
587 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
588 return FAILURE;
589 }
590
591 nextsib = nodep->next;
592 if (!nextsib) {
593 return FAILURE;
594 }
595
596 ALLOC_ZVAL(*retval);
597
598 if (NULL == (*retval = php_dom_create_object(nextsib, &ret, *retval, obj TSRMLS_CC))) {
599 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
600 return FAILURE;
601 }
602 return SUCCESS;
603 }
604
605 /* }}} */
606
607 /* {{{ attributes DomNamedNodeMap
608 readonly=yes
609 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-84CF096
610 Since:
611 */
dom_node_attributes_read(dom_object * obj,zval ** retval TSRMLS_DC)612 int dom_node_attributes_read(dom_object *obj, zval **retval TSRMLS_DC)
613 {
614 xmlNode *nodep;
615 dom_object *intern;
616
617 nodep = dom_object_get_node(obj);
618
619 if (nodep == NULL) {
620 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
621 return FAILURE;
622 }
623
624 ALLOC_ZVAL(*retval);
625
626 if (nodep->type == XML_ELEMENT_NODE) {
627 php_dom_create_interator(*retval, DOM_NAMEDNODEMAP TSRMLS_CC);
628 intern = (dom_object *)zend_objects_get_address(*retval TSRMLS_CC);
629 dom_namednode_iter(obj, XML_ATTRIBUTE_NODE, intern, NULL, NULL, NULL TSRMLS_CC);
630 } else {
631 ZVAL_NULL(*retval);
632 }
633
634 return SUCCESS;
635 }
636
637 /* }}} */
638
639 /* {{{ ownerDocument DomDocument
640 readonly=yes
641 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-node-ownerDoc
642 Since:
643 */
dom_node_owner_document_read(dom_object * obj,zval ** retval TSRMLS_DC)644 int dom_node_owner_document_read(dom_object *obj, zval **retval TSRMLS_DC)
645 {
646 xmlNode *nodep;
647 xmlDocPtr docp;
648 int ret;
649
650 nodep = dom_object_get_node(obj);
651
652 if (nodep == NULL) {
653 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
654 return FAILURE;
655 }
656
657 if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
658 ALLOC_ZVAL(*retval);
659 ZVAL_NULL(*retval);
660 return SUCCESS;
661 }
662
663 docp = nodep->doc;
664 if (!docp) {
665 return FAILURE;
666 }
667
668 ALLOC_ZVAL(*retval);
669
670 if (NULL == (*retval = php_dom_create_object((xmlNodePtr) docp, &ret, *retval, obj TSRMLS_CC))) {
671 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create required DOM object");
672 return FAILURE;
673 }
674 return SUCCESS;
675 }
676
677 /* }}} */
678
679 /* {{{ namespaceUri string
680 readonly=yes
681 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSname
682 Since: DOM Level 2
683 */
dom_node_namespace_uri_read(dom_object * obj,zval ** retval TSRMLS_DC)684 int dom_node_namespace_uri_read(dom_object *obj, zval **retval TSRMLS_DC)
685 {
686 xmlNode *nodep;
687 char *str = NULL;
688
689 nodep = dom_object_get_node(obj);
690
691 if (nodep == NULL) {
692 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
693 return FAILURE;
694 }
695
696 switch (nodep->type) {
697 case XML_ELEMENT_NODE:
698 case XML_ATTRIBUTE_NODE:
699 case XML_NAMESPACE_DECL:
700 if (nodep->ns != NULL) {
701 str = (char *) nodep->ns->href;
702 }
703 break;
704 default:
705 str = NULL;
706 break;
707 }
708
709 ALLOC_ZVAL(*retval);
710
711 if(str != NULL) {
712 ZVAL_STRING(*retval, str, 1);
713 } else {
714 ZVAL_NULL(*retval);
715 }
716
717 return SUCCESS;
718 }
719
720 /* }}} */
721
722 /* {{{ prefix string
723 readonly=no
724 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSPrefix
725 Since: DOM Level 2
726 */
dom_node_prefix_read(dom_object * obj,zval ** retval TSRMLS_DC)727 int dom_node_prefix_read(dom_object *obj, zval **retval TSRMLS_DC)
728 {
729 xmlNode *nodep;
730 xmlNsPtr ns;
731 char *str = NULL;
732
733 nodep = dom_object_get_node(obj);
734
735 if (nodep == NULL) {
736 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
737 return FAILURE;
738 }
739
740 switch (nodep->type) {
741 case XML_ELEMENT_NODE:
742 case XML_ATTRIBUTE_NODE:
743 case XML_NAMESPACE_DECL:
744 ns = nodep->ns;
745 if (ns != NULL && ns->prefix) {
746 str = (char *) ns->prefix;
747 }
748 break;
749 default:
750 str = NULL;
751 break;
752 }
753
754 ALLOC_ZVAL(*retval);
755
756 if (str == NULL) {
757 ZVAL_EMPTY_STRING(*retval);
758 } else {
759 ZVAL_STRING(*retval, str, 1);
760 }
761 return SUCCESS;
762
763 }
764
dom_node_prefix_write(dom_object * obj,zval * newval TSRMLS_DC)765 int dom_node_prefix_write(dom_object *obj, zval *newval TSRMLS_DC)
766 {
767 zval value_copy;
768 xmlNode *nodep, *nsnode = NULL;
769 xmlNsPtr ns = NULL, curns;
770 char *strURI;
771 char *prefix;
772
773 nodep = dom_object_get_node(obj);
774
775 if (nodep == NULL) {
776 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
777 return FAILURE;
778 }
779
780 switch (nodep->type) {
781 case XML_ELEMENT_NODE:
782 nsnode = nodep;
783 case XML_ATTRIBUTE_NODE:
784 if (nsnode == NULL) {
785 nsnode = nodep->parent;
786 if (nsnode == NULL) {
787 nsnode = xmlDocGetRootElement(nodep->doc);
788 }
789 }
790 convert_to_string_copy(newval, value_copy);
791 prefix = Z_STRVAL_P(newval);
792 if (nsnode && nodep->ns != NULL && !xmlStrEqual(nodep->ns->prefix, (xmlChar *)prefix)) {
793 strURI = (char *) nodep->ns->href;
794 if (strURI == NULL ||
795 (!strcmp (prefix, "xml") && strcmp(strURI, XML_XML_NAMESPACE)) ||
796 (nodep->type == XML_ATTRIBUTE_NODE && !strcmp (prefix, "xmlns") &&
797 strcmp (strURI, DOM_XMLNS_NAMESPACE)) ||
798 (nodep->type == XML_ATTRIBUTE_NODE && !strcmp (nodep->name, "xmlns"))) {
799 ns = NULL;
800 } else {
801 curns = nsnode->nsDef;
802 while (curns != NULL) {
803 if (xmlStrEqual((xmlChar *)prefix, curns->prefix) && xmlStrEqual(nodep->ns->href, curns->href)) {
804 ns = curns;
805 break;
806 }
807 curns = curns->next;
808 }
809 if (ns == NULL) {
810 ns = xmlNewNs(nsnode, nodep->ns->href, (xmlChar *)prefix);
811 }
812 }
813
814 if (ns == NULL) {
815 if (newval == &value_copy) {
816 zval_dtor(newval);
817 }
818 php_dom_throw_error(NAMESPACE_ERR, dom_get_strict_error(obj->document) TSRMLS_CC);
819 return FAILURE;
820 }
821
822 xmlSetNs(nodep, ns);
823 }
824 if (newval == &value_copy) {
825 zval_dtor(newval);
826 }
827 break;
828 default:
829 break;
830 }
831
832 return SUCCESS;
833 }
834
835 /* }}} */
836
837 /* {{{ localName string
838 readonly=yes
839 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeNSLocalN
840 Since: DOM Level 2
841 */
dom_node_local_name_read(dom_object * obj,zval ** retval TSRMLS_DC)842 int dom_node_local_name_read(dom_object *obj, zval **retval TSRMLS_DC)
843 {
844 xmlNode *nodep;
845
846 nodep = dom_object_get_node(obj);
847
848 if (nodep == NULL) {
849 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
850 return FAILURE;
851 }
852
853 ALLOC_ZVAL(*retval);
854
855 if (nodep->type == XML_ELEMENT_NODE || nodep->type == XML_ATTRIBUTE_NODE || nodep->type == XML_NAMESPACE_DECL) {
856 ZVAL_STRING(*retval, (char *) (nodep->name), 1);
857 } else {
858 ZVAL_NULL(*retval);
859 }
860
861 return SUCCESS;
862 }
863
864 /* }}} */
865
866 /* {{{ baseURI string
867 readonly=yes
868 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-baseURI
869 Since: DOM Level 3
870 */
dom_node_base_uri_read(dom_object * obj,zval ** retval TSRMLS_DC)871 int dom_node_base_uri_read(dom_object *obj, zval **retval TSRMLS_DC)
872 {
873 xmlNode *nodep;
874 xmlChar *baseuri;
875
876 nodep = dom_object_get_node(obj);
877
878 if (nodep == NULL) {
879 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
880 return FAILURE;
881 }
882
883 ALLOC_ZVAL(*retval);
884
885 baseuri = xmlNodeGetBase(nodep->doc, nodep);
886 if (baseuri) {
887 ZVAL_STRING(*retval, (char *) (baseuri), 1);
888 xmlFree(baseuri);
889 } else {
890 ZVAL_NULL(*retval);
891 }
892
893 return SUCCESS;
894 }
895
896 /* }}} */
897
898 /* {{{ textContent string
899 readonly=no
900 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-textContent
901 Since: DOM Level 3
902 */
dom_node_text_content_read(dom_object * obj,zval ** retval TSRMLS_DC)903 int dom_node_text_content_read(dom_object *obj, zval **retval TSRMLS_DC)
904 {
905 xmlNode *nodep;
906 char *str = NULL;
907
908 nodep = dom_object_get_node(obj);
909
910 if (nodep == NULL) {
911 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
912 return FAILURE;
913 }
914
915 str = xmlNodeGetContent(nodep);
916
917 ALLOC_ZVAL(*retval);
918
919 if(str != NULL) {
920 ZVAL_STRING(*retval, str, 1);
921 xmlFree(str);
922 } else {
923 ZVAL_EMPTY_STRING(*retval);
924 }
925
926 return SUCCESS;
927 }
928
dom_node_text_content_write(dom_object * obj,zval * newval TSRMLS_DC)929 int dom_node_text_content_write(dom_object *obj, zval *newval TSRMLS_DC)
930 {
931 xmlNode *nodep = dom_object_get_node(obj);
932 zval value_copy;
933
934 if (nodep == NULL) {
935 php_dom_throw_error(INVALID_STATE_ERR, 0 TSRMLS_CC);
936 return FAILURE;
937 }
938
939 convert_to_string_copy(newval, value_copy);
940 /* we have to use xmlNodeAddContent() to get the same behavior as with xmlNewText() */
941 xmlNodeSetContent(nodep, (xmlChar *) "");
942 xmlNodeAddContent(nodep, Z_STRVAL_P(newval));
943 if (newval == &value_copy) {
944 zval_dtor(newval);
945 }
946
947 return SUCCESS;
948 }
949
950 /* }}} */
951
_php_dom_insert_fragment(xmlNodePtr nodep,xmlNodePtr prevsib,xmlNodePtr nextsib,xmlNodePtr fragment,dom_object * intern,dom_object * childobj TSRMLS_DC)952 static xmlNodePtr _php_dom_insert_fragment(xmlNodePtr nodep, xmlNodePtr prevsib, xmlNodePtr nextsib, xmlNodePtr fragment, dom_object *intern, dom_object *childobj TSRMLS_DC) /* {{{ */
953 {
954 xmlNodePtr newchild, node;
955
956 newchild = fragment->children;
957
958 if (newchild) {
959 if (prevsib == NULL) {
960 nodep->children = newchild;
961 } else {
962 prevsib->next = newchild;
963 }
964 newchild->prev = prevsib;
965 if (nextsib == NULL) {
966 nodep->last = fragment->last;
967 } else {
968 fragment->last->next = nextsib;
969 nextsib->prev = fragment->last;
970 }
971
972 node = newchild;
973 while (node != NULL) {
974 node->parent = nodep;
975 if (node->doc != nodep->doc) {
976 xmlSetTreeDoc(node, nodep->doc);
977 if (node->_private != NULL) {
978 childobj = node->_private;
979 childobj->document = intern->document;
980 php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL TSRMLS_CC);
981 }
982 }
983 if (node == fragment->last) {
984 break;
985 }
986 node = node->next;
987 }
988
989 fragment->children = NULL;
990 fragment->last = NULL;
991 }
992
993 return newchild;
994 }
995 /* }}} */
996
997 /* {{{ proto domnode dom_node_insert_before(DomNode newChild, DomNode refChild);
998 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-952280727
999 Since:
1000 */
PHP_FUNCTION(dom_node_insert_before)1001 PHP_FUNCTION(dom_node_insert_before)
1002 {
1003 zval *id, *node, *ref = NULL;
1004 xmlNodePtr child, new_child, parentp, refp;
1005 dom_object *intern, *childobj, *refpobj;
1006 int ret, stricterror;
1007
1008 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO|O!", &id, dom_node_class_entry, &node, dom_node_class_entry, &ref, dom_node_class_entry) == FAILURE) {
1009 return;
1010 }
1011
1012 DOM_GET_OBJ(parentp, id, xmlNodePtr, intern);
1013
1014 if (dom_node_children_valid(parentp) == FAILURE) {
1015 RETURN_FALSE;
1016 }
1017
1018 DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
1019
1020 new_child = NULL;
1021
1022 stricterror = dom_get_strict_error(intern->document);
1023
1024 if (dom_node_is_read_only(parentp) == SUCCESS ||
1025 (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
1026 php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror TSRMLS_CC);
1027 RETURN_FALSE;
1028 }
1029
1030 if (dom_hierarchy(parentp, child) == FAILURE) {
1031 php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror TSRMLS_CC);
1032 RETURN_FALSE;
1033 }
1034
1035 if (child->doc != parentp->doc && child->doc != NULL) {
1036 php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror TSRMLS_CC);
1037 RETURN_FALSE;
1038 }
1039
1040 if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
1041 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Document Fragment is empty");
1042 RETURN_FALSE;
1043 }
1044
1045 if (child->doc == NULL && parentp->doc != NULL) {
1046 childobj->document = intern->document;
1047 php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL TSRMLS_CC);
1048 }
1049
1050 if (ref != NULL) {
1051 DOM_GET_OBJ(refp, ref, xmlNodePtr, refpobj);
1052 if (refp->parent != parentp) {
1053 php_dom_throw_error(NOT_FOUND_ERR, stricterror TSRMLS_CC);
1054 RETURN_FALSE;
1055 }
1056
1057 if (child->parent != NULL) {
1058 xmlUnlinkNode(child);
1059 }
1060
1061 if (child->type == XML_TEXT_NODE && (refp->type == XML_TEXT_NODE ||
1062 (refp->prev != NULL && refp->prev->type == XML_TEXT_NODE))) {
1063 if (child->doc == NULL) {
1064 xmlSetTreeDoc(child, parentp->doc);
1065 }
1066 new_child = child;
1067 new_child->parent = refp->parent;
1068 new_child->next = refp;
1069 new_child->prev = refp->prev;
1070 refp->prev = new_child;
1071 if (new_child->prev != NULL) {
1072 new_child->prev->next = new_child;
1073 }
1074 if (new_child->parent != NULL) {
1075 if (new_child->parent->children == refp) {
1076 new_child->parent->children = new_child;
1077 }
1078 }
1079
1080 } else if (child->type == XML_ATTRIBUTE_NODE) {
1081 xmlAttrPtr lastattr;
1082
1083 if (child->ns == NULL)
1084 lastattr = xmlHasProp(refp->parent, child->name);
1085 else
1086 lastattr = xmlHasNsProp(refp->parent, child->name, child->ns->href);
1087 if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
1088 if (lastattr != (xmlAttrPtr) child) {
1089 xmlUnlinkNode((xmlNodePtr) lastattr);
1090 php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC);
1091 } else {
1092 DOM_RET_OBJ(child, &ret, intern);
1093 return;
1094 }
1095 }
1096 } else if (child->type == XML_DOCUMENT_FRAG_NODE) {
1097 new_child = _php_dom_insert_fragment(parentp, refp->prev, refp, child, intern, childobj TSRMLS_CC);
1098 }
1099
1100 if (new_child == NULL) {
1101 new_child = xmlAddPrevSibling(refp, child);
1102 }
1103 } else {
1104 if (child->parent != NULL){
1105 xmlUnlinkNode(child);
1106 }
1107 if (child->type == XML_TEXT_NODE && parentp->last != NULL && parentp->last->type == XML_TEXT_NODE) {
1108 child->parent = parentp;
1109 if (child->doc == NULL) {
1110 xmlSetTreeDoc(child, parentp->doc);
1111 }
1112 new_child = child;
1113 if (parentp->children == NULL) {
1114 parentp->children = child;
1115 parentp->last = child;
1116 } else {
1117 child = parentp->last;
1118 child->next = new_child;
1119 new_child->prev = child;
1120 parentp->last = new_child;
1121 }
1122 } else if (child->type == XML_ATTRIBUTE_NODE) {
1123 xmlAttrPtr lastattr;
1124
1125 if (child->ns == NULL)
1126 lastattr = xmlHasProp(parentp, child->name);
1127 else
1128 lastattr = xmlHasNsProp(parentp, child->name, child->ns->href);
1129 if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
1130 if (lastattr != (xmlAttrPtr) child) {
1131 xmlUnlinkNode((xmlNodePtr) lastattr);
1132 php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC);
1133 } else {
1134 DOM_RET_OBJ(child, &ret, intern);
1135 return;
1136 }
1137 }
1138 } else if (child->type == XML_DOCUMENT_FRAG_NODE) {
1139 new_child = _php_dom_insert_fragment(parentp, parentp->last, NULL, child, intern, childobj TSRMLS_CC);
1140 }
1141 if (new_child == NULL) {
1142 new_child = xmlAddChild(parentp, child);
1143 }
1144 }
1145
1146 if (NULL == new_child) {
1147 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't add newnode as the previous sibling of refnode");
1148 RETURN_FALSE;
1149 }
1150
1151 dom_reconcile_ns(parentp->doc, new_child);
1152
1153 DOM_RET_OBJ(new_child, &ret, intern);
1154
1155 }
1156 /* }}} end dom_node_insert_before */
1157
1158 /* {{{ proto DomNode dom_node_replace_child(DomNode newChild, DomNode oldChild);
1159 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-785887307
1160 Since:
1161 */
PHP_FUNCTION(dom_node_replace_child)1162 PHP_FUNCTION(dom_node_replace_child)
1163 {
1164 zval *id, *newnode, *oldnode;
1165 xmlNodePtr children, newchild, oldchild, nodep;
1166 dom_object *intern, *newchildobj, *oldchildobj;
1167 int foundoldchild = 0, stricterror;
1168
1169 int ret;
1170
1171 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OOO", &id, dom_node_class_entry, &newnode, dom_node_class_entry, &oldnode, dom_node_class_entry) == FAILURE) {
1172 return;
1173 }
1174
1175 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1176
1177 if (dom_node_children_valid(nodep) == FAILURE) {
1178 RETURN_FALSE;
1179 }
1180
1181 DOM_GET_OBJ(newchild, newnode, xmlNodePtr, newchildobj);
1182 DOM_GET_OBJ(oldchild, oldnode, xmlNodePtr, oldchildobj);
1183
1184 children = nodep->children;
1185 if (!children) {
1186 RETURN_FALSE;
1187 }
1188
1189 stricterror = dom_get_strict_error(intern->document);
1190
1191 if (dom_node_is_read_only(nodep) == SUCCESS ||
1192 (newchild->parent != NULL && dom_node_is_read_only(newchild->parent) == SUCCESS)) {
1193 php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror TSRMLS_CC);
1194 RETURN_FALSE;
1195 }
1196
1197 if (newchild->doc != nodep->doc && newchild->doc != NULL) {
1198 php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror TSRMLS_CC);
1199 RETURN_FALSE;
1200 }
1201
1202 if (dom_hierarchy(nodep, newchild) == FAILURE) {
1203 php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror TSRMLS_CC);
1204 RETURN_FALSE;
1205 }
1206
1207 /* check for the old child and whether the new child is already a child */
1208 while (children) {
1209 if (children == oldchild) {
1210 foundoldchild = 1;
1211 break;
1212 }
1213 children = children->next;
1214 }
1215
1216 if (foundoldchild) {
1217 if (newchild->type == XML_DOCUMENT_FRAG_NODE) {
1218 xmlNodePtr prevsib, nextsib;
1219 prevsib = oldchild->prev;
1220 nextsib = oldchild->next;
1221
1222 xmlUnlinkNode(oldchild);
1223
1224 newchild = _php_dom_insert_fragment(nodep, prevsib, nextsib, newchild, intern, newchildobj TSRMLS_CC);
1225 if (newchild) {
1226 dom_reconcile_ns(nodep->doc, newchild);
1227 }
1228 } else if (oldchild != newchild) {
1229 if (newchild->doc == NULL && nodep->doc != NULL) {
1230 xmlSetTreeDoc(newchild, nodep->doc);
1231 newchildobj->document = intern->document;
1232 php_libxml_increment_doc_ref((php_libxml_node_object *)newchildobj, NULL TSRMLS_CC);
1233 }
1234 xmlReplaceNode(oldchild, newchild);
1235 dom_reconcile_ns(nodep->doc, newchild);
1236 }
1237 DOM_RET_OBJ(oldchild, &ret, intern);
1238 return;
1239 } else {
1240 php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document) TSRMLS_CC);
1241 RETURN_FALSE;
1242 }
1243 }
1244 /* }}} end dom_node_replace_child */
1245
1246 /* {{{ proto DomNode dom_node_remove_child(DomNode oldChild);
1247 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-1734834066
1248 Since:
1249 */
PHP_FUNCTION(dom_node_remove_child)1250 PHP_FUNCTION(dom_node_remove_child)
1251 {
1252 zval *id, *node;
1253 xmlNodePtr children, child, nodep;
1254 dom_object *intern, *childobj;
1255 int ret, stricterror;
1256
1257 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &id, dom_node_class_entry, &node, dom_node_class_entry) == FAILURE) {
1258 return;
1259 }
1260
1261 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1262
1263 if (dom_node_children_valid(nodep) == FAILURE) {
1264 RETURN_FALSE;
1265 }
1266
1267 DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
1268
1269 stricterror = dom_get_strict_error(intern->document);
1270
1271 if (dom_node_is_read_only(nodep) == SUCCESS ||
1272 (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
1273 php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror TSRMLS_CC);
1274 RETURN_FALSE;
1275 }
1276
1277 children = nodep->children;
1278 if (!children) {
1279 php_dom_throw_error(NOT_FOUND_ERR, stricterror TSRMLS_CC);
1280 RETURN_FALSE;
1281 }
1282
1283 while (children) {
1284 if (children == child) {
1285 xmlUnlinkNode(child);
1286 DOM_RET_OBJ(child, &ret, intern);
1287 return;
1288 }
1289 children = children->next;
1290 }
1291
1292 php_dom_throw_error(NOT_FOUND_ERR, stricterror TSRMLS_CC);
1293 RETURN_FALSE
1294 }
1295 /* }}} end dom_node_remove_child */
1296
1297 /* {{{ proto DomNode dom_node_append_child(DomNode newChild);
1298 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-184E7107
1299 Since:
1300 */
PHP_FUNCTION(dom_node_append_child)1301 PHP_FUNCTION(dom_node_append_child)
1302 {
1303 zval *id, *node;
1304 xmlNodePtr child, nodep, new_child = NULL;
1305 dom_object *intern, *childobj;
1306 int ret, stricterror;
1307
1308 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &id, dom_node_class_entry, &node, dom_node_class_entry) == FAILURE) {
1309 return;
1310 }
1311
1312 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1313
1314 if (dom_node_children_valid(nodep) == FAILURE) {
1315 RETURN_FALSE;
1316 }
1317
1318 DOM_GET_OBJ(child, node, xmlNodePtr, childobj);
1319
1320 stricterror = dom_get_strict_error(intern->document);
1321
1322 if (dom_node_is_read_only(nodep) == SUCCESS ||
1323 (child->parent != NULL && dom_node_is_read_only(child->parent) == SUCCESS)) {
1324 php_dom_throw_error(NO_MODIFICATION_ALLOWED_ERR, stricterror TSRMLS_CC);
1325 RETURN_FALSE;
1326 }
1327
1328 if (dom_hierarchy(nodep, child) == FAILURE) {
1329 php_dom_throw_error(HIERARCHY_REQUEST_ERR, stricterror TSRMLS_CC);
1330 RETURN_FALSE;
1331 }
1332
1333 if (!(child->doc == NULL || child->doc == nodep->doc)) {
1334 php_dom_throw_error(WRONG_DOCUMENT_ERR, stricterror TSRMLS_CC);
1335 RETURN_FALSE;
1336 }
1337
1338 if (child->type == XML_DOCUMENT_FRAG_NODE && child->children == NULL) {
1339 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Document Fragment is empty");
1340 RETURN_FALSE;
1341 }
1342
1343 if (child->doc == NULL && nodep->doc != NULL) {
1344 childobj->document = intern->document;
1345 php_libxml_increment_doc_ref((php_libxml_node_object *)childobj, NULL TSRMLS_CC);
1346 }
1347
1348 if (child->parent != NULL){
1349 xmlUnlinkNode(child);
1350 }
1351
1352 if (child->type == XML_TEXT_NODE && nodep->last != NULL && nodep->last->type == XML_TEXT_NODE) {
1353 child->parent = nodep;
1354 if (child->doc == NULL) {
1355 xmlSetTreeDoc(child, nodep->doc);
1356 }
1357 new_child = child;
1358 if (nodep->children == NULL) {
1359 nodep->children = child;
1360 nodep->last = child;
1361 } else {
1362 child = nodep->last;
1363 child->next = new_child;
1364 new_child->prev = child;
1365 nodep->last = new_child;
1366 }
1367 } else if (child->type == XML_ATTRIBUTE_NODE) {
1368 xmlAttrPtr lastattr;
1369
1370 if (child->ns == NULL)
1371 lastattr = xmlHasProp(nodep, child->name);
1372 else
1373 lastattr = xmlHasNsProp(nodep, child->name, child->ns->href);
1374 if (lastattr != NULL && lastattr->type != XML_ATTRIBUTE_DECL) {
1375 if (lastattr != (xmlAttrPtr) child) {
1376 xmlUnlinkNode((xmlNodePtr) lastattr);
1377 php_libxml_node_free_resource((xmlNodePtr) lastattr TSRMLS_CC);
1378 }
1379 }
1380 } else if (child->type == XML_DOCUMENT_FRAG_NODE) {
1381 new_child = _php_dom_insert_fragment(nodep, nodep->last, NULL, child, intern, childobj TSRMLS_CC);
1382 }
1383
1384 if (new_child == NULL) {
1385 new_child = xmlAddChild(nodep, child);
1386 if (new_child == NULL) {
1387 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't append node");
1388 RETURN_FALSE;
1389 }
1390 }
1391
1392 dom_reconcile_ns(nodep->doc, new_child);
1393
1394 DOM_RET_OBJ(new_child, &ret, intern);
1395 }
1396 /* }}} end dom_node_append_child */
1397
1398 /* {{{ proto boolean dom_node_has_child_nodes();
1399 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-810594187
1400 Since:
1401 */
PHP_FUNCTION(dom_node_has_child_nodes)1402 PHP_FUNCTION(dom_node_has_child_nodes)
1403 {
1404 zval *id;
1405 xmlNode *nodep;
1406 dom_object *intern;
1407
1408 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_node_class_entry) == FAILURE) {
1409 return;
1410 }
1411
1412 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1413
1414 if (dom_node_children_valid(nodep) == FAILURE) {
1415 RETURN_FALSE;
1416 }
1417
1418 if (nodep->children) {
1419 RETURN_TRUE;
1420 } else {
1421 RETURN_FALSE;
1422 }
1423 }
1424 /* }}} end dom_node_has_child_nodes */
1425
1426 /* {{{ proto DomNode dom_node_clone_node(boolean deep);
1427 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-3A0ED0A4
1428 Since:
1429 */
PHP_FUNCTION(dom_node_clone_node)1430 PHP_FUNCTION(dom_node_clone_node)
1431 {
1432 zval *id;
1433 xmlNode *n, *node;
1434 int ret;
1435 dom_object *intern;
1436 long recursive = 0;
1437
1438 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &id, dom_node_class_entry, &recursive) == FAILURE) {
1439 return;
1440 }
1441
1442 DOM_GET_OBJ(n, id, xmlNodePtr, intern);
1443
1444 node = xmlDocCopyNode(n, n->doc, recursive);
1445
1446 if (!node) {
1447 RETURN_FALSE;
1448 }
1449
1450 /* When deep is false Element nodes still require the attributes
1451 Following taken from libxml as xmlDocCopyNode doesnt do this */
1452 if (n->type == XML_ELEMENT_NODE && recursive == 0) {
1453 if (n->nsDef != NULL) {
1454 node->nsDef = xmlCopyNamespaceList(n->nsDef);
1455 }
1456 if (n->ns != NULL) {
1457 xmlNsPtr ns;
1458 ns = xmlSearchNs(n->doc, node, n->ns->prefix);
1459 if (ns == NULL) {
1460 ns = xmlSearchNs(n->doc, n, n->ns->prefix);
1461 if (ns != NULL) {
1462 xmlNodePtr root = node;
1463
1464 while (root->parent != NULL) {
1465 root = root->parent;
1466 }
1467 node->ns = xmlNewNs(root, ns->href, ns->prefix);
1468 }
1469 } else {
1470 node->ns = ns;
1471 }
1472 }
1473 if (n->properties != NULL) {
1474 node->properties = xmlCopyPropList(node, n->properties);
1475 }
1476 }
1477
1478 /* If document cloned we want a new document proxy */
1479 if (node->doc != n->doc) {
1480 intern = NULL;
1481 }
1482
1483 DOM_RET_OBJ(node, &ret, intern);
1484 }
1485 /* }}} end dom_node_clone_node */
1486
1487 /* {{{ proto void dom_node_normalize();
1488 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-normalize
1489 Since:
1490 */
PHP_FUNCTION(dom_node_normalize)1491 PHP_FUNCTION(dom_node_normalize)
1492 {
1493 zval *id;
1494 xmlNode *nodep;
1495 dom_object *intern;
1496
1497 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_node_class_entry) == FAILURE) {
1498 return;
1499 }
1500
1501 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1502
1503 dom_normalize(nodep TSRMLS_CC);
1504
1505 }
1506 /* }}} end dom_node_normalize */
1507
1508 /* {{{ proto boolean dom_node_is_supported(string feature, string version);
1509 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-Level-2-Core-Node-supports
1510 Since: DOM Level 2
1511 */
PHP_FUNCTION(dom_node_is_supported)1512 PHP_FUNCTION(dom_node_is_supported)
1513 {
1514 zval *id;
1515 int feature_len, version_len;
1516 char *feature, *version;
1517
1518 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oss", &id, dom_node_class_entry, &feature, &feature_len, &version, &version_len) == FAILURE) {
1519 return;
1520 }
1521
1522 if (dom_has_feature(feature, version)) {
1523 RETURN_TRUE;
1524 } else {
1525 RETURN_FALSE;
1526 }
1527 }
1528 /* }}} end dom_node_is_supported */
1529
1530 /* {{{ proto boolean dom_node_has_attributes();
1531 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#core-ID-NodeHasAttrs
1532 Since: DOM Level 2
1533 */
PHP_FUNCTION(dom_node_has_attributes)1534 PHP_FUNCTION(dom_node_has_attributes)
1535 {
1536 zval *id;
1537 xmlNode *nodep;
1538 dom_object *intern;
1539
1540 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &id, dom_node_class_entry) == FAILURE) {
1541 return;
1542 }
1543
1544 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1545
1546 if (nodep->type != XML_ELEMENT_NODE)
1547 RETURN_FALSE;
1548
1549 if (nodep->properties) {
1550 RETURN_TRUE;
1551 } else {
1552 RETURN_FALSE;
1553 }
1554 }
1555 /* }}} end dom_node_has_attributes */
1556
1557 /* {{{ proto short dom_node_compare_document_position(DomNode other);
1558 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-compareDocumentPosition
1559 Since: DOM Level 3
1560 */
PHP_FUNCTION(dom_node_compare_document_position)1561 PHP_FUNCTION(dom_node_compare_document_position)
1562 {
1563 DOM_NOT_IMPLEMENTED();
1564 }
1565 /* }}} end dom_node_compare_document_position */
1566
1567 /* {{{ proto boolean dom_node_is_same_node(DomNode other);
1568 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isSameNode
1569 Since: DOM Level 3
1570 */
PHP_FUNCTION(dom_node_is_same_node)1571 PHP_FUNCTION(dom_node_is_same_node)
1572 {
1573 zval *id, *node;
1574 xmlNodePtr nodeotherp, nodep;
1575 dom_object *intern, *nodeotherobj;
1576
1577 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "OO", &id, dom_node_class_entry, &node, dom_node_class_entry) == FAILURE) {
1578 return;
1579 }
1580
1581 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1582
1583 DOM_GET_OBJ(nodeotherp, node, xmlNodePtr, nodeotherobj);
1584
1585 if (nodep == nodeotherp) {
1586 RETURN_TRUE;
1587 } else {
1588 RETURN_FALSE;
1589 }
1590 }
1591 /* }}} end dom_node_is_same_node */
1592
1593 /* {{{ proto string dom_node_lookup_prefix(string namespaceURI);
1594 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-lookupNamespacePrefix
1595 Since: DOM Level 3
1596 */
PHP_FUNCTION(dom_node_lookup_prefix)1597 PHP_FUNCTION(dom_node_lookup_prefix)
1598 {
1599 zval *id;
1600 xmlNodePtr nodep, lookupp = NULL;
1601 dom_object *intern;
1602 xmlNsPtr nsptr;
1603 int uri_len = 0;
1604 char *uri;
1605
1606 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_node_class_entry, &uri, &uri_len) == FAILURE) {
1607 return;
1608 }
1609
1610 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1611
1612 if (uri_len > 0) {
1613 switch (nodep->type) {
1614 case XML_ELEMENT_NODE:
1615 lookupp = nodep;
1616 break;
1617 case XML_DOCUMENT_NODE:
1618 case XML_HTML_DOCUMENT_NODE:
1619 lookupp = xmlDocGetRootElement((xmlDocPtr) nodep);
1620 break;
1621 case XML_ENTITY_NODE :
1622 case XML_NOTATION_NODE:
1623 case XML_DOCUMENT_FRAG_NODE:
1624 case XML_DOCUMENT_TYPE_NODE:
1625 case XML_DTD_NODE:
1626 RETURN_NULL();
1627 break;
1628 default:
1629 lookupp = nodep->parent;
1630 }
1631
1632 if (lookupp != NULL && (nsptr = xmlSearchNsByHref(lookupp->doc, lookupp, uri))) {
1633 if (nsptr->prefix != NULL) {
1634 RETURN_STRING((char *) nsptr->prefix, 1);
1635 }
1636 }
1637 }
1638
1639 RETURN_NULL();
1640 }
1641 /* }}} end dom_node_lookup_prefix */
1642
1643 /* {{{ proto boolean dom_node_is_default_namespace(string namespaceURI);
1644 URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isDefaultNamespace
1645 Since: DOM Level 3
1646 */
PHP_FUNCTION(dom_node_is_default_namespace)1647 PHP_FUNCTION(dom_node_is_default_namespace)
1648 {
1649 zval *id;
1650 xmlNodePtr nodep;
1651 dom_object *intern;
1652 xmlNsPtr nsptr;
1653 int uri_len = 0;
1654 char *uri;
1655
1656 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &id, dom_node_class_entry, &uri, &uri_len) == FAILURE) {
1657 return;
1658 }
1659
1660 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1661 if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
1662 nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
1663 }
1664
1665 if (nodep && uri_len > 0) {
1666 nsptr = xmlSearchNs(nodep->doc, nodep, NULL);
1667 if (nsptr && xmlStrEqual(nsptr->href, uri)) {
1668 RETURN_TRUE;
1669 }
1670 }
1671
1672 RETURN_FALSE;
1673 }
1674 /* }}} end dom_node_is_default_namespace */
1675
1676 /* {{{ proto string dom_node_lookup_namespace_uri(string prefix);
1677 URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI
1678 Since: DOM Level 3
1679 */
PHP_FUNCTION(dom_node_lookup_namespace_uri)1680 PHP_FUNCTION(dom_node_lookup_namespace_uri)
1681 {
1682 zval *id;
1683 xmlNodePtr nodep;
1684 dom_object *intern;
1685 xmlNsPtr nsptr;
1686 int prefix_len = 0;
1687 char *prefix=NULL;
1688
1689 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os!", &id, dom_node_class_entry, &prefix, &prefix_len) == FAILURE) {
1690 return;
1691 }
1692
1693 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1694 if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
1695 nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
1696 if (nodep == NULL) {
1697 RETURN_NULL();
1698 }
1699 }
1700
1701 nsptr = xmlSearchNs(nodep->doc, nodep, prefix);
1702 if (nsptr && nsptr->href != NULL) {
1703 RETURN_STRING((char *) nsptr->href, 1);
1704 }
1705
1706 RETURN_NULL();
1707 }
1708 /* }}} end dom_node_lookup_namespace_uri */
1709
1710 /* {{{ proto boolean dom_node_is_equal_node(DomNode arg);
1711 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isEqualNode
1712 Since: DOM Level 3
1713 */
PHP_FUNCTION(dom_node_is_equal_node)1714 PHP_FUNCTION(dom_node_is_equal_node)
1715 {
1716 DOM_NOT_IMPLEMENTED();
1717 }
1718 /* }}} end dom_node_is_equal_node */
1719
1720 /* {{{ proto DomNode dom_node_get_feature(string feature, string version);
1721 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getFeature
1722 Since: DOM Level 3
1723 */
PHP_FUNCTION(dom_node_get_feature)1724 PHP_FUNCTION(dom_node_get_feature)
1725 {
1726 DOM_NOT_IMPLEMENTED();
1727 }
1728 /* }}} end dom_node_get_feature */
1729
1730 /* {{{ proto mixed dom_node_set_user_data(string key, mixed data, userdatahandler handler);
1731 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-setUserData
1732 Since: DOM Level 3
1733 */
PHP_FUNCTION(dom_node_set_user_data)1734 PHP_FUNCTION(dom_node_set_user_data)
1735 {
1736 DOM_NOT_IMPLEMENTED();
1737 }
1738 /* }}} end dom_node_set_user_data */
1739
1740 /* {{{ proto mixed dom_node_get_user_data(string key);
1741 URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-getUserData
1742 Since: DOM Level 3
1743 */
PHP_FUNCTION(dom_node_get_user_data)1744 PHP_FUNCTION(dom_node_get_user_data)
1745 {
1746 DOM_NOT_IMPLEMENTED();
1747 }
1748 /* }}} end dom_node_get_user_data */
1749
dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS,int mode)1750 static void dom_canonicalization(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
1751 {
1752 zval *id;
1753 zval *xpath_array=NULL, *ns_prefixes=NULL;
1754 xmlNodePtr nodep;
1755 xmlDocPtr docp;
1756 xmlNodeSetPtr nodeset = NULL;
1757 dom_object *intern;
1758 zend_bool exclusive=0, with_comments=0;
1759 xmlChar **inclusive_ns_prefixes = NULL;
1760 char *file = NULL;
1761 int ret = -1, file_len = 0;
1762 xmlOutputBufferPtr buf;
1763 xmlXPathContextPtr ctxp=NULL;
1764 xmlXPathObjectPtr xpathobjp=NULL;
1765
1766 if (mode == 0) {
1767 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1768 "O|bba!a!", &id, dom_node_class_entry, &exclusive, &with_comments,
1769 &xpath_array, &ns_prefixes) == FAILURE) {
1770 return;
1771 }
1772 } else {
1773 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1774 "Os|bba!a!", &id, dom_node_class_entry, &file, &file_len, &exclusive,
1775 &with_comments, &xpath_array, &ns_prefixes) == FAILURE) {
1776 return;
1777 }
1778 }
1779
1780 DOM_GET_OBJ(nodep, id, xmlNodePtr, intern);
1781
1782 docp = nodep->doc;
1783
1784 if (! docp) {
1785 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Node must be associated with a document");
1786 RETURN_FALSE;
1787 }
1788
1789 if (xpath_array == NULL) {
1790 if (nodep->type != XML_DOCUMENT_NODE) {
1791 ctxp = xmlXPathNewContext(docp);
1792 ctxp->node = nodep;
1793 xpathobjp = xmlXPathEvalExpression("(.//. | .//@* | .//namespace::*)", ctxp);
1794 ctxp->node = NULL;
1795 if (xpathobjp && xpathobjp->type == XPATH_NODESET) {
1796 nodeset = xpathobjp->nodesetval;
1797 } else {
1798 if (xpathobjp) {
1799 xmlXPathFreeObject(xpathobjp);
1800 }
1801 xmlXPathFreeContext(ctxp);
1802 php_error_docref(NULL TSRMLS_CC, E_WARNING, "XPath query did not return a nodeset.");
1803 RETURN_FALSE;
1804 }
1805 }
1806 } else {
1807 /*xpath query from xpath_array */
1808 HashTable *ht = Z_ARRVAL_P(xpath_array);
1809 zval **tmp;
1810 char *xquery;
1811
1812 if (zend_hash_find(ht, "query", sizeof("query"), (void**)&tmp) == SUCCESS &&
1813 Z_TYPE_PP(tmp) == IS_STRING) {
1814 xquery = Z_STRVAL_PP(tmp);
1815 } else {
1816 php_error_docref(NULL TSRMLS_CC, E_WARNING, "'query' missing from xpath array or is not a string");
1817 RETURN_FALSE;
1818 }
1819
1820 ctxp = xmlXPathNewContext(docp);
1821 ctxp->node = nodep;
1822
1823 if (zend_hash_find(ht, "namespaces", sizeof("namespaces"), (void**)&tmp) == SUCCESS &&
1824 Z_TYPE_PP(tmp) == IS_ARRAY) {
1825 zval **tmpns;
1826 while (zend_hash_get_current_data(Z_ARRVAL_PP(tmp), (void **)&tmpns) == SUCCESS) {
1827 if (Z_TYPE_PP(tmpns) == IS_STRING) {
1828 char *prefix;
1829 ulong idx;
1830 uint prefix_key_len;
1831
1832 if (zend_hash_get_current_key_ex(Z_ARRVAL_PP(tmp),
1833 &prefix, &prefix_key_len, &idx, 0, NULL) == HASH_KEY_IS_STRING) {
1834 xmlXPathRegisterNs(ctxp, prefix, Z_STRVAL_PP(tmpns));
1835 }
1836 }
1837 zend_hash_move_forward(Z_ARRVAL_PP(tmp));
1838 }
1839 }
1840
1841 xpathobjp = xmlXPathEvalExpression(xquery, ctxp);
1842 ctxp->node = NULL;
1843 if (xpathobjp && xpathobjp->type == XPATH_NODESET) {
1844 nodeset = xpathobjp->nodesetval;
1845 } else {
1846 if (xpathobjp) {
1847 xmlXPathFreeObject(xpathobjp);
1848 }
1849 xmlXPathFreeContext(ctxp);
1850 php_error_docref(NULL TSRMLS_CC, E_WARNING, "XPath query did not return a nodeset.");
1851 RETURN_FALSE;
1852 }
1853 }
1854
1855 if (ns_prefixes != NULL) {
1856 if (exclusive) {
1857 zval **tmpns;
1858 int nscount = 0;
1859
1860 inclusive_ns_prefixes = safe_emalloc(zend_hash_num_elements(Z_ARRVAL_P(ns_prefixes)) + 1,
1861 sizeof(xmlChar *), 0);
1862 while (zend_hash_get_current_data(Z_ARRVAL_P(ns_prefixes), (void **)&tmpns) == SUCCESS) {
1863 if (Z_TYPE_PP(tmpns) == IS_STRING) {
1864 inclusive_ns_prefixes[nscount++] = Z_STRVAL_PP(tmpns);
1865 }
1866 zend_hash_move_forward(Z_ARRVAL_P(ns_prefixes));
1867 }
1868 inclusive_ns_prefixes[nscount] = NULL;
1869 } else {
1870 php_error_docref(NULL TSRMLS_CC, E_NOTICE,
1871 "Inclusive namespace prefixes only allowed in exclusive mode.");
1872 }
1873 }
1874
1875 if (mode == 1) {
1876 buf = xmlOutputBufferCreateFilename(file, NULL, 0);
1877 } else {
1878 buf = xmlAllocOutputBuffer(NULL);
1879 }
1880
1881 if (buf != NULL) {
1882 ret = xmlC14NDocSaveTo(docp, nodeset, exclusive, inclusive_ns_prefixes,
1883 with_comments, buf);
1884 }
1885
1886 if (inclusive_ns_prefixes != NULL) {
1887 efree(inclusive_ns_prefixes);
1888 }
1889 if (xpathobjp != NULL) {
1890 xmlXPathFreeObject(xpathobjp);
1891 }
1892 if (ctxp != NULL) {
1893 xmlXPathFreeContext(ctxp);
1894 }
1895
1896 if (buf == NULL || ret < 0) {
1897 RETVAL_FALSE;
1898 } else {
1899 if (mode == 0) {
1900 #ifdef LIBXML2_NEW_BUFFER
1901 ret = xmlOutputBufferGetSize(buf);
1902 #else
1903 ret = buf->buffer->use;
1904 #endif
1905 if (ret > 0) {
1906 #ifdef LIBXML2_NEW_BUFFER
1907 RETVAL_STRINGL((char *) xmlOutputBufferGetContent(buf), ret, 1);
1908 #else
1909 RETVAL_STRINGL((char *) buf->buffer->content, ret, 1);
1910 #endif
1911 } else {
1912 RETVAL_EMPTY_STRING();
1913 }
1914 }
1915 }
1916
1917 if (buf) {
1918 int bytes;
1919
1920 bytes = xmlOutputBufferClose(buf);
1921 if (mode == 1 && (ret >= 0)) {
1922 RETURN_LONG(bytes);
1923 }
1924 }
1925 }
1926 /* }}} */
1927
1928 /* {{{ proto string DOMNode::C14N([bool exclusive [, bool with_comments [, array xpath [, array ns_prefixes]]]])
1929 Canonicalize nodes to a string */
PHP_METHOD(domnode,C14N)1930 PHP_METHOD(domnode, C14N)
1931 {
1932 dom_canonicalization(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1933 }
1934 /* }}} */
1935
1936 /* {{{ proto int DOMNode::C14NFile(string uri [, bool exclusive [, bool with_comments [, array xpath [, array ns_prefixes]]]])
1937 Canonicalize nodes to a file */
PHP_METHOD(domnode,C14NFile)1938 PHP_METHOD(domnode, C14NFile)
1939 {
1940 dom_canonicalization(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1941 }
1942 /* }}} */
1943
1944 /* {{{ proto int DOMNode::getNodePath()
1945 Gets an xpath for a node */
PHP_METHOD(domnode,getNodePath)1946 PHP_METHOD(domnode, getNodePath)
1947 {
1948 zval *id;
1949 xmlNode *nodep;
1950 dom_object *intern;
1951 char *value;
1952
1953 DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern);
1954
1955 value = xmlGetNodePath(nodep);
1956 if (value == NULL) {
1957 RETURN_NULL();
1958 } else {
1959 RETVAL_STRING(value, 1);
1960 xmlFree(value);
1961 }
1962 }
1963 /* }}} */
1964
1965 /* {{{ proto int DOMNode::getLineNo()
1966 Gets line number for a node */
PHP_METHOD(domnode,getLineNo)1967 PHP_METHOD(domnode, getLineNo)
1968 {
1969 zval *id;
1970 xmlNode *nodep;
1971 dom_object *intern;
1972
1973 if (zend_parse_parameters_none() == FAILURE) {
1974 return;
1975 }
1976
1977 DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern);
1978
1979 RETURN_LONG(xmlGetLineNo(nodep));
1980 }
1981 /* }}} */
1982
1983 #endif
1984
1985 /*
1986 * Local variables:
1987 * tab-width: 4
1988 * c-basic-offset: 4
1989 * End:
1990 * vim600: noet sw=4 ts=4 fdm=marker
1991 * vim<600: noet sw=4 ts=4
1992 */
1993