]> granicus.if.org Git - php/commitdiff
Unicode support
authorDmitry Stogov <dmitry@php.net>
Tue, 1 Aug 2006 16:10:25 +0000 (16:10 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 1 Aug 2006 16:10:25 +0000 (16:10 +0000)
ext/soap/php_encoding.c
ext/soap/php_http.c
ext/soap/php_soap.h
ext/soap/soap.c
ext/soap/tests/bugs/bug32941.phpt
ext/soap/tests/cookie.phpt [new file with mode: 0755]

index f56f47a1360385375759ededdee5c5e9eb65c49a..99b70139b490191f4ed6710551c08023174e1f7e 100644 (file)
@@ -284,26 +284,15 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
                encodePtr enc = NULL;
                HashTable *ht = Z_OBJPROP_P(data);
                char *stype_str = NULL, *ns_str = NULL;
-               int free_stype = 0, free_ns = 0;
 
                if (zend_hash_find(ht, "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) {
                        soap_error0(E_ERROR, "Encoding: SoapVar hasn't 'enc_type' propery");
                }
 
                if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
-                       if (Z_TYPE_PP(zstype) == IS_STRING) {
-                               stype_str = Z_STRVAL_PP(zstype);
-                       } else if (Z_TYPE_PP(zstype) == IS_UNICODE) {
-                               stype_str = soap_unicode_to_string(Z_USTRVAL_PP(zstype), Z_USTRLEN_PP(zstype) TSRMLS_CC);
-                               free_stype = 1;
-                       }
+                       stype_str = soap_encode_string(*zstype, NULL TSRMLS_CC);
                        if (stype_str && zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
-                               if (Z_TYPE_PP(zns) == IS_STRING) {
-                                       ns_str = Z_STRVAL_PP(zns);
-                               } else if (Z_TYPE_PP(zns) == IS_UNICODE) {
-                                       ns_str = soap_unicode_to_string(Z_USTRVAL_PP(zns), Z_USTRLEN_PP(zns) TSRMLS_CC);
-                                       free_ns = 1;
-                               }
+                               ns_str = soap_encode_string(*zns, NULL TSRMLS_CC);
                        }
                }
 
@@ -334,35 +323,26 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
                                set_ns_and_type_ex(node, ns_str, stype_str);
                        }
                }
-
-               if (free_stype) {
+               
+               if (stype_str) {
                        efree(stype_str);
                }
-               if (free_ns) {
+               if (ns_str) {
                        efree(ns_str);
                }
 
                if (zend_hash_find(ht, "enc_name", sizeof("enc_name"), (void **)&zname) == SUCCESS) {
-                       if (Z_TYPE_PP(zname) == IS_STRING) {
-                               xmlNodeSetName(node, BAD_CAST(Z_STRVAL_PP(zname)));
-                       } else if (Z_TYPE_PP(zname) == IS_UNICODE) {
-                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(zname), Z_USTRLEN_PP(zname) TSRMLS_CC);
+                       char *str = soap_encode_string(*zname, NULL TSRMLS_CC);
 
-                               xmlNodeSetName(node, BAD_CAST(str));
-                               efree(str);
-                       }
+                       xmlNodeSetName(node, BAD_CAST(str));
+                       efree(str);
                }
                if (zend_hash_find(ht, "enc_namens", sizeof("enc_namens"), (void **)&znamens) == SUCCESS) {
-                       if (Z_TYPE_PP(znamens) == IS_STRING) {
-                               xmlNsPtr nsp = encode_add_ns(node, Z_STRVAL_PP(znamens));
-                               xmlSetNs(node, nsp);
-                       } if (Z_TYPE_PP(znamens) == IS_UNICODE) {
-                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(znamens), Z_USTRLEN_PP(znamens) TSRMLS_CC);
+                       char *str = soap_encode_string(*znamens, NULL TSRMLS_CC);
+                       xmlNsPtr nsp = encode_add_ns(node, str);
 
-                               xmlNsPtr nsp = encode_add_ns(node, str);
-                               efree(str);
-                               xmlSetNs(node, nsp);
-                       }
+                       efree(str);
+                       xmlSetNs(node, nsp);
                }
        } else {
                if (SOAP_GLOBAL(class_map) && data &&
@@ -392,9 +372,8 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
                                    if (utype == HASH_KEY_IS_STRING || utype == HASH_KEY_IS_UNICODE) {
                                        encodePtr enc;
 
-                                               if (utype == HASH_KEY_IS_UNICODE) {
-                                                       type_name.s = soap_unicode_to_string(type_name.u, type_len TSRMLS_CC);
-                                               }
+                                       type_name.s = soap_encode_string_ex(utype, type_name, type_len TSRMLS_CC);
+
                                            /* TODO: namespace isn't stored */
                                        enc = get_encoder(SOAP_GLOBAL(sdl), SOAP_GLOBAL(sdl)->target_ns, type_name.s);
                                        if (enc) {
@@ -405,9 +384,7 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr par
                                                                encode = enc;
                                                        }
                                                }
-                                               if (utype == HASH_KEY_IS_UNICODE) {
-                                                       efree(type_name.v);
-                                               }
+                                               efree(type_name.v);
                                        break;
                                    }
                                }
