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: 1019 1218 83.7 %
Date: 2014-07-27 Functions: 69 72 95.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 27 Jul 2014 12:58:35 +0000 (5 days ago)

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