diff options
Diffstat (limited to 'ext/soap/soap.c')
-rw-r--r-- | ext/soap/soap.c | 172 |
1 files changed, 142 insertions, 30 deletions
diff --git a/ext/soap/soap.c b/ext/soap/soap.c index f4d1cbeb6..d11e8e7e4 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -17,7 +17,7 @@ | Dmitry Stogov <dmitry@zend.com> | +----------------------------------------------------------------------+ */ -/* $Id: soap.c,v 1.156.2.28.2.27 2007/08/01 10:39:33 dmitry Exp $ */ +/* $Id: soap.c,v 1.156.2.28.2.33 2007/11/01 15:41:13 dmitry Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -1035,6 +1035,7 @@ PHP_METHOD(SoapServer, SoapServer) service = emalloc(sizeof(soapService)); memset(service, 0, sizeof(soapService)); + service->send_errors = 1; cache_wsdl = SOAP_GLOBAL(cache); @@ -1099,6 +1100,11 @@ PHP_METHOD(SoapServer, SoapServer) cache_wsdl = Z_LVAL_PP(tmp); } + if (zend_hash_find(ht, "send_errors", sizeof("send_errors"), (void**)&tmp) == SUCCESS && + (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG)) { + service->send_errors = 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."); } @@ -1866,8 +1872,10 @@ PHP_METHOD(SoapServer, handle) INIT_ZVAL(result); ZVAL_STRINGL(&nm_ob_gzhandler, "ob_gzhandler", sizeof("ob_gzhandler") - 1, 0); + INIT_PZVAL(&str); ZVAL_STRINGL(&str, (char*)buf, size, 0); params[0] = &str; + INIT_PZVAL(&mode); ZVAL_LONG(&mode, PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END); params[1] = &mode; if (call_user_function(CG(function_table), NULL, &nm_ob_gzhandler, &result, 2, params TSRMLS_CC) != FAILURE && @@ -2005,17 +2013,47 @@ static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeade our fault code with their own handling... Figure this out later */ sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error")-1, 1); - snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size); - sapi_add_header(cont_len, strlen(cont_len), 1); if (soap_version == SOAP_1_2) { sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1); } else { sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1); } - php_write(buf, size TSRMLS_CC); + + if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0) && + zend_hash_exists(EG(function_table), "ob_gzhandler", sizeof("ob_gzhandler"))) { + zval nm_ob_gzhandler; + zval str; + zval mode; + zval result; + zval *params[2]; + + INIT_ZVAL(result); + ZVAL_STRINGL(&nm_ob_gzhandler, "ob_gzhandler", sizeof("ob_gzhandler") - 1, 0); + INIT_PZVAL(&str); + ZVAL_STRINGL(&str, (char*)buf, size, 0); + params[0] = &str; + INIT_PZVAL(&mode); + ZVAL_LONG(&mode, PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END); + params[1] = &mode; + if (call_user_function(CG(function_table), NULL, &nm_ob_gzhandler, &result, 2, params TSRMLS_CC) != FAILURE && + Z_TYPE(result) == IS_STRING && + zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) { + xmlFree(buf); + buf = NULL; + snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", Z_STRLEN(result)); + sapi_add_header(cont_len, strlen(cont_len), 1); + php_write(Z_STRVAL(result), Z_STRLEN(result) TSRMLS_CC); + } + zval_dtor(&result); + } + if (buf) { + snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size); + sapi_add_header(cont_len, strlen(cont_len), 1); + php_write(buf, size TSRMLS_CC); + xmlFree(buf); + } xmlFreeDoc(doc_return); - xmlFree(buf); zend_clear_exception(TSRMLS_C); } @@ -2035,11 +2073,15 @@ static void soap_error_handler(int error_num, const char *error_filename, const { zend_bool _old_in_compilation, _old_in_execution; zend_execute_data *_old_current_execute_data; + int _old_http_response_code; + char *_old_http_status_line; TSRMLS_FETCH(); _old_in_compilation = CG(in_compilation); _old_in_execution = EG(in_execution); _old_current_execute_data = EG(current_execute_data); + _old_http_response_code = SG(sapi_headers).http_response_code; + _old_http_status_line = SG(sapi_headers).http_status_line; if (!SOAP_GLOBAL(use_soap_error_handler)) { call_old_error_handler(error_num, error_filename, error_lineno, format, args); @@ -2097,12 +2139,18 @@ static void soap_error_handler(int error_num, const char *error_filename, const old_objects = EG(objects_store).object_buckets; EG(objects_store).object_buckets = NULL; PG(display_errors) = 0; + SG(sapi_headers).http_status_line = NULL; zend_try { call_old_error_handler(error_num, error_filename, error_lineno, format, args); } zend_catch { CG(in_compilation) = _old_in_compilation; EG(in_execution) = _old_in_execution; EG(current_execute_data) = _old_current_execute_data; + if (SG(sapi_headers).http_status_line) { + efree(SG(sapi_headers).http_status_line); + } + SG(sapi_headers).http_status_line = _old_http_status_line; + SG(sapi_headers).http_response_code = _old_http_response_code; } zend_end_try(); EG(objects_store).object_buckets = old_objects; PG(display_errors) = old; @@ -2129,46 +2177,64 @@ static void soap_error_handler(int error_num, const char *error_filename, const char* code = SOAP_GLOBAL(error_code); char buffer[1024]; - int buffer_len; zval *outbuf = NULL; - zval outbuflen; + zval **tmp; + soapServicePtr service; - INIT_ZVAL(outbuflen); + if (code == NULL) { + code = "Server"; + } + if (SOAP_GLOBAL(error_object) && + Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT && + instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_server_class_entry TSRMLS_CC) && + zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "service", sizeof("service"), (void **)&tmp) != FAILURE && + (service = (soapServicePtr)zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service)) && + !service->send_errors) { + strcpy(buffer, "Internal Error"); + } else { + int buffer_len; + zval outbuflen; + + INIT_ZVAL(outbuflen); #ifdef va_copy - va_copy(argcopy, args); - buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy); - va_end(argcopy); + va_copy(argcopy, args); + buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy); + va_end(argcopy); #else - buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args); + buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args); #endif - buffer[sizeof(buffer)-1]=0; - if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) { - buffer_len = sizeof(buffer) - 1; - } + buffer[sizeof(buffer)-1]=0; + if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) { + buffer_len = sizeof(buffer) - 1; + } - if (code == NULL) { - code = "Server"; - } - /* Get output buffer and send as fault detials */ - if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) { - ALLOC_INIT_ZVAL(outbuf); - php_ob_get_buffer(outbuf TSRMLS_CC); - } - php_end_ob_buffer(0, 0 TSRMLS_CC); + /* Get output buffer and send as fault detials */ + if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) { + ALLOC_INIT_ZVAL(outbuf); + php_ob_get_buffer(outbuf TSRMLS_CC); + } + php_end_ob_buffer(0, 0 TSRMLS_CC); + } INIT_ZVAL(fault_obj); set_soap_fault(&fault_obj, NULL, code, buffer, NULL, outbuf, NULL TSRMLS_CC); fault = 1; } PG(display_errors) = 0; + SG(sapi_headers).http_status_line = NULL; zend_try { call_old_error_handler(error_num, error_filename, error_lineno, format, args); } zend_catch { CG(in_compilation) = _old_in_compilation; EG(in_execution) = _old_in_execution; EG(current_execute_data) = _old_current_execute_data; + if (SG(sapi_headers).http_status_line) { + efree(SG(sapi_headers).http_status_line); + } + SG(sapi_headers).http_status_line = _old_http_status_line; + SG(sapi_headers).http_response_code = _old_http_response_code; } zend_end_try(); PG(display_errors) = old; @@ -2878,8 +2944,8 @@ PHP_METHOD(SoapClient, __getTypes) while (zend_hash_get_current_data_ex(sdl->types, (void **)&type, &pos) != FAILURE) { type_to_string((*type), &buf, 0); add_next_index_stringl(return_value, buf.c, buf.len, 1); - zend_hash_move_forward_ex(sdl->types, &pos); smart_str_free(&buf); + zend_hash_move_forward_ex(sdl->types, &pos); } } } @@ -3248,7 +3314,17 @@ static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, i } trav = trav->next; } - if (num_of_params > 0) { + + if (num_of_params == 1 && + function && + function->binding && + function->binding->bindingType == BINDING_SOAP && + ((sdlSoapBindingFunctionPtr)function->bindingAttributes)->style == SOAP_DOCUMENT && + (function->requestParameters == NULL || + zend_hash_num_elements(function->requestParameters) == 0) && + strcmp(params->name, function->functionName) == 0) { + num_of_params = 0; + } else if (num_of_params > 0) { tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0); trav = params; @@ -3289,7 +3365,11 @@ static sdlFunctionPtr find_function(sdlPtr sdl, xmlNodePtr func, zval* function_ if (function && function->binding && function->binding->bindingType == BINDING_SOAP) { sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes; if (fnb->style == SOAP_DOCUMENT) { - function = NULL; + if (func->children != NULL || + (function->requestParameters != NULL && + zend_hash_num_elements(function->requestParameters) > 0)) { + function = NULL; + } } } if (sdl != NULL && function == NULL) { @@ -4532,8 +4612,6 @@ static void type_to_string(sdlTypePtr type, smart_str *buf, int level) switch (type->kind) { case XSD_TYPEKIND_SIMPLE: - case XSD_TYPEKIND_LIST: - case XSD_TYPEKIND_UNION: if (type->encode) { smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str)); smart_str_appendc(buf, ' '); @@ -4542,6 +4620,40 @@ static void type_to_string(sdlTypePtr type, smart_str *buf, int level) } smart_str_appendl(buf, type->name, strlen(type->name)); break; + case XSD_TYPEKIND_LIST: + smart_str_appendl(buf, "list ", 5); + smart_str_appendl(buf, type->name, strlen(type->name)); + if (type->elements) { + sdlTypePtr *item_type; + + smart_str_appendl(buf, " {", 2); + zend_hash_internal_pointer_reset_ex(type->elements, &pos); + if (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) { + smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name)); + } + smart_str_appendc(buf, '}'); + } + break; + case XSD_TYPEKIND_UNION: + smart_str_appendl(buf, "union ", 6); + smart_str_appendl(buf, type->name, strlen(type->name)); + if (type->elements) { + sdlTypePtr *item_type; + int first = 0; + + smart_str_appendl(buf, " {", 2); + zend_hash_internal_pointer_reset_ex(type->elements, &pos); + while (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) { + if (!first) { + smart_str_appendc(buf, ','); + first = 0; + } + smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name)); + zend_hash_move_forward_ex(type->elements, &pos); + } + smart_str_appendc(buf, '}'); + } + break; case XSD_TYPEKIND_COMPLEX: case XSD_TYPEKIND_RESTRICTION: case XSD_TYPEKIND_EXTENSION: |