@@ -612,25 +589,7 @@ static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
                if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
                        TSRMLS_FETCH();
 
-                       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);
-
-                               if (n >= 0) {
-                                       ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
-                               } else {
-                                       ZVAL_STRING(ret, (char*)data->children->content, 1);
-                               }
-                               xmlBufferFree(out);
-                               xmlBufferFree(in);
-                       } else {
-                               ZVAL_STRING(ret, (char*)data->children->content, 1);
-                       }
+                       soap_decode_string(ret, (char*)data->children->content TSRMLS_CC);
                } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
                        ZVAL_STRING(ret, (char*)data->children->content, 1);
                } else {
@@ -652,25 +611,7 @@ static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
                        TSRMLS_FETCH();
 
                        whiteSpace_replace(data->children->content);
-                       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);
-
-                               if (n >= 0) {
-                                       ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
-                               } else {
-                                       ZVAL_STRING(ret, (char*)data->children->content, 1);
-                               }
-                               xmlBufferFree(out);
-                               xmlBufferFree(in);
-                       } else {
-                               ZVAL_STRING(ret, (char*)data->children->content, 1);
-                       }
+                       soap_decode_string(ret, (char*)data->children->content TSRMLS_CC);
                } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
                        ZVAL_STRING(ret, (char*)data->children->content, 1);
                } else {
@@ -692,25 +633,7 @@ static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
                        TSRMLS_FETCH();
 
                        whiteSpace_collapse(data->children->content);
-                       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);
-
-                               if (n >= 0) {
-                                       ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
-                               } else {
-                                       ZVAL_STRING(ret, (char*)data->children->content, 1);
-                               }
-                               xmlBufferFree(out);
-                               xmlBufferFree(in);
-                       } else {
-                               ZVAL_STRING(ret, (char*)data->children->content, 1);
-                       }
+                       soap_decode_string(ret, (char*)data->children->content TSRMLS_CC);
                } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
                        ZVAL_STRING(ret, (char*)data->children->content, 1);
                } else {
@@ -802,41 +725,7 @@ 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_UNICODE) {
-               str = soap_unicode_to_string(Z_USTRVAL_P(data), Z_USTRLEN_P(data) TSRMLS_CC);
-               new_len = strlen(str);
-       } else {
-               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);
-               }
-
-               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;
-                       } 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);
-               }
-       }
+       str = soap_encode_string(data, &new_len TSRMLS_CC);
        text = xmlNewTextLen(BAD_CAST(str), new_len);
        xmlAddChild(ret, text);
        efree(str);
@@ -1836,9 +1725,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
                                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);
-                                       }
+                                       key.s = soap_encode_string_ex(key_type, key, key_len TSRMLS_CC);
                                        if (Z_TYPE_P(data) == IS_OBJECT) {
                                                char *class_name;
 
@@ -1849,9 +1736,7 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNo
                                        if (prop_name) {
                                                xmlNodeSetName(property, BAD_CAST(prop_name));
                                        }
-                                       if (key_type == IS_UNICODE) {
-                                               efree(key.v);
-                                       }
+                                       efree(key.s);
                                }
                                zend_hash_move_forward(prop);
                        }
@@ -2490,19 +2375,14 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodeP
                                key = xmlNewNode(NULL, BAD_CAST("key"));
                                xmlAddChild(item,key);
                                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.s));
-                               } else if (key_type == HASH_KEY_IS_UNICODE) {
+                               if (key_type == HASH_KEY_IS_STRING || 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);
+                                       str = soap_encode_string_ex(key_type, key_val, key_len TSRMLS_CC);
                                        xmlNodeSetContent(key, BAD_CAST(str));
                                        efree(str);
                                } else {
@@ -2610,9 +2490,9 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
        } else if (data->properties && get_attribute_ex(data->properties, "nil", XSI_NAMESPACE)) {
                enc = get_conversion(IS_NULL);
        } else {
-               tmpattr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
+               tmpattr = get_attribute_ex(data->properties, "type", XSI_NAMESPACE);
                if (tmpattr != NULL) {
-                 type_name = tmpattr->children->content;
+                       type_name = tmpattr->children->content;
                        enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, tmpattr->children->content);
                        if (enc && type == &enc->details) {
                                enc = NULL;
@@ -2669,12 +2549,12 @@ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
                parse_namespace(type_name, &cptype, &ns);
                nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));     
                MAKE_STD_ZVAL(tmp);
-               ZVAL_STRING(tmp, cptype, 1);
+               soap_decode_string(tmp, cptype TSRMLS_CC);
                tmp->refcount--;
                add_property_zval(soapvar, "enc_stype", tmp);
                if (nsptr) {
                        MAKE_STD_ZVAL(tmp);
-                       ZVAL_STRING(tmp, (char*)nsptr->href, 1);
+                       soap_decode_string(tmp, (char*)nsptr->href TSRMLS_CC);
                        tmp->refcount--;
                        add_property_zval(soapvar, "enc_ns", tmp);
                }
