From 38ef28e41b9c57e826d6d494cd9ebbcbfcc9e13e Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 20 May 2004 16:55:03 +0000 Subject: [PATCH] Allowing user defined SOAP transports with SoapClient::__doRequest() --- ext/soap/php_http.c | 22 ++----- ext/soap/php_http.h | 2 +- ext/soap/soap.c | 106 +++++++++++++++++++++++++------ ext/soap/tests/transport001.phpt | 36 +++++++++++ 4 files changed, 128 insertions(+), 38 deletions(-) create mode 100644 ext/soap/tests/transport001.phpt diff --git a/ext/soap/php_http.c b/ext/soap/php_http.c index d41874b9ed..cfe0f7ac4c 100644 --- a/ext/soap/php_http.c +++ b/ext/soap/php_http.c @@ -186,11 +186,11 @@ static int in_domain(const char *host, const char *domain) } } -int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *soapaction, int soap_version TSRMLS_DC) +int send_http_soap_request(zval *this_ptr, char *buf, int buf_size, char *location, char *soapaction, int soap_version TSRMLS_DC) { - xmlChar *buf, *request; + char *request; smart_str soap_headers = {0}; - int buf_size, request_size, err; + int request_size, err; php_url *phpurl = NULL; php_stream *stream; zval **trace, **tmp; @@ -210,16 +210,6 @@ int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *so stream = NULL; } - xmlDocDumpMemory(doc, &buf, &buf_size); - if (!buf) { - add_soap_fault(this_ptr, "HTTP", "Error build soap request", NULL, NULL TSRMLS_CC); - return FALSE; - } - if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS && - Z_LVAL_PP(trace) > 0) { - add_property_stringl(this_ptr, "__last_request", buf, buf_size, 1); - } - if (location != NULL && location[0] != '\000') { phpurl = php_url_parse(location); } @@ -494,7 +484,7 @@ int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *so } if (request != buf) {efree(request);} - xmlFree(buf); + return TRUE; } @@ -790,10 +780,6 @@ int get_http_soap_response(zval *this_ptr, char **buffer, int *buffer_len TSRMLS *buffer = http_body; *buffer_len = http_body_size; } - if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS && - Z_LVAL_PP(trace) > 0) { - add_property_stringl(this_ptr, "__last_response", *buffer, *buffer_len, 1); - } efree(http_headers); return TRUE; diff --git a/ext/soap/php_http.h b/ext/soap/php_http.h index 44b6a64e78..5aede13270 100644 --- a/ext/soap/php_http.h +++ b/ext/soap/php_http.h @@ -22,7 +22,7 @@ #ifndef PHP_HTTP_H #define PHP_HTTP_H -int send_http_soap_request(zval *this_ptr, xmlDoc *doc, char *location, char *soapaction, int soap_version TSRMLS_DC); +int send_http_soap_request(zval *this_ptr, char *request, int request_size, char *location, char *soapaction, int soap_version TSRMLS_DC); int get_http_soap_response(zval *this_ptr, char **buffer, int *buffer_len TSRMLS_DC); #endif diff --git a/ext/soap/soap.c b/ext/soap/soap.c index fe6821bd62..0ac81721bf 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -234,6 +234,7 @@ PHP_METHOD(SoapClient, __getLastRequestHeaders); PHP_METHOD(SoapClient, __getLastResponseHeaders); PHP_METHOD(SoapClient, __getFunctions); PHP_METHOD(SoapClient, __getTypes); +PHP_METHOD(SoapClient, __doRequest); /* SoapVar Functions */ PHP_METHOD(SoapVar, SoapVar); @@ -303,6 +304,7 @@ static zend_function_entry soap_client_functions[] = { PHP_ME(SoapClient, __getLastResponseHeaders, NULL, 0) PHP_ME(SoapClient, __getFunctions, NULL, 0) PHP_ME(SoapClient, __getTypes, NULL, 0) + PHP_ME(SoapClient, __doRequest, NULL, 0) {NULL, NULL, NULL} }; @@ -1313,7 +1315,7 @@ PHP_METHOD(SoapServer, handle) doc_request = soap_xmlParseMemory(arg,arg_len); } - if (doc_request == NULL) { + if (doc_request == NULL) { soap_server_fault("Client", "Bad Request", NULL, NULL, NULL TSRMLS_CC); } if (xmlGetIntSubset(doc_request) != NULL) { @@ -1914,6 +1916,52 @@ PHP_METHOD(SoapClient, SoapClient) SOAP_CLIENT_END_CODE(); } +static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *action, int version, zval *response TSRMLS_DC) +{ + int ret = TRUE; + char *buf; + int buf_size; + zval func; + zval *params[4]; + zval **trace; + + INIT_ZVAL(*response); + + xmlDocDumpMemory(request, (xmlChar**)&buf, &buf_size); + if (!buf) { + add_soap_fault(this_ptr, "HTTP", "Error build soap request", NULL, NULL TSRMLS_CC); + return FALSE; + } + + if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS && + Z_LVAL_PP(trace) > 0) { + add_property_stringl(this_ptr, "__last_request", buf, buf_size, 1); + } + + INIT_ZVAL(func); + ZVAL_STRINGL(&func,"__doRequest",sizeof("__doRequest")-1,0); + ALLOC_INIT_ZVAL(params[0]); + ZVAL_STRINGL(params[0], buf, buf_size, 0); + ALLOC_INIT_ZVAL(params[1]); + ZVAL_STRING(params[1], location, 0); + ALLOC_INIT_ZVAL(params[2]); + ZVAL_STRING(params[2], action, 0); + ALLOC_INIT_ZVAL(params[3]); + ZVAL_LONG(params[3], version); + + if (call_user_function(NULL, &this_ptr, &func, response, 4, params TSRMLS_CC) != SUCCESS) { + add_soap_fault(this_ptr, "Client", "SoapSlient::__doRequest() failed", NULL, NULL TSRMLS_CC); + ret = FALSE; + } else if (Z_TYPE_P(response) != IS_STRING) { + ret = FALSE; + } else if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS && + Z_LVAL_PP(trace) > 0) { + add_property_stringl(this_ptr, "__last_response", Z_STRVAL_P(response), Z_STRLEN_P(response), 1); + } + xmlFree(buf); + return ret; +} + static void do_soap_call(zval* this_ptr, char* function, int function_len, @@ -1936,6 +1984,7 @@ static void do_soap_call(zval* this_ptr, int len; int ret = FALSE; int soap_version; + zval response; SOAP_CLIENT_BEGIN_CODE(); @@ -1964,24 +2013,23 @@ static void do_soap_call(zval* this_ptr, fn = get_function(sdl, function); if (fn != NULL) { sdlBindingPtr binding = fn->binding; - if (binding->bindingType == BINDING_SOAP) { - sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes; + if (binding->bindingType == BINDING_SOAP) { + sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes; request = serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC); - ret = send_http_soap_request(this_ptr, request, binding->location, fnb->soapAction, soap_version TSRMLS_CC); + ret = do_request(this_ptr, request, binding->location, fnb->soapAction, soap_version, &response TSRMLS_CC); } else { request = serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC); - ret = send_http_soap_request(this_ptr, request, binding->location, NULL, soap_version TSRMLS_CC); + ret = do_request(this_ptr, request, binding->location, NULL, soap_version, &response TSRMLS_CC); } - xmlFreeDoc(request); + xmlFreeDoc(request); - if (ret) { - ret = get_http_soap_response(this_ptr, &buffer, &len TSRMLS_CC); - if (ret) { - parse_packet_soap(this_ptr, buffer, len, fn, NULL, return_value, output_headers TSRMLS_CC); - efree(buffer); - } + if (ret && Z_TYPE(response) == IS_STRING) { + ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), fn, NULL, return_value, output_headers TSRMLS_CC); } + + zval_dtor(&response); + } else { smart_str error = {0}; smart_str_appends(&error,"Function (\""); @@ -2014,18 +2062,16 @@ static void do_soap_call(zval* this_ptr, } smart_str_0(&action); - ret = send_http_soap_request(this_ptr, request, Z_STRVAL_PP(location), action.c, soap_version TSRMLS_CC); + ret = do_request(this_ptr, request, Z_STRVAL_PP(location), action.c, soap_version, &response TSRMLS_CC); smart_str_free(&action); xmlFreeDoc(request); - if (ret) { - ret = get_http_soap_response(this_ptr, &buffer, &len TSRMLS_CC); - if (ret) { - ret = parse_packet_soap(this_ptr, buffer, len, NULL, function, return_value, output_headers TSRMLS_CC); - efree(buffer); - } + if (ret && Z_TYPE(response) == IS_STRING) { + ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), NULL, function, return_value, output_headers TSRMLS_CC); } + + zval_dtor(&response); } } @@ -2232,6 +2278,28 @@ PHP_METHOD(SoapClient, __getLastResponseHeaders) RETURN_NULL(); } +PHP_METHOD(SoapClient, __doRequest) +{ + char *buf, *location, *action; + int buf_size, location_size, action_size; + long version; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl", + &buf, &buf_size, + &location, &location_size, + &action, &action_size, + &version) == FAILURE) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "wrong parameters"); + } + if (send_http_soap_request(this_ptr, buf, buf_size, location, action, version TSRMLS_CC)) { + if (get_http_soap_response(this_ptr, &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC)) { + return_value->type = IS_STRING; + return; + } + } + RETURN_NULL(); +} + #ifndef ZEND_ENGINE_2 static void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) { diff --git a/ext/soap/tests/transport001.phpt b/ext/soap/tests/transport001.phpt new file mode 100644 index 0000000000..ae4de92524 --- /dev/null +++ b/ext/soap/tests/transport001.phpt @@ -0,0 +1,36 @@ +--TEST-- +SOAP Transport 1: Local transport using SoapClient::__doRequest +--SKIPIF-- + +--FILE-- +SoapClient($wsdl, $options); + $this->server = new SoapServer($wsdl, $options); + $this->server->addFunction('Add'); + } + + 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')); +var_dump($x->Add(3,4)); +echo "ok\n"; +?> +--EXPECT-- +int(7) +ok -- 2.50.1