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

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
1.1.1.5 ! misho       5:   | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       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.5 ! misho      21: /* $Id: 16070fc92ad6f69cebb2d52ad3f02794f833ce39 $ */
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;
1.1.1.4   misho    1073:        zval            *iter_data = NULL;
1.1.1.2   misho    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:                zend_hash_clean(sxe->properties);
                   1085:                rv = sxe->properties;
                   1086:        } else {
                   1087:                ALLOC_HASHTABLE(rv);
                   1088:                zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
                   1089:                sxe->properties = rv;
                   1090:        }
                   1091: 
                   1092:        GET_NODE(sxe, node);
                   1093:        if (!node) {
                   1094:                return rv;
                   1095:        }
                   1096:        if (is_debug || sxe->iter.type != SXE_ITER_CHILD) {
                   1097:                if (sxe->iter.type == SXE_ITER_ELEMENT) {
                   1098:                        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1099:                }
                   1100:                if (!node || node->type != XML_ENTITY_DECL) {
                   1101:                        attr = node ? (xmlAttrPtr)node->properties : NULL;
                   1102:                        zattr = NULL;
                   1103:                        test = sxe->iter.name && sxe->iter.type == SXE_ITER_ATTRLIST;
                   1104:                        while (attr) {
                   1105:                                if ((!test || !xmlStrcmp(attr->name, sxe->iter.name)) && match_ns(sxe, (xmlNodePtr)attr, sxe->iter.nsprefix, sxe->iter.isprefix)) {
                   1106:                                        MAKE_STD_ZVAL(value);
                   1107:                                        ZVAL_STRING(value, sxe_xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, attr->children, 1), 0);
                   1108:                                        namelen = xmlStrlen(attr->name) + 1;
                   1109:                                        if (!zattr) {
                   1110:                                                MAKE_STD_ZVAL(zattr);
                   1111:                                                array_init(zattr);
                   1112:                                                sxe_properties_add(rv, "@attributes", sizeof("@attributes"), zattr TSRMLS_CC);
                   1113:                                        }
                   1114:                                        add_assoc_zval_ex(zattr, (char*)attr->name, namelen, value);
                   1115:                                }
                   1116:                                attr = attr->next;
                   1117:                        }
                   1118:                }
                   1119:        }
                   1120: 
                   1121:        GET_NODE(sxe, node);
                   1122:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
1.1.1.2   misho    1123: 
1.1       misho    1124:        if (node && sxe->iter.type != SXE_ITER_ATTRLIST) {
                   1125:                if (node->type == XML_ATTRIBUTE_NODE) {
                   1126:                        MAKE_STD_ZVAL(value);
                   1127:                        ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node->children, 1), 0);
                   1128:                        zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
                   1129:                        node = NULL;
                   1130:                } else if (sxe->iter.type != SXE_ITER_CHILD) {
1.1.1.2   misho    1131: 
1.1.1.5 ! misho    1132:                        if ( !node->children || !node->parent || !node->next || node->children->next || node->children->children || node->parent->children == node->parent->last ) {
1.1.1.2   misho    1133:                                node = node->children;
                   1134:                        } else {
                   1135:                                iter_data = sxe->iter.data;
                   1136:                                sxe->iter.data = NULL;
                   1137: 
                   1138:                                node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC);
                   1139: 
                   1140:                                use_iter = 1;
                   1141:                        }
1.1       misho    1142:                }
                   1143: 
                   1144:                while (node) {
                   1145:                        if (node->children != NULL || node->prev != NULL || node->next != NULL) {
                   1146:                                SKIP_TEXT(node);
                   1147:                        } else {
                   1148:                                if (node->type == XML_TEXT_NODE) {
                   1149:                                        const xmlChar *cur = node->content;
                   1150:                                        
                   1151:                                        if (*cur != 0) {
                   1152:                                                MAKE_STD_ZVAL(value);
                   1153:                                                ZVAL_STRING(value, sxe_xmlNodeListGetString(node->doc, node, 1), 0);
                   1154:                                                zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
                   1155:                                        }
                   1156:                                        goto next_iter;
                   1157:                                }
                   1158:                        }
                   1159: 
                   1160:                        if (node->type == XML_ELEMENT_NODE && (! match_ns(sxe, node, sxe->iter.nsprefix, sxe->iter.isprefix))) {
                   1161:                                goto next_iter;
                   1162:                        }
                   1163: 
                   1164:                        name = (char *) node->name;
                   1165:                        if (!name) {
                   1166:                                goto next_iter;
                   1167:                        } else {
                   1168:                                namelen = xmlStrlen(node->name) + 1;
                   1169:                        }
                   1170: 
                   1171:                        _get_base_node_value(sxe, node, &value, sxe->iter.nsprefix, sxe->iter.isprefix TSRMLS_CC);
                   1172: 
1.1.1.2   misho    1173:                        if ( use_iter ) {
                   1174:                                zend_hash_next_index_insert(rv, &value, sizeof(zval *), NULL);
                   1175:                        } else {
                   1176:                                sxe_properties_add(rv, name, namelen, value TSRMLS_CC);
                   1177:                        }
1.1       misho    1178: next_iter:
1.1.1.2   misho    1179:                        if ( use_iter ) {
                   1180:                                node = php_sxe_iterator_fetch(sxe, node->next, 0 TSRMLS_CC);
                   1181:                        } else {
                   1182:                                node = node->next;
                   1183:                        }
                   1184:                }
                   1185:        }
                   1186: 
                   1187:        if ( use_iter ) {
                   1188:                if (sxe->iter.data) {
                   1189:                        zval_ptr_dtor(&sxe->iter.data);
1.1       misho    1190:                }
1.1.1.2   misho    1191:                sxe->iter.data = iter_data;
1.1       misho    1192:        }
                   1193: 
                   1194:        return rv;
                   1195: }
                   1196: /* }}} */
                   1197: 
1.1.1.3   misho    1198: static HashTable * sxe_get_gc(zval *object, zval ***table, int *n TSRMLS_DC) /* {{{ */ {
                   1199:        php_sxe_object  *sxe;
                   1200:        sxe = php_sxe_fetch_object(object TSRMLS_CC);
                   1201:        
                   1202:        *table = NULL;
                   1203:        *n = 0;
                   1204:        return sxe->properties;
                   1205: }
                   1206: /* }}} */
                   1207: 
1.1       misho    1208: static HashTable * sxe_get_properties(zval *object TSRMLS_DC) /* {{{ */
                   1209: {
                   1210:        return sxe_get_prop_hash(object, 0 TSRMLS_CC);
                   1211: }
                   1212: /* }}} */
                   1213: 
                   1214: static HashTable * sxe_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
                   1215: {
                   1216:        *is_temp = 1;
                   1217:        return sxe_get_prop_hash(object, 1 TSRMLS_CC);
                   1218: }
                   1219: /* }}} */
                   1220: 
                   1221: static int sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC) /* {{{ */
                   1222: {
                   1223:        php_sxe_object *sxe1;
                   1224:        php_sxe_object *sxe2;
                   1225: 
                   1226:        sxe1 = php_sxe_fetch_object(object1 TSRMLS_CC);
                   1227:        sxe2 = php_sxe_fetch_object(object2 TSRMLS_CC);
                   1228: 
                   1229:        if (sxe1->node == NULL) {
                   1230:                if (sxe2->node) {
                   1231:                        return 1;
                   1232:                } else if (sxe1->document->ptr == sxe2->document->ptr) {
                   1233:                        return 0;
                   1234:                }
                   1235:        } else {
                   1236:                return !(sxe1->node == sxe2->node);
                   1237:        }
                   1238:        return 1;
                   1239: }
                   1240: /* }}} */
                   1241: 
                   1242: /* {{{ proto array SimpleXMLElement::xpath(string path)
                   1243:    Runs XPath query on the XML data */
                   1244: SXE_METHOD(xpath)
                   1245: {
                   1246:        php_sxe_object    *sxe;
                   1247:        zval              *value;
                   1248:        char              *query;
                   1249:        int                query_len;
                   1250:        int                i;
                   1251:        int                nsnbr = 0;
                   1252:        xmlNsPtr          *ns = NULL;
                   1253:        xmlXPathObjectPtr  retval;
                   1254:        xmlNodeSetPtr      result;
                   1255:        xmlNodePtr                 nodeptr;
                   1256: 
                   1257:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
                   1258:                return;
                   1259:        }
                   1260: 
                   1261:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1262: 
                   1263:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1264:                return; /* attributes don't have attributes */
                   1265:        }
                   1266: 
                   1267:        if (!sxe->xpath) {
                   1268:                sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
                   1269:        }
                   1270:        if (!sxe->node) {
                   1271:                php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL TSRMLS_CC);
1.1.1.5 ! misho    1272:                if (!sxe->node) {
        !          1273:                        RETURN_FALSE;
        !          1274:                }
