diff options
Diffstat (limited to 'ext/soap/php_encoding.c')
-rw-r--r-- | ext/soap/php_encoding.c | 198 |
1 files changed, 175 insertions, 23 deletions
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index aed4400e4..9bf3356fd 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -17,7 +17,7 @@ | Dmitry Stogov <dmitry@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: php_encoding.c 291120 2009-11-21 19:43:00Z felipe $ */ +/* $Id: php_encoding.c 282177 2009-06-15 17:31:02Z felipe $ */ #include <time.h> @@ -26,6 +26,7 @@ #include "ext/standard/base64.h" #include <libxml/parserInternals.h> #include "zend_strtod.h" +#include "zend_interfaces.h" /* zval type decode */ static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data); @@ -346,8 +347,8 @@ static zend_bool soap_check_xml_ref(zval **data, xmlNodePtr node TSRMLS_DC) if (*data != *data_ptr) { zval_ptr_dtor(data); *data = *data_ptr; - (*data)->is_ref = 1; - (*data)->refcount++; + Z_SET_ISREF_PP(data); + Z_ADDREF_PP(data); return 1; } } else { @@ -372,7 +373,7 @@ static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xml HashTable *ht = Z_OBJPROP_P(data); if (zend_hash_find(ht, "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) { - soap_error0(E_ERROR, "Encoding: SoapVar hasn't 'enc_type' property"); + soap_error0(E_ERROR, "Encoding: SoapVar hasn't 'enc_type' propery"); } if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) { @@ -1208,7 +1209,7 @@ static void set_zval_property(zval* object, char* name, zval* val TSRMLS_DC) old_scope = EG(scope); EG(scope) = Z_OBJCE_P(object); #ifdef ZEND_ENGINE_2 - val->refcount--; + Z_DELREF_P(val); #endif add_property_zval(object, name, val); EG(scope) = old_scope; @@ -1269,44 +1270,82 @@ static void unset_zval_property(zval* object, char* name TSRMLS_DC) static void model_to_zval_any(zval *ret, xmlNodePtr node TSRMLS_DC) { zval* any = NULL; + char* name = NULL; while (node != NULL) { if (get_zval_property(ret, (char*)node->name TSRMLS_CC) == NULL) { zval* val = master_to_zval(get_conversion(XSD_ANYXML), node); - if (get_attribute_ex(node->properties,"type", XSI_NAMESPACE) == NULL && - Z_TYPE_P(val) == IS_STRING) { - while (node->next != NULL && - get_zval_property(ret, (char*)node->next->name TSRMLS_CC) == NULL && - get_attribute_ex(node->next->properties,"type", XSI_NAMESPACE) == NULL) { + + if (any && Z_TYPE_P(any) != IS_ARRAY) { + /* Convert into array */ + zval *arr; + + MAKE_STD_ZVAL(arr); + array_init(arr); + if (name) { + add_assoc_zval(arr, name, any); + } else { + add_next_index_zval(arr, any); + } + any = arr; + } + + if (Z_TYPE_P(val) == IS_STRING && *Z_STRVAL_P(val) == '<') { + name = NULL; + while (node->next != NULL) { zval* val2 = master_to_zval(get_conversion(XSD_ANYXML), node->next); - if (Z_TYPE_P(val2) != IS_STRING) { + if (Z_TYPE_P(val2) != IS_STRING || *Z_STRVAL_P(val) != '<') { break; } add_string_to_string(val, val, val2); zval_ptr_dtor(&val2); node = node->next; } + } else { + name = (char*)node->name; } + if (any == NULL) { - any = val; - } else { - if (Z_TYPE_P(any) != IS_ARRAY) { + if (name) { /* Convert into array */ zval *arr; MAKE_STD_ZVAL(arr); array_init(arr); - add_next_index_zval(arr, any); + add_assoc_zval(arr, name, val); any = arr; + name = NULL; + } else { + any = val; } + } else { /* Add array element */ - add_next_index_zval(any, val); + if (name) { + zval **el; + if (zend_hash_find(Z_ARRVAL_P(any), name, strlen(name)+1, (void**)&el) == SUCCESS) { + if (Z_TYPE_PP(el) != IS_ARRAY) { + /* Convert into array */ + zval *arr; + + MAKE_STD_ZVAL(arr); + array_init(arr); + add_next_index_zval(arr, *el); + *el = arr; + } + add_next_index_zval(*el, val); + } else { + add_assoc_zval(any, name, val); + } + } else { + add_next_index_zval(any, val); + } + name = NULL; } } node = node->next; } if (any) { - set_zval_property(ret, "any", any TSRMLS_CC); + set_zval_property(ret, name ? name : "any", any TSRMLS_CC); } } @@ -1518,7 +1557,7 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e } if (sdlType->model) { if (redo_any) { - redo_any->refcount++; + Z_ADDREF_P(redo_any); unset_zval_property(ret, "any" TSRMLS_CC); } model_to_zval_object(ret, sdlType->model, data, sdl TSRMLS_CC); @@ -1602,7 +1641,7 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e MAKE_STD_ZVAL(arr); array_init(arr); - prop->refcount++; + Z_ADDREF_P(prop); add_next_index_zval(arr, prop); set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC); prop = arr; @@ -2224,7 +2263,7 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod int dimension = 1; int* dims; int soap_version; - + zval *array_copy = NULL; TSRMLS_FETCH(); soap_version = SOAP_GLOBAL(soap_version); @@ -2244,6 +2283,75 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod return xmlParam; } + if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), zend_ce_traversable TSRMLS_CC)) { + zend_object_iterator *iter; + zend_class_entry *ce = Z_OBJCE_P(data); + zval **val; + char *str_key; + uint str_key_len; + ulong int_key; + int key_type; + + ALLOC_ZVAL(array_copy); + INIT_PZVAL(array_copy); + array_init(array_copy); + + iter = ce->get_iterator(ce, data, 0 TSRMLS_CC); + + if (EG(exception)) { + goto iterator_done; + } + + if (iter->funcs->rewind) { + iter->funcs->rewind(iter TSRMLS_CC); + if (EG(exception)) { + goto iterator_done; + } + } + + while (iter->funcs->valid(iter TSRMLS_CC) == SUCCESS) { + if (EG(exception)) { + goto iterator_done; + } + + iter->funcs->get_current_data(iter, &val TSRMLS_CC); + if (EG(exception)) { + goto iterator_done; + } + if (iter->funcs->get_current_key) { + key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC); + if (EG(exception)) { + goto iterator_done; + } + switch(key_type) { + case HASH_KEY_IS_STRING: + add_assoc_zval_ex(array_copy, str_key, str_key_len, *val); + efree(str_key); + break; + case HASH_KEY_IS_LONG: + add_index_zval(array_copy, int_key, *val); + break; + } + } else { + add_next_index_zval(array_copy, *val); + } + Z_ADDREF_PP(val); + + iter->funcs->move_forward(iter TSRMLS_CC); + if (EG(exception)) { + goto iterator_done; + } + } +iterator_done: + iter->funcs->dtor(iter TSRMLS_CC); + if (EG(exception)) { + zval_ptr_dtor(&array_copy); + array_copy = NULL; + } else { + data = array_copy; + } + } + if (Z_TYPE_P(data) == IS_ARRAY) { sdlAttributePtr *arrayType; sdlExtraAttributePtr *ext; @@ -2421,6 +2529,11 @@ static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNod set_ns_and_type(xmlParam, type); } } + + if (array_copy) { + zval_ptr_dtor(&array_copy); + } + return xmlParam; } @@ -2685,7 +2798,6 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP } xparam = master_to_xml(get_conversion((*temp_data)->type), (*temp_data), style, item); - xmlNodeSetName(xparam, BAD_CAST("value")); zend_hash_move_forward(data->value.ht); @@ -2830,7 +2942,7 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data) object_init_ex(soapvar, soap_var_class_entry); add_property_long(soapvar, "enc_type", enc->details.type); #ifdef ZEND_ENGINE_2 - ret->refcount--; + Z_DELREF_P(ret); #endif add_property_zval(soapvar, "enc_value", ret); parse_namespace(type_name, &cptype, &ns); @@ -3064,6 +3176,26 @@ static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data) { xmlBufferPtr buf; zval *ret; + TSRMLS_FETCH(); + + if (SOAP_GLOBAL(sdl) && SOAP_GLOBAL(sdl)->elements && data->name) { + smart_str nscat = {0}; + sdlTypePtr *sdl_type; + + if (data->ns && data->ns->href) { + smart_str_appends(&nscat, (char*)data->ns->href); + smart_str_appendc(&nscat, ':'); + } + smart_str_appends(&nscat, (char*)data->name); + smart_str_0(&nscat); + + if (zend_hash_find(SOAP_GLOBAL(sdl)->elements, nscat.c, nscat.len+1, (void **)&sdl_type) == SUCCESS && + (*sdl_type)->encode) { + smart_str_free(&nscat); + return master_to_zval_int((*sdl_type)->encode, data); + } + smart_str_free(&nscat); + } buf = xmlBufferCreate(); xmlNodeDump(buf, NULL, data, 0, 0); @@ -3075,8 +3207,28 @@ static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data) static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - xmlNodePtr ret; + xmlNodePtr ret = NULL; + if (Z_TYPE_P(data) == IS_ARRAY) { + HashPosition pos; + zval **el; + encodePtr enc = get_conversion(XSD_ANYXML); + char *name; + uint name_len; + ulong idx; + + for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(data), &pos); + zend_hash_get_current_data_ex(Z_ARRVAL_P(data), (void **) &el, &pos) == SUCCESS; + zend_hash_move_forward_ex(Z_ARRVAL_P(data), &pos)) { + ret = master_to_xml(enc, *el, style, parent); + if (ret && + ret->name != xmlStringTextNoenc && + zend_hash_get_current_key_ex(Z_ARRVAL_P(data), &name, &name_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) { + xmlNodeSetName(ret, BAD_CAST(name)); + } + } + return ret; + } if (Z_TYPE_P(data) == IS_STRING) { ret = xmlNewTextLen(BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data)); } else { |