summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/dom/nodelist.c71
-rw-r--r--ext/dom/php_dom.c82
-rw-r--r--ext/dom/php_dom.h1
-rw-r--r--ext/dom/tests/bug67949.phpt53
4 files changed, 96 insertions, 111 deletions
diff --git a/ext/dom/nodelist.c b/ext/dom/nodelist.c
index b865740775..1a0c811185 100644
--- a/ext/dom/nodelist.c
+++ b/ext/dom/nodelist.c
@@ -98,47 +98,6 @@ int dom_nodelist_length_read(dom_object *obj, zval **retval TSRMLS_DC)
/* }}} */
-xmlNodePtr dom_nodelist_xml_item(dom_nnodemap_object *objmap, long index) /* {{{ */
-{
- xmlNodePtr itemnode = NULL;
-
- if (objmap->nodetype == XML_ENTITY_NODE) {
- itemnode = php_dom_libxml_hash_iter(objmap->ht, index);
- } else {
- itemnode = php_dom_libxml_notation_iter(objmap->ht, index);
- }
-
- return itemnode;
-} /* }}} end dom_nodelist_xml_item */
-
-xmlNodePtr dom_nodelist_baseobj_item(dom_nnodemap_object *objmap, long index) /* {{{ */
-{
- xmlNodePtr itemnode = NULL;
- xmlNodePtr nodep, curnode;
- int count = 0;
-
- nodep = dom_object_get_node(objmap->baseobj);
- if (nodep) {
- if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
- curnode = nodep->children;
- while (count < index && curnode != NULL) {
- count++;
- curnode = curnode->next;
- }
- itemnode = curnode;
- } else {
- if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
- nodep = xmlDocGetRootElement((xmlDoc *) nodep);
- } else {
- nodep = nodep->children;
- }
- itemnode = dom_get_elements_by_tag_name_ns_raw(nodep, (char *) objmap->ns, (char *) objmap->local, &count, index);
- }
- }
-
- return itemnode;
-} /* }}} end dom_nodelist_baseobj_item */
-
/* {{{ proto DOMNode dom_nodelist_item(int index);
URL: http://www.w3.org/TR/2003/WD-DOM-Level-3-Core-20030226/DOM3-Core.html#ID-844377136
Since:
@@ -152,6 +111,8 @@ PHP_FUNCTION(dom_nodelist_item)
xmlNodePtr itemnode = NULL;
dom_nnodemap_object *objmap;
+ xmlNodePtr nodep, curnode;
+ int count = 0;
HashTable *nodeht;
zval **entry;
@@ -165,16 +126,38 @@ PHP_FUNCTION(dom_nodelist_item)
objmap = (dom_nnodemap_object *)intern->ptr;
if (objmap != NULL) {
if (objmap->ht) {
- itemnode = dom_nodelist_xml_item(objmap, index);
+ if (objmap->nodetype == XML_ENTITY_NODE) {
+ itemnode = php_dom_libxml_hash_iter(objmap->ht, index);
+ } else {
+ itemnode = php_dom_libxml_notation_iter(objmap->ht, index);
+ }
} else {
if (objmap->nodetype == DOM_NODESET) {
nodeht = HASH_OF(objmap->baseobjptr);
if (zend_hash_index_find(nodeht, index, (void **) &entry)==SUCCESS) {
- MAKE_COPY_ZVAL(entry, return_value);
+ *return_value = **entry;
+ zval_copy_ctor(return_value);
return;
}
} else if (objmap->baseobj) {
- itemnode = dom_nodelist_baseobj_item(objmap, index);
+ nodep = dom_object_get_node(objmap->baseobj);
+ if (nodep) {
+ if (objmap->nodetype == XML_ATTRIBUTE_NODE || objmap->nodetype == XML_ELEMENT_NODE) {
+ curnode = nodep->children;
+ while (count < index && curnode != NULL) {
+ count++;
+ curnode = curnode->next;
+ }
+ itemnode = curnode;
+ } else {
+ if (nodep->type == XML_DOCUMENT_NODE || nodep->type == XML_HTML_DOCUMENT_NODE) {
+ nodep = xmlDocGetRootElement((xmlDoc *) nodep);
+ } else {
+ nodep = nodep->children;
+ }
+ itemnode = dom_get_elements_by_tag_name_ns_raw(nodep, objmap->ns, objmap->local, &count, index);
+ }
+ }
}
}
}
diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c
index 01a0a6c6bb..ead6983ec2 100644
--- a/ext/dom/php_dom.c
+++ b/ext/dom/php_dom.c
@@ -1679,66 +1679,18 @@ xmlNsPtr dom_get_nsdecl(xmlNode *node, xmlChar *localName) {
}
/* }}} end dom_get_nsdecl */
-static int dom_nodelist_fetch_dimension(xmlNodePtr *itemnode, zval *offset, dom_nnodemap_object *objmap, zval *rv TSRMLS_DC) /* {{{ */
-{
- convert_to_long(offset);
- long index = Z_LVAL_P(offset);
- HashTable *nodeht;
- zval **entry;
- int ret = 0;
-
- if (objmap->ht) {
- *itemnode = dom_nodelist_xml_item(objmap, index);
- } else {
- if (objmap->nodetype == DOM_NODESET) {
- nodeht = HASH_OF(objmap->baseobjptr);
- if (zend_hash_index_find(nodeht, index, (void **) &entry) == SUCCESS) {
- if (itemnode != NULL && rv != NULL) {
- /* Passed by read_dimension */
- MAKE_COPY_ZVAL(entry, rv);
- }
- ret = 1;
- }
- } else if (objmap->baseobj) {
- if (itemnode == NULL && rv == NULL) {
- /* Passed by has_dimension */
- if (dom_nodelist_baseobj_item(objmap, index)) {
- ret = 1;
- }
- } else {
- *itemnode = dom_nodelist_baseobj_item(objmap, index);
- }
- }
- }
-
- if (rv != NULL && itemnode != NULL) {
- if (*itemnode) {
- ret = 1;
- }
- }
-
- return ret;
-} /* }}} end dom_nodelist_fetch_dimension */
-
zval *dom_nodelist_read_dimension(zval *object, zval *offset, int type TSRMLS_DC) /* {{{ */
{
- dom_object *intern;
- xmlNodePtr itemnode = NULL;
- dom_nnodemap_object *objmap;
- zval *rv;
- int found;
+ zval *rv, offset_copy;
- ALLOC_INIT_ZVAL(rv);
-
- intern = (dom_object *) zend_object_store_get_object(object TSRMLS_CC);
+ if (!offset) {
+ return NULL;
+ }
- objmap = (dom_nnodemap_object *)intern->ptr;
+ MAKE_COPY_ZVAL(&offset, &offset_copy);
+ convert_to_long(&offset_copy);
- if (dom_nodelist_fetch_dimension(&itemnode, offset, objmap, rv TSRMLS_CC)) {
- if (itemnode) {
- php_dom_create_object(itemnode, &found, rv, objmap->baseobj TSRMLS_CC);
- }
- }
+ zend_call_method_with_1_params(&object, Z_OBJCE_P(object), NULL, "item", &rv, &offset_copy);
Z_DELREF_P(rv);
@@ -1747,13 +1699,23 @@ zval *dom_nodelist_read_dimension(zval *object, zval *offset, int type TSRMLS_DC
int dom_nodelist_has_dimension(zval *object, zval *member, int check_empty TSRMLS_DC)
{
- dom_object *intern;
- dom_nnodemap_object *objmap;
+ zval *length, offset_copy;
+ int ret;
- intern = (dom_object *) zend_object_store_get_object(object TSRMLS_CC);
- objmap = (dom_nnodemap_object *)intern->ptr;
+ MAKE_COPY_ZVAL(&member, &offset_copy);
+ convert_to_long(&offset_copy);
+
+ if (Z_LVAL(offset_copy) < 0) {
+ return 0;
+ }
- return dom_nodelist_fetch_dimension(NULL, member, objmap, NULL TSRMLS_CC);
+ length = zend_read_property(Z_OBJCE_P(object), object, "length", sizeof("length") - 1, 0 TSRMLS_CC);
+
+ ret = Z_LVAL(offset_copy) < Z_LVAL_P(length);
+
+ FREE_ZVAL(length);
+
+ return ret;
} /* }}} end dom_nodelist_has_dimension */
#endif /* HAVE_DOM */
diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h
index eb35aa015d..6f0d9b80c1 100644
--- a/ext/dom/php_dom.h
+++ b/ext/dom/php_dom.h
@@ -125,7 +125,6 @@ zend_object_iterator *php_dom_get_iterator(zend_class_entry *ce, zval *object, i
int dom_set_doc_classmap(php_libxml_ref_obj *document, zend_class_entry *basece, zend_class_entry *ce TSRMLS_DC);
zval *dom_nodelist_read_dimension(zval *object, zval *offset, int type TSRMLS_DC);
int dom_nodelist_has_dimension(zval *object, zval *member, int check_empty TSRMLS_DC);
-static int dom_nodelist_fetch_dimension(xmlNodePtr *itemnode, zval *offset, dom_nnodemap_object *objmap, zval *rv TSRMLS_DC);
#define REGISTER_DOM_CLASS(ce, name, parent_ce, funcs, entry) \
INIT_CLASS_ENTRY(ce, name, funcs); \
diff --git a/ext/dom/tests/bug67949.phpt b/ext/dom/tests/bug67949.phpt
index b12dc81d1d..fc29881ca7 100644
--- a/ext/dom/tests/bug67949.phpt
+++ b/ext/dom/tests/bug67949.phpt
@@ -5,16 +5,57 @@ Bug #67949: DOMNodeList elements should be accessible through array notation
$html = <<<HTML
<div>data</div>
+<a href="test">hello world</a>
HTML;
$doc = new DOMDocument;
$doc->loadHTML($html);
-var_dump($doc->getElementsByTagName('div')[0]->textContent);
-var_dump($doc->getElementsByTagName('div')['test']->textContent); // testing that weak casting works
-var_dump(isset($doc->getElementsByTagName('div')[0]));
-var_dump(isset($doc->getElementsByTagName('div')[1]));
---EXPECT--
+$nodes = $doc->getElementsByTagName('div');
+
+echo "testing has_dimension\n";
+var_dump(isset($nodes[0]));
+var_dump(isset($nodes[1]));
+var_dump(isset($nodes[-1]));
+
+echo "testing property access\n";
+var_dump($nodes[0]->textContent);
+var_dump($nodes[1]->textContent);
+
+echo "testing offset not a long\n";
+$offset = 'test';
+var_dump($offset);
+var_dump($nodes[$offset]->textContent);
+var_dump($offset);
+var_dump(isset($nodes[$offset]));
+var_dump($offset);
+
+echo "testing read_dimension with null offset\n";
+var_dump($nodes[][] = 1);
+
+echo "testing attribute access\n";
+$anchor = $doc->getElementsByTagName('a')[0];
+var_dump($anchor->attributes[0]->name);
+
+echo "==DONE==\n";
+
+--EXPECTF--
+testing has_dimension
+bool(true)
+bool(false)
+bool(false)
+testing property access
string(4) "data"
+
+Notice: Trying to get property of non-object in %s on line %d
+NULL
+testing offset not a long
+string(4) "test"
string(4) "data"
+string(4) "test"
bool(true)
-bool(false)
+string(4) "test"
+testing read_dimension with null offset
+NULL
+testing attribute access
+string(4) "href"
+==DONE==