@@ -2737,13 +2617,11 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma
 
                xmlNodeSetContent(xmlParam, BAD_CAST(buf));
                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) {
+       } else if (Z_TYPE_P(data) == IS_STRING || 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);
+               str = soap_encode_string(data, NULL TSRMLS_CC);
                xmlNodeSetContent(xmlParam, BAD_CAST(str));
                efree(str);
        }
@@ -2915,10 +2793,7 @@ static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
        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);
-       }
+       soap_decode_string(ret, (char*)xmlBufferContent(buf) TSRMLS_CC);
        xmlBufferFree(buf);
        return ret;
 }
index 7e7e19c3ab41a0c45f8014a1363f990eb73d45fb..b88c17b0138f920d437c17c363323e43927cd257 100644 (file)
@@ -602,7 +602,9 @@ try_again:
                if (client->cookies) {
                        zval **data;
                        zstr key;
+                       uint key_len;
                        int i, n;
+                       zend_uchar key_type;
 
                        n = zend_hash_num_elements(Z_ARRVAL_P(client->cookies));
                        if (n > 0) {
@@ -610,23 +612,42 @@ try_again:
                                smart_str_append_const(&soap_headers, "Cookie: ");
                                for (i = 0; i < n; i++) {
                                        zend_hash_get_current_data(Z_ARRVAL_P(client->cookies), (void **)&data);
-                                       /* TODO: unicode support */
-                                       zend_hash_get_current_key(Z_ARRVAL_P(client->cookies), &key, NULL, FALSE);
+                                       key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(client->cookies), &key, &key_len, NULL, FALSE, NULL);
 
                                        if (Z_TYPE_PP(data) == IS_ARRAY) {
                                                zval** value;
 
                                                if (zend_hash_index_find(Z_ARRVAL_PP(data), 0, (void**)&value) == SUCCESS &&
-                                                   Z_TYPE_PP(value) == IS_STRING) {
+                                                   (Z_TYPE_PP(value) == IS_STRING || Z_TYPE_PP(value) == IS_UNICODE)) {
                                                  zval **tmp;
                                                  if ((zend_hash_index_find(Z_ARRVAL_PP(data), 1, (void**)&tmp) == FAILURE ||
                                                       strncmp(phpurl->path?phpurl->path:"/",Z_STRVAL_PP(tmp),Z_STRLEN_PP(tmp)) == 0) &&
                                                      (zend_hash_index_find(Z_ARRVAL_PP(data), 2, (void**)&tmp) == FAILURE ||
                                                       in_domain(phpurl->host,Z_STRVAL_PP(tmp))) &&
                                                      (use_ssl || zend_hash_index_find(Z_ARRVAL_PP(data), 3, (void**)&tmp) == FAILURE)) {
-                                                               smart_str_appendl(&soap_headers, key.s, strlen(key.s));
+                                                               if (key_type == IS_STRING) {
+                                                                       smart_str_appendl(&soap_headers, key.s, key_len-1);
+                                                               } else {
+                                                                       UErrorCode status = U_ZERO_ERROR;
+                                                                       char *res;
+                                                                       int res_len;
+
+                                                                       zend_convert_from_unicode(UG(utf8_conv), &res, &res_len, key.u, key_len-1, &status);
+                                                                       smart_str_appendl(&soap_headers, res, res_len);
+                                                                       efree(res);
+                                                               }
                                                                smart_str_appendc(&soap_headers, '=');
-                                                               smart_str_appendl(&soap_headers, Z_STRVAL_PP(value), Z_STRLEN_PP(value));
+                                                               if (Z_TYPE_PP(value) == IS_STRING) {
+                                                                       smart_str_appendl(&soap_headers, Z_STRVAL_PP(value), Z_STRLEN_PP(value));
+                                                               } else {
+                                                                       UErrorCode status = U_ZERO_ERROR;
+                                                                       char *res;
+                                                                       int res_len;
+
+                                                                       zend_convert_from_unicode(UG(utf8_conv), &res, &res_len, Z_USTRVAL_PP(value), Z_USTRLEN_PP(value), &status);
+                                                                       smart_str_appendl(&soap_headers, res, res_len);
+                                                                       efree(res);
+                                                               }
                                                                smart_str_appendc(&soap_headers, ';');
                                                        }
                                                }
@@ -751,6 +772,7 @@ try_again:
                        smart_str name = {0};
                        int cookie_len;
                        zval *zcookie;
+                       zval *zvalue;
 
                        if (sempos != NULL) {
                                cookie_len = sempos-(eqpos+1);
@@ -763,7 +785,12 @@ try_again:
 
                        ALLOC_INIT_ZVAL(zcookie);
                        array_init(zcookie);
-                       add_index_stringl(zcookie, 0, eqpos + 1, cookie_len, 1);
+                       MAKE_STD_ZVAL(zvalue);
+                       ZVAL_STRINGL(zvalue, eqpos + 1, cookie_len, 1);
+                       if (UG(unicode)) {
+                               zval_string_to_unicode_ex(zvalue, UG(utf8_conv) TSRMLS_CC);
+                       }
+                       add_index_zval(zcookie, 0, zvalue);
 
                        if (sempos != NULL) {
                                char *options = cookie + cookie_len+1;
index af8870d8c3421cb694456069e8190628d3f86606..2680045f1c16ee63c755d553850ee8353cda585b 100644 (file)
@@ -275,5 +275,8 @@ zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *faul
        php_error(severity, "SOAP-ERROR: " format, param1, param2, param3)
 
 char* soap_unicode_to_string(UChar *ustr, int ustr_len TSRMLS_DC);
+void soap_decode_string(zval *ret, char* str TSRMLS_DC);
+char* soap_encode_string(zval *data, int* len TSRMLS_DC);
+char* soap_encode_string_ex(zend_uchar type, zstr data, int len TSRMLS_DC);
 
 #endif
index 530f82a337a557217274455ee591e3c7f8b74ba6..6ef0c16faadc01d9b505e5ecbe01e68e78efcbeb 100644 (file)
@@ -27,6 +27,7 @@
 #include "ext/session/php_session.h"
 #endif
 #include "zend_exceptions.h"
+#include "ext/libxml/php_libxml.h"
 
 typedef struct _soapHeader {
        sdlFunctionPtr                    function;
@@ -185,6 +186,7 @@ PHP_METHOD(SoapClient, __getFunctions);
 PHP_METHOD(SoapClient, __getTypes);
 PHP_METHOD(SoapClient, __doRequest);
 PHP_METHOD(SoapClient, __setCookie);
+PHP_METHOD(SoapClient, __getCookies);
 PHP_METHOD(SoapClient, __setLocation);
 PHP_METHOD(SoapClient, __setSoapHeaders);
 
@@ -258,6 +260,7 @@ static zend_function_entry soap_client_functions[] = {
        PHP_ME(SoapClient, __getTypes, NULL, 0)
        PHP_ME(SoapClient, __doRequest, NULL, 0)
        PHP_ME(SoapClient, __setCookie, NULL, 0)
+       PHP_ME(SoapClient, __getCookies, NULL, 0)
        PHP_ME(SoapClient, __setLocation, NULL, 0)
        PHP_ME(SoapClient, __setSoapHeaders, NULL, 0)
        {NULL, NULL, NULL}
@@ -309,6 +312,105 @@ char* soap_unicode_to_string(UChar *ustr, int ustr_len TSRMLS_DC)
        return tmp;
 }
 
+void soap_decode_string(zval *ret, char* str TSRMLS_DC)
+{
+       if (UG(unicode)) {
+               /* TODO: unicode support */
+               ZVAL_STRING(ret, str, 1);
+               zval_string_to_unicode_ex(ret, UG(utf8_conv) TSRMLS_CC);
+       } else if (SOAP_GLOBAL(encoding) != NULL) {
+               xmlBufferPtr in  = xmlBufferCreateStatic(str, strlen(str));
+               xmlBufferPtr out = xmlBufferCreate();
+               int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
+
+               if (n >= 0) {
+                       ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
+               } else {
+                       ZVAL_STRING(ret, str, 1);
+               }
+               xmlBufferFree(out);
+               xmlBufferFree(in);
+       } else {
+               ZVAL_STRING(ret, str, 1);
+       }
+}
+
+char* soap_encode_string_ex(zend_uchar type, zstr data, int len TSRMLS_DC)
+{
+       char *str;
+       int new_len;
+
+       if (type == IS_UNICODE) {
+               str = soap_unicode_to_string(data.u, len TSRMLS_CC);
+       } else {
+               str = estrndup(data.s, len);
+               new_len = len;
+
+               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));
+                       } 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);
+               }
+       }
+       return str;
+}
+
+char* soap_encode_string(zval *data, int* len TSRMLS_DC)
+{
+       char *str;
+       int new_len;
+
+       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 {
+               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);
+               }
+
+               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;
+                       } 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);
+               }
+       }
+       if (len) {
+               *len = new_len;
+       }
+       return str;
+}
 
 ZEND_INI_MH(OnUpdateCacheEnabled)
 {
@@ -1465,7 +1567,6 @@ PHP_METHOD(SoapServer, getFunctions)
                zend_hash_internal_pointer_reset_ex(ft, &pos);
                while (zend_hash_get_current_data_ex(ft, (void **)&f, &pos) != FAILURE) {
                        if ((service->type != SOAP_CLASS) || (f->common.fn_flags & ZEND_ACC_PUBLIC)) {
-                               /* FIXME: Unicode support??? */
                                add_next_index_text(return_value, f->common.function_name, 1);
                        }
                        zend_hash_move_forward_ex(ft, &pos);
@@ -1583,17 +1684,18 @@ PHP_METHOD(SoapServer, handle)
        HashTable *function_table;
        soapHeader *soap_headers = NULL;
        sdlFunctionPtr function;
-       char *arg = NULL;
+       zstr arg = NULL_ZSTR;
        int arg_len;
        xmlCharEncodingHandlerPtr old_encoding;
        HashTable *old_class_map;
        int old_features;
+       zend_uchar arg_type;
 
        SOAP_SERVER_BEGIN_CODE();
 
        service = (soap_server_object*)zend_object_store_get_object(this_ptr TSRMLS_CC);
        SOAP_GLOBAL(soap_version) = service->version;
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|t", &arg, &arg_len, &arg_type) == FAILURE) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
        }
        INIT_ZVAL(retval);
@@ -1709,8 +1811,14 @@ PHP_METHOD(SoapServer, handle)
                        soap_server_fault("Server", "Bad Request. Can't find HTTP_RAW_POST_DATA", NULL, NULL, NULL TSRMLS_CC);
                        return;
                }
