dmitry          Tue Dec 19 11:55:17 2006 UTC

  Modified files:              
    /php-src/main       snprintf.c snprintf.h spprintf.c 
    /php-src/ext/standard       formatted_print.c 
    /php-src/ext/soap   php_encoding.c 
    /php-src/ext/soap/tests/bugs        bug39815.phpt 
    /php-src/ext/soap/tests/interop/Round3/GroupD       
                                                        
r3_groupD_compound2_001w.phpt 
  Log:
  Fixed bug #39815 (SOAP double encoding is not locale-independent)
  
  
http://cvs.php.net/viewvc.cgi/php-src/main/snprintf.c?r1=1.44&r2=1.45&diff_format=u
Index: php-src/main/snprintf.c
diff -u php-src/main/snprintf.c:1.44 php-src/main/snprintf.c:1.45
--- php-src/main/snprintf.c:1.44        Mon Dec 18 09:25:32 2006
+++ php-src/main/snprintf.c     Tue Dec 19 11:55:16 2006
@@ -16,7 +16,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: snprintf.c,v 1.44 2006/12/18 09:25:32 bjori Exp $ */
+/* $Id: snprintf.c,v 1.45 2006/12/19 11:55:16 dmitry Exp $ */
 
 
 #include "php.h"
@@ -115,23 +115,20 @@
        return(s);
 }
 
-char *bsd_ecvt(double value, int ndigit, int *decpt, int *sign)
+static inline char *php_ecvt(double value, int ndigit, int *decpt, int *sign)
 {
        return(__cvt(value, ndigit, decpt, sign, 0, 1));
 }
 
-char *bsd_fcvt(double value, int ndigit, int *decpt, int *sign)
+static inline char *php_fcvt(double value, int ndigit, int *decpt, int *sign)
 {
     return(__cvt(value, ndigit, decpt, sign, 1, 1));
 }
 
