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