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-19 Instrumented lines: 1169
Code covered: 83.7 % Executed lines: 978
Legend: not executed executed

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

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:18 +0000 (5 days ago)

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