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: 1013 1199 84.5 %
Date: 2015-03-28 Functions: 70 73 95.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 29 Mar 2015 03:45:56 +0000 (20 hours ago)

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