mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
plane hacking
This commit is contained in:
parent
3c2f9fd5c0
commit
c60879dbb9
1 changed files with 181 additions and 56 deletions
|
@ -29,6 +29,11 @@
|
|||
|
||||
zend_class_entry *sxe_class_entry;
|
||||
|
||||
#define SKIP_TEXT(__p) \
|
||||
if ((__p)->type == XML_TEXT_NODE) { \
|
||||
goto next_iter; \
|
||||
}
|
||||
|
||||
static php_sxe_object *php_sxe_object_new(TSRMLS_D);
|
||||
static zend_object_value php_sxe_register_object(php_sxe_object * TSRMLS_DC);
|
||||
|
||||
|
@ -99,7 +104,7 @@ sxe_property_read(zval *object, zval *member TSRMLS_DC)
|
|||
APPEND_PREV_ELEMENT(counter, value);
|
||||
|
||||
MAKE_STD_ZVAL(value);
|
||||
contents = xmlNodeListGetString(sxe->document, attr->xmlChildrenNode, 1);
|
||||
contents = xmlNodeListGetString(sxe->document, attr->children, 1);
|
||||
ZVAL_STRING(value, contents, 0);
|
||||
|
||||
APPEND_CUR_ELEMENT(counter, value);
|
||||
|
@ -110,9 +115,11 @@ sxe_property_read(zval *object, zval *member TSRMLS_DC)
|
|||
if (!sxe->node) {
|
||||
sxe->node = node;
|
||||
}
|
||||
node = node->xmlChildrenNode;
|
||||
node = node->children;
|
||||
|
||||
while (node) {
|
||||
SKIP_TEXT(node);
|
||||
|
||||
if (node->ns && !xmlStrcmp(node->ns->prefix, name)) {
|
||||
APPEND_PREV_ELEMENT(counter, value);
|
||||
|
||||
|
@ -129,6 +136,7 @@ sxe_property_read(zval *object, zval *member TSRMLS_DC)
|
|||
APPEND_CUR_ELEMENT(counter, value);
|
||||
}
|
||||
|
||||
next_iter:
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
|
@ -192,21 +200,23 @@ sxe_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
|
|||
attr = attr->next;
|
||||
}
|
||||
|
||||
node = node->xmlChildrenNode;
|
||||
node = node->children;
|
||||
while (node) {
|
||||
SKIP_TEXT(node);
|
||||
if (!xmlStrcmp(node->name, name)) {
|
||||
newnode = node;
|
||||
++counter;
|
||||
}
|
||||
|
||||
next_iter:
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
if (counter == 1) {
|
||||
if (is_attr) {
|
||||
change_node_zval(attr->xmlChildrenNode, value);
|
||||
change_node_zval(attr->children, value);
|
||||
} else {
|
||||
change_node_zval(newnode->xmlChildrenNode, value);
|
||||
change_node_zval(newnode->children, value);
|
||||
}
|
||||
} else if (counter > 1) {
|
||||
php_error(E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)\n");
|
||||
|
@ -258,12 +268,15 @@ sxe_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
|
|||
attr = attr->next;
|
||||
}
|
||||
|
||||
node = node->xmlChildrenNode;
|
||||
node = node->children;
|
||||
while (node) {
|
||||
SKIP_TEXT(node);
|
||||
|
||||
if (!xmlStrcmp(node->name, name)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
next_iter:
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
|
@ -276,7 +289,66 @@ sxe_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
|
|||
static void
|
||||
sxe_property_delete(zval *object, zval *member TSRMLS_DC)
|
||||
{
|
||||
php_sxe_object *sxe;
|
||||
xmlNodePtr node;
|
||||
xmlNodePtr nnext;
|
||||
xmlAttrPtr attr;
|
||||
xmlAttrPtr anext;
|
||||
|
||||
sxe = php_sxe_fetch_object(object TSRMLS_CC);
|
||||
|
||||
GET_NODE(sxe, node);
|
||||
|
||||
attr = node->properties;
|
||||
while (attr) {
|
||||
anext = attr->next;
|
||||
if (!xmlStrcmp(attr->name, Z_STRVAL_P(member))) {
|
||||
// free
|
||||
}
|
||||
attr = anext;
|
||||
}
|
||||
|
||||
node = node->children;
|
||||
while (node) {
|
||||
nnext = node->next;
|
||||
|
||||
SKIP_TEXT(node);
|
||||
|
||||
if (!xmlStrcmp(node->name, Z_STRVAL_P(member))) {
|
||||
xmlUnlinkNode(node);
|
||||
xmlFreeNode(node);
|
||||
}
|
||||
|
||||
next_iter:
|
||||
node = nnext;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ _get_base_node_value()
|
||||
*/
|
||||
static void
|
||||
_get_base_node_value(xmlNodePtr node, zval **value TSRMLS_CC)
|
||||
{
|
||||
php_sxe_object *subnode;
|
||||
char *contents;
|
||||
|
||||
MAKE_STD_ZVAL(*value);
|
||||
|
||||
if (node->children && node->children->type == XML_TEXT_NODE && !xmlIsBlankNode(node->children)) {
|
||||
contents = xmlNodeListGetString(node->doc, node->children, 1);
|
||||
if (contents) {
|
||||
ZVAL_STRING(*value, contents, 1);
|
||||
}
|
||||
} else {
|
||||
subnode = php_sxe_object_new(TSRMLS_C);
|
||||
subnode->document = node->doc;
|
||||
subnode->node = node;
|
||||
|
||||
(*value)->type = IS_OBJECT;
|
||||
(*value)->value.obj = php_sxe_register_object(subnode TSRMLS_CC);
|
||||
zval_add_ref(value);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -285,10 +357,15 @@ sxe_property_delete(zval *object, zval *member TSRMLS_DC)
|
|||
static HashTable *
|
||||
sxe_properties_get(zval *object TSRMLS_DC)
|
||||
{
|
||||
HashTable *rv;
|
||||
php_sxe_object *sxe;
|
||||
xmlNodePtr node;
|
||||
int counter = 0;
|
||||
zval **data_ptr;
|
||||
zval *value;
|
||||
zval *newptr;
|
||||
HashTable *rv;
|
||||
php_sxe_object *sxe;
|
||||
char *name;
|
||||
xmlNodePtr node;
|
||||
ulong h;
|
||||
int namelen;
|
||||
|
||||
ALLOC_HASHTABLE_REL(rv);
|
||||
zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||
|
@ -296,14 +373,37 @@ sxe_properties_get(zval *object TSRMLS_DC)
|
|||
sxe = php_sxe_fetch_object(object TSRMLS_CC);
|
||||
|
||||
GET_NODE(sxe, node);
|
||||
node = node->children;
|
||||
|
||||
while (node) {
|
||||
SKIP_TEXT(node);
|
||||
|
||||
_get_base_node_value(node, &value TSRMLS_CC);
|
||||
|
||||
name = (char *) node->name;
|
||||
namelen = xmlStrlen(node->name) + 1;
|
||||
|
||||
h = zend_hash_func(name, namelen);
|
||||
if (zend_hash_quick_find(rv, name, namelen, h, (void **) &data_ptr) == SUCCESS) {
|
||||
if (Z_TYPE_PP(data_ptr) == IS_ARRAY) {
|
||||
zend_hash_next_index_insert(Z_ARRVAL_PP(data_ptr), &value, sizeof(zval *), NULL);
|
||||
} else {
|
||||
MAKE_STD_ZVAL(newptr);
|
||||
array_init(newptr);
|
||||
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(newptr), data_ptr, sizeof(zval *), NULL);
|
||||
zend_hash_next_index_insert(Z_ARRVAL_P(newptr), &value, sizeof(zval *), NULL);
|
||||
|
||||
zend_hash_quick_update(rv, name, namelen, h, &newptr, sizeof(zval *), NULL);
|
||||
}
|
||||
} else {
|
||||
zend_hash_quick_update(rv, name, namelen, h, &value, sizeof(zval *), NULL);
|
||||
}
|
||||
|
||||
next_iter:
|
||||
node = node->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: TODO
|
||||
* Recurse from the current node through the XML document
|
||||
* and build an array return value. Expensive? sure. But
|
||||
* if you ask for it, you get it :)
|
||||
*/
|
||||
|
||||
return rv;
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -313,7 +413,21 @@ sxe_properties_get(zval *object TSRMLS_DC)
|
|||
static int
|
||||
sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC)
|
||||
{
|
||||
return 0;
|
||||
php_sxe_object *sxe1;
|
||||
php_sxe_object *sxe2;
|
||||
|
||||
sxe1 = php_sxe_fetch_object(object1 TSRMLS_CC);
|
||||
sxe2 = php_sxe_fetch_object(object2 TSRMLS_CC);
|
||||
|
||||
if (sxe1->node == NULL) {
|
||||
if (sxe2->node) {
|
||||
return 1;
|
||||
} else if (sxe1->document == sxe2->document) {
|
||||
return 9;
|
||||
}
|
||||
} else {
|
||||
return !(sxe1->node == sxe2->node);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -375,7 +489,12 @@ simplexml_ce_xpath_search(INTERNAL_FUNCTION_PARAMETERS)
|
|||
|
||||
for (i = 0; i < result->nodeNr; ++i) {
|
||||
MAKE_STD_ZVAL(value);
|
||||
if (!xmlStrcmp(result->nodeTab[i]->name, "text")) {
|
||||
/**
|
||||
* Detect the case where the last selector is text(), simplexml
|
||||
* always accesses the text() child by default, therefore we assign
|
||||
* to the parent node.
|
||||
*/
|
||||
if (result->nodeTab[i]->type == XML_TEXT_NODE) {
|
||||
_node_as_zval(sxe, result->nodeTab[i]->parent, value);
|
||||
} else {
|
||||
_node_as_zval(sxe, result->nodeTab[i], value);
|
||||
|
@ -418,43 +537,22 @@ sxe_class_name_get(zval *object, char **class_name, zend_uint *class_name_len, i
|
|||
{
|
||||
*class_name = estrdup("simplexml_element");
|
||||
*class_name_len = sizeof("simplexml_element");
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ cast_empty_object()
|
||||
/* {{{ cast_object()
|
||||
*/
|
||||
static inline void
|
||||
cast_empty_object(zval *object, int type TSRMLS_DC)
|
||||
cast_object(zval *object, int type, char *contents TSRMLS_DC)
|
||||
{
|
||||
object->type = IS_NULL;
|
||||
switch (type) {
|
||||
case IS_BOOL:
|
||||
convert_to_boolean(object);
|
||||
break;
|
||||
case IS_LONG:
|
||||
convert_to_long(object);
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
convert_to_double(object);
|
||||
break;
|
||||
case IS_STRING:
|
||||
convert_to_string(object);
|
||||
break;
|
||||
if (contents) {
|
||||
int len = strlen(contents);
|
||||
ZVAL_STRINGL(object, contents, len, 1);
|
||||
} else {
|
||||
ZVAL_NULL(object);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ cast_object_with_contents()
|
||||
*/
|
||||
static inline void
|
||||
cast_object_with_contents(zval *object, int type, char *contents TSRMLS_DC)
|
||||
{
|
||||
int len = strlen(contents);
|
||||
|
||||
object->value.str.val = estrndup(contents, len);
|
||||
object->value.str.len = len;
|
||||
object->type = IS_STRING;
|
||||
|
||||
switch (type) {
|
||||
case IS_STRING:
|
||||
|
@ -487,13 +585,13 @@ sxe_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_
|
|||
}
|
||||
|
||||
if (sxe->node) {
|
||||
contents = xmlNodeListGetString(sxe->document, sxe->node->xmlChildrenNode, 1);
|
||||
if (!xmlIsBlankNode(sxe->node->xmlChildrenNode) && contents) {
|
||||
cast_empty_object(writeobj, type TSRMLS_CC);
|
||||
contents = xmlNodeListGetString(sxe->document, sxe->node->children, 1);
|
||||
if (!xmlIsBlankNode(sxe->node->children) && contents) {
|
||||
cast_object(writeobj, type, NULL TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
|
||||
cast_object_with_contents(writeobj, type, contents TSRMLS_CC);
|
||||
cast_object(writeobj, type, contents TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -504,7 +602,7 @@ sxe_object_set(zval **property, zval *value TSRMLS_DC)
|
|||
{
|
||||
/* XXX: TODO
|
||||
* This call is not yet implemented in the engine
|
||||
* so leave them blank for now.
|
||||
* so leave it blank for now.
|
||||
*/
|
||||
}
|
||||
/* }}} */
|
||||
|
@ -516,7 +614,7 @@ sxe_object_get(zval *property TSRMLS_DC)
|
|||
{
|
||||
/* XXX: TODO
|
||||
* This call is not yet implemented in the engine
|
||||
* so leave them blank for now.
|
||||
* so leave it blank for now.
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
|
@ -545,9 +643,24 @@ static zend_object_handlers sxe_object_handlers[] = {
|
|||
/* {{{ sxe_object_clone()
|
||||
*/
|
||||
static void
|
||||
sxe_object_clone(void *object, void **clone TSRMLS_DC)
|
||||
sxe_object_clone(void *object, void **clone_ptr TSRMLS_DC)
|
||||
{
|
||||
|
||||
php_sxe_object *sxe = (php_sxe_object *) object;
|
||||
php_sxe_object *clone;
|
||||
|
||||
clone = php_sxe_object_new(TSRMLS_C);
|
||||
|
||||
/**
|
||||
* XXX: Change parts of the code not to rely on sxe->document
|
||||
* being set.
|
||||
*/
|
||||
if (xmlDocGetRootElement(sxe->document) == sxe->node) {
|
||||
clone->document = xmlCopyDoc(sxe->document, 1);
|
||||
} else {
|
||||
clone->node = xmlCopyNode(sxe->node, 0);
|
||||
}
|
||||
|
||||
*clone_ptr = (void *) clone;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -556,6 +669,18 @@ sxe_object_clone(void *object, void **clone TSRMLS_DC)
|
|||
static void
|
||||
sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
||||
{
|
||||
php_sxe_object *sxe;
|
||||
|
||||
sxe = (php_sxe_object *) object;
|
||||
|
||||
if (sxe->document) {
|
||||
xmlFreeDoc(sxe->document);
|
||||
}
|
||||
|
||||
if (sxe->xpath) {
|
||||
xmlXPathFreeContext(sxe->xpath);
|
||||
}
|
||||
|
||||
zend_objects_destroy_object(object, handle TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue