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: 1036 1224 84.6 %
Date: 2014-08-04 Functions: 70 73 95.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Mon, 04 Aug 2014 15:49:11 +0000 (16 days ago)

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