+       } else if (arg_type == IS_UNICODE) {
+               /* TODO: remove unicode->string conversion */
+               char *str_req = soap_unicode_to_string(arg.u, arg_len TSRMLS_CC);
+
+               doc_request = soap_xmlParseMemory(str_req, strlen(str_req));
+               efree(str_req);
        } else {
-               doc_request = soap_xmlParseMemory(arg,arg_len);
+               doc_request = soap_xmlParseMemory(arg.s, arg_len);
        }
 
        if (doc_request == NULL) {
@@ -2593,22 +2701,29 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
        ZVAL_STRINGL(&func,"__doRequest",sizeof("__doRequest")-1,0);
        INIT_ZVAL(param0);
        params[0] = &param0;
-       ZVAL_STRINGL(params[0], buf, buf_size, 0);
+       ZVAL_STRINGL(params[0], buf, buf_size, 1);
+       if (UG(unicode)) {
+       zval_string_to_unicode_ex(params[0], UG(utf8_conv) TSRMLS_CC);
+       }
        INIT_ZVAL(param1);
        params[1] = &param1;
        if (location == NULL) {
                ZVAL_NULL(params[1]);
        } else {
-               /* TODO: Unicode support */
-               ZVAL_STRING(params[1], location, 0);
+               ZVAL_STRING(params[1], location, 1);
+               if (UG(unicode)) {
+               zval_string_to_unicode_ex(params[1], UG(utf8_conv) TSRMLS_CC);
+               }
        }
        INIT_ZVAL(param2);
        params[2] = &param2;
        if (action == NULL) {
                ZVAL_NULL(params[2]);
        } else {
-               /* TODO: Unicode support */
-               ZVAL_STRING(params[2], action, 0);
+               ZVAL_STRING(params[2], action, 1);
+               if (UG(unicode)) {
+               zval_string_to_unicode_ex(params[2], UG(utf8_conv) TSRMLS_CC);
+               }
        }
        INIT_ZVAL(param3);
        params[3] = &param3;
@@ -2628,7 +2743,7 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
                ret = FALSE;
        } else {
            if (Z_TYPE_P(response) == IS_UNICODE) {
-               zval_unicode_to_string_ex(response, ZEND_U_CONVERTER(UG(runtime_encoding_conv)) TSRMLS_CC);
+               zval_unicode_to_string_ex(response, UG(utf8_conv) TSRMLS_CC);
            }
                if (client->trace) {
                        if (client->last_response) {
@@ -2638,6 +2753,9 @@ static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *act
                }
        }
        xmlFree(buf);
+       zval_dtor(params[0]);
+       zval_dtor(params[1]);
+       zval_dtor(params[2]);
        if (ret && client->fault) {
                return FALSE;
        }
@@ -2950,14 +3068,12 @@ PHP_METHOD(SoapClient, __call)
        if (output_headers) {
                array_init(output_headers);
        }
-       if (function_type == IS_UNICODE) {
-               function.s = soap_unicode_to_string(function.u, function_len TSRMLS_CC);
-               function_len = strlen(function.s);
-       }
+
+       function.s = soap_encode_string_ex(function_type, function, function_len TSRMLS_CC);
+       function_len = strlen(function.s);
        do_soap_call(this_ptr, function.s, function_len, arg_count, real_args, return_value, location, soap_action, uri, soap_headers, output_headers TSRMLS_CC);
-       if (function_type == IS_UNICODE) {
-               efree(function.s);
-       }
+       efree(function.s);
+
        if (arg_count > 0) {
                efree(real_args);
        }
@@ -3100,31 +3216,52 @@ PHP_METHOD(SoapClient, __getLastResponseHeaders)
    SoapClient::__doRequest() */
 PHP_METHOD(SoapClient, __doRequest)
 {
-  char *buf, *location, *action;
+  zstr  buf, location, action;
   int   buf_size, location_size, action_size;
+  zend_uchar buf_type, location_type, action_type;
   long  version;
   long  one_way = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl|l",
-           &buf, &buf_size,
-           &location, &location_size,
-           &action, &action_size,
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "tttl|l",
+           &buf, &buf_size, &buf_type,
+           &location, &location_size, &location_type,
+           &action, &action_size, &action_type,
            &version, &one_way) == FAILURE) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
        }
