ID: 39815 Updated by: [EMAIL PROTECTED] Reported By: fredrik at wangel dot net -Status: Open +Status: Assigned Bug Type: SOAP related Operating System: Irrelevant PHP Version: 6CVS-2006-12-13 (snap) -Assigned To: +Assigned To: dmitry
Previous Comments: ------------------------------------------------------------------------ [2006-12-13 13:15:06] fredrik at wangel dot net Description: ------------ [Note: This is an inherent problem within a PHP extension's C code, not with a PHP script] Problem: The SOAPClient/SOAPServer converts xsd:float values in a locale-dependent fashion, causing serious issues when the caller's locale is not English. According to "XML Schema Part 2: Datatypes", a decimal (either xsd:float or xsd:double) is always written using a period (.) as a decimal indicator [See http://www.w3.org/TR/xmlschema-2/#decimal] However, SOAPServer writes decimals using the current locale's (LC_NUMERIC) formatting rules, which is a violation of the standard. Likewise, on the client side, the function to_zval_double() in ext/soap/php_encoding.c uses atof() which parses a string according to the current locale. Since the server and client can have totally different settings for locale, the conversion fails. Hence, if the SOAP server's locale is set to "sv_SE" (Swedish) or some other language that does not use period as decimal indicator, and the SOAP client is in English, the resulting float is truncated into an integer value. Suggested fix is to either either temporarily change LC_NUMERIC [via setlocale()] into "POSIX" (or "C"), or use zend_strtod() for conversion from XML. When converting to XML [using convert_to_string()] the simplest solution should be to change LC_NUMERIC temporarily, since zend_sprintf() also uses current locale settings. PLEASE NOTE: If you do not have the locales from the example (sv_SE and en_US) on your test server, this will likely fallback into C locale, and thus the result always looks good. Verify that your test server formats 123.456 into "123,456". Try "se" or "Swedish" if "sv_SE" fails. Reproduce code: --------------- -- SERVER -- class Server {function getValue(){return (float)123.456;}} setlocale(LC_ALL,"sv_SE"); $server = new SoapServer(null,array('uri'=>'http://localhost/', 'soap_version'=>SOAP_1_2, 'encoding'=>'ISO-8859-1')); $server->setClass("Server"); $server->handle(); --- CLIENT -- $client = new SoapClient(null,array('location'=>'http://localhost/soap/Server.php', 'uri'=>'http://localhost/', 'soap_version'=>SOAP_1_2, 'encoding'=>'ISO-8859-1')); header("Content-Type: text/plain; charset=ISO-8859-1"); setlocale(LC_ALL,"sv_SE"); print((float)123.456 . "\n"); setlocale(LC_ALL,"en_US"); $value = $client->getValue(); var_dump($value); Expected result: ---------------- 123,456 float(123.456) Actual result: -------------- 123,456 float(123) ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=39815&edit=1