From c21e78ddf21258fc44ea10ae9034705b9ecc8df2 Mon Sep 17 00:00:00 2001 From: Rob Richards Date: Sun, 5 Oct 2003 11:52:22 +0000 Subject: [PATCH] implement isDefaultNameSpace and baseURI nodeName and tagName return qualified names fix removeAttributeNode - takes domAttr as parameter better uri and file handling for document load method fix possible segfault when document is freed set get_property_ptr_ptr handler to NULL --- ext/dom/document.c | 68 ++++++++++++++++++++++++++++++++++++---------- ext/dom/element.c | 63 +++++++++++++++++++++--------------------- ext/dom/node.c | 56 ++++++++++++++++++++++++++++++++++---- ext/dom/php_dom.c | 32 ++++++++++------------ 4 files changed, 149 insertions(+), 70 deletions(-) diff --git a/ext/dom/document.c b/ext/dom/document.c index 35b08074a0..5b59dba232 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1204,10 +1204,10 @@ PHP_FUNCTION(dom_document_document) } /* }}} end dom_document_document */ -/* {{{ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source TSRMLS_DC) */ +/* {{{ */ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source TSRMLS_DC) { xmlDocPtr ret; - xmlParserCtxtPtr ctxt; + xmlParserCtxtPtr ctxt = NULL; dom_doc_props *doc_props; dom_object *intern; dom_ref_obj *document = NULL; @@ -1232,13 +1232,61 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source TSRMLS_DC) xmlInitParser(); + keep_blanks = xmlKeepBlanksDefault(keep_blanks); + if (mode == DOM_LOAD_FILE) { - expand_filepath(source, resolved_path TSRMLS_CC); - ctxt = xmlCreateFileParserCtxt(resolved_path); + + xmlURI *uri; + xmlChar *escsource; + char *file_dest; + int isFileUri = 0; + + uri = xmlCreateURI(); + escsource = xmlURIEscapeStr(source, ":"); + xmlParseURIReference(uri, escsource); + xmlFree(escsource); + + if (uri->scheme != NULL) { + /* absolute file uris - libxml only supports localhost or empty host */ + if (strncasecmp(source, "file:///",8) == 0) { + isFileUri = 1; +#ifdef PHP_WIN32 + source += 8; +#else + source += 7; +#endif + } else if (strncasecmp(source, "file://localhost/",17) == 0) { + isFileUri = 1; +#ifdef PHP_WIN32 + source += 17; +#else + source += 16; +#endif + } + } + + file_dest = source; + + if ((uri->scheme == NULL || isFileUri)) { + if (! VCWD_REALPATH(source, resolved_path)) { + expand_filepath(source, resolved_path TSRMLS_CC); + } + file_dest = resolved_path; + } + + xmlFreeURI(uri); + + if ((PG(safe_mode) && (!php_checkuid(file_dest, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(file_dest TSRMLS_CC)) { + ctxt = NULL; + } else { + ctxt = xmlCreateFileParserCtxt(file_dest); + } } else { ctxt = xmlCreateDocParserCtxt(source); } + xmlKeepBlanksDefault(keep_blanks); + if (ctxt == NULL) { return(NULL); } @@ -1266,7 +1314,6 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source TSRMLS_DC) ctxt->recovery = 0; ctxt->validate = validate; ctxt->loadsubset = (resolve_externals * XML_COMPLETE_ATTRS); - ctxt->keepBlanks = keep_blanks; ctxt->replaceEntities = substitute_ent; ctxt->vctxt.error = php_dom_ctx_error; @@ -1274,9 +1321,6 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source TSRMLS_DC) if (ctxt->sax != NULL) { ctxt->sax->error = php_dom_ctx_error; - if (ctxt->keepBlanks == 0) { - ctxt->sax->ignorableWhitespace = ignorableWhitespace; - } } xmlParseDocument(ctxt); @@ -1297,7 +1341,7 @@ static xmlDocPtr dom_document_parser(zval *id, int mode, char *source TSRMLS_DC) return(ret); } -/* }}} end dom_parser_document */ +/* }}} */ /* {{{ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) */ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) { @@ -1314,12 +1358,6 @@ static void dom_parse_document(INTERNAL_FUNCTION_PARAMETERS, int mode) { return; } - if (mode == DOM_LOAD_FILE) { - if ((PG(safe_mode) && (!php_checkuid(source, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(source TSRMLS_CC)) { - RETURN_FALSE; - } - } - newdoc = dom_document_parser(id, mode, source TSRMLS_CC); if (!newdoc) diff --git a/ext/dom/element.c b/ext/dom/element.c index c8e1aae3c2..ceffc972f2 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -107,10 +107,20 @@ Since: int dom_element_tag_name_read(dom_object *obj, zval **retval TSRMLS_DC) { xmlNodePtr nodep; + xmlNsPtr ns; + xmlChar *qname; nodep = dom_object_get_node(obj); ALLOC_ZVAL(*retval); - ZVAL_STRING(*retval, (char *) (nodep->name), 1); + ns = nodep->ns; + if (ns != NULL && ns->prefix) { + qname = xmlStrdup(ns->prefix); + qname = xmlStrcat(qname, ":"); + } + qname = xmlStrcat(qname, nodep->name); + ZVAL_STRING(*retval, qname, 1); + xmlFree(qname); + return SUCCESS; } @@ -309,14 +319,12 @@ PHP_FUNCTION(dom_element_set_attribute_node) existattrp = xmlHasProp(nodep, attrp->name); if (existattrp != NULL) { - if ((oldobj = dom_object_get_data((xmlNodePtr) existattrp)) == NULL) { - xmlUnlinkNode((xmlNodePtr) existattrp); - } else { - if (((node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp) { - RETURN_NULL(); - } - xmlUnlinkNode((xmlNodePtr) existattrp); + if ((oldobj = dom_object_get_data((xmlNodePtr) existattrp)) != NULL && + ((node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp) + { + RETURN_NULL(); } + xmlUnlinkNode((xmlNodePtr) existattrp); } if (attrp->doc == NULL && nodep->doc != NULL) { @@ -343,16 +351,15 @@ Since: */ PHP_FUNCTION(dom_element_remove_attribute_node) { - zval *id; + zval *id, *node, *rv = NULL; xmlNode *nodep; xmlAttr *attrp; - dom_object *intern; - int name_len; - char *name; + dom_object *intern, *attrobj; + int ret; DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern); - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &node) == FAILURE) { return; } @@ -361,22 +368,16 @@ PHP_FUNCTION(dom_element_remove_attribute_node) RETURN_FALSE; } - attrp = xmlHasProp(nodep,name); - if (attrp == NULL) { + DOM_GET_OBJ(attrp, node, xmlAttrPtr, attrobj); + + if (attrp->type != XML_ATTRIBUTE_NODE || attrp->parent != nodep) { + php_dom_throw_error(NOT_FOUND_ERR, dom_get_strict_error(intern->document) TSRMLS_CC); RETURN_FALSE; } - /* Check for registered nodes within attributes tree when attribute is not referenced - Unlink dependant nodes and free attribute if not registered */ - if (dom_object_get_data((xmlNodePtr) attrp) == NULL) { - node_list_unlink(attrp->children TSRMLS_CC); - xmlUnlinkNode((xmlNodePtr) attrp); - xmlFreeProp(attrp); - } else { - xmlUnlinkNode((xmlNodePtr) attrp); - } + xmlUnlinkNode((xmlNodePtr) attrp); - RETURN_TRUE; + DOM_RET_OBJ(rv, (xmlNodePtr) attrp, &ret, intern); } /* }}} end dom_element_remove_attribute_node */ @@ -684,14 +685,12 @@ PHP_FUNCTION(dom_element_set_attribute_node_ns) } if (existattrp != NULL) { - if ((oldobj = dom_object_get_data((xmlNodePtr) existattrp)) == NULL) { - xmlUnlinkNode((xmlNodePtr) existattrp); - } else { - if (((node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp) { - RETURN_NULL(); - } - xmlUnlinkNode((xmlNodePtr) existattrp); + if ((oldobj = dom_object_get_data((xmlNodePtr) existattrp)) != NULL && + ((node_ptr *)oldobj->ptr)->node == (xmlNodePtr) attrp) + { + RETURN_NULL(); } + xmlUnlinkNode((xmlNodePtr) existattrp); } if (attrp->doc == NULL && nodep->doc != NULL) { diff --git a/ext/dom/node.c b/ext/dom/node.c index 6aabc5e1e9..6a6c0fe74d 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -65,13 +65,23 @@ Since: int dom_node_node_name_read(dom_object *obj, zval **retval TSRMLS_DC) { xmlNode *nodep; + xmlNsPtr ns; char *str = NULL; + xmlChar *qname = NULL; nodep = dom_object_get_node(obj); switch (nodep->type) { case XML_ATTRIBUTE_NODE: case XML_ELEMENT_NODE: + ns = nodep->ns; + if (ns != NULL && ns->prefix) { + qname = xmlStrdup(ns->prefix); + qname = xmlStrcat(qname, ":"); + } + qname = xmlStrcat(qname, nodep->name); + str = qname; + break; case XML_DOCUMENT_TYPE_NODE: case XML_DTD_NODE: case XML_PI_NODE: @@ -113,6 +123,10 @@ int dom_node_node_name_read(dom_object *obj, zval **retval TSRMLS_DC) } else { ZVAL_EMPTY_STRING(*retval); } + + if (qname != NULL) { + xmlFree(qname); + } return SUCCESS; @@ -654,9 +668,21 @@ Since: DOM Level 3 */ int dom_node_base_uri_read(dom_object *obj, zval **retval TSRMLS_DC) { - /* TODO: Implement this feature */ + xmlNode *nodep; + xmlChar *baseuri; + + nodep = dom_object_get_node(obj); + ALLOC_ZVAL(*retval); - ZVAL_NULL(*retval); + + baseuri = xmlNodeGetBase(nodep->doc, nodep); + if (baseuri) { + ZVAL_STRING(*retval, (char *) (baseuri), 1); + xmlFree(baseuri); + } else { + ZVAL_NULL(*retval); + } + return SUCCESS; } @@ -1315,18 +1341,38 @@ PHP_FUNCTION(dom_node_lookup_prefix) /* {{{ proto boolean dom_node_is_default_namespace(string namespaceURI); -URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-isDefaultNamespace +URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-isDefaultNamespace Since: DOM Level 3 */ PHP_FUNCTION(dom_node_is_default_namespace) { - DOM_NOT_IMPLEMENTED(); + zval *id; + xmlNodePtr nodep; + dom_object *intern; + xmlNsPtr nsptr; + int uri_len = 0; + char *uri; + + DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &uri, &uri_len) == FAILURE) { + return; + } + + if (uri_len > 0) { + nsptr = xmlSearchNs(nodep->doc, nodep, NULL); + if (nsptr && xmlStrEqual(nsptr->href, uri)) { + RETURN_TRUE; + } + } + + RETURN_FALSE; } /* }}} end dom_node_is_default_namespace */ /* {{{ proto domstring dom_node_lookup_namespace_uri(string prefix); -URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Node3-lookupNamespaceURI +URL: http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-lookupNamespaceURI Since: DOM Level 3 */ PHP_FUNCTION(dom_node_lookup_namespace_uri) diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 833e7359a9..e22ea1acfc 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -250,13 +250,13 @@ dom_object *dom_object_get_data(xmlNodePtr obj) /* }}} end dom_object_get_data */ /* {{{ php_dom_clear_object */ -static void php_dom_clear_object(dom_object *object TSRMLS_DC) +static int php_dom_clear_object(dom_object *object TSRMLS_DC) { if (object->prop_handler) { object->prop_handler = NULL; } decrement_node_ptr(object TSRMLS_CC); - decrement_document_reference(object TSRMLS_CC); + return decrement_document_reference(object TSRMLS_CC); } /* }}} end php_dom_clear_object */ @@ -284,14 +284,16 @@ void php_dom_set_object(dom_object *object, xmlNodePtr obj TSRMLS_DC) /* }}} end php_dom_set_object */ /* {{{ dom_unregister_node */ -void dom_unregister_node(xmlNodePtr nodep TSRMLS_DC) +static int dom_unregister_node(xmlNodePtr nodep TSRMLS_DC) { dom_object *wrapper; - + wrapper = dom_object_get_data(nodep); if (wrapper != NULL ) { - php_dom_clear_object(wrapper TSRMLS_CC); + return php_dom_clear_object(wrapper TSRMLS_CC); } + + return -1; } /* }}} end dom_unregister_node */ @@ -405,17 +407,6 @@ void dom_write_property(zval *object, zval *member, zval *value TSRMLS_DC) } /* }}} */ -static zval **dom_property_get_ptr(zval *object, zval *member TSRMLS_DC) -{ - zval **prop_ptr; - zval *property; - - property = dom_read_property(object, member, 0 TSRMLS_CC); - prop_ptr = &property; - - return prop_ptr; -} - zend_module_entry dom_module_entry = { STANDARD_MODULE_HEADER, "dom", @@ -441,6 +432,7 @@ PHP_MINIT_FUNCTION(dom) memcpy(&dom_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); dom_object_handlers.read_property = dom_read_property; dom_object_handlers.write_property = dom_write_property; + dom_object_handlers.get_property_ptr_ptr = NULL; zend_hash_init(&classes, 0, NULL, NULL, 1); @@ -871,7 +863,9 @@ void node_free_list(xmlNodePtr node TSRMLS_DC) curnode = node->next; xmlUnlinkNode(node); - dom_unregister_node(node TSRMLS_CC); + if (dom_unregister_node(node TSRMLS_CC) == 0) { + node->doc = NULL; + } dom_node_free(node); } } @@ -903,7 +897,9 @@ void node_free_resource(xmlNodePtr node TSRMLS_DC) default: node_free_list((xmlNodePtr) node->properties TSRMLS_CC); } - dom_unregister_node(node TSRMLS_CC); + if (dom_unregister_node(node TSRMLS_CC) == 0) { + node->doc = NULL; + } dom_node_free(node); } else { dom_unregister_node(node TSRMLS_CC); -- 2.40.0