On 28.07.2009, at 19:14, Jani Taskinen wrote:
Dmitry Stogov wrote:David Zülke wrote:On 28.07.2009, at 13:32, Dmitry Stogov wrote:Hi David, I took only a quick look, but I like the patch.In case it doesn't break any tests, it should be committed at least into HEAD. I agree to commit it into 5.3 too, but RMs take the final decision.The only thing I didn't understood - why win32/php_stdint.h is needed.Ah, yes, that's probably an oversight. Good catch. The headers were copy-pasted from some ext/date file :)Another thing that just occured to me is that we now have a dependency on ext/date; I think I had trouble compiling ext/soap as a standaloneextension like this. Must check again. Any hints?I think ext/date can't be removed or compiled as shared extension. If it's the case, the only problem may be with unexported symbols. Just try to compile/test it as shared extension on Linux and Windows.ext/date is not an extension, it's part of core, just like ext/ standard so you shouldn't have any problems with it.
Attached (and also posted here: http://pastie.org/575559 and here: http://bugs.php.net/44383) is an update of the patch. It has the following updates: 1) all tests adjusted, reviewed and changed to work in sequence (only one of the several variants was not commented out before)
2) fixed handling of unix timestamp longsThere are the following outstanding issues (I'm going on a holiday tomorrow, so I figured I'd shoot you an update in the meantime): 1) there seem to be problems with negative timezone offsets (see tests ext/soap/tests/schema/schema0(89|91).phpt) unless I'm confused 2) at the minute, it breaks ext/soap/tests/schema/schema064.phpt. Except for one of the cases where the formatting is indeed wrong, it's due to time zones not being included. That obviously needs fixing, but I'd like to point out that the current tests do not seem to be in compliance with the XML Schema specification, which for gMonthDay, gDay and gMonth states: "An optional following time zone qualifier is allowed as for date". The rule for "date" and timezone postfixes is "For timezoned values, append the canonical representation of the ·recoverable timezone·". A recoverable timezone is an offset value in the format "[+-]hh:mm". http://www.w3.org/TR/xmlschema-2/ has all the details, but maybe I'm missing something. For gYearMonth and gYear, I think the "dateTime" timezone rules apply, which means the canonical representation must always be in UTC (and thus carry "Z" as the timezone identifier, which is what the tests currently expect, so those are correct).
Finally, when I compile as an extension, I get the following error once I reach tests that execute code relying on timelib:
dyld: lazy symbol binding failed: Symbol not found: _timelib_time_ctor Referenced from: .../extensions/no-debug-non-zts-20090626/soap.so Expected in: flat namespace dyld: Symbol not found: _timelib_time_ctor Referenced from: .../extensions/no-debug-non-zts-20090626/soap.so Expected in: flat namespaceI compiled without --enable-soap, then used the correct "phpize" in ext/soap, ran configure with the correct --with-php-config=.../blah/ php-config, make install and enabled the extension in php.ini.
Feedback/thoughts/advice appreciated. I'll be back in ~2 weeks. Cheers, - David
Index: ext/soap/soap.c =================================================================== --- ext/soap/soap.c (Revision 286909) +++ ext/soap/soap.c (Arbeitskopie) @@ -828,6 +828,7 @@ REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_WAIT_ONE_WAY_CALLS", SOAP_WAIT_ONE_WAY_CALLS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SOAP_USE_XSI_ARRAY_TYPE", SOAP_USE_XSI_ARRAY_TYPE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("SOAP_MARSHAL_DATETIME", SOAP_MARSHAL_DATETIME, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("WSDL_CACHE_NONE", WSDL_CACHE_NONE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("WSDL_CACHE_DISK", WSDL_CACHE_DISK, CONST_CS | CONST_PERSISTENT); Index: ext/soap/php_soap.h =================================================================== --- ext/soap/php_soap.h (Revision 286909) +++ ext/soap/php_soap.h (Arbeitskopie) @@ -143,6 +143,7 @@ #define SOAP_SINGLE_ELEMENT_ARRAYS (1<<0) #define SOAP_WAIT_ONE_WAY_CALLS (1<<1) #define SOAP_USE_XSI_ARRAY_TYPE (1<<2) +#define SOAP_MARSHAL_DATETIME (1<<3) #define WSDL_CACHE_NONE 0x0 #define WSDL_CACHE_DISK 0x1 Index: ext/soap/tests/schema/schema091.phpt =================================================================== --- ext/soap/tests/schema/schema091.phpt (Revision 0) +++ ext/soap/tests/schema/schema091.phpt (Revision 0) @@ -0,0 +1,36 @@ +--TEST-- +SOAP XML Schema 91: xsd:dateTime DateTime to XML conversion +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--INI-- +date.timezone=Etc/GMT-2 +--FILE-- +<?php +include "test_schema.inc"; + +test_schema("", 'type="xsd:dateTime"', new DateTime("15:35:20.12"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', new DateTime("15:35:20+06:00"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +echo "ok"; +?> +--EXPECTF-- +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">%d-%d-%dT17:35:20.12Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(19) "%d-%d-%d 17:35:20" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">%d-%d-%dT09:35:20Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#6 (3) { + ["date"]=> + string(19) "%d-%d-%d 09:35:20" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +ok \ No newline at end of file Index: ext/soap/tests/schema/schema087.phpt =================================================================== --- ext/soap/tests/schema/schema087.phpt (Revision 0) +++ ext/soap/tests/schema/schema087.phpt (Revision 0) @@ -0,0 +1,59 @@ +--TEST-- +SOAP XML Schema 87: xsd:dateTime DateTime to XML conversion +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--INI-- +date.timezone=Etc/GMT-2 +--FILE-- +<?php +include "test_schema.inc"; + +date_default_timezone_set("Europe/Berlin"); +test_schema("", 'type="xsd:dateTime"', new DateTime("2009-06-15 15:35:20.1224"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', new DateTime("2009-06-15 15:35:20.1234Z"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', new DateTime("2009-06-15 15:35:20.12+06:00"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', new DateTime("-2009-06-15 15:35:20.1234+06:00"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +echo "ok"; +?> +--EXPECT-- +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">2009-06-15T13:35:20.1224Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(19) "2009-06-15 13:35:20" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">2009-06-15T15:35:20.1234Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#6 (3) { + ["date"]=> + string(19) "2009-06-15 15:35:20" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">2009-06-15T09:35:20.12Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(19) "2009-06-15 09:35:20" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">-2009-06-15T09:35:20.1234Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#6 (3) { + ["date"]=> + string(20) "-2009-06-15 09:35:20" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +ok \ No newline at end of file Index: ext/soap/tests/schema/schema088.phpt =================================================================== --- ext/soap/tests/schema/schema088.phpt (Revision 0) +++ ext/soap/tests/schema/schema088.phpt (Revision 0) @@ -0,0 +1,36 @@ +--TEST-- +SOAP XML Schema 88: xsd:dateTime XML to DateTime conversion +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--INI-- +date.timezone=Europe/Berlin +--FILE-- +<?php +include "test_schema.inc"; + +test_schema("", 'type="xsd:dateTime"', "1956-10-18", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', "1956-10-18-07:00", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +echo "ok"; +?> +--EXPECT-- +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">1956-10-18</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#4 (3) { + ["date"]=> + string(19) "1956-10-18 00:00:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/Berlin" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">1956-10-18-07:00</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(19) "1956-10-18 00:00:00" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "-07:00" +} +ok \ No newline at end of file Index: ext/soap/tests/schema/schema089.phpt =================================================================== --- ext/soap/tests/schema/schema089.phpt (Revision 0) +++ ext/soap/tests/schema/schema089.phpt (Revision 0) @@ -0,0 +1,36 @@ +--TEST-- +SOAP XML Schema 89: xsd:dateTime DateTime to XML conversion +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--INI-- +date.timezone=Etc/GMT-2 +--FILE-- +<?php +include "test_schema.inc"; + +test_schema("", 'type="xsd:dateTime"', new DateTime("2009-06-15"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', new DateTime("2009-06-15+03:00"), "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +echo "ok"; +?> +--EXPECT-- +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">2009-06-14T21:00:00Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(19) "2009-06-15 02:00:00" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">2009-06-14T21:00:00Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#6 (3) { + ["date"]=> + string(19) "2009-06-14 21:00:00" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +ok \ No newline at end of file Index: ext/soap/tests/schema/schema090.phpt =================================================================== --- ext/soap/tests/schema/schema090.phpt (Revision 0) +++ ext/soap/tests/schema/schema090.phpt (Revision 0) @@ -0,0 +1,36 @@ +--TEST-- +SOAP XML Schema 90: xsd:dateTime XML to DateTime conversion +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--INI-- +date.timezone=Europe/Berlin +--FILE-- +<?php +include "test_schema.inc"; + +test_schema("", 'type="xsd:dateTime"', "22:20:00.1234-07:00", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', "22:20:00", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +echo "ok"; +?> +--EXPECTF-- +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">22:20:00.1234-07:00</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#4 (3) { + ["date"]=> + string(19) "%d-%d-%d 22:20:00" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "-07:00" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">22:20:00</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(19) "%d-%d-%d 22:20:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/Berlin" +} +ok \ No newline at end of file Index: ext/soap/tests/schema/schema086.phpt =================================================================== --- ext/soap/tests/schema/schema086.phpt (Revision 0) +++ ext/soap/tests/schema/schema086.phpt (Revision 0) @@ -0,0 +1,58 @@ +--TEST-- +SOAP XML Schema 86: xsd:dateTime XML to DateTime conversion +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--INI-- +date.timezone=Europe/Berlin +--FILE-- +<?php +include "test_schema.inc"; + +test_schema("", 'type="xsd:dateTime"', "1956-10-18T22:20:00.1234-07:00", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', "1956-10-18T22:20:00Z", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', "1956-10-18T22:20:00.1234", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +test_schema("", 'type="xsd:dateTime"', "-1956-10-18T22:20:00.1234-07:00", "rpc", "encoded", '', SOAP_MARSHAL_DATETIME); +echo "ok"; +?> +--EXPECT-- +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">1956-10-18T22:20:00.1234-07:00</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#4 (3) { + ["date"]=> + string(19) "1956-10-18 22:20:00" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "-07:00" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">1956-10-18T22:20:00Z</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(19) "1956-10-18 22:20:00" + ["timezone_type"]=> + int(2) + ["timezone"]=> + string(1) "Z" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">1956-10-18T22:20:00.1234</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#4 (3) { + ["date"]=> + string(19) "1956-10-18 22:20:00" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(13) "Europe/Berlin" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/" 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:test><testParam xsi:type="xsd:dateTime">-1956-10-18T22:20:00.1234-07:00</testParam></ns1:test></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(DateTime)#5 (3) { + ["date"]=> + string(20) "-1956-10-18 22:20:00" + ["timezone_type"]=> + int(1) + ["timezone"]=> + string(6) "-07:00" +} +ok Index: ext/soap/php_encoding.c =================================================================== --- ext/soap/php_encoding.c (Revision 286909) +++ ext/soap/php_encoding.c (Arbeitskopie) @@ -27,7 +27,13 @@ #include <libxml/parserInternals.h> #include "zend_strtod.h" #include "zend_interfaces.h" +#include "ext/date/lib/timelib.h" +#include "ext/date/php_date.h" +#ifdef PHP_WIN32 +# include "win32/php_stdint.h" +#endif + /* zval type decode */ static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data); static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data); @@ -39,6 +45,7 @@ static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data); static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data); static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data); +static zval *to_zval_datetime(encodeTypePtr type, xmlNodePtr data); static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); @@ -60,7 +67,7 @@ static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent); /* Datetime encode/decode */ -static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent); +static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, int style, xmlNodePtr parent, void (*format_func)(timelib_time *, smart_str *)); static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); @@ -146,9 +153,9 @@ {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double}, {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double}, - {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_datetime}, - {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_time}, - {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_date}, + {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_datetime, to_xml_datetime}, + {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_datetime, to_xml_time}, + {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_datetime, to_xml_date}, {{XSD_GYEARMONTH, XSD_GYEARMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyearmonth}, {{XSD_GYEAR, XSD_GYEAR_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyear}, {{XSD_GMONTHDAY, XSD_GMONTHDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonthday}, @@ -837,6 +844,31 @@ return ret; } +static zval *to_zval_datetime(encodeTypePtr type, xmlNodePtr data) +{ + zval *ret = to_zval_stringc(type, data); + if (SOAP_GLOBAL(features) & SOAP_MARSHAL_DATETIME) { + + zval *object; + zend_class_entry *ce = php_date_get_date_ce(); + + ALLOC_ZVAL(object); + Z_TYPE_P(object) = IS_OBJECT; + object_init_ex(object, ce); + Z_SET_REFCOUNT_P(object, 1); + Z_SET_ISREF_P(object); + + zend_call_method_with_1_params(&object, ce, &ce->constructor, "__construct", NULL, ret); + zval_ptr_dtor(&ret); + + return object; + } + else { + return ret; + } +} + + static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { xmlNodePtr ret, text; @@ -2959,15 +2991,8 @@ } /* Time encode/decode */ -static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent) +static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, int style, xmlNodePtr parent, void (*format_func)(timelib_time *, smart_str *)) { - /* logic hacked from ext/standard/datetime.c */ - struct tm *ta, tmbuf; - time_t timestamp; - int max_reallocs = 5; - size_t buf_len=64, real_len; - char *buf; - char tzbuf[8]; xmlNodePtr xmlParam; @@ -2975,48 +3000,59 @@ xmlAddChild(parent, xmlParam); FIND_ZVAL_NULL(data, xmlParam, style); - if (Z_TYPE_P(data) == IS_LONG) { - timestamp = Z_LVAL_P(data); - ta = php_localtime_r(×tamp, &tmbuf); - /*ta = php_gmtime_r(×tamp, &tmbuf);*/ - - buf = (char *) emalloc(buf_len); - while ((real_len = strftime(buf, buf_len, format, ta)) == buf_len || real_len == 0) { - buf_len *= 2; - buf = (char *) erealloc(buf, buf_len); - if (!--max_reallocs) break; - } - - /* Time zone support */ -#ifdef HAVE_TM_GMTOFF - snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 )); -#else -# if defined(__CYGWIN__) || defined(NETWARE) - snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", ((ta->tm_isdst ? _timezone - 3600:_timezone)>0)?'-':'+', abs((ta->tm_isdst ? _timezone - 3600 : _timezone) / 3600), abs(((ta->tm_isdst ? _timezone - 3600 : _timezone) % 3600) / 60)); -# else - snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", ((ta->tm_isdst ? timezone - 3600:timezone)>0)?'-':'+', abs((ta->tm_isdst ? timezone - 3600 : timezone) / 3600), abs(((ta->tm_isdst ? timezone - 3600 : timezone) % 3600) / 60)); -# endif -#endif - if (strcmp(tzbuf,"+00:00") == 0) { - strcpy(tzbuf,"Z"); - real_len++; + if (Z_TYPE_P(data) == IS_STRING) { + xmlNodeSetContentLen(xmlParam, BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data)); + } else { + timelib_time *time = timelib_time_ctor(); + if (Z_TYPE_P(data) == IS_LONG) { + timelib_set_timezone(time, get_timezone_info(TSRMLS_C)); + timelib_unixtime2local(time, (timelib_sll) Z_LVAL_P(data)); + } else if ((SOAP_GLOBAL(features) & SOAP_MARSHAL_DATETIME) && Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), php_date_get_date_ce() TSRMLS_CC)) { + /* XXX: when the developers decide to follow their advice, this should be + * updated to reference `timelib_time_clone`. All we need to do is clone + * the referent's time into our time data. */ + php_date_obj *dateobj = (php_date_obj *) zend_object_store_get_object(data TSRMLS_CC); + + *time = *dateobj->time; + if (dateobj->time->tz_abbr) { + time->tz_abbr = strdup(dateobj->time->tz_abbr); + } + if (dateobj->time->tz_info) { + time->tz_info = dateobj->time->tz_info; + } } else { - real_len += 6; + goto out; } - if (real_len >= buf_len) { - buf = (char *) erealloc(buf, real_len+1); + + if (time->tz_info) { + /* If we have timezone information, switch us to UTC. */ + timelib_apply_localtime(time, 0); } - strcat(buf, tzbuf); - 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)); + { + /* Now format it. We could use `php_format_date`, but unrolling it here + * seems to make enough sense when we want to generate a canonical + * dateTime. */ + smart_str buffer = {0}; + + /* We pass in the ptr to smart_str to the formatting function so that they + * can be chained or something. Flexible, easy, etc. */ + format_func(time, &buffer); + + /* And we can finalize it sanely here which is always good. */ + smart_str_0(&buffer); + xmlNodeSetContentLen(xmlParam, BAD_CAST(buffer.c), buffer.len); + smart_str_free(&buffer); + } + + out: + timelib_time_dtor(time); } if (style == SOAP_ENCODED) { set_ns_and_type(xmlParam, type); } + return xmlParam; } @@ -3026,45 +3062,174 @@ return to_xml_string(type, data, style, parent); } +static void to_xml_datetime_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + int time_frac; + + /* Why are these members declared as signed long longs? I don't know about + * you, but I'm not worried about there ever being more than 12 months in + * one year, and certainly no more than INT_MAX. My poor brain can't count + * that high. */ + /* seconds are appended further down */ + length = slprintf(temp, 32, "%04d-%02d-%02dT%02d:%02d:%02d", + (int) time->y, /* Year */ + (int) time->m, /* Month */ + (int) time->d, /* Day */ + (int) time->h, /* Hour */ + (int) time->i, /* Minute */ + (int) time->s /* Second */); + smart_str_appendl(buffer, temp, length); + + time_frac = (int) floor(time->f * 1000000); + if (time_frac > 0) { + while (time_frac % 10 == 0) { + time_frac /= 10; + } + + length = slprintf(temp, 32, ".%d", time_frac); + smart_str_appendl(buffer, temp, length); + } + + if (time->tz_info) { + /* Add a 'Z' to indicate that this is a "timezoned" value. */ + smart_str_appendc(buffer, 'Z'); + } +} + static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_datetime_format /* Y-m-dTH:i:s */); } +static void to_xml_time_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + int time_frac; + + length = slprintf(temp, 32, "%02d:%02d:%02d", + (int) time->h, /* Hour */ + (int) time->i, /* Minute */ + (int) time->s /* Second */); + smart_str_appendl(buffer, temp, length); + + time_frac = (int) floor(time->f * 1000000); + if (time_frac > 0) { + while (time_frac % 10 == 0) { + time_frac /= 10; + } + + length = slprintf(temp, 32, ".%d", time_frac); + smart_str_appendl(buffer, temp, length); + } + + if (time->tz_info) { + /* Add a 'Z' to indicate that this is a "timezoned" value. */ + smart_str_appendc(buffer, 'Z'); + } +} + static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - /* TODO: microsecconds */ - return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_time_format /* H:i:s(.sss) */); } +static void to_xml_date_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + + length = slprintf(temp, 32, "%04d-%02d-%02d", + (int) time->y, /* Year */ + (int) time->m, /* Month */ + (int) time->d /* Day */); + smart_str_appendl(buffer, temp, length); + + if (time->tz_info) { + /* Add a 'Z' to indicate that this is a "timezoned" value. */ + smart_str_appendc(buffer, 'Z'); + } +} + static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_date_format /* Y-m-d */); } +static void to_xml_gyearmonth_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + + length = slprintf(temp, 32, "%04d-%02d", + (int) time->y, /* Year */ + (int) time->m /* Month */); + smart_str_appendl(buffer, temp, length); +} + static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - return to_xml_datetime_ex(type, data, "%Y-%m", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_gyearmonth_format /* Y-m */); } +static void to_xml_gyear_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + + length = slprintf(temp, 32, "%04d", (int) time->y /* Year */); + smart_str_appendl(buffer, temp, length); +} + static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - return to_xml_datetime_ex(type, data, "%Y", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_gyear_format /* Y */); } +static void to_xml_gmonthday_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + + length = slprintf(temp, 32, "--%02d-%02d", + (int) time->m, /* Month */ + (int) time->d /* Day */); + smart_str_appendl(buffer, temp, length); +} + static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - return to_xml_datetime_ex(type, data, "--%m-%d", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_gmonthday_format /* --m-d */); } +static void to_xml_gday_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + + length = slprintf(temp, 32, "---%02d", (int) time->d /* Day */); + smart_str_appendl(buffer, temp, length); +} + static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - return to_xml_datetime_ex(type, data, "---%d", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_gday_format /* ---d */); } +static void to_xml_gmonth_format(timelib_time *time, smart_str *buffer) +{ + char temp[33]; + int length; + + length = slprintf(temp, 32, "--%02d", (int) time->m /* Month */); + smart_str_appendl(buffer, temp, length); +} + static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) { - return to_xml_datetime_ex(type, data, "--%m--", style, parent); + return to_xml_datetime_ex(type, data, style, parent, to_xml_gmonth_format /* --m */); } static zval* to_zval_list(encodeTypePtr enc, xmlNodePtr data) {
smime.p7s
Description: S/MIME cryptographic signature