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

LTP GCOV extension - code coverage report
Current view: directory - simplexml - simplexml.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 1263
Code covered: 84.6 % Executed lines: 1069
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:37 +0000 (33 hours ago)

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