- Fixed bug #36242 (Possible memory corruption in stream_select()). (Tony)
- Fixed bug #36235 (ocicolumnname returns false before a succesfull fetch).
(Tony)
+- Fixed bug #36226 (Inconsistent handling when passing potential arrays).
+ (Dmitry)
- Fixed bug #36224 (date(DATE_ATOM) gives wrong results). (Derick, Hannes
Magnusson)
- Fixed bug #36222 (errorInfo in PDOException is always NULL). (Ilia)
add_next_index_zval(array, val);
} while ((node = get_node(node->next, model->u.element->name)) != NULL);
val = array;
+ } else if ((SOAP_GLOBAL(features) & SOAP_SINGLE_ELEMENT_ARRAYS) &&
+ (model->max_occurs == -1 || model->max_occurs > 1)) {
+ zval *array;
+
+ MAKE_STD_ZVAL(array);
+ array_init(array);
+ add_next_index_zval(array, val);
+ val = array;
}
set_zval_property(ret, model->u.element->name, val TSRMLS_CC);
}
char *uri;
xmlCharEncodingHandlerPtr encoding;
HashTable *class_map;
+ int features;
};
#define SOAP_CLASS 1
#define SOAP_AUTHENTICATION_BASIC 0
#define SOAP_AUTHENTICATION_DIGEST 1
+#define SOAP_SINGLE_ELEMENT_ARRAYS (1<<0)
+
ZEND_BEGIN_MODULE_GLOBALS(soap)
HashTable defEncNs; /* mapping of default namespaces to prefixes */
HashTable defEnc;
long cache_ttl;
xmlCharEncodingHandlerPtr encoding;
HashTable *class_map;
+ int features;
ZEND_END_MODULE_GLOBALS(soap)
#ifdef PHP_WIN32
SOAP_GLOBAL(soap_version) = SOAP_1_1;
SOAP_GLOBAL(encoding) = NULL;
SOAP_GLOBAL(class_map) = NULL;
+ SOAP_GLOBAL(features) = 0;
return SUCCESS;
}
REGISTER_STRING_CONSTANT("XSD_NAMESPACE", XSD_NAMESPACE, CONST_CS | CONST_PERSISTENT);
REGISTER_STRING_CONSTANT("XSD_1999_NAMESPACE", XSD_1999_NAMESPACE, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT);
+
old_error_handler = zend_error_cb;
zend_error_cb = soap_error_handler;
zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *));
}
+ if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
+ Z_TYPE_PP(tmp) == IS_LONG) {
+ service->features = Z_LVAL_PP(tmp);
+ }
+
} else if (wsdl == NULL) {
php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid arguments. 'uri' option is required in nonWSDL mode.");
}
int arg_len;
xmlCharEncodingHandlerPtr old_encoding;
HashTable *old_class_map;
+ int old_features;
SOAP_SERVER_BEGIN_CODE();
SOAP_GLOBAL(encoding) = service->encoding;
old_class_map = SOAP_GLOBAL(class_map);
SOAP_GLOBAL(class_map) = service->class_map;
+ old_features = SOAP_GLOBAL(features);
+ SOAP_GLOBAL(features) = service->features;
old_soap_version = SOAP_GLOBAL(soap_version);
function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, ¶ms, &soap_version, &soap_headers TSRMLS_CC);
xmlFreeDoc(doc_request);
SOAP_GLOBAL(encoding) = old_encoding;
SOAP_GLOBAL(sdl) = old_sdl;
SOAP_GLOBAL(class_map) = old_class_map;
+ SOAP_GLOBAL(features) = old_features;
/* Free soap headers */
zval_dtor(&retval);
add_property_zval(this_ptr, "_classmap", class_map);
}
+ if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
+ Z_TYPE_PP(tmp) == IS_ARRAY) {
+ add_property_long(this_ptr, "_features", Z_LVAL_PP(tmp));
+ }
+
if (zend_hash_find(ht, "connection_timeout", sizeof("connection_timeout"), (void**)&tmp) == SUCCESS &&
Z_TYPE_PP(tmp) == IS_LONG && Z_LVAL_PP(tmp) > 0) {
add_property_long(this_ptr, "_connection_timeout", Z_LVAL_PP(tmp));
zval response;
xmlCharEncodingHandlerPtr old_encoding;
HashTable *old_class_map;
+ int old_features;
SOAP_CLIENT_BEGIN_CODE();
} else {
SOAP_GLOBAL(class_map) = NULL;
}
+ old_features = SOAP_GLOBAL(features);
+ if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_features", sizeof("_features"), (void **) &tmp) == SUCCESS &&
+ Z_TYPE_PP(tmp) == IS_LONG) {
+ SOAP_GLOBAL(features) = Z_LVAL_PP(tmp);
+ } else {
+ SOAP_GLOBAL(features) = 0;
+ }
if (sdl != NULL) {
fn = get_function(sdl, function);
zend_throw_exception_object(exception TSRMLS_CC);
}
#endif
- if (SOAP_GLOBAL(encoding) != NULL) {
+ if (SOAP_GLOBAL(encoding) != NULL) {
xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
- }
- SOAP_GLOBAL(class_map) = old_class_map;
+ }
+ SOAP_GLOBAL(features) = old_features;
+ SOAP_GLOBAL(class_map) = old_class_map;
SOAP_GLOBAL(encoding) = old_encoding;
SOAP_GLOBAL(sdl) = old_sdl;
SOAP_CLIENT_END_CODE();
--- /dev/null
+--TEST--
+Bug #36226 SOAP Inconsistent handling when passing potential arrays.
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--INI--
+soap.wsdl_cache_enabled=0
+--FILE--
+<?php
+ini_set("soap.wsdl_cache_enabled",0);
+$timestamp = "2005-11-08T11:22:07+03:00";
+$wsdl = dirname(__FILE__)."/bug35142.wsdl";
+
+function PostEvents($x) {
+ var_dump($x);
+ exit();
+ return $x;
+}
+
+class TestSoapClient extends SoapClient {
+
+ function __construct($wsdl, $options) {
+ parent::__construct($wsdl, $options);
+ $this->server = new SoapServer($wsdl, $options);
+ $this->server->addFunction('PostEvents');
+ }
+
+ function __doRequest($request, $location, $action, $version) {
+ echo "$request\n";
+ $this->server->handle($request);
+ return $response;
+ }
+
+}
+
+$soapClient = new TestSoapClient($wsdl,
+ array('trace' => 1, 'exceptions' => 0,
+ 'classmap' => array('logOnEvent' => 'LogOnEvent',
+ 'logOffEvent' => 'LogOffEvent',
+ 'events' => 'IVREvents'),
+ 'features' => SOAP_SINGLE_ELEMENT_ARRAYS));
+
+$logOnEvent = new LogOnEvent(34567, $timestamp);
+$logOffEvents[] = new LogOffEvent(34567, $timestamp, "Smoked");
+$logOffEvents[] = new LogOffEvent(34568, $timestamp, "SmokeFree");
+$ivrEvents = new IVREvents("1.0", 101, 12345, 'IVR', $logOnEvent, $logOffEvents);
+
+$result = $soapClient->PostEvents($ivrEvents);
+
+class LogOffEvent {
+ public $audienceMemberId;
+ public $timestamp;
+ public $smokeStatus;
+ public $callInititator;
+
+ function __construct($audienceMemberId, $timestamp, $smokeStatus) {
+ $this->audienceMemberId = $audienceMemberId;
+ $this->timestamp = $timestamp;
+ $this->smokeStatus = $smokeStatus;
+ $this->callInitiator = "IVR";
+ }
+}
+
+class LogOnEvent {
+ public $audienceMemberId;
+ public $timestamp;
+
+ function __construct($audienceMemberId, $timestamp) {
+ $this->audienceMemberId = $audienceMemberId;
+ $this->timestamp = $timestamp;
+ }
+}
+
+class IVREvents {
+ public $version;
+ public $activityId;
+ public $messageId;
+ public $source;
+ public $logOnEvent;
+ public $logOffEvent;
+
+ function __construct($version, $activityId, $messageId, $source, $logOnEvent=NULL, $logOffEvent=NULL) {
+ $this->version = $version;
+ $this->activityId = $activityId;
+ $this->messageId = $messageId;
+ $this->source = $source;
+ $this->logOnEvent = $logOnEvent;
+ $this->logOffEvent = $logOffEvent;
+ }
+}
+?>
+--EXPECTF--
+<?xml version="1.0" encoding="UTF-8"?>
+<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://testurl/Message"><SOAP-ENV:Body><ns1:ivrEvents version="1.0" activityId="101" messageId="12345" source="IVR"><ns1:logOffEvent audienceMemberId="34567" timestamp="2005-11-08T11:22:07+03:00" smokeStatus="Smoked" callInitiator="IVR"/><ns1:logOffEvent audienceMemberId="34568" timestamp="2005-11-08T11:22:07+03:00" smokeStatus="SmokeFree" callInitiator="IVR"/><ns1:logOnEvent audienceMemberId="34567" timestamp="2005-11-08T11:22:07+03:00"/></ns1:ivrEvents></SOAP-ENV:Body></SOAP-ENV:Envelope>
+
+object(IVREvents)#%d (6) {
+ ["version"]=>
+ string(3) "1.0"
+ ["activityId"]=>
+ int(101)
+ ["messageId"]=>
+ int(12345)
+ ["logOffEvent"]=>
+ array(2) {
+ [0]=>
+ object(LogOffEvent)#%d (4) {
+ ["audienceMemberId"]=>
+ int(34567)
+ ["timestamp"]=>
+ string(25) "2005-11-08T11:22:07+03:00"
+ ["smokeStatus"]=>
+ string(6) "Smoked"
+ ["callInitiator"]=>
+ string(3) "IVR"
+ }
+ [1]=>
+ object(LogOffEvent)#%d (4) {
+ ["audienceMemberId"]=>
+ int(34568)
+ ["timestamp"]=>
+ string(25) "2005-11-08T11:22:07+03:00"
+ ["smokeStatus"]=>
+ string(9) "SmokeFree"
+ ["callInitiator"]=>
+ string(3) "IVR"
+ }
+ }
+ ["logOnEvent"]=>
+ array(1) {
+ [0]=>
+ object(LogOnEvent)#10 (2) {
+ ["audienceMemberId"]=>
+ int(34567)
+ ["timestamp"]=>
+ string(25) "2005-11-08T11:22:07+03:00"
+ }
+ }
+ ["source"]=>
+ string(3) "IVR"
+}