1.1       misho    1275:        }
                   1276: 
                   1277:        nodeptr = php_sxe_get_first_node(sxe, sxe->node->node TSRMLS_CC);
                   1278: 
                   1279:        sxe->xpath->node = nodeptr;
                   1280: 
                   1281:        ns = xmlGetNsList((xmlDocPtr) sxe->document->ptr, nodeptr);
                   1282:        if (ns != NULL) {
                   1283:                while (ns[nsnbr] != NULL) {
                   1284:                        nsnbr++;
                   1285:                }
                   1286:        }
                   1287: 
                   1288:        sxe->xpath->namespaces = ns;
                   1289:        sxe->xpath->nsNr = nsnbr;
                   1290: 
                   1291:        retval = xmlXPathEval((xmlChar *)query, sxe->xpath);
                   1292:        if (ns != NULL) {
                   1293:                xmlFree(ns);
                   1294:                sxe->xpath->namespaces = NULL;
                   1295:                sxe->xpath->nsNr = 0;
                   1296:        }
                   1297: 
                   1298:        if (!retval) {
                   1299:                RETURN_FALSE;
                   1300:        }
                   1301: 
                   1302:        result = retval->nodesetval;
                   1303: 
                   1304:        array_init(return_value);
                   1305:                
                   1306:        if (result != NULL) {
                   1307:                for (i = 0; i < result->nodeNr; ++i) {
                   1308:                        nodeptr = result->nodeTab[i];
                   1309:                        if (nodeptr->type == XML_TEXT_NODE || nodeptr->type == XML_ELEMENT_NODE || nodeptr->type == XML_ATTRIBUTE_NODE) {
                   1310:                                MAKE_STD_ZVAL(value);
                   1311:                                /**
                   1312:                                 * Detect the case where the last selector is text(), simplexml
                   1313:                                 * always accesses the text() child by default, therefore we assign
                   1314:                                 * to the parent node.
                   1315:                                 */
                   1316:                                if (nodeptr->type == XML_TEXT_NODE) {
                   1317:                                        _node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_NONE, NULL, NULL, 0 TSRMLS_CC);
                   1318:                                } else if (nodeptr->type == XML_ATTRIBUTE_NODE) {
                   1319:                                        _node_as_zval(sxe, nodeptr->parent, value, SXE_ITER_ATTRLIST, (char*)nodeptr->name, nodeptr->ns ? (xmlChar *)nodeptr->ns->href : NULL, 0 TSRMLS_CC);
                   1320:                                } else {
                   1321:                                        _node_as_zval(sxe, nodeptr, value, SXE_ITER_NONE, NULL, NULL, 0 TSRMLS_CC);
                   1322:                                }
                   1323: 
                   1324:                                add_next_index_zval(return_value, value);
                   1325:                        }
                   1326:                }
                   1327:        }
                   1328: 
                   1329:        xmlXPathFreeObject(retval);
                   1330: }
                   1331: /* }}} */
                   1332: 
                   1333: /* {{{ proto bool SimpleXMLElement::registerXPathNamespace(string prefix, string ns)
                   1334:    Creates a prefix/ns context for the next XPath query */
                   1335: SXE_METHOD(registerXPathNamespace)
                   1336: {
                   1337:        php_sxe_object    *sxe;
                   1338:        int prefix_len, ns_uri_len;
                   1339:        char *prefix, *ns_uri;
                   1340: 
                   1341:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &prefix, &prefix_len, &ns_uri, &ns_uri_len) == FAILURE) {
                   1342:                return;
                   1343:        }
                   1344: 
                   1345:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1346:        if (!sxe->xpath) {
                   1347:                sxe->xpath = xmlXPathNewContext((xmlDocPtr) sxe->document->ptr);
                   1348:        }
                   1349: 
                   1350:        if (xmlXPathRegisterNs(sxe->xpath, (xmlChar *)prefix, (xmlChar *)ns_uri) != 0) {
                   1351:                RETURN_FALSE
                   1352:        }
                   1353:        RETURN_TRUE;
                   1354: }
                   1355: 
                   1356: /* }}} */
                   1357: 
                   1358: /* {{{ proto string SimpleXMLElement::asXML([string filename])
                   1359:    Return a well-formed XML string based on SimpleXML element */
                   1360: SXE_METHOD(asXML)
                   1361: {
                   1362:        php_sxe_object     *sxe;
                   1363:        xmlNodePtr          node;
                   1364:        xmlOutputBufferPtr  outbuf;
                   1365:        xmlChar            *strval;
                   1366:        int                 strval_len;
                   1367:        char               *filename;
                   1368:        int                 filename_len;
                   1369: 
                   1370:        if (ZEND_NUM_ARGS() > 1) {
                   1371:                RETURN_FALSE;
                   1372:        }
                   1373: 
                   1374:        if (ZEND_NUM_ARGS() == 1) {
1.1.1.2   misho    1375:                if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p", &filename, &filename_len) == FAILURE) {
1.1       misho    1376:                        RETURN_FALSE;
                   1377:                }
                   1378: 
                   1379:                sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1380:                GET_NODE(sxe, node);
                   1381:                node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1382: 
                   1383:                if (node) {
                   1384:                        if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
                   1385:                                int bytes;
                   1386:                                bytes = xmlSaveFile(filename, (xmlDocPtr) sxe->document->ptr);
                   1387:                                if (bytes == -1) {
                   1388:                                        RETURN_FALSE;
                   1389:                                } else {
                   1390:                                        RETURN_TRUE;
                   1391:                                }
                   1392:                        } else {
                   1393:                                outbuf = xmlOutputBufferCreateFilename(filename, NULL, 0);
                   1394: 
                   1395:                                if (outbuf == NULL) {
                   1396:                                        RETURN_FALSE;
                   1397:                                }
                   1398: 
                   1399:                                xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, NULL);
                   1400:                                xmlOutputBufferClose(outbuf);
                   1401:                                RETURN_TRUE;
                   1402:                        }
                   1403:                } else {
                   1404:                        RETURN_FALSE;
                   1405:                }
                   1406:        }
                   1407: 
                   1408:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1409:        GET_NODE(sxe, node);
                   1410:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1411: 
                   1412:        if (node) {
                   1413:                if (node->parent && (XML_DOCUMENT_NODE == node->parent->type)) {
                   1414:                        xmlDocDumpMemoryEnc((xmlDocPtr) sxe->document->ptr, &strval, &strval_len, ((xmlDocPtr) sxe->document->ptr)->encoding);
                   1415:                        RETVAL_STRINGL((char *)strval, strval_len, 1);
                   1416:                        xmlFree(strval);
                   1417:                } else {
                   1418:                        /* Should we be passing encoding information instead of NULL? */
                   1419:                        outbuf = xmlAllocOutputBuffer(NULL);
                   1420: 
                   1421:                        if (outbuf == NULL) {
                   1422:                                RETURN_FALSE;
                   1423:                        }
                   1424: 
                   1425:                        xmlNodeDumpOutput(outbuf, (xmlDocPtr) sxe->document->ptr, node, 0, 0, ((xmlDocPtr) sxe->document->ptr)->encoding);
                   1426:                        xmlOutputBufferFlush(outbuf);
1.1.1.3   misho    1427: #ifdef LIBXML2_NEW_BUFFER
                   1428:                        RETVAL_STRINGL((char *)xmlOutputBufferGetContent(outbuf), xmlOutputBufferGetSize(outbuf), 1);
                   1429: #else
1.1       misho    1430:                        RETVAL_STRINGL((char *)outbuf->buffer->content, outbuf->buffer->use, 1);
1.1.1.3   misho    1431: #endif
1.1       misho    1432:                        xmlOutputBufferClose(outbuf);
                   1433:                }
                   1434:        } else {
                   1435:                RETVAL_FALSE;
                   1436:        }
                   1437: }
                   1438: /* }}} */
                   1439: 
                   1440: #define SXE_NS_PREFIX(ns) (ns->prefix ? (char*)ns->prefix : "")
                   1441: 
                   1442: static inline void sxe_add_namespace_name(zval *return_value, xmlNsPtr ns) /* {{{ */
                   1443: {
                   1444:        char *prefix = SXE_NS_PREFIX(ns);
                   1445:        if (zend_hash_exists(Z_ARRVAL_P(return_value), prefix, strlen(prefix) + 1) == 0) {
                   1446:                add_assoc_string(return_value, prefix, (char*)ns->href, 1);
                   1447:        }
                   1448: }
                   1449: /* }}} */
                   1450: 
                   1451: static void sxe_add_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */
                   1452: {
                   1453:        xmlAttrPtr  attr;
                   1454: 
                   1455:        if (node->ns) {
                   1456:                sxe_add_namespace_name(return_value, node->ns);
                   1457:        }
                   1458: 
                   1459:        attr = node->properties;
                   1460:        while (attr) {
                   1461:                if (attr->ns) {
                   1462:                        sxe_add_namespace_name(return_value, attr->ns);
                   1463:                }
                   1464:                attr = attr->next;
                   1465:        }
                   1466: 
                   1467:        if (recursive) {
                   1468:                node = node->children;
                   1469:                while (node) {
                   1470:                        if (node->type == XML_ELEMENT_NODE) {
                   1471:                                sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
                   1472:                        }
                   1473:                        node = node->next;
                   1474:                }
                   1475:        }
                   1476: } /* }}} */
                   1477: 
                   1478: /* {{{ proto string SimpleXMLElement::getNamespaces([bool recursve])
                   1479:    Return all namespaces in use */
                   1480: SXE_METHOD(getNamespaces)
                   1481: {
                   1482:        zend_bool           recursive = 0;
                   1483:        php_sxe_object     *sxe;
                   1484:        xmlNodePtr          node;
                   1485: 
                   1486:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &recursive) == FAILURE) {
                   1487:                return;
                   1488:        }
                   1489: 
                   1490:        array_init(return_value);
                   1491: 
                   1492:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1493:        GET_NODE(sxe, node);
                   1494:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1495: 
                   1496:        if (node) {
                   1497:                if (node->type == XML_ELEMENT_NODE) {
                   1498:                        sxe_add_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
                   1499:                } else if (node->type == XML_ATTRIBUTE_NODE && node->ns) {
                   1500:                        sxe_add_namespace_name(return_value, node->ns);
                   1501:                }
                   1502:        }
                   1503: }
                   1504: /* }}} */
                   1505: 
                   1506: static void sxe_add_registered_namespaces(php_sxe_object *sxe, xmlNodePtr node, zend_bool recursive, zval *return_value TSRMLS_DC) /* {{{ */
                   1507: {
                   1508:        xmlNsPtr ns;
                   1509: 
                   1510:        if (node->type == XML_ELEMENT_NODE) {
                   1511:                ns = node->nsDef;
                   1512:                while (ns != NULL) {
                   1513:                        sxe_add_namespace_name(return_value, ns);
                   1514:                        ns = ns->next;
                   1515:                }
                   1516:                if (recursive) {
                   1517:                        node = node->children;
                   1518:                        while (node) {
                   1519:                                sxe_add_registered_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
                   1520:                                node = node->next;
                   1521:                        }
                   1522:                }
                   1523:        }
                   1524: }
                   1525: /* }}} */
                   1526: 
