root/ext/soap/soap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ZEND_GET_MODULE
  2. PHP_INI_MH
  3. PHP_INI_BEGIN
  4. php_soap_init_globals
  5. PHP_MSHUTDOWN_FUNCTION
  6. PHP_RINIT_FUNCTION
  7. PHP_MINIT_FUNCTION
  8. PHP_MINFO_FUNCTION
  9. PHP_METHOD
  10. PHP_METHOD
  11. PHP_METHOD
  12. PHP_METHOD
  13. PHP_METHOD
  14. soap_create_typemap
  15. PHP_METHOD
  16. PHP_METHOD
  17. PHP_METHOD
  18. PHP_METHOD
  19. PHP_METHOD
  20. PHP_METHOD
  21. PHP_METHOD
  22. PHP_METHOD
  23. PHP_METHOD
  24. soap_server_fault_ex
  25. soap_server_fault
  26. soap_error_handler
  27. PHP_FUNCTION
  28. PHP_FUNCTION
  29. PHP_METHOD
  30. do_request
  31. do_soap_call
  32. verify_soap_headers_array
  33. PHP_METHOD
  34. PHP_METHOD
  35. PHP_METHOD
  36. PHP_METHOD
  37. PHP_METHOD
  38. PHP_METHOD
  39. PHP_METHOD
  40. PHP_METHOD
  41. PHP_METHOD
  42. PHP_METHOD
  43. PHP_METHOD
  44. PHP_METHOD
  45. clear_soap_fault
  46. add_soap_fault
  47. set_soap_fault
  48. deserialize_parameters
  49. find_function
  50. deserialize_function_call
  51. set_soap_header_attributes
  52. serialize_response_call2
  53. serialize_response_call
  54. serialize_function_call
  55. serialize_parameter
  56. serialize_zval
  57. get_param
  58. get_function
  59. get_doc_function
  60. function_to_string
  61. model_to_string
  62. type_to_string
  63. delete_url
  64. delete_service
  65. delete_hashtable

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 5                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 1997-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
  16   |          Shane Caraveo <shane@caraveo.com>                           |
  17   |          Dmitry Stogov <dmitry@zend.com>                             |
  18   +----------------------------------------------------------------------+
  19 */
  20 /* $Id$ */
  21 
  22 #ifdef HAVE_CONFIG_H
  23 #include "config.h"
  24 #endif
  25 #include "php_soap.h"
  26 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
  27 #include "ext/session/php_session.h"
  28 #endif
  29 #include "zend_exceptions.h"
  30 
  31 
  32 static int le_sdl = 0;
  33 int le_url = 0;
  34 static int le_service = 0;
  35 static int le_typemap = 0;
  36 
  37 typedef struct _soapHeader {
  38         sdlFunctionPtr                    function;
  39         zval                              function_name;
  40         int                               mustUnderstand;
  41         int                               num_params;
  42         zval                            **parameters;
  43         zval                              retval;
  44         sdlSoapBindingFunctionHeaderPtr   hdr;
  45         struct _soapHeader               *next;
  46 } soapHeader;
  47 
  48 /* Local functions */
  49 static void function_to_string(sdlFunctionPtr function, smart_str *buf);
  50 static void type_to_string(sdlTypePtr type, smart_str *buf, int level);
  51 
  52 static void clear_soap_fault(zval *obj TSRMLS_DC);
  53 static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC);
  54 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char *name TSRMLS_DC);
  55 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader* hdr TSRMLS_DC);
  56 
  57 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int);
  58 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name);
  59 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr node);
  60 
  61 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval **parameters[], int *version, soapHeader **headers TSRMLS_DC);
  62 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name,char *uri,zval *ret, soapHeader *headers, int version TSRMLS_DC);
  63 static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function, char *function_name, char *uri, zval **arguments, int arg_count, int version, HashTable *soap_headers TSRMLS_DC);
  64 static xmlNodePtr serialize_parameter(sdlParamPtr param,zval *param_val,int index,char *name, int style, xmlNodePtr parent TSRMLS_DC);
  65 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent TSRMLS_DC);
  66 
  67 static void delete_service(void *service);
  68 static void delete_url(void *handle);
  69 static void delete_hashtable(void *hashtable);
  70 
  71 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
  72 
  73 #define SOAP_SERVER_BEGIN_CODE() \
  74         zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
  75         char* _old_error_code = SOAP_GLOBAL(error_code);\
  76         zval* _old_error_object = SOAP_GLOBAL(error_object);\
  77         int _old_soap_version = SOAP_GLOBAL(soap_version);\
  78         SOAP_GLOBAL(use_soap_error_handler) = 1;\
  79         SOAP_GLOBAL(error_code) = "Server";\
  80         SOAP_GLOBAL(error_object) = this_ptr;
  81 
  82 #define SOAP_SERVER_END_CODE() \
  83         SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
  84         SOAP_GLOBAL(error_code) = _old_error_code;\
  85         SOAP_GLOBAL(error_object) = _old_error_object;\
  86         SOAP_GLOBAL(soap_version) = _old_soap_version;
  87 
  88 #define SOAP_CLIENT_BEGIN_CODE() \
  89         zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
  90         char* _old_error_code = SOAP_GLOBAL(error_code);\
  91         zval* _old_error_object = SOAP_GLOBAL(error_object);\
  92         int _old_soap_version = SOAP_GLOBAL(soap_version);\
  93         zend_bool _old_in_compilation = CG(in_compilation); \
  94         zend_bool _old_in_execution = EG(in_execution); \
  95         zend_execute_data *_old_current_execute_data = EG(current_execute_data); \
  96         void **_old_stack_top = EG(argument_stack)->top; \
  97         int _bailout = 0;\
  98         SOAP_GLOBAL(use_soap_error_handler) = 1;\
  99         SOAP_GLOBAL(error_code) = "Client";\
 100         SOAP_GLOBAL(error_object) = this_ptr;\
 101         zend_try {
 102 
 103 #define SOAP_CLIENT_END_CODE() \
 104         } zend_catch {\
 105                 CG(in_compilation) = _old_in_compilation; \
 106                 EG(in_execution) = _old_in_execution; \
 107                 EG(current_execute_data) = _old_current_execute_data; \
 108                 if (EG(exception) == NULL || \
 109                     Z_TYPE_P(EG(exception)) != IS_OBJECT || \
 110                     !instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {\
 111                         _bailout = 1;\
 112                 }\
 113                 if (_old_stack_top != EG(argument_stack)->top) { \
 114                         while (EG(argument_stack)->prev != NULL && \
 115                                ((char*)_old_stack_top < (char*)EG(argument_stack) || \
 116                                 (char*) _old_stack_top > (char*)EG(argument_stack)->end)) { \
 117                                 zend_vm_stack tmp = EG(argument_stack)->prev; \
 118                                 efree(EG(argument_stack)); \
 119                                 EG(argument_stack) = tmp; \
 120                         } \
 121                         EG(argument_stack)->top = _old_stack_top; \
 122                 } \
 123         } zend_end_try();\
 124         SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
 125         SOAP_GLOBAL(error_code) = _old_error_code;\
 126         SOAP_GLOBAL(error_object) = _old_error_object;\
 127         SOAP_GLOBAL(soap_version) = _old_soap_version;\
 128         if (_bailout) {\
 129                 zend_bailout();\
 130         }
 131 
 132 #define FETCH_THIS_SDL(ss) \
 133         { \
 134                 zval **__tmp; \
 135                 if(FIND_SDL_PROPERTY(this_ptr,__tmp) != FAILURE) { \
 136                         FETCH_SDL_RES(ss,__tmp); \
 137                 } else { \
 138                         ss = NULL; \
 139                 } \
 140         }
 141 
 142 #define FIND_SDL_PROPERTY(ss,tmp) zend_hash_find(Z_OBJPROP_P(ss), "sdl", sizeof("sdl"), (void **)&tmp)
 143 #define FETCH_SDL_RES(ss,tmp) ss = (sdlPtr) zend_fetch_resource(tmp TSRMLS_CC, -1, "sdl", NULL, 1, le_sdl)
 144 
 145 #define FIND_TYPEMAP_PROPERTY(ss,tmp) zend_hash_find(Z_OBJPROP_P(ss), "typemap", sizeof("typemap"), (void **)&tmp)
 146 #define FETCH_TYPEMAP_RES(ss,tmp) ss = (HashTable*) zend_fetch_resource(tmp TSRMLS_CC, -1, "typemap", NULL, 1, le_typemap)
 147 
 148 #define FETCH_THIS_SERVICE(ss) \
 149         { \
 150                 zval **tmp; \
 151                 if (zend_hash_find(Z_OBJPROP_P(this_ptr),"service", sizeof("service"), (void **)&tmp) != FAILURE) { \
 152                         ss = (soapServicePtr)zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service); \
 153                 } else { \
 154                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Can not fetch service object"); \
 155                         SOAP_SERVER_END_CODE(); \
 156                         return; \
 157                 } \
 158         }
 159 
 160 static zend_class_entry* soap_class_entry;
 161 static zend_class_entry* soap_server_class_entry;
 162 static zend_class_entry* soap_fault_class_entry;
 163 static zend_class_entry* soap_header_class_entry;
 164 static zend_class_entry* soap_param_class_entry;
 165 zend_class_entry* soap_var_class_entry;
 166 
 167 ZEND_DECLARE_MODULE_GLOBALS(soap)
 168 
 169 static void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
 170 
 171 #ifdef va_copy
 172 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
 173 { \
 174         va_list copy; \
 175         va_copy(copy, args); \
 176         old_error_handler(error_num, error_filename, error_lineno, format, copy); \
 177         va_end(copy); \
 178 }
 179 #else
 180 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
 181 { \
 182         old_error_handler(error_num, error_filename, error_lineno, format, args); \
 183 }
 184 #endif
 185 
 186 #define PHP_SOAP_SERVER_CLASSNAME "SoapServer"
 187 #define PHP_SOAP_CLIENT_CLASSNAME "SoapClient"
 188 #define PHP_SOAP_VAR_CLASSNAME    "SoapVar"
 189 #define PHP_SOAP_FAULT_CLASSNAME  "SoapFault"
 190 #define PHP_SOAP_PARAM_CLASSNAME  "SoapParam"
 191 #define PHP_SOAP_HEADER_CLASSNAME "SoapHeader"
 192 
 193 PHP_RINIT_FUNCTION(soap);
 194 PHP_MINIT_FUNCTION(soap);
 195 PHP_MSHUTDOWN_FUNCTION(soap);
 196 PHP_MINFO_FUNCTION(soap);
 197 
 198 /*
 199   Registry Functions
 200   TODO: this!
 201 */
 202 PHP_FUNCTION(soap_encode_to_xml);
 203 PHP_FUNCTION(soap_encode_to_zval);
 204 PHP_FUNCTION(use_soap_error_handler);
 205 PHP_FUNCTION(is_soap_fault);
 206 
 207 
 208 /* Server Functions */
 209 PHP_METHOD(SoapServer, SoapServer);
 210 PHP_METHOD(SoapServer, setClass);
 211 PHP_METHOD(SoapServer, setObject);
 212 PHP_METHOD(SoapServer, addFunction);
 213 PHP_METHOD(SoapServer, getFunctions);
 214 PHP_METHOD(SoapServer, handle);
 215 PHP_METHOD(SoapServer, setPersistence);
 216 PHP_METHOD(SoapServer, fault);
 217 PHP_METHOD(SoapServer, addSoapHeader);
 218 
 219 /* Client Functions */
 220 PHP_METHOD(SoapClient, SoapClient);
 221 PHP_METHOD(SoapClient, __call);
 222 PHP_METHOD(SoapClient, __getLastRequest);
 223 PHP_METHOD(SoapClient, __getLastResponse);
 224 PHP_METHOD(SoapClient, __getLastRequestHeaders);
 225 PHP_METHOD(SoapClient, __getLastResponseHeaders);
 226 PHP_METHOD(SoapClient, __getFunctions);
 227 PHP_METHOD(SoapClient, __getTypes);
 228 PHP_METHOD(SoapClient, __doRequest);
 229 PHP_METHOD(SoapClient, __setCookie);
 230 PHP_METHOD(SoapClient, __getCookies);
 231 PHP_METHOD(SoapClient, __setLocation);
 232 PHP_METHOD(SoapClient, __setSoapHeaders);
 233 
 234 /* SoapVar Functions */
 235 PHP_METHOD(SoapVar, SoapVar);
 236 
 237 /* SoapFault Functions */
 238 PHP_METHOD(SoapFault, SoapFault);
 239 PHP_METHOD(SoapFault, __toString);
 240 
 241 /* SoapParam Functions */
 242 PHP_METHOD(SoapParam, SoapParam);
 243 
 244 /* SoapHeader Functions */
 245 PHP_METHOD(SoapHeader, SoapHeader);
 246 
 247 #define SOAP_CTOR(class_name, func_name, arginfo, flags) PHP_ME(class_name, func_name, arginfo, flags)
 248 
 249 /* {{{ arginfo */
 250 ZEND_BEGIN_ARG_INFO(arginfo_soap__void, 0)
 251 ZEND_END_ARG_INFO()
 252 
 253 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapparam_soapparam, 0, 0, 2)
 254         ZEND_ARG_INFO(0, data)
 255         ZEND_ARG_INFO(0, name)
 256 ZEND_END_ARG_INFO()
 257 
 258 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapheader_soapheader, 0, 0, 2)
 259         ZEND_ARG_INFO(0, namespace)
 260         ZEND_ARG_INFO(0, name)
 261         ZEND_ARG_INFO(0, data)
 262         ZEND_ARG_INFO(0, mustunderstand)
 263         ZEND_ARG_INFO(0, actor)
 264 ZEND_END_ARG_INFO()
 265 
 266 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapfault_soapfault, 0, 0, 2)
 267         ZEND_ARG_INFO(0, faultcode)
 268         ZEND_ARG_INFO(0, faultstring)
 269         ZEND_ARG_INFO(0, faultactor)
 270         ZEND_ARG_INFO(0, detail)
 271         ZEND_ARG_INFO(0, faultname)
 272         ZEND_ARG_INFO(0, headerfault)
 273 ZEND_END_ARG_INFO()
 274 
 275 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapvar_soapvar, 0, 0, 2)
 276         ZEND_ARG_INFO(0, data)
 277         ZEND_ARG_INFO(0, encoding)
 278         ZEND_ARG_INFO(0, type_name)
 279         ZEND_ARG_INFO(0, type_namespace)
 280         ZEND_ARG_INFO(0, node_name)
 281         ZEND_ARG_INFO(0, node_namespace)
 282 ZEND_END_ARG_INFO()
 283 
 284 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_fault, 0, 0, 2)
 285         ZEND_ARG_INFO(0, code)
 286         ZEND_ARG_INFO(0, string)
 287         ZEND_ARG_INFO(0, actor)
 288         ZEND_ARG_INFO(0, details)
 289         ZEND_ARG_INFO(0, name)
 290 ZEND_END_ARG_INFO()
 291 
 292 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addsoapheader, 0, 0, 1)
 293         ZEND_ARG_INFO(0, object)
 294 ZEND_END_ARG_INFO()
 295 
 296 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_soapserver, 0, 0, 1)
 297         ZEND_ARG_INFO(0, wsdl)
 298         ZEND_ARG_INFO(0, options)
 299 ZEND_END_ARG_INFO()
 300 
 301 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setpersistence, 0, 0, 1)
 302         ZEND_ARG_INFO(0, mode)
 303 ZEND_END_ARG_INFO()
 304 
 305 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setclass, 0, 0, 1)
 306         ZEND_ARG_INFO(0, class_name)
 307         ZEND_ARG_INFO(0, args)
 308 ZEND_END_ARG_INFO()
 309 
 310 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setobject, 0, 0, 1)
 311         ZEND_ARG_INFO(0, object)
 312 ZEND_END_ARG_INFO()
 313 
 314 ZEND_BEGIN_ARG_INFO(arginfo_soapserver_getfunctions, 0)
 315 ZEND_END_ARG_INFO()
 316 
 317 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addfunction, 0, 0, 1)
 318         ZEND_ARG_INFO(0, functions)
 319 ZEND_END_ARG_INFO()
 320 
 321 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_handle, 0, 0, 0)
 322         ZEND_ARG_INFO(0, soap_request)
 323 ZEND_END_ARG_INFO()
 324 
 325 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient_soapclient, 0, 0, 1)
 326         ZEND_ARG_INFO(0, wsdl)
 327         ZEND_ARG_INFO(0, options)
 328 ZEND_END_ARG_INFO()
 329 
 330 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___call, 0, 0, 2)
 331         ZEND_ARG_INFO(0, function_name)
 332         ZEND_ARG_INFO(0, arguments)
 333 ZEND_END_ARG_INFO()
 334 
 335 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___soapcall, 0, 0, 2)
 336         ZEND_ARG_INFO(0, function_name)
 337         ZEND_ARG_INFO(0, arguments)
 338         ZEND_ARG_INFO(0, options)
 339         ZEND_ARG_INFO(0, input_headers)
 340         ZEND_ARG_INFO(1, output_headers)
 341 ZEND_END_ARG_INFO()
 342 
 343 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getfunctions, 0)
 344 ZEND_END_ARG_INFO()
 345 
 346 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___gettypes, 0)
 347 ZEND_END_ARG_INFO()
 348 
 349 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequest, 0)
 350 ZEND_END_ARG_INFO()
 351 
 352 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponse, 0)
 353 ZEND_END_ARG_INFO()
 354 
 355 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequestheaders, 0)
 356 ZEND_END_ARG_INFO()
 357 
 358 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponseheaders, 0)
 359 ZEND_END_ARG_INFO()
 360 
 361 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___dorequest, 0, 0, 4)
 362         ZEND_ARG_INFO(0, request)
 363         ZEND_ARG_INFO(0, location)
 364         ZEND_ARG_INFO(0, action)
 365         ZEND_ARG_INFO(0, version)
 366         ZEND_ARG_INFO(0, one_way)
 367 ZEND_END_ARG_INFO()
 368 
 369 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setcookie, 0, 0, 1)
 370         ZEND_ARG_INFO(0, name)
 371         ZEND_ARG_INFO(0, value)
 372 ZEND_END_ARG_INFO()
 373 
 374 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getcookies, 0)
 375 ZEND_END_ARG_INFO()
 376 
 377 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setsoapheaders, 0, 0, 1)
 378         ZEND_ARG_INFO(0, soapheaders)
 379 ZEND_END_ARG_INFO()
 380 
 381 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setlocation, 0, 0, 0)
 382         ZEND_ARG_INFO(0, new_location)
 383 ZEND_END_ARG_INFO()
 384 
 385 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_use_soap_error_handler, 0, 0, 0)
 386         ZEND_ARG_INFO(0, handler)
 387 ZEND_END_ARG_INFO()
 388 
 389 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_is_soap_fault, 0, 0, 1)
 390         ZEND_ARG_INFO(0, object)
 391 ZEND_END_ARG_INFO()
 392 /* }}} */
 393 
 394 static const zend_function_entry soap_functions[] = {
 395         PHP_FE(use_soap_error_handler,  arginfo_soap_use_soap_error_handler)
 396         PHP_FE(is_soap_fault,                   arginfo_soap_is_soap_fault)
 397         PHP_FE_END
 398 };
 399 
 400 static const zend_function_entry soap_fault_functions[] = {
 401         SOAP_CTOR(SoapFault, SoapFault, arginfo_soapfault_soapfault, 0)
 402         PHP_ME(SoapFault, __toString, arginfo_soap__void, 0)
 403         PHP_FE_END
 404 };
 405 
 406 static const zend_function_entry soap_server_functions[] = {
 407         SOAP_CTOR(SoapServer, SoapServer,       arginfo_soapserver_soapserver, 0)
 408         PHP_ME(SoapServer, setPersistence,      arginfo_soapserver_setpersistence, 0)
 409         PHP_ME(SoapServer, setClass,            arginfo_soapserver_setclass, 0)
 410         PHP_ME(SoapServer, setObject,           arginfo_soapserver_setobject, 0)
 411         PHP_ME(SoapServer, addFunction,         arginfo_soapserver_addfunction, 0)
 412         PHP_ME(SoapServer, getFunctions,        arginfo_soapserver_getfunctions, 0)
 413         PHP_ME(SoapServer, handle,                      arginfo_soapserver_handle, 0)
 414         PHP_ME(SoapServer, fault,                       arginfo_soapserver_fault, 0)
 415         PHP_ME(SoapServer, addSoapHeader,       arginfo_soapserver_addsoapheader, 0)
 416         PHP_FE_END
 417 };
 418 
 419 static const zend_function_entry soap_client_functions[] = {
 420         SOAP_CTOR(SoapClient, SoapClient, arginfo_soapclient_soapclient, 0)
 421         PHP_ME(SoapClient, __call,                                              arginfo_soapclient___call, 0)
 422         ZEND_NAMED_ME(__soapCall, ZEND_MN(SoapClient___call), arginfo_soapclient___soapcall, 0)
 423         PHP_ME(SoapClient, __getLastRequest,                    arginfo_soapclient___getlastrequest, 0)
 424         PHP_ME(SoapClient, __getLastResponse,                   arginfo_soapclient___getlastresponse, 0)
 425         PHP_ME(SoapClient, __getLastRequestHeaders,     arginfo_soapclient___getlastrequestheaders, 0)
 426         PHP_ME(SoapClient, __getLastResponseHeaders,    arginfo_soapclient___getlastresponseheaders, 0)
 427         PHP_ME(SoapClient, __getFunctions,                              arginfo_soapclient___getfunctions, 0)
 428         PHP_ME(SoapClient, __getTypes,                                  arginfo_soapclient___gettypes, 0)
 429         PHP_ME(SoapClient, __doRequest,                                 arginfo_soapclient___dorequest, 0)
 430         PHP_ME(SoapClient, __setCookie,                                 arginfo_soapclient___setcookie, 0)
 431         PHP_ME(SoapClient, __getCookies,                                arginfo_soapclient___getcookies, 0)
 432         PHP_ME(SoapClient, __setLocation,                               arginfo_soapclient___setlocation, 0)
 433         PHP_ME(SoapClient, __setSoapHeaders,                    arginfo_soapclient___setsoapheaders, 0)
 434         PHP_FE_END
 435 };
 436 
 437 static const zend_function_entry soap_var_functions[] = {
 438         SOAP_CTOR(SoapVar, SoapVar, arginfo_soapvar_soapvar, 0)
 439         PHP_FE_END
 440 };
 441 
 442 static const zend_function_entry soap_param_functions[] = {
 443         SOAP_CTOR(SoapParam, SoapParam, arginfo_soapparam_soapparam, 0)
 444         PHP_FE_END
 445 };
 446 
 447 static const zend_function_entry soap_header_functions[] = {
 448         SOAP_CTOR(SoapHeader, SoapHeader, arginfo_soapheader_soapheader, 0)
 449         PHP_FE_END
 450 };
 451 
 452 zend_module_entry soap_module_entry = {
 453 #ifdef STANDARD_MODULE_HEADER
 454   STANDARD_MODULE_HEADER,
 455 #endif
 456   "soap",
 457   soap_functions,
 458   PHP_MINIT(soap),
 459   PHP_MSHUTDOWN(soap),
 460   PHP_RINIT(soap),
 461   NULL,
 462   PHP_MINFO(soap),
 463 #ifdef STANDARD_MODULE_HEADER
 464   NO_VERSION_YET,
 465 #endif
 466   STANDARD_MODULE_PROPERTIES,
 467 };
 468 
 469 #ifdef COMPILE_DL_SOAP
 470 ZEND_GET_MODULE(soap)
 471 #endif
 472 
 473 ZEND_INI_MH(OnUpdateCacheMode)
 474 {
 475         char *p;
 476 #ifndef ZTS
 477         char *base = (char *) mh_arg2;
 478 #else
 479         char *base = (char *) ts_resource(*((int *) mh_arg2));
 480 #endif
 481 
 482         p = (char*) (base+(size_t) mh_arg1);
 483 
 484         *p = (char)atoi(new_value);
 485 
 486         return SUCCESS;
 487 }
 488 
 489 static PHP_INI_MH(OnUpdateCacheDir)
 490 {
 491         /* Only do the open_basedir check at runtime */
 492         if (stage == PHP_INI_STAGE_RUNTIME || stage == PHP_INI_STAGE_HTACCESS) {
 493                 char *p;
 494 
 495                 if (memchr(new_value, '\0', new_value_length) != NULL) {
 496                         return FAILURE;
 497                 }
 498 
 499                 /* we do not use zend_memrchr() since path can contain ; itself */
 500                 if ((p = strchr(new_value, ';'))) {
 501                         char *p2;
 502                         p++;
 503                         if ((p2 = strchr(p, ';'))) {
 504                                 p = p2 + 1;
 505                         }
 506                 } else {
 507                         p = new_value;
 508                 }
 509 
 510                 if (PG(open_basedir) && *p && php_check_open_basedir(p TSRMLS_CC)) {
 511                         return FAILURE;
 512                 }
 513         }
 514 
 515         OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
 516         return SUCCESS;
 517 }
 518 
 519 PHP_INI_BEGIN()
 520 STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled",     "1", PHP_INI_ALL, OnUpdateBool,
 521                   cache_enabled, zend_soap_globals, soap_globals)
 522 STD_PHP_INI_ENTRY("soap.wsdl_cache_dir",         "/tmp", PHP_INI_ALL, OnUpdateCacheDir,
 523                   cache_dir, zend_soap_globals, soap_globals)
 524 STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl",         "86400", PHP_INI_ALL, OnUpdateLong,
 525                   cache_ttl, zend_soap_globals, soap_globals)
 526 STD_PHP_INI_ENTRY("soap.wsdl_cache",             "1", PHP_INI_ALL, OnUpdateCacheMode,
 527                   cache_mode, zend_soap_globals, soap_globals)
 528 STD_PHP_INI_ENTRY("soap.wsdl_cache_limit",       "5", PHP_INI_ALL, OnUpdateLong,
 529                   cache_limit, zend_soap_globals, soap_globals)
 530 PHP_INI_END()
 531 
 532 static HashTable defEnc, defEncIndex, defEncNs;
 533 
 534 static void php_soap_prepare_globals()
 535 {
 536         int i;
 537         encodePtr enc;
 538 
 539         zend_hash_init(&defEnc, 0, NULL, NULL, 1);
 540         zend_hash_init(&defEncIndex, 0, NULL, NULL, 1);
 541         zend_hash_init(&defEncNs, 0, NULL, NULL, 1);
 542 
 543         i = 0;
 544         do {
 545                 enc = &defaultEncoding[i];
 546 
 547                 /* If has a ns and a str_type then index it */
 548                 if (defaultEncoding[i].details.type_str) {
 549                         if (defaultEncoding[i].details.ns != NULL) {
 550                                 char *ns_type;
 551                                 spprintf(&ns_type, 0, "%s:%s", defaultEncoding[i].details.ns, defaultEncoding[i].details.type_str);
 552                                 zend_hash_add(&defEnc, ns_type, strlen(ns_type) + 1, &enc, sizeof(encodePtr), NULL);
 553                                 efree(ns_type);
 554                         } else {
 555                                 zend_hash_add(&defEnc, defaultEncoding[i].details.type_str, strlen(defaultEncoding[i].details.type_str) + 1, &enc, sizeof(encodePtr), NULL);
 556                         }
 557                 }
 558                 /* Index everything by number */
 559                 if (!zend_hash_index_exists(&defEncIndex, defaultEncoding[i].details.type)) {
 560                         zend_hash_index_update(&defEncIndex, defaultEncoding[i].details.type, &enc, sizeof(encodePtr), NULL);
 561                 }
 562                 i++;
 563         } while (defaultEncoding[i].details.type != END_KNOWN_TYPES);
 564 
 565         /* hash by namespace */
 566         zend_hash_add(&defEncNs, XSD_1999_NAMESPACE, sizeof(XSD_1999_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
 567         zend_hash_add(&defEncNs, XSD_NAMESPACE, sizeof(XSD_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
 568         zend_hash_add(&defEncNs, XSI_NAMESPACE, sizeof(XSI_NAMESPACE), XSI_NS_PREFIX, sizeof(XSI_NS_PREFIX), NULL);
 569         zend_hash_add(&defEncNs, XML_NAMESPACE, sizeof(XML_NAMESPACE), XML_NS_PREFIX, sizeof(XML_NS_PREFIX), NULL);
 570         zend_hash_add(&defEncNs, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE), SOAP_1_1_ENC_NS_PREFIX, sizeof(SOAP_1_1_ENC_NS_PREFIX), NULL);
 571         zend_hash_add(&defEncNs, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE), SOAP_1_2_ENC_NS_PREFIX, sizeof(SOAP_1_2_ENC_NS_PREFIX), NULL);
 572 }
 573 
 574 static void php_soap_init_globals(zend_soap_globals *soap_globals TSRMLS_DC)
 575 {
 576         soap_globals->defEnc = defEnc;
 577         soap_globals->defEncIndex = defEncIndex;
 578         soap_globals->defEncNs = defEncNs;
 579         soap_globals->typemap = NULL;
 580         soap_globals->use_soap_error_handler = 0;
 581         soap_globals->error_code = NULL;
 582         soap_globals->error_object = NULL;
 583         soap_globals->sdl = NULL;
 584         soap_globals->soap_version = SOAP_1_1;
 585         soap_globals->mem_cache = NULL;
 586         soap_globals->ref_map = NULL;
 587 }
 588 
 589 PHP_MSHUTDOWN_FUNCTION(soap)
 590 {
 591         zend_error_cb = old_error_handler;
 592         zend_hash_destroy(&SOAP_GLOBAL(defEnc));
 593         zend_hash_destroy(&SOAP_GLOBAL(defEncIndex));
 594         zend_hash_destroy(&SOAP_GLOBAL(defEncNs));
 595         if (SOAP_GLOBAL(mem_cache)) {
 596                 zend_hash_destroy(SOAP_GLOBAL(mem_cache));
 597                 free(SOAP_GLOBAL(mem_cache));
 598         }
 599         UNREGISTER_INI_ENTRIES();
 600         return SUCCESS;
 601 }
 602 
 603 PHP_RINIT_FUNCTION(soap)
 604 {
 605         SOAP_GLOBAL(typemap) = NULL;
 606         SOAP_GLOBAL(use_soap_error_handler) = 0;
 607         SOAP_GLOBAL(error_code) = NULL;
 608         SOAP_GLOBAL(error_object) = NULL;
 609         SOAP_GLOBAL(sdl) = NULL;
 610         SOAP_GLOBAL(soap_version) = SOAP_1_1;
 611         SOAP_GLOBAL(encoding) = NULL;
 612         SOAP_GLOBAL(class_map) = NULL;
 613         SOAP_GLOBAL(features) = 0;
 614         SOAP_GLOBAL(ref_map) = NULL;
 615         return SUCCESS;
 616 }
 617 
 618 PHP_MINIT_FUNCTION(soap)
 619 {
 620         zend_class_entry ce;
 621 
 622         /* TODO: add ini entry for always use soap errors */
 623         php_soap_prepare_globals();
 624         ZEND_INIT_MODULE_GLOBALS(soap, php_soap_init_globals, NULL);
 625         REGISTER_INI_ENTRIES();
 626 
 627         /* Register SoapClient class */
 628         /* BIG NOTE : THIS EMITS AN COMPILATION WARNING UNDER ZE2 - handle_function_call deprecated.
 629                 soap_call_function_handler should be of type struct _zend_function, not (*handle_function_call).
 630         */
 631         {
 632                 zend_internal_function fe;
 633 
 634                 fe.type = ZEND_INTERNAL_FUNCTION;
 635                 fe.handler = ZEND_MN(SoapClient___call);
 636                 fe.function_name = NULL;
 637                 fe.scope = NULL;
 638                 fe.fn_flags = 0;
 639                 fe.prototype = NULL;
 640                 fe.num_args = 2;
 641                 fe.arg_info = NULL;
 642 
 643                 INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions,
 644                         (zend_function *)&fe, NULL, NULL);
 645                 soap_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 646         }
 647         /* Register SoapVar class */
 648         INIT_CLASS_ENTRY(ce, PHP_SOAP_VAR_CLASSNAME, soap_var_functions);
 649         soap_var_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 650 
 651         /* Register SoapServer class */
 652         INIT_CLASS_ENTRY(ce, PHP_SOAP_SERVER_CLASSNAME, soap_server_functions);
 653         soap_server_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 654 
 655         /* Register SoapFault class */
 656         INIT_CLASS_ENTRY(ce, PHP_SOAP_FAULT_CLASSNAME, soap_fault_functions);
 657         soap_fault_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
 658 
 659         /* Register SoapParam class */
 660         INIT_CLASS_ENTRY(ce, PHP_SOAP_PARAM_CLASSNAME, soap_param_functions);
 661         soap_param_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 662 
 663         INIT_CLASS_ENTRY(ce, PHP_SOAP_HEADER_CLASSNAME, soap_header_functions);
 664         soap_header_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
 665 
 666         le_sdl = register_list_destructors(delete_sdl, NULL);
 667         le_url = register_list_destructors(delete_url, NULL);
 668         le_service = register_list_destructors(delete_service, NULL);
 669         le_typemap = register_list_destructors(delete_hashtable, NULL);
 670 
 671         REGISTER_LONG_CONSTANT("SOAP_1_1", SOAP_1_1, CONST_CS | CONST_PERSISTENT);
 672         REGISTER_LONG_CONSTANT("SOAP_1_2", SOAP_1_2, CONST_CS | CONST_PERSISTENT);
 673 
 674         REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_SESSION", SOAP_PERSISTENCE_SESSION, CONST_CS | CONST_PERSISTENT);
 675         REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_REQUEST", SOAP_PERSISTENCE_REQUEST, CONST_CS | CONST_PERSISTENT);
 676         REGISTER_LONG_CONSTANT("SOAP_FUNCTIONS_ALL", SOAP_FUNCTIONS_ALL, CONST_CS | CONST_PERSISTENT);
 677 
 678         REGISTER_LONG_CONSTANT("SOAP_ENCODED", SOAP_ENCODED, CONST_CS | CONST_PERSISTENT);
 679         REGISTER_LONG_CONSTANT("SOAP_LITERAL", SOAP_LITERAL, CONST_CS | CONST_PERSISTENT);
 680 
 681         REGISTER_LONG_CONSTANT("SOAP_RPC", SOAP_RPC, CONST_CS | CONST_PERSISTENT);
 682         REGISTER_LONG_CONSTANT("SOAP_DOCUMENT", SOAP_DOCUMENT, CONST_CS | CONST_PERSISTENT);
 683 
 684         REGISTER_LONG_CONSTANT("SOAP_ACTOR_NEXT", SOAP_ACTOR_NEXT, CONST_CS | CONST_PERSISTENT);
 685         REGISTER_LONG_CONSTANT("SOAP_ACTOR_NONE", SOAP_ACTOR_NONE, CONST_CS | CONST_PERSISTENT);
 686         REGISTER_LONG_CONSTANT("SOAP_ACTOR_UNLIMATERECEIVER", SOAP_ACTOR_UNLIMATERECEIVER, CONST_CS | CONST_PERSISTENT);
 687 
 688         REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_ACCEPT", SOAP_COMPRESSION_ACCEPT, CONST_CS | CONST_PERSISTENT);
 689         REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_GZIP", SOAP_COMPRESSION_GZIP, CONST_CS | CONST_PERSISTENT);
 690         REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_DEFLATE", SOAP_COMPRESSION_DEFLATE, CONST_CS | CONST_PERSISTENT);
 691 
 692         REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_BASIC", SOAP_AUTHENTICATION_BASIC, CONST_CS | CONST_PERSISTENT);
 693         REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_DIGEST", SOAP_AUTHENTICATION_DIGEST, CONST_CS | CONST_PERSISTENT);
 694 
 695         REGISTER_LONG_CONSTANT("UNKNOWN_TYPE", UNKNOWN_TYPE, CONST_CS | CONST_PERSISTENT);
 696 
 697         REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT);
 698         REGISTER_LONG_CONSTANT("XSD_BOOLEAN", XSD_BOOLEAN, CONST_CS | CONST_PERSISTENT);
 699         REGISTER_LONG_CONSTANT("XSD_DECIMAL", XSD_DECIMAL, CONST_CS | CONST_PERSISTENT);
 700         REGISTER_LONG_CONSTANT("XSD_FLOAT", XSD_FLOAT, CONST_CS | CONST_PERSISTENT);
 701         REGISTER_LONG_CONSTANT("XSD_DOUBLE", XSD_DOUBLE, CONST_CS | CONST_PERSISTENT);
 702         REGISTER_LONG_CONSTANT("XSD_DURATION", XSD_DURATION, CONST_CS | CONST_PERSISTENT);
 703         REGISTER_LONG_CONSTANT("XSD_DATETIME", XSD_DATETIME, CONST_CS | CONST_PERSISTENT);
 704         REGISTER_LONG_CONSTANT("XSD_TIME", XSD_TIME, CONST_CS | CONST_PERSISTENT);
 705         REGISTER_LONG_CONSTANT("XSD_DATE", XSD_DATE, CONST_CS | CONST_PERSISTENT);
 706         REGISTER_LONG_CONSTANT("XSD_GYEARMONTH", XSD_GYEARMONTH, CONST_CS | CONST_PERSISTENT);
 707         REGISTER_LONG_CONSTANT("XSD_GYEAR", XSD_GYEAR, CONST_CS | CONST_PERSISTENT);
 708         REGISTER_LONG_CONSTANT("XSD_GMONTHDAY", XSD_GMONTHDAY, CONST_CS | CONST_PERSISTENT);
 709         REGISTER_LONG_CONSTANT("XSD_GDAY", XSD_GDAY, CONST_CS | CONST_PERSISTENT);
 710         REGISTER_LONG_CONSTANT("XSD_GMONTH", XSD_GMONTH, CONST_CS | CONST_PERSISTENT);
 711         REGISTER_LONG_CONSTANT("XSD_HEXBINARY", XSD_HEXBINARY, CONST_CS | CONST_PERSISTENT);
 712         REGISTER_LONG_CONSTANT("XSD_BASE64BINARY", XSD_BASE64BINARY, CONST_CS | CONST_PERSISTENT);
 713         REGISTER_LONG_CONSTANT("XSD_ANYURI", XSD_ANYURI, CONST_CS | CONST_PERSISTENT);
 714         REGISTER_LONG_CONSTANT("XSD_QNAME", XSD_QNAME, CONST_CS | CONST_PERSISTENT);
 715         REGISTER_LONG_CONSTANT("XSD_NOTATION", XSD_NOTATION, CONST_CS | CONST_PERSISTENT);
 716         REGISTER_LONG_CONSTANT("XSD_NORMALIZEDSTRING", XSD_NORMALIZEDSTRING, CONST_CS | CONST_PERSISTENT);
 717         REGISTER_LONG_CONSTANT("XSD_TOKEN", XSD_TOKEN, CONST_CS | CONST_PERSISTENT);
 718         REGISTER_LONG_CONSTANT("XSD_LANGUAGE", XSD_LANGUAGE, CONST_CS | CONST_PERSISTENT);
 719         REGISTER_LONG_CONSTANT("XSD_NMTOKEN", XSD_NMTOKEN, CONST_CS | CONST_PERSISTENT);
 720         REGISTER_LONG_CONSTANT("XSD_NAME", XSD_NAME, CONST_CS | CONST_PERSISTENT);
 721         REGISTER_LONG_CONSTANT("XSD_NCNAME", XSD_NCNAME, CONST_CS | CONST_PERSISTENT);
 722         REGISTER_LONG_CONSTANT("XSD_ID", XSD_ID, CONST_CS | CONST_PERSISTENT);
 723         REGISTER_LONG_CONSTANT("XSD_IDREF", XSD_IDREF, CONST_CS | CONST_PERSISTENT);
 724         REGISTER_LONG_CONSTANT("XSD_IDREFS", XSD_IDREFS, CONST_CS | CONST_PERSISTENT);
 725         REGISTER_LONG_CONSTANT("XSD_ENTITY", XSD_ENTITY, CONST_CS | CONST_PERSISTENT);
 726         REGISTER_LONG_CONSTANT("XSD_ENTITIES", XSD_ENTITIES, CONST_CS | CONST_PERSISTENT);
 727         REGISTER_LONG_CONSTANT("XSD_INTEGER", XSD_INTEGER, CONST_CS | CONST_PERSISTENT);
 728         REGISTER_LONG_CONSTANT("XSD_NONPOSITIVEINTEGER", XSD_NONPOSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
 729         REGISTER_LONG_CONSTANT("XSD_NEGATIVEINTEGER", XSD_NEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
 730         REGISTER_LONG_CONSTANT("XSD_LONG", XSD_LONG, CONST_CS | CONST_PERSISTENT);
 731         REGISTER_LONG_CONSTANT("XSD_INT", XSD_INT, CONST_CS | CONST_PERSISTENT);
 732         REGISTER_LONG_CONSTANT("XSD_SHORT", XSD_SHORT, CONST_CS | CONST_PERSISTENT);
 733         REGISTER_LONG_CONSTANT("XSD_BYTE", XSD_BYTE, CONST_CS | CONST_PERSISTENT);
 734         REGISTER_LONG_CONSTANT("XSD_NONNEGATIVEINTEGER", XSD_NONNEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
 735         REGISTER_LONG_CONSTANT("XSD_UNSIGNEDLONG", XSD_UNSIGNEDLONG, CONST_CS | CONST_PERSISTENT);
 736         REGISTER_LONG_CONSTANT("XSD_UNSIGNEDINT", XSD_UNSIGNEDINT, CONST_CS | CONST_PERSISTENT);
 737         REGISTER_LONG_CONSTANT("XSD_UNSIGNEDSHORT", XSD_UNSIGNEDSHORT, CONST_CS | CONST_PERSISTENT);
 738         REGISTER_LONG_CONSTANT("XSD_UNSIGNEDBYTE", XSD_UNSIGNEDBYTE, CONST_CS | CONST_PERSISTENT);
 739         REGISTER_LONG_CONSTANT("XSD_POSITIVEINTEGER", XSD_POSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
 740         REGISTER_LONG_CONSTANT("XSD_NMTOKENS", XSD_NMTOKENS, CONST_CS | CONST_PERSISTENT);
 741         REGISTER_LONG_CONSTANT("XSD_ANYTYPE", XSD_ANYTYPE, CONST_CS | CONST_PERSISTENT);
 742         REGISTER_LONG_CONSTANT("XSD_ANYXML", XSD_ANYXML, CONST_CS | CONST_PERSISTENT);
 743 
 744         REGISTER_LONG_CONSTANT("APACHE_MAP", APACHE_MAP, CONST_CS | CONST_PERSISTENT);
 745 
 746         REGISTER_LONG_CONSTANT("SOAP_ENC_OBJECT", SOAP_ENC_OBJECT, CONST_CS | CONST_PERSISTENT);
 747         REGISTER_LONG_CONSTANT("SOAP_ENC_ARRAY", SOAP_ENC_ARRAY, CONST_CS | CONST_PERSISTENT);
 748 
 749         REGISTER_LONG_CONSTANT("XSD_1999_TIMEINSTANT", XSD_1999_TIMEINSTANT, CONST_CS | CONST_PERSISTENT);
 750 
 751         REGISTER_STRING_CONSTANT("XSD_NAMESPACE", XSD_NAMESPACE, CONST_CS | CONST_PERSISTENT);
 752         REGISTER_STRING_CONSTANT("XSD_1999_NAMESPACE", XSD_1999_NAMESPACE,  CONST_CS | CONST_PERSISTENT);
 753 
 754         REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT);
 755         REGISTER_LONG_CONSTANT("SOAP_WAIT_ONE_WAY_CALLS", SOAP_WAIT_ONE_WAY_CALLS, CONST_CS | CONST_PERSISTENT);
 756         REGISTER_LONG_CONSTANT("SOAP_USE_XSI_ARRAY_TYPE", SOAP_USE_XSI_ARRAY_TYPE, CONST_CS | CONST_PERSISTENT);
 757 
 758         REGISTER_LONG_CONSTANT("WSDL_CACHE_NONE",   WSDL_CACHE_NONE,   CONST_CS | CONST_PERSISTENT);
 759         REGISTER_LONG_CONSTANT("WSDL_CACHE_DISK",   WSDL_CACHE_DISK,   CONST_CS | CONST_PERSISTENT);
 760         REGISTER_LONG_CONSTANT("WSDL_CACHE_MEMORY", WSDL_CACHE_MEMORY, CONST_CS | CONST_PERSISTENT);
 761         REGISTER_LONG_CONSTANT("WSDL_CACHE_BOTH",   WSDL_CACHE_BOTH,   CONST_CS | CONST_PERSISTENT);
 762 
 763         /* New SOAP SSL Method Constants */
 764         REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_TLS",    SOAP_SSL_METHOD_TLS,    CONST_CS | CONST_PERSISTENT);
 765         REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv2",  SOAP_SSL_METHOD_SSLv2,  CONST_CS | CONST_PERSISTENT);
 766         REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv3",  SOAP_SSL_METHOD_SSLv3,  CONST_CS | CONST_PERSISTENT);
 767         REGISTER_LONG_CONSTANT("SOAP_SSL_METHOD_SSLv23", SOAP_SSL_METHOD_SSLv23, CONST_CS | CONST_PERSISTENT);
 768 
 769         old_error_handler = zend_error_cb;
 770         zend_error_cb = soap_error_handler;
 771 
 772         return SUCCESS;
 773 }
 774 
 775 PHP_MINFO_FUNCTION(soap)
 776 {
 777         php_info_print_table_start();
 778         php_info_print_table_row(2, "Soap Client", "enabled");
 779         php_info_print_table_row(2, "Soap Server", "enabled");
 780         php_info_print_table_end();
 781         DISPLAY_INI_ENTRIES();
 782 }
 783 
 784 
 785 /* {{{ proto object SoapParam::SoapParam ( mixed data, string name)
 786    SoapParam constructor */
 787 PHP_METHOD(SoapParam, SoapParam)
 788 {
 789         zval *data;
 790         char *name;
 791         int name_length;
 792 
 793         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &data, &name, &name_length) == FAILURE) {
 794                 return;
 795         }
 796         if (name_length == 0) {
 797                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter name");
 798                 return;
 799         }
 800 
 801         add_property_stringl(this_ptr, "param_name", name, name_length, 1);
 802         add_property_zval(this_ptr, "param_data", data);
 803 }
 804 /* }}} */
 805 
 806 
 807 /* {{{ proto object SoapHeader::SoapHeader ( string namespace, string name [, mixed data [, bool mustUnderstand [, mixed actor]]])
 808    SoapHeader constructor */
 809 PHP_METHOD(SoapHeader, SoapHeader)
 810 {
 811         zval *data = NULL, *actor = NULL;
 812         char *name, *ns;
 813         int name_len, ns_len;
 814         zend_bool must_understand = 0;
 815 
 816         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|zbz", &ns, &ns_len, &name, &name_len, &data, &must_understand, &actor) == FAILURE) {
 817                 return;
 818         }
 819         if (ns_len == 0) {
 820                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid namespace");
 821                 return;
 822         }
 823         if (name_len == 0) {
 824                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid header name");
 825                 return;
 826         }
 827 
 828         add_property_stringl(this_ptr, "namespace", ns, ns_len, 1);
 829         add_property_stringl(this_ptr, "name", name, name_len, 1);
 830         if (data) {
 831                 add_property_zval(this_ptr, "data", data);
 832         }
 833         add_property_bool(this_ptr, "mustUnderstand", must_understand);
 834         if (actor == NULL) {
 835         } else if (Z_TYPE_P(actor) == IS_LONG &&
 836           (Z_LVAL_P(actor) == SOAP_ACTOR_NEXT ||
 837            Z_LVAL_P(actor) == SOAP_ACTOR_NONE ||
 838            Z_LVAL_P(actor) == SOAP_ACTOR_UNLIMATERECEIVER)) {
 839                 add_property_long(this_ptr, "actor", Z_LVAL_P(actor));
 840         } else if (Z_TYPE_P(actor) == IS_STRING && Z_STRLEN_P(actor) > 0) {
 841                 add_property_stringl(this_ptr, "actor", Z_STRVAL_P(actor), Z_STRLEN_P(actor), 1);
 842         } else {
 843                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid actor");
 844         }
 845 }
 846 
 847 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
 848    SoapFault constructor */
 849 PHP_METHOD(SoapFault, SoapFault)
 850 {
 851         char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL, *name = NULL, *fault_code_ns = NULL;
 852         int fault_string_len, fault_actor_len = 0, name_len = 0, fault_code_len = 0;
 853         zval *code = NULL, *details = NULL, *headerfault = NULL;
 854 
 855         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|s!z!s!z",
 856                 &code,
 857                 &fault_string, &fault_string_len,
 858                 &fault_actor, &fault_actor_len,
 859                 &details, &name, &name_len, &headerfault) == FAILURE) {
 860                 return;
 861         }
 862 
 863         if (Z_TYPE_P(code) == IS_NULL) {
 864         } else if (Z_TYPE_P(code) == IS_STRING) {
 865                 fault_code = Z_STRVAL_P(code);
 866                 fault_code_len = Z_STRLEN_P(code);
 867         } else if (Z_TYPE_P(code) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(code)) == 2) {
 868                 zval **t_ns, **t_code;
 869 
 870                 zend_hash_internal_pointer_reset(Z_ARRVAL_P(code));
 871                 zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_ns);
 872                 zend_hash_move_forward(Z_ARRVAL_P(code));
 873                 zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_code);
 874                 if (Z_TYPE_PP(t_ns) == IS_STRING && Z_TYPE_PP(t_code) == IS_STRING) {
 875                   fault_code_ns = Z_STRVAL_PP(t_ns);
 876                   fault_code = Z_STRVAL_PP(t_code);
 877                   fault_code_len = Z_STRLEN_PP(t_code);
 878                 } else {
 879                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
 880                         return;
 881                 }
 882         } else  {
 883                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
 884                 return;
 885         }
 886         if (fault_code != NULL && fault_code_len == 0) {
 887                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
 888                 return;
 889         }
 890         if (name != NULL && name_len == 0) {
 891                 name = NULL;
 892         }
 893 
 894         set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name TSRMLS_CC);
 895         if (headerfault != NULL) {
 896                 add_property_zval(this_ptr, "headerfault", headerfault);
 897         }
 898 }
 899 /* }}} */
 900 
 901 
 902 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
 903    SoapFault constructor */
 904 PHP_METHOD(SoapFault, __toString)
 905 {
 906         zval *faultcode, *faultstring, *file, *line, *trace;
 907         char *str;
 908         int len;
 909         zend_fcall_info fci;
 910         zval fname;
 911 
 912         if (zend_parse_parameters_none() == FAILURE) {
 913                 return;
 914         }
 915 
 916         faultcode   = zend_read_property(soap_fault_class_entry, this_ptr, "faultcode", sizeof("faultcode")-1, 1 TSRMLS_CC);
 917         faultstring = zend_read_property(soap_fault_class_entry, this_ptr, "faultstring", sizeof("faultstring")-1, 1 TSRMLS_CC);
 918         file = zend_read_property(soap_fault_class_entry, this_ptr, "file", sizeof("file")-1, 1 TSRMLS_CC);
 919         line = zend_read_property(soap_fault_class_entry, this_ptr, "line", sizeof("line")-1, 1 TSRMLS_CC);
 920 
 921         ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
 922 
 923         fci.size = sizeof(fci);
 924         fci.function_table = &Z_OBJCE_P(getThis())->function_table;
 925         fci.function_name = &fname;
 926         fci.symbol_table = NULL;
 927         fci.object_ptr = getThis();
 928         fci.retval_ptr_ptr = &trace;
 929         fci.param_count = 0;
 930         fci.params = NULL;
 931         fci.no_separation = 1;
 932 
 933         zend_call_function(&fci, NULL TSRMLS_CC);
 934 
 935         convert_to_string(faultcode);
 936         convert_to_string(faultstring);
 937         convert_to_string(file);
 938         convert_to_long(line);
 939         convert_to_string(trace);
 940 
 941         len = spprintf(&str, 0, "SoapFault exception: [%s] %s in %s:%ld\nStack trace:\n%s",
 942                        Z_STRVAL_P(faultcode), Z_STRVAL_P(faultstring), Z_STRVAL_P(file), Z_LVAL_P(line),
 943                        Z_STRLEN_P(trace) ? Z_STRVAL_P(trace) : "#0 {main}\n");
 944 
 945         zval_ptr_dtor(&trace);
 946 
 947         RETURN_STRINGL(str, len, 0);
 948 }
 949 /* }}} */
 950 
 951 /* {{{ proto object SoapVar::SoapVar ( mixed data, int encoding [, string type_name [, string type_namespace [, string node_name [, string node_namespace]]]])
 952    SoapVar constructor */
 953 PHP_METHOD(SoapVar, SoapVar)
 954 {
 955         zval *data, *type;
 956         char *stype = NULL, *ns = NULL, *name = NULL, *namens = NULL;
 957         int stype_len = 0, ns_len = 0, name_len = 0, namens_len = 0;
 958 
 959         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z!z|ssss", &data, &type, &stype, &stype_len, &ns, &ns_len, &name, &name_len, &namens, &namens_len) == FAILURE) {
 960                 return;
 961         }
 962 
 963         if (Z_TYPE_P(type) == IS_NULL) {
 964                 add_property_long(this_ptr, "enc_type", UNKNOWN_TYPE);
 965         } else {
 966                 if (zend_hash_index_exists(&SOAP_GLOBAL(defEncIndex), Z_LVAL_P(type))) {
 967                         add_property_long(this_ptr, "enc_type", Z_LVAL_P(type));
 968                 } else {
 969                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type ID");
 970                         return;
 971                 }
 972         }
 973 
 974         if (data) {
 975                 add_property_zval(this_ptr, "enc_value", data);
 976         }
 977 
 978         if (stype && stype_len > 0) {
 979                 add_property_stringl(this_ptr, "enc_stype", stype, stype_len, 1);
 980         }
 981         if (ns && ns_len > 0) {
 982                 add_property_stringl(this_ptr, "enc_ns", ns, ns_len, 1);
 983         }
 984         if (name && name_len > 0) {
 985                 add_property_stringl(this_ptr, "enc_name", name, name_len, 1);
 986         }
 987         if (namens && namens_len > 0) {
 988                 add_property_stringl(this_ptr, "enc_namens", namens, namens_len, 1);
 989         }
 990 }
 991 /* }}} */
 992 
 993 
 994 static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
 995 {
 996         zval **tmp;
 997         HashTable *ht2;
 998         HashPosition pos1, pos2;
 999         HashTable *typemap = NULL;
1000 
1001         zend_hash_internal_pointer_reset_ex(ht, &pos1);
1002         while (zend_hash_get_current_data_ex(ht, (void**)&tmp, &pos1) == SUCCESS) {
1003                 char *type_name = NULL;
1004                 char *type_ns = NULL;
1005                 zval *to_xml = NULL;
1006                 zval *to_zval = NULL;
1007                 encodePtr enc, new_enc;
1008 
1009                 if (Z_TYPE_PP(tmp) != IS_ARRAY) {
1010                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong 'typemap' option");
1011                         return NULL;
1012                 }
1013                 ht2 = Z_ARRVAL_PP(tmp);
1014 
1015                 zend_hash_internal_pointer_reset_ex(ht2, &pos2);
1016                 while (zend_hash_get_current_data_ex(ht2, (void**)&tmp, &pos2) == SUCCESS) {
1017                         char *name = NULL;
1018                         unsigned int name_len;
1019                         ulong index;
1020 
1021                         zend_hash_get_current_key_ex(ht2, &name, &name_len, &index, 0, &pos2);
1022                         if (name) {
1023                                 if (name_len == sizeof("type_name") &&
1024                                     strncmp(name, "type_name", sizeof("type_name")-1) == 0) {
1025                                         if (Z_TYPE_PP(tmp) == IS_STRING) {
1026                                                 type_name = Z_STRVAL_PP(tmp);
1027                                         } else if (Z_TYPE_PP(tmp) != IS_NULL) {
1028                                         }
1029                                 } else if (name_len == sizeof("type_ns") &&
1030                                     strncmp(name, "type_ns", sizeof("type_ns")-1) == 0) {
1031                                         if (Z_TYPE_PP(tmp) == IS_STRING) {
1032                                                 type_ns = Z_STRVAL_PP(tmp);
1033                                         } else if (Z_TYPE_PP(tmp) != IS_NULL) {
1034                                         }
1035                                 } else if (name_len == sizeof("to_xml") &&
1036                                     strncmp(name, "to_xml", sizeof("to_xml")-1) == 0) {
1037                                         to_xml = *tmp;
1038                                 } else if (name_len == sizeof("from_xml") &&
1039                                     strncmp(name, "from_xml", sizeof("from_xml")-1) == 0) {
1040                                         to_zval = *tmp;
1041                                 }
1042                         }
1043                         zend_hash_move_forward_ex(ht2, &pos2);
1044                 }
1045 
1046                 if (type_name) {
1047                         smart_str nscat = {0};
1048 
1049                         if (type_ns) {
1050                                 enc = get_encoder(sdl, type_ns, type_name);
1051                         } else {
1052                                 enc = get_encoder_ex(sdl, type_name, strlen(type_name));
1053                         }
1054 
1055                         new_enc = emalloc(sizeof(encode));
1056                         memset(new_enc, 0, sizeof(encode));
1057 
1058                         if (enc) {
1059                                 new_enc->details.type = enc->details.type;
1060                                 new_enc->details.ns = estrdup(enc->details.ns);
1061                                 new_enc->details.type_str = estrdup(enc->details.type_str);
1062                                 new_enc->details.sdl_type = enc->details.sdl_type;
1063                         } else {
1064                                 enc = get_conversion(UNKNOWN_TYPE);
1065                                 new_enc->details.type = enc->details.type;
1066                                 if (type_ns) {
1067                                         new_enc->details.ns = estrdup(type_ns);
1068                                 }
1069                                 new_enc->details.type_str = estrdup(type_name);
1070                         }
1071                         new_enc->to_xml = enc->to_xml;
1072                         new_enc->to_zval = enc->to_zval;
1073                         new_enc->details.map = emalloc(sizeof(soapMapping));
1074                         memset(new_enc->details.map, 0, sizeof(soapMapping));
1075                         if (to_xml) {
1076                                 zval_add_ref(&to_xml);
1077                                 new_enc->details.map->to_xml = to_xml;
1078                                 new_enc->to_xml = to_xml_user;
1079                         } else if (enc->details.map && enc->details.map->to_xml) {
1080                                 zval_add_ref(&enc->details.map->to_xml);
1081                                 new_enc->details.map->to_xml = enc->details.map->to_xml;
1082                         }
1083                         if (to_zval) {
1084                                 zval_add_ref(&to_zval);
1085                                 new_enc->details.map->to_zval = to_zval;
1086                                 new_enc->to_zval = to_zval_user;
1087                         } else if (enc->details.map && enc->details.map->to_zval) {
1088                                 zval_add_ref(&enc->details.map->to_zval);
1089                                 new_enc->details.map->to_zval = enc->details.map->to_zval;
1090                         }
1091                         if (!typemap) {
1092                                 typemap = emalloc(sizeof(HashTable));
1093                                 zend_hash_init(typemap, 0, NULL, delete_encoder, 0);
1094                         }
1095 
1096                         if (type_ns) {
1097                                 smart_str_appends(&nscat, type_ns);
1098                                 smart_str_appendc(&nscat, ':');
1099                         }
1100                         smart_str_appends(&nscat, type_name);
1101                         smart_str_0(&nscat);
1102                         zend_hash_update(typemap, nscat.c, nscat.len + 1, &new_enc, sizeof(encodePtr), NULL);
1103                         smart_str_free(&nscat);
1104                 }
1105                 zend_hash_move_forward_ex(ht, &pos1);
1106         }
1107         return typemap;
1108 }
1109 
1110 
1111 /* {{{ proto object SoapServer::SoapServer ( mixed wsdl [, array options])
1112    SoapServer constructor */
1113 PHP_METHOD(SoapServer, SoapServer)
1114 {
1115         soapServicePtr service;
1116         zval *wsdl = NULL, *options = NULL;
1117         int ret;
1118         int version = SOAP_1_1;
1119         long cache_wsdl;
1120         HashTable *typemap_ht = NULL;
1121 
1122         SOAP_SERVER_BEGIN_CODE();
1123 
1124         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
1125                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
1126         }
1127 
1128         if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
1129                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
1130         }
1131 
1132         service = emalloc(sizeof(soapService));
1133         memset(service, 0, sizeof(soapService));
1134         service->send_errors = 1;
1135 
1136         cache_wsdl = SOAP_GLOBAL(cache_enabled) ? SOAP_GLOBAL(cache_mode) : 0;
1137 
1138         if (options != NULL) {
1139                 HashTable *ht = Z_ARRVAL_P(options);
1140                 zval **tmp;
1141 
1142                 if (zend_hash_find(ht, "soap_version", sizeof("soap_version"), (void**)&tmp) == SUCCESS) {
1143                         if (Z_TYPE_PP(tmp) == IS_LONG &&
1144                             (Z_LVAL_PP(tmp) == SOAP_1_1 || Z_LVAL_PP(tmp) == SOAP_1_2)) {
1145                                 version = Z_LVAL_PP(tmp);
1146                         } else {
1147                                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'soap_version' option must be SOAP_1_1 or SOAP_1_2");
1148                         }
1149                 }
1150 
1151                 if (zend_hash_find(ht, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
1152                     Z_TYPE_PP(tmp) == IS_STRING) {
1153                         service->uri = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
1154                 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
1155                         php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
1156                 }
1157 
1158                 if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS &&
1159                     Z_TYPE_PP(tmp) == IS_STRING) {
1160                         service->actor = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
1161                 }
1162 
1163                 if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
1164                     Z_TYPE_PP(tmp) == IS_STRING) {
1165                         xmlCharEncodingHandlerPtr encoding;
1166 
1167                         encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
1168                         if (encoding == NULL) {
1169                                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
1170                         } else {
1171                           service->encoding = encoding;
1172                         }
1173                 }
1174 
1175                 if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
1176                         Z_TYPE_PP(tmp) == IS_ARRAY) {
1177                         zval *ztmp;
1178 
1179                         ALLOC_HASHTABLE(service->class_map);
1180                         zend_hash_init(service->class_map, zend_hash_num_elements((*tmp)->value.ht), NULL, ZVAL_PTR_DTOR, 0);
1181                         zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *));
1182                 }
1183 
1184                 if (zend_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS &&
1185                         Z_TYPE_PP(tmp) == IS_ARRAY &&
1186                         zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) {
1187                         typemap_ht = Z_ARRVAL_PP(tmp);
1188                 }
1189 
1190                 if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
1191                         Z_TYPE_PP(tmp) == IS_LONG) {
1192                         service->features = Z_LVAL_PP(tmp);
1193                 }
1194 
1195                 if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
1196                     Z_TYPE_PP(tmp) == IS_LONG) {
1197                         cache_wsdl = Z_LVAL_PP(tmp);
1198                 }
1199 
1200                 if (zend_hash_find(ht, "send_errors", sizeof("send_errors"), (void**)&tmp) == SUCCESS &&
1201                     (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG)) {
1202                         service->send_errors = Z_LVAL_PP(tmp);
1203                 }
1204 
1205         } else if (Z_TYPE_P(wsdl) == IS_NULL) {
1206                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
1207         }
1208 
1209         service->version = version;
1210         service->type = SOAP_FUNCTIONS;
1211         service->soap_functions.functions_all = FALSE;
1212         service->soap_functions.ft = emalloc(sizeof(HashTable));
1213         zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
1214 
1215         if (Z_TYPE_P(wsdl) != IS_NULL) {
1216                 service->sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
1217                 if (service->uri == NULL) {
1218                         if (service->sdl->target_ns) {
1219                                 service->uri = estrdup(service->sdl->target_ns);
1220                         } else {
1221                                 /*FIXME*/
1222                                 service->uri = estrdup("http://unknown-uri/");
1223                         }
1224                 }
1225         }
1226 
1227         if (typemap_ht) {
1228                 service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC);
1229         }
1230 
1231         ret = zend_list_insert(service, le_service TSRMLS_CC);
1232         add_property_resource(this_ptr, "service", ret);
1233 
1234         SOAP_SERVER_END_CODE();
1235 }
1236 /* }}} */
1237 
1238 
1239 /* {{{ proto object SoapServer::setPersistence ( int mode )
1240    Sets persistence mode of SoapServer */
1241 PHP_METHOD(SoapServer, setPersistence)
1242 {
1243         soapServicePtr service;
1244         long value;
1245 
1246         SOAP_SERVER_BEGIN_CODE();
1247 
1248         FETCH_THIS_SERVICE(service);
1249 
1250         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) != FAILURE) {
1251                 if (service->type == SOAP_CLASS) {
1252                         if (value == SOAP_PERSISTENCE_SESSION ||
1253                                 value == SOAP_PERSISTENCE_REQUEST) {
1254                                 service->soap_class.persistance = value;
1255                         } else {
1256                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set persistence with bogus value (%ld)", value);
1257                                 return;
1258                         }
1259                 } else {
1260                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set persistence when you are using you SOAP SERVER in function mode, no persistence needed");
1261                         return;
1262                 }
1263         }
1264 
1265         SOAP_SERVER_END_CODE();
1266 }
1267 /* }}} */
1268 
1269 
1270 /* {{{ proto void SoapServer::setClass(string class_name [, mixed args])
1271    Sets class which will handle SOAP requests */
1272 PHP_METHOD(SoapServer, setClass)
1273 {
1274         soapServicePtr service;
1275         char *classname;
1276         zend_class_entry **ce;
1277 
1278         int classname_len, found, num_args = 0;
1279         zval ***argv = NULL;
1280 
1281         SOAP_SERVER_BEGIN_CODE();
1282 
1283         FETCH_THIS_SERVICE(service);
1284 
1285         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s*", &classname, &classname_len, &argv, &num_args) == FAILURE) {
1286                 return;
1287         }
1288 
1289         found = zend_lookup_class(classname, classname_len, &ce TSRMLS_CC);
1290 
1291         if (found != FAILURE) {
1292                 service->type = SOAP_CLASS;
1293                 service->soap_class.ce = *ce;
1294 
1295                 service->soap_class.persistance = SOAP_PERSISTENCE_REQUEST;
1296                 service->soap_class.argc = num_args;
1297                 if (service->soap_class.argc > 0) {
1298                         int i;
1299                         service->soap_class.argv = safe_emalloc(sizeof(zval), service->soap_class.argc, 0);
1300                         for (i = 0;i < service->soap_class.argc;i++) {
1301                                 service->soap_class.argv[i] = *(argv[i]);
1302                                 zval_add_ref(&service->soap_class.argv[i]);
1303                         }
1304                 }
1305         } else {
1306                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set a non existent class (%s)", classname);
1307                 return;
1308         }
1309 
1310         if (argv) {
1311                 efree(argv);
1312         }
1313 
1314         SOAP_SERVER_END_CODE();
1315 }
1316 /* }}} */
1317 
1318 
1319 /* {{{ proto void SoapServer::setObject(object)
1320    Sets object which will handle SOAP requests */
1321 PHP_METHOD(SoapServer, setObject)
1322 {
1323         soapServicePtr service;
1324         zval *obj;
1325 
1326         SOAP_SERVER_BEGIN_CODE();
1327 
1328         FETCH_THIS_SERVICE(service);
1329 
1330         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
1331                 return;
1332         }
1333 
1334         service->type = SOAP_OBJECT;
1335 
1336         MAKE_STD_ZVAL(service->soap_object);
1337         MAKE_COPY_ZVAL(&obj, service->soap_object);
1338 
1339         SOAP_SERVER_END_CODE();
1340 }
1341 /* }}} */
1342 
1343 
1344 /* {{{ proto array SoapServer::getFunctions(void)
1345    Returns list of defined functions */
1346 PHP_METHOD(SoapServer, getFunctions)
1347 {
1348         soapServicePtr  service;
1349         HashTable      *ft = NULL;
1350 
1351         SOAP_SERVER_BEGIN_CODE();
1352 
1353         if (zend_parse_parameters_none() == FAILURE) {
1354                 return;
1355         }
1356 
1357         FETCH_THIS_SERVICE(service);
1358 
1359         array_init(return_value);
1360         if (service->type == SOAP_OBJECT) {
1361                 ft = &(Z_OBJCE_P(service->soap_object)->function_table);
1362         } else if (service->type == SOAP_CLASS) {
1363                 ft = &service->soap_class.ce->function_table;
1364         } else if (service->soap_functions.functions_all == TRUE) {
1365                 ft = EG(function_table);
1366         } else if (service->soap_functions.ft != NULL) {
1367                 zval **name;
1368                 HashPosition pos;
1369 
1370                 zend_hash_internal_pointer_reset_ex(service->soap_functions.ft, &pos);
1371                 while (zend_hash_get_current_data_ex(service->soap_functions.ft, (void **)&name, &pos) != FAILURE) {
1372                         add_next_index_string(return_value, Z_STRVAL_PP(name), 1);
1373                         zend_hash_move_forward_ex(service->soap_functions.ft, &pos);
1374                 }
1375         }
1376         if (ft != NULL) {
1377                 zend_function *f;
1378                 HashPosition pos;
1379                 zend_hash_internal_pointer_reset_ex(ft, &pos);
1380                 while (zend_hash_get_current_data_ex(ft, (void **)&f, &pos) != FAILURE) {
1381                         if ((service->type != SOAP_OBJECT && service->type != SOAP_CLASS) || (f->common.fn_flags & ZEND_ACC_PUBLIC)) {
1382                                 add_next_index_string(return_value, f->common.function_name, 1);
1383                         }
1384                         zend_hash_move_forward_ex(ft, &pos);
1385                 }
1386         }
1387 
1388         SOAP_SERVER_END_CODE();
1389 }
1390 /* }}} */
1391 
1392 
1393 /* {{{ proto void SoapServer::addFunction(mixed functions)
1394    Adds one or several functions those will handle SOAP requests */
1395 PHP_METHOD(SoapServer, addFunction)
1396 {
1397         soapServicePtr service;
1398         zval *function_name, *function_copy;
1399         HashPosition pos;
1400 
1401         SOAP_SERVER_BEGIN_CODE();
1402 
1403         FETCH_THIS_SERVICE(service);
1404 
1405         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE) {
1406                 return;
1407         }
1408 
1409         /* TODO: could use zend_is_callable here */
1410 
1411         if (function_name->type == IS_ARRAY) {
1412                 if (service->type == SOAP_FUNCTIONS) {
1413                         zval **tmp_function, *function_copy;
1414 
1415                         if (service->soap_functions.ft == NULL) {
1416                                 service->soap_functions.functions_all = FALSE;
1417                                 service->soap_functions.ft = emalloc(sizeof(HashTable));
1418                                 zend_hash_init(service->soap_functions.ft, zend_hash_num_elements(Z_ARRVAL_P(function_name)), NULL, ZVAL_PTR_DTOR, 0);
1419                         }
1420 
1421                         zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(function_name), &pos);
1422                         while (zend_hash_get_current_data_ex(Z_ARRVAL_P(function_name), (void **)&tmp_function, &pos) != FAILURE) {
1423                                 char *key;
1424                                 int   key_len;
1425                                 zend_function *f;
1426 
1427                                 if (Z_TYPE_PP(tmp_function) != IS_STRING) {
1428                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a function that isn't a string");
1429                                         return;
1430                                 }
1431 
1432                                 key_len = Z_STRLEN_PP(tmp_function);
1433                                 key = emalloc(key_len + 1);
1434                                 zend_str_tolower_copy(key, Z_STRVAL_PP(tmp_function), key_len);
1435 
1436                                 if (zend_hash_find(EG(function_table), key, key_len+1, (void**)&f) == FAILURE) {
1437                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a non existent function '%s'", Z_STRVAL_PP(tmp_function));
1438                                         return;
1439                                 }
1440 
1441                                 MAKE_STD_ZVAL(function_copy);
1442                                 ZVAL_STRING(function_copy, f->common.function_name, 1);
1443                                 zend_hash_update(service->soap_functions.ft, key, key_len+1, &function_copy, sizeof(zval *), NULL);
1444 
1445                                 efree(key);
1446                                 zend_hash_move_forward_ex(Z_ARRVAL_P(function_name), &pos);
1447                         }
1448                 }
1449         } else if (function_name->type == IS_STRING) {
1450                 char *key;
1451                 int   key_len;
1452                 zend_function *f;
1453 
1454                 key_len = Z_STRLEN_P(function_name);
1455                 key = emalloc(key_len + 1);
1456                 zend_str_tolower_copy(key, Z_STRVAL_P(function_name), key_len);
1457 
1458                 if (zend_hash_find(EG(function_table), key, key_len+1, (void**)&f) == FAILURE) {
1459                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a non existent function '%s'", Z_STRVAL_P(function_name));
1460                         return;
1461                 }
1462                 if (service->soap_functions.ft == NULL) {
1463                         service->soap_functions.functions_all = FALSE;
1464                         service->soap_functions.ft = emalloc(sizeof(HashTable));
1465                         zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
1466                 }
1467 
1468                 MAKE_STD_ZVAL(function_copy);
1469                 ZVAL_STRING(function_copy, f->common.function_name, 1);
1470                 zend_hash_update(service->soap_functions.ft, key, key_len+1, &function_copy, sizeof(zval *), NULL);
1471                 efree(key);
1472         } else if (function_name->type == IS_LONG) {
1473                 if (Z_LVAL_P(function_name) == SOAP_FUNCTIONS_ALL) {
1474                         if (service->soap_functions.ft != NULL) {
1475                                 zend_hash_destroy(service->soap_functions.ft);
1476                                 efree(service->soap_functions.ft);
1477                                 service->soap_functions.ft = NULL;
1478                         }
1479                         service->soap_functions.functions_all = TRUE;
1480                 } else {
1481                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value passed");
1482                         return;
1483                 }
1484         }
1485 
1486         SOAP_SERVER_END_CODE();
1487 }
1488 /* }}} */
1489 
1490 
1491 /* {{{ proto void SoapServer::handle ( [string soap_request])
1492    Handles a SOAP request */
1493 PHP_METHOD(SoapServer, handle)
1494 {
1495         int soap_version, old_soap_version;
1496         sdlPtr old_sdl = NULL;
1497         soapServicePtr service;
1498         xmlDocPtr doc_request=NULL, doc_return;
1499         zval function_name, **params, *soap_obj, *retval;
1500         char *fn_name, cont_len[30];
1501         int num_params = 0, size, i, call_status = 0;
1502         xmlChar *buf;
1503         HashTable *function_table;
1504         soapHeader *soap_headers = NULL;
1505         sdlFunctionPtr function;
1506         char *arg = NULL;
1507         int arg_len = 0;
1508         xmlCharEncodingHandlerPtr old_encoding;
1509         HashTable *old_class_map, *old_typemap;
1510         int old_features;
1511 
1512         SOAP_SERVER_BEGIN_CODE();
1513 
1514         FETCH_THIS_SERVICE(service);
1515         SOAP_GLOBAL(soap_version) = service->version;
1516 
1517         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
1518                 return;
1519         }
1520 
1521         if (SG(request_info).request_method &&
1522             strcmp(SG(request_info).request_method, "GET") == 0 &&
1523             SG(request_info).query_string &&
1524             stricmp(SG(request_info).query_string, "wsdl") == 0) {
1525 
1526                 if (service->sdl) {
1527 /*
1528                         char *hdr = emalloc(sizeof("Location: ")+strlen(service->sdl->source));
1529                         strcpy(hdr,"Location: ");
1530                         strcat(hdr,service->sdl->source);
1531                         sapi_add_header(hdr, sizeof("Location: ")+strlen(service->sdl->source)-1, 1);
1532                         efree(hdr);
1533 */
1534                         zval readfile, readfile_ret, *param;
1535 
1536                         INIT_ZVAL(readfile);
1537                         INIT_ZVAL(readfile_ret);
1538                         MAKE_STD_ZVAL(param);
1539 
1540                         sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
1541                         ZVAL_STRING(param, service->sdl->source, 1);
1542                         ZVAL_STRING(&readfile, "readfile", 1);
1543                         if (call_user_function(EG(function_table), NULL, &readfile, &readfile_ret, 1, &param  TSRMLS_CC) == FAILURE) {
1544                                 soap_server_fault("Server", "Couldn't find WSDL", NULL, NULL, NULL TSRMLS_CC);
1545                         }
1546 
1547                         zval_ptr_dtor(&param);
1548                         zval_dtor(&readfile);
1549                         zval_dtor(&readfile_ret);
1550 
1551                         SOAP_SERVER_END_CODE();
1552                         return;
1553                 } else {
1554                         soap_server_fault("Server", "WSDL generation is not supported yet", NULL, NULL, NULL TSRMLS_CC);
1555 /*
1556                         sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8"), 1);
1557                         PUTS("<?xml version=\"1.0\" ?>\n<definitions\n");
1558                         PUTS("    xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\n");
1559                         PUTS("    targetNamespace=\"");
1560                         PUTS(service->uri);
1561                         PUTS("\">\n");
1562                         PUTS("</definitions>");
1563 */
1564                         SOAP_SERVER_END_CODE();
1565                         return;
1566                 }
1567         }
1568 
1569         ALLOC_INIT_ZVAL(retval);
1570 
1571         if (php_output_start_default(TSRMLS_C) != SUCCESS) {
1572                 php_error_docref(NULL TSRMLS_CC, E_ERROR,"ob_start failed");
1573         }
1574 
1575         if (ZEND_NUM_ARGS() == 0) {
1576                 if (SG(request_info).request_body && 0 == php_stream_rewind(SG(request_info).request_body)) {
1577                         zval **server_vars, **encoding;
1578                         php_stream_filter *zf = NULL;
1579 
1580                         zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
1581                         if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
1582                             Z_TYPE_PP(server_vars) == IS_ARRAY &&
1583                             zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_CONTENT_ENCODING", sizeof("HTTP_CONTENT_ENCODING"), (void **) &encoding)==SUCCESS &&
1584                             Z_TYPE_PP(encoding) == IS_STRING) {
1585 
1586                                 if (strcmp(Z_STRVAL_PP(encoding),"gzip") == 0
1587                                 ||  strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0
1588                                 ||  strcmp(Z_STRVAL_PP(encoding),"deflate") == 0
1589                                 ) {
1590                                         zval filter_params;
1591 
1592                                         INIT_PZVAL(&filter_params);
1593                                         array_init_size(&filter_params, 1);
1594                                         add_assoc_long_ex(&filter_params, ZEND_STRS("window"), 0x2f); /* ANY WBITS */
1595 
1596                                         zf = php_stream_filter_create("zlib.inflate", &filter_params, 0 TSRMLS_CC);
1597                                         zval_dtor(&filter_params);
1598 
1599                                         if (zf) {
1600                                                 php_stream_filter_append(&SG(request_info).request_body->readfilters, zf);
1601                                         } else {
1602                                                 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't uncompress compressed request");
1603                                                 return;
1604                                         }
1605                                 } else {
1606                                         php_error_docref(NULL TSRMLS_CC, E_WARNING,"Request is compressed with unknown compression '%s'",Z_STRVAL_PP(encoding));
1607                                         return;
1608                                 }
1609                         }
1610 
1611                         doc_request = soap_xmlParseFile("php://input" TSRMLS_CC);
1612 
1613                         if (zf) {
1614                                 php_stream_filter_remove(zf, 1 TSRMLS_CC);
1615                         }
1616                 } else {
1617                         zval_ptr_dtor(&retval);
1618                         return;
1619                 }
1620         } else {
1621                 doc_request = soap_xmlParseMemory(arg,arg_len);
1622         }
1623 
1624         if (doc_request == NULL) {
1625                 soap_server_fault("Client", "Bad Request", NULL, NULL, NULL TSRMLS_CC);
1626         }
1627         if (xmlGetIntSubset(doc_request) != NULL) {
1628                 xmlNodePtr env = get_node(doc_request->children,"Envelope");
1629                 if (env && env->ns) {
1630                         if (strcmp((char*)env->ns->href, SOAP_1_1_ENV_NAMESPACE) == 0) {
1631                                 SOAP_GLOBAL(soap_version) = SOAP_1_1;
1632                         } else if (strcmp((char*)env->ns->href,SOAP_1_2_ENV_NAMESPACE) == 0) {
1633                                 SOAP_GLOBAL(soap_version) = SOAP_1_2;
1634                         }
1635                 }
1636                 xmlFreeDoc(doc_request);
1637                 soap_server_fault("Server", "DTD are not supported by SOAP", NULL, NULL, NULL TSRMLS_CC);
1638         }
1639 
1640         old_sdl = SOAP_GLOBAL(sdl);
1641         SOAP_GLOBAL(sdl) = service->sdl;
1642         old_encoding = SOAP_GLOBAL(encoding);
1643         SOAP_GLOBAL(encoding) = service->encoding;
1644         old_class_map = SOAP_GLOBAL(class_map);
1645         SOAP_GLOBAL(class_map) = service->class_map;
1646         old_typemap = SOAP_GLOBAL(typemap);
1647         SOAP_GLOBAL(typemap) = service->typemap;
1648         old_features = SOAP_GLOBAL(features);
1649         SOAP_GLOBAL(features) = service->features;
1650         old_soap_version = SOAP_GLOBAL(soap_version);
1651         function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers TSRMLS_CC);
1652         xmlFreeDoc(doc_request);
1653 
1654         if (EG(exception)) {
1655                 php_output_discard(TSRMLS_C);
1656                 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1657                     instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1658                         soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1659                 }
1660                 goto fail;
1661         }
1662 
1663         service->soap_headers_ptr = &soap_headers;
1664 
1665         soap_obj = NULL;
1666         if (service->type == SOAP_OBJECT) {
1667                 soap_obj = service->soap_object;
1668                 function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1669         } else if (service->type == SOAP_CLASS) {
1670 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1671                 /* If persistent then set soap_obj from from the previous created session (if available) */
1672                 if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
1673                         zval **tmp_soap;
1674 
1675                         if (PS(session_status) != php_session_active &&
1676                             PS(session_status) != php_session_disabled) {
1677                                 php_session_start(TSRMLS_C);
1678                         }
1679 
1680                         /* Find the soap object and assign */
1681                         if (zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), "_bogus_session_name", sizeof("_bogus_session_name"), (void **) &tmp_soap) == SUCCESS &&
1682                             Z_TYPE_PP(tmp_soap) == IS_OBJECT &&
1683                             Z_OBJCE_PP(tmp_soap) == service->soap_class.ce) {
1684                                 soap_obj = *tmp_soap;
1685                         }
1686                 }
1687 #endif
1688                 /* If new session or something weird happned */
1689                 if (soap_obj == NULL) {
1690                         zval *tmp_soap;
1691 
1692                         MAKE_STD_ZVAL(tmp_soap);
1693                         object_init_ex(tmp_soap, service->soap_class.ce);
1694 
1695                         /* Call constructor */
1696                         if (zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
1697                                 zval c_ret, constructor;
1698 
1699                                 INIT_ZVAL(c_ret);
1700                                 INIT_ZVAL(constructor);
1701 
1702                                 ZVAL_STRING(&constructor, ZEND_CONSTRUCTOR_FUNC_NAME, 1);
1703                                 if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE) {
1704                                         php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
1705                                 }
1706                                 if (EG(exception)) {
1707                                         php_output_discard(TSRMLS_C);
1708                                         if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1709                                             instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1710                                                 soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1711                                         }
1712                                         zval_dtor(&constructor);
1713                                         zval_dtor(&c_ret);
1714                                         zval_ptr_dtor(&tmp_soap);
1715                                         goto fail;
1716                                 }
1717                                 zval_dtor(&constructor);
1718                                 zval_dtor(&c_ret);
1719                         } else {
1720                                 int class_name_len = strlen(service->soap_class.ce->name);
1721                                 char *class_name = emalloc(class_name_len+1);
1722 
1723                                 memcpy(class_name, service->soap_class.ce->name,class_name_len+1);
1724                                 if (zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, php_strtolower(class_name, class_name_len), class_name_len+1)) {
1725                                         zval c_ret, constructor;
1726 
1727                                         INIT_ZVAL(c_ret);
1728                                         INIT_ZVAL(constructor);
1729 
1730                                         ZVAL_STRING(&constructor, service->soap_class.ce->name, 1);
1731                                         if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE) {
1732                                                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
1733                                         }
1734 
1735                                         if (EG(exception)) {
1736                                                 php_output_discard(TSRMLS_C);
1737                                                 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1738                                                     instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1739                                                         soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1740                                                 }
1741                                                 zval_dtor(&constructor);
1742                                                 zval_dtor(&c_ret);
1743                                                 efree(class_name);
1744                                                 zval_ptr_dtor(&tmp_soap);
1745                                                 goto fail;
1746                                         }
1747 
1748                                         zval_dtor(&constructor);
1749                                         zval_dtor(&c_ret);
1750                                 }
1751                                 efree(class_name);
1752                         }
1753 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1754                         /* If session then update session hash with new object */
1755                         if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
1756                                 zval **tmp_soap_pp;
1757                                 if (zend_hash_update(Z_ARRVAL_P(PS(http_session_vars)), "_bogus_session_name", sizeof("_bogus_session_name"), &tmp_soap, sizeof(zval *), (void **)&tmp_soap_pp) == SUCCESS) {
1758                                         soap_obj = *tmp_soap_pp;
1759                                 }
1760                         } else {
1761                                 soap_obj = tmp_soap;
1762                         }
1763 #else
1764                         soap_obj = tmp_soap;
1765 #endif
1766 
1767                 }
1768                 function_table = &((Z_OBJCE_P(soap_obj))->function_table);
1769         } else {
1770                 if (service->soap_functions.functions_all == TRUE) {
1771                         function_table = EG(function_table);
1772                 } else {
1773                         function_table = service->soap_functions.ft;
1774                 }
1775         }
1776 
1777         doc_return = NULL;
1778 
1779         /* Process soap headers */
1780         if (soap_headers != NULL) {
1781                 soapHeader *header = soap_headers;
1782                 while (header != NULL) {
1783                         soapHeader *h = header;
1784 
1785                         header = header->next;
1786 #if 0
1787                         if (service->sdl && !h->function && !h->hdr) {
1788                                 if (h->mustUnderstand) {
1789                                         soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC);
1790                                 } else {
1791                                         continue;
1792                                 }
1793                         }
1794 #endif
1795                         fn_name = estrndup(Z_STRVAL(h->function_name),Z_STRLEN(h->function_name));
1796                         if (zend_hash_exists(function_table, php_strtolower(fn_name, Z_STRLEN(h->function_name)), Z_STRLEN(h->function_name) + 1) ||
1797                             ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1798                              zend_hash_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
1799                                 if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
1800                                         call_status = call_user_function(NULL, &soap_obj, &h->function_name, &h->retval, h->num_params, h->parameters TSRMLS_CC);
1801                                 } else {
1802                                         call_status = call_user_function(EG(function_table), NULL, &h->function_name, &h->retval, h->num_params, h->parameters TSRMLS_CC);
1803                                 }
1804                                 if (call_status != SUCCESS) {
1805                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function '%s' call failed", Z_STRVAL(h->function_name));
1806                                         return;
1807                                 }
1808                                 if (Z_TYPE(h->retval) == IS_OBJECT &&
1809                                     instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry TSRMLS_CC)) {
1810                                         zval *headerfault = NULL, **tmp;
1811 
1812                                         if (zend_hash_find(Z_OBJPROP(h->retval), "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS &&
1813                                             Z_TYPE_PP(tmp) != IS_NULL) {
1814                                                 headerfault = *tmp;
1815                                         }
1816                                         php_output_discard(TSRMLS_C);
1817                                         soap_server_fault_ex(function, &h->retval, h TSRMLS_CC);
1818                                         efree(fn_name);
1819                                         if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
1820                                         goto fail;
1821                                 } else if (EG(exception)) {
1822                                         php_output_discard(TSRMLS_C);
1823                                         if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1824                                             instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1825                                                 zval *headerfault = NULL, **tmp;
1826 
1827                                                 if (zend_hash_find(Z_OBJPROP_P(EG(exception)), "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS &&
1828                                                     Z_TYPE_PP(tmp) != IS_NULL) {
1829                                                         headerfault = *tmp;
1830                                                 }
1831                                                 soap_server_fault_ex(function, EG(exception), h TSRMLS_CC);
1832                                         }
1833                                         efree(fn_name);
1834                                         if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
1835                                         goto fail;
1836                                 }
1837                         } else if (h->mustUnderstand) {
1838                                 soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC);
1839                         }
1840                         efree(fn_name);
1841                 }
1842         }
1843 
1844         fn_name = estrndup(Z_STRVAL(function_name),Z_STRLEN(function_name));
1845         if (zend_hash_exists(function_table, php_strtolower(fn_name, Z_STRLEN(function_name)), Z_STRLEN(function_name) + 1) ||
1846             ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
1847              zend_hash_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
1848                 if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
1849                         call_status = call_user_function(NULL, &soap_obj, &function_name, retval, num_params, params TSRMLS_CC);
1850                         if (service->type == SOAP_CLASS) {
1851 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1852                                 if (service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
1853                                         zval_ptr_dtor(&soap_obj);
1854                                         soap_obj = NULL;
1855                                 }
1856 #else
1857                                 zval_ptr_dtor(&soap_obj);
1858                                 soap_obj = NULL;
1859 #endif
1860                         }
1861                 } else {
1862                         call_status = call_user_function(EG(function_table), NULL, &function_name, retval, num_params, params TSRMLS_CC);
1863                 }
1864         } else {
1865                 php_error(E_ERROR, "Function '%s' doesn't exist", Z_STRVAL(function_name));
1866         }
1867         efree(fn_name);
1868 
1869         if (EG(exception)) {
1870                 php_output_discard(TSRMLS_C);
1871                 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1872                     instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1873                         soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1874                 }
1875                 if (service->type == SOAP_CLASS) {
1876 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1877                         if (soap_obj && service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
1878 #else
1879                         if (soap_obj) {
1880 #endif
1881                           zval_ptr_dtor(&soap_obj);
1882                         }
1883                 }
1884                 goto fail;
1885         }
1886 
1887         if (call_status == SUCCESS) {
1888                 char *response_name;
1889 
1890                 if (Z_TYPE_P(retval) == IS_OBJECT &&
1891                     instanceof_function(Z_OBJCE_P(retval), soap_fault_class_entry TSRMLS_CC)) {
1892                         php_output_discard(TSRMLS_C);
1893                         soap_server_fault_ex(function, retval, NULL TSRMLS_CC);
1894                         goto fail;
1895                 }
1896 
1897                 if (function && function->responseName) {
1898                         response_name = estrdup(function->responseName);
1899                 } else {
1900                         response_name = emalloc(Z_STRLEN(function_name) + sizeof("Response"));
1901                         memcpy(response_name,Z_STRVAL(function_name),Z_STRLEN(function_name));
1902                         memcpy(response_name+Z_STRLEN(function_name),"Response",sizeof("Response"));
1903                 }
1904                 doc_return = serialize_response_call(function, response_name, service->uri, retval, soap_headers, soap_version TSRMLS_CC);
1905                 efree(response_name);
1906         } else {
1907                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function '%s' call failed", Z_STRVAL(function_name));
1908                 return;
1909         }
1910 
1911         if (EG(exception)) {
1912                 php_output_discard(TSRMLS_C);
1913                 if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
1914                     instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
1915                         soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
1916                 }
1917                 if (service->type == SOAP_CLASS) {
1918 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
1919                         if (soap_obj && service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
1920 #else
1921                         if (soap_obj) {
1922 #endif
1923                           zval_ptr_dtor(&soap_obj);
1924                         }
1925                 }
1926                 goto fail;
1927         }
1928 
1929         /* Flush buffer */
1930         php_output_discard(TSRMLS_C);
1931 
1932         if (doc_return) {
1933                 /* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */
1934                 xmlDocDumpMemory(doc_return, &buf, &size);
1935 
1936                 if (size == 0) {
1937                         php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
1938                 }
1939 
1940                 if (soap_version == SOAP_1_2) {
1941                         sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
1942                 } else {
1943                         sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
1944                 }
1945 
1946                 xmlFreeDoc(doc_return);
1947 
1948                 if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
1949                         sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
1950                 } else {
1951                         snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
1952                         sapi_add_header(cont_len, strlen(cont_len), 1);
1953                 }
1954                 php_write(buf, size TSRMLS_CC);
1955                 xmlFree(buf);
1956         } else {
1957                 sapi_add_header("HTTP/1.1 202 Accepted", sizeof("HTTP/1.1 202 Accepted")-1, 1);
1958                 sapi_add_header("Content-Length: 0", sizeof("Content-Length: 0")-1, 1);
1959         }
1960 
1961 fail:
1962         SOAP_GLOBAL(soap_version) = old_soap_version;
1963         SOAP_GLOBAL(encoding) = old_encoding;
1964         SOAP_GLOBAL(sdl) = old_sdl;
1965         SOAP_GLOBAL(class_map) = old_class_map;
1966         SOAP_GLOBAL(typemap) = old_typemap;
1967         SOAP_GLOBAL(features) = old_features;
1968 
1969         /* Free soap headers */
1970         zval_ptr_dtor(&retval);
1971         while (soap_headers != NULL) {
1972                 soapHeader *h = soap_headers;
1973                 int i;
1974 
1975                 soap_headers = soap_headers->next;
1976                 if (h->parameters) {
1977                         i = h->num_params;
1978                         while (i > 0) {
1979                                 zval_ptr_dtor(&h->parameters[--i]);
1980                         }
1981                         efree(h->parameters);
1982                 }
1983                 zval_dtor(&h->function_name);
1984                 zval_dtor(&h->retval);
1985                 efree(h);
1986         }
1987         service->soap_headers_ptr = NULL;
1988 
1989         /* Free Memory */
1990         if (num_params > 0) {
1991                 for (i = 0; i < num_params;i++) {
1992                         zval_ptr_dtor(&params[i]);
1993                 }
1994                 efree(params);
1995         }
1996         zval_dtor(&function_name);
1997 
1998         SOAP_SERVER_END_CODE();
1999 }
2000 /* }}} */
2001 
2002 
2003 /* {{{ proto SoapServer::fault ( staring code, string string [, string actor [, mixed details [, string name]]] )
2004    Issue SoapFault indicating an error */
2005 PHP_METHOD(SoapServer, fault)
2006 {
2007         char *code, *string, *actor=NULL, *name=NULL;
2008         int code_len, string_len, actor_len = 0, name_len = 0;
2009         zval* details = NULL;
2010         soapServicePtr service;
2011         xmlCharEncodingHandlerPtr old_encoding;
2012 
2013         SOAP_SERVER_BEGIN_CODE();
2014         FETCH_THIS_SERVICE(service);
2015         old_encoding = SOAP_GLOBAL(encoding);
2016         SOAP_GLOBAL(encoding) = service->encoding;
2017 
2018         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|szs",
2019             &code, &code_len, &string, &string_len, &actor, &actor_len, &details,
2020             &name, &name_len) == FAILURE) {
2021                 return;
2022         }
2023 
2024         soap_server_fault(code, string, actor, details, name TSRMLS_CC);
2025 
2026         SOAP_GLOBAL(encoding) = old_encoding;
2027         SOAP_SERVER_END_CODE();
2028 }
2029 /* }}} */
2030 
2031 PHP_METHOD(SoapServer, addSoapHeader)
2032 {
2033         soapServicePtr service;
2034         zval *fault;
2035         soapHeader **p;
2036 
2037         SOAP_SERVER_BEGIN_CODE();
2038 
2039         FETCH_THIS_SERVICE(service);
2040 
2041         if (!service || !service->soap_headers_ptr) {
2042                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "The SoapServer::addSoapHeader function may be called only during SOAP request processing");
2043                 return;
2044         }
2045 
2046         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &fault, soap_header_class_entry) == FAILURE) {
2047                 return;
2048         }
2049 
2050         p = service->soap_headers_ptr;
2051         while (*p != NULL) {
2052                 p = &(*p)->next;
2053         }
2054         *p = emalloc(sizeof(soapHeader));
2055         memset(*p, 0, sizeof(soapHeader));
2056         ZVAL_NULL(&(*p)->function_name);
2057         (*p)->retval = *fault;
2058         zval_copy_ctor(&(*p)->retval);
2059 
2060         SOAP_SERVER_END_CODE();
2061 }
2062 
2063 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader *hdr TSRMLS_DC)
2064 {
2065         int soap_version;
2066         xmlChar *buf;
2067         char cont_len[30];
2068         int size;
2069         xmlDocPtr doc_return;
2070         zval **agent_name;
2071         int use_http_error_status = 1;
2072 
2073         soap_version = SOAP_GLOBAL(soap_version);
2074 
2075         doc_return = serialize_response_call(function, NULL, NULL, fault, hdr, soap_version TSRMLS_CC);
2076 
2077         xmlDocDumpMemory(doc_return, &buf, &size);
2078 
2079         if ((PG(http_globals)[TRACK_VARS_SERVER] || zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC)) &&
2080                 zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT"), (void **) &agent_name) == SUCCESS &&
2081                 Z_TYPE_PP(agent_name) == IS_STRING) {
2082                 if (strncmp(Z_STRVAL_PP(agent_name), "Shockwave Flash", sizeof("Shockwave Flash")-1) == 0) {
2083                         use_http_error_status = 0;
2084                 }
2085         }
2086         /*
2087            Want to return HTTP 500 but apache wants to over write
2088            our fault code with their own handling... Figure this out later
2089         */
2090         if (use_http_error_status) {
2091                 sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error")-1, 1);
2092         }
2093         if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
2094                 sapi_add_header("Connection: close", sizeof("Connection: close")-1, 1);
2095         } else {
2096                 snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
2097                 sapi_add_header(cont_len, strlen(cont_len), 1);
2098         }
2099         if (soap_version == SOAP_1_2) {
2100                 sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
2101         } else {
2102                 sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
2103         }
2104 
2105         php_write(buf, size TSRMLS_CC);
2106 
2107         xmlFreeDoc(doc_return);
2108         xmlFree(buf);
2109         zend_clear_exception(TSRMLS_C);
2110 }
2111 
2112 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char* name TSRMLS_DC)
2113 {
2114         zval ret;
2115 
2116         INIT_ZVAL(ret);
2117 
2118         set_soap_fault(&ret, NULL, code, string, actor, details, name TSRMLS_CC);
2119         /* TODO: Which function */
2120         soap_server_fault_ex(NULL, &ret, NULL TSRMLS_CC);
2121         zend_bailout();
2122 }
2123 
2124 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
2125 {
2126         zend_bool _old_in_compilation, _old_in_execution;
2127         zend_execute_data *_old_current_execute_data;
2128         int _old_http_response_code;
2129         char *_old_http_status_line;
2130         TSRMLS_FETCH();
2131 
2132         _old_in_compilation = CG(in_compilation);
2133         _old_in_execution = EG(in_execution);
2134         _old_current_execute_data = EG(current_execute_data);
2135         _old_http_response_code = SG(sapi_headers).http_response_code;
2136         _old_http_status_line = SG(sapi_headers).http_status_line;
2137 
2138         if (!PG(modules_activated) || !SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) {
2139                 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2140                 return;
2141         }
2142 
2143         if (SOAP_GLOBAL(error_object) &&
2144             Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
2145             instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_class_entry TSRMLS_CC)) {
2146                 zval **tmp;
2147                 int use_exceptions = 0;
2148 
2149                 if (zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
2150                      Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0) {
2151                      use_exceptions = 1;
2152                 }
2153 
2154                 if ((error_num == E_USER_ERROR ||
2155                      error_num == E_COMPILE_ERROR ||
2156                      error_num == E_CORE_ERROR ||
2157                      error_num == E_ERROR ||
2158                      error_num == E_PARSE) &&
2159                     use_exceptions) {
2160                         zval *fault, *exception;
2161                         char* code = SOAP_GLOBAL(error_code);
2162                         char buffer[1024];
2163                         int buffer_len;
2164                         zval outbuf, outbuflen;
2165 #ifdef va_copy
2166                         va_list argcopy;
2167 #endif
2168                         zend_object_store_bucket *old_objects;
2169                         int old = PG(display_errors);
2170 
2171                         INIT_ZVAL(outbuf);
2172                         INIT_ZVAL(outbuflen);
2173 #ifdef va_copy
2174                         va_copy(argcopy, args);
2175                         buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
2176                         va_end(argcopy);
2177 #else
2178                         buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
2179 #endif
2180                         buffer[sizeof(buffer)-1]=0;
2181                         if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
2182                                 buffer_len = sizeof(buffer) - 1;
2183                         }
2184 
2185                         if (code == NULL) {
2186                                 code = "Client";
2187                         }
2188                         fault = add_soap_fault(SOAP_GLOBAL(error_object), code, buffer, NULL, NULL TSRMLS_CC);
2189                         MAKE_STD_ZVAL(exception);
2190                         MAKE_COPY_ZVAL(&fault, exception);
2191                         zend_throw_exception_object(exception TSRMLS_CC);
2192 
2193                         old_objects = EG(objects_store).object_buckets;
2194                         EG(objects_store).object_buckets = NULL;
2195                         PG(display_errors) = 0;
2196                         SG(sapi_headers).http_status_line = NULL;
2197                         zend_try {
2198                                 call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2199                         } zend_catch {
2200                                 CG(in_compilation) = _old_in_compilation;
2201                                 EG(in_execution) = _old_in_execution;
2202                                 EG(current_execute_data) = _old_current_execute_data;
2203                                 if (SG(sapi_headers).http_status_line) {
2204                                         efree(SG(sapi_headers).http_status_line);
2205                                 }
2206                                 SG(sapi_headers).http_status_line = _old_http_status_line;
2207                                 SG(sapi_headers).http_response_code = _old_http_response_code;
2208                         } zend_end_try();
2209                         EG(objects_store).object_buckets = old_objects;
2210                         PG(display_errors) = old;
2211                         zend_bailout();
2212                 } else if (!use_exceptions ||
2213                            !SOAP_GLOBAL(error_code) ||
2214                            strcmp(SOAP_GLOBAL(error_code),"WSDL") != 0) {
2215                         /* Ignore libxml warnings during WSDL parsing */
2216                         call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2217                 }
2218         } else {
2219                 int old = PG(display_errors);
2220                 int fault = 0;
2221                 zval fault_obj;
2222 #ifdef va_copy
2223                 va_list argcopy;
2224 #endif
2225 
2226                 if (error_num == E_USER_ERROR ||
2227                     error_num == E_COMPILE_ERROR ||
2228                     error_num == E_CORE_ERROR ||
2229                     error_num == E_ERROR ||
2230                     error_num == E_PARSE) {
2231 
2232                         char* code = SOAP_GLOBAL(error_code);
2233                         char buffer[1024];
2234                         zval *outbuf = NULL;
2235                         zval **tmp;
2236                         soapServicePtr service;
2237 
2238                         if (code == NULL) {
2239                                 code = "Server";
2240                         }
2241                         if (SOAP_GLOBAL(error_object) &&
2242                             Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
2243                             instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_server_class_entry TSRMLS_CC) &&
2244                         zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "service", sizeof("service"), (void **)&tmp) != FAILURE &&
2245                                 (service = (soapServicePtr)zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service)) &&
2246                                 !service->send_errors) {
2247                                 strcpy(buffer, "Internal Error");
2248                         } else {
2249                                 int buffer_len;
2250                                 zval outbuflen;
2251 
2252                                 INIT_ZVAL(outbuflen);
2253 
2254 #ifdef va_copy
2255                                 va_copy(argcopy, args);
2256                                 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
2257                                 va_end(argcopy);
2258 #else
2259                                 buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
2260 #endif
2261                                 buffer[sizeof(buffer)-1]=0;
2262                                 if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
2263                                         buffer_len = sizeof(buffer) - 1;
2264                                 }
2265 
2266                                 /* Get output buffer and send as fault detials */
2267                                 if (php_output_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) {
2268                                         ALLOC_INIT_ZVAL(outbuf);
2269                                         php_output_get_contents(outbuf TSRMLS_CC);
2270                                 }
2271                                 php_output_discard(TSRMLS_C);
2272 
2273                         }
2274                         INIT_ZVAL(fault_obj);
2275                         set_soap_fault(&fault_obj, NULL, code, buffer, NULL, outbuf, NULL TSRMLS_CC);
2276                         fault = 1;
2277                 }
2278 
2279                 PG(display_errors) = 0;
2280                 SG(sapi_headers).http_status_line = NULL;
2281                 zend_try {
2282                         call_old_error_handler(error_num, error_filename, error_lineno, format, args);
2283                 } zend_catch {
2284                         CG(in_compilation) = _old_in_compilation;
2285                         EG(in_execution) = _old_in_execution;
2286                         EG(current_execute_data) = _old_current_execute_data;
2287                         if (SG(sapi_headers).http_status_line) {
2288                                 efree(SG(sapi_headers).http_status_line);
2289                         }
2290                         SG(sapi_headers).http_status_line = _old_http_status_line;
2291                         SG(sapi_headers).http_response_code = _old_http_response_code;
2292                 } zend_end_try();
2293                 PG(display_errors) = old;
2294 
2295                 if (fault) {
2296                         soap_server_fault_ex(NULL, &fault_obj, NULL TSRMLS_CC);
2297                         zend_bailout();
2298                 }
2299         }
2300 }
2301 
2302 PHP_FUNCTION(use_soap_error_handler)
2303 {
2304         zend_bool handler = 1;
2305 
2306         ZVAL_BOOL(return_value, SOAP_GLOBAL(use_soap_error_handler));
2307         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &handler) == SUCCESS) {
2308                 SOAP_GLOBAL(use_soap_error_handler) = handler;
2309         }
2310 }
2311 
2312 PHP_FUNCTION(is_soap_fault)
2313 {
2314         zval *fault;
2315 
2316         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &fault) == SUCCESS &&
2317             Z_TYPE_P(fault) == IS_OBJECT &&
2318             instanceof_function(Z_OBJCE_P(fault), soap_fault_class_entry TSRMLS_CC)) {
2319                 RETURN_TRUE;
2320         }
2321         RETURN_FALSE
2322 }
2323 
2324 /* SoapClient functions */
2325 
2326 /* {{{ proto object SoapClient::SoapClient ( mixed wsdl [, array options])
2327    SoapClient constructor */
2328 PHP_METHOD(SoapClient, SoapClient)
2329 {
2330 
2331         zval *wsdl, *options = NULL;
2332         int  soap_version = SOAP_1_1;
2333         php_stream_context *context = NULL;
2334         long cache_wsdl;
2335         sdlPtr sdl = NULL;
2336         HashTable *typemap_ht = NULL;
2337 
2338         SOAP_CLIENT_BEGIN_CODE();
2339 
2340         if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
2341                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
2342         }
2343 
2344         if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
2345                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "$wsdl must be string or null");
2346         }
2347 
2348         cache_wsdl = SOAP_GLOBAL(cache_enabled) ? SOAP_GLOBAL(cache_mode) : 0;
2349 
2350         if (options != NULL) {
2351                 HashTable *ht = Z_ARRVAL_P(options);
2352                 zval **tmp;
2353 
2354                 if (Z_TYPE_P(wsdl) == IS_NULL) {
2355                         /* Fetching non-WSDL mode options */
2356                         if (zend_hash_find(ht, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
2357                             Z_TYPE_PP(tmp) == IS_STRING) {
2358                                 add_property_stringl(this_ptr, "uri", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2359                         } else {
2360                                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
2361                         }
2362 
2363                         if (zend_hash_find(ht, "style", sizeof("style"), (void**)&tmp) == SUCCESS &&
2364                                         Z_TYPE_PP(tmp) == IS_LONG &&
2365                                         (Z_LVAL_PP(tmp) == SOAP_RPC || Z_LVAL_PP(tmp) == SOAP_DOCUMENT)) {
2366                                 add_property_long(this_ptr, "style", Z_LVAL_PP(tmp));
2367                         }
2368 
2369                         if (zend_hash_find(ht, "use", sizeof("use"), (void**)&tmp) == SUCCESS &&
2370                                         Z_TYPE_PP(tmp) == IS_LONG &&
2371                                         (Z_LVAL_PP(tmp) == SOAP_LITERAL || Z_LVAL_PP(tmp) == SOAP_ENCODED)) {
2372                                 add_property_long(this_ptr, "use", Z_LVAL_PP(tmp));
2373                         }
2374                 }
2375 
2376                 if (zend_hash_find(ht, "stream_context", sizeof("stream_context"), (void**)&tmp) == SUCCESS &&
2377                                 Z_TYPE_PP(tmp) == IS_RESOURCE) {
2378                         context = php_stream_context_from_zval(*tmp, 1);
2379                         zend_list_addref(context->rsrc_id);
2380                 }
2381 
2382                 if (zend_hash_find(ht, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
2383                     Z_TYPE_PP(tmp) == IS_STRING) {
2384                         add_property_stringl(this_ptr, "location", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2385                 } else if (Z_TYPE_P(wsdl) == IS_NULL) {
2386                         php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' option is required in nonWSDL mode");
2387                 }
2388 
2389                 if (zend_hash_find(ht, "soap_version", sizeof("soap_version"), (void**)&tmp) == SUCCESS) {
2390                         if (Z_TYPE_PP(tmp) == IS_LONG ||
2391                             (Z_LVAL_PP(tmp) == SOAP_1_1 && Z_LVAL_PP(tmp) == SOAP_1_2)) {
2392                                 soap_version = Z_LVAL_PP(tmp);
2393                         }
2394                 }
2395                 if (zend_hash_find(ht, "login", sizeof("login"), (void**)&tmp) == SUCCESS &&
2396                     Z_TYPE_PP(tmp) == IS_STRING) {
2397                         add_property_stringl(this_ptr, "_login", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2398                         if (zend_hash_find(ht, "password", sizeof("password"), (void**)&tmp) == SUCCESS &&
2399                             Z_TYPE_PP(tmp) == IS_STRING) {
2400                                 add_property_stringl(this_ptr, "_password", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2401                         }
2402                         if (zend_hash_find(ht, "authentication", sizeof("authentication"), (void**)&tmp) == SUCCESS &&
2403                             Z_TYPE_PP(tmp) == IS_LONG &&
2404                             Z_LVAL_PP(tmp) == SOAP_AUTHENTICATION_DIGEST) {
2405                                 add_property_null(this_ptr, "_digest");
2406                         }
2407                 }
2408                 if (zend_hash_find(ht, "proxy_host", sizeof("proxy_host"), (void**)&tmp) == SUCCESS &&
2409                     Z_TYPE_PP(tmp) == IS_STRING) {
2410                         add_property_stringl(this_ptr, "_proxy_host", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2411                         if (zend_hash_find(ht, "proxy_port", sizeof("proxy_port"), (void**)&tmp) == SUCCESS) {
2412                                 convert_to_long(*tmp);
2413                                 add_property_long(this_ptr, "_proxy_port", Z_LVAL_PP(tmp));
2414                         }
2415                         if (zend_hash_find(ht, "proxy_login", sizeof("proxy_login"), (void**)&tmp) == SUCCESS &&
2416                             Z_TYPE_PP(tmp) == IS_STRING) {
2417                                 add_property_stringl(this_ptr, "_proxy_login", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2418                                 if (zend_hash_find(ht, "proxy_password", sizeof("proxy_password"), (void**)&tmp) == SUCCESS &&
2419                                     Z_TYPE_PP(tmp) == IS_STRING) {
2420                                         add_property_stringl(this_ptr, "_proxy_password", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2421                                 }
2422                         }
2423                 }
2424                 if (zend_hash_find(ht, "local_cert", sizeof("local_cert"), (void**)&tmp) == SUCCESS &&
2425                     Z_TYPE_PP(tmp) == IS_STRING) {
2426                   if (!context) {
2427                         context = php_stream_context_alloc(TSRMLS_C);
2428                   }
2429                         php_stream_context_set_option(context, "ssl", "local_cert", *tmp);
2430                         if (zend_hash_find(ht, "passphrase", sizeof("passphrase"), (void**)&tmp) == SUCCESS &&
2431                             Z_TYPE_PP(tmp) == IS_STRING) {
2432                                 php_stream_context_set_option(context, "ssl", "passphrase", *tmp);
2433                         }
2434                 }
2435                 if (zend_hash_find(ht, "trace", sizeof("trace"), (void**)&tmp) == SUCCESS &&
2436                     (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
2437                                 Z_LVAL_PP(tmp) == 1) {
2438                         add_property_long(this_ptr, "trace", 1);
2439                 }
2440 
2441                 if (zend_hash_find(ht, "exceptions", sizeof("exceptions"), (void**)&tmp) == SUCCESS &&
2442                     (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
2443                                 Z_LVAL_PP(tmp) == 0) {
2444                         add_property_bool(this_ptr, "_exceptions", 0);
2445                 }
2446 
2447                 if (zend_hash_find(ht, "compression", sizeof("compression"), (void**)&tmp) == SUCCESS &&
2448                     Z_TYPE_PP(tmp) == IS_LONG &&
2449               zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate")) &&
2450               zend_hash_exists(EG(function_table), "gzdeflate", sizeof("gzdeflate")) &&
2451               zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress")) &&
2452               zend_hash_exists(EG(function_table), "gzcompress", sizeof("gzcompress")) &&
2453               zend_hash_exists(EG(function_table), "gzencode", sizeof("gzencode"))) {
2454                         add_property_long(this_ptr, "compression", Z_LVAL_PP(tmp));
2455                 }
2456                 if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
2457                     Z_TYPE_PP(tmp) == IS_STRING) {
2458                         xmlCharEncodingHandlerPtr encoding;
2459 
2460                         encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
2461                         if (encoding == NULL) {
2462                                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
2463                         } else {
2464                                 xmlCharEncCloseFunc(encoding);
2465                                 add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2466                         }
2467                 }
2468                 if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
2469                         Z_TYPE_PP(tmp) == IS_ARRAY) {
2470                         zval *class_map;
2471 
2472                         MAKE_STD_ZVAL(class_map);
2473                         MAKE_COPY_ZVAL(tmp, class_map);
2474                         Z_DELREF_P(class_map);
2475 
2476                         add_property_zval(this_ptr, "_classmap", class_map);
2477                 }
2478 
2479                 if (zend_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS &&
2480                         Z_TYPE_PP(tmp) == IS_ARRAY &&
2481                         zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) {
2482                         typemap_ht = Z_ARRVAL_PP(tmp);
2483                 }
2484 
2485                 if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
2486                         Z_TYPE_PP(tmp) == IS_LONG) {
2487                         add_property_long(this_ptr, "_features", Z_LVAL_PP(tmp));
2488             }
2489 
2490                 if (zend_hash_find(ht, "connection_timeout", sizeof("connection_timeout"), (void**)&tmp) == SUCCESS) {
2491                         convert_to_long(*tmp);
2492                         if (Z_LVAL_PP(tmp) > 0) {
2493                                 add_property_long(this_ptr, "_connection_timeout", Z_LVAL_PP(tmp));
2494                         }
2495                 }
2496 
2497                 if (context) {
2498                         add_property_resource(this_ptr, "_stream_context", context->rsrc_id);
2499                 }
2500 
2501                 if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
2502                     Z_TYPE_PP(tmp) == IS_LONG) {
2503                         cache_wsdl = Z_LVAL_PP(tmp);
2504                 }
2505 
2506                 if (zend_hash_find(ht, "user_agent", sizeof("user_agent"), (void**)&tmp) == SUCCESS &&
2507                     Z_TYPE_PP(tmp) == IS_STRING) {
2508                         add_property_stringl(this_ptr, "_user_agent", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
2509                 }
2510 
2511                 if (zend_hash_find(ht, "keep_alive", sizeof("keep_alive"), (void**)&tmp) == SUCCESS &&
2512                                 (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) && Z_LVAL_PP(tmp) == 0) {
2513                         add_property_long(this_ptr, "_keep_alive", 0);
2514                 }
2515 
2516                 if (zend_hash_find(ht, "ssl_method", sizeof("ssl_method"), (void**)&tmp) == SUCCESS &&
2517                         Z_TYPE_PP(tmp) == IS_LONG) {
2518                         add_property_long(this_ptr, "_ssl_method", Z_LVAL_PP(tmp));
2519                 }
2520         } else if (Z_TYPE_P(wsdl) == IS_NULL) {
2521                 php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' and 'uri' options are required in nonWSDL mode");
2522         }
2523 
2524         add_property_long(this_ptr, "_soap_version", soap_version);
2525 
2526         if (Z_TYPE_P(wsdl) != IS_NULL) {
2527                 int    old_soap_version, ret;
2528 
2529                 old_soap_version = SOAP_GLOBAL(soap_version);
2530                 SOAP_GLOBAL(soap_version) = soap_version;
2531 
2532                 sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
2533                 ret = zend_list_insert(sdl, le_sdl TSRMLS_CC);
2534 
2535                 add_property_resource(this_ptr, "sdl", ret);
2536 
2537                 SOAP_GLOBAL(soap_version) = old_soap_version;
2538         }
2539 
2540         if (typemap_ht) {
2541                 HashTable *typemap = soap_create_typemap(sdl, typemap_ht TSRMLS_CC);
2542                 if (typemap) {
2543                         int ret;
2544 
2545                         ret = zend_list_insert(typemap, le_typemap TSRMLS_CC);
2546                         add_property_resource(this_ptr, "typemap", ret);
2547                 }
2548         }
2549         SOAP_CLIENT_END_CODE();
2550 }
2551 /* }}} */
2552 
2553 static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *action, int version, int one_way, zval *response TSRMLS_DC)
2554 {
2555         int    ret = TRUE;
2556         char  *buf;
2557         int    buf_size;
2558         zval   func;
2559         zval  *params[5];
2560         zval **trace;
2561         zval **fault;
2562 
2563         INIT_ZVAL(*response);
2564 
2565         xmlDocDumpMemory(request, (xmlChar**)&buf, &buf_size);
2566         if (!buf) {
2567                 add_soap_fault(this_ptr, "HTTP", "Error build soap request", NULL, NULL TSRMLS_CC);
2568                 return FALSE;
2569         }
2570 
2571         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
2572             (Z_TYPE_PP(trace) == IS_BOOL || Z_TYPE_PP(trace) == IS_LONG) && Z_LVAL_PP(trace) != 0) {
2573                 add_property_stringl(this_ptr, "__last_request", buf, buf_size, 1);
2574         }
2575 
2576         INIT_ZVAL(func);
2577         ZVAL_STRINGL(&func,"__doRequest",sizeof("__doRequest")-1,0);
2578         ALLOC_INIT_ZVAL(params[0]);
2579         ZVAL_STRINGL(params[0], buf, buf_size, 1);
2580         ALLOC_INIT_ZVAL(params[1]);
2581         if (location == NULL) {
2582                 ZVAL_NULL(params[1]);
2583         } else {
2584                 ZVAL_STRING(params[1], location, 1);
2585         }
2586         ALLOC_INIT_ZVAL(params[2]);
2587         if (action == NULL) {
2588                 ZVAL_NULL(params[2]);
2589         } else {
2590                 ZVAL_STRING(params[2], action, 1);
2591         }
2592         ALLOC_INIT_ZVAL(params[3]);
2593         ZVAL_LONG(params[3], version);
2594 
2595         ALLOC_INIT_ZVAL(params[4]);
2596         ZVAL_LONG(params[4], one_way);
2597 
2598         if (call_user_function(NULL, &this_ptr, &func, response, 5, params TSRMLS_CC) != SUCCESS) {
2599                 add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() failed", NULL, NULL TSRMLS_CC);
2600                 ret = FALSE;
2601         } else if (Z_TYPE_P(response) != IS_STRING) {
2602                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == FAILURE) {
2603                         add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() returned non string value", NULL, NULL TSRMLS_CC);
2604                 }
2605                 ret = FALSE;
2606         } else if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
2607                    (Z_TYPE_PP(trace) == IS_BOOL || Z_TYPE_PP(trace) == IS_LONG) && Z_LVAL_PP(trace) != 0) {
2608                 add_property_stringl(this_ptr, "__last_response", Z_STRVAL_P(response), Z_STRLEN_P(response), 1);
2609         }
2610         zval_ptr_dtor(&params[4]);
2611         zval_ptr_dtor(&params[3]);
2612         zval_ptr_dtor(&params[2]);
2613         zval_ptr_dtor(&params[1]);
2614         zval_ptr_dtor(&params[0]);
2615         xmlFree(buf);
2616         if (ret && zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
2617           return FALSE;
2618         }
2619   return ret;
2620 }
2621 
2622 static void do_soap_call(zval* this_ptr,
2623                          char* function,
2624                          int function_len,
2625                          int arg_count,
2626                          zval** real_args,
2627                          zval* return_value,
2628                          char* location,
2629                          char* soap_action,
2630                          char* call_uri,
2631                          HashTable* soap_headers,
2632                          zval* output_headers
2633                          TSRMLS_DC)
2634 {
2635         zval **tmp;
2636         zval **trace;
2637         sdlPtr sdl = NULL;
2638         sdlPtr old_sdl = NULL;
2639         sdlFunctionPtr fn;
2640         xmlDocPtr request = NULL;
2641         int ret = FALSE;
2642         int soap_version;
2643         zval response;
2644         xmlCharEncodingHandlerPtr old_encoding;
2645         HashTable *old_class_map;
2646         int old_features;
2647         HashTable *old_typemap, *typemap = NULL;
2648 
2649         SOAP_CLIENT_BEGIN_CODE();
2650 
2651         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
2652             (Z_TYPE_PP(trace) == IS_BOOL || Z_TYPE_PP(trace) == IS_LONG) && Z_LVAL_PP(trace) != 0) {
2653                 zend_hash_del(Z_OBJPROP_P(this_ptr), "__last_request", sizeof("__last_request"));
2654                 zend_hash_del(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"));
2655         }
2656         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_soap_version", sizeof("_soap_version"), (void **) &tmp) == SUCCESS &&
2657                 Z_TYPE_PP(tmp) == IS_LONG && Z_LVAL_PP(tmp) == SOAP_1_2) {
2658                 soap_version = SOAP_1_2;
2659         } else {
2660                 soap_version = SOAP_1_1;
2661         }
2662 
2663         if (location == NULL) {
2664                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS &&
2665                     Z_TYPE_PP(tmp) == IS_STRING) {
2666                   location = Z_STRVAL_PP(tmp);
2667                 }
2668         }
2669 
2670         if (FIND_SDL_PROPERTY(this_ptr,tmp) != FAILURE) {
2671                 FETCH_SDL_RES(sdl,tmp);
2672         }
2673         if (FIND_TYPEMAP_PROPERTY(this_ptr,tmp) != FAILURE) {
2674                 FETCH_TYPEMAP_RES(typemap,tmp);
2675         }
2676 
2677         clear_soap_fault(this_ptr TSRMLS_CC);
2678 
2679         SOAP_GLOBAL(soap_version) = soap_version;
2680         old_sdl = SOAP_GLOBAL(sdl);
2681         SOAP_GLOBAL(sdl) = sdl;
2682         old_encoding = SOAP_GLOBAL(encoding);
2683         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_encoding", sizeof("_encoding"), (void **) &tmp) == SUCCESS &&
2684             Z_TYPE_PP(tmp) == IS_STRING) {
2685                 SOAP_GLOBAL(encoding) = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
2686         } else {
2687                 SOAP_GLOBAL(encoding) = NULL;
2688         }
2689         old_class_map = SOAP_GLOBAL(class_map);
2690         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_classmap", sizeof("_classmap"), (void **) &tmp) == SUCCESS &&
2691             Z_TYPE_PP(tmp) == IS_ARRAY) {
2692                 SOAP_GLOBAL(class_map) = (*tmp)->value.ht;
2693         } else {
2694                 SOAP_GLOBAL(class_map) = NULL;
2695         }
2696         old_typemap = SOAP_GLOBAL(typemap);
2697         SOAP_GLOBAL(typemap) = typemap;
2698         old_features = SOAP_GLOBAL(features);
2699         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_features", sizeof("_features"), (void **) &tmp) == SUCCESS &&
2700             Z_TYPE_PP(tmp) == IS_LONG) {
2701                 SOAP_GLOBAL(features) = Z_LVAL_PP(tmp);
2702         } else {
2703                 SOAP_GLOBAL(features) = 0;
2704         }
2705 
2706         zend_try {
2707                 if (sdl != NULL) {
2708                         fn = get_function(sdl, function);
2709                         if (fn != NULL) {
2710                                 sdlBindingPtr binding = fn->binding;
2711                                 int one_way = 0;
2712 
2713                                 if (fn->responseName == NULL &&
2714                                     fn->responseParameters == NULL &&
2715                                     soap_headers == NULL) {
2716                                         one_way = 1;
2717                                 }
2718 
2719                                 if (location == NULL) {
2720                                         location = binding->location;
2721                                 }
2722                                 if (binding->bindingType == BINDING_SOAP) {
2723                                         sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
2724                                         request = serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
2725                                         ret = do_request(this_ptr, request, location, fnb->soapAction, soap_version, one_way, &response TSRMLS_CC);
2726                                 } else {
2727                                         request = serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
2728                                         ret = do_request(this_ptr, request, location, NULL, soap_version, one_way, &response TSRMLS_CC);
2729                                 }
2730 
2731                                 xmlFreeDoc(request);
2732 
2733                                 if (ret && Z_TYPE(response) == IS_STRING) {
2734                                         encode_reset_ns();
2735                                         ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), fn, NULL, return_value, output_headers TSRMLS_CC);
2736                                         encode_finish();
2737                                 }
2738 
2739                                 zval_dtor(&response);
2740 
2741                         } else {
2742                                 smart_str error = {0};
2743                                 smart_str_appends(&error,"Function (\"");
2744                                 smart_str_appends(&error,function);
2745                                 smart_str_appends(&error,"\") is not a valid method for this service");
2746                                 smart_str_0(&error);
2747                                 add_soap_fault(this_ptr, "Client", error.c, NULL, NULL TSRMLS_CC);
2748                                 smart_str_free(&error);
2749                         }
2750                 } else {
2751                         zval **uri;
2752                         smart_str action = {0};
2753 
2754                         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri"), (void *)&uri) == FAILURE || Z_TYPE_PP(uri) != IS_STRING) {
2755                                 add_soap_fault(this_ptr, "Client", "Error finding \"uri\" property", NULL, NULL TSRMLS_CC);
2756                         } else if (location == NULL) {
2757                                 add_soap_fault(this_ptr, "Client", "Error could not find \"location\" property", NULL, NULL TSRMLS_CC);
2758                         } else {
2759                                 if (call_uri == NULL) {
2760                                         call_uri = Z_STRVAL_PP(uri);
2761                                 }
2762                                 request = serialize_function_call(this_ptr, NULL, function, call_uri, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
2763 
2764                                 if (soap_action == NULL) {
2765                                         smart_str_appends(&action, call_uri);
2766                                         smart_str_appendc(&action, '#');
2767                                         smart_str_appends(&action, function);
2768                                 } else {
2769                                         smart_str_appends(&action, soap_action);
2770                                 }
2771                                 smart_str_0(&action);
2772 
2773                                 ret = do_request(this_ptr, request, location, action.c, soap_version, 0, &response TSRMLS_CC);
2774 
2775                                 smart_str_free(&action);
2776                                 xmlFreeDoc(request);
2777 
2778                                 if (ret && Z_TYPE(response) == IS_STRING) {
2779                                         encode_reset_ns();
2780                                         ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), NULL, function, return_value, output_headers TSRMLS_CC);
2781                                         encode_finish();
2782                                 }
2783 
2784                                 zval_dtor(&response);
2785                         }
2786                 }
2787 
2788                 if (!ret) {
2789                         zval** fault;
2790                         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
2791                                 *return_value = **fault;
2792                                 zval_copy_ctor(return_value);
2793                         } else {
2794                                 *return_value = *add_soap_fault(this_ptr, "Client", "Unknown Error", NULL, NULL TSRMLS_CC);
2795                                 zval_copy_ctor(return_value);
2796                         }
2797                 } else {
2798                         zval** fault;
2799                         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
2800                                 *return_value = **fault;
2801                                 zval_copy_ctor(return_value);
2802                         }
2803                 }
2804 
2805                 if (!EG(exception) &&
2806                     Z_TYPE_P(return_value) == IS_OBJECT &&
2807                     instanceof_function(Z_OBJCE_P(return_value), soap_fault_class_entry TSRMLS_CC) &&
2808                     (zend_hash_find(Z_OBJPROP_P(this_ptr), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
2809                            Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0)) {
2810                         zval *exception;
2811 
2812                         MAKE_STD_ZVAL(exception);
2813                         MAKE_COPY_ZVAL(&return_value, exception);
2814                         zend_throw_exception_object(exception TSRMLS_CC);
2815                 }
2816 
2817         } zend_catch {
2818                 _bailout = 1;
2819         } zend_end_try();
2820         
2821         if (SOAP_GLOBAL(encoding) != NULL) {
2822                 xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
2823         }
2824 
2825         SOAP_GLOBAL(features) = old_features;
2826         SOAP_GLOBAL(typemap) = old_typemap;
2827         SOAP_GLOBAL(class_map) = old_class_map;
2828         SOAP_GLOBAL(encoding) = old_encoding;
2829         SOAP_GLOBAL(sdl) = old_sdl;
2830         if (_bailout) {
2831                 _bailout = 0;
2832                 zend_bailout();
2833         }
2834         SOAP_CLIENT_END_CODE();
2835 }
2836 
2837 static void verify_soap_headers_array(HashTable *ht TSRMLS_DC)
2838 {
2839         zval **tmp;
2840 
2841         zend_hash_internal_pointer_reset(ht);
2842         while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
2843                 if (Z_TYPE_PP(tmp) != IS_OBJECT ||
2844                     !instanceof_function(Z_OBJCE_PP(tmp), soap_header_class_entry TSRMLS_CC)) {
2845                         php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid SOAP header");
2846                 }
2847                 zend_hash_move_forward(ht);
2848         }
2849 }
2850 
2851 
2852 /* {{{ proto mixed SoapClient::__call ( string function_name, array arguments [, array options [, array input_headers [, array output_headers]]])
2853    Calls a SOAP function */
2854 PHP_METHOD(SoapClient, __call)
2855 {
2856         char *function, *location=NULL, *soap_action = NULL, *uri = NULL;
2857         int function_len, i = 0;
2858         HashTable* soap_headers = NULL;
2859         zval *options = NULL;
2860         zval *headers = NULL;
2861         zval *output_headers = NULL;
2862         zval *args;
2863         zval **real_args = NULL;
2864         zval **param;
2865         int arg_count;
2866         zval **tmp;
2867         zend_bool free_soap_headers = 0;
2868 
2869         HashPosition pos;
2870 
2871         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a!zz",
2872                 &function, &function_len, &args, &options, &headers, &output_headers) == FAILURE) {
2873                 return;
2874         }
2875 
2876         if (options) {
2877                 HashTable *hto = Z_ARRVAL_P(options);
2878                 if (zend_hash_find(hto, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
2879                         Z_TYPE_PP(tmp) == IS_STRING) {
2880                         location = Z_STRVAL_PP(tmp);
2881                 }
2882 
2883                 if (zend_hash_find(hto, "soapaction", sizeof("soapaction"), (void**)&tmp) == SUCCESS &&
2884                         Z_TYPE_PP(tmp) == IS_STRING) {
2885                         soap_action = Z_STRVAL_PP(tmp);
2886                 }
2887 
2888                 if (zend_hash_find(hto, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
2889                         Z_TYPE_PP(tmp) == IS_STRING) {
2890                         uri = Z_STRVAL_PP(tmp);
2891                 }
2892         }
2893 
2894         if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
2895         } else if (Z_TYPE_P(headers) == IS_ARRAY) {
2896                 soap_headers = Z_ARRVAL_P(headers);
2897                 verify_soap_headers_array(soap_headers TSRMLS_CC);
2898                 free_soap_headers = 0;
2899         } else if (Z_TYPE_P(headers) == IS_OBJECT &&
2900                    instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
2901             soap_headers = emalloc(sizeof(HashTable));
2902                 zend_hash_init(soap_headers, 0, NULL, ZVAL_PTR_DTOR, 0);
2903                 zend_hash_next_index_insert(soap_headers, &headers, sizeof(zval*), NULL);
2904                 Z_ADDREF_P(headers);
2905                 free_soap_headers = 1;
2906         } else{
2907                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid SOAP header");
2908                 return;
2909         }
2910 
2911         /* Add default headers */
2912         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_ARRAY) {
2913                 HashTable *default_headers = Z_ARRVAL_P(*tmp);
2914                 if (soap_headers) {
2915                         if (!free_soap_headers) {
2916                                 HashTable *t =  emalloc(sizeof(HashTable));
2917                                 zend_hash_init(t, 0, NULL, ZVAL_PTR_DTOR, 0);
2918                                 zend_hash_copy(t, soap_headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
2919                                 soap_headers = t;
2920                                 free_soap_headers = 1;
2921                         }
2922                         zend_hash_internal_pointer_reset(default_headers);
2923                         while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
2924                                 if(Z_TYPE_PP(tmp) == IS_OBJECT) {
2925                                         Z_ADDREF_PP(tmp);
2926                                         zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
2927                                 }
2928                                 zend_hash_move_forward(default_headers);
2929                         }
2930                 } else {
2931                         soap_headers = Z_ARRVAL_P(*tmp);
2932                         free_soap_headers = 0;
2933                 }
2934         }
2935 
2936         arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
2937 
2938         if (arg_count > 0) {
2939                 real_args = safe_emalloc(sizeof(zval *), arg_count, 0);
2940                 for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
2941                         zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) &param, &pos) == SUCCESS;
2942                         zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos)) {
2943                                 /*zval_add_ref(param);*/
2944                                 real_args[i++] = *param;
2945                 }
2946         }
2947         if (output_headers) {
2948                 array_init(output_headers);
2949         }
2950         do_soap_call(this_ptr, function, function_len, arg_count, real_args, return_value, location, soap_action, uri, soap_headers, output_headers TSRMLS_CC);
2951         if (arg_count > 0) {
2952                 efree(real_args);
2953         }
2954 
2955         if (soap_headers && free_soap_headers) {
2956                 zend_hash_destroy(soap_headers);
2957                 efree(soap_headers);
2958         }
2959 }
2960 /* }}} */
2961 
2962 
2963 /* {{{ proto array SoapClient::__getFunctions ( void )
2964    Returns list of SOAP functions */
2965 PHP_METHOD(SoapClient, __getFunctions)
2966 {
2967         sdlPtr sdl;
2968         HashPosition pos;
2969 
2970         FETCH_THIS_SDL(sdl);
2971 
2972         if (zend_parse_parameters_none() == FAILURE) {
2973                 return;
2974         }
2975 
2976         if (sdl) {
2977                 smart_str buf = {0};
2978                 sdlFunctionPtr *function;
2979 
2980                 array_init(return_value);
2981                 zend_hash_internal_pointer_reset_ex(&sdl->functions, &pos);
2982                 while (zend_hash_get_current_data_ex(&sdl->functions, (void **)&function, &pos) != FAILURE) {
2983                         function_to_string((*function), &buf);
2984                         add_next_index_stringl(return_value, buf.c, buf.len, 1);
2985                         smart_str_free(&buf);
2986                         zend_hash_move_forward_ex(&sdl->functions, &pos);
2987                 }
2988         }
2989 }
2990 /* }}} */
2991 
2992 
2993 /* {{{ proto array SoapClient::__getTypes ( void )
2994    Returns list of SOAP types */
2995 PHP_METHOD(SoapClient, __getTypes)
2996 {
2997         sdlPtr sdl;
2998         HashPosition pos;
2999 
3000         FETCH_THIS_SDL(sdl);
3001 
3002         if (zend_parse_parameters_none() == FAILURE) {
3003                 return;
3004         }
3005 
3006         if (sdl) {
3007                 sdlTypePtr *type;
3008                 smart_str buf = {0};
3009 
3010                 array_init(return_value);
3011                 if (sdl->types) {
3012                         zend_hash_internal_pointer_reset_ex(sdl->types, &pos);
3013                         while (zend_hash_get_current_data_ex(sdl->types, (void **)&type, &pos) != FAILURE) {
3014                                 type_to_string((*type), &buf, 0);
3015                                 add_next_index_stringl(return_value, buf.c, buf.len, 1);
3016                                 smart_str_free(&buf);
3017                                 zend_hash_move_forward_ex(sdl->types, &pos);
3018                         }
3019                 }
3020         }
3021 }
3022 /* }}} */
3023 
3024 
3025 /* {{{ proto string SoapClient::__getLastRequest ( void )
3026    Returns last SOAP request */
3027 PHP_METHOD(SoapClient, __getLastRequest)
3028 {
3029         zval **tmp;
3030 
3031         if (zend_parse_parameters_none() == FAILURE) {
3032                 return;
3033         }
3034 
3035         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request", sizeof("__last_request"), (void **)&tmp) == SUCCESS &&
3036             Z_TYPE_PP(tmp) == IS_STRING) {
3037                 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3038         }
3039         RETURN_NULL();
3040 }
3041 /* }}} */
3042 
3043 
3044 /* {{{ proto object SoapClient::__getLastResponse ( void )
3045    Returns last SOAP response */
3046 PHP_METHOD(SoapClient, __getLastResponse)
3047 {
3048         zval **tmp;
3049 
3050         if (zend_parse_parameters_none() == FAILURE) {
3051                 return;
3052         }
3053 
3054         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"), (void **)&tmp) == SUCCESS &&
3055             Z_TYPE_PP(tmp) == IS_STRING) {
3056                 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3057         }
3058         RETURN_NULL();
3059 }
3060 /* }}} */
3061 
3062 
3063 /* {{{ proto string SoapClient::__getLastRequestHeaders(void)
3064    Returns last SOAP request headers */
3065 PHP_METHOD(SoapClient, __getLastRequestHeaders)
3066 {
3067         zval **tmp;
3068 
3069         if (zend_parse_parameters_none() == FAILURE) {
3070                 return;
3071         }
3072 
3073         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request_headers", sizeof("__last_request_headers"), (void **)&tmp) == SUCCESS &&
3074             Z_TYPE_PP(tmp) == IS_STRING) {
3075                 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3076         }
3077         RETURN_NULL();
3078 }
3079 /* }}} */
3080 
3081 
3082 /* {{{ proto string SoapClient::__getLastResponseHeaders(void)
3083    Returns last SOAP response headers */
3084 PHP_METHOD(SoapClient, __getLastResponseHeaders)
3085 {
3086         zval **tmp;
3087 
3088         if (zend_parse_parameters_none() == FAILURE) {
3089                 return;
3090         }
3091 
3092         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response_headers", sizeof("__last_response_headers"), (void **)&tmp) == SUCCESS &&
3093             Z_TYPE_PP(tmp) == IS_STRING) {
3094                 RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3095         }
3096         RETURN_NULL();
3097 }
3098 /* }}} */
3099 
3100 
3101 /* {{{ proto string SoapClient::__doRequest()
3102    SoapClient::__doRequest() */
3103 PHP_METHOD(SoapClient, __doRequest)
3104 {
3105   char *buf, *location, *action;
3106   int   buf_size, location_size, action_size;
3107   long  version;
3108   long  one_way = 0;
3109 
3110         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl|l",
3111             &buf, &buf_size,
3112             &location, &location_size,
3113             &action, &action_size,
3114             &version, &one_way) == FAILURE) {
3115                 return;
3116         }
3117         if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) {
3118                 one_way = 0;
3119         }
3120         if (one_way) {
3121                 if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version, NULL, NULL TSRMLS_CC)) {
3122                         RETURN_EMPTY_STRING();
3123                 }
3124         } else if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version,
3125             &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC)) {
3126                 return_value->type = IS_STRING;
3127                 return;
3128         }
3129         RETURN_NULL();
3130 }
3131 /* }}} */
3132 
3133 /* {{{ proto void SoapClient::__setCookie(string name [, strung value])
3134    Sets cookie thet will sent with SOAP request.
3135    The call to this function will effect all following calls of SOAP methods.
3136    If value is not specified cookie is removed. */
3137 PHP_METHOD(SoapClient, __setCookie)
3138 {
3139         char *name;
3140         char *val = NULL;
3141         int  name_len, val_len = 0;
3142         zval **cookies;
3143 
3144         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name, &name_len, &val, &val_len) == FAILURE) {
3145                 return;
3146         }
3147 
3148         if (val == NULL) {
3149                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == SUCCESS &&
3150                     Z_TYPE_PP(cookies) == IS_ARRAY) {
3151                         zend_hash_del(Z_ARRVAL_PP(cookies), name, name_len+1);
3152                 }
3153         } else {
3154                 zval *zcookie;
3155 
3156                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == FAILURE ||
3157                     Z_TYPE_PP(cookies) != IS_ARRAY) {
3158                         zval *tmp_cookies;
3159 
3160                         MAKE_STD_ZVAL(tmp_cookies);
3161                         array_init(tmp_cookies);
3162                         zend_hash_update(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), &tmp_cookies, sizeof(zval *), (void **)&cookies);
3163                 }
3164 
3165                 ALLOC_INIT_ZVAL(zcookie);
3166                 array_init(zcookie);
3167                 add_index_stringl(zcookie, 0, val, val_len, 1);
3168                 add_assoc_zval_ex(*cookies, name, name_len+1, zcookie);
3169         }
3170 }
3171 /* }}} */
3172 
3173 /* {{{ proto array SoapClient::__getCookies ( void )
3174    Returns list of cookies */
3175 PHP_METHOD(SoapClient, __getCookies)
3176 {
3177         zval **cookies, *tmp;
3178 
3179         if (zend_parse_parameters_none() == FAILURE) {
3180                 return;
3181         }
3182 
3183         array_init(return_value);
3184 
3185         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) != FAILURE &&
3186             Z_TYPE_PP(cookies) == IS_ARRAY) {
3187                 zend_hash_copy(Z_ARRVAL_P(return_value), Z_ARRVAL_P(*cookies), (copy_ctor_func_t) zval_add_ref, (void *)&tmp, sizeof(zval*));
3188         }
3189 }
3190 /* }}} */
3191 
3192 /* {{{ proto void SoapClient::__setSoapHeaders(array SoapHeaders)
3193    Sets SOAP headers for subsequent calls (replaces any previous
3194    values).
3195    If no value is specified, all of the headers are removed. */
3196 PHP_METHOD(SoapClient, __setSoapHeaders)
3197 {
3198         zval *headers = NULL;
3199 
3200         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &headers) == FAILURE) {
3201                 return;
3202         }
3203 
3204         if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
3205                 zend_hash_del(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"));
3206         } else if (Z_TYPE_P(headers) == IS_ARRAY) {
3207                 zval *default_headers;
3208 
3209                 verify_soap_headers_array(Z_ARRVAL_P(headers) TSRMLS_CC);
3210                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &default_headers)==FAILURE) {
3211                         add_property_zval(this_ptr, "__default_headers", headers);
3212                 }
3213         } else if (Z_TYPE_P(headers) == IS_OBJECT &&
3214                    instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
3215                 zval *default_headers;
3216                 ALLOC_INIT_ZVAL(default_headers);
3217                 array_init(default_headers);
3218                 Z_ADDREF_P(headers);
3219                 add_next_index_zval(default_headers, headers);
3220                 Z_DELREF_P(default_headers);
3221                 add_property_zval(this_ptr, "__default_headers", default_headers);
3222         } else{
3223                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid SOAP header");
3224         }
3225         RETURN_TRUE;
3226 }
3227 /* }}} */
3228 
3229 
3230 
3231 /* {{{ proto string SoapClient::__setLocation([string new_location])
3232    Sets the location option (the endpoint URL that will be touched by the
3233    following SOAP requests).
3234    If new_location is not specified or null then SoapClient will use endpoint
3235    from WSDL file.
3236    The function returns old value of location options. */
3237 PHP_METHOD(SoapClient, __setLocation)
3238 {
3239         char *location = NULL;
3240         int  location_len = 0;
3241         zval **tmp;
3242 
3243         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &location, &location_len) == FAILURE) {
3244                 return;
3245         }
3246 
3247         if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
3248                 RETVAL_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
3249         } else {
3250           RETVAL_NULL();
3251         }
3252 
3253         if (location && location_len) {
3254                 add_property_stringl(this_ptr, "location", location, location_len, 1);
3255         } else {
3256                 zend_hash_del(Z_OBJPROP_P(this_ptr), "location", sizeof("location"));
3257         }
3258 }
3259 /* }}} */
3260 
3261 static void clear_soap_fault(zval *obj TSRMLS_DC)
3262 {
3263         if (obj != NULL && obj->type == IS_OBJECT) {
3264                 zend_hash_del(Z_OBJPROP_P(obj), "__soap_fault", sizeof("__soap_fault"));
3265         }
3266 }
3267 
3268 zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail TSRMLS_DC)
3269 {
3270         zval *fault;
3271         ALLOC_INIT_ZVAL(fault);
3272         set_soap_fault(fault, NULL, fault_code, fault_string, fault_actor, fault_detail, NULL TSRMLS_CC);
3273         Z_DELREF_P(fault);
3274 
3275         add_property_zval(obj, "__soap_fault", fault);
3276         return fault;
3277 }
3278 
3279 static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC)
3280 {
3281         if (Z_TYPE_P(obj) != IS_OBJECT) {
3282                 object_init_ex(obj, soap_fault_class_entry);
3283         }
3284 
3285         add_property_string(obj, "faultstring", fault_string ? fault_string : "", 1);
3286         zend_update_property_string(zend_exception_get_default(TSRMLS_C), obj, "message", sizeof("message")-1, (fault_string ? fault_string : "") TSRMLS_CC);
3287 
3288         if (fault_code != NULL) {
3289                 int soap_version = SOAP_GLOBAL(soap_version);
3290 
3291                 if (fault_code_ns) {
3292                         add_property_string(obj, "faultcode", fault_code, 1);
3293                         add_property_string(obj, "faultcodens", fault_code_ns, 1);
3294                 } else {
3295                         if (soap_version == SOAP_1_1) {
3296                                 add_property_string(obj, "faultcode", fault_code, 1);
3297                                 if (strcmp(fault_code,"Client") == 0 ||
3298                                     strcmp(fault_code,"Server") == 0 ||
3299                                     strcmp(fault_code,"VersionMismatch") == 0 ||
3300                                   strcmp(fault_code,"MustUnderstand") == 0) {
3301                                         add_property_string(obj, "faultcodens", SOAP_1_1_ENV_NAMESPACE, 1);
3302                                 }
3303                         } else if (soap_version == SOAP_1_2) {
3304                                 if (strcmp(fault_code,"Client") == 0) {
3305                                         add_property_string(obj, "faultcode", "Sender", 1);
3306                                         add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
3307                                 } else if (strcmp(fault_code,"Server") == 0) {
3308                                         add_property_string(obj, "faultcode", "Receiver", 1);
3309                                         add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
3310                                 } else if (strcmp(fault_code,"VersionMismatch") == 0 ||
3311                                            strcmp(fault_code,"MustUnderstand") == 0 ||
3312                                            strcmp(fault_code,"DataEncodingUnknown") == 0) {
3313                                         add_property_string(obj, "faultcode", fault_code, 1);
3314                                         add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
3315                                 } else {
3316                                         add_property_string(obj, "faultcode", fault_code, 1);
3317                                 }
3318                         }
3319                 }
3320         }
3321         if (fault_actor != NULL) {
3322                 add_property_string(obj, "faultactor", fault_actor, 1);
3323         }
3324         if (fault_detail != NULL) {
3325                 add_property_zval(obj, "detail", fault_detail);
3326         }
3327         if (name != NULL) {
3328                 add_property_string(obj, "_name", name, 1);
3329         }
3330 }
3331 
3332 static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, int *num_params, zval ***parameters TSRMLS_DC)
3333 {
3334         int cur_param = 0,num_of_params = 0;
3335         zval **tmp_parameters = NULL;
3336 
3337         if (function != NULL) {
3338                 sdlParamPtr *param;
3339                 xmlNodePtr val;
3340                 int     use_names = 0;
3341 
3342                 if (function->requestParameters == NULL) {
3343                         return;
3344                 }
3345                 num_of_params = zend_hash_num_elements(function->requestParameters);
3346                 zend_hash_internal_pointer_reset(function->requestParameters);
3347                 while (zend_hash_get_current_data(function->requestParameters, (void **)&param) == SUCCESS) {
3348                         if (get_node(params, (*param)->paramName) != NULL) {
3349                                 use_names = 1;
3350                         }
3351                         zend_hash_move_forward(function->requestParameters);
3352                 }
3353                 if (use_names) {
3354                         tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0);
3355                         zend_hash_internal_pointer_reset(function->requestParameters);
3356                         while (zend_hash_get_current_data(function->requestParameters, (void **)&param) == SUCCESS) {
3357                                 val = get_node(params, (*param)->paramName);
3358                                 if (!val) {
3359                                         /* TODO: may be "nil" is not OK? */
3360                                         MAKE_STD_ZVAL(tmp_parameters[cur_param]);
3361                                         ZVAL_NULL(tmp_parameters[cur_param]);
3362                                 } else {
3363                                         tmp_parameters[cur_param] = master_to_zval((*param)->encode, val TSRMLS_CC);
3364                                 }
3365                                 cur_param++;
3366 
3367                                 zend_hash_move_forward(function->requestParameters);
3368                         }
3369                         (*parameters) = tmp_parameters;
3370                         (*num_params) = num_of_params;
3371                         return;
3372                 }
3373         }
3374         if (params) {
3375                 xmlNodePtr trav;
3376 
3377                 num_of_params = 0;
3378                 trav = params;
3379                 while (trav != NULL) {
3380                         if (trav->type == XML_ELEMENT_NODE) {
3381                                 num_of_params++;
3382                         }
3383                         trav = trav->next;
3384                 }
3385 
3386                 if (num_of_params == 1 &&
3387                     function &&
3388                     function->binding &&
3389                     function->binding->bindingType == BINDING_SOAP &&
3390                     ((sdlSoapBindingFunctionPtr)function->bindingAttributes)->style == SOAP_DOCUMENT &&
3391                     (function->requestParameters == NULL ||
3392                      zend_hash_num_elements(function->requestParameters) == 0) &&
3393                     strcmp((char *)params->name, function->functionName) == 0) {
3394                         num_of_params = 0;
3395                 } else if (num_of_params > 0) {
3396                         tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0);
3397 
3398                         trav = params;
3399                         while (trav != 0 && cur_param < num_of_params) {
3400                                 if (trav->type == XML_ELEMENT_NODE) {
3401                                         encodePtr enc;
3402                                         sdlParamPtr *param = NULL;
3403                                         if (function != NULL &&
3404                                             zend_hash_index_find(function->requestParameters, cur_param, (void **)&param) == FAILURE) {
3405                                                 TSRMLS_FETCH();
3406                                                 soap_server_fault("Client", "Error cannot find parameter", NULL, NULL, NULL TSRMLS_CC);
3407                                         }
3408                                         if (param == NULL) {
3409                                                 enc = NULL;
3410                                         } else {
3411                                                 enc = (*param)->encode;
3412                                         }
3413                                         tmp_parameters[cur_param] = master_to_zval(enc, trav TSRMLS_CC);
3414                                         cur_param++;
3415                                 }
3416                                 trav = trav->next;
3417                         }
3418                 }
3419         }
3420         if (num_of_params > cur_param) {
3421                 soap_server_fault("Client","Missing parameter", NULL, NULL, NULL TSRMLS_CC);
3422         }
3423         (*parameters) = tmp_parameters;
3424         (*num_params) = num_of_params;
3425 }
3426 
3427 static sdlFunctionPtr find_function(sdlPtr sdl, xmlNodePtr func, zval* function_name)
3428 {
3429         sdlFunctionPtr function;
3430 
3431         function = get_function(sdl, (char*)func->name);
3432         if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3433                 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3434                 if (fnb->style == SOAP_DOCUMENT) {
3435                         if (func->children != NULL ||
3436                             (function->requestParameters != NULL &&
3437                              zend_hash_num_elements(function->requestParameters) > 0)) {
3438                                 function = NULL;
3439                         }
3440                 }
3441         }
3442         if (sdl != NULL && function == NULL) {
3443                 function = get_doc_function(sdl, func);
3444         }
3445 
3446         INIT_ZVAL(*function_name);
3447         if (function != NULL) {
3448                 ZVAL_STRING(function_name, (char *)function->functionName, 1);
3449         } else {
3450                 ZVAL_STRING(function_name, (char *)func->name, 1);
3451         }
3452 
3453         return function;
3454 }
3455 
3456 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval ***parameters, int *version, soapHeader **headers TSRMLS_DC)
3457 {
3458         char* envelope_ns = NULL;
3459         xmlNodePtr trav,env,head,body,func;
3460         xmlAttrPtr attr;
3461         sdlFunctionPtr function;
3462 
3463         encode_reset_ns();
3464 
3465         /* Get <Envelope> element */
3466         env = NULL;
3467         trav = request->children;
3468         while (trav != NULL) {
3469                 if (trav->type == XML_ELEMENT_NODE) {
3470                         if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
3471                                 env = trav;
3472                                 *version = SOAP_1_1;
3473                                 envelope_ns = SOAP_1_1_ENV_NAMESPACE;
3474                                 SOAP_GLOBAL(soap_version) = SOAP_1_1;
3475                         } else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
3476                                 env = trav;
3477                                 *version = SOAP_1_2;
3478                                 envelope_ns = SOAP_1_2_ENV_NAMESPACE;
3479                                 SOAP_GLOBAL(soap_version) = SOAP_1_2;
3480                         } else {
3481                                 soap_server_fault("VersionMismatch", "Wrong Version", NULL, NULL, NULL TSRMLS_CC);
3482                         }
3483                 }
3484                 trav = trav->next;
3485         }
3486         if (env == NULL) {
3487                 soap_server_fault("Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, NULL TSRMLS_CC);
3488         }
3489 
3490         attr = env->properties;
3491         while (attr != NULL) {
3492                 if (attr->ns == NULL) {
3493                         soap_server_fault("Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
3494                 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3495                         if (*version == SOAP_1_2) {
3496                                 soap_server_fault("Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, NULL TSRMLS_CC);
3497                         } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3498                                 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
3499                         }
3500                 }
3501                 attr = attr->next;
3502         }
3503 
3504         /* Get <Header> element */
3505         head = NULL;
3506         trav = env->children;
3507         while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3508                 trav = trav->next;
3509         }
3510         if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
3511                 head = trav;
3512                 trav = trav->next;
3513         }
3514 
3515         /* Get <Body> element */
3516         body = NULL;
3517         while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3518                 trav = trav->next;
3519         }
3520         if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
3521                 body = trav;
3522                 trav = trav->next;
3523         }
3524         while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
3525                 trav = trav->next;
3526         }
3527         if (body == NULL) {
3528                 soap_server_fault("Client", "Body must be present in a SOAP envelope", NULL, NULL, NULL TSRMLS_CC);
3529         }
3530         attr = body->properties;
3531         while (attr != NULL) {
3532                 if (attr->ns == NULL) {
3533                         if (*version == SOAP_1_2) {
3534                                 soap_server_fault("Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
3535                         }
3536                 } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3537                         if (*version == SOAP_1_2) {
3538                                 soap_server_fault("Client", "encodingStyle cannot be specified on the Body", NULL, NULL, NULL TSRMLS_CC);
3539                         } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3540                                 soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
3541                         }
3542                 }
3543                 attr = attr->next;
3544         }
3545 
3546         if (trav != NULL && *version == SOAP_1_2) {
3547                 soap_server_fault("Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, NULL TSRMLS_CC);
3548         }
3549 
3550         func = NULL;
3551         trav = body->children;
3552         while (trav != NULL) {
3553                 if (trav->type == XML_ELEMENT_NODE) {
3554 /*
3555                         if (func != NULL) {
3556                                 soap_server_fault("Client", "looks like we got \"Body\" with several functions call", NULL, NULL, NULL TSRMLS_CC);
3557                         }
3558 */
3559                         func = trav;
3560                         break; /* FIXME: the rest of body is ignored */
3561                 }
3562                 trav = trav->next;
3563         }
3564         if (func == NULL) {
3565                 function = get_doc_function(sdl, NULL);
3566                 if (function != NULL) {
3567                         INIT_ZVAL(*function_name);
3568                         ZVAL_STRING(function_name, (char *)function->functionName, 1);
3569                 } else {
3570                         soap_server_fault("Client", "looks like we got \"Body\" without function call", NULL, NULL, NULL TSRMLS_CC);
3571                 }
3572         } else {
3573                 if (*version == SOAP_1_1) {
3574                         attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
3575                         if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3576                                 soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3577                         }
3578                 } else {
3579                         attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
3580                         if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
3581                                 soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3582                         }
3583                 }
3584                 function = find_function(sdl, func, function_name);
3585                 if (sdl != NULL && function == NULL) {
3586                         if (*version == SOAP_1_2) {
3587                                 soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL, NULL TSRMLS_CC);
3588                         } else {
3589                                 php_error(E_ERROR, "Procedure '%s' not present", func->name);
3590                         }
3591                 }
3592         }
3593 
3594         *headers = NULL;
3595         if (head) {
3596                 soapHeader *h, *last = NULL;
3597 
3598                 attr = head->properties;
3599                 while (attr != NULL) {
3600                         if (attr->ns == NULL) {
3601                                 soap_server_fault("Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
3602                         } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
3603                                 if (*version == SOAP_1_2) {
3604                                         soap_server_fault("Client", "encodingStyle cannot be specified on the Header", NULL, NULL, NULL TSRMLS_CC);
3605                                 } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3606                                         soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
3607                                 }
3608                         }
3609                         attr = attr->next;
3610                 }
3611                 trav = head->children;
3612                 while (trav != NULL) {
3613                         if (trav->type == XML_ELEMENT_NODE) {
3614                                 xmlNodePtr hdr_func = trav;
3615                                 int mustUnderstand = 0;
3616 
3617                                 if (*version == SOAP_1_1) {
3618                                         attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
3619                                         if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
3620                                                 soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3621                                         }
3622                                         attr = get_attribute_ex(hdr_func->properties,"actor",envelope_ns);
3623                                         if (attr != NULL) {
3624                                                 if (strcmp((char*)attr->children->content,SOAP_1_1_ACTOR_NEXT) != 0 &&
3625                                                     (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
3626                                                   goto ignore_header;
3627                                                 }
3628                                         }
3629                                 } else if (*version == SOAP_1_2) {
3630                                         attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
3631                                         if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
3632                                                 soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
3633                                         }
3634                                         attr = get_attribute_ex(hdr_func->properties,"role",envelope_ns);
3635                                         if (attr != NULL) {
3636                                                 if (strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_UNLIMATERECEIVER) != 0 &&
3637                                                     strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_NEXT) != 0 &&
3638                                                     (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
3639                                                   goto ignore_header;
3640                                                 }
3641                                         }
3642                                 }
3643                                 attr = get_attribute_ex(hdr_func->properties,"mustUnderstand",envelope_ns);
3644                                 if (attr) {
3645                                         if (strcmp((char*)attr->children->content,"1") == 0 ||
3646                                             strcmp((char*)attr->children->content,"true") == 0) {
3647                                                 mustUnderstand = 1;
3648                                         } else if (strcmp((char*)attr->children->content,"0") == 0 ||
3649                                                    strcmp((char*)attr->children->content,"false") == 0) {
3650                                                 mustUnderstand = 0;
3651                                         } else {
3652                                                 soap_server_fault("Client","mustUnderstand value is not boolean", NULL, NULL, NULL TSRMLS_CC);
3653                                         }
3654                                 }
3655                                 h = emalloc(sizeof(soapHeader));
3656                                 memset(h, 0, sizeof(soapHeader));
3657                                 h->mustUnderstand = mustUnderstand;
3658                                 h->function = find_function(sdl, hdr_func, &h->function_name);
3659                                 if (!h->function && sdl && function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3660                                         sdlSoapBindingFunctionHeaderPtr *hdr;
3661                                         sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3662                                         if (fnb->input.headers) {
3663                                                 smart_str key = {0};
3664 
3665                                                 if (hdr_func->ns) {
3666                                                         smart_str_appends(&key, (char*)hdr_func->ns->href);
3667                                                         smart_str_appendc(&key, ':');
3668                                                 }
3669                                                 smart_str_appendl(&key, Z_STRVAL(h->function_name), Z_STRLEN(h->function_name));
3670                                                 smart_str_0(&key);
3671                                                 if (zend_hash_find(fnb->input.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
3672                                                         h->hdr = *hdr;
3673                                                 }
3674                                                 smart_str_free(&key);
3675                                         }
3676                                 }
3677                                 if (h->hdr) {
3678                                         h->num_params = 1;
3679                                         h->parameters = emalloc(sizeof(zval*));
3680                                         h->parameters[0] = master_to_zval(h->hdr->encode, hdr_func TSRMLS_CC);
3681                                 } else {
3682                                         if (h->function && h->function->binding && h->function->binding->bindingType == BINDING_SOAP) {
3683                                                 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)h->function->bindingAttributes;
3684                                                 if (fnb->style == SOAP_RPC) {
3685                                                         hdr_func = hdr_func->children;
3686                                                 }
3687                                         }
3688                                         deserialize_parameters(hdr_func, h->function, &h->num_params, &h->parameters TSRMLS_CC);
3689                                 }
3690                                 INIT_ZVAL(h->retval);
3691                                 if (last == NULL) {
3692                                         *headers = h;
3693                                 } else {
3694                                         last->next = h;
3695                                 }
3696                                 last = h;
3697                         }
3698 ignore_header:
3699                         trav = trav->next;
3700                 }
3701         }
3702 
3703         if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
3704                 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3705                 if (fnb->style == SOAP_RPC) {
3706                         func = func->children;
3707                 }
3708         } else {
3709                 func = func->children;
3710         }
3711         deserialize_parameters(func, function, num_params, parameters TSRMLS_CC);
3712 
3713         encode_finish();
3714 
3715         return function;
3716 }
3717 
3718 static void set_soap_header_attributes(xmlNodePtr h, HashTable *ht, int version)
3719 {
3720         zval **tmp;
3721 
3722         if (zend_hash_find(ht, "mustUnderstand", sizeof("mustUnderstand"), (void**)&tmp) == SUCCESS &&
3723             Z_TYPE_PP(tmp) == IS_BOOL && Z_LVAL_PP(tmp)) {
3724                 if (version == SOAP_1_1) {
3725                         xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1"));
3726                 } else {
3727                         xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true"));
3728                 }
3729         }
3730         if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) {
3731                 if (Z_TYPE_PP(tmp) == IS_STRING) {
3732                         if (version == SOAP_1_1) {
3733                                 xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp)));
3734                         } else {
3735                                 xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp)));
3736                         }
3737                 } else if (Z_TYPE_PP(tmp) == IS_LONG) {
3738                         if (version == SOAP_1_1) {
3739                                 if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
3740                                         xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT));
3741                                 }
3742                         } else {
3743                                 if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
3744                                         xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT));
3745                                 } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NONE) {
3746                                         xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE));
3747                                 } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) {
3748                                         xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER));
3749                                 }
3750                         }
3751                 }
3752         }
3753 }
3754 
3755 static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main, xmlNodePtr *node TSRMLS_DC)
3756 {
3757         xmlNodePtr method = NULL, param;
3758         sdlParamPtr parameter = NULL;
3759         int param_count;
3760         int style, use;
3761         xmlNsPtr ns = NULL;
3762 
3763         if (function != NULL && function->binding->bindingType == BINDING_SOAP) {
3764                 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
3765 
3766                 style = fnb->style;
3767                 use = fnb->output.use;
3768                 if (style == SOAP_RPC) {
3769                         ns = encode_add_ns(body, fnb->output.ns);
3770                         if (function->responseName) {
3771                                 method = xmlNewChild(body, ns, BAD_CAST(function->responseName), NULL);
3772                         } else if (function->responseParameters) {
3773                                 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
3774                         }
3775                 }
3776         } else {
3777                 style = main?SOAP_RPC:SOAP_DOCUMENT;
3778                 use = main?SOAP_ENCODED:SOAP_LITERAL;
3779                 if (style == SOAP_RPC) {
3780                         ns = encode_add_ns(body, uri);
3781                         method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
3782                 }
3783         }
3784 
3785         if (function != NULL) {
3786                 if (function->responseParameters) {
3787                         param_count = zend_hash_num_elements(function->responseParameters);
3788                 } else {
3789                   param_count = 0;
3790                 }
3791         } else {
3792           param_count = 1;
3793         }
3794 
3795         if (param_count == 1) {
3796                 parameter = get_param(function, NULL, 0, TRUE);
3797 
3798                 if (style == SOAP_RPC) {
3799                   xmlNode *rpc_result;
3800                         if (main && version == SOAP_1_2) {
3801                                 xmlNs *rpc_ns = xmlNewNs(body, BAD_CAST(RPC_SOAP12_NAMESPACE), BAD_CAST(RPC_SOAP12_NS_PREFIX));
3802                                 rpc_result = xmlNewChild(method, rpc_ns, BAD_CAST("result"), NULL);
3803                                 param = serialize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
3804                                 xmlNodeSetContent(rpc_result,param->name);
3805                         } else {
3806                                 param = serialize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
3807                         }
3808                 } else {
3809                         param = serialize_parameter(parameter, ret, 0, "return", use, body TSRMLS_CC);
3810                         if (function && function->binding->bindingType == BINDING_SOAP) {
3811                                 if (parameter && parameter->element) {
3812                                         ns = encode_add_ns(param, parameter->element->namens);
3813                                         xmlNodeSetName(param, BAD_CAST(parameter->element->name));
3814                                         xmlSetNs(param, ns);
3815                                 }
3816                         } else if (strcmp((char*)param->name,"return") == 0) {
3817                                 ns = encode_add_ns(param, uri);
3818                                 xmlNodeSetName(param, BAD_CAST(function_name));
3819                                 xmlSetNs(param, ns);
3820                         }
3821                 }
3822         } else if (param_count > 1 && Z_TYPE_P(ret) == IS_ARRAY) {
3823                 HashPosition pos;
3824                 zval **data;
3825                 int i = 0;
3826 
3827                 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(ret), &pos);
3828                 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(ret), (void **)&data, &pos) != FAILURE) {
3829                         char *param_name = NULL;
3830                         unsigned int param_name_len;
3831                         ulong param_index = i;
3832 
3833                         zend_hash_get_current_key_ex(Z_ARRVAL_P(ret), &param_name, &param_name_len, &param_index, 0, &pos);
3834                         parameter = get_param(function, param_name, param_index, TRUE);
3835                         if (style == SOAP_RPC) {
3836                                 param = serialize_parameter(parameter, *data, i, param_name, use, method TSRMLS_CC);
3837                         } else {
3838                                 param = serialize_parameter(parameter, *data, i, param_name, use, body TSRMLS_CC);
3839                                 if (function && function->binding->bindingType == BINDING_SOAP) {
3840                                         if (parameter && parameter->element) {
3841                                                 ns = encode_add_ns(param, parameter->element->namens);
3842                                                 xmlNodeSetName(param, BAD_CAST(parameter->element->name));
3843                                                 xmlSetNs(param, ns);
3844                                         }
3845                                 }
3846                         }
3847 
3848                         zend_hash_move_forward_ex(Z_ARRVAL_P(ret), &pos);
3849                         i++;
3850                 }
3851         }
3852         if (use == SOAP_ENCODED && version == SOAP_1_2 && method != NULL) {
3853                 xmlSetNsProp(method, body->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
3854         }
3855         if (node) {
3856                 *node = method;
3857         }
3858         return use;
3859 }
3860 
3861 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name, char *uri, zval *ret, soapHeader* headers, int version TSRMLS_DC)
3862 {
3863         xmlDocPtr doc;
3864         xmlNodePtr envelope = NULL, body, param;
3865         xmlNsPtr ns = NULL;
3866         int use = SOAP_LITERAL;
3867         xmlNodePtr head = NULL;
3868 
3869         encode_reset_ns();
3870 
3871         doc = xmlNewDoc(BAD_CAST("1.0"));
3872         doc->charset = XML_CHAR_ENCODING_UTF8;
3873         doc->encoding = xmlCharStrdup("UTF-8");
3874 
3875         if (version == SOAP_1_1) {
3876                 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
3877                 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
3878                 xmlSetNs(envelope,ns);
3879         } else if (version == SOAP_1_2) {
3880                 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
3881                 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
3882                 xmlSetNs(envelope,ns);
3883         } else {
3884                 soap_server_fault("Server", "Unknown SOAP version", NULL, NULL, NULL TSRMLS_CC);
3885         }
3886         xmlDocSetRootElement(doc, envelope);
3887 
3888         if (Z_TYPE_P(ret) == IS_OBJECT &&
3889             instanceof_function(Z_OBJCE_P(ret), soap_fault_class_entry TSRMLS_CC)) {
3890           char *detail_name;
3891                 HashTable* prop;
3892                 zval **tmp;
3893                 sdlFaultPtr fault = NULL;
3894                 char *fault_ns = NULL;
3895 
3896                 prop = Z_OBJPROP_P(ret);
3897 
3898                 if (headers &&
3899                     zend_hash_find(prop, "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS) {
3900                         encodePtr hdr_enc = NULL;
3901                         int hdr_use = SOAP_LITERAL;
3902                         zval *hdr_ret  = *tmp;
3903                         char *hdr_ns   = headers->hdr?headers->hdr->ns:NULL;
3904                         char *hdr_name = Z_STRVAL(headers->function_name);
3905 
3906                         head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
3907                         if (Z_TYPE_P(hdr_ret) == IS_OBJECT &&
3908                             instanceof_function(Z_OBJCE_P(hdr_ret), soap_header_class_entry TSRMLS_CC)) {
3909                                 HashTable* ht = Z_OBJPROP_P(hdr_ret);
3910                                 sdlSoapBindingFunctionHeaderPtr *hdr;
3911                                 smart_str key = {0};
3912 
3913                                 if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS &&
3914                               Z_TYPE_PP(tmp) == IS_STRING) {
3915                                         smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3916                                         smart_str_appendc(&key, ':');
3917                                         hdr_ns = Z_STRVAL_PP(tmp);
3918                                 }
3919                                 if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS &&
3920                                     Z_TYPE_PP(tmp) == IS_STRING) {
3921                                         smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
3922                                         hdr_name = Z_STRVAL_PP(tmp);
3923                                 }
3924                                 smart_str_0(&key);
3925                                 if (headers->hdr && headers->hdr->headerfaults &&
3926                                     zend_hash_find(headers->hdr->headerfaults, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
3927                                         hdr_enc = (*hdr)->encode;
3928                                         hdr_use = (*hdr)->use;
3929                                 }
3930                                 smart_str_free(&key);
3931                                 if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
3932                                         hdr_ret = *tmp;
3933                                 } else {
3934                                         hdr_ret = NULL;
3935                                 }
3936                         }
3937 
3938                         if (headers->function) {
3939                                 if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0, NULL TSRMLS_CC) == SOAP_ENCODED) {
3940                                         use = SOAP_ENCODED;
3941                                 }
3942                         } else {
3943                                 xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC);
3944                                 if (hdr_name) {
3945                                         xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
3946                                 }
3947                                 if (hdr_ns) {
3948                                         xmlNsPtr nsptr = encode_add_ns(xmlHdr, hdr_ns);
3949                                         xmlSetNs(xmlHdr, nsptr);
3950                                 }
3951                         }
3952                 }
3953 
3954                 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
3955                 param = xmlNewChild(body, ns, BAD_CAST("Fault"), NULL);
3956 
3957                 if (zend_hash_find(prop, "faultcodens", sizeof("faultcodens"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
3958                         fault_ns = Z_STRVAL_PP(tmp);
3959                 }
3960                 use = SOAP_LITERAL;
3961                 if (zend_hash_find(prop, "_name", sizeof("_name"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
3962                         sdlFaultPtr *tmp_fault;
3963                         if (function && function->faults &&
3964                             zend_hash_find(function->faults, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)+1, (void**)&tmp_fault) == SUCCESS) {
3965                           fault = *tmp_fault;
3966                                 if (function->binding &&
3967                                     function->binding->bindingType == BINDING_SOAP &&
3968                                     fault->bindingAttributes) {
3969                                         sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3970                                         use = fb->use;
3971                                         if (fault_ns == NULL) {
3972                                                 fault_ns = fb->ns;
3973                                         }
3974                                 }
3975                         }
3976                 } else if (function && function->faults &&
3977                            zend_hash_num_elements(function->faults) == 1) {
3978 
3979                         zend_hash_internal_pointer_reset(function->faults);
3980                         zend_hash_get_current_data(function->faults, (void**)&fault);
3981                         fault = *(sdlFaultPtr*)fault;
3982                         if (function->binding &&
3983                             function->binding->bindingType == BINDING_SOAP &&
3984                             fault->bindingAttributes) {
3985                                 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3986                                 use = fb->use;
3987                                 if (fault_ns == NULL) {
3988                                   fault_ns = fb->ns;
3989                                 }
3990                         }
3991                 }
3992 
3993                 if (fault_ns == NULL &&
3994                     fault &&
3995                     fault->details &&
3996                     zend_hash_num_elements(fault->details) == 1) {
3997                         sdlParamPtr sparam;
3998 
3999                         zend_hash_internal_pointer_reset(fault->details);
4000                         zend_hash_get_current_data(fault->details, (void**)&sparam);
4001                         sparam = *(sdlParamPtr*)sparam;
4002                         if (sparam->element) {
4003                                 fault_ns = sparam->element->namens;
4004                         }
4005                 }
4006 
4007                 if (version == SOAP_1_1) {
4008                         if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS &&
4009                             Z_TYPE_PP(tmp) == IS_STRING) {
4010                                 size_t new_len;
4011                                 xmlNodePtr node = xmlNewNode(NULL, BAD_CAST("faultcode"));
4012                                 char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
4013                                 xmlAddChild(param, node);
4014                                 if (fault_ns) {
4015                                         xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
4016                                         xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
4017                                         xmlNodeSetContent(node, code);
4018                                         xmlFree(code);
4019                                 } else {
4020                                         xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
4021                                 }
4022                                 str_efree(str);
4023                         }
4024                         if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
4025                                 xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param TSRMLS_CC);
4026                                 xmlNodeSetName(node, BAD_CAST("faultstring"));
4027                         }
4028                         if (zend_hash_find(prop, "faultactor", sizeof("faultactor"), (void**)&tmp) == SUCCESS) {
4029                                 xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param TSRMLS_CC);
4030                                 xmlNodeSetName(node, BAD_CAST("faultactor"));
4031                         }
4032                         detail_name = "detail";
4033                 } else {
4034                         if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS &&
4035                             Z_TYPE_PP(tmp) == IS_STRING) {
4036                                 size_t new_len;
4037                                 xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Code"), NULL);
4038                                 char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
4039                                 node = xmlNewChild(node, ns, BAD_CAST("Value"), NULL);
4040                                 if (fault_ns) {
4041                                         xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
4042                                         xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
4043                                         xmlNodeSetContent(node, code);
4044                                         xmlFree(code);
4045                                 } else {
4046                                         xmlNodeSetContentLen(node, BAD_CAST(str), (int)new_len);
4047                                 }
4048                                 str_efree(str);
4049                         }
4050                         if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
4051                                 xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Reason"), NULL);
4052                                 node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, node TSRMLS_CC);
4053                                 xmlNodeSetName(node, BAD_CAST("Text"));
4054                                 xmlSetNs(node, ns);
4055                         }
4056                         detail_name = SOAP_1_2_ENV_NS_PREFIX":Detail";
4057                 }
4058                 if (fault && fault->details && zend_hash_num_elements(fault->details) == 1) {
4059                         xmlNodePtr node;
4060                         zval *detail = NULL;
4061                         sdlParamPtr sparam;
4062                         xmlNodePtr x;
4063 
4064                         if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS &&
4065                             Z_TYPE_PP(tmp) != IS_NULL) {
4066                                 detail = *tmp;
4067                         }
4068                         node = xmlNewNode(NULL, BAD_CAST(detail_name));
4069                         xmlAddChild(param, node);
4070 
4071                         zend_hash_internal_pointer_reset(fault->details);
4072                         zend_hash_get_current_data(fault->details, (void**)&sparam);
4073                         sparam = *(sdlParamPtr*)sparam;
4074 
4075                         if (detail &&
4076                             Z_TYPE_P(detail) == IS_OBJECT &&
4077                             sparam->element &&
4078                             zend_hash_num_elements(Z_OBJPROP_P(detail)) == 1 &&
4079                             zend_hash_find(Z_OBJPROP_P(detail), sparam->element->name, strlen(sparam->element->name)+1, (void**)&tmp) == SUCCESS) {
4080                                 detail = *tmp;
4081                         }
4082 
4083                         x = serialize_parameter(sparam, detail, 1, NULL, use, node TSRMLS_CC);
4084 
4085                         if (function &&
4086                             function->binding &&
4087                             function->binding->bindingType == BINDING_SOAP &&
4088                             function->bindingAttributes) {
4089                                 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4090                                 if (fnb->style == SOAP_RPC && !sparam->element) {
4091                                   if (fault->bindingAttributes) {
4092                                                 sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
4093                                                 if (fb->ns) {
4094                                                         xmlNsPtr ns = encode_add_ns(x, fb->ns);
4095                                                         xmlSetNs(x, ns);
4096                                                 }
4097                                         }
4098                                 } else {
4099                                         if (sparam->element) {
4100                                                 ns = encode_add_ns(x, sparam->element->namens);
4101                                                 xmlNodeSetName(x, BAD_CAST(sparam->element->name));
4102                                                 xmlSetNs(x, ns);
4103                                         }
4104                                 }
4105                         }
4106                         if (use == SOAP_ENCODED && version == SOAP_1_2) {
4107                                 xmlSetNsProp(x, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
4108                         }
4109                 } else if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS &&
4110                     Z_TYPE_PP(tmp) != IS_NULL) {
4111                         serialize_zval(*tmp, NULL, detail_name, use, param TSRMLS_CC);
4112                 }
4113         } else {
4114 
4115                 if (headers) {
4116                         soapHeader *h;
4117 
4118                         head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
4119                         h = headers;
4120                         while (h != NULL) {
4121                                 if (Z_TYPE(h->retval) != IS_NULL) {
4122                                         encodePtr hdr_enc = NULL;
4123                                         int hdr_use = SOAP_LITERAL;
4124                                         zval *hdr_ret = &h->retval;
4125                                         char *hdr_ns   = h->hdr?h->hdr->ns:NULL;
4126                                         char *hdr_name = Z_STRVAL(h->function_name);
4127                                         HashTable *ht = NULL;
4128 
4129                                         if (Z_TYPE(h->retval) == IS_OBJECT &&
4130                                             instanceof_function(Z_OBJCE(h->retval), soap_header_class_entry TSRMLS_CC)) {
4131                                                 zval **tmp;
4132                                                 sdlSoapBindingFunctionHeaderPtr *hdr;
4133                                                 smart_str key = {0};
4134 
4135                                                 ht = Z_OBJPROP(h->retval);
4136                                                 if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS &&
4137                                               Z_TYPE_PP(tmp) == IS_STRING) {
4138                                                         smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
4139                                                         smart_str_appendc(&key, ':');
4140                                                         hdr_ns = Z_STRVAL_PP(tmp);
4141                                                 }
4142                                                 if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS &&
4143                                                     Z_TYPE_PP(tmp) == IS_STRING) {
4144                                                         smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
4145                                                         hdr_name = Z_STRVAL_PP(tmp);
4146                                                 }
4147                                                 smart_str_0(&key);
4148                                                 if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
4149                                                         sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4150 
4151                                                         if (fnb->output.headers &&
4152                                                             zend_hash_find(fnb->output.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
4153                                                                 hdr_enc = (*hdr)->encode;
4154                                                                 hdr_use = (*hdr)->use;
4155                                                         }
4156                                                 }
4157                                                 smart_str_free(&key);
4158                                                 if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
4159                                                         hdr_ret = *tmp;
4160                                                 } else {
4161                                                         hdr_ret = NULL;
4162                                                 }
4163                                         }
4164 
4165                                         if (h->function) {
4166                                                 xmlNodePtr xmlHdr = NULL;
4167 
4168                                                 if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0, &xmlHdr TSRMLS_CC) == SOAP_ENCODED) {
4169                                                         use = SOAP_ENCODED;
4170                                                 }
4171                                                 if (ht) {
4172                                                         set_soap_header_attributes(xmlHdr, ht, version);
4173                                                 }
4174                                         } else {
4175                                                 xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head TSRMLS_CC);
4176                                                 if (hdr_name) {
4177                                                         xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
4178                                                 }
4179                                                 if (hdr_ns) {
4180                                                         xmlNsPtr nsptr = encode_add_ns(xmlHdr,hdr_ns);
4181                                                         xmlSetNs(xmlHdr, nsptr);
4182                                                 }
4183                                                 if (ht) {
4184                                                         set_soap_header_attributes(xmlHdr, ht, version);
4185                                                 }
4186                                         }
4187                                 }
4188                                 h = h->next;
4189                         }
4190 
4191                         if (head->children == NULL) {
4192                                 xmlUnlinkNode(head);
4193                                 xmlFreeNode(head);
4194                         }
4195                 }
4196 
4197                 body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
4198 
4199                 if (serialize_response_call2(body, function, function_name, uri, ret, version, 1, NULL TSRMLS_CC) == SOAP_ENCODED) {
4200                         use = SOAP_ENCODED;
4201                 }
4202 
4203         }
4204 
4205         if (use == SOAP_ENCODED) {
4206                 xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
4207                 if (version == SOAP_1_1) {
4208                         xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
4209                         xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
4210                 } else if (version == SOAP_1_2) {
4211                         xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
4212                 }
4213         }
4214 
4215         encode_finish();
4216 
4217         if (function && function->responseName == NULL &&
4218             body->children == NULL && head == NULL) {
4219                 xmlFreeDoc(doc);
4220                 return NULL;
4221         }
4222         return doc;
4223 }
4224 
4225 static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function, char *function_name, char *uri, zval **arguments, int arg_count, int version, HashTable *soap_headers TSRMLS_DC)
4226 {
4227         xmlDoc *doc;
4228         xmlNodePtr envelope = NULL, body, method = NULL, head = NULL;
4229         xmlNsPtr ns = NULL;
4230         zval **zstyle, **zuse;
4231         int i, style, use;
4232         HashTable *hdrs = NULL;
4233 
4234         encode_reset_ns();
4235 
4236         doc = xmlNewDoc(BAD_CAST("1.0"));
4237         doc->encoding = xmlCharStrdup("UTF-8");
4238         doc->charset = XML_CHAR_ENCODING_UTF8;
4239         if (version == SOAP_1_1) {
4240                 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
4241                 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
4242                 xmlSetNs(envelope, ns);
4243         } else if (version == SOAP_1_2) {
4244                 envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
4245                 ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
4246                 xmlSetNs(envelope, ns);
4247         } else {
4248                 soap_error0(E_ERROR, "Unknown SOAP version");
4249         }
4250         xmlDocSetRootElement(doc, envelope);
4251 
4252         if (soap_headers) {
4253                 head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
4254         }
4255 
4256         body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
4257 
4258         if (function && function->binding->bindingType == BINDING_SOAP) {
4259                 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
4260 
4261                 hdrs = fnb->input.headers;
4262                 style = fnb->style;
4263                 /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
4264                 /*style = SOAP_RPC;*/
4265                 use = fnb->input.use;
4266                 if (style == SOAP_RPC) {
4267                         ns = encode_add_ns(body, fnb->input.ns);
4268                         if (function->requestName) {
4269                                 method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
4270                         } else {
4271                                 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
4272                         }
4273                 }
4274         } else {
4275                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "style", sizeof("style"), (void **)&zstyle) == SUCCESS &&
4276                     Z_TYPE_PP(zstyle) == IS_LONG) {
4277                         style = Z_LVAL_PP(zstyle);
4278                 } else {
4279                         style = SOAP_RPC;
4280                 }
4281                 /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
4282                 /*style = SOAP_RPC;*/
4283                 if (style == SOAP_RPC) {
4284                         ns = encode_add_ns(body, uri);
4285                         if (function_name) {
4286                                 method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
4287                         } else if (function && function->requestName) {
4288                                 method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
4289                         } else if (function && function->functionName) {
4290                                 method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
4291                         } else {
4292                                 method = body;
4293                         }
4294                 } else {
4295                         method = body;
4296                 }
4297 
4298                 if (zend_hash_find(Z_OBJPROP_P(this_ptr), "use", sizeof("use"), (void **)&zuse) == SUCCESS &&
4299                     Z_TYPE_PP(zuse) == IS_LONG && Z_LVAL_PP(zuse) == SOAP_LITERAL) {
4300                         use = SOAP_LITERAL;
4301                 } else {
4302                         use = SOAP_ENCODED;
4303                 }
4304         }
4305 
4306         for (i = 0;i < arg_count;i++) {
4307                 xmlNodePtr param;
4308                 sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
4309 
4310                 if (style == SOAP_RPC) {
4311                         param = serialize_parameter(parameter, arguments[i], i, NULL, use, method TSRMLS_CC);
4312                 } else if (style == SOAP_DOCUMENT) {
4313                         param = serialize_parameter(parameter, arguments[i], i, NULL, use, body TSRMLS_CC);
4314                         if (function && function->binding->bindingType == BINDING_SOAP) {
4315                                 if (parameter && parameter->element) {
4316                                         ns = encode_add_ns(param, parameter->element->namens);
4317                                         xmlNodeSetName(param, BAD_CAST(parameter->element->name));
4318                                         xmlSetNs(param, ns);
4319                                 }
4320                         }
4321                 }
4322         }
4323 
4324         if (function && function->requestParameters) {
4325                 int n = zend_hash_num_elements(function->requestParameters);
4326 
4327                 if (n > arg_count) {
4328                         for (i = arg_count; i < n; i++) {
4329                                 xmlNodePtr param;
4330                                 sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
4331 
4332                                 if (style == SOAP_RPC) {
4333                                         param = serialize_parameter(parameter, NULL, i, NULL, use, method TSRMLS_CC);
4334                                 } else if (style == SOAP_DOCUMENT) {
4335                                         param = serialize_parameter(parameter, NULL, i, NULL, use, body TSRMLS_CC);
4336                                         if (function && function->binding->bindingType == BINDING_SOAP) {
4337                                                 if (parameter && parameter->element) {
4338                                                         ns = encode_add_ns(param, parameter->element->namens);
4339                                                         xmlNodeSetName(param, BAD_CAST(parameter->element->name));
4340                                                         xmlSetNs(param, ns);
4341                                                 }
4342                                         }
4343                                 }
4344                         }
4345                 }
4346         }
4347 
4348         if (head) {
4349                 zval** header;
4350 
4351                 for(zend_hash_internal_pointer_reset(soap_headers);
4352                                 zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS;
4353                                 zend_hash_move_forward(soap_headers)
4354                         ) {
4355                         HashTable *ht;
4356                         zval **name, **ns, **tmp;
4357 
4358                         if (Z_TYPE_PP(header) != IS_OBJECT) {
4359                                 continue;
4360                         }
4361 
4362                         ht = Z_OBJPROP_PP(header);
4363                         if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
4364                             Z_TYPE_PP(name) == IS_STRING &&
4365                             zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
4366                             Z_TYPE_PP(ns) == IS_STRING) {
4367                                 xmlNodePtr h;
4368                                 xmlNsPtr nsptr;
4369                                 int hdr_use = SOAP_LITERAL;
4370                                 encodePtr enc = NULL;
4371 
4372                                 if (hdrs) {
4373                                         smart_str key = {0};
4374                                         sdlSoapBindingFunctionHeaderPtr *hdr;
4375 
4376                                         smart_str_appendl(&key, Z_STRVAL_PP(ns), Z_STRLEN_PP(ns));
4377                                         smart_str_appendc(&key, ':');
4378                                         smart_str_appendl(&key, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
4379                                         smart_str_0(&key);
4380                                         if (zend_hash_find(hdrs, key.c, key.len+1,(void**)&hdr) == SUCCESS) {
4381                                                 hdr_use = (*hdr)->use;
4382                                                 enc = (*hdr)->encode;
4383                                                 if (hdr_use == SOAP_ENCODED) {
4384                                                         use = SOAP_ENCODED;
4385                                                 }
4386                                         }
4387                                         smart_str_free(&key);
4388                                 }
4389 
4390                                 if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
4391                                         h = master_to_xml(enc, *tmp, hdr_use, head TSRMLS_CC);
4392                                         xmlNodeSetName(h, BAD_CAST(Z_STRVAL_PP(name)));
4393                                 } else {
4394                                         h = xmlNewNode(NULL, BAD_CAST(Z_STRVAL_PP(name)));
4395                                         xmlAddChild(head, h);
4396                                 }
4397                                 nsptr = encode_add_ns(h, Z_STRVAL_PP(ns));
4398                                 xmlSetNs(h, nsptr);
4399                                 set_soap_header_attributes(h, ht, version);
4400                         }
4401                 }
4402         }
4403 
4404         if (use == SOAP_ENCODED) {
4405                 xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
4406                 if (version == SOAP_1_1) {
4407                         xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
4408                         xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
4409                 } else if (version == SOAP_1_2) {
4410                         xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
4411                         if (method) {
4412                                 xmlSetNsProp(method, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
4413                         }
4414                 }
4415         }
4416 
4417         encode_finish();
4418 
4419         return doc;
4420 }
4421 
4422 static xmlNodePtr serialize_parameter(sdlParamPtr param, zval *param_val, int index, char *name, int style, xmlNodePtr parent TSRMLS_DC)
4423 {
4424         char *paramName;
4425         xmlNodePtr xmlParam;
4426         char paramNameBuf[10];
4427 
4428         if (param_val &&
4429             Z_TYPE_P(param_val) == IS_OBJECT &&
4430             Z_OBJCE_P(param_val) == soap_param_class_entry) {
4431                 zval **param_name;
4432                 zval **param_data;
4433 
4434                 if (zend_hash_find(Z_OBJPROP_P(param_val), "param_name", sizeof("param_name"), (void **)&param_name) == SUCCESS &&
4435                     Z_TYPE_PP(param_name) == IS_STRING &&
4436                     zend_hash_find(Z_OBJPROP_P(param_val), "param_data", sizeof("param_data"), (void **)&param_data) == SUCCESS) {
4437                         param_val = *param_data;
4438                         name = Z_STRVAL_PP(param_name);
4439                 }
4440         }
4441 
4442         if (param != NULL && param->paramName != NULL) {
4443                 paramName = param->paramName;
4444         } else {
4445                 if (name == NULL) {
4446                         paramName = paramNameBuf;
4447                         snprintf(paramName, sizeof(paramNameBuf), "param%d",index);
4448                 } else {
4449                         paramName = name;
4450                 }
4451         }
4452 
4453         xmlParam = serialize_zval(param_val, param, paramName, style, parent TSRMLS_CC);
4454 
4455         return xmlParam;
4456 }
4457 
4458 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent TSRMLS_DC)
4459 {
4460         xmlNodePtr xmlParam;
4461         encodePtr enc;
4462         zval defval;
4463 
4464         if (param != NULL) {
4465                 enc = param->encode;
4466                 if (val == NULL) {
4467                         if (param->element) {
4468                                 if (param->element->fixed) {
4469                                         ZVAL_STRING(&defval, param->element->fixed, 0);
4470                                         val = &defval;
4471                                 } else if (param->element->def && !param->element->nillable) {
4472                                         ZVAL_STRING(&defval, param->element->def, 0);
4473                                         val = &defval;
4474                                 }
4475                         }
4476                 }
4477         } else {
4478                 enc = NULL;
4479         }
4480         xmlParam = master_to_xml(enc, val, style, parent TSRMLS_CC);
4481         if (!strcmp((char*)xmlParam->name, "BOGUS")) {
4482                 xmlNodeSetName(xmlParam, BAD_CAST(paramName));
4483         }
4484         return xmlParam;
4485 }
4486 
4487 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int response)
4488 {
4489         sdlParamPtr *tmp;
4490         HashTable   *ht;
4491 
4492         if (function == NULL) {
4493                 return NULL;
4494         }
4495 
4496         if (response == FALSE) {
4497                 ht = function->requestParameters;
4498         } else {
4499                 ht = function->responseParameters;
4500         }
4501 
4502         if (ht == NULL) {
4503           return NULL;
4504         }
4505 
4506         if (param_name != NULL) {
4507                 if (zend_hash_find(ht, param_name, strlen(param_name), (void **)&tmp) != FAILURE) {
4508                         return *tmp;
4509                 } else {
4510                         HashPosition pos;
4511 
4512                         zend_hash_internal_pointer_reset_ex(ht, &pos);
4513                         while (zend_hash_get_current_data_ex(ht, (void **)&tmp, &pos) != FAILURE) {
4514                                 if ((*tmp)->paramName && strcmp(param_name, (*tmp)->paramName) == 0) {
4515                                         return *tmp;
4516                                 }
4517                                 zend_hash_move_forward_ex(ht, &pos);
4518                         }
4519                 }
4520         } else {
4521                 if (zend_hash_index_find(ht, index, (void **)&tmp) != FAILURE) {
4522                         return (*tmp);
4523                 }
4524         }
4525         return NULL;
4526 }
4527 
4528 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name)
4529 {
4530         sdlFunctionPtr *tmp;
4531 
4532         int len = strlen(function_name);
4533         char *str = estrndup(function_name,len);
4534         php_strtolower(str,len);
4535         if (sdl != NULL) {
4536                 if (zend_hash_find(&sdl->functions, str, len+1, (void **)&tmp) != FAILURE) {
4537                         efree(str);
4538                         return (*tmp);
4539                 } else if (sdl->requests != NULL && zend_hash_find(sdl->requests, str, len+1, (void **)&tmp) != FAILURE) {
4540                         efree(str);
4541                         return (*tmp);
4542                 }
4543         }
4544         efree(str);
4545         return NULL;
4546 }
4547 
4548 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr params)
4549 {
4550         if (sdl) {
4551                 sdlFunctionPtr *tmp;
4552                 sdlParamPtr    *param;
4553 
4554                 zend_hash_internal_pointer_reset(&sdl->functions);
4555                 while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
4556                         if ((*tmp)->binding && (*tmp)->binding->bindingType == BINDING_SOAP) {
4557                                 sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
4558                                 if (fnb->style == SOAP_DOCUMENT) {
4559                                         if (params == NULL) {
4560                                                 if ((*tmp)->requestParameters == NULL ||
4561                                                     zend_hash_num_elements((*tmp)->requestParameters) == 0) {
4562                                                   return *tmp;
4563                                                 }
4564                                         } else if ((*tmp)->requestParameters != NULL &&
4565                                                    zend_hash_num_elements((*tmp)->requestParameters) > 0) {
4566                                                 int ok = 1;
4567                                                 xmlNodePtr node = params;
4568 
4569                                                 zend_hash_internal_pointer_reset((*tmp)->requestParameters);
4570                                                 while (zend_hash_get_current_data((*tmp)->requestParameters, (void**)&param) == SUCCESS) {
4571                                                         if ((*param)->element) {
4572                                                                 if (strcmp((*param)->element->name, (char*)node->name) != 0) {
4573                                                                         ok = 0;
4574                                                                         break;
4575                                                                 }
4576                                                                 if ((*param)->element->namens != NULL && node->ns != NULL) {
4577                                                                         if (strcmp((*param)->element->namens, (char*)node->ns->href) != 0) {
4578                                                                                 ok = 0;
4579                                                                                 break;
4580                                                                         }
4581                                                                 } else if ((void*)(*param)->element->namens != (void*)node->ns) {
4582                                                                         ok = 0;
4583                                                                         break;
4584                                                                 }
4585                                                         } else if (strcmp((*param)->paramName, (char*)node->name) != 0) {
4586                                                                 ok = 0;
4587                                                                 break;
4588                                                         }
4589                                                         zend_hash_move_forward((*tmp)->requestParameters);
4590                                                         node = node->next;
4591                                                 }
4592                                                 if (ok /*&& node == NULL*/) {
4593                                                         return (*tmp);
4594                                                 }
4595                                         }
4596                                 }
4597                         }
4598                         zend_hash_move_forward(&sdl->functions);
4599                 }
4600         }
4601         return NULL;
4602 }
4603 
4604 static void function_to_string(sdlFunctionPtr function, smart_str *buf)
4605 {
4606         int i = 0;
4607         HashPosition pos;
4608         sdlParamPtr *param;
4609 
4610         if (function->responseParameters &&
4611             zend_hash_num_elements(function->responseParameters) > 0) {
4612                 if (zend_hash_num_elements(function->responseParameters) == 1) {
4613                         zend_hash_internal_pointer_reset(function->responseParameters);
4614                         zend_hash_get_current_data(function->responseParameters, (void**)&param);
4615                         if ((*param)->encode && (*param)->encode->details.type_str) {
4616                                 smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
4617                                 smart_str_appendc(buf, ' ');
4618                         } else {
4619                                 smart_str_appendl(buf, "UNKNOWN ", 8);
4620                         }
4621                 } else {
4622                         i = 0;
4623                         smart_str_appendl(buf, "list(", 5);
4624                         zend_hash_internal_pointer_reset_ex(function->responseParameters, &pos);
4625                         while (zend_hash_get_current_data_ex(function->responseParameters, (void **)&param, &pos) != FAILURE) {
4626                                 if (i > 0) {
4627                                         smart_str_appendl(buf, ", ", 2);
4628                                 }
4629                                 if ((*param)->encode && (*param)->encode->details.type_str) {
4630                                         smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
4631                                 } else {
4632                                         smart_str_appendl(buf, "UNKNOWN", 7);
4633                                 }
4634                                 smart_str_appendl(buf, " $", 2);
4635                                 smart_str_appendl(buf, (*param)->paramName, strlen((*param)->paramName));
4636                                 zend_hash_move_forward_ex(function->responseParameters, &pos);
4637                                 i++;
4638                         }
4639                         smart_str_appendl(buf, ") ", 2);
4640                 }
4641         } else {
4642                 smart_str_appendl(buf, "void ", 5);
4643         }
4644 
4645         smart_str_appendl(buf, function->functionName, strlen(function->functionName));
4646 
4647         smart_str_appendc(buf, '(');
4648         if (function->requestParameters) {
4649                 i = 0;
4650                 zend_hash_internal_pointer_reset_ex(function->requestParameters, &pos);
4651                 while (zend_hash_get_current_data_ex(function->requestParameters, (void **)&param, &pos) != FAILURE) {
4652                         if (i > 0) {
4653                                 smart_str_appendl(buf, ", ", 2);
4654                         }
4655                         if ((*param)->encode && (*param)->encode->details.type_str) {
4656                                 smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
4657                         } else {
4658                                 smart_str_appendl(buf, "UNKNOWN", 7);
4659                         }
4660                         smart_str_appendl(buf, " $", 2);
4661                         smart_str_appendl(buf, (*param)->paramName, strlen((*param)->paramName));
4662                         zend_hash_move_forward_ex(function->requestParameters, &pos);
4663                         i++;
4664                 }
4665         }
4666         smart_str_appendc(buf, ')');
4667         smart_str_0(buf);
4668 }
4669 
4670 static void model_to_string(sdlContentModelPtr model, smart_str *buf, int level)
4671 {
4672         int i;
4673 
4674         switch (model->kind) {
4675                 case XSD_CONTENT_ELEMENT:
4676                         type_to_string(model->u.element, buf, level);
4677                         smart_str_appendl(buf, ";\n", 2);
4678                         break;
4679                 case XSD_CONTENT_ANY:
4680                         for (i = 0;i < level;i++) {
4681                                 smart_str_appendc(buf, ' ');
4682                         }
4683                         smart_str_appendl(buf, "<anyXML> any;\n", sizeof("<anyXML> any;\n")-1);
4684                         break;
4685                 case XSD_CONTENT_SEQUENCE:
4686                 case XSD_CONTENT_ALL:
4687                 case XSD_CONTENT_CHOICE: {
4688                         sdlContentModelPtr *tmp;
4689 
4690                         zend_hash_internal_pointer_reset(model->u.content);
4691                         while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
4692                                 model_to_string(*tmp, buf, level);
4693                                 zend_hash_move_forward(model->u.content);
4694                         }
4695                         break;
4696                 }
4697                 case XSD_CONTENT_GROUP:
4698                         model_to_string(model->u.group->model, buf, level);
4699                 default:
4700                   break;
4701         }
4702 }
4703 
4704 static void type_to_string(sdlTypePtr type, smart_str *buf, int level)
4705 {
4706         int i;
4707         smart_str spaces = {0};
4708         HashPosition pos;
4709 
4710         for (i = 0;i < level;i++) {
4711                 smart_str_appendc(&spaces, ' ');
4712         }
4713         smart_str_appendl(buf, spaces.c, spaces.len);
4714 
4715         switch (type->kind) {
4716                 case XSD_TYPEKIND_SIMPLE:
4717                         if (type->encode) {
4718                                 smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
4719                                 smart_str_appendc(buf, ' ');
4720                         } else {
4721                                 smart_str_appendl(buf, "anyType ", sizeof("anyType ")-1);
4722                         }
4723                         smart_str_appendl(buf, type->name, strlen(type->name));
4724                         break;
4725                 case XSD_TYPEKIND_LIST:
4726                         smart_str_appendl(buf, "list ", 5);
4727                         smart_str_appendl(buf, type->name, strlen(type->name));
4728                         if (type->elements) {
4729                                 sdlTypePtr *item_type;
4730 
4731                                 smart_str_appendl(buf, " {", 2);
4732                                 zend_hash_internal_pointer_reset_ex(type->elements, &pos);
4733                                 if (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) {
4734                                         smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name));
4735                                 }
4736                                 smart_str_appendc(buf, '}');
4737                         }
4738                         break;
4739                 case XSD_TYPEKIND_UNION:
4740                         smart_str_appendl(buf, "union ", 6);
4741                         smart_str_appendl(buf, type->name, strlen(type->name));
4742                         if (type->elements) {
4743                                 sdlTypePtr *item_type;
4744                                 int first = 0;
4745 
4746                                 smart_str_appendl(buf, " {", 2);
4747                                 zend_hash_internal_pointer_reset_ex(type->elements, &pos);
4748                                 while (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) {
4749                                         if (!first) {
4750                                                 smart_str_appendc(buf, ',');
4751                                                 first = 0;
4752                                         }
4753                                         smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name));
4754                                         zend_hash_move_forward_ex(type->elements, &pos);
4755                                 }
4756                                 smart_str_appendc(buf, '}');
4757                         }
4758                         break;
4759                 case XSD_TYPEKIND_COMPLEX:
4760                 case XSD_TYPEKIND_RESTRICTION:
4761                 case XSD_TYPEKIND_EXTENSION:
4762                         if (type->encode &&
4763                             (type->encode->details.type == IS_ARRAY ||
4764                              type->encode->details.type == SOAP_ENC_ARRAY)) {
4765                           sdlAttributePtr *attr;
4766                           sdlExtraAttributePtr *ext;
4767 
4768                                 if (type->attributes &&
4769                                     zend_hash_find(type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
4770                                       sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
4771                                       (void **)&attr) == SUCCESS &&
4772                                       (*attr)->extraAttributes &&
4773                                       zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
4774                                         char *end = strchr((*ext)->val, '[');
4775                                         int len;
4776                                         if (end == NULL) {
4777                                                 len = strlen((*ext)->val);
4778                                         } else {
4779                                                 len = end-(*ext)->val;
4780                                         }
4781                                         if (len == 0) {
4782                                                 smart_str_appendl(buf, "anyType", sizeof("anyType")-1);
4783                                         } else {
4784                                                 smart_str_appendl(buf, (*ext)->val, len);
4785                                         }
4786                                         smart_str_appendc(buf, ' ');
4787                                         smart_str_appendl(buf, type->name, strlen(type->name));
4788                                         if (end != NULL) {
4789                                                 smart_str_appends(buf, end);
4790                                         }
4791                                 } else {
4792                                         sdlTypePtr elementType;
4793                                         if (type->attributes &&
4794                                             zend_hash_find(type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
4795                                               sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
4796                                               (void **)&attr) == SUCCESS &&
4797                                               (*attr)->extraAttributes &&
4798                                               zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
4799                                                 smart_str_appends(buf, (*ext)->val);
4800                                                 smart_str_appendc(buf, ' ');
4801                                         } else if (type->elements &&
4802                                                    zend_hash_num_elements(type->elements) == 1 &&
4803                                                    (zend_hash_internal_pointer_reset(type->elements),
4804                                                     zend_hash_get_current_data(type->elements, (void**)&elementType) == SUCCESS) &&
4805                                                    (elementType = *(sdlTypePtr*)elementType) != NULL &&
4806                                                    elementType->encode && elementType->encode->details.type_str) {
4807                                                 smart_str_appends(buf, elementType->encode->details.type_str);
4808                                                 smart_str_appendc(buf, ' ');
4809                                         } else {
4810                                                 smart_str_appendl(buf, "anyType ", 8);
4811                                         }
4812                                         smart_str_appendl(buf, type->name, strlen(type->name));
4813                                         if (type->attributes &&
4814                                             zend_hash_find(type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
4815                                               sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
4816                                               (void **)&attr) == SUCCESS &&
4817                                               (*attr)->extraAttributes &&
4818                                               zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arraySize"), (void **)&ext) == SUCCESS) {
4819                                                 smart_str_appendc(buf, '[');
4820                                                 smart_str_appends(buf, (*ext)->val);
4821                                                 smart_str_appendc(buf, ']');
4822                                         } else {
4823                                                 smart_str_appendl(buf, "[]", 2);
4824                                         }
4825                                 }
4826                         } else {
4827                                 smart_str_appendl(buf, "struct ", 7);
4828                                 smart_str_appendl(buf, type->name, strlen(type->name));
4829                                 smart_str_appendc(buf, ' ');
4830                                 smart_str_appendl(buf, "{\n", 2);
4831                                 if ((type->kind == XSD_TYPEKIND_RESTRICTION ||
4832                                      type->kind == XSD_TYPEKIND_EXTENSION) && type->encode) {
4833                                         encodePtr enc = type->encode;
4834                                         while (enc && enc->details.sdl_type &&
4835                                                enc != enc->details.sdl_type->encode &&
4836                                                enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
4837                                                enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
4838                                                enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
4839                                                 enc = enc->details.sdl_type->encode;
4840                                         }
4841                                         if (enc) {
4842                                                 smart_str_appendl(buf, spaces.c, spaces.len);
4843                                                 smart_str_appendc(buf, ' ');
4844                                                 smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
4845                                                 smart_str_appendl(buf, " _;\n", 4);
4846                                         }
4847                                 }
4848                                 if (type->model) {
4849                                         model_to_string(type->model, buf, level+1);
4850                                 }
4851                                 if (type->attributes) {
4852                                         sdlAttributePtr *attr;
4853 
4854                                         zend_hash_internal_pointer_reset_ex(type->attributes, &pos);
4855                                         while (zend_hash_get_current_data_ex(type->attributes, (void **)&attr, &pos) != FAILURE) {
4856                                                 smart_str_appendl(buf, spaces.c, spaces.len);
4857                                                 smart_str_appendc(buf, ' ');
4858                                                 if ((*attr)->encode && (*attr)->encode->details.type_str) {
4859                                                         smart_str_appends(buf, (*attr)->encode->details.type_str);
4860                                                         smart_str_appendc(buf, ' ');
4861                                                 } else {
4862                                                         smart_str_appendl(buf, "UNKNOWN ", 8);
4863                                                 }
4864                                                 smart_str_appends(buf, (*attr)->name);
4865                                                 smart_str_appendl(buf, ";\n", 2);
4866                                                 zend_hash_move_forward_ex(type->attributes, &pos);
4867                                         }
4868                                 }
4869                                 smart_str_appendl(buf, spaces.c, spaces.len);
4870                                 smart_str_appendc(buf, '}');
4871                         }
4872                         break;
4873                 default:
4874                         break;
4875         }
4876         smart_str_free(&spaces);
4877         smart_str_0(buf);
4878 }
4879 
4880 static void delete_url(void *handle)
4881 {
4882         php_url_free((php_url*)handle);
4883 }
4884 
4885 static void delete_service(void *data)
4886 {
4887         soapServicePtr service = (soapServicePtr)data;
4888 
4889         if (service->soap_functions.ft) {
4890                 zend_hash_destroy(service->soap_functions.ft);
4891                 efree(service->soap_functions.ft);
4892         }
4893 
4894         if (service->typemap) {
4895                 zend_hash_destroy(service->typemap);
4896                 efree(service->typemap);
4897         }
4898 
4899         if (service->soap_class.argc) {
4900                 int i;
4901                 for (i = 0; i < service->soap_class.argc;i++) {
4902                         zval_ptr_dtor(&service->soap_class.argv[i]);
4903                 }
4904                 efree(service->soap_class.argv);
4905         }
4906 
4907         if (service->actor) {
4908                 efree(service->actor);
4909         }
4910         if (service->uri) {
4911                 efree(service->uri);
4912         }
4913         if (service->sdl) {
4914                 delete_sdl(service->sdl);
4915         }
4916         if (service->encoding) {
4917                 xmlCharEncCloseFunc(service->encoding);
4918         }
4919         if (service->class_map) {
4920                 zend_hash_destroy(service->class_map);
4921                 FREE_HASHTABLE(service->class_map);
4922         }
4923         if (service->soap_object) {
4924                 zval_ptr_dtor(&service->soap_object);
4925         }
4926         efree(service);
4927 }
4928 
4929 static void delete_hashtable(void *data)
4930 {
4931         HashTable *ht = (HashTable*)data;
4932         zend_hash_destroy(ht);
4933         efree(ht);
4934 }

/* [<][>][^][v][top][bottom][index][help] */