-char *bsd_gcvt(double value, int ndigit, char *buf)
+PHPAPI char *php_gcvt(double value, int ndigit, char dec_point, char exponent, 
char *buf)
 {
        char *digits, *dst, *src;
        int i, decpt, sign;
-       struct lconv *lconv;
-
-       lconv = localeconv();
 
        digits = zend_dtoa(value, 2, ndigit, &decpt, &sign, NULL);
        if (decpt == 9999) {
@@ -161,7 +158,7 @@
                        sign = 0;
                src = digits;
                *dst++ = *src++;
-               *dst++ = *lconv->decimal_point;
+               *dst++ = dec_point;
                if (*src == '\0') {
                        *dst++ = '0';
                } else {
@@ -169,7 +166,7 @@
                                *dst++ = *src++;
                        } while (*src != '\0');
                }
-               *dst++ = 'e';
+               *dst++ = exponent;
                if (sign)
                        *dst++ = '-';
                else
@@ -190,7 +187,7 @@
        } else if (decpt < 0) {
                /* standard format 0. */
                *dst++ = '0';   /* zero before decimal point */
-               *dst++ = *lconv->decimal_point;
+               *dst++ = dec_point;
                do {
                        *dst++ = '0';
                } while (++decpt < 0);
@@ -210,7 +207,7 @@
                if (*src != '\0') {
                        if (src == digits)
                                *dst++ = '0';   /* zero before decimal point */
-                       *dst++ = *lconv->decimal_point;
+                       *dst++ = dec_point;
                        for (i = decpt; digits[i] != '\0'; i++) {
                 *dst++ = digits[i];
             }
@@ -357,29 +354,21 @@
  * The sign is returned in the is_negative argument (and is not placed
  * in buf).
  */
-char * ap_php_conv_fp(register char format, register double num,
-                boolean_e add_dp, int precision, bool_int * is_negative, char 
*buf, int *len)
+PHPAPI char * php_conv_fp(register char format, register double num,
+                boolean_e add_dp, int precision, char dec_point, bool_int * 
is_negative, char *buf, int *len)
 {
        register char *s = buf;
        register char *p, *p_orig;
        int decimal_point;
-       char dec_point = '.';
-
-       if (format == 'f') {
-               struct lconv *lconv;
-               lconv = localeconv();
-               dec_point = *lconv->decimal_point;
-               format = 'F';
-       }
 
        if (precision >= NDIG - 1) {
                precision = NDIG - 2;
        }
 
        if (format == 'F')
-               p_orig = p = bsd_fcvt(num, precision, &decimal_point, 
is_negative);
+               p_orig = p = php_fcvt(num, precision, &decimal_point, 
is_negative);
        else                                            /* either e or E format 
*/
-               p_orig = p = bsd_ecvt(num, precision + 1, &decimal_point, 
is_negative);
+               p_orig = p = php_ecvt(num, precision + 1, &decimal_point, 
is_negative);
 
        /*
         * Check for Infinity and NaN
@@ -595,6 +584,8 @@
        char num_buf[NUM_BUF_SIZE];
        char char_buf[2];                       /* for printing %% and 
%<unknown> */
 
+       struct lconv *lconv = NULL;
+
        /*
         * Flag variables
         */
@@ -929,6 +920,7 @@
 
                                
                                case 'f':
+                               case 'F':
                                case 'e':
                                case 'E':
                                        switch(modifier) {
@@ -949,8 +941,12 @@
                                                s = "inf";
                                                s_len = 3;
                                        } else {
-                                               s = ap_php_conv_fp(*fmt, 
fp_num, alternate_form,
+                                               if (!lconv) {
+                                                       lconv = localeconv();
+                                               }
+                                               s = php_conv_fp((*fmt == 
'f')?'F':*fmt, fp_num, alternate_form,
                                                 (adjust_precision == NO) ? 
FLOAT_DIGITS : precision,
+                                                (*fmt == 
'f')?(*lconv->decimal_point):'.',
                                                                        
&is_negative, &num_buf[1], &s_len);
                                                if (is_negative)
                                                        prefix_char = '-';
@@ -997,7 +993,10 @@
                                        /*
                                         * * We use &num_buf[ 1 ], so that we 
have room for the sign
                                         */
-                                       s = bsd_gcvt(fp_num, precision, 
&num_buf[1]);
+                                       if (!lconv) {
+                                               lconv = localeconv();
+                                       }
+                                       s = php_gcvt(fp_num, precision, 
*lconv->decimal_point, (*fmt == 'G')?'E':'e', &num_buf[1]);
                                        if (*s == '-')
                                                prefix_char = *s++;
                                        else if (print_sign)
@@ -1009,8 +1008,6 @@
 
                                        if (alternate_form && (q = strchr(s, 
'.')) == NULL)
                                                s[s_len++] = '.';
-                                       if (*fmt == 'G' && (q = strchr(s, 'e')) 
!= NULL)
-                                               *q = 'E';
                                        break;
 
 
http://cvs.php.net/viewvc.cgi/php-src/main/snprintf.h?r1=1.36&r2=1.37&diff_format=u
Index: php-src/main/snprintf.h
diff -u php-src/main/snprintf.h:1.36 php-src/main/snprintf.h:1.37
--- php-src/main/snprintf.h:1.36        Wed Dec  6 09:50:28 2006
+++ php-src/main/snprintf.h     Tue Dec 19 11:55:16 2006
@@ -17,7 +17,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: snprintf.h,v 1.36 2006/12/06 09:50:28 tony2001 Exp $ */
+/* $Id: snprintf.h,v 1.37 2006/12/19 11:55:16 dmitry Exp $ */
 
 /*
 
@@ -65,10 +65,19 @@
 #ifndef SNPRINTF_H
 #define SNPRINTF_H
 
+typedef int bool_int;
+
+typedef enum {
+       NO = 0, YES = 1
+} boolean_e;
+
 BEGIN_EXTERN_C()
 PHPAPI int ap_php_snprintf(char *, size_t, const char *, ...) 
PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
 PHPAPI int ap_php_vsnprintf(char *, size_t, const char *, va_list ap) 
PHP_ATTRIBUTE_FORMAT(printf, 3, 0);
 PHPAPI int php_sprintf (char* s, const char* format, ...) 
PHP_ATTRIBUTE_FORMAT(printf, 2, 3);
+PHPAPI char * php_gcvt(double value, int ndigit, char dec_point, char 
exponent, char *buf);
+PHPAPI char * php_conv_fp(register char format, register double num,
+                boolean_e add_dp, int precision, char dec_point, bool_int * 
is_negative, char *buf, int *len);
 END_EXTERN_C()
 
 #ifdef snprintf
@@ -87,10 +96,6 @@
 #define sprintf php_sprintf
 
 typedef enum {
-       NO = 0, YES = 1
-} boolean_e;
-
-typedef enum {
        LM_STD = 0,
 #if SIZEOF_INTMAX_T
        LM_INTMAX_T,
@@ -118,21 +123,12 @@
 typedef WIDE_INT wide_int;
 typedef unsigned WIDE_INT u_wide_int;
 
-typedef int bool_int;
-
 extern char * ap_php_conv_10(register wide_int num, register bool_int 
is_unsigned,
           register bool_int * is_negative, char *buf_end, register int *len);
 
-extern char * ap_php_conv_fp(register char format, register double num,
-                boolean_e add_dp, int precision, bool_int * is_negative, char 
*buf, int *len);
-
 extern char * ap_php_conv_p2(register u_wide_int num, register int nbits,
                 char format, char *buf_end, register int *len);
 
-extern char * bsd_ecvt(double value, int ndigit, int *decpt, int *sign);
-extern char * bsd_fcvt(double value, int ndigit, int *decpt, int *sign);
-extern char * bsd_gcvt(double value, int ndigit, char *buf);
-
 #endif /* SNPRINTF_H */
 
 /*
http://cvs.php.net/viewvc.cgi/php-src/main/spprintf.c?r1=1.38&r2=1.39&diff_format=u
Index: php-src/main/spprintf.c
diff -u php-src/main/spprintf.c:1.38 php-src/main/spprintf.c:1.39
--- php-src/main/spprintf.c:1.38        Wed Dec  6 09:50:28 2006
+++ php-src/main/spprintf.c     Tue Dec 19 11:55:16 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
 */
 
-/* $Id: spprintf.c,v 1.38 2006/12/06 09:50:28 tony2001 Exp $ */
+/* $Id: spprintf.c,v 1.39 2006/12/19 11:55:16 dmitry Exp $ */
 
 /* This is the spprintf implementation.
  * It has emerged from apache snprintf. See original header:
@@ -91,6 +91,10 @@
 #include <inttypes.h>
 #endif
 
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
 #include "snprintf.h"
 
 #define FALSE           0
@@ -226,6 +230,8 @@
        char char_buf[2];                       /* for printing %% and 
%<unknown> */
        zend_bool free_s; /* free string if allocated here */
 
+       struct lconv *lconv = NULL;
+
        /*
         * Flag variables
         */
@@ -617,6 +623,7 @@
                                        break;
 
                                case 'f':
+                               case 'F':
                                case 'e':
                                case 'E':
                                        switch(modifier) {
@@ -637,8 +644,12 @@
                                                s = "inf";
                                                s_len = 3;
                                        } else {
-                                               s = ap_php_conv_fp(*fmt, 
fp_num, alternate_form,
-                                                                       
(adjust_precision == NO) ? FLOAT_DIGITS : precision,
+                                               if (!lconv) {
+                                                       lconv = localeconv();
+                                               }
+                                               s = php_conv_fp((*fmt == 
'f')?'F':*fmt, fp_num, alternate_form,
+                                                (adjust_precision == NO) ? 
FLOAT_DIGITS : precision,
+                                                (*fmt == 
'f')?(*lconv->decimal_point):'.',
                                                                        
&is_negative, &num_buf[1], &s_len);
                                                if (is_negative)
                                                        prefix_char = '-';
@@ -685,7 +696,10 @@
                                        /*
                                         * * We use &num_buf[ 1 ], so that we 
have room for the sign
                                         */
-                                       s = bsd_gcvt(fp_num, precision, 
&num_buf[1]);
+                                       if (!lconv) {
+                                               lconv = localeconv();
+                                       }
+                                       s = php_gcvt(fp_num, precision, 
*lconv->decimal_point, (*fmt == 'G')?'E':'e', &num_buf[1]);
                                        if (*s == '-')
                                                prefix_char = *s++;
                                        else if (print_sign)
@@ -697,8 +711,6 @@
 
                                        if (alternate_form && (q = strchr(s, 
'.')) == NULL)
                                                s[s_len++] = '.';
-                                       if (*fmt == 'G' && (q = strchr(s, 'e')) 
!= NULL)
-                                               *q = 'E';
                                        break;
 
 
http://cvs.php.net/viewvc.cgi/php-src/ext/standard/formatted_print.c?r1=1.89&r2=1.90&diff_format=u
Index: php-src/ext/standard/formatted_print.c
diff -u php-src/ext/standard/formatted_print.c:1.89 
php-src/ext/standard/formatted_print.c:1.90
--- php-src/ext/standard/formatted_print.c:1.89 Mon Dec 18 09:25:32 2006
+++ php-src/ext/standard/formatted_print.c      Tue Dec 19 11:55:16 2006
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: formatted_print.c,v 1.89 2006/12/18 09:25:32 bjori Exp $ */
+/* $Id: formatted_print.c,v 1.90 2006/12/19 11:55:16 dmitry Exp $ */
 
 #include <math.h>                              /* modf() */
 #include "php.h"
@@ -196,8 +196,9 @@
                                                 TSRMLS_DC)
 {
        char num_buf[NUM_BUF_SIZE];
-       char *s = NULL, *q;
+       char *s = NULL;
        int s_len = 0, is_negative = 0;
+       struct lconv *lconv;
 
        PRINTF_DEBUG(("sprintf: appenddouble(%x, %x, %x, %f, %d, '%c', %d, 
%c)\n",
                                  *buffer, pos, size, number, width, padding, 
alignment, fmt));
@@ -229,7 +230,9 @@
                case 'E':
                case 'f':
                case 'F':
-                       s = ap_php_conv_fp(fmt, number, 0, precision,
+                       lconv = localeconv();
+                       s = php_conv_fp((fmt == 'f')?'F':fmt, number, 0, 
precision,
+                                               (fmt == 
'f')?(*lconv->decimal_point):'.',
                                                &is_negative, &num_buf[1], 
&s_len);
                        if (is_negative) {
                                num_buf[0] = '-';
@@ -249,7 +252,8 @@
                        /*
                         * * We use &num_buf[ 1 ], so that we have room for the 
sign
                         */
-                       s = bsd_gcvt(number, precision, &num_buf[1]);
+                       lconv = localeconv();
+                       s = php_gcvt(number, precision, *lconv->decimal_point, 
(fmt == 'G')?'E':'e', &num_buf[1]);
                        is_negative = 0;
                        if (*s == '-') {
                                is_negative = 1;
@@ -260,10 +264,6 @@
                        }
 
                        s_len = strlen(s);
-
-                       if (fmt == 'G' && (q = strchr(s, 'e')) != NULL) {
-                               *q = 'E';
-                       }
                        break;
        }
 
http://cvs.php.net/viewvc.cgi/php-src/ext/soap/php_encoding.c?r1=1.148&r2=1.149&diff_format=u
Index: php-src/ext/soap/php_encoding.c
diff -u php-src/ext/soap/php_encoding.c:1.148 
php-src/ext/soap/php_encoding.c:1.149
--- php-src/ext/soap/php_encoding.c:1.148       Mon Dec 18 14:39:39 2006
+++ php-src/ext/soap/php_encoding.c     Tue Dec 19 11:55:16 2006
@@ -17,7 +17,7 @@
   |          Dmitry Stogov <[EMAIL PROTECTED]>                             |
   +----------------------------------------------------------------------+
 */
-/* $Id: php_encoding.c,v 1.148 2006/12/18 14:39:39 dmitry Exp $ */
+/* $Id: php_encoding.c,v 1.149 2006/12/19 11:55:16 dmitry Exp $ */
 
 #include <time.h>
 
@@ -928,19 +928,23 @@
 {
        xmlNodePtr ret;
        zval tmp;
+       char *str;
+       TSRMLS_FETCH();
 
        ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
        xmlAddChild(parent, ret);
        FIND_ZVAL_NULL(data, ret, style);
 
        tmp = *data;
-       zval_copy_ctor(&tmp);
        if (Z_TYPE(tmp) != IS_DOUBLE) {
+               zval_copy_ctor(&tmp);
                convert_to_double(&tmp);
        }
-       convert_to_string(&tmp);
-       xmlNodeSetContentLen(ret, BAD_CAST(Z_STRVAL(tmp)), Z_STRLEN(tmp));
-       zval_dtor(&tmp);
+       
+       str = (char *) emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
+       php_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
+       xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str));
+       efree(str);
 
        if (style == SOAP_ENCODED) {
                set_ns_and_type(ret, type);
http://cvs.php.net/viewvc.cgi/php-src/ext/soap/tests/bugs/bug39815.phpt?r1=1.1&r2=1.2&diff_format=u
Index: php-src/ext/soap/tests/bugs/bug39815.phpt
diff -u /dev/null php-src/ext/soap/tests/bugs/bug39815.phpt:1.2
--- /dev/null   Tue Dec 19 11:55:17 2006
+++ php-src/ext/soap/tests/bugs/bug39815.phpt   Tue Dec 19 11:55:16 2006
@@ -0,0 +1,42 @@
+--TEST--
+Bug #39815 (to_zval_double() in ext/soap/php_encoding.c is not 
locale-independent)
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function test(){
+  return 123.456;
+}
+class LocalSoapClient extends SoapClient {
+
+  function __construct($wsdl, $options) {
+    parent::__construct($wsdl, $options);
+    $this->server = new SoapServer($wsdl, $options);
+    $this->server->addFunction('test');
+  }
+
+  function __doRequest($request, $location, $action, $version) {
+    ob_start();
+    $this->server->handle($request);
+    $response = ob_get_contents();
+    ob_end_clean();
+    return $response;
+  }
+
+}
+$x = new LocalSoapClient(NULL,array('location'=>'test://', 
+                                   'uri'=>'http://testuri.org',
+                                   "trace"=>1)); 
[EMAIL PROTECTED](LC_ALL,"sv_SE");
+var_dump($x->test());
+echo $x->__getLastResponse();
[EMAIL PROTECTED](LC_ALL,"en_US");
+var_dump($x->test());
+echo $x->__getLastResponse();
+--EXPECT--
+float(123,456)
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://testuri.org"; xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"; 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";><SOAP-ENV:Body><ns1:testResponse><return
 
xsi:type="xsd:float">123.456</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
+float(123.456)
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://testuri.org"; xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"; 
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/";><SOAP-ENV:Body><ns1:testResponse><return
 
xsi:type="xsd:float">123.456</return></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>
http://cvs.php.net/viewvc.cgi/php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt?r1=1.2&r2=1.3&diff_format=u
Index: 
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt
diff -u 
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt:1.2 
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt:1.3
--- 
php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt:1.2  
    Wed Aug 24 11:46:26 2005
+++ php-src/ext/soap/tests/interop/Round3/GroupD/r3_groupD_compound2_001w.phpt  
Tue Dec 19 11:55:16 2006
@@ -31,7 +31,7 @@
 ?>
 --EXPECT--
 <?xml version="1.0" encoding="UTF-8"?>
-<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://soapinterop.org/person"; 
xmlns:ns2="http://soapinterop.org/employee";><SOAP-ENV:Body><ns2:x_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1000000</ns2:salary><ns2:ID>12345</ns2:ID></ns2:x_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://soapinterop.org/person"; 
xmlns:ns2="http://soapinterop.org/employee";><SOAP-ENV:Body><ns2:x_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1.0E+6</ns2:salary><ns2:ID>12345</ns2:ID></ns2:x_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
 <?xml version="1.0" encoding="UTF-8"?>
-<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://soapinterop.org/person"; 
xmlns:ns2="http://soapinterop.org/employee";><SOAP-ENV:Body><ns2:result_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1000000</ns2:salary><ns2:ID>12345</ns2:ID></ns2:result_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"; 
xmlns:ns1="http://soapinterop.org/person"; 
xmlns:ns2="http://soapinterop.org/employee";><SOAP-ENV:Body><ns2:result_Employee><ns2:person><ns1:Name>Shane</ns1:Name><ns1:Male>true</ns1:Male></ns2:person><ns2:salary>1.0E+6</ns2:salary><ns2:ID>12345</ns2:ID></ns2:result_Employee></SOAP-ENV:Body></SOAP-ENV:Envelope>
 ok

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to