1.1.1.3   misho    1527: /* {{{ proto string SimpleXMLElement::getDocNamespaces([bool recursive [, bool from_root])
1.1       misho    1528:    Return all namespaces registered with document */
                   1529: SXE_METHOD(getDocNamespaces)
                   1530: {
1.1.1.3   misho    1531:        zend_bool           recursive = 0, from_root = 1;
1.1       misho    1532:        php_sxe_object     *sxe;
1.1.1.3   misho    1533:        xmlNodePtr          node;
1.1       misho    1534: 
1.1.1.3   misho    1535:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &recursive, &from_root) == FAILURE) {
1.1       misho    1536:                return;
                   1537:        }
                   1538: 
                   1539:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
1.1.1.3   misho    1540:        if(from_root){
                   1541:                node = xmlDocGetRootElement((xmlDocPtr)sxe->document->ptr);
                   1542:        }else{
                   1543:                GET_NODE(sxe, node);
                   1544:        }
1.1.1.5 ! misho    1545:        
        !          1546:        if (node == NULL) {
        !          1547:                RETURN_FALSE;
        !          1548:        }
        !          1549:        
        !          1550:        array_init(return_value);
1.1.1.3   misho    1551:        sxe_add_registered_namespaces(sxe, node, recursive, return_value TSRMLS_CC);
1.1       misho    1552: }
                   1553: /* }}} */
                   1554: 
                   1555: /* {{{ proto object SimpleXMLElement::children([string ns [, bool is_prefix]])
                   1556:    Finds children of given node */
                   1557: SXE_METHOD(children)
                   1558: {
                   1559:        php_sxe_object *sxe;
                   1560:        char           *nsprefix = NULL;
                   1561:        int             nsprefix_len = 0;
                   1562:        xmlNodePtr      node;
                   1563:        zend_bool       isprefix = 0;
                   1564: 
                   1565:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
                   1566:                return;
                   1567:        }
                   1568: 
                   1569:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1570: 
                   1571:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1572:                return; /* attributes don't have attributes */
                   1573:        }
                   1574: 
                   1575:        GET_NODE(sxe, node);
                   1576:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1577: 
                   1578:        _node_as_zval(sxe, node, return_value, SXE_ITER_CHILD, NULL, (xmlChar *)nsprefix, isprefix TSRMLS_CC);
                   1579: 
                   1580: }
                   1581: /* }}} */
                   1582: 
                   1583: /* {{{ proto object SimpleXMLElement::getName()
                   1584:    Finds children of given node */
                   1585: SXE_METHOD(getName)
                   1586: {
                   1587:        php_sxe_object *sxe;
                   1588:        xmlNodePtr      node;
                   1589:        int             namelen;
                   1590: 
                   1591:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1592: 
                   1593:        GET_NODE(sxe, node);
                   1594:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1595:        if (node) {
                   1596:                namelen = xmlStrlen(node->name);
                   1597:                RETURN_STRINGL((char*)node->name, namelen, 1);
                   1598:        } else {
                   1599:                RETURN_EMPTY_STRING();
                   1600:        }
                   1601: }
                   1602: /* }}} */
                   1603: 
                   1604: /* {{{ proto array SimpleXMLElement::attributes([string ns [, bool is_prefix]])
                   1605:    Identifies an element's attributes */
                   1606: SXE_METHOD(attributes)
                   1607: {
                   1608:        php_sxe_object *sxe;
                   1609:        char           *nsprefix = NULL;
                   1610:        int             nsprefix_len = 0;
                   1611:        xmlNodePtr      node;
                   1612:        zend_bool       isprefix = 0;
                   1613: 
                   1614:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s!b", &nsprefix, &nsprefix_len, &isprefix) == FAILURE) {
                   1615:                return;
                   1616:        }
                   1617: 
                   1618:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1619:        GET_NODE(sxe, node);
                   1620: 
                   1621:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1622:                return; /* attributes don't have attributes */
                   1623:        }
                   1624: 
                   1625:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1626: 
                   1627:        _node_as_zval(sxe, node, return_value, SXE_ITER_ATTRLIST, NULL, (xmlChar *)nsprefix, isprefix TSRMLS_CC);
                   1628: }
                   1629: /* }}} */
                   1630: 
                   1631: /* {{{ proto void SimpleXMLElement::addChild(string qName [, string value [, string ns]])
                   1632:    Add Element with optional namespace information */
                   1633: SXE_METHOD(addChild)
                   1634: {
                   1635:        php_sxe_object *sxe;
                   1636:        char           *qname, *value = NULL, *nsuri = NULL;
                   1637:        int             qname_len, value_len = 0, nsuri_len = 0;
                   1638:        xmlNodePtr      node, newnode;
                   1639:        xmlNsPtr        nsptr = NULL;
                   1640:        xmlChar        *localname, *prefix = NULL;
                   1641: 
                   1642:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s!s!",
                   1643:                &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
                   1644:                return;
                   1645:        }
                   1646: 
                   1647:        if (qname_len == 0) {
                   1648:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Element name is required");
                   1649:                return;
                   1650:        }
                   1651: 
                   1652:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1653:        GET_NODE(sxe, node);
                   1654: 
                   1655:        if (sxe->iter.type == SXE_ITER_ATTRLIST) {
                   1656:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add element to attributes");
                   1657:                return;
                   1658:        }
                   1659: 
                   1660:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1661: 
                   1662:        if (node == NULL) {
                   1663:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot add child. Parent is not a permanent member of the XML tree");
                   1664:                return;
                   1665:        }
                   1666: 
                   1667:        localname = xmlSplitQName2((xmlChar *)qname, &prefix);
                   1668:        if (localname == NULL) {
                   1669:                localname = xmlStrdup((xmlChar *)qname);
                   1670:        }
                   1671: 
                   1672:        newnode = xmlNewChild(node, NULL, localname, (xmlChar *)value);
                   1673: 
                   1674:        if (nsuri != NULL) {
                   1675:                if (nsuri_len == 0) {
                   1676:                        newnode->ns = NULL;
                   1677:                        nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
                   1678:                } else {
                   1679:                        nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
                   1680:                        if (nsptr == NULL) {
                   1681:                                nsptr = xmlNewNs(newnode, (xmlChar *)nsuri, prefix);
                   1682:                        }
                   1683:                        newnode->ns = nsptr;
                   1684:                }
                   1685:        }
                   1686: 
                   1687:        _node_as_zval(sxe, newnode, return_value, SXE_ITER_NONE, (char *)localname, prefix, 0 TSRMLS_CC);
                   1688: 
                   1689:        xmlFree(localname);
                   1690:        if (prefix != NULL) {
                   1691:                xmlFree(prefix);
                   1692:        }
                   1693: }
                   1694: /* }}} */
                   1695: 
                   1696: /* {{{ proto void SimpleXMLElement::addAttribute(string qName, string value [,string ns])
                   1697:    Add Attribute with optional namespace information */
                   1698: SXE_METHOD(addAttribute)
                   1699: {
                   1700:        php_sxe_object *sxe;
                   1701:        char           *qname, *value = NULL, *nsuri = NULL;
                   1702:        int             qname_len, value_len = 0, nsuri_len = 0;
                   1703:        xmlNodePtr      node;
                   1704:        xmlAttrPtr      attrp = NULL;
                   1705:        xmlNsPtr        nsptr = NULL;
                   1706:        xmlChar        *localname, *prefix = NULL;
                   1707: 
                   1708:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s!",
                   1709:                &qname, &qname_len, &value, &value_len, &nsuri, &nsuri_len) == FAILURE) {
                   1710:                return;
                   1711:        }
                   1712: 
                   1713:        if (qname_len == 0) {
                   1714:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute name is required");
                   1715:                return;
                   1716:        }
                   1717: 
                   1718:        sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1719:        GET_NODE(sxe, node);
                   1720: 
                   1721:        node = php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   1722: 
                   1723:        if (node && node->type != XML_ELEMENT_NODE) {
                   1724:                node = node->parent;
                   1725:        }
                   1726: 
                   1727:        if (node == NULL) {
                   1728:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate parent Element");
                   1729:                return;
                   1730:        }
                   1731: 
                   1732:        localname = xmlSplitQName2((xmlChar *)qname, &prefix);
                   1733:        if (localname == NULL) {
                   1734:                if (nsuri_len > 0) {
                   1735:                        if (prefix != NULL) {
                   1736:                                xmlFree(prefix);
                   1737:                        }
                   1738:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute requires prefix for namespace");
                   1739:                        return;
                   1740:                }
                   1741:                localname = xmlStrdup((xmlChar *)qname);
                   1742:        }
                   1743: 
                   1744:        attrp = xmlHasNsProp(node, localname, (xmlChar *)nsuri);
                   1745:        if (attrp != NULL && attrp->type != XML_ATTRIBUTE_DECL) {
                   1746:                xmlFree(localname);
                   1747:                if (prefix != NULL) {
                   1748:                        xmlFree(prefix);
                   1749:                }
                   1750:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attribute already exists");
                   1751:                return;
                   1752:        }
                   1753: 
                   1754:        if (nsuri != NULL) {
                   1755:                nsptr = xmlSearchNsByHref(node->doc, node, (xmlChar *)nsuri);
                   1756:                if (nsptr == NULL) {
                   1757:                        nsptr = xmlNewNs(node, (xmlChar *)nsuri, prefix);
                   1758:                }
                   1759:        }
                   1760: 
                   1761:        attrp = xmlNewNsProp(node, nsptr, localname, (xmlChar *)value);
                   1762: 
                   1763:        xmlFree(localname);
                   1764:        if (prefix != NULL) {
                   1765:                xmlFree(prefix);
                   1766:        }
                   1767: }
                   1768: /* }}} */
                   1769: 
                   1770: /* {{{ cast_object()
                   1771:  */
                   1772: static int cast_object(zval *object, int type, char *contents TSRMLS_DC)
                   1773: {
                   1774:        if (contents) {
                   1775:                ZVAL_STRINGL(object, contents, strlen(contents), 1);
                   1776:        } else {
                   1777:                ZVAL_NULL(object);
                   1778:        }
                   1779:        Z_SET_REFCOUNT_P(object, 1);
                   1780:        Z_UNSET_ISREF_P(object);
                   1781: 
                   1782:        switch (type) {
                   1783:                case IS_STRING:
                   1784:                        convert_to_string(object);
                   1785:                        break;
                   1786:                case IS_BOOL:
                   1787:                        convert_to_boolean(object);
                   1788:                        break;
                   1789:                case IS_LONG:
                   1790:                        convert_to_long(object);
                   1791:                        break;
                   1792:                case IS_DOUBLE:
                   1793:                        convert_to_double(object);
                   1794:                        break;
                   1795:                default:
                   1796:                        return FAILURE;
                   1797:        }
                   1798:        return SUCCESS;
                   1799: }
                   1800: /* }}} */
                   1801: 
                   1802: /* {{{ sxe_object_cast()
                   1803:  */
                   1804: static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
                   1805: {
                   1806:        php_sxe_object *sxe;
                   1807:        xmlChar           *contents = NULL;
                   1808:        xmlNodePtr          node;
                   1809:        int rv;
                   1810:        HashTable      *prop_hash;
                   1811: 
                   1812:        sxe = php_sxe_fetch_object(readobj TSRMLS_CC);
                   1813: 
                   1814:        if (type == IS_BOOL) {
                   1815:                node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
                   1816:                prop_hash = sxe_get_prop_hash(readobj, 1 TSRMLS_CC);
                   1817:                INIT_PZVAL(writeobj);
                   1818:                ZVAL_BOOL(writeobj, node != NULL || zend_hash_num_elements(prop_hash) > 0);
                   1819:                zend_hash_destroy(prop_hash);
                   1820:                efree(prop_hash);
                   1821:                return SUCCESS;
                   1822:        }
                   1823: 
                   1824:        if (sxe->iter.type != SXE_ITER_NONE) {
                   1825:                node = php_sxe_get_first_node(sxe, NULL TSRMLS_CC);
                   1826:                if (node) {
                   1827:                        contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, node->children, 1);
                   1828:                }
                   1829:        } else {
                   1830:                if (!sxe->node) {
                   1831:                        if (sxe->document) {
                   1832:                                php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement((xmlDocPtr) sxe->document->ptr), NULL TSRMLS_CC);
                   1833:                        }
                   1834:                }
                   1835: 
                   1836:                if (sxe->node && sxe->node->node) {
                   1837:                        if (sxe->node->node->children) {
                   1838:                                contents = xmlNodeListGetString((xmlDocPtr) sxe->document->ptr, sxe->node->node->children, 1);
                   1839:                        }
                   1840:                }
                   1841:        }
                   1842: 
                   1843:        if (readobj == writeobj) {
                   1844:                INIT_PZVAL(writeobj);
                   1845:                zval_dtor(readobj);
                   1846:        }
                   1847: 
                   1848:        rv = cast_object(writeobj, type, (char *)contents TSRMLS_CC);
                   1849: 
                   1850:        if (contents) {
                   1851:                xmlFree(contents);
                   1852:        }
                   1853:        return rv;
                   1854: }
                   1855: /* }}} */
                   1856: 
                   1857: /* {{{ proto object SimpleXMLElement::__toString() U
                   1858:    Returns the string content */
                   1859: SXE_METHOD(__toString)
                   1860: {
                   1861:        zval           *result;
                   1862: 
                   1863:        ALLOC_INIT_ZVAL(result);
                   1864: 
                   1865:        if (sxe_object_cast(getThis(), result, IS_STRING TSRMLS_CC) == SUCCESS) {
                   1866:                RETURN_ZVAL(result, 1, 1);
                   1867:        } else {
                   1868:                zval_ptr_dtor(&result);
                   1869:                RETURN_EMPTY_STRING();
                   1870:        }
                   1871: }
                   1872: /* }}} */
                   1873: 
                   1874: static int php_sxe_count_elements_helper(php_sxe_object *sxe, long *count TSRMLS_DC) /* {{{ */
                   1875: {
                   1876:        xmlNodePtr       node;
                   1877:        zval            *data;
                   1878: 
                   1879:        *count = 0;
                   1880: 
                   1881:        data = sxe->iter.data;
                   1882:        sxe->iter.data = NULL;
                   1883: 
                   1884:        node = php_sxe_reset_iterator(sxe, 0 TSRMLS_CC);
                   1885: 
                   1886:        while (node)
                   1887:        {
                   1888:                (*count)++;
                   1889:                node = php_sxe_iterator_fetch(sxe, node->next, 0 TSRMLS_CC);
                   1890:        }
                   1891: 
                   1892:        if (sxe->iter.data) {
                   1893:                zval_ptr_dtor(&sxe->iter.data);
                   1894:        }
                   1895:        sxe->iter.data = data;
                   1896: 
                   1897:        return SUCCESS;
                   1898: }
                   1899: /* }}} */
                   1900: 
                   1901: static int sxe_count_elements(zval *object, long *count TSRMLS_DC) /* {{{ */
                   1902: {
                   1903:        php_sxe_object  *intern;
                   1904:        intern = php_sxe_fetch_object(object TSRMLS_CC);
                   1905:        if (intern->fptr_count) {
                   1906:                zval *rv;
                   1907:                zend_call_method_with_0_params(&object, intern->zo.ce, &intern->fptr_count, "count", &rv);
                   1908:                if (rv) {
                   1909:                        if (intern->tmp) {
                   1910:                                zval_ptr_dtor(&intern->tmp);
                   1911:                        }
                   1912:                        MAKE_STD_ZVAL(intern->tmp);
                   1913:                        ZVAL_ZVAL(intern->tmp, rv, 1, 1);
                   1914:                        convert_to_long(intern->tmp);
                   1915:                        *count = (long) Z_LVAL_P(intern->tmp);
                   1916:                        return SUCCESS;
                   1917:                }
                   1918:                return FAILURE;
                   1919:        }
                   1920:        return php_sxe_count_elements_helper(intern, count TSRMLS_CC);
                   1921: }
                   1922: /* }}} */
                   1923: 
                   1924: /* {{{ proto int SimpleXMLElement::count()
                   1925:  Get number of child elements */
                   1926: SXE_METHOD(count)
                   1927: {
                   1928:        long count = 0;
                   1929:        php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   1930: 
                   1931:        if (zend_parse_parameters_none() == FAILURE) {
                   1932:                return;
                   1933:        }
                   1934: 
                   1935:        php_sxe_count_elements_helper(sxe, &count TSRMLS_CC);
                   1936:        
                   1937:        RETURN_LONG(count);
                   1938: }
                   1939: /* }}} */
                   1940: 
                   1941: static zval *sxe_get_value(zval *z TSRMLS_DC) /* {{{ */
                   1942: {
                   1943:        zval *retval;
                   1944: 
                   1945:        MAKE_STD_ZVAL(retval);
                   1946: 
                   1947:        if (sxe_object_cast(z, retval, IS_STRING TSRMLS_CC)==FAILURE) {
                   1948:                zend_error(E_ERROR, "Unable to cast node to string");
                   1949:                /* FIXME: Should not be fatal */
                   1950:        }
                   1951: 
                   1952:        Z_SET_REFCOUNT_P(retval, 0);
                   1953:        return retval;
                   1954: }
                   1955: /* }}} */
                   1956: 
                   1957: static zend_object_handlers sxe_object_handlers = { /* {{{ */
                   1958:        ZEND_OBJECTS_STORE_HANDLERS,
                   1959:        sxe_property_read,
                   1960:        sxe_property_write,
                   1961:        sxe_dimension_read,
                   1962:        sxe_dimension_write,
                   1963:        sxe_property_get_adr,
                   1964:        sxe_get_value,                  /* get */
                   1965:        NULL,
                   1966:        sxe_property_exists,
                   1967:        sxe_property_delete,
                   1968:        sxe_dimension_exists,
                   1969:        sxe_dimension_delete,
                   1970:        sxe_get_properties,
                   1971:        NULL, /* zend_get_std_object_handlers()->get_method,*/
                   1972:        NULL, /* zend_get_std_object_handlers()->call_method,*/
                   1973:        NULL, /* zend_get_std_object_handlers()->get_constructor, */
                   1974:        NULL, /* zend_get_std_object_handlers()->get_class_entry,*/
                   1975:        NULL, /* zend_get_std_object_handlers()->get_class_name,*/
                   1976:        sxe_objects_compare,
                   1977:        sxe_object_cast,
                   1978:        sxe_count_elements,
1.1.1.3   misho    1979:        sxe_get_debug_info,
                   1980:        NULL,
                   1981:        sxe_get_gc
1.1       misho    1982: };
                   1983: /* }}} */
                   1984: 
                   1985: /* {{{ sxe_object_clone()
                   1986:  */
                   1987: static void
                   1988: sxe_object_clone(void *object, void **clone_ptr TSRMLS_DC)
                   1989: {
                   1990:        php_sxe_object *sxe = (php_sxe_object *) object;
                   1991:        php_sxe_object *clone;
                   1992:        xmlNodePtr nodep = NULL;
                   1993:        xmlDocPtr docp = NULL;
                   1994: 
                   1995:        clone = php_sxe_object_new(sxe->zo.ce TSRMLS_CC);
                   1996:        clone->document = sxe->document;
                   1997:        if (clone->document) {
                   1998:                clone->document->refcount++;
                   1999:                docp = clone->document->ptr;
                   2000:        }
                   2001: 
                   2002:        clone->iter.isprefix = sxe->iter.isprefix;
                   2003:        if (sxe->iter.name != NULL) {
                   2004:                clone->iter.name = xmlStrdup((xmlChar *)sxe->iter.name);
                   2005:        }
                   2006:        if (sxe->iter.nsprefix != NULL) {
                   2007:                clone->iter.nsprefix = xmlStrdup((xmlChar *)sxe->iter.nsprefix);
                   2008:        }
                   2009:        clone->iter.type = sxe->iter.type;
                   2010: 
                   2011:        if (sxe->node) {
                   2012:                nodep = xmlDocCopyNode(sxe->node->node, docp, 1);
                   2013:        }
                   2014: 
                   2015:        php_libxml_increment_node_ptr((php_libxml_node_object *)clone, nodep, NULL TSRMLS_CC);
                   2016: 
                   2017:        *clone_ptr = (void *) clone;
                   2018: }
                   2019: /* }}} */
                   2020: 
                   2021: /* {{{ sxe_object_dtor()
                   2022:  */
                   2023: static void sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
                   2024: {
                   2025:        /* dtor required to cleanup iterator related data properly */
                   2026: 
                   2027:        php_sxe_object *sxe;
                   2028: 
                   2029:        sxe = (php_sxe_object *) object;
                   2030: 
                   2031:        if (sxe->iter.data) {
                   2032:                zval_ptr_dtor(&sxe->iter.data);
                   2033:                sxe->iter.data = NULL;
                   2034:        }
                   2035: 
                   2036:        if (sxe->iter.name) {
                   2037:                xmlFree(sxe->iter.name);
                   2038:                sxe->iter.name = NULL;
                   2039:        }
                   2040:        if (sxe->iter.nsprefix) {
                   2041:                xmlFree(sxe->iter.nsprefix);
                   2042:                sxe->iter.nsprefix = NULL;
                   2043:        }
                   2044:        if (sxe->tmp) {
                   2045:                zval_ptr_dtor(&sxe->tmp);
                   2046:                sxe->tmp = NULL;
                   2047:        }
                   2048: }
                   2049: /* }}} */
                   2050: 
                   2051: /* {{{ sxe_object_free_storage()
                   2052:  */
                   2053: static void sxe_object_free_storage(void *object TSRMLS_DC)
                   2054: {
                   2055:        php_sxe_object *sxe;
                   2056: 
                   2057:        sxe = (php_sxe_object *) object;
                   2058: 
                   2059: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
                   2060:        zend_object_std_dtor(&sxe->zo TSRMLS_CC);
                   2061: #else
                   2062:        if (sxe->zo.guards) {
                   2063:                zend_hash_destroy(sxe->zo.guards);
                   2064:                FREE_HASHTABLE(sxe->zo.guards);
                   2065:        }
                   2066: 
                   2067:        if (sxe->zo.properties) {
                   2068:                zend_hash_destroy(sxe->zo.properties);
                   2069:                FREE_HASHTABLE(sxe->zo.properties);
                   2070:        }
                   2071: #endif
                   2072: 
                   2073:        php_libxml_node_decrement_resource((php_libxml_node_object *)sxe TSRMLS_CC);
                   2074: 
                   2075:        if (sxe->xpath) {
                   2076:                xmlXPathFreeContext(sxe->xpath);
                   2077:        }
                   2078: 
                   2079:        if (sxe->properties) {
                   2080:                zend_hash_destroy(sxe->properties);
                   2081:                FREE_HASHTABLE(sxe->properties);
                   2082:        }
                   2083: 
                   2084:        efree(object);
                   2085: }
                   2086: /* }}} */
                   2087: 
                   2088: /* {{{ php_sxe_object_new()
                   2089:  */
                   2090: static php_sxe_object* php_sxe_object_new(zend_class_entry *ce TSRMLS_DC)
                   2091: {
                   2092:        php_sxe_object *intern;
                   2093:        zend_class_entry     *parent = ce;
                   2094:        int inherited = 0;
                   2095: 
                   2096:        intern = ecalloc(1, sizeof(php_sxe_object));
                   2097: 
                   2098:        intern->iter.type = SXE_ITER_NONE;
                   2099:        intern->iter.nsprefix = NULL;
                   2100:        intern->iter.name = NULL;
                   2101:        intern->fptr_count = NULL;
                   2102: 
                   2103: #if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 1 && PHP_RELEASE_VERSION > 2) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 1) || (PHP_MAJOR_VERSION > 5)
                   2104:        zend_object_std_init(&intern->zo, ce TSRMLS_CC);
                   2105: #else
                   2106:        ALLOC_HASHTABLE(intern->zo.properties);
                   2107:        zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
                   2108: 
                   2109:        intern->zo.ce = ce;
                   2110:        intern->zo.guards = NULL;
                   2111: #endif
                   2112: 
                   2113:        while (parent) {
                   2114:                if (parent == sxe_class_entry) {
                   2115:                        break;
                   2116:                }
                   2117: 
                   2118:                parent = parent->parent;
                   2119:                inherited = 1;
                   2120:        }
                   2121: 
                   2122:        if (inherited) {
                   2123:                zend_hash_find(&ce->function_table, "count", sizeof("count"),(void **) &intern->fptr_count);
                   2124:                if (intern->fptr_count->common.scope == parent) {
                   2125:                        intern->fptr_count = NULL;
                   2126:                }
                   2127:        }
                   2128: 
                   2129:        return intern;
                   2130: }
                   2131: /* }}} */
                   2132: 
                   2133: /* {{{ php_sxe_register_object
                   2134:  */
                   2135: static zend_object_value
                   2136: php_sxe_register_object(php_sxe_object *intern TSRMLS_DC)
                   2137: {
                   2138:        zend_object_value rv;
                   2139: 
                   2140:        rv.handle = zend_objects_store_put(intern, sxe_object_dtor, (zend_objects_free_object_storage_t)sxe_object_free_storage, sxe_object_clone TSRMLS_CC);
                   2141:        rv.handlers = (zend_object_handlers *) &sxe_object_handlers;
                   2142: 
                   2143:        return rv;
                   2144: }
                   2145: /* }}} */
                   2146: 
                   2147: /* {{{ sxe_object_new()
                   2148:  */
                   2149: PHP_SXE_API zend_object_value
                   2150: sxe_object_new(zend_class_entry *ce TSRMLS_DC)
                   2151: {
                   2152:        php_sxe_object    *intern;
                   2153: 
                   2154:        intern = php_sxe_object_new(ce TSRMLS_CC);
                   2155:        return php_sxe_register_object(intern TSRMLS_CC);
                   2156: }
                   2157: /* }}} */
                   2158: 
                   2159: /* {{{ proto simplemxml_element simplexml_load_file(string filename [, string class_name [, int options [, string ns [, bool is_prefix]]]])
                   2160:    Load a filename and return a simplexml_element object to allow for processing */
                   2161: PHP_FUNCTION(simplexml_load_file)
                   2162: {
                   2163:        php_sxe_object *sxe;
                   2164:        char           *filename;
                   2165:        int             filename_len;
                   2166:        xmlDocPtr       docp;
                   2167:        char           *ns = NULL;
                   2168:        int             ns_len = 0;
                   2169:        long            options = 0;
                   2170:        zend_class_entry *ce= sxe_class_entry;
                   2171:        zend_bool       isprefix = 0;
                   2172: 
1.1.1.2   misho    2173:        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    2174:                return;
                   2175:        }
                   2176: 
                   2177:        docp = xmlReadFile(filename, NULL, options);
                   2178: 
                   2179:        if (! docp) {
                   2180:                RETURN_FALSE;
                   2181:        }
                   2182: 
                   2183:        if (!ce) {
                   2184:                ce = sxe_class_entry;
                   2185:        }
                   2186:        sxe = php_sxe_object_new(ce TSRMLS_CC);
                   2187:        sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
                   2188:        sxe->iter.isprefix = isprefix;
                   2189:        php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
                   2190:        php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
                   2191: 
                   2192:        return_value->type = IS_OBJECT;
                   2193:        return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
                   2194: }
                   2195: /* }}} */
                   2196: 
                   2197: /* {{{ proto simplemxml_element simplexml_load_string(string data [, string class_name [, int options [, string ns [, bool is_prefix]]]])
                   2198:    Load a string and return a simplexml_element object to allow for processing */
                   2199: PHP_FUNCTION(simplexml_load_string)
                   2200: {
                   2201:        php_sxe_object *sxe;
                   2202:        char           *data;
                   2203:        int             data_len;
                   2204:        xmlDocPtr       docp;
                   2205:        char           *ns = NULL;
                   2206:        int             ns_len = 0;
                   2207:        long            options = 0;
                   2208:        zend_class_entry *ce= sxe_class_entry;
                   2209:        zend_bool       isprefix = 0;
                   2210: 
                   2211:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|C!lsb", &data, &data_len, &ce, &options, &ns, &ns_len, &isprefix) == FAILURE) {
                   2212:                return;
                   2213:        }
                   2214: 
                   2215:        docp = xmlReadMemory(data, data_len, NULL, NULL, options);
                   2216: 
                   2217:        if (! docp) {
                   2218:                RETURN_FALSE;
                   2219:        }
                   2220: 
                   2221:        if (!ce) {
                   2222:                ce = sxe_class_entry;
                   2223:        }
                   2224:        sxe = php_sxe_object_new(ce TSRMLS_CC);
                   2225:        sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
                   2226:        sxe->iter.isprefix = isprefix;
                   2227:        php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
                   2228:        php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
                   2229: 
                   2230:        return_value->type = IS_OBJECT;
                   2231:        return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
                   2232: }
                   2233: /* }}} */
                   2234: 
                   2235: /* {{{ proto SimpleXMLElement::__construct(string data [, int options [, bool data_is_url [, string ns [, bool is_prefix]]]])
                   2236:    SimpleXMLElement constructor */
                   2237: SXE_METHOD(__construct)
                   2238: {
                   2239:        php_sxe_object *sxe = php_sxe_fetch_object(getThis() TSRMLS_CC);
                   2240:        char           *data, *ns = NULL;
                   2241:        int             data_len, ns_len = 0;
                   2242:        xmlDocPtr       docp;
                   2243:        long            options = 0;
                   2244:        zend_bool       is_url = 0, isprefix = 0;
                   2245:        zend_error_handling error_handling;
                   2246: 
                   2247:        zend_replace_error_handling(EH_THROW, NULL, &error_handling TSRMLS_CC);
                   2248:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lbsb", &data, &data_len, &options, &is_url, &ns, &ns_len, &isprefix) == FAILURE) {
                   2249:                zend_restore_error_handling(&error_handling TSRMLS_CC);
                   2250:                return;
                   2251:        }
                   2252: 
                   2253:        zend_restore_error_handling(&error_handling TSRMLS_CC);
                   2254: 
                   2255:        docp = is_url ? xmlReadFile(data, NULL, options) : xmlReadMemory(data, data_len, NULL, NULL, options);
                   2256: 
                   2257:        if (!docp) {
                   2258:                ((php_libxml_node_object *)sxe)->document = NULL;
                   2259:                zend_throw_exception(zend_exception_get_default(TSRMLS_C), "String could not be parsed as XML", 0 TSRMLS_CC);
                   2260:                return;
                   2261:        }
                   2262: 
                   2263:        sxe->iter.nsprefix = ns_len ? xmlStrdup((xmlChar *)ns) : NULL;
                   2264:        sxe->iter.isprefix = isprefix;
                   2265:        php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, docp TSRMLS_CC);
                   2266:        php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, xmlDocGetRootElement(docp), NULL TSRMLS_CC);
                   2267: }
                   2268: /* }}} */
                   2269: 
                   2270: zend_object_iterator_funcs php_sxe_iterator_funcs = { /* {{{ */
                   2271:        php_sxe_iterator_dtor,
                   2272:        php_sxe_iterator_valid,
                   2273:        php_sxe_iterator_current_data,
                   2274:        php_sxe_iterator_current_key,
                   2275:        php_sxe_iterator_move_forward,
                   2276:        php_sxe_iterator_rewind,
                   2277: };
                   2278: /* }}} */
                   2279: 
                   2280: static xmlNodePtr php_sxe_iterator_fetch(php_sxe_object *sxe, xmlNodePtr node, int use_data TSRMLS_DC) /* {{{ */
                   2281: {
                   2282:        xmlChar *prefix  = sxe->iter.nsprefix;
                   2283:        int isprefix  = sxe->iter.isprefix;
                   2284:        int test_elem = sxe->iter.type == SXE_ITER_ELEMENT  && sxe->iter.name;
                   2285:        int test_attr = sxe->iter.type == SXE_ITER_ATTRLIST && sxe->iter.name;
                   2286: 
                   2287:        while (node) {
                   2288:                SKIP_TEXT(node);
                   2289:                if (sxe->iter.type != SXE_ITER_ATTRLIST && node->type == XML_ELEMENT_NODE) {
                   2290:                        if ((!test_elem || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) {
                   2291:                                break;
                   2292:                        }
                   2293:                } else if (node->type == XML_ATTRIBUTE_NODE) {
                   2294:                        if ((!test_attr || !xmlStrcmp(node->name, sxe->iter.name)) && match_ns(sxe, node, prefix, isprefix)) {
                   2295:                                break;
                   2296:                        }
                   2297:                }
                   2298: next_iter:
                   2299:                node = node->next;
                   2300:        }
                   2301: 
                   2302:        if (node && use_data) {
                   2303:                ALLOC_INIT_ZVAL(sxe->iter.data);
                   2304:                _node_as_zval(sxe, node, sxe->iter.data, SXE_ITER_NONE, NULL, prefix, isprefix TSRMLS_CC);
                   2305:        }
                   2306: 
                   2307:        return node;
                   2308: }
                   2309: /* }}} */
                   2310: 
                   2311: static xmlNodePtr php_sxe_reset_iterator(php_sxe_object *sxe, int use_data TSRMLS_DC) /* {{{ */
                   2312: {
                   2313:        xmlNodePtr node;
                   2314: 
                   2315:        if (sxe->iter.data) {
                   2316:                zval_ptr_dtor(&sxe->iter.data);
                   2317:                sxe->iter.data = NULL;
                   2318:        }
                   2319: 
                   2320:        GET_NODE(sxe, node)
                   2321: 
                   2322:        if (node) {
                   2323:                switch (sxe->iter.type) {
                   2324:                        case SXE_ITER_ELEMENT:
                   2325:                        case SXE_ITER_CHILD:
                   2326:                        case SXE_ITER_NONE:
                   2327:                                node = node->children;
                   2328:                                break;
                   2329:                        case SXE_ITER_ATTRLIST:
                   2330:                                node = (xmlNodePtr) node->properties;
                   2331:                }
                   2332:                return php_sxe_iterator_fetch(sxe, node, use_data TSRMLS_CC);
                   2333:        }
                   2334:        return NULL;
                   2335: }
                   2336: /* }}} */
                   2337: 
                   2338: zend_object_iterator *php_sxe_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */
                   2339: {
                   2340:        php_sxe_iterator *iterator;
                   2341: 
                   2342:        if (by_ref) {
                   2343:                zend_error(E_ERROR, "An iterator cannot be used with foreach by reference");
                   2344:        }
                   2345:        iterator = emalloc(sizeof(php_sxe_iterator));
                   2346: 
                   2347:        Z_ADDREF_P(object);
                   2348:        iterator->intern.data = (void*)object;
                   2349:        iterator->intern.funcs = &php_sxe_iterator_funcs;
                   2350:        iterator->sxe = php_sxe_fetch_object(object TSRMLS_CC);
                   2351: 
                   2352:        return (zend_object_iterator*)iterator;
                   2353: }
                   2354: /* }}} */
                   2355: 
                   2356: static void php_sxe_iterator_dtor(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2357: {
                   2358:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2359: 
                   2360:        /* cleanup handled in sxe_object_dtor as we dont always have an iterator wrapper */
                   2361:        if (iterator->intern.data) {
                   2362:                zval_ptr_dtor((zval**)&iterator->intern.data);
                   2363:        }
                   2364: 
                   2365:        efree(iterator);
                   2366: }
                   2367: /* }}} */
                   2368: 
                   2369: static int php_sxe_iterator_valid(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2370: {
                   2371:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2372: 
                   2373:        return iterator->sxe->iter.data ? SUCCESS : FAILURE;
                   2374: }
                   2375: /* }}} */
                   2376: 
                   2377: static void php_sxe_iterator_current_data(zend_object_iterator *iter, zval ***data TSRMLS_DC) /* {{{ */
                   2378: {
                   2379:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2380: 
                   2381:        *data = &iterator->sxe->iter.data;
                   2382: }
                   2383: /* }}} */
                   2384: 
                   2385: static int php_sxe_iterator_current_key(zend_object_iterator *iter, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */
                   2386: {
                   2387:        zval *curobj;
                   2388:        xmlNodePtr curnode = NULL;
                   2389:        php_sxe_object *intern;
                   2390:        int namelen;
                   2391: 
                   2392:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2393:        curobj = iterator->sxe->iter.data;
                   2394: 
                   2395:        intern = (php_sxe_object *)zend_object_store_get_object(curobj TSRMLS_CC);
                   2396:        if (intern != NULL && intern->node != NULL) {
                   2397:                curnode = (xmlNodePtr)((php_libxml_node_ptr *)intern->node)->node;
                   2398:        }
                   2399:        if (!curnode) {
                   2400:                return HASH_KEY_NON_EXISTANT;
                   2401:        }
                   2402: 
                   2403:        namelen = xmlStrlen(curnode->name);
                   2404:        *str_key = estrndup((char *)curnode->name, namelen);
                   2405:        *str_key_len = namelen + 1;
                   2406:        return HASH_KEY_IS_STRING;
                   2407: 
                   2408: }
                   2409: /* }}} */
                   2410: 
                   2411: PHP_SXE_API void php_sxe_move_forward_iterator(php_sxe_object *sxe TSRMLS_DC) /* {{{ */
                   2412: {
                   2413:        xmlNodePtr      node = NULL;
                   2414:        php_sxe_object  *intern;
                   2415: 
                   2416:        if (sxe->iter.data) {
                   2417:                intern = (php_sxe_object *)zend_object_store_get_object(sxe->iter.data TSRMLS_CC);
                   2418:                GET_NODE(intern, node)
                   2419:                zval_ptr_dtor(&sxe->iter.data);
                   2420:                sxe->iter.data = NULL;
                   2421:        }
                   2422: 
                   2423:        if (node) {
                   2424:                php_sxe_iterator_fetch(sxe, node->next, 1 TSRMLS_CC);
                   2425:        }
                   2426: }
                   2427: /* }}} */
                   2428: 
                   2429: static void php_sxe_iterator_move_forward(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2430: {
                   2431:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2432:        php_sxe_move_forward_iterator(iterator->sxe TSRMLS_CC);
                   2433: }
                   2434: /* }}} */
                   2435: 
                   2436: static void php_sxe_iterator_rewind(zend_object_iterator *iter TSRMLS_DC) /* {{{ */
                   2437: {
                   2438:        php_sxe_object  *sxe;
                   2439: 
                   2440:        php_sxe_iterator *iterator = (php_sxe_iterator *)iter;
                   2441:        sxe = iterator->sxe;
                   2442: 
                   2443:        php_sxe_reset_iterator(sxe, 1 TSRMLS_CC);
                   2444: }
                   2445: /* }}} */
                   2446: 
                   2447: void *simplexml_export_node(zval *object TSRMLS_DC) /* {{{ */
                   2448: {
                   2449:        php_sxe_object *sxe;
                   2450:        xmlNodePtr node;
                   2451: 
                   2452:        sxe = php_sxe_fetch_object(object TSRMLS_CC);
                   2453:        GET_NODE(sxe, node);
                   2454:        return php_sxe_get_first_node(sxe, node TSRMLS_CC);
                   2455: }
                   2456: /* }}} */
                   2457: 
                   2458: /* {{{ proto simplemxml_element simplexml_import_dom(domNode node [, string class_name])
                   2459:    Get a simplexml_element object from dom to allow for processing */
                   2460: PHP_FUNCTION(simplexml_import_dom)
                   2461: {
                   2462:        php_sxe_object *sxe;
                   2463:        zval *node;
                   2464:        php_libxml_node_object *object;
                   2465:        xmlNodePtr              nodep = NULL;
                   2466:        zend_class_entry *ce= sxe_class_entry;
                   2467: 
                   2468:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|C!", &node, &ce) == FAILURE) {
                   2469:                return;
                   2470:        }
                   2471: 
                   2472:        object = (php_libxml_node_object *)zend_object_store_get_object(node TSRMLS_CC);
                   2473: 
                   2474:        nodep = php_libxml_import_node(node TSRMLS_CC);
                   2475: 
                   2476:        if (nodep) {
                   2477:                if (nodep->doc == NULL) {
                   2478:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Imported Node must have associated Document");
                   2479:                        RETURN_NULL();
                   2480:                }
                   2481:                if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
                   2482:                        nodep = xmlDocGetRootElement((xmlDocPtr) nodep);
                   2483:                }
                   2484:        }
                   2485: 
                   2486:        if (nodep && nodep->type == XML_ELEMENT_NODE) {
                   2487:                if (!ce) {
                   2488:                        ce = sxe_class_entry;
                   2489:                }
                   2490:                sxe = php_sxe_object_new(ce TSRMLS_CC);
                   2491:                sxe->document = object->document;
                   2492:                php_libxml_increment_doc_ref((php_libxml_node_object *)sxe, nodep->doc TSRMLS_CC);
                   2493:                php_libxml_increment_node_ptr((php_libxml_node_object *)sxe, nodep, NULL TSRMLS_CC);
                   2494: 
                   2495:                return_value->type = IS_OBJECT;
                   2496:                return_value->value.obj = php_sxe_register_object(sxe TSRMLS_CC);
                   2497:        } else {
                   2498:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Nodetype to import");
                   2499:                RETVAL_NULL();
                   2500:        }
                   2501: }
                   2502: /* }}} */
                   2503: 
                   2504: /* {{{ arginfo */
                   2505: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_file, 0, 0, 1)
                   2506:        ZEND_ARG_INFO(0, filename)
                   2507:        ZEND_ARG_INFO(0, class_name)
                   2508:        ZEND_ARG_INFO(0, options)
                   2509:        ZEND_ARG_INFO(0, ns)
                   2510:        ZEND_ARG_INFO(0, is_prefix)
                   2511: ZEND_END_ARG_INFO()
                   2512: 
                   2513: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_load_string, 0, 0, 1)
                   2514:        ZEND_ARG_INFO(0, data)
                   2515:        ZEND_ARG_INFO(0, class_name)
                   2516:        ZEND_ARG_INFO(0, options)
                   2517:        ZEND_ARG_INFO(0, ns)
                   2518:        ZEND_ARG_INFO(0, is_prefix)
                   2519: ZEND_END_ARG_INFO()
                   2520: 
                   2521: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexml_import_dom, 0, 0, 1)
                   2522:        ZEND_ARG_INFO(0, node)
                   2523:        ZEND_ARG_INFO(0, class_name)
                   2524: ZEND_END_ARG_INFO()
                   2525: 
                   2526: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_xpath, 0, 0, 1)
                   2527:        ZEND_ARG_INFO(0, path)
                   2528: ZEND_END_ARG_INFO()
                   2529: 
                   2530: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_registerxpathnamespace, 0, 0, 2)
                   2531:        ZEND_ARG_INFO(0, prefix)
                   2532:        ZEND_ARG_INFO(0, ns)
                   2533: ZEND_END_ARG_INFO()
                   2534: 
                   2535: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_asxml, 0, 0, 0)
                   2536:        ZEND_ARG_INFO(0, filename)
                   2537: ZEND_END_ARG_INFO()
                   2538: 
                   2539: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getnamespaces, 0, 0, 0)
                   2540:        ZEND_ARG_INFO(0, recursve)
                   2541: ZEND_END_ARG_INFO()
                   2542: 
