dmitry Tue Mar 22 05:19:09 2005 EDT Modified files: /php-src/ext/soap php_encoding.c php_encoding.h php_packet_soap.c php_schema.c php_sdl.h soap.c /php-src/ext/soap/tests/bugs bug30106.phpt bug30106.wsdl Log: Fixed bug #30106 (SOAP cannot not parse 'ref' element. Causes Uncaught SoapFault exception)
http://cvs.php.net/diff.php/php-src/ext/soap/php_encoding.c?r1=1.86&r2=1.87&ty=u Index: php-src/ext/soap/php_encoding.c diff -u php-src/ext/soap/php_encoding.c:1.86 php-src/ext/soap/php_encoding.c:1.87 --- php-src/ext/soap/php_encoding.c:1.86 Sat Mar 5 08:27:13 2005 +++ php-src/ext/soap/php_encoding.c Tue Mar 22 05:19:07 2005 @@ -17,7 +17,7 @@ | Dmitry Stogov <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ -/* $Id: php_encoding.c,v 1.86 2005/03/05 13:27:13 dmitry Exp $ */ +/* $Id: php_encoding.c,v 1.87 2005/03/22 10:19:07 dmitry Exp $ */ #include <time.h> @@ -72,6 +72,9 @@ static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); +static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data); +static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); + /* Try and guess for non-wsdl clients and servers */ static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data); static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent); @@ -81,8 +84,6 @@ static xmlNodePtr check_and_resolve_href(xmlNodePtr data); -static encodePtr get_conversion(int encode); - static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret); static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type); @@ -201,6 +202,8 @@ {{XSD_BYTE, XSD_BYTE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long}, {{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string}, + {{XSD_ANYXML, "<anyXML>", "<anyXML>", NULL}, to_zval_any, to_xml_any}, + {{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert} }; @@ -963,17 +966,58 @@ } } break; - case XSD_CONTENT_SEQUENCE: case XSD_CONTENT_ALL: + case XSD_CONTENT_SEQUENCE: case XSD_CONTENT_CHOICE: { sdlContentModelPtr *tmp; HashPosition pos; + sdlContentModelPtr any = NULL; zend_hash_internal_pointer_reset_ex(model->u.content, &pos); while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) { - model_to_zval_object(ret, *tmp, data, sdl TSRMLS_CC); + if ((*tmp)->kind == XSD_CONTENT_ANY) { + any = *tmp; + } else { + model_to_zval_object(ret, *tmp, data, sdl TSRMLS_CC); + } zend_hash_move_forward_ex(model->u.content, &pos); } + if (any) { + xmlNodePtr node = data->children; + zval* any = NULL; + + while (node != NULL) { + if (get_zval_property(ret, (char*)node->name TSRMLS_CC) == NULL) { + zval* val = master_to_zval(get_conversion(XSD_ANYXML), node); + while (node->next != NULL && + get_zval_property(ret, (char*)node->next->name TSRMLS_CC) == NULL) { + zval* val2 = master_to_zval(get_conversion(XSD_ANYXML), node->next); + add_string_to_string(val, val, val2); + zval_ptr_dtor(&val2); + node = node->next; + } + if (any == NULL) { + any = val; + } else { + if (Z_TYPE_P(any) != IS_ARRAY) { + /* Convert into array */ + zval *arr; + + MAKE_STD_ZVAL(arr); + array_init(arr); + add_next_index_zval(arr, any); + any = arr; + } + /* Add array element */ + add_next_index_zval(any, val); + } + } + node = node->next; + } + if (any) { + set_zval_property(ret, "any", any TSRMLS_CC); + } + } break; } case XSD_CONTENT_GROUP: @@ -1205,6 +1249,37 @@ } break; } + case XSD_CONTENT_ANY: { + zval *data; + xmlNodePtr property; + encodePtr enc; + + data = get_zval_property(object, "any" TSRMLS_CC); + if (data) { + enc = get_conversion(XSD_ANYXML); + if ((model->max_occurs == -1 || model->max_occurs > 1) && Z_TYPE_P(data) == IS_ARRAY) { + HashTable *ht = Z_ARRVAL_P(data); + zval **val; + + zend_hash_internal_pointer_reset(ht); + while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) { + property = master_to_xml(enc, *val, style, node); + zend_hash_move_forward(ht); + } + } else { + property = master_to_xml(enc, data, style, node); + } + return 1; + } else if (model->min_occurs == 0) { + return 2; + } else { + if (strict) { + soap_error0(E_ERROR, "Encoding: object hasn't 'any' property"); + } + return 0; + } + break; + } case XSD_CONTENT_SEQUENCE: case XSD_CONTENT_ALL: { sdlContentModelPtr *tmp; @@ -2492,6 +2567,41 @@ return to_xml_list(enc,data,style, parent); } +static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data) +{ + xmlBufferPtr buf; + zval *ret; + + buf = xmlBufferCreate(); + xmlNodeDump(buf, NULL, data, 0, 0); + MAKE_STD_ZVAL(ret); + ZVAL_STRING(ret, (char*)xmlBufferContent(buf), 1); + xmlBufferFree(buf); + return ret; +} + +extern const xmlChar xmlStringTextNoenc[]; + +static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent) +{ + xmlNodePtr ret; + + if (Z_TYPE_P(data) == IS_STRING) { + ret = xmlNewTextLen(Z_STRVAL_P(data), Z_STRLEN_P(data)); + } else { + zval tmp = *data; + + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + ret = xmlNewTextLen(Z_STRVAL_P(data), Z_STRLEN_P(data)); + zval_dtor(&tmp); + } + ret->name = xmlStringTextNoenc; + xmlAddChild(parent, ret); + + return ret; +} + zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data) { sdlTypePtr type; @@ -2723,7 +2833,7 @@ SOAP_GLOBAL(cur_uniq_ns) = 0; } -static encodePtr get_conversion(int encode) +encodePtr get_conversion(int encode) { encodePtr *enc = NULL; TSRMLS_FETCH(); http://cvs.php.net/diff.php/php-src/ext/soap/php_encoding.h?r1=1.36&r2=1.37&ty=u Index: php-src/ext/soap/php_encoding.h diff -u php-src/ext/soap/php_encoding.h:1.36 php-src/ext/soap/php_encoding.h:1.37 --- php-src/ext/soap/php_encoding.h:1.36 Thu Aug 26 14:40:10 2004 +++ php-src/ext/soap/php_encoding.h Tue Mar 22 05:19:07 2005 @@ -17,7 +17,7 @@ | Dmitry Stogov <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ -/* $Id: php_encoding.h,v 1.36 2004/08/26 18:40:10 dmitry Exp $ */ +/* $Id: php_encoding.h,v 1.37 2005/03/22 10:19:07 dmitry Exp $ */ #ifndef PHP_ENCODING_H #define PHP_ENCODING_H @@ -139,6 +139,8 @@ #define XSD_UR_TYPE 146 #define XSD_UR_TYPE_STRING "ur-type" +#define XSD_ANYXML 147 + #define APACHE_NAMESPACE "http://xml.apache.org/xml-soap" #define APACHE_MAP 200 #define APACHE_MAP_STRING "Map" @@ -214,6 +216,8 @@ void encode_reset_ns(); xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns); +encodePtr get_conversion(int encode); + void delete_encoder(void *handle); extern encode defaultEncoding[]; http://cvs.php.net/diff.php/php-src/ext/soap/php_packet_soap.c?r1=1.39&r2=1.40&ty=u Index: php-src/ext/soap/php_packet_soap.c diff -u php-src/ext/soap/php_packet_soap.c:1.39 php-src/ext/soap/php_packet_soap.c:1.40 --- php-src/ext/soap/php_packet_soap.c:1.39 Tue Oct 5 12:00:40 2004 +++ php-src/ext/soap/php_packet_soap.c Tue Mar 22 05:19:07 2005 @@ -17,7 +17,7 @@ | Dmitry Stogov <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ -/* $Id: php_packet_soap.c,v 1.39 2004/10/05 16:00:40 dmitry Exp $ */ +/* $Id: php_packet_soap.c,v 1.40 2005/03/22 10:19:07 dmitry Exp $ */ #include "php_soap.h" @@ -222,6 +222,11 @@ } } add_soap_fault(this_ptr, faultcode, faultstring, faultactor, details TSRMLS_CC); +#ifdef ZEND_ENGINE_2 + if (details) { + details->refcount--; + } +#endif xmlFreeDoc(response); return FALSE; } http://cvs.php.net/diff.php/php-src/ext/soap/php_schema.c?r1=1.52&r2=1.53&ty=u Index: php-src/ext/soap/php_schema.c diff -u php-src/ext/soap/php_schema.c:1.52 php-src/ext/soap/php_schema.c:1.53 --- php-src/ext/soap/php_schema.c:1.52 Fri Mar 18 10:40:04 2005 +++ php-src/ext/soap/php_schema.c Tue Mar 22 05:19:07 2005 @@ -17,7 +17,7 @@ | Dmitry Stogov <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ -/* $Id: php_schema.c,v 1.52 2005/03/18 15:40:04 gschlossnagle Exp $ */ +/* $Id: php_schema.c,v 1.53 2005/03/22 10:19:07 dmitry Exp $ */ #include "php_soap.h" #include "libxml/uri.h" @@ -1301,9 +1301,44 @@ return TRUE; } -static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr extType, sdlTypePtr cur_type, sdlContentModelPtr model) +/* +<any + id = ID + maxOccurs = (nonNegativeInteger | unbounded) : 1 + minOccurs = nonNegativeInteger : 1 + namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) : ##any + processContents = (lax | skip | strict) : strict + {any attributes with non-schema namespace . . .}> + Content: (annotation?) +</any> +*/ +static int schema_any(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr anyType, sdlTypePtr cur_type, sdlContentModelPtr model) { - /* TODO: <any> support */ + if (model != NULL) { + sdlContentModelPtr newModel; + xmlAttrPtr attr; + + newModel = emalloc(sizeof(sdlContentModel)); + newModel->kind = XSD_CONTENT_ANY; + newModel->min_occurs = 1; + newModel->max_occurs = 1; + + attr = get_attribute(anyType->properties, "minOccurs"); + if (attr) { + newModel->min_occurs = atoi(attr->children->content); + } + + attr = get_attribute(anyType->properties, "maxOccurs"); + if (attr) { + if (!strncmp(attr->children->content, "unbounded", sizeof("unbounded"))) { + newModel->max_occurs = -1; + } else { + newModel->max_occurs = atoi(attr->children->content); + } + } + + zend_hash_next_index_insert(model->u.content, &newModel, sizeof(sdlContentModelPtr), NULL); + } return TRUE; } @@ -2156,6 +2191,8 @@ if ((*tmp)->def) { type->def = estrdup((*tmp)->def); } + } else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) { + type->encode = get_conversion(XSD_ANYXML); } else { soap_error0(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute"); } @@ -2257,6 +2294,8 @@ case XSD_CONTENT_GROUP_REF: efree(tmp->u.group_ref); break; + default: + break; } efree(tmp); } http://cvs.php.net/diff.php/php-src/ext/soap/php_sdl.h?r1=1.34&r2=1.35&ty=u Index: php-src/ext/soap/php_sdl.h diff -u php-src/ext/soap/php_sdl.h:1.34 php-src/ext/soap/php_sdl.h:1.35 --- php-src/ext/soap/php_sdl.h:1.34 Mon Mar 21 10:52:50 2005 +++ php-src/ext/soap/php_sdl.h Tue Mar 22 05:19:08 2005 @@ -17,7 +17,7 @@ | Dmitry Stogov <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ -/* $Id: php_sdl.h,v 1.34 2005/03/21 15:52:50 dmitry Exp $ */ +/* $Id: php_sdl.h,v 1.35 2005/03/22 10:19:08 dmitry Exp $ */ #ifndef PHP_SDL_H #define PHP_SDL_H @@ -152,7 +152,8 @@ XSD_CONTENT_ALL, XSD_CONTENT_CHOICE, XSD_CONTENT_GROUP_REF, - XSD_CONTENT_GROUP + XSD_CONTENT_GROUP, + XSD_CONTENT_ANY } sdlContentKind; http://cvs.php.net/diff.php/php-src/ext/soap/soap.c?r1=1.138&r2=1.139&ty=u Index: php-src/ext/soap/soap.c diff -u php-src/ext/soap/soap.c:1.138 php-src/ext/soap/soap.c:1.139 --- php-src/ext/soap/soap.c:1.138 Sun Mar 20 04:55:47 2005 +++ php-src/ext/soap/soap.c Tue Mar 22 05:19:08 2005 @@ -17,7 +17,7 @@ | Dmitry Stogov <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ */ -/* $Id: soap.c,v 1.138 2005/03/20 09:55:47 dmitry Exp $ */ +/* $Id: soap.c,v 1.139 2005/03/22 10:19:08 dmitry Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -3946,11 +3946,19 @@ static void model_to_string(sdlContentModelPtr model, smart_str *buf, int level) { + int i; + switch (model->kind) { case XSD_CONTENT_ELEMENT: type_to_string(model->u.element, buf, level); smart_str_appendl(buf, ";\n", 2); break; + case XSD_CONTENT_ANY: + for (i = 0;i < level;i++) { + smart_str_appendc(buf, ' '); + } + smart_str_appendl(buf, "<anyXML> any;\n", sizeof("<anyXML> any;\n")-1); + break; case XSD_CONTENT_SEQUENCE: case XSD_CONTENT_ALL: case XSD_CONTENT_CHOICE: { http://cvs.php.net/diff.php/php-src/ext/soap/tests/bugs/bug30106.phpt?r1=1.1&r2=1.2&ty=u Index: php-src/ext/soap/tests/bugs/bug30106.phpt diff -u /dev/null php-src/ext/soap/tests/bugs/bug30106.phpt:1.2 --- /dev/null Tue Mar 22 05:19:09 2005 +++ php-src/ext/soap/tests/bugs/bug30106.phpt Tue Mar 22 05:19:08 2005 @@ -0,0 +1,72 @@ +--TEST-- +Bug #30106 SOAP cannot not parse 'ref' element. Causes Uncaught SoapFault exception. +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +--FILE-- +<?php +ini_set("soap.wsdl_cache_enabled", 0); + +function getContinentList() { + return array("getContinentListResult"=>array( + "schema"=>"<xsd:schema><element name=\"test\" type=\"xsd:string\"/></xsd:schema>", + "any"=>"<test>Hello World!</test><test>Bye World!</test>")); +} + +class LocalSoapClient extends SoapClient { + function __construct($wsdl, $options=array()) { + parent::__construct($wsdl, $options); + $this->server = new SoapServer($wsdl, $options); + $this->server->addFunction("getContinentList"); + } + + function __doRequest($request, $location, $action, $version) { + echo $request; + ob_start(); + $this->server->handle($request); + $response = ob_get_contents(); + ob_end_clean(); + echo $response; + return $response; + } +} + +$client = new LocalSoapClient(dirname(__FILE__)."/bug30106.wsdl"); +var_dump($client->__getFunctions()); +var_dump($client->__getTypes()); +$x = $client->getContinentList(array("AFFILIATE_ID"=>1,"PASSWORD"=>"x")); +var_dump($x); +?> +--EXPECTF-- +array(1) { + [0]=> + string(71) "getContinentListResponse getContinentList(getContinentList $parameters)" +} +array(3) { + [0]=> + string(64) "struct getContinentList { + int AFFILIATE_ID; + string PASSWORD; +}" + [1]=> + string(83) "struct getContinentListResponse { + getContinentListResult getContinentListResult; +}" + [2]=> + string(66) "struct getContinentListResult { + <anyXML> schema; + <anyXML> any; +}" +} +<?xml version="1.0" encoding="UTF-8"?> +<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/PRWebServ/getOtherInformation"><SOAP-ENV:Body><ns1:getContinentList><ns1:AFFILIATE_ID>1</ns1:AFFILIATE_ID><ns1:PASSWORD>x</ns1:PASSWORD></ns1:getContinentList></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:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="http://tempuri.org/PRWebServ/getOtherInformation"><SOAP-ENV:Body><ns1:getContinentListResponse><ns1:getContinentListResult><xsd:schema><element name="test" type="xsd:string"/></xsd:schema><test>Hello World!</test><test>Bye World!</test></ns1:getContinentListResult></ns1:getContinentListResponse></SOAP-ENV:Body></SOAP-ENV:Envelope> +object(stdClass)#%d (1) { + ["getContinentListResult"]=> + object(stdClass)#%d (2) { + ["schema"]=> + string(65) "<xsd:schema><element name="test" type="xsd:string"/></xsd:schema>" + ["any"]=> + string(48) "<test>Hello World!</test><test>Bye World!</test>" + } +} http://cvs.php.net/diff.php/php-src/ext/soap/tests/bugs/bug30106.wsdl?r1=1.1&r2=1.2&ty=u Index: php-src/ext/soap/tests/bugs/bug30106.wsdl diff -u /dev/null php-src/ext/soap/tests/bugs/bug30106.wsdl:1.2 --- /dev/null Tue Mar 22 05:19:09 2005 +++ php-src/ext/soap/tests/bugs/bug30106.wsdl Tue Mar 22 05:19:08 2005 @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<wsdl:definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://tempuri.org/PRWebServ/getOtherInformation" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://tempuri.org/PRWebServ/getOtherInformation" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"> + <wsdl:types> + <s:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/PRWebServ/getOtherInformation"> + <s:import namespace="http://www.w3.org/2001/XMLSchema" /> + <s:element name="getContinentList"> + <s:complexType> + <s:sequence> + <s:element minOccurs="1" maxOccurs="1" name="AFFILIATE_ID" type="s:int" /> + <s:element minOccurs="0" maxOccurs="1" name="PASSWORD" type="s:string" /> + </s:sequence> + </s:complexType> + </s:element> + <s:element name="getContinentListResponse"> + <s:complexType> + <s:sequence> + <s:element minOccurs="0" maxOccurs="1" name="getContinentListResult"> + <s:complexType> + <s:sequence> + <s:element ref="s:schema" /> + <s:any /> + </s:sequence> + </s:complexType> + </s:element> + </s:sequence> + </s:complexType> + </s:element> + </s:schema> + </wsdl:types> + <wsdl:message name="getContinentListSoapIn"> + <wsdl:part name="parameters" element="tns:getContinentList" /> + </wsdl:message> + <wsdl:message name="getContinentListSoapOut"> + <wsdl:part name="parameters" element="tns:getContinentListResponse" /> + </wsdl:message> + <wsdl:portType name="getOtherInformationSoap"> + <wsdl:operation name="getContinentList"> + <wsdl:input message="tns:getContinentListSoapIn" /> + <wsdl:output message="tns:getContinentListSoapOut" /> + </wsdl:operation> + </wsdl:portType> + <wsdl:binding name="getOtherInformationSoap" type="tns:getOtherInformationSoap"> + <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> + <wsdl:operation name="getContinentList"> + <soap:operation soapAction="http://tempuri.org/PRWebServ/getOtherInformation/getContinentList" style="document" /> + <wsdl:input> + <soap:body use="literal" /> + </wsdl:input> + <wsdl:output> + <soap:body use="literal" /> + </wsdl:output> + </wsdl:operation> + </wsdl:binding> + <wsdl:service name="getOtherInformation"> + <wsdl:port name="getOtherInformationSoap" binding="tns:getOtherInformationSoap"> + <soap:address location="http://www.precisionreservations.com/PRWebServ/getOtherInformation.asmx" /> + </wsdl:port> + </wsdl:service> +</wsdl:definitions> \ No newline at end of file
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php