+       if (buf_type == IS_UNICODE) {
+               buf.s = soap_unicode_to_string(buf.u, buf_size TSRMLS_CC);
+               buf_size = strlen(buf.s);
+       }
+       if (location_type == IS_UNICODE) {
+               location.s = soap_unicode_to_string(location.u, location_size TSRMLS_CC);
+       }
+       if (action_type == IS_UNICODE) {
+               action.s = soap_unicode_to_string(action.u, action_size TSRMLS_CC);
+       }
        if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) {
                one_way = 0;
        }
        if (one_way) {
-               if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version, NULL, NULL TSRMLS_CC)) {
-                       RETURN_EMPTY_STRING();
+               if (make_http_soap_request(this_ptr, buf.s, buf_size, location.s, action.s, version, NULL, NULL TSRMLS_CC)) {
+                       RETVAL_EMPTY_STRING();
                }
-       } else if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version,
+       } else if (make_http_soap_request(this_ptr, buf.s, buf_size, location.s, action.s, version,
            &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC)) {
                return_value->type = IS_STRING;
-               return;
+               if (UG(unicode)) {
+                       zval_string_to_unicode_ex(return_value, UG(utf8_conv) TSRMLS_CC);
+               }
+       }
+       if (buf_type == IS_UNICODE) {
+               efree(buf.s);
+       }
+       if (location_type == IS_UNICODE) {
+               efree(location.s);
+       }
+       if (action_type == IS_UNICODE) {
+               efree(action.s);
        }
