diff options
-rw-r--r-- | ext/dom/attr.c | 16 | ||||
-rw-r--r-- | ext/dom/document.c | 59 | ||||
-rw-r--r-- | ext/dom/domimplementation.c | 67 | ||||
-rw-r--r-- | ext/dom/element.c | 40 | ||||
-rw-r--r-- | ext/dom/node.c | 142 | ||||
-rw-r--r-- | ext/dom/php_dom.c | 63 | ||||
-rw-r--r-- | ext/dom/php_dom.h | 3 |
7 files changed, 224 insertions, 166 deletions
diff --git a/ext/dom/attr.c b/ext/dom/attr.c index 398796261f..fb6531abd7 100644 --- a/ext/dom/attr.c +++ b/ext/dom/attr.c @@ -210,13 +210,25 @@ int dom_attr_schema_type_info_read(dom_object *obj, zval **retval TSRMLS_DC) - /* {{{ proto boolean dom_attr_is_id(); URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#Attr-isId Since: DOM Level 3 */ PHP_FUNCTION(dom_attr_is_id) { - DOM_NOT_IMPLEMENTED(); + zval *id; + dom_object *intern; + xmlAttrPtr attrp; + xmlNodePtr nodep; + + DOM_GET_THIS_OBJ(attrp, id, xmlAttrPtr, intern); + + nodep = attrp->parent; + + if (xmlIsID(attrp->doc, nodep, attrp)) { + RETURN_TRUE; + } else { + RETURN_FALSE; + } } /* }}} end dom_attr_is_id */ diff --git a/ext/dom/document.c b/ext/dom/document.c index df1a28b2c3..6489510615 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -793,7 +793,7 @@ PHP_FUNCTION(dom_document_create_element_ns) xmlNsPtr nsptr; int ret, uri_len = 0, name_len = 0; char *uri, *name; - xmlChar *localname = NULL; + char *localname = NULL, *prefix = NULL; int errorcode; dom_object *intern; @@ -803,20 +803,28 @@ PHP_FUNCTION(dom_document_create_element_ns) return; } - nsptr = dom_get_ns(uri, name, uri_len, name_len, &errorcode, (char **) &localname); + errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len); + if (errorcode == 0) { - if (nsptr != NULL) { - dom_set_old_ns(docp, nsptr); - nodep = xmlNewDocNode (docp, nsptr, localname, NULL); - } else { - nodep = xmlNewDocNode (docp, NULL, name, NULL); + nodep = xmlNewDocNode (docp, NULL, localname, NULL); + if (nodep != NULL) { + nsptr = xmlSearchNsByHref (nodep->doc, nodep, uri); + if (nsptr == NULL) { + nsptr = dom_get_ns(nodep, uri, &errorcode, prefix); + } + xmlSetNs(nodep, nsptr); } } - if (localname != NULL) { - xmlFree(localname); + + xmlFree(localname); + if (prefix != NULL) { + xmlFree(prefix); } if (errorcode != 0) { + if (nodep != NULL) { + xmlFreeNode(nodep); + } php_dom_throw_error(errorcode, &return_value TSRMLS_CC); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); RETURN_FALSE; @@ -826,6 +834,9 @@ PHP_FUNCTION(dom_document_create_element_ns) RETURN_FALSE; } + + nodep->ns = nsptr; + DOM_RET_OBJ(rv, nodep, &ret, intern); } /* }}} end dom_document_create_element_ns */ @@ -839,11 +850,11 @@ PHP_FUNCTION(dom_document_create_attribute_ns) { zval *id, *rv = NULL; xmlDocPtr docp; - xmlNodePtr nodep = NULL; + xmlNodePtr nodep = NULL, root; xmlNsPtr nsptr; int ret, uri_len = 0, name_len = 0; char *uri, *name; - xmlChar *localname = NULL; + char *localname = NULL, *prefix = NULL; dom_object *intern; int errorcode; @@ -853,23 +864,33 @@ PHP_FUNCTION(dom_document_create_attribute_ns) return; } - nsptr = dom_get_ns(uri, name, uri_len, name_len, &errorcode, (char **) &localname); - if (errorcode == 0) { - if (nsptr != NULL) { + root = xmlDocGetRootElement(docp); + if (root != NULL) { + errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len); + if (errorcode == 0) { nodep = (xmlNodePtr) xmlNewDocProp(docp, localname, NULL); - dom_set_old_ns(docp, nsptr); if (nodep != NULL) { + nsptr = xmlSearchNsByHref (nodep->doc, root, uri); + if (nsptr == NULL) { + nsptr = dom_get_ns(root, uri, &errorcode, prefix); + } xmlSetNs(nodep, nsptr); } - } else { - nodep = (xmlNodePtr) xmlNewDocProp(docp, name, NULL); } + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Document Missing Root Element"); + RETURN_FALSE; } - if (localname != NULL) { - xmlFree(localname); + + xmlFree(localname); + if (prefix != NULL) { + xmlFree(prefix); } if (errorcode != 0) { + if (nodep != NULL) { + xmlFreeProp((xmlAttrPtr) nodep); + } php_dom_throw_error(errorcode, &return_value TSRMLS_CC); php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); RETURN_FALSE; diff --git a/ext/dom/domimplementation.c b/ext/dom/domimplementation.c index fccae0b6f3..dd255a21ce 100644 --- a/ext/dom/domimplementation.c +++ b/ext/dom/domimplementation.c @@ -132,10 +132,9 @@ PHP_FUNCTION(dom_domimplementation_create_document) xmlNode *nodep; xmlDtdPtr doctype = NULL; xmlNsPtr nsptr = NULL; - int ret, uri_len = 0, name_len = 0; + int ret, uri_len = 0, name_len = 0, errorcode = 0; char *uri, *name; - xmlChar *prefix = NULL, *localname = NULL; - xmlURIPtr uristruct; + char *prefix = NULL, *localname = NULL; dom_object *doctobj; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sso", &uri, &uri_len, &name, &name_len, &node) == FAILURE) { @@ -155,58 +154,24 @@ PHP_FUNCTION(dom_domimplementation_create_document) } } - if (uri_len > 0 || name_len > 0 || doctype != NULL) { - if (name_len == 0 && uri_len > 0) { - php_dom_throw_error(NAMESPACE_ERR, &return_value TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); + if (name_len > 0) { + errorcode = dom_check_qname(name, &localname, &prefix, 1, name_len); + if (errorcode == 0 && uri_len > 0 && ((nsptr = xmlNewNs(NULL, uri, prefix)) == NULL)) { + errorcode = NAMESPACE_ERR; } - if (name_len > 0) { - uristruct = xmlParseURI(name); - if (uristruct->opaque != NULL) { - prefix = xmlStrdup(uristruct->scheme); - localname = xmlStrdup(uristruct->opaque); - if (xmlStrchr(localname, (xmlChar) ':') != NULL) { - php_dom_throw_error(NAMESPACE_ERR, &return_value TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); - xmlFreeURI(uristruct); - xmlFree(prefix); - xmlFree(localname); - RETURN_FALSE; - } - if (!strcmp (prefix, "xml") && strcmp(uri, XML_XML_NAMESPACE)) { - php_dom_throw_error(NAMESPACE_ERR, &return_value TSRMLS_CC); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); - xmlFreeURI(uristruct); - xmlFree(prefix); - xmlFree(localname); - RETURN_FALSE; - } - } else { - localname = xmlStrdup(name); - } - - /* TODO: Test that localname has no invalid chars - php_dom_throw_error(INVALID_CHARACTER_ERR, TSRMLS_CC); - */ - - xmlFreeURI(uristruct); + } - if (uri_len > 0) { - if ((nsptr = xmlNewNs(NULL, uri, prefix)) == NULL) { - php_dom_throw_error(NAMESPACE_ERR, &return_value TSRMLS_CC); - if (prefix != NULL) { - xmlFree(prefix); - } - xmlFree(localname); - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); - RETURN_FALSE; - } + if (prefix != NULL) { + xmlFree(prefix); + } - } - if (prefix != NULL) { - xmlFree(prefix); - } + if (errorcode != 0) { + if (localname != NULL) { + xmlFree(localname); } + php_dom_throw_error(errorcode, &return_value TSRMLS_CC); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); + RETURN_FALSE; } /* currently letting libxml2 set the version string */ diff --git a/ext/dom/element.c b/ext/dom/element.c index 1c75f6982d..f2ba0b650d 100644 --- a/ext/dom/element.c +++ b/ext/dom/element.c @@ -497,7 +497,7 @@ PHP_FUNCTION(dom_element_set_attribute_ns) xmlNsPtr nsptr; int ret, uri_len = 0, name_len = 0; char *uri, *name; - xmlChar *localname = NULL; + char *localname = NULL, *prefix = NULL; dom_object *intern; int errorcode = 0; @@ -512,22 +512,33 @@ PHP_FUNCTION(dom_element_set_attribute_ns) RETURN_FALSE; } - nsptr = xmlSearchNsByHref (elemp->doc, elemp, uri); - if (nsptr == NULL) { - nsptr = dom_get_ns(uri, name, uri_len, name_len, &errorcode, (char **) &localname); - if (nsptr != NULL) { - dom_set_old_ns(elemp->doc, nsptr); - } - } + errorcode = dom_check_qname(name, &localname, &prefix, uri_len, name_len); + if (errorcode == 0) { - if (nsptr != NULL) { + nodep = (xmlNodePtr) xmlHasNsProp(elemp, localname, uri); + if (nodep != NULL) { + node_list_unlink(nodep->children TSRMLS_CC); + } + nsptr = xmlSearchNsByHref(elemp->doc, elemp, uri); + while (nsptr && nsptr->prefix == NULL) { + nsptr = nsptr->next; + } + if (nsptr == NULL) { + if (prefix == NULL) { + errorcode = NAMESPACE_ERR; + } else { + nsptr = dom_get_ns(elemp, uri, &errorcode, prefix); + } + } + + if (errorcode == 0) { nodep = (xmlNodePtr) xmlSetNsProp(elemp, nsptr, localname, NULL); - } else { - nodep = (xmlNodePtr) xmlSetProp(elemp, name, NULL); } } - if (localname != NULL) { - xmlFree(localname); + + xmlFree(localname); + if (prefix != NULL) { + xmlFree(prefix); } if (errorcode != 0) { @@ -687,9 +698,6 @@ PHP_FUNCTION(dom_element_set_attribute_node_ns) } xmlAddChild(nodep, (xmlNodePtr) attrp); - if (existattrp == NULL) { - xmlReconciliateNs(nodep->doc, nodep); - } /* Returns old property if removed otherwise NULL */ if (existattrp != NULL) { diff --git a/ext/dom/node.c b/ext/dom/node.c index 2faedfee80..951a75c97f 100644 --- a/ext/dom/node.c +++ b/ext/dom/node.c @@ -543,10 +543,8 @@ int dom_node_prefix_read(dom_object *obj, zval **retval TSRMLS_DC) case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: ns = nodep->ns; - if (ns != NULL) { - if (ns->prefix) { - str = (char *) ns->prefix; - } + if (ns != NULL && ns->prefix) { + str = (char *) ns->prefix; } break; default: @@ -578,42 +576,40 @@ int dom_node_prefix_write(dom_object *obj, zval *newval TSRMLS_DC) switch (nodep->type) { case XML_ELEMENT_NODE: case XML_ATTRIBUTE_NODE: - ns = nodep->ns; - strURI = NULL; - if (nodep->ns != NULL) { - strURI = (char *) nodep->ns->href; - } prefix = Z_STRVAL_P(newval); - if (strURI == NULL || - (!strcmp (prefix, "xml") && strcmp(strURI, XML_XML_NAMESPACE)) || - (nodep->type == XML_ATTRIBUTE_NODE && !strcmp (prefix, "xmlns") && - strcmp (strURI, DOM_XMLNS_NAMESPACE)) || - (nodep->type == XML_ATTRIBUTE_NODE && !strcmp (nodep->name, "xmlns"))) { - - /* TODO: throw error - find out how to without a return_value - php_dom_throw_error(NAMESPACE_ERR, &return_value TSRMLS_CC); */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); - return FAILURE; - } - ns = xmlNewNs(NULL, nodep->ns->href, (xmlChar *)prefix); - if (nodep->doc != NULL) { - doc = nodep->doc; - if (doc->oldNs == NULL) { - doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); - memset(doc->oldNs, 0, sizeof(xmlNs)); - doc->oldNs->type = XML_LOCAL_NAMESPACE; - doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE); - doc->oldNs->prefix = xmlStrdup((const xmlChar *)"xml"); + if (nodep->ns != NULL && !xmlStrEqual(nodep->ns->prefix, (xmlChar *)prefix)) { + strURI = (char *) nodep->ns->href; + if (strURI == NULL || + (!strcmp (prefix, "xml") && strcmp(strURI, XML_XML_NAMESPACE)) || + (nodep->type == XML_ATTRIBUTE_NODE && !strcmp (prefix, "xmlns") && + strcmp (strURI, DOM_XMLNS_NAMESPACE)) || + (nodep->type == XML_ATTRIBUTE_NODE && !strcmp (nodep->name, "xmlns"))) { + + /* TODO: throw error - find out how to without a return_value + php_dom_throw_error(NAMESPACE_ERR, &return_value TSRMLS_CC); */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Namespace"); + return FAILURE; } - - curns = doc->oldNs; - while (curns->next != NULL) { - curns = curns->next; + ns = xmlNewNs(NULL, nodep->ns->href, (xmlChar *)prefix); + if (nodep->doc != NULL) { + doc = nodep->doc; + if (doc->oldNs == NULL) { + doc->oldNs = (xmlNsPtr) xmlMalloc(sizeof(xmlNs)); + memset(doc->oldNs, 0, sizeof(xmlNs)); + doc->oldNs->type = XML_LOCAL_NAMESPACE; + doc->oldNs->href = xmlStrdup(XML_XML_NAMESPACE); + doc->oldNs->prefix = xmlStrdup((const xmlChar *)"xml"); + } + + curns = doc->oldNs; + while (curns->next != NULL) { + curns = curns->next; + } + curns->next = ns; } - curns->next = ns; - } - nodep->ns = curns; + nodep->ns = curns; + } break; default: break; @@ -1002,6 +998,7 @@ PHP_FUNCTION(dom_node_append_child) zval *id, *node, *rv = NULL; xmlNodePtr child, nodep, new_child = NULL; dom_object *intern, *childobj; + xmlNsPtr nsptr; int ret; DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern); @@ -1089,6 +1086,15 @@ PHP_FUNCTION(dom_node_append_child) RETURN_FALSE; } + if (new_child->nsDef != NULL && new_child->type == XML_ELEMENT_NODE && new_child->nsDef->href != NULL) { + if((nsptr = xmlSearchNsByHref(nodep->doc, new_child->parent, new_child->nsDef->href)) && + (new_child->nsDef->prefix == NULL || xmlStrEqual(nsptr->prefix, new_child->nsDef->prefix))) { + dom_set_old_ns(nodep->doc, new_child->ns); + new_child->nsDef = NULL; + new_child->ns = nsptr; + } + } + DOM_RET_OBJ(rv, new_child, &ret, intern); } /* }}} end dom_node_append_child */ @@ -1263,7 +1269,47 @@ Since: DOM Level 3 */ PHP_FUNCTION(dom_node_lookup_prefix) { - DOM_NOT_IMPLEMENTED(); + zval *id; + xmlNodePtr nodep, lookupp = NULL; + 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) { + switch (nodep->type) { + case XML_ELEMENT_NODE: + lookupp = nodep; + break; + case XML_DOCUMENT_NODE: + case XML_HTML_DOCUMENT_NODE: + lookupp = xmlDocGetRootElement((xmlDocPtr) nodep); + break; + case XML_ENTITY_NODE : + case XML_NOTATION_NODE: + case XML_DOCUMENT_FRAG_NODE: + case XML_DOCUMENT_TYPE_NODE: + case XML_DTD_NODE: + RETURN_NULL(); + break; + default: + lookupp = nodep->parent; + } + + if (lookupp != NULL && (nsptr = xmlSearchNsByHref(lookupp->doc, lookupp, uri))) { + if (nsptr->prefix != NULL) { + RETURN_STRING((char *) nsptr->prefix, 1); + } + } + } + + RETURN_NULL(); } /* }}} end dom_node_lookup_prefix */ @@ -1285,7 +1331,27 @@ Since: DOM Level 3 */ PHP_FUNCTION(dom_node_lookup_namespace_uri) { - DOM_NOT_IMPLEMENTED(); + zval *id; + xmlNodePtr nodep; + dom_object *intern; + xmlNsPtr nsptr; + int prefix_len = 0; + char *prefix; + + DOM_GET_THIS_OBJ(nodep, id, xmlNodePtr, intern); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &prefix, &prefix_len) == FAILURE) { + return; + } + + if (prefix_len > 0) { + nsptr = xmlSearchNs(nodep->doc, nodep, prefix); + if (nsptr && nsptr->href != NULL) { + RETURN_STRING((char *) nsptr->href, 1); + } + } + + RETURN_NULL(); } /* }}} end dom_node_lookup_namespace_uri */ diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index 9a141fe194..17964978ef 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -680,7 +680,7 @@ PHP_MSHUTDOWN_FUNCTION(dom) uncomment the following line, this will tell you the amount of not freed memory and the total used memory into apaches error_log */ /* xmlMemoryDump();*/ - +xmlMemoryDump(); return SUCCESS; } @@ -1190,51 +1190,36 @@ void dom_set_old_ns(xmlDoc *doc, xmlNs *ns) { } /* }}} end dom_set_old_ns */ +int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len) { + int errorcode = 0; -/* {{{ xmlNsPtr dom_get_ns(char *uri, char *qName, int uri_len, int qName_len, int *errorcode, char *localname) */ -xmlNsPtr dom_get_ns(char *uri, char *qName, int uri_len, int qName_len, int *errorcode, char **localname) { - xmlNsPtr nsptr = NULL; - xmlURIPtr uristruct; - char *prefix = NULL; + if (uri_len > 0 && name_len > 0) { + *localname = xmlSplitQName2(qname, (xmlChar **) prefix); + if (*localname == NULL) { + *localname = xmlStrdup(qname); + } + if (*localname == NULL || (xmlStrchr(*localname, (xmlChar) ':') != NULL)) { + errorcode = NAMESPACE_ERR; + } + } else { + errorcode = NAMESPACE_ERR; + } - *localname = NULL; - *errorcode = 0; + return errorcode; +} - if (uri_len > 0 || qName_len > 0) { - if (qName_len == 0 && uri_len > 0) { - *errorcode = NAMESPACE_ERR; - return nsptr; - } - if (qName_len > 0 && *errorcode == 0) { - uristruct = xmlParseURI(qName); - if (uristruct->opaque != NULL) { - prefix = xmlStrdup(uristruct->scheme); - *localname = xmlStrdup(uristruct->opaque); - if (xmlStrchr(*localname, (xmlChar) ':') != NULL) { - *errorcode = NAMESPACE_ERR; - } else if (!strcmp (prefix, "xml") && strcmp(uri, XML_XML_NAMESPACE)) { - *errorcode = NAMESPACE_ERR; - } - } +/* {{{ xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) */ +xmlNsPtr dom_get_ns(xmlNodePtr nodep, char *uri, int *errorcode, char *prefix) { + xmlNsPtr nsptr = NULL; - /* TODO: Test that localname has no invalid chars - php_dom_throw_error(INVALID_CHARACTER_ERR, TSRMLS_CC); - */ + *errorcode = 0; - xmlFreeURI(uristruct); - - if (*errorcode == 0) { - if (uri_len > 0 && prefix == NULL) { - *errorcode = NAMESPACE_ERR; - } else if (*localname != NULL) { - nsptr = xmlNewNs(NULL, uri, prefix); - } - } - } + if (! (prefix && !strcmp (prefix, "xml") && strcmp(uri, XML_XML_NAMESPACE))) { + nsptr = xmlNewNs(nodep, uri, prefix); } - if (prefix != NULL) { - xmlFree(prefix); + if (nsptr == NULL) { + *errorcode = NAMESPACE_ERR; } return nsptr; diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index 4f5d947594..6bdf13952f 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -77,7 +77,8 @@ void node_list_unlink(xmlNodePtr node TSRMLS_DC); int decrement_node_ptr(dom_object *object TSRMLS_DC); int increment_document_reference(dom_object *object, xmlDocPtr docp TSRMLS_DC); int decrement_document_reference(dom_object *object TSRMLS_DC); -xmlNsPtr dom_get_ns(char *uri, char *qName, int uri_len, int qName_len, int *errorcode, char **localname); +int dom_check_qname(char *qname, char **localname, char **prefix, int uri_len, int name_len); +xmlNsPtr dom_get_ns(xmlNodePtr node, char *uri, int *errorcode, char *prefix); void dom_set_old_ns(xmlDoc *doc, xmlNs *ns); xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName); void dom_normalize (xmlNodePtr nodep TSRMLS_DC); |