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

Generated by: LCOV version 1.10

Generated at Thu, 21 May 2015 19:59:02 +0000 (2 days ago)

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