Index: ext/domxml/php_domxml.c =================================================================== RCS file: /repository/php4/ext/domxml/php_domxml.c,v retrieving revision 1.159 diff -u -r1.159 php_domxml.c --- ext/domxml/php_domxml.c 19 May 2002 00:02:05 -0000 1.159 +++ ext/domxml/php_domxml.c 24 May 2002 17:16:48 -0000 @@ -140,6 +140,8 @@ #define DOMXML_LOAD_SUBSTITUTE_ENTITIES 4 #define DOMXML_LOAD_COMPLETE_ATTRS 8 +static int in_request_shutdown = 0; + static int le_domxmldocp; static int le_domxmldoctypep; static int le_domxmldtdp; @@ -222,6 +224,7 @@ PHP_FE(domxml_node_has_attributes, NULL) PHP_FE(domxml_node_new_child, NULL) PHP_FE(domxml_node, NULL) + PHP_FE(domxml_text_node, NULL) PHP_FE(domxml_node_unlink_node, NULL) PHP_FE(domxml_node_set_content, NULL) PHP_FE(domxml_node_get_content, NULL) @@ -464,7 +467,7 @@ PHP_MINIT(domxml), NULL, PHP_RINIT(domxml), - NULL, + PHP_RSHUTDOWN(domxml), PHP_MINFO(domxml), DOMXML_API_VERSION, /* Extension versionnumber */ STANDARD_MODULE_PROPERTIES @@ -504,22 +507,24 @@ static inline void node_wrapper_dtor(xmlNodePtr node) { zval *wrapper; - int refcount = 0; - /* FIXME: type check probably unnecessary here? */ - if (!node || Z_TYPE_P(node) == XML_DTD_NODE) - return; + zval **handle; wrapper = dom_object_get_data(node); - if (wrapper != NULL) { - refcount = wrapper->refcount; - zval_ptr_dtor(&wrapper); - /*only set it to null, if refcount was 1 before, otherwise it has still needed references */ - if (refcount == 1) { - dom_object_set_data(node, NULL); + if (wrapper) { + dom_object_set_data(node, 0); + + /* + * XXX: in_request_shutdown prevents list entries from being removed + * while zend is traversing it during cleanups + */ + if (!in_request_shutdown + && zend_hash_index_find(Z_OBJPROP_P(wrapper), 0, (void **) &handle) == SUCCESS) { + zend_list_delete(Z_LVAL_PP(handle)); } - } + zval_ptr_dtor(&wrapper); + } } @@ -577,8 +582,6 @@ xmlDoc *doc = (xmlDoc *) rsrc->ptr; if (doc) { - node_list_wrapper_dtor(doc->children); - node_wrapper_dtor((xmlNodePtr) doc); xmlFreeDoc(doc); } } @@ -588,17 +591,17 @@ { xmlNodePtr node = (xmlNodePtr) rsrc->ptr; - /* if node has no parent, it will not be freed by php_free_xml_doc, so do it here - and for all children as well. */ - if (node->parent == NULL) { - attr_list_wrapper_dtor(node->properties); - node_list_wrapper_dtor(node->children); - node_wrapper_dtor(node); - xmlFreeNode(node); - } else { - node_wrapper_dtor(node); + if (node && dom_object_get_data(node)) { + xmlUnlinkNode(node); + switch(node->type) { + case XML_ATTRIBUTE_NODE: + xmlFreeProp(node); + break; + default: + xmlFreeNode(node); + break; + } } - } @@ -1031,31 +1034,15 @@ zend_hash_index_update(Z_OBJPROP_P(wrapper), 0, &handle, sizeof(zval *), NULL); zend_hash_index_update(Z_OBJPROP_P(wrapper), 1, &addr, sizeof(zval *), NULL); - zval_add_ref(&wrapper); dom_object_set_data(obj, wrapper); } - -static zval *php_domobject_new(xmlNodePtr obj, int *found TSRMLS_DC) +static void domxml_register_node(xmlNodePtr obj) { zval *wrapper; char *content; int rsrc_type; - *found = 0; - - if (!obj) { - MAKE_STD_ZVAL(wrapper); - ZVAL_NULL(wrapper); - return wrapper; - } - - if ((wrapper = (zval *) dom_object_get_data((void *) obj))) { - zval_add_ref(&wrapper); - *found = 1; - return wrapper; - } - MAKE_STD_ZVAL(wrapper); switch (Z_TYPE_P(obj)) { @@ -1234,11 +1221,50 @@ default: php_error(E_WARNING, "%s(): unsupported node type: %d\n", get_active_function_name(TSRMLS_C), Z_TYPE_P(obj)); FREE_ZVAL(wrapper); - return NULL; + wrapper = NULL; } - php_dom_set_object(wrapper, (void *) obj, rsrc_type); - return (wrapper); + if (wrapper) { + php_dom_set_object(wrapper, (void *) obj, rsrc_type); + } +} + +static void domxml_deregister_node(xmlNodePtr node) +{ + zval *wrapper; + + if ((wrapper = dom_object_get_data(node))) { + node_wrapper_dtor(node); + } +} + +static zval *php_domobject_new(xmlNodePtr obj, int *found TSRMLS_DC) +{ + zval *wrapper; + + *found = 0; + + if (!obj) { + MAKE_STD_ZVAL(wrapper); + ZVAL_NULL(wrapper); + return wrapper; + } + + if ((wrapper = (zval *) dom_object_get_data((void *) obj))) { + zval_add_ref(&wrapper); + *found = 1; + return wrapper; + } + + /* + * domxml_register_node should take care so that we never end up below this point + */ + + php_error(E_ERROR, "%s(): domxml fatal error: no wrapper found for node (type=%d; name=%s)\n", + get_active_function_name(TSRMLS_C), obj->type, obj->name); + MAKE_STD_ZVAL(wrapper); + ZVAL_NULL(wrapper); + return wrapper; } @@ -1255,6 +1281,13 @@ PHP_RINIT_FUNCTION(domxml) { + in_request_shutdown = 0; + return SUCCESS; +} + +PHP_RSHUTDOWN_FUNCTION(domxml) +{ + in_request_shutdown = 1; return SUCCESS; } @@ -1263,6 +1296,10 @@ { zend_class_entry ce; + xmlRegisterNodeDefault(domxml_register_node); + xmlDeregisterNodeDefault(domxml_deregister_node); + + le_domxmldocp = zend_register_list_destructors_ex(php_free_xml_doc, NULL, "domdocument", module_number); /* Freeing the document contains freeing the complete tree. Therefore nodes, attributes etc. may not be freed seperately. @@ -1590,6 +1627,34 @@ } /* }}} */ +static void php_textnode_new(INTERNAL_FUNCTION_PARAMETERS, xmlDocPtr docp) +{ + zval *rv; + xmlNode *node; + int ret, content_len; + char *content; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) { + return; + } + + node = xmlNewTextLen(content, content_len); + if (!node) { + RETURN_FALSE; + } + node->doc = docp; + + DOMXML_RET_OBJ(rv, node, &ret); +} + +/* {{{ proto object domxml_text_node(string content) + Creates node */ +PHP_FUNCTION(domxml_text_node) +{ + php_textnode_new(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL); +} +/* }}} */ + /* {{{ proto object domxml_node_name(void) Returns name of node */ PHP_FUNCTION(domxml_node_name) @@ -1917,6 +1982,26 @@ } /* }}} */ +/* {{{ proto string domxml_node_get_path(void) + Returns the path of the node in the document */ +PHP_FUNCTION(domxml_node_get_path) +{ + zval *id; + xmlNode *nodep; + xmlChar *path; + + DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); + + DOMXML_NO_ARGS(); + + path = xmlGetNodePath(nodep); + if (!path) { + RETURN_FALSE; + } + RETVAL_STRING((char *)path, 1); + xmlFree(path); +} + /* {{{ proto object domxml_node_parent(void) Returns parent of node */ PHP_FUNCTION(domxml_node_parent) @@ -2039,34 +2124,32 @@ DOMXML_GET_THIS_OBJ(nodep, id, le_domxmlnodep); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &node) == FAILURE) { - return; + RETURN_FALSE; } DOMXML_GET_OBJ(child, node, le_domxmlnodep); + if (child->type == XML_ATTRIBUTE_NODE) { php_error(E_WARNING, "%s(): can't append attribute node", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } +#if 0 if (NULL == (new_child = xmlCopyNode(child, 1))) { php_error(E_WARNING, "%s(): unable to clone node", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } +#endif - /* FIXME reverted xmlAddChildList; crashes - * Uwe: must have been a temporary problem. It works for me with both - * xmlAddChildList and xmlAddChild - */ - - child = xmlAddChild(nodep, new_child); + new_child = xmlAddChild(nodep, child); - if (NULL == child) { + if (NULL == new_child) { php_error(E_WARNING, "%s(): couldn't append node", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } - DOMXML_RET_OBJ(rv, child, &ret); + DOMXML_RET_OBJ(rv, new_child, &ret); } /* }}} */ @@ -2961,25 +3044,11 @@ Creates new text node */ PHP_FUNCTION(domxml_doc_create_text_node) { - zval *id, *rv; - xmlNode *node; + zval *id; xmlDocPtr docp; - int ret, content_len; - char *content; DOMXML_GET_THIS_OBJ(docp, id, le_domxmldocp); - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &content, &content_len) == FAILURE) { - return; - } - - node = xmlNewTextLen(content, content_len); - if (!node) { - RETURN_FALSE; - } - node->doc = docp; - - DOMXML_RET_OBJ(rv, node, &ret); + php_textnode_new(INTERNAL_FUNCTION_PARAM_PASSTHRU, docp); } /* }}} */ Index: ext/domxml/php_domxml.h =================================================================== RCS file: /repository/php4/ext/domxml/php_domxml.h,v retrieving revision 1.53 diff -u -r1.53 php_domxml.h --- ext/domxml/php_domxml.h 16 May 2002 21:59:26 -0000 1.53 +++ ext/domxml/php_domxml.h 24 May 2002 17:16:48 -0000 @@ -53,6 +53,7 @@ /* directory functions */ PHP_MINIT_FUNCTION(domxml); PHP_RINIT_FUNCTION(domxml); +PHP_RSHUTDOWN_FUNCTION(domxml); PHP_MINFO_FUNCTION(domxml); PHP_FUNCTION(domxml_version); PHP_FUNCTION(xmldoc); @@ -118,7 +119,9 @@ PHP_FUNCTION(domxml_node_has_child_nodes); PHP_FUNCTION(domxml_node_parent); PHP_FUNCTION(domxml_node_prefix); +PHP_FUNCTION(domxml_node_get_path); PHP_FUNCTION(domxml_node); +PHP_FUNCTION(domxml_text_node); PHP_FUNCTION(domxml_clone_node); PHP_FUNCTION(domxml_node_unlink_node); PHP_FUNCTION(domxml_node_replace_node);