root/ext/soap/soap.c

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

DEFINITIONS

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

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

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