Annotation of embedaddon/php/ext/simplexml/simplexml.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>