summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Richards <rrichards@php.net>2003-10-05 11:52:22 +0000
committerRob Richards <rrichards@php.net>2003-10-05 11:52:22 +0000
commitc21e78ddf21258fc44ea10ae9034705b9ecc8df2 (patch)
treeda3b397ae111a4473ff6c3ffc171e32a993d1a08
parent4de32429f597d3facced853f0deeca0990a3f33d (diff)
downloadphp-git-c21e78ddf21258fc44ea10ae9034705b9ecc8df2.tar.gz
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
-rw-r--r--ext/dom/document.c68
-rw-r--r--ext/dom/element.c63
-rw-r--r--ext/dom/node.c56
-rw-r--r--ext/dom/php_dom.c32
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);