PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/simplexml - simplexml.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 1128 1317 85.6 %
Date: 2022-01-21 Functions: 74 75 98.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2018 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Authors: Sterling Hughes <sterling@php.net>                          |
      16             :   |          Marcus Boerger <helly@php.net>                              |
      17             :   |          Rob Richards <rrichards@php.net>                            |
      18             :   +----------------------------------------------------------------------+
      19             : */
      20             : 
      21             : /* $Id: 341daed0ee94ea8f728bfd0ba4626e6ed365c0d1 $ */
      22             : 
      23             : #ifdef HAVE_CONFIG_H
      24             : #include "config.h"
      25             : #endif
      26             : 
      27             : #include "php.h"
      28             : #if HAVE_LIBXML && HAVE_SIMPLEXML
      29             : 
      30             : #include "php_ini.h"
      31             : #include "ext/standard/info.h"
      32             : #include "ext/standard/php_string.h"
      33             : #include "php_simplexml.h"
      34             : #include "php_simplexml_exports.h"
      35             : #include "zend_exceptions.h"
      36             : #include "zend_interfaces.h"
      37             : #include "sxe.h"
      38             : 
      39             : zend_class_entry *sxe_class_entry = NULL;
      40             : 
      41           0 : PHP_SXE_API zend_class_entry *sxe_get_element_class_entry() /* {{{ */
      42             : {
      43           0 :         return sxe_class_entry;
      44             : }
      45             : /* }}} */
      46             : 
      47             : #define SXE_ME(func, arg_info, flags) PHP_ME(simplexml_element, func, arg_info, flags)
      48             : #define SXE_MALIAS(func, alias, arg_info, flags) PHP_MALIAS(simplexml_element, func, alias, arg_info, flags)
      49             : 
      50             : #define SXE_METHOD(func) PHP_METHOD(simplexml_element, func)
      51             : 
      52             : static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function *fptr_count);
      53             : static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data);
      54             : static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data);
      55             : static zval *sxe_get_value(zval *z, zval *rv);
      56             : static void php_sxe_iterator_dtor(zend_object_iterator *iter);
      57             : static int php_sxe_iterator_valid(zend_object_iterator *iter);
      58             : static zval *php_sxe_iterator_current_data(zend_object_iterator *iter);
      59             : static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key);
      60             : static void php_sxe_iterator_move_forward(zend_object_iterator *iter);
      61             : static void php_sxe_iterator_rewind(zend_object_iterator *iter);
      62             : 
      63             : /* {{{ _node_as_zval()
      64             :  */
      65      401239 : static void _node_as_zval(php_sxe_object *sxe, xmlNodePtr node, zval *value, SXE_ITER itertype, char *name, const xmlChar *nsprefix, int isprefix)
      66             : {
      67             :         php_sxe_object *subnode;
      68             : 
      69      401239 :         subnode = php_sxe_object_new(sxe->zo.ce, sxe->fptr_count);
      70      401239 :         subnode->document = sxe->document;
      71      401239 :         subnode->document->refcount++;
      72      401239 :         subnode->iter.type = itertype;
      73      401239 :         if (name) {
      74      200370 :                 subnode->iter.name = (xmlChar*)estrdup(name);
      75             :         }
      76      401239 :         if (nsprefix && *nsprefix) {
      77         132 :                 subnode->iter.nsprefix = (xmlChar*)estrdup((char*)nsprefix);
      78         132 :                 subnode->iter.isprefix = isprefix;
      79             :         }
      80             : 
      81      401239 :         php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL);
      82             : 
      83      401239 :         ZVAL_OBJ(value, &subnode->zo);
      84      401239 : }
      85             : /* }}} */
      86             : 
      87             : #define GET_NODE(__s, __n) { \
      88             :         if ((__s)->node && (__s)->node->node) { \
      89             :                 __n = (__s)->node->node; \
      90             :         } else { \
      91             :                 __n = NULL; \
      92             :                 php_error_docref(NULL, E_WARNING, "Node no longer exists"); \
      93             :         } \
      94             : }
      95             : 
      96      401353 : static xmlNodePtr php_sxe_get_first_node(php_sxe_object *sxe, xmlNodePtr node) /* {{{ */
      97             : {
      98             :         php_sxe_object *intern;
      99      401353 :         xmlNodePtr retnode = NULL;
     100             : 
     101      401353 :         if (sxe && sxe->iter.type != SXE_ITER_NONE) {
     102      200459 :                 php_sxe_reset_iterator(sxe, 1);
     103      400918 :                 if (!Z_ISUNDEF(sxe->iter.data)) {
     104      200407 :                         intern = Z_SXEOBJ_P(&sxe->iter.data);
     105      200407 :                         GET_NODE(intern, retnode)
     106             :                 }
     107      200459 :                 return retnode;
     108             :         } else {
     109      200894 :                 return node;
     110             :         }
     111             : }
     112             : /* }}} */
     113             : 
     114      201283 : static inline int match_ns(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name, int prefix) /* {{{ */
     115             : {
     116      201283 :         if (name == NULL && (node->ns == NULL || node->ns->prefix == NULL)) {
     117      201160 :                 return 1;
     118             :         }
     119             : 
     120         123 :         if (node->ns && !xmlStrcmp(prefix ? node->ns->prefix : node->ns->href, name)) {
     121          70 :                 return 1;
     122             :         }
     123             : 
     124          53 :         return 0;
     125             : }
     126             : /* }}} */
     127             : 
     128         112 : static xmlNodePtr sxe_get_element_by_offset(php_sxe_object *sxe, zend_long offset, xmlNodePtr node, zend_long *cnt) /* {{{ */
     129             : {
     130         112 :         zend_long nodendx = 0;
     131             : 
     132         112 :         if (sxe->iter.type == SXE_ITER_NONE) {
     133           0 :                 if (offset == 0) {
     134           0 :                         if (cnt) {
     135           0 :                                 *cnt = 0;
     136             :                         }
     137           0 :                         return node;
     138             :                 } else {
     139           0 :                         return NULL;
     140             :                 }
     141             :         }
     142         353 :         while (node && nodendx <= offset) {
     143         227 :                 SKIP_TEXT(node)
     144         334 :                 if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     145         332 :                         if (sxe->iter.type == SXE_ITER_CHILD || (
     146         332 :                                 sxe->iter.type == SXE_ITER_ELEMENT && !xmlStrcmp(node->name, sxe->iter.name))) {
     147         162 :                                 if (nodendx == offset) {
     148          98 :                                         break;
     149             :                                 }
     150          64 :                                 nodendx++;
     151             :                         }
     152             :                 }
     153         134 : next_iter:
     154         129 :                 node = node->next;
     155             :         }
     156             : 
     157         112 :         if (cnt) {
     158         103 :                 *cnt = nodendx;
     159             :         }
     160             : 
     161         112 :         return node;
     162             : }
     163             : /* }}} */
     164             : 
     165          66 : static xmlNodePtr sxe_find_element_by_name(php_sxe_object *sxe, xmlNodePtr node, xmlChar *name) /* {{{ */
     166             : {
     167         296 :         while (node) {
     168         210 :                 SKIP_TEXT(node)
     169         107 :                 if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     170          99 :                         if (!xmlStrcmp(node->name, name)) {
     171          46 :                                 return node;
     172             :                         }
     173             :                 }
     174          61 : next_iter:
     175         164 :                 node = node->next;
     176             :         }
     177          20 :         return NULL;
     178             : } /* }}} */
     179             : 
     180          40 : static xmlNodePtr sxe_get_element_by_name(php_sxe_object *sxe, xmlNodePtr node, char **name, SXE_ITER *type) /* {{{ */
     181             : {
     182             :         int         orgtype;
     183          40 :         xmlNodePtr  orgnode = node;
     184          40 :         xmlNodePtr  retnode = NULL;
     185             : 
     186          40 :         if (sxe->iter.type != SXE_ITER_ATTRLIST)
     187             :         {
     188          40 :                 orgtype = sxe->iter.type;
     189          40 :                 if (sxe->iter.type == SXE_ITER_NONE) {
     190          40 :                         sxe->iter.type = SXE_ITER_CHILD;
     191             :                 }
     192          40 :                 node = php_sxe_get_first_node(sxe, node);
     193          40 :                 sxe->iter.type = orgtype;
     194             :         }
     195             : 
     196          40 :         if (sxe->iter.type == SXE_ITER_ELEMENT) {
     197           0 :                 orgnode = sxe_find_element_by_name(sxe, node, sxe->iter.name);
     198           0 :                 if (!orgnode) {
     199           0 :                         return NULL;
     200             :                 }
     201           0 :                 node = orgnode->children;
     202             :         }
     203             : 
     204          89 :         while (node) {
     205          37 :                 SKIP_TEXT(node)
     206          33 :                 if (node->type == XML_ELEMENT_NODE && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     207          33 :                         if (!xmlStrcmp(node->name, (xmlChar *)*name)) {
     208             :                                 if (1||retnode)
     209             :                                 {
     210          28 :                                         *type = SXE_ITER_ELEMENT;
     211          28 :                                         return orgnode;
     212             :                                 }
     213             :                                 retnode = node;
     214             :                         }
     215             :                 }
     216           5 : next_iter:
     217           9 :                 node = node->next;
     218             :         }
     219             : 
     220          12 :         if (retnode)
     221             :         {
     222           0 :                 *type = SXE_ITER_NONE;
     223           0 :                 *name = NULL;
     224           0 :                 return retnode;
     225             :         }
     226             : 
     227          12 :         return NULL;
     228             : }
     229             : /* }}} */
     230             : 
     231             : /* {{{ sxe_prop_dim_read()
     232             :  */
     233      200537 : static zval *sxe_prop_dim_read(zval *object, zval *member, zend_bool elements, zend_bool attribs, int type, zval *rv)
     234             : {
     235             :         php_sxe_object *sxe;
     236             :         char           *name;
     237             :         xmlNodePtr      node;
     238      200537 :         xmlAttrPtr      attr = NULL;
     239             :         zval            tmp_zv;
     240      200537 :         int             nodendx = 0;
     241      200537 :         int             test = 0;
     242             : 
     243      200537 :         sxe = Z_SXEOBJ_P(object);
     244             : 
     245      200537 :         if (!member) {
     246           2 :                 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
     247             :                         /* This happens when the user did: $sxe[]->foo = $value */
     248           0 :                         zend_throw_error(NULL, "Cannot create unnamed attribute");
     249           0 :                         return &EG(uninitialized_zval);
     250             :                 }
     251           2 :                 goto long_dim;
     252             :         } else {
     253      200535 :                 ZVAL_DEREF(member);
     254      200535 :                 if (Z_TYPE_P(member) == IS_LONG) {
     255         102 :                         if (sxe->iter.type != SXE_ITER_ATTRLIST) {
     256         102 : long_dim:
     257         104 :                                 attribs = 0;
     258         104 :                                 elements = 1;
     259             :                         }
     260         104 :                         name = NULL;
     261             :                 } else {
     262      200433 :                         if (Z_TYPE_P(member) != IS_STRING) {
     263           0 :                                 ZVAL_STR(&tmp_zv, zval_get_string(member));
     264           0 :                                 member = &tmp_zv;
     265             :                         }
     266      200433 :                         name = Z_STRVAL_P(member);
     267             :                 }
     268             :         }
     269             : 
     270      200537 :         GET_NODE(sxe, node);
     271             : 
     272      200537 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
     273           5 :                 attribs = 1;
     274           5 :                 elements = 0;
     275           5 :                 node = php_sxe_get_first_node(sxe, node);
     276           5 :                 attr = (xmlAttrPtr)node;
     277           5 :                 test = sxe->iter.name != NULL;
     278      200532 :         } else if (sxe->iter.type != SXE_ITER_CHILD) {
     279      200502 :                 node = php_sxe_get_first_node(sxe, node);
     280      200502 :                 attr = node ? node->properties : NULL;
     281      200502 :                 test = 0;
     282      200504 :                 if (!member && node && node->parent &&
     283           2 :                     node->parent->type == XML_DOCUMENT_NODE) {
     284             :                         /* This happens when the user did: $sxe[]->foo = $value */
     285           0 :                         zend_throw_error(NULL, "Cannot create unnamed attribute");
     286           0 :                         return &EG(uninitialized_zval);
     287             :                 }
     288             :         }
     289             : 
     290      200537 :         ZVAL_UNDEF(rv);
     291             : 
     292      200537 :         if (node) {
     293      200529 :                 if (attribs) {
     294          78 :                         if (Z_TYPE_P(member) != IS_LONG || sxe->iter.type == SXE_ITER_ATTRLIST) {
     295          78 :                                 if (Z_TYPE_P(member) == IS_LONG) {
     296           0 :                                         while (attr && nodendx <= Z_LVAL_P(member)) {
     297           0 :                                                 if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     298           0 :                                                         if (nodendx == Z_LVAL_P(member)) {
     299           0 :                                                                 _node_as_zval(sxe, (xmlNodePtr) attr, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
     300           0 :                                                                 break;
     301             :                                                         }
     302           0 :                                                         nodendx++;
     303             :                                                 }
     304           0 :                                                 attr = attr->next;
     305             :                                         }
     306             :                                 } else {
     307         174 :                                         while (attr) {
     308          84 :                                                 if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)name) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     309          66 :                                                         _node_as_zval(sxe, (xmlNodePtr) attr, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
     310          66 :                                                         break;
     311             :                                                 }
     312          18 :                                                 attr = attr->next;
     313             :                                         }
     314             :                                 }
     315             :                         }
     316             :                 }
     317             : 
     318      200529 :                 if (elements) {
     319      200451 :                         if (!sxe->node) {
     320           0 :                                 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, node, NULL);
     321             :                         }
     322      401004 :                         if (!member || Z_TYPE_P(member) == IS_LONG) {
     323         104 :                                 zend_long cnt = 0;
     324         104 :                                 xmlNodePtr mynode = node;
     325             : 
     326         104 :                                 if (sxe->iter.type == SXE_ITER_CHILD) {
     327           0 :                                         node = php_sxe_get_first_node(sxe, node);
     328             :                                 }
     329         104 :                                 if (sxe->iter.type == SXE_ITER_NONE) {
     330           4 :                                         if (member && Z_LVAL_P(member) > 0) {
     331           0 :                                                 php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only 0 such elements exist", mynode->name, Z_LVAL_P(member));
     332             :                                         }
     333         100 :                                 } else if (member) {
     334         100 :                                         node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
     335             :                                 } else {
     336           0 :                                         node = NULL;
     337             :                                 }
     338         104 :                                 if (node) {
     339          96 :                                         _node_as_zval(sxe, node, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
     340           8 :                                 } else if (type == BP_VAR_W || type == BP_VAR_RW) {
     341           1 :                                         if (member && cnt < Z_LVAL_P(member)) {
     342           0 :                                                 php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only " ZEND_LONG_FMT " such elements exist", mynode->name, Z_LVAL_P(member), cnt);
     343             :                                         }
     344           1 :                                         node = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, NULL);
     345           1 :                                         _node_as_zval(sxe, node, rv, SXE_ITER_NONE, NULL, sxe->iter.nsprefix, sxe->iter.isprefix);
     346             :                                 }
     347             :                         } else {
     348             :                                 /* In BP_VAR_IS mode only return a proper node if it actually exists. */
     349      200347 :                                 if (type != BP_VAR_IS || sxe_find_element_by_name(sxe, node->children, (xmlChar *) name)) {
     350      200339 :                                         _node_as_zval(sxe, node, rv, SXE_ITER_ELEMENT, name, sxe->iter.nsprefix, sxe->iter.isprefix);
     351             :                                 }
     352             :                         }
     353             :                 }
     354             :         }
     355             : 
     356      200537 :         if (member == &tmp_zv) {
     357             :                 zval_dtor(&tmp_zv);
     358             :         }
     359             : 
     360      200537 :         if (Z_ISUNDEF_P(rv)) {
     361          35 :                 ZVAL_COPY_VALUE(rv, &EG(uninitialized_zval));
     362             :         }
     363             : 
     364      200537 :         return rv;
     365             : }
     366             : /* }}} */
     367             : 
     368             : /* {{{ sxe_property_read()
     369             :  */
     370      200352 : static zval *sxe_property_read(zval *object, zval *member, int type, void **cache_slot, zval *rv)
     371             : {
     372      200352 :         return sxe_prop_dim_read(object, member, 1, 0, type, rv);
     373             : }
     374             : /* }}} */
     375             : 
     376             : /* {{{ sxe_dimension_read()
     377             :  */
     378         185 : static zval *sxe_dimension_read(zval *object, zval *offset, int type, zval *rv)
     379             : {
     380         185 :         return sxe_prop_dim_read(object, offset, 0, 1, type, rv);
     381             : }
     382             : /* }}} */
     383             : 
     384             : /* {{{ change_node_zval()
     385             :  */
     386          27 : static void change_node_zval(xmlNodePtr node, zval *value)
     387             : {
     388             :         zval value_copy;
     389             :         xmlChar *buffer;
     390             :         int buffer_len;
     391             : 
     392          27 :         if (!value)
     393             :         {
     394           0 :                 xmlNodeSetContentLen(node, (xmlChar *)"", 0);
     395           0 :                 return;
     396             :         }
     397          27 :         switch (Z_TYPE_P(value)) {
     398           0 :                 case IS_LONG:
     399             :                 case IS_FALSE:
     400             :                 case IS_TRUE:
     401             :                 case IS_DOUBLE:
     402             :                 case IS_NULL:
     403           0 :                         if (Z_REFCOUNT_P(value) > 1) {
     404           0 :                                 value_copy = *value;
     405             :                                 zval_copy_ctor(&value_copy);
     406           0 :                                 value = &value_copy;
     407             :                         }
     408           0 :                         convert_to_string(value);
     409             :                         /* break missing intentionally */
     410             :                 case IS_STRING:
     411          27 :                         buffer = xmlEncodeEntitiesReentrant(node->doc, (xmlChar *)Z_STRVAL_P(value));
     412          27 :                         buffer_len = xmlStrlen(buffer);
     413             :                         /* check for NULL buffer in case of memory error in xmlEncodeEntitiesReentrant */
     414          27 :                         if (buffer) {
     415          27 :                                 xmlNodeSetContentLen(node, buffer, buffer_len);
     416          27 :                                 xmlFree(buffer);
     417             :                         }
     418          27 :                         if (value == &value_copy) {
     419             :                                 zval_dtor(value);
     420             :                         }
     421          27 :                         break;
     422           0 :                 default:
     423           0 :                         php_error_docref(NULL, E_WARNING, "It is not possible to assign complex types to nodes");
     424           0 :                         break;
     425             :         }
     426             : }
     427             : /* }}} */
     428             : 
     429             : /* {{{ sxe_property_write()
     430             :  */
     431          76 : static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool elements, zend_bool attribs, xmlNodePtr *pnewnode)
     432             : {
     433             :         php_sxe_object *sxe;
     434             :         xmlNodePtr      node;
     435          76 :         xmlNodePtr      newnode = NULL;
     436             :         xmlNodePtr      mynode;
     437             :         xmlNodePtr              tempnode;
     438          76 :         xmlAttrPtr      attr = NULL;
     439          76 :         int             counter = 0;
     440          76 :         int             is_attr = 0;
     441          76 :         int                             nodendx = 0;
     442          76 :         int             test = 0;
     443          76 :         int                             new_value = 0;
     444          76 :         zend_long            cnt = 0;
     445          76 :         int                             retval = SUCCESS;
     446             :         zval            tmp_zv, zval_copy;
     447             :         zend_string    *trim_str;
     448             : 
     449          76 :         sxe = Z_SXEOBJ_P(object);
     450             : 
     451          76 :         if (!member) {
     452           1 :                 if (sxe->iter.type == SXE_ITER_ATTRLIST) {
     453             :                         /* This happens when the user did: $sxe[] = $value
     454             :                          * and could also be E_PARSE, but we use this only during parsing
     455             :                          * and this is during runtime.
     456             :                          */
     457           0 :                         zend_throw_error(NULL, "Cannot create unnamed attribute");
     458           0 :                         return FAILURE;
     459             :                 }
     460           1 :                 goto long_dim;
     461             :         } else {
     462          75 :                 ZVAL_DEREF(member);
     463          75 :                 if (Z_TYPE_P(member) == IS_LONG) {
     464           5 :                         if (sxe->iter.type != SXE_ITER_ATTRLIST) {
     465           5 : long_dim:
     466           6 :                                 attribs = 0;
     467           6 :                                 elements = 1;
     468             :                         }
     469             :                 } else {
     470          70 :                         if (Z_TYPE_P(member) != IS_STRING) {
     471           1 :                                 trim_str = zval_get_string(member);
     472           1 :                                 ZVAL_STR(&tmp_zv, php_trim(trim_str, NULL, 0, 3));
     473             :                                 zend_string_release(trim_str);
     474           1 :                                 member = &tmp_zv;
     475             :                         }
     476             : 
     477          70 :                         if (!Z_STRLEN_P(member)) {
     478           3 :                                 php_error_docref(NULL, E_WARNING, "Cannot write or create unnamed %s", attribs ? "attribute" : "element");
     479           3 :                                 if (member == &tmp_zv) {
     480             :                                         zval_dtor(&tmp_zv);
     481             :                                 }
     482           3 :                                 return FAILURE;
     483             :                         }
     484             :                 }
     485             :         }
     486             : 
     487          73 :         GET_NODE(sxe, node);
     488             : 
     489          73 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
     490           0 :                 attribs = 1;
     491           0 :                 elements = 0;
     492           0 :                 node = php_sxe_get_first_node(sxe, node);
     493           0 :                 attr = (xmlAttrPtr)node;
     494           0 :                 test = sxe->iter.name != NULL;
     495          73 :         } else if (sxe->iter.type != SXE_ITER_CHILD) {
     496          72 :                 mynode = node;
     497          72 :                 node = php_sxe_get_first_node(sxe, node);
     498          72 :                 attr = node ? node->properties : NULL;
     499          72 :                 test = 0;
     500          73 :                 if (!member && node && node->parent &&
     501           1 :                     node->parent->type == XML_DOCUMENT_NODE) {
     502             :                         /* This happens when the user did: $sxe[] = $value
     503             :                          * and could also be E_PARSE, but we use this only during parsing
     504             :                          * and this is during runtime.
     505             :                          */
     506           1 :                         zend_throw_error(NULL, "Cannot create unnamed attribute");
     507           1 :                         return FAILURE;
     508             :                 }
     509          71 :                 if (attribs && !node && sxe->iter.type == SXE_ITER_ELEMENT) {
     510           0 :                         node = xmlNewChild(mynode, mynode->ns, sxe->iter.name, NULL);
     511           0 :                         attr = node->properties;
     512             :                 }
     513             :         }
     514             : 
     515          72 :         mynode = node;
     516             : 
     517          72 :         if (value) {
     518          61 :                 switch (Z_TYPE_P(value)) {
     519          10 :                         case IS_LONG:
     520             :                         case IS_FALSE:
     521             :                         case IS_TRUE:
     522             :                         case IS_DOUBLE:
     523             :                         case IS_NULL:
     524          10 :                                 if (Z_TYPE_P(value) != IS_STRING) {
     525          10 :                                         ZVAL_COPY(&zval_copy, value);
     526          10 :                                         value = &zval_copy;
     527          10 :                                         convert_to_string(value);
     528          10 :                                         new_value = 1;
     529             :                                 }
     530          10 :                                 break;
     531          49 :                         case IS_STRING:
     532          49 :                                 break;
     533           2 :                         case IS_OBJECT:
     534           2 :                                 if (Z_OBJCE_P(value) == sxe_class_entry) {
     535           1 :                                         value = sxe_get_value(value, &zval_copy);
     536           1 :                                         new_value = 1;
     537           1 :                                         break;
     538             :                                 }
     539             :                                 /* break is missing intentionally */
     540             :                         default:
     541           1 :                                 if (member == &tmp_zv) {
     542             :                                         zval_dtor(&tmp_zv);
     543             :                                 }
     544           1 :                                 zend_error(E_WARNING, "It is not yet possible to assign complex types to %s", attribs ? "attributes" : "properties");
     545           1 :                                 return FAILURE;
     546             :                 }
     547          11 :         }
     548             : 
     549          71 :         if (node) {
     550          71 :                 if (attribs) {
     551          31 :                         if (Z_TYPE_P(member) == IS_LONG) {
     552           0 :                                 while (attr && nodendx <= Z_LVAL_P(member)) {
     553           0 :                                         if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     554           0 :                                                 if (nodendx == Z_LVAL_P(member)) {
     555           0 :                                                         is_attr = 1;
     556           0 :                                                         ++counter;
     557           0 :                                                         break;
     558             :                                                 }
     559           0 :                                                 nodendx++;
     560             :                                         }
     561           0 :                                         attr = attr->next;
     562             :                                 }
     563             :                         } else {
     564          77 :                                 while (attr) {
     565          30 :                                         if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     566          15 :                                                 is_attr = 1;
     567          15 :                                                 ++counter;
     568          15 :                                                 break;
     569             :                                         }
     570          15 :                                         attr = attr->next;
     571             :                                 }
     572             :                         }
     573             : 
     574             :                 }
     575             : 
     576          71 :                 if (elements) {
     577          80 :                         if (!member || Z_TYPE_P(member) == IS_LONG) {
     578           5 :                                 if (node->type == XML_ATTRIBUTE_NODE) {
     579           0 :                                         zend_throw_error(NULL, "Cannot create duplicate attribute");
     580           0 :                                         if (new_value) {
     581           0 :                                                 zval_ptr_dtor(value);
     582             :                                         }
     583           0 :                                         return FAILURE;
     584             :                                 }
     585             : 
     586          10 :                                 if (sxe->iter.type == SXE_ITER_NONE) {
     587           2 :                                         newnode = node;
     588           2 :                                         ++counter;
     589           2 :                                         if (member && Z_LVAL_P(member) > 0) {
     590           0 :                                                 php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only 0 such elements exist", mynode->name, Z_LVAL_P(member));
     591           0 :                                                 retval = FAILURE;
     592             :                                         }
     593           3 :                                 } else if (member) {
     594           3 :                                         newnode = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, &cnt);
     595           3 :                                         if (newnode) {
     596           0 :                                                 ++counter;
     597             :                                         }
     598             :                                 }
     599             :                         } else {
     600          35 :                                 node = node->children;
     601         140 :                                 while (node) {
     602          70 :                                         SKIP_TEXT(node);
     603             : 
     604          51 :                                         if (!xmlStrcmp(node->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     605          10 :                                                 newnode = node;
     606          10 :                                                 ++counter;
     607             :                                         }
     608             : 
     609          99 : next_iter:
     610          70 :                                         node = node->next;
     611             :                                 }
     612             :                         }
     613             :                 }
     614             : 
     615          71 :                 if (counter == 1) {
     616          27 :                         if (is_attr) {
     617          15 :                                 newnode = (xmlNodePtr) attr;
     618             :                         }
     619          27 :                         if (value) {
     620          79 :                                 while ((tempnode = (xmlNodePtr) newnode->children)) {
     621          25 :                                         xmlUnlinkNode(tempnode);
     622          25 :                                         php_libxml_node_free_resource((xmlNodePtr) tempnode);
     623             :                                 }
     624          27 :                                 change_node_zval(newnode, value);
     625             :                         }
     626          44 :                 } else if (counter > 1) {
     627           0 :                         php_error_docref(NULL, E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)");
     628           0 :                         retval = FAILURE;
     629          44 :                 } else if (elements) {
     630          28 :                         if (!node) {
     631          50 :                                 if (!member || Z_TYPE_P(member) == IS_LONG) {
     632           0 :                                         newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
     633             :                                 } else {
     634          25 :                                         newnode = xmlNewTextChild(mynode, mynode->ns, (xmlChar *)Z_STRVAL_P(member), value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
     635             :                                 }
     636           6 :                         } else if (!member || Z_TYPE_P(member) == IS_LONG) {
     637           3 :                                 if (member && cnt < Z_LVAL_P(member)) {
     638           1 :                                         php_error_docref(NULL, E_WARNING, "Cannot add element %s number " ZEND_LONG_FMT " when only " ZEND_LONG_FMT " such elements exist", mynode->name, Z_LVAL_P(member), cnt);
     639           1 :                                         retval = FAILURE;
     640             :                                 }
     641           3 :                                 newnode = xmlNewTextChild(mynode->parent, mynode->ns, mynode->name, value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
     642             :                         }
     643          16 :                 } else if (attribs) {
     644          16 :                         if (Z_TYPE_P(member) == IS_LONG) {
     645           0 :                                 php_error_docref(NULL, E_WARNING, "Cannot change attribute number " ZEND_LONG_FMT " when only %d attributes exist", Z_LVAL_P(member), nodendx);
     646           0 :                                 retval = FAILURE;
     647             :                         } else {
     648          16 :                                 newnode = (xmlNodePtr)xmlNewProp(node, (xmlChar *)Z_STRVAL_P(member), value ? (xmlChar *)Z_STRVAL_P(value) : NULL);
     649             :                         }
     650             :                 }
     651             :         }
     652             : 
     653          71 :         if (member == &tmp_zv) {
     654             :                 zval_dtor(&tmp_zv);
     655             :         }
     656          71 :         if (pnewnode) {
     657          11 :                 *pnewnode = newnode;
     658             :         }
     659          71 :         if (new_value) {
     660          11 :                 zval_ptr_dtor(value);
     661             :         }
     662          71 :         return retval;
     663             : }
     664             : /* }}} */
     665             : 
     666             : /* {{{ sxe_property_write()
     667             :  */
     668          26 : static void sxe_property_write(zval *object, zval *member, zval *value, void **cache_slot)
     669             : {
     670          26 :         sxe_prop_dim_write(object, member, value, 1, 0, NULL);
     671          26 : }
     672             : /* }}} */
     673             : 
     674             : /* {{{ sxe_dimension_write()
     675             :  */
     676          38 : static void sxe_dimension_write(zval *object, zval *offset, zval *value)
     677             : {
     678          38 :         sxe_prop_dim_write(object, offset, value, 0, 1, NULL);
     679          38 : }
     680             : /* }}} */
     681             : 
     682          40 : static zval *sxe_property_get_adr(zval *object, zval *member, int fetch_type, void **cache_slot) /* {{{ */
     683             : {
     684             :         php_sxe_object *sxe;
     685             :         xmlNodePtr      node;
     686             :         zval            ret;
     687             :         char           *name;
     688             :         SXE_ITER        type;
     689             : 
     690          40 :         sxe = Z_SXEOBJ_P(object);
     691             : 
     692          40 :         GET_NODE(sxe, node);
     693          40 :         convert_to_string(member);
     694          40 :         name = Z_STRVAL_P(member);
     695          40 :         node = sxe_get_element_by_name(sxe, node, &name, &type);
     696          40 :         if (node) {
     697          28 :                 return NULL;
     698             :         }
     699          12 :         if (sxe_prop_dim_write(object, member, NULL, 1, 0, &node) != SUCCESS) {
     700           1 :                 return NULL;
     701             :         }
     702          11 :         type = SXE_ITER_NONE;
     703          11 :         name = NULL;
     704             : 
     705          11 :         _node_as_zval(sxe, node, &ret, type, name, sxe->iter.nsprefix, sxe->iter.isprefix);
     706             : 
     707          22 :         if (!Z_ISUNDEF(sxe->tmp)) {
     708           0 :                 zval_ptr_dtor(&sxe->tmp);
     709             :         }
     710             : 
     711          11 :         ZVAL_COPY_VALUE(&sxe->tmp, &ret);
     712             : 
     713          11 :         return &sxe->tmp;
     714             : }
     715             : /* }}} */
     716             : 
     717             : /* {{{ sxe_prop_dim_exists()
     718             :  */
     719          42 : static int sxe_prop_dim_exists(zval *object, zval *member, int check_empty, zend_bool elements, zend_bool attribs)
     720             : {
     721             :         php_sxe_object *sxe;
     722             :         xmlNodePtr      node;
     723          42 :         xmlAttrPtr      attr = NULL;
     724          42 :         int                             exists = 0;
     725          42 :         int             test = 0;
     726             :         zval            tmp_zv;
     727             : 
     728          53 :         if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
     729           2 :                 ZVAL_STR(&tmp_zv, zval_get_string(member));
     730           1 :                 member = &tmp_zv;
     731             :         }
     732             : 
     733          42 :         sxe = Z_SXEOBJ_P(object);
     734             : 
     735          42 :         GET_NODE(sxe, node);
     736             : 
     737          42 :         if (Z_TYPE_P(member) == IS_LONG) {
     738          10 :                 if (sxe->iter.type != SXE_ITER_ATTRLIST) {
     739           8 :                         attribs = 0;
     740           8 :                         elements = 1;
     741           8 :                         if (sxe->iter.type == SXE_ITER_CHILD) {
     742           0 :                                 node = php_sxe_get_first_node(sxe, node);
     743             :                         }
     744             :                 }
     745             :         }
     746             : 
     747          42 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
     748           3 :                 attribs = 1;
     749           3 :                 elements = 0;
     750           3 :                 node = php_sxe_get_first_node(sxe, node);
     751           3 :                 attr = (xmlAttrPtr)node;
     752           3 :                 test = sxe->iter.name != NULL;
     753          39 :         } else if (sxe->iter.type != SXE_ITER_CHILD) {
     754          39 :                 node = php_sxe_get_first_node(sxe, node);
     755          39 :                 attr = node ? node->properties : NULL;
     756          39 :                 test = 0;
     757             :         }
     758             : 
     759          42 :         if (node) {
     760          40 :                 if (attribs) {
     761           6 :                         if (Z_TYPE_P(member) == IS_LONG) {
     762           1 :                                 int     nodendx = 0;
     763             : 
     764           2 :                                 while (attr && nodendx <= Z_LVAL_P(member)) {
     765           1 :                                         if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     766           1 :                                                 if (nodendx == Z_LVAL_P(member)) {
     767           1 :                                                         exists = 1;
     768           1 :                                                         break;
     769             :                                                 }
     770           0 :                                                 nodendx++;
     771             :                                         }
     772           0 :                                         attr = attr->next;
     773             :                                 }
     774             :                         } else {
     775          13 :                                 while (attr) {
     776           5 :                                         if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     777           2 :                                                 exists = 1;
     778           2 :                                                 break;
     779             :                                         }
     780             : 
     781           3 :                                         attr = attr->next;
     782             :                                 }
     783             :                         }
     784           6 :                         if (exists && check_empty == 1 &&
     785           0 :                                 (!attr->children || !attr->children->content || !attr->children->content[0] || !xmlStrcmp(attr->children->content, (const xmlChar *) "0")) ) {
     786             :                                 /* Attribute with no content in it's text node */
     787           0 :                                 exists = 0;
     788             :                         }
     789             :                 }
     790             : 
     791          40 :                 if (elements) {
     792          34 :                         if (Z_TYPE_P(member) == IS_LONG) {
     793           8 :                                 if (sxe->iter.type == SXE_ITER_CHILD) {
     794           0 :                                         node = php_sxe_get_first_node(sxe, node);
     795             :                                 }
     796           8 :                                 node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
     797             :                         } else {
     798          26 :                                 node = sxe_find_element_by_name(sxe, node->children, (xmlChar *)Z_STRVAL_P(member));
     799             :                         }
     800          34 :                         if (node) {
     801          19 :                                 exists = 1;
     802          19 :                                 if (check_empty == 1 &&
     803           0 :                                         (!node->children || (node->children->type == XML_TEXT_NODE && !node->children->next &&
     804           0 :                                          (!node->children->content || !node->children->content[0] || !xmlStrcmp(node->children->content, (const xmlChar *) "0")))) ) {
     805           0 :                                         exists = 0;
     806             :                                 }
     807             :                         }
     808             :                 }
     809             :         }
     810             : 
     811          42 :         if (member == &tmp_zv) {
     812             :                 zval_dtor(&tmp_zv);
     813             :         }
     814             : 
     815          42 :         return exists;
     816             : }
     817             : /* }}} */
     818             : 
     819             : /* {{{ sxe_property_exists()
     820             :  */
     821          26 : static int sxe_property_exists(zval *object, zval *member, int check_empty, void **cache_slot)
     822             : {
     823          26 :         return sxe_prop_dim_exists(object, member, check_empty, 1, 0);
     824             : }
     825             : /* }}} */
     826             : 
     827             : /* {{{ sxe_dimension_exists()
     828             :  */
     829          16 : static int sxe_dimension_exists(zval *object, zval *member, int check_empty)
     830             : {
     831          16 :         return sxe_prop_dim_exists(object, member, check_empty, 0, 1);
     832             : }
     833             : /* }}} */
     834             : 
     835             : /* {{{ sxe_prop_dim_delete()
     836             :  */
     837           8 : static void sxe_prop_dim_delete(zval *object, zval *member, zend_bool elements, zend_bool attribs)
     838             : {
     839             :         php_sxe_object *sxe;
     840             :         xmlNodePtr      node;
     841             :         xmlNodePtr      nnext;
     842           8 :         xmlAttrPtr      attr = NULL;
     843             :         xmlAttrPtr      anext;
     844             :         zval            tmp_zv;
     845           8 :         int             test = 0;
     846             : 
     847          10 :         if (Z_TYPE_P(member) != IS_STRING && Z_TYPE_P(member) != IS_LONG) {
     848           0 :                 ZVAL_STR(&tmp_zv, zval_get_string(member));
     849           0 :                 member = &tmp_zv;
     850             :         }
     851             : 
     852           8 :         sxe = Z_SXEOBJ_P(object);
     853             : 
     854           8 :         GET_NODE(sxe, node);
     855             : 
     856           8 :         if (Z_TYPE_P(member) == IS_LONG) {
     857           2 :                 if (sxe->iter.type != SXE_ITER_ATTRLIST) {
     858           1 :                         attribs = 0;
     859           1 :                         elements = 1;
     860           1 :                         if (sxe->iter.type == SXE_ITER_CHILD) {
     861           0 :                                 node = php_sxe_get_first_node(sxe, node);
     862             :                         }
     863             :                 }
     864             :         }
     865             : 
     866           8 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
     867           1 :                 attribs = 1;
     868           1 :                 elements = 0;
     869           1 :                 node = php_sxe_get_first_node(sxe, node);
     870           1 :                 attr = (xmlAttrPtr)node;
     871           1 :                 test = sxe->iter.name != NULL;
     872           7 :         } else if (sxe->iter.type != SXE_ITER_CHILD) {
     873           7 :                 node = php_sxe_get_first_node(sxe, node);
     874           7 :                 attr = node ? node->properties : NULL;
     875           7 :                 test = 0;
     876             :         }
     877             : 
     878           8 :         if (node) {
     879           8 :                 if (attribs) {
     880           6 :                         if (Z_TYPE_P(member) == IS_LONG) {
     881           1 :                                 int     nodendx = 0;
     882             : 
     883           2 :                                 while (attr && nodendx <= Z_LVAL_P(member)) {
     884           1 :                                         if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     885           1 :                                                 if (nodendx == Z_LVAL_P(member)) {
     886           1 :                                                         xmlUnlinkNode((xmlNodePtr) attr);
     887           1 :                                                         php_libxml_node_free_resource((xmlNodePtr) attr);
     888           1 :                                                         break;
     889             :                                                 }
     890           0 :                                                 nodendx++;
     891             :                                         }
     892           0 :                                         attr = attr->next;
     893             :                                 }
     894             :                         } else {
     895          13 :                                 while (attr) {
     896           8 :                                         anext = attr->next;
     897           8 :                                         if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && !xmlStrcmp(attr->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, (xmlNodePtr) attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     898           5 :                                                 xmlUnlinkNode((xmlNodePtr) attr);
     899           5 :                                                 php_libxml_node_free_resource((xmlNodePtr) attr);
     900           5 :                                                 break;
     901             :                                         }
     902           3 :                                         attr = anext;
     903             :                                 }
     904             :                         }
     905             :                 }
     906             : 
     907           8 :                 if (elements) {
     908           2 :                         if (Z_TYPE_P(member) == IS_LONG) {
     909           1 :                                 if (sxe->iter.type == SXE_ITER_CHILD) {
     910           0 :                                         node = php_sxe_get_first_node(sxe, node);
     911             :                                 }
     912           1 :                                 node = sxe_get_element_by_offset(sxe, Z_LVAL_P(member), node, NULL);
     913           1 :                                 if (node) {
     914           1 :                                         xmlUnlinkNode(node);
     915           1 :                                         php_libxml_node_free_resource(node);
     916             :                                 }
     917             :                         } else {
     918           1 :                                 node = node->children;
     919           5 :                                 while (node) {
     920           3 :                                         nnext = node->next;
     921             : 
     922           3 :                                         SKIP_TEXT(node);
     923             : 
     924           5 :                                         if (!xmlStrcmp(node->name, (xmlChar *)Z_STRVAL_P(member)) && match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix)) {
     925           1 :                                                 xmlUnlinkNode(node);
     926           1 :                                                 php_libxml_node_free_resource(node);
     927             :                                         }
     928             : 
     929           5 : next_iter:
     930           3 :                                         node = nnext;
     931             :                                 }
     932             :                         }
     933             :                 }
     934             :         }
     935             : 
     936           8 :         if (member == &tmp_zv) {
     937             :                 zval_dtor(&tmp_zv);
     938             :         }
     939           8 : }
     940             : /* }}} */
     941             : 
     942             : /* {{{ sxe_property_delete()
     943             :  */
     944           1 : static void sxe_property_delete(zval *object, zval *member, void **cache_slot)
     945             : {
     946           1 :         sxe_prop_dim_delete(object, member, 1, 0);
     947           1 : }
     948             : /* }}} */
     949             : 
     950             : /* {{{ sxe_dimension_unset()
     951             :  */
     952           7 : static void sxe_dimension_delete(zval *object, zval *offset)
     953             : {
     954           7 :         sxe_prop_dim_delete(object, offset, 0, 1);
     955           7 : }
     956             : /* }}} */
     957             : 
     958         124 : static inline zend_string *sxe_xmlNodeListGetString(xmlDocPtr doc, xmlNodePtr list, int inLine) /* {{{ */
     959             : {
     960         124 :         xmlChar *tmp = xmlNodeListGetString(doc, list, inLine);
     961             :         zend_string *res;
     962             : 
     963         124 :         if (tmp) {
     964         246 :                 res = zend_string_init((char*)tmp, strlen((char *)tmp), 0);
     965         123 :                 xmlFree(tmp);
     966             :         } else {
     967           1 :                 res = ZSTR_EMPTY_ALLOC();
     968             :         }
     969             : 
     970         124 :         return res;
     971             : }
     972             : /* }}} */
     973             : 
     974             : /* {{{ _get_base_node_value()
     975             :  */
     976         193 : static void _get_base_node_value(php_sxe_object *sxe_ref, xmlNodePtr node, zval *value, xmlChar *nsprefix, int isprefix)
     977             : {
     978             :         php_sxe_object *subnode;
     979             :         xmlChar        *contents;
     980             : 
     981         193 :         if (node->children && node->children->type == XML_TEXT_NODE && !xmlIsBlankNode(node->children)) {
     982          51 :                 contents = xmlNodeListGetString(node->doc, node->children, 1);
     983         102 :                 if (contents) {
     984         102 :                         ZVAL_STRING(value, (char *)contents);
     985          51 :                         xmlFree(contents);
     986             :                 }
     987             :         } else {
     988         142 :                 subnode = php_sxe_object_new(sxe_ref->zo.ce, sxe_ref->fptr_count);
     989         142 :                 subnode->document = sxe_ref->document;
     990         142 :                 subnode->document->refcount++;
     991         142 :                 if (nsprefix && *nsprefix) {
     992           1 :                         subnode->iter.nsprefix = (xmlChar*)estrdup((char *)nsprefix);
     993           1 :                         subnode->iter.isprefix = isprefix;
     994             :                 }
     995         142 :                 php_libxml_increment_node_ptr((php_libxml_node_object *)subnode, node, NULL);
     996             : 
     997         142 :                 ZVAL_OBJ(value, &subnode->zo);
     998             :                 /*zval_add_ref(value);*/
     999             :         }
    1000         193 : }
    1001             : /* }}} */
    1002             : 
    1003         256 : static void sxe_properties_add(HashTable *rv, char *name, int namelen, zval *value) /* {{{ */
    1004             : {
    1005             :         zend_string *key;
    1006             :         zval  *data_ptr;
    1007             :         zval  newptr;
    1008             : 
    1009         512 :         key = zend_string_init(name, namelen, 0);
    1010         256 :         if ((data_ptr = zend_hash_find(rv, key)) != NULL) {
    1011           8 :                 if (Z_TYPE_P(data_ptr) == IS_ARRAY) {
    1012           2 :                         zend_hash_next_index_insert_new(Z_ARRVAL_P(data_ptr), value);
    1013             :                 } else {
    1014           6 :                         array_init(&newptr);
    1015           6 :                         zend_hash_next_index_insert_new(Z_ARRVAL(newptr), data_ptr);
    1016           6 :                         zend_hash_next_index_insert_new(Z_ARRVAL(newptr), value);
    1017           6 :                         ZVAL_ARR(data_ptr, Z_ARR(newptr));
    1018             :                 }
    1019             :         } else {
    1020         248 :                 zend_hash_add_new(rv, key, value);
    1021             :         }
    1022             :         zend_string_release(key);
    1023         256 : }
    1024             : /* }}} */
    1025             : 
    1026          19 : static int sxe_prop_is_empty(zval *object) /* {{{ */
    1027             : {
    1028             :         php_sxe_object  *sxe;
    1029             :         xmlNodePtr       node;
    1030             :         xmlAttrPtr       attr;
    1031             :         zval             iter_data;
    1032             :         int              test;
    1033             :         int              is_empty;
    1034             : 
    1035          19 :         sxe = Z_SXEOBJ_P(object);
    1036             : 
    1037          19 :         GET_NODE(sxe, node);
    1038          19 :         if (!node) {
    1039           0 :                 return 1;
    1040             :         }
    1041             : 
    1042          19 :         if (sxe->iter.type == SXE_ITER_ELEMENT) {
    1043           3 :                 node = php_sxe_get_first_node(sxe, node);
    1044             :         }
    1045          19 :         if (!node || node->type != XML_ENTITY_DECL) {
    1046          19 :                 attr = node ? (xmlAttrPtr)node->properties : NULL;
    1047          19 :                 test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST;
    1048          38 :                 while (attr) {
    1049           3 :                         if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr)attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
    1050           3 :                                 return 0;
    1051             :                         }
    1052           0 :                         attr = attr->next;
    1053             :                 }
    1054             :         }
    1055             : 
    1056          16 :         GET_NODE(sxe, node);
    1057          16 :         node = php_sxe_get_first_node(sxe, node);
    1058          16 :         is_empty = 1;
    1059          16 :         ZVAL_UNDEF(&iter_data);
    1060          16 :         if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
    1061          10 :                 if (node->type == XML_ATTRIBUTE_NODE) {
    1062           1 :                         return 0;
    1063           9 :                 } else if (sxe->iter.type != SXE_ITER_CHILD) {
    1064           9 :                         if (sxe->iter.type == SXE_ITER_NONE || !node->children || !node->parent || node->children->next || node->children->children || node->parent->children == node->parent->last) {
    1065           9 :                                 node = node->children;
    1066             :                         } else {
    1067           0 :                                 ZVAL_COPY_VALUE(&iter_data, &sxe->iter.data);
    1068           0 :                                 ZVAL_UNDEF(&sxe->iter.data);
    1069           0 :                                 node = php_sxe_reset_iterator(sxe, 0);
    1070             :                         }
    1071             :                 }
    1072             : 
    1073          20 :                 while (node) {
    1074          10 :                         if (node->children != NULL || node->prev != NULL || node->next != NULL) {
    1075           4 :                                 SKIP_TEXT(node);
    1076             :                         } else {
    1077           6 :                                 if (node->type == XML_TEXT_NODE) {
    1078           6 :                                         const xmlChar *cur = node->content;
    1079           6 :                                         if (*cur != 0) {
    1080           6 :                                                 is_empty = 0;
    1081           6 :                                                 break;
    1082             :                                         }
    1083           0 :                                         goto next_iter;
    1084             :                                 }
    1085             :                         }
    1086             : 
    1087           2 :                         if (node->type == XML_ELEMENT_NODE && (! match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix))) {
    1088           0 :                                 goto next_iter;
    1089             :                         }
    1090             : 
    1091           2 :                         if (!node->name) {
    1092           0 :                                 goto next_iter;
    1093             :                         }
    1094             : 
    1095           2 :                         is_empty = 0;
    1096           2 :                         break;
    1097           2 : next_iter:
    1098           2 :                         if (!Z_ISUNDEF(iter_data)) {
    1099           0 :                                 node = php_sxe_iterator_fetch(sxe, node->next, 0);
    1100             :                         } else {
    1101           2 :                                 node = node->next;
    1102             :                         }
    1103             :                 }
    1104             :         }
    1105             : 
    1106          15 :         if (!Z_ISUNDEF(iter_data)) {
    1107           0 :                 if (!Z_ISUNDEF(sxe->iter.data)) {
    1108           0 :                         zval_ptr_dtor(&sxe->iter.data);
    1109             :                 }
    1110           0 :                 ZVAL_COPY_VALUE(&sxe->iter.data, &iter_data);
    1111             :         }
    1112             : 
    1113          15 :         return is_empty;
    1114             : }
    1115             : /* }}} */
    1116             : 
    1117         273 : static HashTable *sxe_get_prop_hash(zval *object, int is_debug) /* {{{ */
    1118             : {
    1119             :         zval            value;
    1120             :         zval            zattr;
    1121             :         HashTable       *rv;
    1122             :         php_sxe_object  *sxe;
    1123             :         char            *name;
    1124             :         xmlNodePtr       node;
    1125             :         xmlAttrPtr       attr;
    1126             :         int              namelen;
    1127             :         int              test;
    1128             :         char                     use_iter;
    1129             :         zval             iter_data;
    1130             : 
    1131         273 :         use_iter = 0;
    1132             : 
    1133         273 :         sxe = Z_SXEOBJ_P(object);
    1134             : 
    1135         273 :         if (is_debug) {
    1136         247 :                 ALLOC_HASHTABLE(rv);
    1137         247 :                 zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
    1138          26 :         } else if (sxe->properties) {
    1139           0 :                 zend_hash_clean(sxe->properties);
    1140           0 :                 rv = sxe->properties;
    1141             :         } else {
    1142          26 :                 ALLOC_HASHTABLE(rv);
    1143          26 :                 zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
    1144          26 :                 sxe->properties = rv;
    1145             :         }
    1146             : 
    1147         273 :         GET_NODE(sxe, node);
    1148         273 :         if (!node) {
    1149           0 :                 return rv;
    1150             :         }
    1151         273 :         if (is_debug || sxe->iter.type != SXE_ITER_CHILD) {
    1152         273 :                 if (sxe->iter.type == SXE_ITER_ELEMENT) {
    1153          31 :                         node = php_sxe_get_first_node(sxe, node);
    1154             :                 }
    1155         273 :                 if (!node || node->type != XML_ENTITY_DECL) {
    1156         273 :                         attr = node ? (xmlAttrPtr)node->properties : NULL;
    1157         273 :                         ZVAL_UNDEF(&zattr);
    1158         273 :                         test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST;
    1159         662 :                         while (attr) {
    1160         116 :                                 if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr)attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
    1161          84 :                                         ZVAL_STR(&value, sxe_xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1));
    1162          84 :                                         namelen = xmlStrlen(attr->name);
    1163          84 :                                         if (Z_ISUNDEF(zattr)) {
    1164          75 :                                                 array_init(&zattr);
    1165          75 :                                                 sxe_properties_add(rv, "@attributes", sizeof("@attributes") - 1, &zattr);
    1166             :                                         }
    1167          84 :                                         add_assoc_zval_ex(&zattr, (char*)attr->name, namelen, &value);
    1168             :                                 }
    1169         116 :                                 attr = attr->next;
    1170             :                         }
    1171             :                 }
    1172             :         }
    1173             : 
    1174         273 :         GET_NODE(sxe, node);
    1175         273 :         node = php_sxe_get_first_node(sxe, node);
    1176             : 
    1177         273 :         if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
    1178         251 :                 if (node->type == XML_ATTRIBUTE_NODE) {
    1179          32 :                         ZVAL_STR(&value, sxe_xmlNodeListGetString(node->doc, node->children, 1));
    1180          32 :                         zend_hash_next_index_insert(rv, &value);
    1181          32 :                         node = NULL;
    1182         219 :                 } else if (sxe->iter.type != SXE_ITER_CHILD) {
    1183             : 
    1184         214 :                         if ( sxe->iter.type == SXE_ITER_NONE || !node->children || !node->parent || !node->next || node->children->next || node->children->children || node->parent->children == node->parent->last ) {
    1185         205 :                                 node = node->children;
    1186             :                         } else {
    1187           9 :                                 ZVAL_COPY_VALUE(&iter_data, &sxe->iter.data);
    1188           9 :                                 ZVAL_UNDEF(&sxe->iter.data);
    1189             : 
    1190           9 :                                 node = php_sxe_reset_iterator(sxe, 0);
    1191             : 
    1192           9 :                                 use_iter = 1;
    1193             :                         }
    1194             :                 }
    1195             : 
    1196         904 :                 while (node) {
    1197         402 :                         if (node->children != NULL || node->prev != NULL || node->next != NULL) {
    1198         377 :                                 SKIP_TEXT(node);
    1199             :                         } else {
    1200          25 :                                 if (node->type == XML_TEXT_NODE) {
    1201           9 :                                         const xmlChar *cur = node->content;
    1202             : 
    1203           9 :                                         if (*cur != 0) {
    1204           8 :                                                 ZVAL_STR(&value, sxe_xmlNodeListGetString(node->doc, node, 1));
    1205           8 :                                                 zend_hash_next_index_insert(rv, &value);
    1206             :                                         }
    1207           9 :                                         goto next_iter;
    1208             :                                 }
    1209             :                         }
    1210             : 
    1211         197 :                         if (node->type == XML_ELEMENT_NODE && (! match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix))) {
    1212           3 :                                 goto next_iter;
    1213             :                         }
    1214             : 
    1215         194 :                         name = (char *) node->name;
    1216         194 :                         if (!name) {
    1217           1 :                                 goto next_iter;
    1218             :                         } else {
    1219         193 :                                 namelen = xmlStrlen(node->name);
    1220             :                         }
    1221             : 
    1222         193 :                         _get_base_node_value(sxe, node, &value, sxe->iter.nsprefix, sxe->iter.isprefix);
    1223             : 
    1224         193 :                         if ( use_iter ) {
    1225          12 :                                 zend_hash_next_index_insert(rv, &value);
    1226             :                         } else {
    1227         181 :                                 sxe_properties_add(rv, name, namelen, &value);
    1228             :                         }
    1229         402 : next_iter:
    1230         402 :                         if (use_iter) {
    1231          12 :                                 node = php_sxe_iterator_fetch(sxe, node->next, 0);
    1232             :                         } else {
    1233         390 :                                 node = node->next;
    1234             :                         }
    1235             :                 }
    1236             :         }
    1237             : 
    1238         273 :         if (use_iter) {
    1239          18 :                 if (!Z_ISUNDEF(sxe->iter.data)) {
    1240           0 :                         zval_ptr_dtor(&sxe->iter.data);
    1241             :                 }
    1242           9 :                 ZVAL_COPY_VALUE(&sxe->iter.data, &iter_data);
    1243             :         }
    1244             : 
    1245         273 :         return rv;
    1246             : }
    1247             : /* }}} */
    1248             : 
    1249        4000 : static HashTable *sxe_get_gc(zval *object, zval **table, int *n) /* {{{ */ {
    1250             :         php_sxe_object *sxe;
    1251        4000 :         sxe = Z_SXEOBJ_P(object);
    1252             : 
    1253        4000 :         *table = NULL;
    1254        4000 :         *n = 0;
    1255        4000 :         return sxe->properties;
    1256             : }
    1257             : /* }}} */
    1258             : 
    1259          26 : static HashTable *sxe_get_properties(zval *object) /* {{{ */
    1260             : {
    1261          26 :         return sxe_get_prop_hash(object, 0);
    1262             : }
    1263             : /* }}} */
    1264             : 
    1265         247 : static HashTable * sxe_get_debug_info(zval *object, int *is_temp) /* {{{ */
    1266             : {
    1267         247 :         *is_temp = 1;
    1268         247 :         return sxe_get_prop_hash(object, 1);
    1269             : }
    1270             : /* }}} */
    1271             : 
    1272           3 : static int sxe_objects_compare(zval *object1, zval *object2) /* {{{ */
    1273             : {
    1274             :         php_sxe_object *sxe1;
    1275             :         php_sxe_object *sxe2;
    1276             : 
    1277           3 :         sxe1 = Z_SXEOBJ_P(object1);
    1278           3 :         sxe2 = Z_SXEOBJ_P(object2);
    1279             : 
    1280           3 :         if (sxe1->node == NULL) {
    1281           0 :                 if (sxe2->node) {
    1282           0 :                         return 1;
    1283           0 :                 } else if (sxe1->document->ptr == sxe2->document->ptr) {
    1284           0 :                         return 0;
    1285             :                 }
    1286             :         } else {
    1287           3 :                 return !(sxe1->node == sxe2->node);
    1288             :         }
    1289           0 :         return 1;
    1290             : }
    1291             : /* }}} */
    1292             : 
    1293             : /* {{{ proto array SimpleXMLElement::xpath(string path)
    1294             :    Runs XPath query on the XML data */
    1295          23 : SXE_METHOD(xpath)
    1296             : {
    1297             :         php_sxe_object    *sxe;
    1298             :         zval               value;
    1299             :         char              *query;
    1300             :         size_t                query_len;
    1301             :         int                i;
    1302          23 :         int                nsnbr = 0;
    1303          23 :         xmlNsPtr          *ns = NULL;
    1304             :         xmlXPathObjectPtr  retval;
    1305             :         xmlNodeSetPtr      result;
    1306             :         xmlNodePtr                 nodeptr;
    1307             : 
    1308          23 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &query, &query_len) == FAILURE) {
    1309           2 :                 return;
    1310             :         }
    1311             : 
    1312          46 :         sxe = Z_SXEOBJ_P(getThis());
    1313             : 
    1314          23 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
    1315           0 :                 return; /* attributes don't have attributes */
    1316             :         }
    1317             : 
    1318          23 :         if (!sxe->xpath) {
    1319          13 :                 sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
    1320             :         }
    1321          23 :         if (!sxe->node) {
    1322           1 :                 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL);
    1323           1 :                 if (!sxe->node) {
    1324           1 :                         RETURN_FALSE;
    1325             :                 }
    1326             :         }
    1327             : 
    1328          22 :         nodeptr = php_sxe_get_first_node(sxe, sxe->node->node);
    1329             : 
    1330          22 :         sxe->xpath->node = nodeptr;
    1331             : 
    1332          22 :         ns = xmlGetNsList((xmlDocPtr) sxe->document->ptr, nodeptr);
    1333          22 :         if (ns != NULL) {
    1334          18 :                 while (ns[nsnbr] != NULL) {
    1335           6 :                         nsnbr++;
    1336             :                 }
    1337             :         }
    1338             : 
    1339          22 :         sxe->xpath->namespaces = ns;
    1340          22 :         sxe->xpath->nsNr = nsnbr;
    1341             : 
    1342          22 :         retval = xmlXPathEval((xmlChar *)query, sxe->xpath);
    1343          22 :         if (ns != NULL) {
    1344           6 :                 xmlFree(ns);
    1345           6 :                 sxe->xpath->namespaces = NULL;
    1346           6 :                 sxe->xpath->nsNr = 0;
    1347             :         }
    1348             : 
    1349          22 :         if (!retval) {
    1350           1 :                 RETURN_FALSE;
    1351             :         }
    1352             : 
    1353          21 :         result = retval->nodesetval;
    1354             : 
    1355          21 :         array_init(return_value);
    1356             : 
    1357          21 :         if (result != NULL) {
    1358          69 :                 for (i = 0; i < result->nodeNr; ++i) {
    1359          50 :                         nodeptr = result->nodeTab[i];
    1360          50 :                         if (nodeptr->type == XML_TEXT_NODE || nodeptr->type == XML_ELEMENT_NODE || nodeptr->type == XML_ATTRIBUTE_NODE) {
    1361             :                                 /**
    1362             :                                  * Detect the case where the last selector is text(), simplexml
    1363             :                                  * always accesses the text() child by default, therefore we assign
    1364             :                                  * to the parent node.
    1365             :                                  */
    1366          50 :                                 if (nodeptr->type == XML_TEXT_NODE) {
    1367           0 :                                         _node_as_zval(sxe, nodeptr->parent, &value, SXE_ITER_NONE, NULL, NULL, 0);
    1368          50 :                                 } else if (nodeptr->type == XML_ATTRIBUTE_NODE) {
    1369          20 :                                         _node_as_zval(sxe, nodeptr->parent, &value, SXE_ITER_ATTRLIST, (char*)nodeptr->name, nodeptr->ns ? (xmlChar *)nodeptr->ns->href : NULL, 0);
    1370             :                                 } else {
    1371          30 :                                         _node_as_zval(sxe, nodeptr, &value, SXE_ITER_NONE, NULL, NULL, 0);
    1372             :                                 }
    1373             : 
    1374          50 :                                 add_next_index_zval(return_value, &value);
    1375             :                         }
    1376             :                 }
    1377             :         }
    1378             : 
    1379          21 :         xmlXPathFreeObject(retval);
    1380             : }
    1381             : /* }}} */
    1382             : 
    1383             : /* {{{ proto bool SimpleXMLElement::registerXPathNamespace(string prefix, string ns)
    1384             :    Creates a prefix/ns context for the next XPath query */
    1385           1 : SXE_METHOD(registerXPathNamespace)
    1386             : {
    1387             :         php_sxe_object    *sxe;
    1388             :         size_t prefix_len, ns_uri_len;
    1389             :         char *prefix, *ns_uri;
    1390             : 
    1391           1 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &prefix, &prefix_len, &ns_uri, &ns_uri_len) == FAILURE) {
    1392           0 :                 return;
    1393             :         }
    1394             : 
    1395           2 :         sxe = Z_SXEOBJ_P(getThis());
    1396           1 :         if (!sxe->xpath) {
    1397           1 :                 sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
    1398             :         }
    1399             : 
    1400           1 :         if (xmlXPathRegisterNs(sxe->xpath, (xmlChar *)prefix, (xmlChar *)ns_uri) != 0) {
    1401           0 :                 RETURN_FALSE
    1402             :         }
    1403           1 :         RETURN_TRUE;
    1404             : }
    1405             : 
    1406             : /* }}} */
    1407             : 
    1408             : /* {{{ proto string SimpleXMLElement::asXML([string filename])
    1409             :    Return a well-formed XML string based on SimpleXML element */
    1410          32 : SXE_METHOD(asXML)
    1411             : {
    1412             :         php_sxe_object     *sxe;
    1413             :         xmlNodePtr          node;
    1414             :         xmlOutputBufferPtr  outbuf;
    1415             :         xmlChar            *strval;
    1416             :         int                 strval_len;
    1417             :         char               *filename;
    1418             :         size_t                 filename_len;
    1419             : 
    1420          32 :         if (ZEND_NUM_ARGS() > 1) {
    1421           0 :                 RETURN_FALSE;
    1422             :         }
    1423             : 
    1424          32 :         if (ZEND_NUM_ARGS() == 1) {
    1425           0 :                 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) {
    1426           0 :                         RETURN_FALSE;
    1427             :                 }
    1428             : 
    1429           0 :                 sxe = Z_SXEOBJ_P(getThis());
    1430           0 :                 GET_NODE(sxe, node);
    1431           0 :                 node = php_sxe_get_first_node(sxe, node);
    1432             : 
    1433           0 :                 if (node) {
    1434           0 :                         if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
    1435             :                                 int bytes;
    1436           0 :                                 bytes = xmlSaveFile(filename, (xmlDocPtr) sxe->document->ptr);
    1437           0 :                                 if (bytes == -1) {
    1438           0 :                                         RETURN_FALSE;
    1439             :                                 } else {
    1440           0 :                                         RETURN_TRUE;
    1441             :                                 }
    1442             :                         } else {
    1443           0 :                                 outbuf = xmlOutputBufferCreateFilename(filename, NULL, 0);
    1444             : 
    1445           0 :                                 if (outbuf == NULL) {
    1446           0 :                                         RETURN_FALSE;
    1447             :                                 }
    1448             : 
    1449           0 :                                 xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, NULL);
    1450           0 :                                 xmlOutputBufferClose(outbuf);
    1451           0 :                                 RETURN_TRUE;
    1452             :                         }
    1453             :                 } else {
    1454           0 :                         RETURN_FALSE;
    1455             :                 }
    1456             :         }
    1457             : 
    1458          64 :         sxe = Z_SXEOBJ_P(getThis());
    1459          32 :         GET_NODE(sxe, node);
    1460          32 :         node = php_sxe_get_first_node(sxe, node);
    1461             : 
    1462          32 :         if (node) {
    1463          32 :                 if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
    1464          19 :                         xmlDocDumpMemoryEnc((xmlDocPtr) sxe->document->ptr, &strval, &strval_len, (const char *) ((xmlDocPtr) sxe->document->ptr)->encoding);
    1465          19 :                         if (!strval) {
    1466           0 :                                 RETVAL_FALSE;
    1467             :                         } else {
    1468          38 :                                 RETVAL_STRINGL((char *)strval, strval_len);
    1469             :                         }
    1470          19 :                         xmlFree(strval);
    1471             :                 } else {
    1472             :                         char *return_content;
    1473             :                         size_t return_len;
    1474             :                         /* Should we be passing encoding information instead of NULL? */
    1475          13 :                         outbuf = xmlAllocOutputBuffer(NULL);
    1476             : 
    1477          13 :                         if (outbuf == NULL) {
    1478           0 :                                 RETURN_FALSE;
    1479             :                         }
    1480             : 
    1481          13 :                         xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, (const char *) ((xmlDocPtr) sxe->document->ptr)->encoding);
    1482          13 :                         xmlOutputBufferFlush(outbuf);
    1483             : #ifdef LIBXML2_NEW_BUFFER
    1484             :                         return_content = (char *)xmlOutputBufferGetContent(outbuf);
    1485             :                         return_len = xmlOutputBufferGetSize(outbuf);
    1486             : #else
    1487          13 :                         return_content = (char *)outbuf->buffer->content;
    1488          13 :                         return_len = outbuf->buffer->use;
    1489             : #endif
    1490          13 :                         if (!return_content) {
    1491           0 :                                 RETVAL_FALSE;
    1492             :                         } else {
    1493          26 :                                 RETVAL_STRINGL(return_content, return_len);
    1494             :                         }
    1495          13 :                         xmlOutputBufferClose(outbuf);
    1496             :                 }
    1497             :         } else {
    1498           0 :                 RETVAL_FALSE;
    1499             :         }
    1500             : }
    1501             : /* }}} */
    1502             : 
    1503             : #define SXE_NS_PREFIX(ns) (ns->prefix ? (char*)ns->prefix : "")
    1504             : 
    1505          38 : static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) /* {{{ */
    1506             : {
    1507          38 :         char *prefix = SXE_NS_PREFIX(ns);
    1508          76 :         zend_string *key = zend_string_init(prefix, strlen(prefix), 0);
    1509             :         zval zv;
    1510             : 
    1511          38 :         if (!zend_hash_exists(Z_ARRVAL_P(return_value), key)) {
    1512          66 :                 ZVAL_STRING(&zv, (char*)ns->href);
    1513          33 :                 zend_hash_add_new(Z_ARRVAL_P(return_value), key, &zv);
    1514             :         }
    1515             :         zend_string_release(key);
    1516          38 : }
    1517             : /* }}} */
    1518             : 
    1519          22 : static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value) /* {{{ */
    1520             : {
    1521             :         xmlAttrPtr  attr;
    1522             : 
    1523          22 :         if (node->ns) {
    1524          15 :                 sxe_add_namespace_name(return_value, node->ns);
    1525             :         }
    1526             : 
    1527          22 :         attr = node->properties;
    1528          45 :         while (attr) {
    1529           1 :                 if (attr->ns) {
    1530           1 :                         sxe_add_namespace_name(return_value, attr->ns);
    1531             :                 }
    1532           1 :                 attr = attr->next;
    1533             :         }
    1534             : 
    1535          22 :         if (recursive) {
    1536          12 :                 node = node->children;
    1537          48 :                 while (node) {
    1538          24 :                         if (node->type == XML_ELEMENT_NODE) {
    1539          10 :                                 sxe_add_namespaces(sxe, node, recursive, return_value);
    1540             :                         }
    1541          24 :                         node = node->next;
    1542             :                 }
    1543             :         }
    1544          22 : } /* }}} */
    1545             : 
    1546             : /* {{{ proto string SimpleXMLElement::getNamespaces([bool recursve])
    1547             :    Return all namespaces in use */
    1548          12 : SXE_METHOD(getNamespaces)
    1549             : {
    1550          12 :         zend_bool           recursive = 0;
    1551             :         php_sxe_object     *sxe;
    1552             :         xmlNodePtr          node;
    1553             : 
    1554          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &recursive) == FAILURE) {
    1555           0 :                 return;
    1556             :         }
    1557             : 
    1558          12 :         array_init(return_value);
    1559             : 
    1560          24 :         sxe = Z_SXEOBJ_P(getThis());
    1561          12 :         GET_NODE(sxe, node);
    1562          12 :         node = php_sxe_get_first_node(sxe, node);
    1563             : 
    1564          12 :         if (node) {
    1565          12 :                 if (node->type == XML_ELEMENT_NODE) {
    1566          12 :                         sxe_add_namespaces(sxe, node, recursive, return_value);
    1567           0 :                 } else if (node->type == XML_ATTRIBUTE_NODE && node->ns) {
    1568           0 :                         sxe_add_namespace_name(return_value, node->ns);
    1569             :                 }
    1570             :         }
    1571             : }
    1572             : /* }}} */
    1573             : 
    1574          98 : static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value) /* {{{ */
    1575             : {
    1576             :         xmlNsPtr ns;
    1577             : 
    1578          98 :         if (node->type == XML_ELEMENT_NODE) {
    1579          42 :                 ns = node->nsDef;
    1580         106 :                 while (ns != NULL) {
    1581          22 :                         sxe_add_namespace_name(return_value, ns);
    1582          22 :                         ns = ns->next;
    1583             :                 }
    1584          42 :                 if (recursive) {
    1585          33 :                         node = node->children;
    1586         148 :                         while (node) {
    1587          82 :                                 sxe_add_registered_namespaces(sxe, node, recursive, return_value);
    1588          82 :                                 node = node->next;
    1589             :                         }
    1590             :                 }
    1591             :         }
    1592          98 : }
    1593             : /* }}} */
    1594             : 
    1595             : /* {{{ proto string SimpleXMLElement::getDocNamespaces([bool recursive [, bool from_root])
    1596             :    Return all namespaces registered with document */
    1597          17 : SXE_METHOD(getDocNamespaces)
    1598             : {
    1599          17 :         zend_bool           recursive = 0, from_root = 1;
    1600             :         php_sxe_object     *sxe;
    1601             :         xmlNodePtr          node;
    1602             : 
    1603          17 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|bb", &recursive, &from_root) == FAILURE) {
    1604           1 :                 return;
    1605             :         }
    1606             : 
    1607          34 :         sxe = Z_SXEOBJ_P(getThis());
    1608          17 :         if(from_root){
    1609          11 :                 node = xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr);
    1610             :         }else{
    1611           6 :                 GET_NODE(sxe, node);
    1612             :         }
    1613             : 
    1614          17 :         if (node == NULL) {
    1615           1 :                 RETURN_FALSE;
    1616             :         }
    1617             : 
    1618          16 :         array_init(return_value);
    1619          16 :         sxe_add_registered_namespaces(sxe, node, recursive, return_value);
    1620             : }
    1621             : /* }}} */
    1622             : 
    1623             : /* {{{ proto object SimpleXMLElement::children([string ns [, bool is_prefix]])
    1624             :    Finds children of given node */
    1625          96 : SXE_METHOD(children)
    1626             : {
    1627             :         php_sxe_object *sxe;
    1628          96 :         char           *nsprefix = NULL;
    1629          96 :         size_t             nsprefix_len = 0;
    1630             :         xmlNodePtr      node;
    1631          96 :         zend_bool       isprefix = 0;
    1632             : 
    1633          96 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
    1634           0 :                 return;
    1635             :         }
    1636             : 
    1637         192 :         sxe = Z_SXEOBJ_P(getThis());
    1638             : 
    1639          96 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
    1640           0 :                 return; /* attributes don't have attributes */
    1641             :         }
    1642             : 
    1643          96 :         GET_NODE(sxe, node);
    1644          96 :         node = php_sxe_get_first_node(sxe, node);
    1645             : 
    1646          96 :         _node_as_zval(sxe, node, return_value, SXE_ITER_CHILD, NULL, (xmlChar *)nsprefix, isprefix);
    1647             : 
    1648             : }
    1649             : /* }}} */
    1650             : 
    1651             : /* {{{ proto object SimpleXMLElement::getName()
    1652             :    Finds children of given node */
    1653          55 : SXE_METHOD(getName)
    1654             : {
    1655             :         php_sxe_object *sxe;
    1656             :         xmlNodePtr      node;
    1657             :         int             namelen;
    1658             : 
    1659         110 :         sxe = Z_SXEOBJ_P(getThis());
    1660             : 
    1661          55 :         GET_NODE(sxe, node);
    1662          55 :         node = php_sxe_get_first_node(sxe, node);
    1663          55 :         if (node) {
    1664          55 :                 namelen = xmlStrlen(node->name);
    1665         110 :                 RETURN_STRINGL((char*)node->name, namelen);
    1666             :         } else {
    1667           0 :                 RETURN_EMPTY_STRING();
    1668             :         }
    1669             : }
    1670             : /* }}} */
    1671             : 
    1672             : /* {{{ proto array SimpleXMLElement::attributes([string ns [, bool is_prefix]])
    1673             :    Identifies an element's attributes */
    1674          39 : SXE_METHOD(attributes)
    1675             : {
    1676             :         php_sxe_object *sxe;
    1677          39 :         char           *nsprefix = NULL;
    1678          39 :         size_t             nsprefix_len = 0;
    1679             :         xmlNodePtr      node;
    1680          39 :         zend_bool       isprefix = 0;
    1681             : 
    1682          39 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
    1683           0 :                 return;
    1684             :         }
    1685             : 
    1686          78 :         sxe = Z_SXEOBJ_P(getThis());
    1687          39 :         GET_NODE(sxe, node);
    1688             : 
    1689          39 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
    1690           0 :                 return; /* attributes don't have attributes */
    1691             :         }
    1692             : 
    1693          39 :         node = php_sxe_get_first_node(sxe, node);
    1694             : 
    1695          39 :         _node_as_zval(sxe, node, return_value, SXE_ITER_ATTRLIST, NULL, (xmlChar *)nsprefix, isprefix);
    1696             : }
    1697             : /* }}} */
    1698             : 
    1699             : /* {{{ proto void SimpleXMLElement::addChild(string qName [, string value [, string ns]])
    1700             :    Add Element with optional namespace information */
    1701          12 : SXE_METHOD(addChild)
    1702             : {
    1703             :         php_sxe_object *sxe;
    1704          12 :         char           *qname, *value = NULL, *nsuri = NULL;
    1705          12 :         size_t             qname_len, value_len = 0, nsuri_len = 0;
    1706             :         xmlNodePtr      node, newnode;
    1707          12 :         xmlNsPtr        nsptr = NULL;
    1708          12 :         xmlChar        *localname, *prefix = NULL;
    1709             : 
    1710          12 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!s!",
    1711             :                 &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
    1712           1 :                 return;
    1713             :         }
    1714             : 
    1715          12 :         if (qname_len == 0) {
    1716           0 :                 php_error_docref(NULL, E_WARNING, "Element name is required");
    1717           0 :                 return;
    1718             :         }
    1719             : 
    1720          24 :         sxe = Z_SXEOBJ_P(getThis());
    1721          12 :         GET_NODE(sxe, node);
    1722             : 
    1723          12 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
    1724           1 :                 php_error_docref(NULL, E_WARNING, "Cannot add element to attributes");
    1725           1 :                 return;
    1726             :         }
    1727             : 
    1728          11 :         node = php_sxe_get_first_node(sxe, node);
    1729             : 
    1730          11 :         if (node == NULL) {
    1731           0 :                 php_error_docref(NULL, E_WARNING, "Cannot add child. Parent is not a permanent member of the XML tree");
    1732           0 :                 return;
    1733             :         }
    1734             : 
    1735          11 :         localname = xmlSplitQName2((xmlChar *)qname, &prefix);
    1736          11 :         if (localname == NULL) {
    1737           8 :                 localname = xmlStrdup((xmlChar *)qname);
    1738             :         }
    1739             : 
    1740          11 :         newnode = xmlNewChild(node, NULL, localname, (xmlChar *)value);
    1741             : 
    1742          11 :         if (nsuri != NULL) {
    1743           5 :                 if (nsuri_len == 0) {
    1744           1 :                         newnode->ns = NULL;
    1745           1 :                         nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
    1746             :                 } else {
    1747           4 :                         nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
    1748           4 :                         if (nsptr == NULL) {
    1749           2 :                                 nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
    1750             :                         }
    1751           4 :                         newnode->ns = nsptr;
    1752             :                 }
    1753             :         }
    1754             : 
    1755          11 :         _node_as_zval(sxe, newnode, return_value, SXE_ITER_NONE, (char *)localname, prefix, 0);
    1756             : 
    1757          11 :         xmlFree(localname);
    1758          11 :         if (prefix != NULL) {
    1759           3 :                 xmlFree(prefix);
    1760             :         }
    1761             : }
    1762             : /* }}} */
    1763             : 
    1764             : /* {{{ proto void SimpleXMLElement::addAttribute(string qName, string value [,string ns])
    1765             :    Add Attribute with optional namespace information */
    1766          11 : SXE_METHOD(addAttribute)
    1767             : {
    1768             :         php_sxe_object *sxe;
    1769          11 :         char           *qname, *value = NULL, *nsuri = NULL;
    1770          11 :         size_t             qname_len, value_len = 0, nsuri_len = 0;
    1771             :         xmlNodePtr      node;
    1772          11 :         xmlAttrPtr      attrp = NULL;
    1773          11 :         xmlNsPtr        nsptr = NULL;
    1774          11 :         xmlChar        *localname, *prefix = NULL;
    1775             : 
    1776          11 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|s!",
    1777             :                 &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
    1778           4 :                 return;
    1779             :         }
    1780             : 
    1781          11 :         if (qname_len == 0) {
    1782           1 :                 php_error_docref(NULL, E_WARNING, "Attribute name is required");
    1783           1 :                 return;
    1784             :         }
    1785             : 
    1786          20 :         sxe = Z_SXEOBJ_P(getThis());
    1787          10 :         GET_NODE(sxe, node);
    1788             : 
    1789          10 :         node = php_sxe_get_first_node(sxe, node);
    1790             : 
    1791          10 :         if (node && node->type != XML_ELEMENT_NODE) {
    1792           0 :                 node = node->parent;
    1793             :         }
    1794             : 
    1795          10 :         if (node == NULL) {
    1796           1 :                 php_error_docref(NULL, E_WARNING, "Unable to locate parent Element");
    1797           1 :                 return;
    1798             :         }
    1799             : 
    1800           9 :         localname = xmlSplitQName2((xmlChar *)qname, &prefix);
    1801           9 :         if (localname == NULL) {
    1802           6 :                 if (nsuri_len > 0) {
    1803           1 :                         if (prefix != NULL) {
    1804           0 :                                 xmlFree(prefix);
    1805             :                         }
    1806           1 :                         php_error_docref(NULL, E_WARNING, "Attribute requires prefix for namespace");
    1807           1 :                         return;
    1808             :                 }
    1809           5 :                 localname = xmlStrdup((xmlChar *)qname);
    1810             :         }
    1811             : 
    1812           8 :         attrp = xmlHasNsProp(node, localname, (xmlChar *)nsuri);
    1813           8 :         if (attrp != NULL && attrp->type != XML_ATTRIBUTE_DECL) {
    1814           1 :                 xmlFree(localname);
    1815           1 :                 if (prefix != NULL) {
    1816           1 :                         xmlFree(prefix);
    1817             :                 }
    1818           1 :                 php_error_docref(NULL, E_WARNING, "Attribute already exists");
    1819           1 :                 return;
    1820             :         }
    1821             : 
    1822           7 :         if (nsuri != NULL) {
    1823           2 :                 nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
    1824           2 :                 if (nsptr == NULL) {
    1825           2 :                         nsptr = xmlNewNs(node, (xmlChar *)nsuri, prefix);
    1826             :                 }
    1827             :         }
    1828             : 
    1829           7 :         attrp = xmlNewNsProp(node, nsptr, localname, (xmlChar *)value);
    1830             : 
    1831           7 :         xmlFree(localname);
    1832           7 :         if (prefix != NULL) {
    1833           2 :                 xmlFree(prefix);
    1834             :         }
    1835             : }
    1836             : /* }}} */
    1837             : 
    1838             : /* {{{ cast_object()
    1839             :  */
    1840      200184 : static int cast_object(zval *object, int type, char *contents)
    1841             : {
    1842      200184 :         if (contents) {
    1843      400332 :                 ZVAL_STRINGL(object, contents, strlen(contents));
    1844             :         } else {
    1845          18 :                 ZVAL_NULL(object);
    1846             :         }
    1847             : 
    1848      200184 :         switch (type) {
    1849      200179 :                 case IS_STRING:
    1850      200179 :                         convert_to_string(object);
    1851      200179 :                         break;
    1852           0 :                 case _IS_BOOL:
    1853           0 :                         convert_to_boolean(object);
    1854           0 :                         break;
    1855           3 :                 case IS_LONG:
    1856           3 :                         convert_to_long(object);
    1857           3 :                         break;
    1858           2 :                 case IS_DOUBLE:
    1859           2 :                         convert_to_double(object);
    1860           2 :                         break;
    1861           0 :                 default:
    1862           0 :                         return FAILURE;
    1863             :         }
    1864      200184 :         return SUCCESS;
    1865             : }
    1866             : /* }}} */
    1867             : 
    1868             : /* {{{ sxe_object_cast()
    1869             :  */
    1870      200208 : static int sxe_object_cast_ex(zval *readobj, zval *writeobj, int type)
    1871             : {
    1872             :         php_sxe_object *sxe;
    1873      200208 :         xmlChar        *contents = NULL;
    1874             :         xmlNodePtr          node;
    1875             :         int rv;
    1876             : 
    1877      200208 :         sxe = Z_SXEOBJ_P(readobj);
    1878             : 
    1879      200208 :         if (type == _IS_BOOL) {
    1880          24 :                 node = php_sxe_get_first_node(sxe, NULL);
    1881          24 :                 if (node) {
    1882           5 :                         ZVAL_TRUE(writeobj);
    1883             :                 } else {
    1884          19 :                         ZVAL_BOOL(writeobj, !sxe_prop_is_empty(readobj));
    1885             :                 }
    1886          24 :                 return SUCCESS;
    1887             :         }
    1888             : 
    1889      200184 :         if (sxe->iter.type != SXE_ITER_NONE) {
    1890      200058 :                 node = php_sxe_get_first_node(sxe, NULL);
    1891      200058 :                 if (node) {
    1892      200053 :                         contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, node->children, 1);
    1893             :                 }
    1894             :         } else {
    1895         126 :                 if (!sxe->node) {
    1896           0 :                         if (sxe->document) {
    1897           0 :                                 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL);
    1898             :                         }
    1899             :                 }
    1900             : 
    1901         126 :                 if (sxe->node && sxe->node->node) {
    1902         126 :                         if (sxe->node->node->children) {
    1903         119 :                                 contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, sxe->node->node->children, 1);
    1904             :                         }
    1905             :                 }
    1906             :         }
    1907             : 
    1908      200184 :         if (readobj == writeobj) {
    1909           0 :                 zval_ptr_dtor(readobj);
    1910             :         }
    1911             : 
    1912      200184 :         rv = cast_object(writeobj, type, (char *)contents);
    1913             : 
    1914      200184 :         if (contents) {
    1915      200166 :                 xmlFree(contents);
    1916             :         }
    1917             : 
    1918      200184 :         return rv;
    1919             : }
    1920             : /* }}} */
    1921             : 
    1922             : /*  {{{ Variant of sxe_object_cast_ex that handles overwritten __toString() method */
    1923      200199 : static int sxe_object_cast(zval *readobj, zval *writeobj, int type)
    1924             : {
    1925      200199 :         if (type == IS_STRING
    1926      200170 :                 && zend_std_cast_object_tostring(readobj, writeobj, IS_STRING) == SUCCESS
    1927             :         ) {
    1928      200170 :                 return SUCCESS;
    1929             :         }
    1930             : 
    1931          29 :         return sxe_object_cast_ex(readobj, writeobj, type);
    1932             : }
    1933             : /* }}} */
    1934             : 
    1935             : /* {{{ proto object SimpleXMLElement::__toString()
    1936             :    Returns the string content */
    1937      200170 : SXE_METHOD(__toString)
    1938             : {
    1939      400340 :         if (sxe_object_cast_ex(getThis(), return_value, IS_STRING) != SUCCESS) {
    1940           0 :                 zval_ptr_dtor(return_value);
    1941           0 :                 RETURN_EMPTY_STRING();
    1942             :         }
    1943             : }
    1944             : /* }}} */
    1945             : 
    1946          20 : static int php_sxe_count_elements_helper(php_sxe_object *sxe, zend_long *count) /* {{{ */
    1947             : {
    1948             :         xmlNodePtr      node;
    1949             :         zval            data;
    1950             : 
    1951          20 :         *count = 0;
    1952             : 
    1953          20 :         ZVAL_COPY_VALUE(&data, &sxe->iter.data);
    1954          20 :         ZVAL_UNDEF(&sxe->iter.data);
    1955             : 
    1956          20 :         node = php_sxe_reset_iterator(sxe, 0);
    1957             : 
    1958          71 :         while (node)
    1959             :         {
    1960          31 :                 (*count)++;
    1961          31 :                 node = php_sxe_iterator_fetch(sxe, node->next, 0);
    1962             :         }
    1963             : 
    1964          40 :         if (!Z_ISUNDEF(sxe->iter.data)) {
    1965           0 :                 zval_ptr_dtor(&sxe->iter.data);
    1966             :         }
    1967          20 :         ZVAL_COPY_VALUE(&sxe->iter.data, &data);
    1968             : 
    1969          20 :         return SUCCESS;
    1970             : }
    1971             : /* }}} */
    1972             : 
    1973          20 : static int sxe_count_elements(zval *object, zend_long *count) /* {{{ */
    1974             : {
    1975             :         php_sxe_object  *intern;
    1976          20 :         intern = Z_SXEOBJ_P(object);
    1977          20 :         if (intern->fptr_count) {
    1978             :                 zval rv;
    1979           4 :                 zend_call_method_with_0_params(object, intern->zo.ce, &intern->fptr_count, "count", &rv);
    1980           4 :                 if (!Z_ISUNDEF(rv)) {
    1981           4 :                         *count = zval_get_long(&rv);
    1982           4 :                         zval_ptr_dtor(&rv);
    1983           4 :                         return SUCCESS;
    1984             :                 }
    1985           0 :                 return FAILURE;
    1986             :         }
    1987          16 :         return php_sxe_count_elements_helper(intern, count);
    1988             : }
    1989             : /* }}} */
    1990             : 
    1991             : /* {{{ proto int SimpleXMLElement::count()
    1992             :  Get number of child elements */
    1993           4 : SXE_METHOD(count)
    1994             : {
    1995           4 :         zend_long count = 0;
    1996           8 :         php_sxe_object *sxe = Z_SXEOBJ_P(getThis());
    1997             : 
    1998           4 :         if (zend_parse_parameters_none() == FAILURE) {
    1999           0 :                 return;
    2000             :         }
    2001             : 
    2002           4 :         php_sxe_count_elements_helper(sxe, &count);
    2003             : 
    2004           4 :         RETURN_LONG(count);
    2005             : }
    2006             : /* }}} */
    2007             : 
    2008           9 : static zval *sxe_get_value(zval *z, zval *rv) /* {{{ */
    2009             : {
    2010           9 :         if (sxe_object_cast_ex(z, rv, IS_STRING) == FAILURE) {
    2011           0 :                 zend_error(E_ERROR, "Unable to cast node to string");
    2012             :                 /* FIXME: Should not be fatal */
    2013             :         }
    2014             : 
    2015           9 :         return rv;
    2016             : }
    2017             : /* }}} */
    2018             : 
    2019             : static zend_object_handlers sxe_object_handlers = { /* {{{ */
    2020             :         ZEND_OBJECTS_STORE_HANDLERS,
    2021             :         sxe_property_read,
    2022             :         sxe_property_write,
    2023             :         sxe_dimension_read,
    2024             :         sxe_dimension_write,
    2025             :         sxe_property_get_adr,
    2026             :         sxe_get_value,                  /* get */
    2027             :         NULL,
    2028             :         sxe_property_exists,
    2029             :         sxe_property_delete,
    2030             :         sxe_dimension_exists,
    2031             :         sxe_dimension_delete,
    2032             :         sxe_get_properties,
    2033             :         NULL, /* zend_get_std_object_handlers()->get_method,*/
    2034             :         NULL, /* zend_get_std_object_handlers()->call_method,*/
    2035             :         NULL, /* zend_get_std_object_handlers()->get_constructor, */
    2036             :         NULL, /* zend_get_std_object_handlers()->get_class_name,*/
    2037             :         sxe_objects_compare,
    2038             :         sxe_object_cast,
    2039             :         sxe_count_elements,
    2040             :         sxe_get_debug_info,
    2041             :         NULL,
    2042             :         sxe_get_gc,
    2043             :         NULL,
    2044             :         NULL
    2045             : };
    2046             : /* }}} */
    2047             : 
    2048             : /* {{{ sxe_object_clone()
    2049             :  */
    2050             : static zend_object *
    2051           7 : sxe_object_clone(zval *object)
    2052             : {
    2053           7 :         php_sxe_object *sxe = Z_SXEOBJ_P(object);
    2054             :         php_sxe_object *clone;
    2055           7 :         xmlNodePtr nodep = NULL;
    2056           7 :         xmlDocPtr docp = NULL;
    2057             : 
    2058           7 :         clone = php_sxe_object_new(sxe->zo.ce, sxe->fptr_count);
    2059           7 :         clone->document = sxe->document;
    2060           7 :         if (clone->document) {
    2061           7 :                 clone->document->refcount++;
    2062           7 :                 docp = clone->document->ptr;
    2063             :         }
    2064             : 
    2065           7 :         clone->iter.isprefix = sxe->iter.isprefix;
    2066           7 :         if (sxe->iter.name != NULL) {
    2067           1 :                 clone->iter.name = (xmlChar*)estrdup((char*)sxe->iter.name);
    2068             :         }
    2069           7 :         if (sxe->iter.nsprefix != NULL) {
    2070           0 :                 clone->iter.nsprefix = (xmlChar*)estrdup((char*)sxe->iter.nsprefix);
    2071             :         }
    2072           7 :         clone->iter.type = sxe->iter.type;
    2073             : 
    2074           7 :         if (sxe->node) {
    2075           7 :                 nodep = xmlDocCopyNode(sxe->node->node, docp, 1);
    2076             :         }
    2077             : 
    2078           7 :         php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL);
    2079             : 
    2080           7 :         return &clone->zo;
    2081             : }
    2082             : /* }}} */
    2083             : 
    2084             : /* {{{ sxe_object_dtor()
    2085             :  */
    2086      403553 : static void sxe_object_dtor(zend_object *object)
    2087             : {
    2088             :         /* dtor required to cleanup iterator related data properly */
    2089             :         php_sxe_object *sxe;
    2090             : 
    2091      403553 :         sxe = php_sxe_fetch_object(object);
    2092             : 
    2093      807106 :         if (!Z_ISUNDEF(sxe->iter.data)) {
    2094      200357 :                 zval_ptr_dtor(&sxe->iter.data);
    2095      200357 :                 ZVAL_UNDEF(&sxe->iter.data);
    2096             :         }
    2097             : 
    2098      403553 :         if (sxe->iter.name) {
    2099      200371 :                 efree(sxe->iter.name);
    2100      200371 :                 sxe->iter.name = NULL;
    2101             :         }
    2102      403553 :         if (sxe->iter.nsprefix) {
    2103         135 :                 efree(sxe->iter.nsprefix);
    2104         135 :                 sxe->iter.nsprefix = NULL;
    2105             :         }
    2106      807106 :         if (!Z_ISUNDEF(sxe->tmp)) {
    2107          11 :                 zval_ptr_dtor(&sxe->tmp);
    2108          11 :                 ZVAL_UNDEF(&sxe->tmp);
    2109             :         }
    2110      403553 : }
    2111             : /* }}} */
    2112             : 
    2113             : /* {{{ sxe_object_free_storage()
    2114             :  */
    2115      403556 : static void sxe_object_free_storage(zend_object *object)
    2116             : {
    2117             :         php_sxe_object *sxe;
    2118             : 
    2119      403556 :         sxe = php_sxe_fetch_object(object);
    2120             : 
    2121      403556 :         zend_object_std_dtor(&sxe->zo);
    2122             : 
    2123      403556 :         php_libxml_node_decrement_resource((php_libxml_node_object *)sxe);
    2124             : 
    2125      403556 :         if (sxe->xpath) {
    2126          14 :                 xmlXPathFreeContext(sxe->xpath);
    2127             :         }
    2128             : 
    2129      403556 :         if (sxe->properties) {
    2130          26 :                 zend_hash_destroy(sxe->properties);
    2131          26 :                 FREE_HASHTABLE(sxe->properties);
    2132             :         }
    2133      403556 : }
    2134             : /* }}} */
    2135             : 
    2136             : /* {{{ php_sxe_find_fptr_count()
    2137             :  */
    2138        2166 : static zend_function* php_sxe_find_fptr_count(zend_class_entry *ce)
    2139             : {
    2140        2166 :         zend_function *fptr_count = NULL;
    2141        2166 :         zend_class_entry *parent = ce;
    2142        2166 :         int inherited = 0;
    2143             : 
    2144        4345 :         while (parent) {
    2145        2179 :                 if (parent == sxe_class_entry) {
    2146        2166 :                         break;
    2147             :                 }
    2148          13 :                 parent = parent->parent;
    2149          13 :                 inherited = 1;
    2150             :         }
    2151             : 
    2152        2166 :         if (inherited) {
    2153          22 :                 fptr_count = zend_hash_str_find_ptr(&ce->function_table, "count", sizeof("count") - 1);
    2154          11 :                 if (fptr_count->common.scope == parent) {
    2155           9 :                         fptr_count = NULL;
    2156             :                 }
    2157             :         }
    2158             : 
    2159        2166 :         return fptr_count;
    2160             : }
    2161             : /* }}} */
    2162             : 
    2163             : /* {{{ php_sxe_object_new()
    2164             :  */
    2165      403556 : static php_sxe_object* php_sxe_object_new(zend_class_entry *ce, zend_function *fptr_count)
    2166             : {
    2167             :         php_sxe_object *intern;
    2168             : 
    2169      403556 :         intern = ecalloc(1, sizeof(php_sxe_object) + zend_object_properties_size(ce));
    2170             : 
    2171      403556 :         intern->iter.type = SXE_ITER_NONE;
    2172      403556 :         intern->iter.nsprefix = NULL;
    2173      403556 :         intern->iter.name = NULL;
    2174      403556 :         intern->fptr_count = fptr_count;
    2175             : 
    2176      403556 :         zend_object_std_init(&intern->zo, ce);
    2177      403556 :         object_properties_init(&intern->zo, ce);
    2178      403556 :         intern->zo.handlers = &sxe_object_handlers;
    2179             : 
    2180      403556 :         return intern;
    2181             : }
    2182             : /* }}} */
    2183             : 
    2184             : /* {{{ sxe_object_new()
    2185             :  */
    2186             : PHP_SXE_API zend_object *
    2187        2032 : sxe_object_new(zend_class_entry *ce)
    2188             : {
    2189             :         php_sxe_object    *intern;
    2190             : 
    2191        2032 :         intern = php_sxe_object_new(ce, php_sxe_find_fptr_count(ce));
    2192        2032 :         return &intern->zo;
    2193             : }
    2194             : /* }}} */
    2195             : 
    2196             : /* {{{ proto simplemxml_element simplexml_load_file(string filename [, string class_name [, int options [, string ns [, bool is_prefix]]]])
    2197             :    Load a filename and return a simplexml_element object to allow for processing */
    2198          10 : PHP_FUNCTION(simplexml_load_file)
    2199             : {
    2200             :         php_sxe_object *sxe;
    2201             :         char           *filename;
    2202             :         size_t             filename_len;
    2203             :         xmlDocPtr       docp;
    2204          10 :         char           *ns = NULL;
    2205          10 :         size_t             ns_len = 0;
    2206          10 :         zend_long            options = 0;
    2207          10 :         zend_class_entry *ce= sxe_class_entry;
    2208             :         zend_function    *fptr_count;
    2209          10 :         zend_bool       isprefix = 0;
    2210             : 
    2211          10 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|C!lsb", &filename, &filename_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
    2212           4 :                 return;
    2213             :         }
    2214             : 
    2215           9 :         if (ZEND_LONG_EXCEEDS_INT(options)) {
    2216           0 :                 php_error_docref(NULL, E_WARNING, "Invalid options");
    2217           0 :                 RETURN_FALSE;
    2218             :         }
    2219             : 
    2220           9 :         docp = xmlReadFile(filename, NULL, (int)options);
    2221             : 
    2222           9 :         if (!docp) {
    2223           2 :                 RETURN_FALSE;
    2224             :         }
    2225             : 
    2226           7 :         if (!ce) {
    2227           0 :                 ce = sxe_class_entry;
    2228           0 :                 fptr_count = NULL;
    2229             :         } else {
    2230           7 :                 fptr_count = php_sxe_find_fptr_count(ce);
    2231             :         }
    2232           7 :         sxe = php_sxe_object_new(ce, fptr_count);
    2233           7 :         sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL;
    2234           7 :         sxe->iter.isprefix = isprefix;
    2235           7 :         php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);
    2236           7 :         php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL);
    2237             : 
    2238           7 :         ZVAL_OBJ(return_value, &sxe->zo);
    2239             : }
    2240             : /* }}} */
    2241             : 
    2242             : /* {{{ proto simplemxml_element simplexml_load_string(string data [, string class_name [, int options [, string ns [, bool is_prefix]]]])
    2243             :    Load a string and return a simplexml_element object to allow for processing */
    2244         131 : PHP_FUNCTION(simplexml_load_string)
    2245             : {
    2246             :         php_sxe_object *sxe;
    2247             :         char           *data;
    2248             :         size_t             data_len;
    2249             :         xmlDocPtr       docp;
    2250         131 :         char           *ns = NULL;
    2251         131 :         size_t             ns_len = 0;
    2252         131 :         zend_long            options = 0;
    2253         131 :         zend_class_entry *ce= sxe_class_entry;
    2254             :         zend_function    *fptr_count;
    2255         131 :         zend_bool       isprefix = 0;
    2256             : 
    2257         131 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|C!lsb", &data, &data_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
    2258           5 :                 return;
    2259             :         }
    2260             : 
    2261         130 :         if (ZEND_SIZE_T_INT_OVFL(data_len)) {
    2262           0 :                 php_error_docref(NULL, E_WARNING, "Data is too long");
    2263           0 :                 RETURN_FALSE;
    2264             :         }
    2265         130 :         if (ZEND_SIZE_T_INT_OVFL(ns_len)) {
    2266           0 :                 php_error_docref(NULL, E_WARNING, "Namespace is too long");
    2267           0 :                 RETURN_FALSE;
    2268             :         }
    2269         130 :         if (ZEND_LONG_EXCEEDS_INT(options)) {
    2270           1 :                 php_error_docref(NULL, E_WARNING, "Invalid options");
    2271           1 :                 RETURN_FALSE;
    2272             :         }
    2273             : 
    2274         129 :         docp = xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
    2275             : 
    2276         129 :         if (!docp) {
    2277           2 :                 RETURN_FALSE;
    2278             :         }
    2279             : 
    2280         127 :         if (!ce) {
    2281           2 :                 ce = sxe_class_entry;
    2282           2 :                 fptr_count = NULL;
    2283             :         } else {
    2284         125 :                 fptr_count = php_sxe_find_fptr_count(ce);
    2285             :         }
    2286         127 :         sxe = php_sxe_object_new(ce, fptr_count);
    2287         127 :         sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL;
    2288         127 :         sxe->iter.isprefix = isprefix;
    2289         127 :         php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);
    2290         127 :         php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL);
    2291             : 
    2292         127 :         ZVAL_OBJ(return_value, &sxe->zo);
    2293             : }
    2294             : /* }}} */
    2295             : 
    2296             : /* {{{ proto SimpleXMLElement::__construct(string data [, int options [, bool data_is_url [, string ns [, bool is_prefix]]]])
    2297             :    SimpleXMLElement constructor */
    2298        2031 : SXE_METHOD(__construct)
    2299             : {
    2300        4062 :         php_sxe_object *sxe = Z_SXEOBJ_P(getThis());
    2301        2031 :         char           *data, *ns = NULL;
    2302        2031 :         size_t             data_len, ns_len = 0;
    2303             :         xmlDocPtr       docp;
    2304        2031 :         zend_long            options = 0;
    2305        2031 :         zend_bool       is_url = 0, isprefix = 0;
    2306             : 
    2307        2031 :         if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "s|lbsb", &data, &data_len, &options, &is_url, &ns, &ns_len, &isprefix) == FAILURE) {
    2308           1 :                 return;
    2309             :         }
    2310             : 
    2311        2031 :         if (ZEND_SIZE_T_INT_OVFL(data_len)) {
    2312           0 :                 zend_throw_exception(zend_ce_exception, "Data is too long", 0);
    2313           0 :                 return;
    2314             :         }
    2315        2031 :         if (ZEND_SIZE_T_INT_OVFL(ns_len)) {
    2316           0 :                 zend_throw_exception(zend_ce_exception, "Namespace is too long", 0);
    2317           0 :                 return;
    2318             :         }
    2319        2031 :         if (ZEND_LONG_EXCEEDS_INT(options)) {
    2320           1 :                 zend_throw_exception(zend_ce_exception, "Invalid options", 0);
    2321           1 :                 return;
    2322             :         }
    2323             : 
    2324        2030 :         docp = is_url ? xmlReadFile(data, NULL, (int)options) : xmlReadMemory(data, (int)data_len, NULL, NULL, (int)options);
    2325             : 
    2326        2030 :         if (!docp) {
    2327           0 :                 ((php_libxml_node_object *)sxe)->document = NULL;
    2328           0 :                 zend_throw_exception(zend_ce_exception, "String could not be parsed as XML", 0);
    2329           0 :                 return;
    2330             :         }
    2331             : 
    2332        2030 :         sxe->iter.nsprefix = ns_len ? (xmlChar*)estrdup(ns) : NULL;
    2333        2030 :         sxe->iter.isprefix = isprefix;
    2334        2030 :         php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp);
    2335        2030 :         php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL);
    2336             : }
    2337             : /* }}} */
    2338             : 
    2339             : zend_object_iterator_funcs php_sxe_iterator_funcs = { /* {{{ */
    2340             :         php_sxe_iterator_dtor,
    2341             :         php_sxe_iterator_valid,
    2342             :         php_sxe_iterator_current_data,
    2343             :         php_sxe_iterator_current_key,
    2344             :         php_sxe_iterator_move_forward,
    2345             :         php_sxe_iterator_rewind,
    2346             :         NULL
    2347             : };
    2348             : /* }}} */
    2349             : 
    2350      200764 : static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data) /* {{{ */
    2351             : {
    2352      200764 :         xmlChar *prefix  = sxe->iter.nsprefix;
    2353      200764 :         int isprefix  = sxe->iter.isprefix;
    2354             : 
    2355      200764 :         if (sxe->iter.type == SXE_ITER_ATTRLIST) {
    2356          80 :                 if (sxe->iter.name) {
    2357          58 :                         while (node) {
    2358          38 :                                 if (node->type == XML_ATTRIBUTE_NODE) {
    2359          38 :                                         if (!xmlStrcmp(node->name, sxe->iter.name) && match_ns(sxe, node, prefix, isprefix)) {
    2360          20 :                                                 break;
    2361             :                                         }
    2362             :                                 }
    2363          18 :                                 node = node->next;
    2364             :                         }
    2365             :                 } else {
    2366         125 :                         while (node) {
    2367          32 :                                 if (node->type == XML_ATTRIBUTE_NODE) {
    2368          32 :                                         if (match_ns(sxe, node, prefix, isprefix)) {
    2369          27 :                                                 break;
    2370             :                                         }
    2371             :                                 }
    2372           5 :                                 node = node->next;
    2373             :                         }
    2374             :                 }
    2375      401121 :         } else if (sxe->iter.type == SXE_ITER_ELEMENT && sxe->iter.name) {
    2376      401477 :                 while (node) {
    2377      200983 :                         if (node->type == XML_ELEMENT_NODE) {
    2378      200526 :                                 if (!xmlStrcmp(node->name, sxe->iter.name) && match_ns(sxe, node, prefix, isprefix)) {
    2379      200380 :                                         break;
    2380             :                                 }
    2381             :                         }
    2382         603 :                         node = node->next;
    2383             :                 }
    2384             :         } else {
    2385         713 :                 while (node) {
    2386         365 :                         if (node->type == XML_ELEMENT_NODE) {
    2387         165 :                                 if (match_ns(sxe, node, prefix, isprefix)) {
    2388         146 :                                         break;
    2389             :                                 }
    2390             :                         }
    2391         219 :                         node = node->next;
    2392             :                 }
    2393             :         }
    2394             : 
    2395      200764 :         if (node && use_data) {
    2396      200530 :                 _node_as_zval(sxe, node, &sxe->iter.data, SXE_ITER_NONE, NULL, prefix, isprefix);
    2397             :         }
    2398             : 
    2399      200764 :         return node;
    2400             : }
    2401             : /* }}} */
    2402             : 
    2403      200598 : static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data) /* {{{ */
    2404             : {
    2405             :         xmlNodePtr node;
    2406             : 
    2407      401196 :         if (!Z_ISUNDEF(sxe->iter.data)) {
    2408          50 :                 zval_ptr_dtor(&sxe->iter.data);
    2409          50 :                 ZVAL_UNDEF(&sxe->iter.data);
    2410             :         }
    2411             : 
    2412      200598 :         GET_NODE(sxe, node)
    2413             : 
    2414      200598 :         if (node) {
    2415      200598 :                 switch (sxe->iter.type) {
    2416      200537 :                         case SXE_ITER_ELEMENT:
    2417             :                         case SXE_ITER_CHILD:
    2418             :                         case SXE_ITER_NONE:
    2419      200537 :                                 node = node->children;
    2420      200537 :                                 break;
    2421          61 :                         case SXE_ITER_ATTRLIST:
    2422          61 :                                 node = (xmlNodePtr) node->properties;
    2423             :                 }
    2424      200598 :                 return php_sxe_iterator_fetch(sxe, node, use_data);
    2425             :         }
    2426           0 :         return NULL;
    2427             : }
    2428             : /* }}} */
    2429             : 
    2430         104 : zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref) /* {{{ */
    2431             : {
    2432             :         php_sxe_iterator *iterator;
    2433             : 
    2434         104 :         if (by_ref) {
    2435           0 :                 zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
    2436             :         }
    2437         104 :         iterator = emalloc(sizeof(php_sxe_iterator));
    2438         104 :         zend_iterator_init(&iterator->intern);
    2439             : 
    2440         104 :         ZVAL_COPY(&iterator->intern.data, object);
    2441         104 :         iterator->intern.funcs = &php_sxe_iterator_funcs;
    2442         104 :         iterator->sxe = Z_SXEOBJ_P(object);
    2443             : 
    2444         104 :         return (zend_object_iterator*)iterator;
    2445             : }
    2446             : /* }}} */
    2447             : 
    2448         104 : static void php_sxe_iterator_dtor(zend_object_iterator *iter) /* {{{ */
    2449             : {
    2450         104 :         php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
    2451             : 
    2452             :         /* cleanup handled in sxe_object_dtor as we dont always have an iterator wrapper */
    2453         208 :         if (!Z_ISUNDEF(iterator->intern.data)) {
    2454         104 :                 zval_ptr_dtor(&iterator->intern.data);
    2455             :         }
    2456         104 : }
    2457             : /* }}} */
    2458             : 
    2459         234 : static int php_sxe_iterator_valid(zend_object_iterator *iter) /* {{{ */
    2460             : {
    2461         234 :         php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
    2462             : 
    2463         468 :         return Z_ISUNDEF(iterator->sxe->iter.data) ? FAILURE : SUCCESS;
    2464             : }
    2465             : /* }}} */
    2466             : 
    2467         112 : static zval *php_sxe_iterator_current_data(zend_object_iterator *iter) /* {{{ */
    2468             : {
    2469         112 :         php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
    2470             : 
    2471         112 :         return &iterator->sxe->iter.data;
    2472             : }
    2473             : /* }}} */
    2474             : 
    2475          59 : static void php_sxe_iterator_current_key(zend_object_iterator *iter, zval *key) /* {{{ */
    2476             : {
    2477          59 :         php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
    2478          59 :         zval *curobj = &iterator->sxe->iter.data;
    2479          59 :         php_sxe_object *intern = Z_SXEOBJ_P(curobj);
    2480             : 
    2481          59 :         xmlNodePtr curnode = NULL;
    2482          59 :         if (intern != NULL && intern->node != NULL) {
    2483          59 :                 curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
    2484             :         }
    2485             : 
    2486          59 :         if (curnode) {
    2487         118 :                 ZVAL_STRINGL(key, (char *) curnode->name, xmlStrlen(curnode->name));
    2488             :         } else {
    2489           0 :                 ZVAL_NULL(key);
    2490             :         }
    2491          59 : }
    2492             : /* }}} */
    2493             : 
    2494         123 : PHP_SXE_API void php_sxe_move_forward_iterator(php_sxe_object *sxe) /* {{{ */
    2495             : {
    2496         123 :         xmlNodePtr      node = NULL;
    2497             :         php_sxe_object  *intern;
    2498             : 
    2499         246 :         if (!Z_ISUNDEF(sxe->iter.data)) {
    2500         123 :                 intern = Z_SXEOBJ_P(&sxe->iter.data);
    2501         123 :                 GET_NODE(intern, node)
    2502         123 :                 zval_ptr_dtor(&sxe->iter.data);
    2503         123 :                 ZVAL_UNDEF(&sxe->iter.data);
    2504             :         }
    2505             : 
    2506         123 :         if (node) {
    2507         123 :                 php_sxe_iterator_fetch(sxe, node->next, 1);
    2508             :         }
    2509         123 : }
    2510             : /* }}} */
    2511             : 
    2512         123 : static void php_sxe_iterator_move_forward(zend_object_iterator *iter) /* {{{ */
    2513             : {
    2514         123 :         php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
    2515         123 :         php_sxe_move_forward_iterator(iterator->sxe);
    2516         123 : }
    2517             : /* }}} */
    2518             : 
    2519         110 : static void php_sxe_iterator_rewind(zend_object_iterator *iter) /* {{{ */
    2520             : {
    2521             :         php_sxe_object  *sxe;
    2522             : 
    2523         110 :         php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
    2524         110 :         sxe = iterator->sxe;
    2525             : 
    2526         110 :         php_sxe_reset_iterator(sxe, 1);
    2527         110 : }
    2528             : /* }}} */
    2529             : 
    2530           2 : void *simplexml_export_node(zval *object) /* {{{ */
    2531             : {
    2532             :         php_sxe_object *sxe;
    2533             :         xmlNodePtr node;
    2534             : 
    2535           2 :         sxe = Z_SXEOBJ_P(object);
    2536           2 :         GET_NODE(sxe, node);
    2537           2 :         return php_sxe_get_first_node(sxe, node);
    2538             : }
    2539             : /* }}} */
    2540             : 
    2541             : /* {{{ proto simplemxml_element simplexml_import_dom(domNode node [, string class_name])
    2542             :    Get a simplexml_element object from dom to allow for processing */
    2543           2 : PHP_FUNCTION(simplexml_import_dom)
    2544             : {
    2545             :         php_sxe_object *sxe;
    2546             :         zval *node;
    2547             :         php_libxml_node_object *object;
    2548           2 :         xmlNodePtr              nodep = NULL;
    2549           2 :         zend_class_entry *ce = sxe_class_entry;
    2550             :         zend_function    *fptr_count;
    2551             : 
    2552           2 :         if (zend_parse_parameters(ZEND_NUM_ARGS(), "o|C!", &node, &ce) == FAILURE) {
    2553           0 :                 return;
    2554             :         }
    2555             : 
    2556           2 :         object = Z_LIBXML_NODE_P(node);
    2557             : 
    2558           2 :         nodep = php_libxml_import_node(node);
    2559             : 
    2560           2 :         if (nodep) {
    2561           2 :                 if (nodep->doc == NULL) {
    2562           0 :                         php_error_docref(NULL, E_WARNING, "Imported Node must have associated Document");
    2563           0 :                         RETURN_NULL();
    2564             :                 }
    2565           2 :                 if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
    2566           2 :                         nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
    2567             :                 }
    2568             :         }
    2569             : 
    2570           2 :         if (nodep && nodep->type == XML_ELEMENT_NODE) {
    2571           2 :                 if (!ce) {
    2572           0 :                         ce = sxe_class_entry;
    2573           0 :                         fptr_count = NULL;
    2574             :                 } else {
    2575           2 :                         fptr_count = php_sxe_find_fptr_count(ce);
    2576             :                 }
    2577           2 :                 sxe = php_sxe_object_new(ce, fptr_count);
    2578           2 :                 sxe->document = object->document;
    2579           2 :                 php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, nodep->doc);
    2580           2 :                 php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, nodep, NULL);
    2581             : 
    2582           2 :                 ZVAL_OBJ(return_value, &sxe->zo);
    2583             :         } else {
    2584           0 :                 php_error_docref(NULL, E_WARNING, "Invalid Nodetype to import");
    2585           0 :                 RETVAL_NULL();
    2586             :         }
    2587             : }
    2588             : /* }}} */
    2589             : 
    2590             : /* {{{ arginfo */
    2591             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_file, 0, 0, 1)
    2592             :         ZEND_ARG_INFO(0, filename)
    2593             :         ZEND_ARG_INFO(0, class_name)
    2594             :         ZEND_ARG_INFO(0, options)
    2595             :         ZEND_ARG_INFO(0, ns)
    2596             :         ZEND_ARG_INFO(0, is_prefix)
    2597             : ZEND_END_ARG_INFO()
    2598             : 
    2599             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_string, 0, 0, 1)
    2600             :         ZEND_ARG_INFO(0, data)
    2601             :         ZEND_ARG_INFO(0, class_name)
    2602             :         ZEND_ARG_INFO(0, options)
    2603             :         ZEND_ARG_INFO(0, ns)
    2604             :         ZEND_ARG_INFO(0, is_prefix)
    2605             : ZEND_END_ARG_INFO()
    2606             : 
    2607             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_import_dom, 0, 0, 1)
    2608             :         ZEND_ARG_INFO(0, node)
    2609             :         ZEND_ARG_INFO(0, class_name)
    2610             : ZEND_END_ARG_INFO()
    2611             : 
    2612             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_xpath, 0, 0, 1)
    2613             :         ZEND_ARG_INFO(0, path)
    2614             : ZEND_END_ARG_INFO()
    2615             : 
    2616             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_registerxpathnamespace, 0, 0, 2)
    2617             :         ZEND_ARG_INFO(0, prefix)
    2618             :         ZEND_ARG_INFO(0, ns)
    2619             : ZEND_END_ARG_INFO()
    2620             : 
    2621             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_asxml, 0, 0, 0)
    2622             :         ZEND_ARG_INFO(0, filename)
    2623             : ZEND_END_ARG_INFO()
    2624             : 
    2625             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getnamespaces, 0, 0, 0)
    2626             :         ZEND_ARG_INFO(0, recursve)
    2627             : ZEND_END_ARG_INFO()
    2628             : 
    2629             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getdocnamespaces, 0, 0, 0)
    2630             :         ZEND_ARG_INFO(0, recursve)
    2631             :         ZEND_ARG_INFO(0, from_root)
    2632             : ZEND_END_ARG_INFO()
    2633             : 
    2634             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_children, 0, 0, 0)
    2635             :         ZEND_ARG_INFO(0, ns)
    2636             :         ZEND_ARG_INFO(0, is_prefix)
    2637             : ZEND_END_ARG_INFO()
    2638             : 
    2639             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement__construct, 0, 0, 1)
    2640             :         ZEND_ARG_INFO(0, data)
    2641             :         ZEND_ARG_INFO(0, options)
    2642             :         ZEND_ARG_INFO(0, data_is_url)
    2643             :         ZEND_ARG_INFO(0, ns)
    2644             :         ZEND_ARG_INFO(0, is_prefix)
    2645             : ZEND_END_ARG_INFO()
    2646             : 
    2647             : ZEND_BEGIN_ARG_INFO(arginfo_simplexmlelement__void, 0)
    2648             : ZEND_END_ARG_INFO()
    2649             : 
    2650             : ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_addchild, 0, 0, 1)
    2651             :         ZEND_ARG_INFO(0, name)
    2652             :         ZEND_ARG_INFO(0, value)
    2653             :         ZEND_ARG_INFO(0, ns)
    2654             : ZEND_END_ARG_INFO()
    2655             : /* }}} */
    2656             : 
    2657             : const zend_function_entry simplexml_functions[] = { /* {{{ */
    2658             :         PHP_FE(simplexml_load_file,     arginfo_simplexml_load_file)
    2659             :         PHP_FE(simplexml_load_string,   arginfo_simplexml_load_string)
    2660             :         PHP_FE(simplexml_import_dom,    arginfo_simplexml_import_dom)
    2661             :         PHP_FE_END
    2662             : };
    2663             : /* }}} */
    2664             : 
    2665             : static const zend_module_dep simplexml_deps[] = { /* {{{ */
    2666             :         ZEND_MOD_REQUIRED("libxml")
    2667             :         ZEND_MOD_REQUIRED("spl")
    2668             :         ZEND_MOD_END
    2669             : };
    2670             : /* }}} */
    2671             : 
    2672             : zend_module_entry simplexml_module_entry = { /* {{{ */
    2673             :         STANDARD_MODULE_HEADER_EX, NULL,
    2674             :         simplexml_deps,
    2675             :         "SimpleXML",
    2676             :         simplexml_functions,
    2677             :         PHP_MINIT(simplexml),
    2678             :         PHP_MSHUTDOWN(simplexml),
    2679             :         NULL,
    2680             :         NULL,
    2681             :         PHP_MINFO(simplexml),
    2682             :         PHP_SIMPLEXML_VERSION,
    2683             :         STANDARD_MODULE_PROPERTIES
    2684             : };
    2685             : /* }}} */
    2686             : 
    2687             : #ifdef COMPILE_DL_SIMPLEXML
    2688             : ZEND_GET_MODULE(simplexml)
    2689             : #endif
    2690             : 
    2691             : /* the method table */
    2692             : /* each method can have its own parameters and visibility */
    2693             : static const zend_function_entry sxe_functions[] = { /* {{{ */
    2694             :         SXE_ME(__construct,            arginfo_simplexmlelement__construct, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) /* must be called */
    2695             :         SXE_ME(asXML,                  arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
    2696             :         SXE_MALIAS(saveXML, asXML,         arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
    2697             :         SXE_ME(xpath,                  arginfo_simplexmlelement_xpath, ZEND_ACC_PUBLIC)
    2698             :         SXE_ME(registerXPathNamespace, arginfo_simplexmlelement_registerxpathnamespace, ZEND_ACC_PUBLIC)
    2699             :         SXE_ME(attributes,             arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
    2700             :         SXE_ME(children,               arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
    2701             :         SXE_ME(getNamespaces,          arginfo_simplexmlelement_getnamespaces, ZEND_ACC_PUBLIC)
    2702             :         SXE_ME(getDocNamespaces,       arginfo_simplexmlelement_getdocnamespaces, ZEND_ACC_PUBLIC)
    2703             :         SXE_ME(getName,                arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
    2704             :         SXE_ME(addChild,               arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
    2705             :         SXE_ME(addAttribute,           arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
    2706             :         SXE_ME(__toString,             arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
    2707             :         SXE_ME(count,                  arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
    2708             :         PHP_FE_END
    2709             : };
    2710             : /* }}} */
    2711             : 
    2712             : /* {{{ PHP_MINIT_FUNCTION(simplexml)
    2713             :  */
    2714       25286 : PHP_MINIT_FUNCTION(simplexml)
    2715             : {
    2716             :         zend_class_entry sxe;
    2717             : 
    2718       25286 :         INIT_CLASS_ENTRY(sxe, "SimpleXMLElement", sxe_functions);
    2719       25286 :         sxe.create_object = sxe_object_new;
    2720       25286 :         sxe_class_entry = zend_register_internal_class(&sxe);
    2721       25286 :         sxe_class_entry->get_iterator = php_sxe_get_iterator;
    2722       25286 :         sxe_class_entry->iterator_funcs.funcs = &php_sxe_iterator_funcs;
    2723       25286 :         zend_class_implements(sxe_class_entry, 1, zend_ce_traversable);
    2724       25286 :         sxe_object_handlers.offset = XtOffsetOf(php_sxe_object, zo);
    2725       25286 :         sxe_object_handlers.dtor_obj = sxe_object_dtor;
    2726       25286 :         sxe_object_handlers.free_obj = sxe_object_free_storage;
    2727       25286 :         sxe_object_handlers.clone_obj = sxe_object_clone;
    2728       25286 :         sxe_object_handlers.get_method = zend_get_std_object_handlers()->get_method;
    2729       25286 :         sxe_object_handlers.get_constructor = zend_get_std_object_handlers()->get_constructor;
    2730       25286 :         sxe_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name;
    2731       25286 :         sxe_class_entry->serialize = zend_class_serialize_deny;
    2732       25286 :         sxe_class_entry->unserialize = zend_class_unserialize_deny;
    2733             : 
    2734       25286 :         php_libxml_register_export(sxe_class_entry, simplexml_export_node);
    2735             : 
    2736       25286 :         PHP_MINIT(sxe)(INIT_FUNC_ARGS_PASSTHRU);
    2737             : 
    2738       25286 :         return SUCCESS;
    2739             : }
    2740             : /* }}} */
    2741             : 
    2742             : /* {{{ PHP_MSHUTDOWN_FUNCTION(simplexml)
    2743             :  */
    2744       25335 : PHP_MSHUTDOWN_FUNCTION(simplexml)
    2745             : {
    2746       25335 :         sxe_class_entry = NULL;
    2747       25335 :         return SUCCESS;
    2748             : }
    2749             : /* }}} */
    2750             : 
    2751             : /* {{{ PHP_MINFO_FUNCTION(simplexml)
    2752             :  */
    2753         149 : PHP_MINFO_FUNCTION(simplexml)
    2754             : {
    2755         149 :         php_info_print_table_start();
    2756         149 :         php_info_print_table_header(2, "Simplexml support", "enabled");
    2757         149 :         php_info_print_table_row(2, "Revision", "$Id: 341daed0ee94ea8f728bfd0ba4626e6ed365c0d1 $");
    2758         149 :         php_info_print_table_row(2, "Schema support",
    2759             : #ifdef LIBXML_SCHEMAS_ENABLED
    2760             :                 "enabled");
    2761             : #else
    2762             :                 "not available");
    2763             : #endif
    2764         149 :         php_info_print_table_end();
    2765         149 : }
    2766             : /* }}} */
    2767             : 
    2768             : #endif
    2769             : 
    2770             : /**
    2771             :  * Local Variables:
    2772             :  * c-basic-offset: 4
    2773             :  * tab-width: 4
    2774             :  * indent-tabs-mode: t
    2775             :  * End:
    2776             :  * vim600: fdm=marker
    2777             :  * vim: noet sw=4 ts=4
    2778             :  */

Generated by: LCOV version 1.10

Generated at Fri, 21 Jan 2022 14:15:20 +0000 (30 hours ago)

Copyright © 2005-2022 The PHP Group
All rights reserved.