File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / simplexml / simplexml.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:34:42 2012 UTC (12 years, 2 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, HEAD
php 5.4.3+patches

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

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