1.1.1.3   misho    2543: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_getdocnamespaces, 0, 0, 0)
                   2544:        ZEND_ARG_INFO(0, recursve)
                   2545:        ZEND_ARG_INFO(0, from_root)
                   2546: ZEND_END_ARG_INFO()
                   2547: 
1.1       misho    2548: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_children, 0, 0, 0)
                   2549:        ZEND_ARG_INFO(0, ns)
                   2550:        ZEND_ARG_INFO(0, is_prefix)
                   2551: ZEND_END_ARG_INFO()
                   2552: 
                   2553: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement__construct, 0, 0, 1)
                   2554:        ZEND_ARG_INFO(0, data)
                   2555:        ZEND_ARG_INFO(0, options)
                   2556:        ZEND_ARG_INFO(0, data_is_url)
                   2557:        ZEND_ARG_INFO(0, ns)
                   2558:        ZEND_ARG_INFO(0, is_prefix)
                   2559: ZEND_END_ARG_INFO()
                   2560: 
                   2561: ZEND_BEGIN_ARG_INFO(arginfo_simplexmlelement__void, 0)
                   2562: ZEND_END_ARG_INFO()
                   2563: 
                   2564: ZEND_BEGIN_ARG_INFO_EX(arginfo_simplexmlelement_addchild, 0, 0, 1)
                   2565:        ZEND_ARG_INFO(0, name)
                   2566:        ZEND_ARG_INFO(0, value)
                   2567:        ZEND_ARG_INFO(0, ns)
                   2568: ZEND_END_ARG_INFO()
                   2569: /* }}} */
                   2570: 
                   2571: const zend_function_entry simplexml_functions[] = { /* {{{ */
                   2572:        PHP_FE(simplexml_load_file,     arginfo_simplexml_load_file)
                   2573:        PHP_FE(simplexml_load_string,   arginfo_simplexml_load_string)
                   2574:        PHP_FE(simplexml_import_dom,    arginfo_simplexml_import_dom)
                   2575:        PHP_FE_END
                   2576: };
                   2577: /* }}} */
                   2578: 
                   2579: static const zend_module_dep simplexml_deps[] = { /* {{{ */
                   2580:        ZEND_MOD_REQUIRED("libxml")
                   2581:        ZEND_MOD_REQUIRED("spl")
                   2582:        ZEND_MOD_END
                   2583: };
                   2584: /* }}} */
                   2585: 
                   2586: zend_module_entry simplexml_module_entry = { /* {{{ */
                   2587:        STANDARD_MODULE_HEADER_EX, NULL,
                   2588:        simplexml_deps,
                   2589:        "SimpleXML",
                   2590:        simplexml_functions,
                   2591:        PHP_MINIT(simplexml),
                   2592:        PHP_MSHUTDOWN(simplexml),
                   2593:        NULL,
                   2594:        NULL,
                   2595:        PHP_MINFO(simplexml),
                   2596:        "0.1",
                   2597:        STANDARD_MODULE_PROPERTIES
                   2598: };
                   2599: /* }}} */
                   2600: 
                   2601: #ifdef COMPILE_DL_SIMPLEXML
                   2602: ZEND_GET_MODULE(simplexml)
                   2603: #endif
                   2604: 
                   2605: /* the method table */
                   2606: /* each method can have its own parameters and visibility */
                   2607: static const zend_function_entry sxe_functions[] = { /* {{{ */
                   2608:        SXE_ME(__construct,            arginfo_simplexmlelement__construct, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL) /* must be called */
                   2609:        SXE_ME(asXML,                  arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
                   2610:        SXE_MALIAS(saveXML, asXML,         arginfo_simplexmlelement_asxml, ZEND_ACC_PUBLIC)
                   2611:        SXE_ME(xpath,                  arginfo_simplexmlelement_xpath, ZEND_ACC_PUBLIC)
                   2612:        SXE_ME(registerXPathNamespace, arginfo_simplexmlelement_registerxpathnamespace, ZEND_ACC_PUBLIC)
                   2613:        SXE_ME(attributes,             arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
                   2614:        SXE_ME(children,               arginfo_simplexmlelement_children, ZEND_ACC_PUBLIC)
                   2615:        SXE_ME(getNamespaces,          arginfo_simplexmlelement_getnamespaces, ZEND_ACC_PUBLIC)
1.1.1.3   misho    2616:        SXE_ME(getDocNamespaces,       arginfo_simplexmlelement_getdocnamespaces, ZEND_ACC_PUBLIC)
1.1       misho    2617:        SXE_ME(getName,                arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
                   2618:        SXE_ME(addChild,               arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
                   2619:        SXE_ME(addAttribute,           arginfo_simplexmlelement_addchild, ZEND_ACC_PUBLIC)
                   2620:        SXE_ME(__toString,             arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
                   2621:        SXE_ME(count,                  arginfo_simplexmlelement__void, ZEND_ACC_PUBLIC)
                   2622:        PHP_FE_END
                   2623: };
                   2624: /* }}} */
                   2625: 
                   2626: /* {{{ PHP_MINIT_FUNCTION(simplexml)
                   2627:  */
                   2628: PHP_MINIT_FUNCTION(simplexml)
                   2629: {
                   2630:        zend_class_entry sxe;
                   2631: 
                   2632:        INIT_CLASS_ENTRY(sxe, "SimpleXMLElement", sxe_functions);
                   2633:        sxe.create_object = sxe_object_new;
                   2634:        sxe_class_entry = zend_register_internal_class(&sxe TSRMLS_CC);
                   2635:        sxe_class_entry->get_iterator = php_sxe_get_iterator;
                   2636:        sxe_class_entry->iterator_funcs.funcs = &php_sxe_iterator_funcs;
                   2637:        zend_class_implements(sxe_class_entry TSRMLS_CC, 1, zend_ce_traversable);
                   2638:        sxe_object_handlers.get_method = zend_get_std_object_handlers()->get_method;
                   2639:        sxe_object_handlers.get_constructor = zend_get_std_object_handlers()->get_constructor;
                   2640:        sxe_object_handlers.get_class_entry = zend_get_std_object_handlers()->get_class_entry;
                   2641:        sxe_object_handlers.get_class_name = zend_get_std_object_handlers()->get_class_name;
                   2642:        sxe_class_entry->serialize = zend_class_serialize_deny;
                   2643:        sxe_class_entry->unserialize = zend_class_unserialize_deny;
                   2644: 
                   2645:        php_libxml_register_export(sxe_class_entry, simplexml_export_node);
                   2646: 
                   2647:        PHP_MINIT(sxe)(INIT_FUNC_ARGS_PASSTHRU);
                   2648: 
                   2649:        return SUCCESS;
                   2650: }
                   2651: /* }}} */
                   2652: 
                   2653: /* {{{ PHP_MSHUTDOWN_FUNCTION(simplexml)
                   2654:  */
                   2655: PHP_MSHUTDOWN_FUNCTION(simplexml)
                   2656: {
                   2657:        sxe_class_entry = NULL;
                   2658:        return SUCCESS;
                   2659: }
                   2660: /* }}} */
                   2661: 
                   2662: /* {{{ PHP_MINFO_FUNCTION(simplexml)
                   2663:  */
                   2664: PHP_MINFO_FUNCTION(simplexml)
                   2665: {
                   2666:        php_info_print_table_start();
                   2667:        php_info_print_table_header(2, "Simplexml support", "enabled");
1.1.1.5 ! misho    2668:        php_info_print_table_row(2, "Revision", "$Id: 16070fc92ad6f69cebb2d52ad3f02794f833ce39 $");
1.1       misho    2669:        php_info_print_table_row(2, "Schema support",
                   2670: #ifdef LIBXML_SCHEMAS_ENABLED
                   2671:                "enabled");
                   2672: #else
                   2673:                "not available");
                   2674: #endif
                   2675:        php_info_print_table_end();
                   2676: }
                   2677: /* }}} */
                   2678: 
                   2679: #endif
                   2680: 
                   2681: /**
                   2682:  * Local Variables:
                   2683:  * c-basic-offset: 4
                   2684:  * tab-width: 4
                   2685:  * indent-tabs-mode: t
                   2686:  * End:
                   2687:  * vim600: fdm=marker
                   2688:  * vim: noet sw=4 ts=4
                   2689:  */

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