-       RETURN_NULL();
 }
 /* }}} */
 
@@ -3134,21 +3271,22 @@ PHP_METHOD(SoapClient, __doRequest)
    If value is not specified cookie is removed. */
 PHP_METHOD(SoapClient, __setCookie)
 {
-       char *name;
-       char *val = NULL;
+       zstr name;
+       zstr val = NULL_ZSTR;
        int  name_len, val_len;
+       zend_uchar name_type, val_type;
        soap_client_object *client;
 
        client = (soap_client_object*)zend_object_store_get_object(this_ptr TSRMLS_CC);
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s",
-           &name, &name_len, &val, &val_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|t",
+           &name, &name_len, &name_type, &val, &val_len, &val_type) == FAILURE) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
          RETURN_NULL();
        }
 
-       if (val == NULL) {
+       if (val.v == NULL) {
                if (client->cookies) {
-                       zend_hash_del(Z_ARRVAL_P(client->cookies), name, name_len+1);
+                       zend_u_hash_del(Z_ARRVAL_P(client->cookies), name_type, name, name_len+1);
                }
        } else {
                zval *zcookie;
@@ -3160,8 +3298,30 @@ PHP_METHOD(SoapClient, __setCookie)
 
                ALLOC_INIT_ZVAL(zcookie);
                array_init(zcookie);
-               add_index_stringl(zcookie, 0, val, val_len, 1);
-               add_assoc_zval_ex(client->cookies, name, name_len+1, zcookie);
+               if (val_type == IS_STRING) {
+                       add_index_stringl(zcookie, 0, val.s, val_len, 1);
+               } else {
+                       add_index_unicodel(zcookie, 0, val.u, val_len, 1);
+               }
+               add_u_assoc_zval_ex(client->cookies, name_type, name, name_len+1, zcookie);
+       }
+}
+/* }}} */
+
+/* {{{ proto array SoapClient::__getCookies()
+   Returns array of cookies. */
+PHP_METHOD(SoapClient, __getCookies)
+{
+       soap_client_object *client;
+
+       client = (soap_client_object*)zend_object_store_get_object(this_ptr TSRMLS_CC);
+
+       if (!client->cookies) {
+               array_init(return_value);
+       } else {
+               *return_value = *client->cookies;
+               zval_copy_ctor(return_value);
+               INIT_PZVAL(return_value);
        }
 }
 /* }}} */
@@ -3760,10 +3920,8 @@ static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, ch
                        ulong param_index = i;
 
                        param_name_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(ret), &param_name, &param_name_len, &param_index, 0, &pos);
-                       if (param_name_type == IS_UNICODE) {
-                               param_name.s = soap_unicode_to_string(param_name.u, param_name_len TSRMLS_CC);
-                               param_name_len = strlen(param_name.s);
-                       }
+                       param_name.s = soap_encode_string_ex(param_name_type, param_name, param_name_len TSRMLS_CC);
+                       param_name_len = strlen(param_name.s);
                        parameter = get_param(function, param_name.s, param_index, TRUE);
                        if (style == SOAP_RPC) {
                                param = serialize_parameter(parameter, *data, i, param_name.s, use, method TSRMLS_CC);
@@ -3777,9 +3935,7 @@ static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, ch
                                        }
                                }
                        }
-                       if (param_name_type == IS_UNICODE) {
-                               efree(param_name.v);
-                   }
+                       efree(param_name.s);
 
                        zend_hash_move_forward_ex(Z_ARRVAL_P(ret), &pos);
                        i++;
