mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +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;
|
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 php_sxe_object *php_sxe_object_new(TSRMLS_D);
|
||||||
static zend_object_value php_sxe_register_object(php_sxe_object * TSRMLS_DC);
|
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);
|
APPEND_PREV_ELEMENT(counter, value);
|
||||||
|
|
||||||
MAKE_STD_ZVAL(value);
|
MAKE_STD_ZVAL(value);
|
||||||
contents = xmlNodeListGetString(sxe->document, attr->xmlChildrenNode, 1);
|
contents = xmlNodeListGetString(sxe->document, attr->children, 1);
|
||||||
ZVAL_STRING(value, contents, 0);
|
ZVAL_STRING(value, contents, 0);
|
||||||
|
|
||||||
APPEND_CUR_ELEMENT(counter, value);
|
APPEND_CUR_ELEMENT(counter, value);
|
||||||
|
@ -110,9 +115,11 @@ sxe_property_read(zval *object, zval *member TSRMLS_DC)
|
||||||
if (!sxe->node) {
|
if (!sxe->node) {
|
||||||
sxe->node = node;
|
sxe->node = node;
|
||||||
}
|
}
|
||||||
node = node->xmlChildrenNode;
|
node = node->children;
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
|
SKIP_TEXT(node);
|
||||||
|
|
||||||
if (node->ns && !xmlStrcmp(node->ns->prefix, name)) {
|
if (node->ns && !xmlStrcmp(node->ns->prefix, name)) {
|
||||||
APPEND_PREV_ELEMENT(counter, value);
|
APPEND_PREV_ELEMENT(counter, value);
|
||||||
|
|
||||||
|
@ -129,6 +136,7 @@ sxe_property_read(zval *object, zval *member TSRMLS_DC)
|
||||||
APPEND_CUR_ELEMENT(counter, value);
|
APPEND_CUR_ELEMENT(counter, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_iter:
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,21 +200,23 @@ sxe_property_write(zval *object, zval *member, zval *value TSRMLS_DC)
|
||||||
attr = attr->next;
|
attr = attr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node->xmlChildrenNode;
|
node = node->children;
|
||||||
while (node) {
|
while (node) {
|
||||||
|
SKIP_TEXT(node);
|
||||||
if (!xmlStrcmp(node->name, name)) {
|
if (!xmlStrcmp(node->name, name)) {
|
||||||
newnode = node;
|
newnode = node;
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_iter:
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter == 1) {
|
if (counter == 1) {
|
||||||
if (is_attr) {
|
if (is_attr) {
|
||||||
change_node_zval(attr->xmlChildrenNode, value);
|
change_node_zval(attr->children, value);
|
||||||
} else {
|
} else {
|
||||||
change_node_zval(newnode->xmlChildrenNode, value);
|
change_node_zval(newnode->children, value);
|
||||||
}
|
}
|
||||||
} else if (counter > 1) {
|
} else if (counter > 1) {
|
||||||
php_error(E_WARNING, "Cannot assign to an array of nodes (duplicate subnodes or attr detected)\n");
|
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;
|
attr = attr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = node->xmlChildrenNode;
|
node = node->children;
|
||||||
while (node) {
|
while (node) {
|
||||||
|
SKIP_TEXT(node);
|
||||||
|
|
||||||
if (!xmlStrcmp(node->name, name)) {
|
if (!xmlStrcmp(node->name, name)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_iter:
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +289,66 @@ sxe_property_exists(zval *object, zval *member, int check_empty TSRMLS_DC)
|
||||||
static void
|
static void
|
||||||
sxe_property_delete(zval *object, zval *member TSRMLS_DC)
|
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 *
|
static HashTable *
|
||||||
sxe_properties_get(zval *object TSRMLS_DC)
|
sxe_properties_get(zval *object TSRMLS_DC)
|
||||||
{
|
{
|
||||||
HashTable *rv;
|
zval **data_ptr;
|
||||||
php_sxe_object *sxe;
|
zval *value;
|
||||||
xmlNodePtr node;
|
zval *newptr;
|
||||||
int counter = 0;
|
HashTable *rv;
|
||||||
|
php_sxe_object *sxe;
|
||||||
|
char *name;
|
||||||
|
xmlNodePtr node;
|
||||||
|
ulong h;
|
||||||
|
int namelen;
|
||||||
|
|
||||||
ALLOC_HASHTABLE_REL(rv);
|
ALLOC_HASHTABLE_REL(rv);
|
||||||
zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
|
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);
|
sxe = php_sxe_fetch_object(object TSRMLS_CC);
|
||||||
|
|
||||||
GET_NODE(sxe, node);
|
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;
|
return rv;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
@ -313,7 +413,21 @@ sxe_properties_get(zval *object TSRMLS_DC)
|
||||||
static int
|
static int
|
||||||
sxe_objects_compare(zval *object1, zval *object2 TSRMLS_DC)
|
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) {
|
for (i = 0; i < result->nodeNr; ++i) {
|
||||||
MAKE_STD_ZVAL(value);
|
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);
|
_node_as_zval(sxe, result->nodeTab[i]->parent, value);
|
||||||
} else {
|
} else {
|
||||||
_node_as_zval(sxe, result->nodeTab[i], value);
|
_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 = estrdup("simplexml_element");
|
||||||
*class_name_len = sizeof("simplexml_element");
|
*class_name_len = sizeof("simplexml_element");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ cast_empty_object()
|
/* {{{ cast_object()
|
||||||
*/
|
*/
|
||||||
static inline void
|
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;
|
if (contents) {
|
||||||
switch (type) {
|
int len = strlen(contents);
|
||||||
case IS_BOOL:
|
ZVAL_STRINGL(object, contents, len, 1);
|
||||||
convert_to_boolean(object);
|
} else {
|
||||||
break;
|
ZVAL_NULL(object);
|
||||||
case IS_LONG:
|
|
||||||
convert_to_long(object);
|
|
||||||
break;
|
|
||||||
case IS_DOUBLE:
|
|
||||||
convert_to_double(object);
|
|
||||||
break;
|
|
||||||
case IS_STRING:
|
|
||||||
convert_to_string(object);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
/* {{{ 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) {
|
switch (type) {
|
||||||
case IS_STRING:
|
case IS_STRING:
|
||||||
|
@ -487,13 +585,13 @@ sxe_object_cast(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sxe->node) {
|
if (sxe->node) {
|
||||||
contents = xmlNodeListGetString(sxe->document, sxe->node->xmlChildrenNode, 1);
|
contents = xmlNodeListGetString(sxe->document, sxe->node->children, 1);
|
||||||
if (!xmlIsBlankNode(sxe->node->xmlChildrenNode) && contents) {
|
if (!xmlIsBlankNode(sxe->node->children) && contents) {
|
||||||
cast_empty_object(writeobj, type TSRMLS_CC);
|
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
|
/* XXX: TODO
|
||||||
* This call is not yet implemented in the engine
|
* 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
|
/* XXX: TODO
|
||||||
* This call is not yet implemented in the engine
|
* This call is not yet implemented in the engine
|
||||||
* so leave them blank for now.
|
* so leave it blank for now.
|
||||||
*/
|
*/
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -545,9 +643,24 @@ static zend_object_handlers sxe_object_handlers[] = {
|
||||||
/* {{{ sxe_object_clone()
|
/* {{{ sxe_object_clone()
|
||||||
*/
|
*/
|
||||||
static void
|
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
|
static void
|
||||||
sxe_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
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);
|
zend_objects_destroy_object(object, handle TSRMLS_CC);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue