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
This commit is contained in:
Rob Richards 2003-10-05 11:52:22 +00:00
parent 4de32429f5
commit c21e78ddf2
4 changed files with 149 additions and 70 deletions

View file

@ -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)

View file

@ -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) {

View file

@ -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)

View file

@ -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);