@@ -3847,12 +4003,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
                                smart_str key = {0};
 
                                if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS) {
-                                       if (Z_TYPE_PP(tmp) == IS_STRING) {
-                                               smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
-                                               smart_str_appendc(&key, ':');
-                                               hdr_ns = Z_STRVAL_PP(tmp);
-                                       } else if (Z_TYPE_PP(tmp) == IS_UNICODE) {
-                                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp) TSRMLS_CC);
+                                       if (Z_TYPE_PP(tmp) == IS_STRING || Z_TYPE_PP(tmp) == IS_UNICODE) {
+                                               char *str = soap_encode_string(*tmp, NULL TSRMLS_CC);
 
                                                smart_str_appends(&key, str);
                                                smart_str_appendc(&key, ':');
@@ -3861,11 +4013,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
                                        }
                                }
                                if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS) {
-                                       if (Z_TYPE_PP(tmp) == IS_STRING) {
-                                               smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
-                                               hdr_name = Z_STRVAL_PP(tmp);
-                                       } else if (Z_TYPE_PP(tmp) == IS_UNICODE) {
-                                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp) TSRMLS_CC);
+                                       if (Z_TYPE_PP(tmp) == IS_STRING || Z_TYPE_PP(tmp) == IS_UNICODE) {
+                                               char *str = soap_encode_string(*tmp, NULL TSRMLS_CC);
 
                                                smart_str_appends(&key, str);
                                                hdr_name = str;
@@ -4086,12 +4235,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
                                                smart_str key = {0};
 
                                                if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS) {
-                                               if (Z_TYPE_PP(tmp) == IS_STRING) {
-                                                               smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
-                                                               smart_str_appendc(&key, ':');
-                                                               hdr_ns = Z_STRVAL_PP(tmp);
-                                                       } else if (Z_TYPE_PP(tmp) == IS_UNICODE) {
-                                                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp) TSRMLS_CC);
+                                               if (Z_TYPE_PP(tmp) == IS_STRING || Z_TYPE_PP(tmp) == IS_UNICODE) {
+                                                               char *str = soap_encode_string(*tmp, NULL TSRMLS_CC);
 
                                                                smart_str_appends(&key, str);
                                                                smart_str_appendc(&key, ':');
@@ -4100,11 +4245,8 @@ static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function
                                                        }
                                                }
                                                if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS) {
-                                                       if (Z_TYPE_PP(tmp) == IS_STRING) {
-                                                               smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
-                                                               hdr_name = Z_STRVAL_PP(tmp);
-                                                       } else if (Z_TYPE_PP(tmp) == IS_UNICODE) {
-                                                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(tmp), Z_USTRLEN_PP(tmp) TSRMLS_CC);
+                                                       if (Z_TYPE_PP(tmp) == IS_STRING || Z_TYPE_PP(tmp) == IS_UNICODE) {
+                                                               char *str = soap_encode_string(*tmp, NULL TSRMLS_CC);
 
                                                                smart_str_appends(&key, str);
                                                                hdr_name = str;
@@ -4316,24 +4458,16 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
                                        smart_str key = {0};
                                        sdlSoapBindingFunctionHeaderPtr *hdr;
 
-                                       if (Z_TYPE_PP(ns) == IS_STRING) {
-                                               smart_str_appendl(&key, Z_STRVAL_PP(ns), Z_STRLEN_PP(ns));
-                                       } else {
-                                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(ns), Z_USTRLEN_PP(ns) TSRMLS_CC);
+                                       ns_str = soap_encode_string(*ns, NULL TSRMLS_CC);
+                                       smart_str_appends(&key, ns_str);
 
-                                               smart_str_appends(&key, str);
-                                               ns_str = str;
-                                       }
                                        smart_str_appendc(&key, ':');
-                                       if (Z_TYPE_PP(name) == IS_STRING) {
-                                               smart_str_appendl(&key, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
-                                       } else {
-                                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(name), Z_USTRLEN_PP(name) TSRMLS_CC);
 
-                                               smart_str_appends(&key, str);
-                                               name_str = str;
-                                       }
+                                       name_str = soap_encode_string(*name, NULL TSRMLS_CC);
+                                       
+                                       smart_str_appends(&key, name_str);
                                        smart_str_0(&key);
+
                                        if (zend_hash_find(hdrs, key.c, key.len+1,(void**)&hdr) == SUCCESS) {
                                                hdr_use = (*hdr)->use;
                                                enc = (*hdr)->encode;
@@ -4343,12 +4477,8 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
                                        }
                                        smart_str_free(&key);
                                } else {
-                                       if (Z_TYPE_PP(ns) == IS_UNICODE) {
-                                               ns_str = soap_unicode_to_string(Z_USTRVAL_PP(ns), Z_USTRLEN_PP(ns) TSRMLS_CC);
-                                       }
-                                       if (Z_TYPE_PP(name) == IS_UNICODE) {
-                                               name_str = soap_unicode_to_string(Z_USTRVAL_PP(name), Z_USTRLEN_PP(name) TSRMLS_CC);
-                                       }
+                                       ns_str = soap_encode_string(*ns, NULL TSRMLS_CC);
+                                       name_str = soap_encode_string(*name, NULL TSRMLS_CC);
                                }
 
                                if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
