summaryrefslogtreecommitdiff
path: root/ext/soap/php_encoding.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/soap/php_encoding.c')
-rw-r--r--ext/soap/php_encoding.c236
1 files changed, 149 insertions, 87 deletions
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
index 0760a2aec0..79a983a629 100644
--- a/ext/soap/php_encoding.c
+++ b/ext/soap/php_encoding.c
@@ -128,6 +128,7 @@ encode defaultEncoding[] = {
{{IS_NULL, "nil", XSI_NAMESPACE, NULL}, to_zval_null, to_xml_null},
{{IS_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
+ {{IS_UNICODE, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
{{IS_LONG, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
{{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
{{IS_BOOL, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
@@ -333,30 +334,43 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
zend_class_entry *ce = Z_OBJCE_P(data);
HashPosition pos;
zval **tmp;
- char *type_name = NULL;
+ zstr type_name = NULL_ZSTR;
uint type_len;
ulong idx;
for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(class_map), &pos);
zend_hash_get_current_data_ex(SOAP_GLOBAL(class_map), (void **) &tmp, &pos) == SUCCESS;
zend_hash_move_forward_ex(SOAP_GLOBAL(class_map), &pos)) {
- if (Z_TYPE_PP(tmp) == IS_STRING &&
- ce->name_length == Z_STRLEN_PP(tmp) &&
- /* FIXME: Unicode support??? */
- zend_binary_strncasecmp(ce->name.s, ce->name_length, Z_STRVAL_PP(tmp), ce->name_length, ce->name_length) == 0 &&
- zend_hash_get_current_key_ex(SOAP_GLOBAL(class_map), &type_name, &type_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) {
-
- /* TODO: namespace isn't stored */
- encodePtr enc = get_encoder(SOAP_GLOBAL(sdl), SOAP_GLOBAL(sdl)->target_ns, type_name);
- if (enc) {
- encode = enc;
- } else if (SOAP_GLOBAL(sdl)) {
- enc = find_encoder_by_type_name(SOAP_GLOBAL(sdl), type_name);
- if (enc) {
- encode = enc;
+ if ((!UG(unicode) &&
+ Z_TYPE_PP(tmp) == IS_STRING &&
+ ce->name_length == Z_STRLEN_PP(tmp) &&
+ zend_binary_strncasecmp(ce->name.s, ce->name_length, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), ce->name_length) == 0) ||
+ (UG(unicode) &&
+ Z_TYPE_PP(tmp) == IS_UNICODE &&
+ ce->name_length == Z_USTRLEN_PP(tmp) &&
+ zend_u_binary_strncasecmp(ce->name.u, ce->name_length, Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp), ce->name_length) == 0)) {
+
+ zend_uchar utype = zend_hash_get_current_key_ex(SOAP_GLOBAL(class_map), &type_name, &type_len, &idx, 0, &pos);
+
+ if (utype == HASH_KEY_IS_STRING || utype == HASH_KEY_IS_UNICODE) {
+ if (utype == HASH_KEY_IS_UNICODE) {
+ type_name.s = soap_unicode_to_string(type_name.u, type_len TSRMLS_CC);
}
- }
- break;
+ /* TODO: namespace isn't stored */
+ encodePtr enc = get_encoder(SOAP_GLOBAL(sdl), SOAP_GLOBAL(sdl)->target_ns, type_name.s);
+ if (enc) {
+ encode = enc;
+ } else if (SOAP_GLOBAL(sdl)) {
+ enc = find_encoder_by_type_name(SOAP_GLOBAL(sdl), type_name.s);
+ if (enc) {
+ encode = enc;
+ }
+ }
+ if (utype == HASH_KEY_IS_UNICODE) {
+ efree(type_name.v);
+ }
+ break;
+ }
}
}
}
@@ -559,7 +573,11 @@ static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
TSRMLS_FETCH();
- if (SOAP_GLOBAL(encoding) != NULL) {
+ if (UG(unicode)) {
+ /* TODO: unicode support */
+ ZVAL_STRING(ret, (char*)data->children->content, 1);
+ zval_string_to_unicode_ex(ret, UG(utf8_conv) TSRMLS_CC);
+ } else if (SOAP_GLOBAL(encoding) != NULL) {
xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
xmlBufferPtr out = xmlBufferCreate();
int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
@@ -595,7 +613,11 @@ static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
TSRMLS_FETCH();
whiteSpace_replace(data->children->content);
- if (SOAP_GLOBAL(encoding) != NULL) {
+ if (UG(unicode)) {
+ /* TODO: unicode support */
+ ZVAL_STRING(ret, (char*)data->children->content, 1);
+ zval_string_to_unicode_ex(ret, UG(utf8_conv) TSRMLS_CC);
+ } else if (SOAP_GLOBAL(encoding) != NULL) {
xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
xmlBufferPtr out = xmlBufferCreate();
int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
@@ -631,7 +653,11 @@ static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
TSRMLS_FETCH();
whiteSpace_collapse(data->children->content);
- if (SOAP_GLOBAL(encoding) != NULL) {
+ if (UG(unicode)) {
+ /* TODO: unicode support */
+ ZVAL_STRING(ret, (char*)data->children->content, 1);
+ zval_string_to_unicode_ex(ret, UG(utf8_conv) TSRMLS_CC);
+ } else if (SOAP_GLOBAL(encoding) != NULL) {
xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
xmlBufferPtr out = xmlBufferCreate();
int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
@@ -737,37 +763,41 @@ static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNo
xmlAddChild(parent, ret);
FIND_ZVAL_NULL(data, ret, style);
- if (Z_TYPE_P(data) == IS_STRING) {
- str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
- new_len = Z_STRLEN_P(data);
+ if (Z_TYPE_P(data) == IS_UNICODE) {
+ str = soap_unicode_to_string(Z_USTRVAL_P(data), Z_USTRLEN_P(data) TSRMLS_CC);
+ new_len = strlen(str);
} else {
- zval tmp = *data;
+ if (Z_TYPE_P(data) == IS_STRING) {
+ str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
+ new_len = Z_STRLEN_P(data);
+ } else {
+ zval tmp = *data;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
- new_len = Z_STRLEN(tmp);
- zval_dtor(&tmp);
- }
+ zval_copy_ctor(&tmp);
+ convert_to_string(&tmp);
+ str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
+ new_len = Z_STRLEN(tmp);
+ zval_dtor(&tmp);
+ }
- if (SOAP_GLOBAL(encoding) != NULL) {
- xmlBufferPtr in = xmlBufferCreateStatic(str, new_len);
- xmlBufferPtr out = xmlBufferCreate();
- int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
+ if (SOAP_GLOBAL(encoding) != NULL) {
+ xmlBufferPtr in = xmlBufferCreateStatic(str, new_len);
+ xmlBufferPtr out = xmlBufferCreate();
+ int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
- if (n >= 0) {
- efree(str);
- str = estrdup((char*)xmlBufferContent(out));
- new_len = n;
+ if (n >= 0) {
+ efree(str);
+ str = estrdup((char*)xmlBufferContent(out));
+ new_len = n;
+ } else if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
+ soap_error1(E_ERROR, "Encoding: string '%s' is not a valid utf-8 string", str);
+ }
+ xmlBufferFree(out);
+ xmlBufferFree(in);
} else if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
soap_error1(E_ERROR, "Encoding: string '%s' is not a valid utf-8 string", str);
}
- xmlBufferFree(out);
- xmlBufferFree(in);
- } else if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
- soap_error1(E_ERROR, "Encoding: string '%s' is not a valid utf-8 string", str);
}
-
text = xmlNewTextLen(BAD_CAST(str), new_len);
xmlAddChild(ret, text);
efree(str);
@@ -1043,7 +1073,7 @@ static zval* get_zval_property(zval* object, char* name TSRMLS_DC)
ZVAL_STRING(&member, name, 0);
old_scope = EG(scope);
- EG(scope) = Z_OBJCE_P(object);
+ EG(scope) = Z_OBJCE_P(object);
data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS TSRMLS_CC);
if (data == EG(uninitialized_zval_ptr)) {
/* Hack for bug #32455 */
@@ -1077,7 +1107,7 @@ static void unset_zval_property(zval* object, char* name TSRMLS_DC)
ZVAL_STRING(&member, name, 0);
old_scope = EG(scope);
- EG(scope) = Z_OBJCE_P(object);
+ EG(scope) = Z_OBJCE_P(object);
Z_OBJ_HT_P(object)->unset_property(object, &member TSRMLS_CC);
EG(scope) = old_scope;
} else if (Z_TYPE_P(object) == IS_ARRAY) {
@@ -1093,33 +1123,33 @@ static void model_to_zval_any(zval *ret, xmlNodePtr node TSRMLS_DC)
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) {
+ (Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_UNICODE)) {
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) {
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_TYPE_P(val2) != IS_UNICODE) {
break;
}
add_string_to_string(val, val, val2);
zval_ptr_dtor(&val2);
- node = node->next;
+ node = node->next;
}
}
if (any == NULL) {
any = val;
} else {
if (Z_TYPE_P(any) != IS_ARRAY) {
- /* Convert into array */
- zval *arr;
+ /* Convert into array */
+ zval *arr;
- MAKE_STD_ZVAL(arr);
- array_init(arr);
- add_next_index_zval(arr, any);
- any = arr;
- }
- /* Add array element */
- add_next_index_zval(any, val);
+ MAKE_STD_ZVAL(arr);
+ array_init(arr);
+ add_next_index_zval(arr, any);
+ any = arr;
+ }
+ /* Add array element */
+ add_next_index_zval(any, val);
}
}
node = node->next;
@@ -1247,8 +1277,9 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
zend_class_entry *tmp;
if (zend_hash_find(SOAP_GLOBAL(class_map), type->type_str, strlen(type->type_str)+1, (void**)&classname) == SUCCESS &&
- Z_TYPE_PP(classname) == IS_STRING &&
- (tmp = zend_fetch_class(Z_STRVAL_PP(classname), Z_STRLEN_PP(classname), ZEND_FETCH_CLASS_AUTO TSRMLS_CC)) != NULL) {
+ (Z_TYPE_PP(classname) == IS_STRING ||
+ Z_TYPE_PP(classname) == IS_UNICODE) &&
+ (tmp = zend_u_fetch_class(Z_TYPE_PP(classname), Z_UNIVAL_PP(classname), Z_UNILEN_PP(classname), ZEND_FETCH_CLASS_AUTO TSRMLS_CC)) != NULL) {
ce = tmp;
}
}
@@ -1380,22 +1411,22 @@ static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_e
prop = get_zval_property(ret, (char*)trav->name TSRMLS_CC);
if (!prop) {
- set_zval_property(ret, (char*)trav->name, tmpVal TSRMLS_CC);
+ set_zval_property(ret, (char*)trav->name, tmpVal TSRMLS_CC);
} else {
- /* Property already exist - make array */
- if (Z_TYPE_P(prop) != IS_ARRAY) {
- /* Convert into array */
- zval *arr;
-
- MAKE_STD_ZVAL(arr);
- array_init(arr);
- prop->refcount++;
- add_next_index_zval(arr, prop);
- set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC);
- prop = arr;
- }
- /* Add array element */
- add_next_index_zval(prop, tmpVal);
+ /* Property already exist - make array */
+ if (Z_TYPE_P(prop) != IS_ARRAY) {
+ /* Convert into array */
+ zval *arr;
+
+ MAKE_STD_ZVAL(arr);
+ array_init(arr);
+ prop->refcount++;
+ add_next_index_zval(arr, prop);
+ set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC);
+ prop = arr;
+ }
+ /* Add array element */
+ add_next_index_zval(prop, tmpVal);
}
}
trav = trav->next;
@@ -1755,28 +1786,35 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
for (;i > 0;i--) {
xmlNodePtr property;
zval **zprop;
- char *str_key;
+ zstr key;
+ uint key_len;
ulong index;
- int key_type;
+ zend_uchar key_type;
- key_type = zend_hash_get_current_key(prop, &str_key, &index, FALSE);
+ key_type = zend_hash_get_current_key_ex(prop, &key, &key_len, &index, FALSE, NULL);
zend_hash_get_current_data(prop, (void **)&zprop);
property = master_to_xml(get_conversion((*zprop)->type), (*zprop), style, xmlParam);
- if (key_type == HASH_KEY_IS_STRING) {
- char *prop_name;
+ if (key_type != HASH_KEY_IS_LONG) {
+ char *prop_name;
+ if (key_type == IS_UNICODE) {
+ key.s = soap_unicode_to_string(key.u, key_len TSRMLS_CC);
+ }
if (Z_TYPE_P(data) == IS_OBJECT) {
char *class_name;
- zend_unmangle_property_name(str_key, &class_name, &prop_name);
+ zend_unmangle_property_name(key.s, &class_name, &prop_name);
} else {
- prop_name = str_key;
+ prop_name = key.s;
}
if (prop_name) {
xmlNodeSetName(property, BAD_CAST(prop_name));
}
+ if (key_type == IS_UNICODE) {
+ efree(key.v);
+ }
}
zend_hash_move_forward(prop);
}
@@ -2400,10 +2438,12 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP
i = zend_hash_num_elements(Z_ARRVAL_P(data));
zend_hash_internal_pointer_reset(data->value.ht);
for (;i > 0;i--) {
+ zend_uchar key_type;
xmlNodePtr xparam, item;
xmlNodePtr key;
zval **temp_data;
- char *key_val;
+ zstr key_val;
+ uint key_len;
ulong int_val;
zend_hash_get_current_data(data->value.ht, (void **)&temp_data);
@@ -2412,11 +2452,22 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP
xmlAddChild(xmlParam, item);
key = xmlNewNode(NULL, BAD_CAST("key"));
xmlAddChild(item,key);
- if (zend_hash_get_current_key(data->value.ht, &key_val, &int_val, FALSE) == HASH_KEY_IS_STRING) {
+ key_type = zend_hash_get_current_key_ex(data->value.ht, &key_val, &key_len, &int_val, FALSE, NULL);
+ if (key_type == HASH_KEY_IS_STRING) {
if (style == SOAP_ENCODED) {
set_xsi_type(key, "xsd:string");
}
- xmlNodeSetContent(key, BAD_CAST(key_val));
+ xmlNodeSetContent(key, BAD_CAST(key_val.s));
+ } else if (key_type == HASH_KEY_IS_UNICODE) {
+ char *str;
+ TSRMLS_FETCH();
+
+ if (style == SOAP_ENCODED) {
+ set_xsi_type(key, "xsd:string");
+ }
+ str = soap_unicode_to_string(key_val.u, key_len TSRMLS_CC);
+ xmlNodeSetContent(key, BAD_CAST(str));
+ efree(str);
} else {
smart_str tmp = {0};
smart_str_append_long(&tmp, int_val);
@@ -2471,8 +2522,8 @@ static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
key = master_to_zval(NULL, xmlKey);
value = master_to_zval(NULL, xmlValue);
- if (Z_TYPE_P(key) == IS_STRING) {
- zend_hash_update(Z_ARRVAL_P(ret), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
+ if (Z_TYPE_P(key) == IS_STRING || Z_TYPE_P(key) == IS_UNICODE) {
+ zend_u_hash_update(Z_ARRVAL_P(ret), Z_TYPE_P(key), Z_UNIVAL_P(key), Z_UNILEN_P(key) + 1, &value, sizeof(zval *), NULL);
} else if (Z_TYPE_P(key) == IS_LONG) {
zend_hash_index_update(Z_ARRVAL_P(ret), Z_LVAL_P(key), &value, sizeof(zval *), NULL);
} else {
@@ -2646,6 +2697,13 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma
efree(buf);
} else if (Z_TYPE_P(data) == IS_STRING) {
xmlNodeSetContentLen(xmlParam, BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
+ } else if (Z_TYPE_P(data) == IS_UNICODE) {
+ char *str;
+ TSRMLS_FETCH();
+
+ str = soap_unicode_to_string(Z_USTRVAL_P(data), Z_USTRLEN_P(data) TSRMLS_CC);
+ xmlNodeSetContent(xmlParam, BAD_CAST(str));
+ efree(str);
}
if (style == SOAP_ENCODED) {
@@ -2810,11 +2868,15 @@ static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
{
xmlBufferPtr buf;
zval *ret;
+ TSRMLS_FETCH();
buf = xmlBufferCreate();
xmlNodeDump(buf, NULL, data, 0, 0);
MAKE_STD_ZVAL(ret);
ZVAL_STRING(ret, (char*)xmlBufferContent(buf), 1);
+ if (UG(unicode)) {
+ zval_string_to_unicode_ex(ret, UG(utf8_conv) TSRMLS_CC);
+ }
xmlBufferFree(buf);
return ret;
}
@@ -3122,7 +3184,7 @@ static int is_map(zval *array)
zend_hash_internal_pointer_reset(Z_ARRVAL_P(array));
for (i = 0;i < count;i++) {
- if (zend_hash_get_current_key_type(Z_ARRVAL_P(array)) == HASH_KEY_IS_STRING) {
+ if (zend_hash_get_current_key_type(Z_ARRVAL_P(array)) != HASH_KEY_IS_LONG) {
return TRUE;
}
zend_hash_move_forward(Z_ARRVAL_P(array));