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