@@ -4378,14 +4508,8 @@ static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function
                                        }
                                }
                                if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) {
-                                       if (Z_TYPE_PP(tmp) == IS_STRING) {
-                                               if (version == SOAP_1_1) {
-                                                       xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp)));
-                                               } else {
-                                                       xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp)));
-                                               }
-                                       } else if (Z_TYPE_PP(tmp) == IS_UNICODE) {
-                                               char *str = soap_unicode_to_string(Z_USTRVAL_PP(tmp), Z_STRLEN_PP(tmp) TSRMLS_CC);
+                                       if (Z_TYPE_PP(tmp) == IS_STRING || Z_TYPE_PP(tmp) == IS_UNICODE) {
+                                               char *str = soap_encode_string(*tmp, NULL TSRMLS_CC);
 
                                                if (version == SOAP_1_1) {
                                                        xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(str));
@@ -4447,12 +4571,8 @@ static xmlNodePtr serialize_parameter(sdlParamPtr param, zval *param_val, int in
                        (Z_TYPE_PP(param_name) == IS_STRING || Z_TYPE_PP(param_name) == IS_UNICODE) &&
                    zend_hash_find(Z_OBJPROP_P(param_val), "param_data", sizeof("param_data"), (void **)&param_data) == SUCCESS) {
                        param_val = *param_data;
-                       if (Z_TYPE_PP(param_name) == IS_STRING) {
-                               name = Z_STRVAL_PP(param_name);
-                       } else {
-                               name = soap_unicode_to_string(Z_USTRVAL_PP(param_name), Z_USTRLEN_PP(param_name) TSRMLS_CC);
-                               free_name = 1;
-                       }
+                       name = soap_encode_string(*param_name, NULL TSRMLS_CC);
+                       free_name = 1;
                }
        }
 
index 5fd17df18e06d87912c87e9cde55b8c25841a823..6113a9116bd0820903f2f8290ff03c206f12ce5b 100755 (executable)
@@ -35,7 +35,50 @@ $client = new TestSoapClient(dirname(__FILE__).'/bug32941.wsdl', array("trace" =
 $ahoj = $client->echoString('exception');
 $client = new TestSoapClient(dirname(__FILE__).'/bug32941.wsdl', array("trace" => 1, 'exceptions' => 0));
 $ahoj = $client->echoString('exception');
+var_dump($ahoj->detail);
 echo "ok\n";
 ?>
 --EXPECT--
+object(stdClass)#1 (2) {
+  ["service.EchoServiceException"]=>
+  object(SoapVar)#8 (4) {
+    ["enc_type"]=>
+    int(0)
+    ["enc_value"]=>
+    object(stdClass)#7 (2) {
+      ["intParameter"]=>
+      int(105)
+      ["parameter"]=>
+      string(12) "string param"
+    }
+    ["enc_stype"]=>
+    string(20) "EchoServiceException"
+    ["enc_ns"]=>
+    string(23) "urn:service.EchoService"
+  }
+  ["hostname"]=>
+  string(9) "steckovic"
+}
+ok
+--UEXPECT--
+object(stdClass)#1 (2) {
+  [u"service.EchoServiceException"]=>
+  object(SoapVar)#8 (4) {
+    [u"enc_type"]=>
+    int(0)
+    [u"enc_value"]=>
+    object(stdClass)#7 (2) {
+      [u"intParameter"]=>
+      int(105)
+      [u"parameter"]=>
+      unicode(12) "string param"
+    }
+    [u"enc_stype"]=>
+    unicode(20) "EchoServiceException"
+    [u"enc_ns"]=>
+    unicode(23) "urn:service.EchoService"
+  }
+  [u"hostname"]=>
+  unicode(9) "steckovic"
+}
 ok
diff --git a/ext/soap/tests/cookie.phpt b/ext/soap/tests/cookie.phpt
new file mode 100755 (executable)
index 0000000..9831feb
--- /dev/null
@@ -0,0 +1,56 @@
+--TEST--
+SOAP: SoapClient::__setCookie() and SoapClient::__getCookies()
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function dump_cookies($client) {
+       $c = $client->__getCookies();
+       $client->test();
+       if (preg_match('/^Cookie:[^\n\r]*/mi', $client->__getLastRequestHeaders(), $r)) {
+               echo $r[0]."\n";
+       } else {
+               echo "Cookie:\n";
+       }
+       foreach ($c as $key => $val) {
+               if (isset($val[0])) {
+                       echo "  ".gettype($key)."(\"".$key."\") => ".gettype($val[0])."(\"".$val[0]."\")\n";
+               }
+       }
+}
+
+ini_set('default_socket_timeout', 0.1);
+$server = stream_socket_server('tcp://127.0.0.1:31337');
+$client = new SoapClient(NULL, array("location"=>"http://127.0.0.1:31337","uri"=>"test://",
+  "exceptions"=>0,"trace"=>1, "connection_timeout"=>1));
+dump_cookies($client);
+$client->__setCookie("var1","val1");
+dump_cookies($client);
+$client->__setCookie("var2","val2");
+dump_cookies($client);
+$client->__setCookie("var1");
+$client->__setCookie("var2","val3");
+dump_cookies($client);
+$client->__setCookie("var2");
+dump_cookies($client);
+?>
+--EXPECT--
+Cookie:
+Cookie: var1=val1;
+  string("var1") => string("val1")
+Cookie: var1=val1;var2=val2;
+  string("var1") => string("val1")
+  string("var2") => string("val2")
+Cookie: var2=val3;
+  string("var2") => string("val3")
+Cookie:
+--UEXPECT--
+Cookie:
+Cookie: var1=val1;
+  unicode("var1") => unicode("val1")
+Cookie: var1=val1;var2=val2;
+  unicode("var1") => unicode("val1")
+  unicode("var2") => unicode("val2")
+Cookie: var2=val3;
+  unicode("var2") => unicode("val3")
+Cookie: