]> granicus.if.org Git - php/commitdiff
Fixed bug #28969 (Wrong data encoding of special characters)
authorDmitry Stogov <dmitry@php.net>
Tue, 10 Aug 2004 16:30:31 +0000 (16:30 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 10 Aug 2004 16:30:31 +0000 (16:30 +0000)
NEWS
ext/soap/php_encoding.c
ext/soap/php_soap.h
ext/soap/soap.c
ext/soap/tests/server021.phpt

diff --git a/NEWS b/NEWS
index d19363a9a92884d9a1747d02a421c5a9eb104b65..9336b11919b51de37b5737a61d8377755bf57527 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -44,6 +44,7 @@ PHP                                                                        NEWS
 - Fixed bug #29109 (SoapFault exception: [WSDL] Out of memory). (Dmitry)
 - Fixed bug #29061 (soap extension segfaults). (Dmitry)
 - Fixed bug #28985 (__getTypes() returning nothing on complex WSDL). (Dmitry)
+- Fixed bug #28969 (Wrong data encoding of special characters). (Dmitry)
 - Fixed bug #28895 (ReflectionClass::isAbstract always returns false). (Marcus)
 - Fixed bug #28829 (Thread-unsafety in bcmath elementary values). (Sara)
 - Fixed bug #28464 (catch() does not catch exceptions by interfaces). (Marcus)
index 7174eb9f167bcfbc6f4a94237421c4111f457625..08e80c223f67a127ecce5050c848464dbacf2acf 100644 (file)
@@ -31,6 +31,7 @@ static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data);
+static zval *to_zval_stringb(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data);
 static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data);
 
@@ -145,8 +146,8 @@ encode defaultEncoding[] = {
        {{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonth},
        {{XSD_DURATION, XSD_DURATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_duration},
 
-       {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_stringl},
-       {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_stringl},
+       {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringb, to_xml_stringl},
+       {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringb, to_xml_stringl},
 
        {{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
        {{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
@@ -460,7 +461,23 @@ static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
        FIND_XML_NULL(data, ret);
        if (data && data->children) {
                if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
-                       ZVAL_STRING(ret, data->children->content, 1);
+                       TSRMLS_FETCH();
+
+                       if (SOAP_GLOBAL(encoding) != NULL) {
+                               xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, strlen(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, data->children->content, 1);
+                               }
+                               xmlBufferFree(out);
+                               xmlBufferFree(in);
+                       } else {
+                               ZVAL_STRING(ret, data->children->content, 1);
+                       }
                } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
                        ZVAL_STRING(ret, data->children->content, 1);
                } else {
@@ -479,8 +496,24 @@ static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
        FIND_XML_NULL(data, ret);
        if (data && data->children) {
                if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
+                       TSRMLS_FETCH();
+
                        whiteSpace_replace(data->children->content);
-                       ZVAL_STRING(ret, data->children->content, 1);
+                       if (SOAP_GLOBAL(encoding) != NULL) {
+                               xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, strlen(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, data->children->content, 1);
+                               }
+                               xmlBufferFree(out);
+                               xmlBufferFree(in);
+                       } else {
+                               ZVAL_STRING(ret, data->children->content, 1);
+                       }
                } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
                        ZVAL_STRING(ret, data->children->content, 1);
                } else {
@@ -493,6 +526,42 @@ static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
 }
 
 static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
+{
+       zval *ret;
+       MAKE_STD_ZVAL(ret);
+       FIND_XML_NULL(data, ret);
+       if (data && data->children) {
+               if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
+                       TSRMLS_FETCH();
+
+                       whiteSpace_collapse(data->children->content);
+                       if (SOAP_GLOBAL(encoding) != NULL) {
+                               xmlBufferPtr in  = xmlBufferCreateStatic(data->children->content, strlen(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, data->children->content, 1);
+                               }
+                               xmlBufferFree(out);
+                               xmlBufferFree(in);
+                       } else {
+                               ZVAL_STRING(ret, data->children->content, 1);
+                       }
+               } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
+                       ZVAL_STRING(ret, data->children->content, 1);
+               } else {
+                       soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
+               }
+       } else {
+               ZVAL_EMPTY_STRING(ret);
+       }
+       return ret;
+}
+
+static zval *to_zval_stringb(encodeTypePtr type, xmlNodePtr data)
 {
        zval *ret;
        MAKE_STD_ZVAL(ret);
@@ -534,6 +603,24 @@ static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNo
                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(xmlBufferContent(out));
+                       new_len = n;
+               } else if (!xmlCheckUTF8(str)) {
+                       soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", str);
+               }
+               xmlBufferFree(out);
+               xmlBufferFree(in);
+       } else if (!xmlCheckUTF8(str)) {
+               soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", str);
+       }
+
        xmlNodeSetContentLen(ret, str, new_len);
        efree(str);
 
index dfe1af553ea825c3bccb9dd0304c9796e1d97942..7b631f9578c708b73f9d78ad3b24383ca57b0f6d 100644 (file)
@@ -115,6 +115,7 @@ struct _soapService {
        int        type;
        char      *actor;
        char      *uri;
+       xmlCharEncodingHandlerPtr encoding;
 };
 
 #define SOAP_CLASS 1
@@ -158,6 +159,7 @@ ZEND_BEGIN_MODULE_GLOBALS(soap)
        zend_bool  cache_enabled;
        char*      cache_dir;
        long       cache_ttl;
+       xmlCharEncodingHandlerPtr encoding;
 ZEND_END_MODULE_GLOBALS(soap)
 
 #ifdef PHP_WIN32
index 604e1062a5a1528595d8b69429df117f30cfdb9b..45947e1375d7df65d8df611db9d9e0bd0eec9cf7 100644 (file)
@@ -423,6 +423,7 @@ PHP_RINIT_FUNCTION(soap)
        SOAP_GLOBAL(error_object) = NULL;
        SOAP_GLOBAL(sdl) = NULL;
        SOAP_GLOBAL(soap_version) = SOAP_1_1;
+       SOAP_GLOBAL(encoding) = NULL;
        return SUCCESS;
 }
 
@@ -835,6 +836,19 @@ PHP_METHOD(SoapServer, SoapServer)
                    Z_TYPE_PP(tmp) == IS_STRING) {
                        service->actor = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
                }
+
+               if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
+                   Z_TYPE_PP(tmp) == IS_STRING) {
+                       xmlCharEncodingHandlerPtr encoding;
+               
+                       encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
+       if (encoding == NULL) {
+                               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments. Invalid 'encoding' option - '%s'.", Z_STRVAL_PP(tmp));
+           } else {
+             service->encoding = encoding;
+           }
+               }
+
        } else if (wsdl == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments. 'uri' option is required in nonWSDL mode.");
        }
@@ -1233,6 +1247,7 @@ PHP_METHOD(SoapServer, handle)
        sdlFunctionPtr function;
        char *arg = NULL;
        int arg_len;
+       xmlCharEncodingHandlerPtr old_encoding;
 
        SOAP_SERVER_BEGIN_CODE();
 
@@ -1374,6 +1389,8 @@ PHP_METHOD(SoapServer, handle)
 
        old_sdl = SOAP_GLOBAL(sdl);
        SOAP_GLOBAL(sdl) = service->sdl;
+       old_encoding = SOAP_GLOBAL(encoding);
+       SOAP_GLOBAL(encoding) = service->encoding;
        old_soap_version = SOAP_GLOBAL(soap_version);
        function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers TSRMLS_CC);
        xmlFreeDoc(doc_request);
@@ -1636,6 +1653,7 @@ PHP_METHOD(SoapServer, handle)
 
 fail:
        SOAP_GLOBAL(soap_version) = old_soap_version;
+       SOAP_GLOBAL(encoding) = old_encoding;
        SOAP_GLOBAL(sdl) = old_sdl;
 
        /* Free soap headers */
@@ -1936,6 +1954,18 @@ PHP_METHOD(SoapClient, SoapClient)
              zend_hash_exists(EG(function_table), "gzencode", sizeof("gzencode"))) {
                        add_property_long(this_ptr, "compression", Z_LVAL_PP(tmp));
                }
+               if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
+                   Z_TYPE_PP(tmp) == IS_STRING) {
+                       xmlCharEncodingHandlerPtr encoding;
+               
+                       encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
+       if (encoding == NULL) {
+                               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'.", Z_STRVAL_PP(tmp));
+           } else {
+                   xmlCharEncCloseFunc(encoding);
+                               add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);                     
+                       }
+               }
        } else if (wsdl == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' and 'uri' options are requred in nonWSDL mode.");
                return;
@@ -2046,6 +2076,7 @@ static void do_soap_call(zval* this_ptr,
        int ret = FALSE;
        int soap_version;
        zval response;
+       xmlCharEncodingHandlerPtr old_encoding;
 
        SOAP_CLIENT_BEGIN_CODE();
 
@@ -2070,6 +2101,14 @@ static void do_soap_call(zval* this_ptr,
        SOAP_GLOBAL(soap_version) = soap_version;
        old_sdl = SOAP_GLOBAL(sdl);
        SOAP_GLOBAL(sdl) = sdl;
+       old_encoding = SOAP_GLOBAL(encoding);
+       if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_encoding", sizeof("_encoding"), (void **) &tmp) == SUCCESS &&
+           Z_TYPE_PP(tmp) == IS_STRING) {
+               SOAP_GLOBAL(encoding) = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
+       } else {
+               SOAP_GLOBAL(encoding) = NULL;
+       }
+
        if (sdl != NULL) {
                fn = get_function(sdl, function);
                if (fn != NULL) {
@@ -2166,6 +2205,10 @@ static void do_soap_call(zval* this_ptr,
                zend_throw_exception_object(exception TSRMLS_CC);
        }
 #endif
+  if (SOAP_GLOBAL(encoding) != NULL) {
+               xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
+  }
+       SOAP_GLOBAL(encoding) = old_encoding;
        SOAP_GLOBAL(sdl) = old_sdl;
        SOAP_CLIENT_END_CODE();
 }
@@ -3910,5 +3953,8 @@ static void delete_service(void *data)
        if (service->sdl) {
                delete_sdl(service->sdl);
        }
+       if (service->encoding) {
+               xmlCharEncCloseFunc(service->encoding);
+       }
        efree(service);
 }
index d557204b5f02844c961b99f79527eb8cba9a42ef..787e959fb36d6118a39444e7ff1817ac389c3617 100644 (file)
@@ -5,7 +5,7 @@ SOAP Server 21: SoapServer::setClass and __call()
 --FILE--
 <?php
 class Foo {
-  function __call($name) {
+  function __call($name, $args) {
     if ($name == "test") {
       return "Hello World";
     } else {