Back to index

php5  5.3.10
soap.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 1997-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Brad Lafountain <rodif_bl@yahoo.com>                        |
00016   |          Shane Caraveo <shane@caraveo.com>                           |
00017   |          Dmitry Stogov <dmitry@zend.com>                             |
00018   +----------------------------------------------------------------------+
00019 */
00020 /* $Id: soap.c 321634 2012-01-01 13:15:04Z felipe $ */
00021 
00022 #ifdef HAVE_CONFIG_H
00023 #include "config.h"
00024 #endif
00025 #include "php_soap.h"
00026 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
00027 #include "ext/session/php_session.h"
00028 #endif
00029 #ifdef ZEND_ENGINE_2
00030 #  include "zend_exceptions.h"
00031 #endif
00032 
00033 static int le_sdl = 0;
00034 int le_url = 0;
00035 static int le_service = 0;
00036 static int le_typemap = 0;
00037 
00038 typedef struct _soapHeader {
00039        sdlFunctionPtr                    function;
00040        zval                              function_name;
00041        int                               mustUnderstand;
00042        int                               num_params;
00043        zval                            **parameters;
00044        zval                              retval;
00045        sdlSoapBindingFunctionHeaderPtr   hdr;
00046        struct _soapHeader               *next;
00047 } soapHeader;
00048 
00049 /* Local functions */
00050 static void function_to_string(sdlFunctionPtr function, smart_str *buf);
00051 static void type_to_string(sdlTypePtr type, smart_str *buf, int level);
00052 
00053 static void clear_soap_fault(zval *obj TSRMLS_DC);
00054 static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC);
00055 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char *name TSRMLS_DC);
00056 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader* hdr TSRMLS_DC);
00057 
00058 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int);
00059 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name);
00060 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr node);
00061 
00062 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval **parameters[], int *version, soapHeader **headers TSRMLS_DC);
00063 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name,char *uri,zval *ret, soapHeader *headers, int version TSRMLS_DC);
00064 static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function, char *function_name, char *uri, zval **arguments, int arg_count, int version, HashTable *soap_headers TSRMLS_DC);
00065 static xmlNodePtr serialize_parameter(sdlParamPtr param,zval *param_val,int index,char *name, int style, xmlNodePtr parent TSRMLS_DC);
00066 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent TSRMLS_DC);
00067 
00068 static void delete_service(void *service);
00069 static void delete_url(void *handle);
00070 static void delete_hashtable(void *hashtable);
00071 
00072 #ifndef ZEND_ENGINE_2
00073 static void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference);
00074 #endif
00075 
00076 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
00077 
00078 #define SOAP_SERVER_BEGIN_CODE() \
00079        zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
00080        char* _old_error_code = SOAP_GLOBAL(error_code);\
00081        zval* _old_error_object = SOAP_GLOBAL(error_object);\
00082        int _old_soap_version = SOAP_GLOBAL(soap_version);\
00083        SOAP_GLOBAL(use_soap_error_handler) = 1;\
00084        SOAP_GLOBAL(error_code) = "Server";\
00085        SOAP_GLOBAL(error_object) = this_ptr;
00086 
00087 #define SOAP_SERVER_END_CODE() \
00088        SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
00089        SOAP_GLOBAL(error_code) = _old_error_code;\
00090        SOAP_GLOBAL(error_object) = _old_error_object;\
00091        SOAP_GLOBAL(soap_version) = _old_soap_version;
00092 
00093 #ifdef ZEND_ENGINE_2
00094 #define SOAP_CLIENT_BEGIN_CODE() \
00095        zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
00096        char* _old_error_code = SOAP_GLOBAL(error_code);\
00097        zval* _old_error_object = SOAP_GLOBAL(error_object);\
00098        int _old_soap_version = SOAP_GLOBAL(soap_version);\
00099        zend_bool _old_in_compilation = CG(in_compilation); \
00100        zend_bool _old_in_execution = EG(in_execution); \
00101        zend_execute_data *_old_current_execute_data = EG(current_execute_data); \
00102        void **_old_stack_top = EG(argument_stack)->top; \
00103        int _bailout = 0;\
00104        SOAP_GLOBAL(use_soap_error_handler) = 1;\
00105        SOAP_GLOBAL(error_code) = "Client";\
00106        SOAP_GLOBAL(error_object) = this_ptr;\
00107        zend_try {
00108 
00109 #define SOAP_CLIENT_END_CODE() \
00110        } zend_catch {\
00111               CG(in_compilation) = _old_in_compilation; \
00112               EG(in_execution) = _old_in_execution; \
00113               EG(current_execute_data) = _old_current_execute_data; \
00114               if (EG(exception) == NULL || \
00115                   Z_TYPE_P(EG(exception)) != IS_OBJECT || \
00116                   !instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {\
00117                      _bailout = 1;\
00118               }\
00119               if (_old_stack_top != EG(argument_stack)->top) { \
00120                      while (EG(argument_stack)->prev != NULL && \
00121                             ((char*)_old_stack_top < (char*)EG(argument_stack) || \
00122                              (char*) _old_stack_top > (char*)EG(argument_stack)->end)) { \
00123                             zend_vm_stack tmp = EG(argument_stack)->prev; \
00124                             efree(EG(argument_stack)); \
00125                             EG(argument_stack) = tmp; \
00126                      } \
00127                      EG(argument_stack)->top = _old_stack_top; \
00128               } \
00129        } zend_end_try();\
00130        SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
00131        SOAP_GLOBAL(error_code) = _old_error_code;\
00132        SOAP_GLOBAL(error_object) = _old_error_object;\
00133        SOAP_GLOBAL(soap_version) = _old_soap_version;\
00134        if (_bailout) {\
00135               zend_bailout();\
00136        }
00137 #else
00138 #define SOAP_CLIENT_BEGIN_CODE() \
00139        zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
00140        char* _old_error_code = SOAP_GLOBAL(error_code);\
00141        zval* _old_error_object = SOAP_GLOBAL(error_object);\
00142        int _old_soap_version = SOAP_GLOBAL(soap_version);\
00143        SOAP_GLOBAL(use_soap_error_handler) = 1;\
00144        SOAP_GLOBAL(error_code) = "Client";\
00145        SOAP_GLOBAL(error_object) = this_ptr;
00146 
00147 #define SOAP_CLIENT_END_CODE() \
00148        SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
00149        SOAP_GLOBAL(error_code) = _old_error_code;\
00150        SOAP_GLOBAL(error_object) = _old_error_object;\
00151        SOAP_GLOBAL(soap_version) = _old_soap_version;
00152 #endif
00153 
00154 #define FETCH_THIS_SDL(ss) \
00155        { \
00156               zval **__tmp; \
00157               if(FIND_SDL_PROPERTY(this_ptr,__tmp) != FAILURE) { \
00158                      FETCH_SDL_RES(ss,__tmp); \
00159               } else { \
00160                      ss = NULL; \
00161               } \
00162        }
00163 
00164 #define FIND_SDL_PROPERTY(ss,tmp) zend_hash_find(Z_OBJPROP_P(ss), "sdl", sizeof("sdl"), (void **)&tmp)
00165 #define FETCH_SDL_RES(ss,tmp) ss = (sdlPtr) zend_fetch_resource(tmp TSRMLS_CC, -1, "sdl", NULL, 1, le_sdl)
00166 
00167 #define FIND_TYPEMAP_PROPERTY(ss,tmp) zend_hash_find(Z_OBJPROP_P(ss), "typemap", sizeof("typemap"), (void **)&tmp)
00168 #define FETCH_TYPEMAP_RES(ss,tmp) ss = (HashTable*) zend_fetch_resource(tmp TSRMLS_CC, -1, "typemap", NULL, 1, le_typemap)
00169 
00170 #define FETCH_THIS_SERVICE(ss) \
00171        { \
00172               zval **tmp; \
00173               if (zend_hash_find(Z_OBJPROP_P(this_ptr),"service", sizeof("service"), (void **)&tmp) != FAILURE) { \
00174                      ss = (soapServicePtr)zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service); \
00175               } else { \
00176                      ss = NULL; \
00177               } \
00178        }
00179 
00180 static zend_class_entry* soap_class_entry;
00181 static zend_class_entry* soap_server_class_entry;
00182 static zend_class_entry* soap_fault_class_entry;
00183 static zend_class_entry* soap_header_class_entry;
00184 static zend_class_entry* soap_param_class_entry;
00185 zend_class_entry* soap_var_class_entry;
00186 
00187 ZEND_DECLARE_MODULE_GLOBALS(soap)
00188 
00189 static void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
00190 
00191 #ifdef va_copy
00192 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
00193 { \
00194        va_list copy; \
00195        va_copy(copy, args); \
00196        old_error_handler(error_num, error_filename, error_lineno, format, copy); \
00197        va_end(copy); \
00198 }
00199 #else
00200 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
00201 { \
00202        old_error_handler(error_num, error_filename, error_lineno, format, args); \
00203 }
00204 #endif
00205 
00206 #define PHP_SOAP_SERVER_CLASSNAME "SoapServer"
00207 #define PHP_SOAP_CLIENT_CLASSNAME "SoapClient"
00208 #define PHP_SOAP_VAR_CLASSNAME    "SoapVar"
00209 #define PHP_SOAP_FAULT_CLASSNAME  "SoapFault"
00210 #define PHP_SOAP_PARAM_CLASSNAME  "SoapParam"
00211 #define PHP_SOAP_HEADER_CLASSNAME "SoapHeader"
00212 
00213 PHP_RINIT_FUNCTION(soap);
00214 PHP_MINIT_FUNCTION(soap);
00215 PHP_MSHUTDOWN_FUNCTION(soap);
00216 PHP_MINFO_FUNCTION(soap);
00217 
00218 #ifndef ZEND_ENGINE_2
00219 # ifndef PHP_METHOD
00220 #  define PHP_METHOD(classname, name)     ZEND_NAMED_FUNCTION(ZEND_FN(classname##_##name))
00221 #  define PHP_ME(classname, name, arg_info, flags)      ZEND_NAMED_FE(name, ZEND_FN(classname##_##name), arg_info)
00222 # endif
00223 
00224 static char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length)
00225 {
00226        register unsigned char *str = (unsigned char*)source;
00227        register unsigned char *result = (unsigned char*)dest;
00228        register unsigned char *end = str + length;
00229 
00230        while (str < end) {
00231               *result++ = tolower((int)*str++);
00232        }
00233        *result = *end;
00234 
00235        return dest;
00236 }
00237 #endif
00238 
00239 /*
00240   Registry Functions
00241   TODO: this!
00242 */
00243 PHP_FUNCTION(soap_encode_to_xml);
00244 PHP_FUNCTION(soap_encode_to_zval);
00245 PHP_FUNCTION(use_soap_error_handler);
00246 PHP_FUNCTION(is_soap_fault);
00247 
00248 
00249 /* Server Functions */
00250 PHP_METHOD(SoapServer, SoapServer);
00251 PHP_METHOD(SoapServer, setClass);
00252 PHP_METHOD(SoapServer, setObject);
00253 PHP_METHOD(SoapServer, addFunction);
00254 PHP_METHOD(SoapServer, getFunctions);
00255 PHP_METHOD(SoapServer, handle);
00256 PHP_METHOD(SoapServer, setPersistence);
00257 PHP_METHOD(SoapServer, fault);
00258 PHP_METHOD(SoapServer, addSoapHeader);
00259 
00260 /* Client Functions */
00261 PHP_METHOD(SoapClient, SoapClient);
00262 PHP_METHOD(SoapClient, __call);
00263 PHP_METHOD(SoapClient, __getLastRequest);
00264 PHP_METHOD(SoapClient, __getLastResponse);
00265 PHP_METHOD(SoapClient, __getLastRequestHeaders);
00266 PHP_METHOD(SoapClient, __getLastResponseHeaders);
00267 PHP_METHOD(SoapClient, __getFunctions);
00268 PHP_METHOD(SoapClient, __getTypes);
00269 PHP_METHOD(SoapClient, __doRequest);
00270 PHP_METHOD(SoapClient, __setCookie);
00271 PHP_METHOD(SoapClient, __setLocation);
00272 PHP_METHOD(SoapClient, __setSoapHeaders);
00273 
00274 /* SoapVar Functions */
00275 PHP_METHOD(SoapVar, SoapVar);
00276 
00277 /* SoapFault Functions */
00278 PHP_METHOD(SoapFault, SoapFault);
00279 #ifdef ZEND_ENGINE_2
00280 PHP_METHOD(SoapFault, __toString);
00281 #endif
00282 
00283 /* SoapParam Functions */
00284 PHP_METHOD(SoapParam, SoapParam);
00285 
00286 /* SoapHeader Functions */
00287 PHP_METHOD(SoapHeader, SoapHeader);
00288 
00289 #define SOAP_CTOR(class_name, func_name, arginfo, flags) PHP_ME(class_name, func_name, arginfo, flags)
00290 
00291 /* {{{ arginfo */
00292 #ifdef ZEND_ENGINE_2
00293 ZEND_BEGIN_ARG_INFO(arginfo_soap__void, 0)
00294 ZEND_END_ARG_INFO()
00295 
00296 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapparam_soapparam, 0, 0, 2)
00297        ZEND_ARG_INFO(0, data)
00298        ZEND_ARG_INFO(0, name)
00299 ZEND_END_ARG_INFO()
00300 
00301 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapheader_soapheader, 0, 0, 2)
00302        ZEND_ARG_INFO(0, namespace)
00303        ZEND_ARG_INFO(0, name)
00304        ZEND_ARG_INFO(0, data)
00305        ZEND_ARG_INFO(0, mustunderstand)
00306        ZEND_ARG_INFO(0, actor)
00307 ZEND_END_ARG_INFO()
00308 
00309 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapfault_soapfault, 0, 0, 2)
00310        ZEND_ARG_INFO(0, faultcode)
00311        ZEND_ARG_INFO(0, faultstring)
00312        ZEND_ARG_INFO(0, faultactor)
00313        ZEND_ARG_INFO(0, detail)
00314        ZEND_ARG_INFO(0, faultname)
00315        ZEND_ARG_INFO(0, headerfault)
00316 ZEND_END_ARG_INFO()
00317 
00318 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapvar_soapvar, 0, 0, 2)
00319        ZEND_ARG_INFO(0, data)
00320        ZEND_ARG_INFO(0, encoding)
00321        ZEND_ARG_INFO(0, type_name)
00322        ZEND_ARG_INFO(0, type_namespace)
00323        ZEND_ARG_INFO(0, node_name)
00324        ZEND_ARG_INFO(0, node_namespace)
00325 ZEND_END_ARG_INFO()
00326 
00327 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_fault, 0, 0, 2)
00328        ZEND_ARG_INFO(0, code)
00329        ZEND_ARG_INFO(0, string)
00330        ZEND_ARG_INFO(0, actor)
00331        ZEND_ARG_INFO(0, details)
00332        ZEND_ARG_INFO(0, name)
00333 ZEND_END_ARG_INFO()
00334 
00335 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addsoapheader, 0, 0, 1)
00336        ZEND_ARG_INFO(0, object)
00337 ZEND_END_ARG_INFO()
00338 
00339 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_soapserver, 0, 0, 1)
00340        ZEND_ARG_INFO(0, wsdl)
00341        ZEND_ARG_INFO(0, options)
00342 ZEND_END_ARG_INFO()
00343 
00344 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setpersistence, 0, 0, 1)
00345        ZEND_ARG_INFO(0, mode)
00346 ZEND_END_ARG_INFO()
00347 
00348 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setclass, 0, 0, 1)
00349        ZEND_ARG_INFO(0, class_name)
00350        ZEND_ARG_INFO(0, args)
00351 ZEND_END_ARG_INFO()
00352 
00353 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setobject, 0, 0, 1)
00354        ZEND_ARG_INFO(0, object)
00355 ZEND_END_ARG_INFO()
00356 
00357 ZEND_BEGIN_ARG_INFO(arginfo_soapserver_getfunctions, 0)
00358 ZEND_END_ARG_INFO()
00359 
00360 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addfunction, 0, 0, 1)
00361        ZEND_ARG_INFO(0, functions)
00362 ZEND_END_ARG_INFO()
00363 
00364 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_handle, 0, 0, 0)
00365        ZEND_ARG_INFO(0, soap_request)
00366 ZEND_END_ARG_INFO()
00367 
00368 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient_soapclient, 0, 0, 1)
00369        ZEND_ARG_INFO(0, wsdl)
00370        ZEND_ARG_INFO(0, options)
00371 ZEND_END_ARG_INFO()
00372 
00373 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___call, 0, 0, 2)
00374        ZEND_ARG_INFO(0, function_name)
00375        ZEND_ARG_INFO(0, arguments)
00376 ZEND_END_ARG_INFO()
00377 
00378 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___soapcall, 0, 0, 2)
00379        ZEND_ARG_INFO(0, function_name)
00380        ZEND_ARG_INFO(0, arguments)
00381        ZEND_ARG_INFO(0, options)
00382        ZEND_ARG_INFO(0, input_headers)
00383        ZEND_ARG_INFO(1, output_headers)
00384 ZEND_END_ARG_INFO()
00385 
00386 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getfunctions, 0)
00387 ZEND_END_ARG_INFO()
00388 
00389 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___gettypes, 0)
00390 ZEND_END_ARG_INFO()
00391 
00392 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequest, 0)
00393 ZEND_END_ARG_INFO()
00394 
00395 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponse, 0)
00396 ZEND_END_ARG_INFO()
00397 
00398 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequestheaders, 0)
00399 ZEND_END_ARG_INFO()
00400 
00401 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponseheaders, 0)
00402 ZEND_END_ARG_INFO()
00403 
00404 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___dorequest, 0, 0, 4)
00405        ZEND_ARG_INFO(0, request)
00406        ZEND_ARG_INFO(0, location)
00407        ZEND_ARG_INFO(0, action)
00408        ZEND_ARG_INFO(0, version)
00409        ZEND_ARG_INFO(0, one_way)
00410 ZEND_END_ARG_INFO()
00411 
00412 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setcookie, 0, 0, 1)
00413        ZEND_ARG_INFO(0, name)
00414        ZEND_ARG_INFO(0, value)
00415 ZEND_END_ARG_INFO()
00416 
00417 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setsoapheaders, 0, 0, 1)
00418        ZEND_ARG_INFO(0, soapheaders)
00419 ZEND_END_ARG_INFO()
00420 
00421 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setlocation, 0, 0, 0)
00422        ZEND_ARG_INFO(0, new_location)
00423 ZEND_END_ARG_INFO()
00424 
00425 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_use_soap_error_handler, 0, 0, 0)
00426        ZEND_ARG_INFO(0, handler)
00427 ZEND_END_ARG_INFO()
00428 
00429 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_is_soap_fault, 0, 0, 1)
00430        ZEND_ARG_INFO(0, object)
00431 ZEND_END_ARG_INFO()
00432 #else
00433 unsigned char arginfo_soapclient___call[] = { 2, BYREF_NONE, BYREF_NONE };
00434 unsigned char arginfo_soapclient___soapcall[] = { 5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
00435 # define arginfo_soapclient_soapclient                                NULL
00436 # define arginfo_soapclient___getlastrequest                   NULL
00437 # define arginfo_soapclient___getlastresponse                  NULL
00438 # define arginfo_soapclient___getlastrequestheaders     NULL
00439 # define arginfo_soapclient___getlastresponseheaders    NULL
00440 # define arginfo_soapclient___getfunctions                            NULL
00441 # define arginfo_soapclient___gettypes                                NULL
00442 # define arginfo_soapclient___dorequest                               NULL
00443 # define arginfo_soapclient___setcookie                               NULL
00444 # define arginfo_soapclient___setlocation                      NULL
00445 # define arginfo_soapclient___setsoapheaders                   NULL
00446 
00447 # define arginfo_soapserver_soapserver                                NULL
00448 # define arginfo_soapserver_setpersistence                            NULL
00449 # define arginfo_soapserver_setclass                                  NULL
00450 # define arginfo_soapserver_setobject                                 NULL
00451 # define arginfo_soapserver_addfunction                               NULL
00452 # define arginfo_soapserver_getfunctions                       NULL
00453 # defina arginfo_soapserver_handle                                    NULL
00454 # define arginfo_soapserver_fault                                     NULL
00455 # define arginfo_soapserver_addsoapheader                      NULL
00456 
00457 # define arginfo_soapvar_soapvar                                      NULL
00458 
00459 # define arginfo_soapfault_soapfault                                  NULL
00460 
00461 # define arginfo_soapheader_soapheader                                NULL
00462 
00463 # define arginfo_soapparam_soapparam                                  NULL
00464 
00465 # define arginfo_soap_use_soap_error_handler                   NULL
00466 
00467 # define arginfo_soap_is_soap_fault                                          NULL
00468 #endif
00469 /* }}} */
00470 
00471 static const zend_function_entry soap_functions[] = {
00472        PHP_FE(use_soap_error_handler,     arginfo_soap_use_soap_error_handler)
00473        PHP_FE(is_soap_fault,                     arginfo_soap_is_soap_fault)
00474        PHP_FE_END
00475 };
00476 
00477 static const zend_function_entry soap_fault_functions[] = {
00478        SOAP_CTOR(SoapFault, SoapFault, arginfo_soapfault_soapfault, 0)
00479 #ifdef ZEND_ENGINE_2
00480        PHP_ME(SoapFault, __toString, arginfo_soap__void, 0)
00481 #endif
00482        PHP_FE_END
00483 };
00484 
00485 static const zend_function_entry soap_server_functions[] = {
00486        SOAP_CTOR(SoapServer, SoapServer,  arginfo_soapserver_soapserver, 0)
00487        PHP_ME(SoapServer, setPersistence,        arginfo_soapserver_setpersistence, 0)
00488        PHP_ME(SoapServer, setClass,              arginfo_soapserver_setclass, 0)
00489        PHP_ME(SoapServer, setObject,             arginfo_soapserver_setobject, 0)
00490        PHP_ME(SoapServer, addFunction,    arginfo_soapserver_addfunction, 0)
00491        PHP_ME(SoapServer, getFunctions,   arginfo_soapserver_getfunctions, 0)
00492        PHP_ME(SoapServer, handle,                arginfo_soapserver_handle, 0)
00493        PHP_ME(SoapServer, fault,                 arginfo_soapserver_fault, 0)
00494        PHP_ME(SoapServer, addSoapHeader,  arginfo_soapserver_addsoapheader, 0)
00495        PHP_FE_END
00496 };
00497 
00498 static const zend_function_entry soap_client_functions[] = {
00499        SOAP_CTOR(SoapClient, SoapClient, arginfo_soapclient_soapclient, 0)
00500        PHP_ME(SoapClient, __call,                                     arginfo_soapclient___call, 0)
00501        ZEND_NAMED_ME(__soapCall, ZEND_MN(SoapClient___call), arginfo_soapclient___soapcall, 0)
00502        PHP_ME(SoapClient, __getLastRequest,                    arginfo_soapclient___getlastrequest, 0)
00503        PHP_ME(SoapClient, __getLastResponse,                   arginfo_soapclient___getlastresponse, 0)
00504        PHP_ME(SoapClient, __getLastRequestHeaders,      arginfo_soapclient___getlastrequestheaders, 0)
00505        PHP_ME(SoapClient, __getLastResponseHeaders,     arginfo_soapclient___getlastresponseheaders, 0)
00506        PHP_ME(SoapClient, __getFunctions,                             arginfo_soapclient___getfunctions, 0)
00507        PHP_ME(SoapClient, __getTypes,                                 arginfo_soapclient___gettypes, 0)
00508        PHP_ME(SoapClient, __doRequest,                         arginfo_soapclient___dorequest, 0)
00509        PHP_ME(SoapClient, __setCookie,                         arginfo_soapclient___setcookie, 0)
00510        PHP_ME(SoapClient, __setLocation,                       arginfo_soapclient___setlocation, 0)
00511        PHP_ME(SoapClient, __setSoapHeaders,                    arginfo_soapclient___setsoapheaders, 0)
00512        PHP_FE_END
00513 };
00514 
00515 static const zend_function_entry soap_var_functions[] = {
00516        SOAP_CTOR(SoapVar, SoapVar, arginfo_soapvar_soapvar, 0)
00517        PHP_FE_END
00518 };
00519 
00520 static const zend_function_entry soap_param_functions[] = {
00521        SOAP_CTOR(SoapParam, SoapParam, arginfo_soapparam_soapparam, 0)
00522        PHP_FE_END
00523 };
00524 
00525 static const zend_function_entry soap_header_functions[] = {
00526        SOAP_CTOR(SoapHeader, SoapHeader, arginfo_soapheader_soapheader, 0)
00527        PHP_FE_END
00528 };
00529 
00530 zend_module_entry soap_module_entry = {
00531 #ifdef STANDARD_MODULE_HEADER
00532   STANDARD_MODULE_HEADER,
00533 #endif
00534   "soap",
00535   soap_functions,
00536   PHP_MINIT(soap),
00537   PHP_MSHUTDOWN(soap),
00538   PHP_RINIT(soap),
00539   NULL,
00540   PHP_MINFO(soap),
00541 #ifdef STANDARD_MODULE_HEADER
00542   NO_VERSION_YET,
00543 #endif
00544   STANDARD_MODULE_PROPERTIES,
00545 };
00546 
00547 #ifdef COMPILE_DL_SOAP
00548 ZEND_GET_MODULE(soap)
00549 #endif
00550 
00551 #ifndef ZEND_ENGINE_2
00552 # define OnUpdateLong OnUpdateInt
00553 #endif
00554 
00555 ZEND_INI_MH(OnUpdateCacheEnabled)
00556 {
00557        if (OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC) == FAILURE) {
00558               return FAILURE;
00559        }
00560        if (SOAP_GLOBAL(cache_enabled)) {
00561               SOAP_GLOBAL(cache) = SOAP_GLOBAL(cache_mode);
00562        } else {
00563               SOAP_GLOBAL(cache) = 0;
00564        }
00565        return SUCCESS;
00566 }
00567 
00568 ZEND_INI_MH(OnUpdateCacheMode)
00569 {
00570        char *p;
00571 #ifndef ZTS
00572        char *base = (char *) mh_arg2;
00573 #else
00574        char *base = (char *) ts_resource(*((int *) mh_arg2));
00575 #endif
00576 
00577        p = (char*) (base+(size_t) mh_arg1);
00578 
00579        *p = (char)atoi(new_value);
00580 
00581        if (SOAP_GLOBAL(cache_enabled)) {
00582               SOAP_GLOBAL(cache) = SOAP_GLOBAL(cache_mode);
00583        } else {
00584               SOAP_GLOBAL(cache) = 0;
00585        }
00586        return SUCCESS;
00587 }
00588 
00589 PHP_INI_BEGIN()
00590 STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled",     "1", PHP_INI_ALL, OnUpdateCacheEnabled,
00591                   cache_enabled, zend_soap_globals, soap_globals)
00592 STD_PHP_INI_ENTRY("soap.wsdl_cache_dir",         "/tmp", PHP_INI_ALL, OnUpdateString,
00593                   cache_dir, zend_soap_globals, soap_globals)
00594 STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl",         "86400", PHP_INI_ALL, OnUpdateLong,
00595                   cache_ttl, zend_soap_globals, soap_globals)
00596 STD_PHP_INI_ENTRY("soap.wsdl_cache",             "1", PHP_INI_ALL, OnUpdateCacheMode,
00597                   cache_mode, zend_soap_globals, soap_globals)
00598 STD_PHP_INI_ENTRY("soap.wsdl_cache_limit",       "5", PHP_INI_ALL, OnUpdateLong,
00599                   cache_limit, zend_soap_globals, soap_globals)
00600 PHP_INI_END()
00601 
00602 static HashTable defEnc, defEncIndex, defEncNs;
00603 
00604 static void php_soap_prepare_globals()
00605 {
00606        int i;
00607        encodePtr enc;
00608 
00609        zend_hash_init(&defEnc, 0, NULL, NULL, 1);
00610        zend_hash_init(&defEncIndex, 0, NULL, NULL, 1);
00611        zend_hash_init(&defEncNs, 0, NULL, NULL, 1);
00612 
00613        i = 0;
00614        do {
00615               enc = &defaultEncoding[i];
00616 
00617               /* If has a ns and a str_type then index it */
00618               if (defaultEncoding[i].details.type_str) {
00619                      if (defaultEncoding[i].details.ns != NULL) {
00620                             char *ns_type;
00621                             spprintf(&ns_type, 0, "%s:%s", defaultEncoding[i].details.ns, defaultEncoding[i].details.type_str);
00622                             zend_hash_add(&defEnc, ns_type, strlen(ns_type) + 1, &enc, sizeof(encodePtr), NULL);
00623                             efree(ns_type);
00624                      } else {
00625                             zend_hash_add(&defEnc, defaultEncoding[i].details.type_str, strlen(defaultEncoding[i].details.type_str) + 1, &enc, sizeof(encodePtr), NULL);
00626                      }
00627               }
00628               /* Index everything by number */
00629               if (!zend_hash_index_exists(&defEncIndex, defaultEncoding[i].details.type)) {
00630                      zend_hash_index_update(&defEncIndex, defaultEncoding[i].details.type, &enc, sizeof(encodePtr), NULL);
00631               }
00632               i++;
00633        } while (defaultEncoding[i].details.type != END_KNOWN_TYPES);
00634 
00635        /* hash by namespace */
00636        zend_hash_add(&defEncNs, XSD_1999_NAMESPACE, sizeof(XSD_1999_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
00637        zend_hash_add(&defEncNs, XSD_NAMESPACE, sizeof(XSD_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
00638        zend_hash_add(&defEncNs, XSI_NAMESPACE, sizeof(XSI_NAMESPACE), XSI_NS_PREFIX, sizeof(XSI_NS_PREFIX), NULL);
00639        zend_hash_add(&defEncNs, XML_NAMESPACE, sizeof(XML_NAMESPACE), XML_NS_PREFIX, sizeof(XML_NS_PREFIX), NULL);
00640        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);
00641        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);
00642 }
00643 
00644 static void php_soap_init_globals(zend_soap_globals *soap_globals TSRMLS_DC)
00645 {
00646        soap_globals->defEnc = defEnc;
00647        soap_globals->defEncIndex = defEncIndex;
00648        soap_globals->defEncNs = defEncNs;
00649        soap_globals->typemap = NULL;
00650        soap_globals->use_soap_error_handler = 0;
00651        soap_globals->error_code = NULL;
00652        soap_globals->error_object = NULL;
00653        soap_globals->sdl = NULL;
00654        soap_globals->soap_version = SOAP_1_1;
00655        soap_globals->mem_cache = NULL;
00656        soap_globals->ref_map = NULL;
00657 }
00658 
00659 PHP_MSHUTDOWN_FUNCTION(soap)
00660 {
00661        zend_error_cb = old_error_handler;
00662        zend_hash_destroy(&SOAP_GLOBAL(defEnc));
00663        zend_hash_destroy(&SOAP_GLOBAL(defEncIndex));
00664        zend_hash_destroy(&SOAP_GLOBAL(defEncNs));
00665        if (SOAP_GLOBAL(mem_cache)) {
00666               zend_hash_destroy(SOAP_GLOBAL(mem_cache));
00667               free(SOAP_GLOBAL(mem_cache));
00668        }
00669        UNREGISTER_INI_ENTRIES();
00670        return SUCCESS;
00671 }
00672 
00673 PHP_RINIT_FUNCTION(soap)
00674 {
00675        SOAP_GLOBAL(typemap) = NULL;
00676        SOAP_GLOBAL(use_soap_error_handler) = 0;
00677        SOAP_GLOBAL(error_code) = NULL;
00678        SOAP_GLOBAL(error_object) = NULL;
00679        SOAP_GLOBAL(sdl) = NULL;
00680        SOAP_GLOBAL(soap_version) = SOAP_1_1;
00681        SOAP_GLOBAL(encoding) = NULL;
00682        SOAP_GLOBAL(class_map) = NULL;
00683        SOAP_GLOBAL(features) = 0;
00684        SOAP_GLOBAL(ref_map) = NULL;
00685        return SUCCESS;
00686 }
00687 
00688 PHP_MINIT_FUNCTION(soap)
00689 {
00690        zend_class_entry ce;
00691 
00692        /* TODO: add ini entry for always use soap errors */
00693        php_soap_prepare_globals();
00694        ZEND_INIT_MODULE_GLOBALS(soap, php_soap_init_globals, NULL);
00695        REGISTER_INI_ENTRIES();
00696 
00697 #ifndef ZEND_ENGINE_2
00698        /* Enable php stream/wrapper support for libxml */
00699        xmlRegisterDefaultInputCallbacks();
00700        xmlRegisterInputCallbacks(php_stream_xmlIO_match_wrapper, php_stream_xmlIO_open_wrapper,
00701                      php_stream_xmlIO_read, php_stream_xmlIO_close);
00702 #endif
00703 
00704        /* Register SoapClient class */
00705        /* BIG NOTE : THIS EMITS AN COMPILATION WARNING UNDER ZE2 - handle_function_call deprecated.
00706               soap_call_function_handler should be of type struct _zend_function, not (*handle_function_call).
00707        */
00708 #ifdef ZEND_ENGINE_2
00709        {
00710               zend_internal_function fe;
00711 
00712               fe.type = ZEND_INTERNAL_FUNCTION;
00713               fe.handler = ZEND_MN(SoapClient___call);
00714               fe.function_name = NULL;
00715               fe.scope = NULL;
00716               fe.fn_flags = 0;
00717               fe.prototype = NULL;
00718               fe.num_args = 2;
00719               fe.arg_info = NULL;
00720               fe.pass_rest_by_reference = 0;
00721 
00722               INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions,
00723                      (zend_function *)&fe, NULL, NULL);
00724               soap_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
00725        }
00726 #else
00727        INIT_OVERLOADED_CLASS_ENTRY(ce, PHP_SOAP_CLIENT_CLASSNAME, soap_client_functions, soap_call_function_handler, NULL, NULL);
00728        soap_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
00729 #endif
00730 
00731        /* Register SoapVar class */
00732        INIT_CLASS_ENTRY(ce, PHP_SOAP_VAR_CLASSNAME, soap_var_functions);
00733        soap_var_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
00734 
00735        /* Register SoapServer class */
00736        INIT_CLASS_ENTRY(ce, PHP_SOAP_SERVER_CLASSNAME, soap_server_functions);
00737        soap_server_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
00738 
00739        /* Register SoapFault class */
00740        INIT_CLASS_ENTRY(ce, PHP_SOAP_FAULT_CLASSNAME, soap_fault_functions);
00741 #ifdef ZEND_ENGINE_2
00742        soap_fault_class_entry = zend_register_internal_class_ex(&ce, zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC);
00743 #else
00744        soap_fault_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
00745 #endif
00746 
00747        /* Register SoapParam class */
00748        INIT_CLASS_ENTRY(ce, PHP_SOAP_PARAM_CLASSNAME, soap_param_functions);
00749        soap_param_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
00750 
00751        INIT_CLASS_ENTRY(ce, PHP_SOAP_HEADER_CLASSNAME, soap_header_functions);
00752        soap_header_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
00753 
00754        le_sdl = register_list_destructors(delete_sdl, NULL);
00755        le_url = register_list_destructors(delete_url, NULL);
00756        le_service = register_list_destructors(delete_service, NULL);
00757        le_typemap = register_list_destructors(delete_hashtable, NULL);
00758 
00759        REGISTER_LONG_CONSTANT("SOAP_1_1", SOAP_1_1, CONST_CS | CONST_PERSISTENT);
00760        REGISTER_LONG_CONSTANT("SOAP_1_2", SOAP_1_2, CONST_CS | CONST_PERSISTENT);
00761 
00762        REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_SESSION", SOAP_PERSISTENCE_SESSION, CONST_CS | CONST_PERSISTENT);
00763        REGISTER_LONG_CONSTANT("SOAP_PERSISTENCE_REQUEST", SOAP_PERSISTENCE_REQUEST, CONST_CS | CONST_PERSISTENT);
00764        REGISTER_LONG_CONSTANT("SOAP_FUNCTIONS_ALL", SOAP_FUNCTIONS_ALL, CONST_CS | CONST_PERSISTENT);
00765 
00766        REGISTER_LONG_CONSTANT("SOAP_ENCODED", SOAP_ENCODED, CONST_CS | CONST_PERSISTENT);
00767        REGISTER_LONG_CONSTANT("SOAP_LITERAL", SOAP_LITERAL, CONST_CS | CONST_PERSISTENT);
00768 
00769        REGISTER_LONG_CONSTANT("SOAP_RPC", SOAP_RPC, CONST_CS | CONST_PERSISTENT);
00770        REGISTER_LONG_CONSTANT("SOAP_DOCUMENT", SOAP_DOCUMENT, CONST_CS | CONST_PERSISTENT);
00771 
00772        REGISTER_LONG_CONSTANT("SOAP_ACTOR_NEXT", SOAP_ACTOR_NEXT, CONST_CS | CONST_PERSISTENT);
00773        REGISTER_LONG_CONSTANT("SOAP_ACTOR_NONE", SOAP_ACTOR_NONE, CONST_CS | CONST_PERSISTENT);
00774        REGISTER_LONG_CONSTANT("SOAP_ACTOR_UNLIMATERECEIVER", SOAP_ACTOR_UNLIMATERECEIVER, CONST_CS | CONST_PERSISTENT);
00775 
00776        REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_ACCEPT", SOAP_COMPRESSION_ACCEPT, CONST_CS | CONST_PERSISTENT);
00777        REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_GZIP", SOAP_COMPRESSION_GZIP, CONST_CS | CONST_PERSISTENT);
00778        REGISTER_LONG_CONSTANT("SOAP_COMPRESSION_DEFLATE", SOAP_COMPRESSION_DEFLATE, CONST_CS | CONST_PERSISTENT);
00779 
00780        REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_BASIC", SOAP_AUTHENTICATION_BASIC, CONST_CS | CONST_PERSISTENT);
00781        REGISTER_LONG_CONSTANT("SOAP_AUTHENTICATION_DIGEST", SOAP_AUTHENTICATION_DIGEST, CONST_CS | CONST_PERSISTENT);
00782 
00783        REGISTER_LONG_CONSTANT("UNKNOWN_TYPE", UNKNOWN_TYPE, CONST_CS | CONST_PERSISTENT);
00784 
00785        REGISTER_LONG_CONSTANT("XSD_STRING", XSD_STRING, CONST_CS | CONST_PERSISTENT);
00786        REGISTER_LONG_CONSTANT("XSD_BOOLEAN", XSD_BOOLEAN, CONST_CS | CONST_PERSISTENT);
00787        REGISTER_LONG_CONSTANT("XSD_DECIMAL", XSD_DECIMAL, CONST_CS | CONST_PERSISTENT);
00788        REGISTER_LONG_CONSTANT("XSD_FLOAT", XSD_FLOAT, CONST_CS | CONST_PERSISTENT);
00789        REGISTER_LONG_CONSTANT("XSD_DOUBLE", XSD_DOUBLE, CONST_CS | CONST_PERSISTENT);
00790        REGISTER_LONG_CONSTANT("XSD_DURATION", XSD_DURATION, CONST_CS | CONST_PERSISTENT);
00791        REGISTER_LONG_CONSTANT("XSD_DATETIME", XSD_DATETIME, CONST_CS | CONST_PERSISTENT);
00792        REGISTER_LONG_CONSTANT("XSD_TIME", XSD_TIME, CONST_CS | CONST_PERSISTENT);
00793        REGISTER_LONG_CONSTANT("XSD_DATE", XSD_DATE, CONST_CS | CONST_PERSISTENT);
00794        REGISTER_LONG_CONSTANT("XSD_GYEARMONTH", XSD_GYEARMONTH, CONST_CS | CONST_PERSISTENT);
00795        REGISTER_LONG_CONSTANT("XSD_GYEAR", XSD_GYEAR, CONST_CS | CONST_PERSISTENT);
00796        REGISTER_LONG_CONSTANT("XSD_GMONTHDAY", XSD_GMONTHDAY, CONST_CS | CONST_PERSISTENT);
00797        REGISTER_LONG_CONSTANT("XSD_GDAY", XSD_GDAY, CONST_CS | CONST_PERSISTENT);
00798        REGISTER_LONG_CONSTANT("XSD_GMONTH", XSD_GMONTH, CONST_CS | CONST_PERSISTENT);
00799        REGISTER_LONG_CONSTANT("XSD_HEXBINARY", XSD_HEXBINARY, CONST_CS | CONST_PERSISTENT);
00800        REGISTER_LONG_CONSTANT("XSD_BASE64BINARY", XSD_BASE64BINARY, CONST_CS | CONST_PERSISTENT);
00801        REGISTER_LONG_CONSTANT("XSD_ANYURI", XSD_ANYURI, CONST_CS | CONST_PERSISTENT);
00802        REGISTER_LONG_CONSTANT("XSD_QNAME", XSD_QNAME, CONST_CS | CONST_PERSISTENT);
00803        REGISTER_LONG_CONSTANT("XSD_NOTATION", XSD_NOTATION, CONST_CS | CONST_PERSISTENT);
00804        REGISTER_LONG_CONSTANT("XSD_NORMALIZEDSTRING", XSD_NORMALIZEDSTRING, CONST_CS | CONST_PERSISTENT);
00805        REGISTER_LONG_CONSTANT("XSD_TOKEN", XSD_TOKEN, CONST_CS | CONST_PERSISTENT);
00806        REGISTER_LONG_CONSTANT("XSD_LANGUAGE", XSD_LANGUAGE, CONST_CS | CONST_PERSISTENT);
00807        REGISTER_LONG_CONSTANT("XSD_NMTOKEN", XSD_NMTOKEN, CONST_CS | CONST_PERSISTENT);
00808        REGISTER_LONG_CONSTANT("XSD_NAME", XSD_NAME, CONST_CS | CONST_PERSISTENT);
00809        REGISTER_LONG_CONSTANT("XSD_NCNAME", XSD_NCNAME, CONST_CS | CONST_PERSISTENT);
00810        REGISTER_LONG_CONSTANT("XSD_ID", XSD_ID, CONST_CS | CONST_PERSISTENT);
00811        REGISTER_LONG_CONSTANT("XSD_IDREF", XSD_IDREF, CONST_CS | CONST_PERSISTENT);
00812        REGISTER_LONG_CONSTANT("XSD_IDREFS", XSD_IDREFS, CONST_CS | CONST_PERSISTENT);
00813        REGISTER_LONG_CONSTANT("XSD_ENTITY", XSD_ENTITY, CONST_CS | CONST_PERSISTENT);
00814        REGISTER_LONG_CONSTANT("XSD_ENTITIES", XSD_ENTITIES, CONST_CS | CONST_PERSISTENT);
00815        REGISTER_LONG_CONSTANT("XSD_INTEGER", XSD_INTEGER, CONST_CS | CONST_PERSISTENT);
00816        REGISTER_LONG_CONSTANT("XSD_NONPOSITIVEINTEGER", XSD_NONPOSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
00817        REGISTER_LONG_CONSTANT("XSD_NEGATIVEINTEGER", XSD_NEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
00818        REGISTER_LONG_CONSTANT("XSD_LONG", XSD_LONG, CONST_CS | CONST_PERSISTENT);
00819        REGISTER_LONG_CONSTANT("XSD_INT", XSD_INT, CONST_CS | CONST_PERSISTENT);
00820        REGISTER_LONG_CONSTANT("XSD_SHORT", XSD_SHORT, CONST_CS | CONST_PERSISTENT);
00821        REGISTER_LONG_CONSTANT("XSD_BYTE", XSD_BYTE, CONST_CS | CONST_PERSISTENT);
00822        REGISTER_LONG_CONSTANT("XSD_NONNEGATIVEINTEGER", XSD_NONNEGATIVEINTEGER, CONST_CS | CONST_PERSISTENT);
00823        REGISTER_LONG_CONSTANT("XSD_UNSIGNEDLONG", XSD_UNSIGNEDLONG, CONST_CS | CONST_PERSISTENT);
00824        REGISTER_LONG_CONSTANT("XSD_UNSIGNEDINT", XSD_UNSIGNEDINT, CONST_CS | CONST_PERSISTENT);
00825        REGISTER_LONG_CONSTANT("XSD_UNSIGNEDSHORT", XSD_UNSIGNEDSHORT, CONST_CS | CONST_PERSISTENT);
00826        REGISTER_LONG_CONSTANT("XSD_UNSIGNEDBYTE", XSD_UNSIGNEDBYTE, CONST_CS | CONST_PERSISTENT);
00827        REGISTER_LONG_CONSTANT("XSD_POSITIVEINTEGER", XSD_POSITIVEINTEGER, CONST_CS | CONST_PERSISTENT);
00828        REGISTER_LONG_CONSTANT("XSD_NMTOKENS", XSD_NMTOKENS, CONST_CS | CONST_PERSISTENT);
00829        REGISTER_LONG_CONSTANT("XSD_ANYTYPE", XSD_ANYTYPE, CONST_CS | CONST_PERSISTENT);
00830        REGISTER_LONG_CONSTANT("XSD_ANYXML", XSD_ANYXML, CONST_CS | CONST_PERSISTENT);
00831 
00832        REGISTER_LONG_CONSTANT("APACHE_MAP", APACHE_MAP, CONST_CS | CONST_PERSISTENT);
00833 
00834        REGISTER_LONG_CONSTANT("SOAP_ENC_OBJECT", SOAP_ENC_OBJECT, CONST_CS | CONST_PERSISTENT);
00835        REGISTER_LONG_CONSTANT("SOAP_ENC_ARRAY", SOAP_ENC_ARRAY, CONST_CS | CONST_PERSISTENT);
00836 
00837        REGISTER_LONG_CONSTANT("XSD_1999_TIMEINSTANT", XSD_1999_TIMEINSTANT, CONST_CS | CONST_PERSISTENT);
00838 
00839        REGISTER_STRING_CONSTANT("XSD_NAMESPACE", XSD_NAMESPACE, CONST_CS | CONST_PERSISTENT);
00840        REGISTER_STRING_CONSTANT("XSD_1999_NAMESPACE", XSD_1999_NAMESPACE,  CONST_CS | CONST_PERSISTENT);
00841 
00842        REGISTER_LONG_CONSTANT("SOAP_SINGLE_ELEMENT_ARRAYS", SOAP_SINGLE_ELEMENT_ARRAYS, CONST_CS | CONST_PERSISTENT);
00843        REGISTER_LONG_CONSTANT("SOAP_WAIT_ONE_WAY_CALLS", SOAP_WAIT_ONE_WAY_CALLS, CONST_CS | CONST_PERSISTENT);
00844        REGISTER_LONG_CONSTANT("SOAP_USE_XSI_ARRAY_TYPE", SOAP_USE_XSI_ARRAY_TYPE, CONST_CS | CONST_PERSISTENT);
00845 
00846        REGISTER_LONG_CONSTANT("WSDL_CACHE_NONE",   WSDL_CACHE_NONE,   CONST_CS | CONST_PERSISTENT);
00847        REGISTER_LONG_CONSTANT("WSDL_CACHE_DISK",   WSDL_CACHE_DISK,   CONST_CS | CONST_PERSISTENT);
00848        REGISTER_LONG_CONSTANT("WSDL_CACHE_MEMORY", WSDL_CACHE_MEMORY, CONST_CS | CONST_PERSISTENT);
00849        REGISTER_LONG_CONSTANT("WSDL_CACHE_BOTH",   WSDL_CACHE_BOTH,   CONST_CS | CONST_PERSISTENT);
00850 
00851        old_error_handler = zend_error_cb;
00852        zend_error_cb = soap_error_handler;
00853 
00854        return SUCCESS;
00855 }
00856 
00857 PHP_MINFO_FUNCTION(soap)
00858 {
00859        php_info_print_table_start();
00860        php_info_print_table_row(2, "Soap Client", "enabled");
00861        php_info_print_table_row(2, "Soap Server", "enabled");
00862        php_info_print_table_end();
00863        DISPLAY_INI_ENTRIES();
00864 }
00865 
00866 
00867 /* {{{ proto object SoapParam::SoapParam ( mixed data, string name)
00868    SoapParam constructor */
00869 PHP_METHOD(SoapParam, SoapParam)
00870 {
00871        zval *data;
00872        char *name;
00873        int name_length;
00874 
00875        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &data, &name, &name_length) == FAILURE) {
00876               return;
00877        }
00878        if (name_length == 0) {
00879               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid parameter name");
00880               return;
00881        }
00882 
00883 #ifndef ZEND_ENGINE_2
00884        zval_add_ref(&data);
00885 #endif
00886        add_property_stringl(this_ptr, "param_name", name, name_length, 1);
00887        add_property_zval(this_ptr, "param_data", data);
00888 }
00889 /* }}} */
00890 
00891 
00892 /* {{{ proto object SoapHeader::SoapHeader ( string namespace, string name [, mixed data [, bool mustUnderstand [, mixed actor]]])
00893    SoapHeader constructor */
00894 PHP_METHOD(SoapHeader, SoapHeader)
00895 {
00896        zval *data = NULL, *actor = NULL;
00897        char *name, *ns;
00898        int name_len, ns_len;
00899        zend_bool must_understand = 0;
00900 
00901        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|zbz", &ns, &ns_len, &name, &name_len, &data, &must_understand, &actor) == FAILURE) {
00902               return;
00903        }
00904        if (ns_len == 0) {
00905               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid namespace");
00906               return;
00907        }
00908        if (name_len == 0) {
00909               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid header name");
00910               return;
00911        }
00912 
00913        add_property_stringl(this_ptr, "namespace", ns, ns_len, 1);
00914        add_property_stringl(this_ptr, "name", name, name_len, 1);
00915        if (data) {
00916 #ifndef ZEND_ENGINE_2
00917               zval_add_ref(&data);
00918 #endif
00919               add_property_zval(this_ptr, "data", data);
00920        }
00921        add_property_bool(this_ptr, "mustUnderstand", must_understand);
00922        if (actor == NULL) {
00923        } else if (Z_TYPE_P(actor) == IS_LONG &&
00924          (Z_LVAL_P(actor) == SOAP_ACTOR_NEXT ||
00925           Z_LVAL_P(actor) == SOAP_ACTOR_NONE ||
00926           Z_LVAL_P(actor) == SOAP_ACTOR_UNLIMATERECEIVER)) {
00927               add_property_long(this_ptr, "actor", Z_LVAL_P(actor));
00928        } else if (Z_TYPE_P(actor) == IS_STRING && Z_STRLEN_P(actor) > 0) {
00929               add_property_stringl(this_ptr, "actor", Z_STRVAL_P(actor), Z_STRLEN_P(actor), 1);
00930        } else {
00931               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid actor");
00932        }
00933 }
00934 
00935 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
00936    SoapFault constructor */
00937 PHP_METHOD(SoapFault, SoapFault)
00938 {
00939        char *fault_string = NULL, *fault_code = NULL, *fault_actor = NULL, *name = NULL, *fault_code_ns = NULL;
00940        int fault_string_len, fault_actor_len = 0, name_len = 0, fault_code_len = 0;
00941        zval *code = NULL, *details = NULL, *headerfault = NULL;
00942 
00943        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs|s!z!s!z",
00944               &code,
00945               &fault_string, &fault_string_len,
00946               &fault_actor, &fault_actor_len,
00947               &details, &name, &name_len, &headerfault) == FAILURE) {
00948               return;
00949        }
00950 
00951        if (Z_TYPE_P(code) == IS_NULL) {
00952        } else if (Z_TYPE_P(code) == IS_STRING) {
00953               fault_code = Z_STRVAL_P(code);
00954               fault_code_len = Z_STRLEN_P(code);
00955        } else if (Z_TYPE_P(code) == IS_ARRAY && zend_hash_num_elements(Z_ARRVAL_P(code)) == 2) {
00956               zval **t_ns, **t_code;
00957 
00958               zend_hash_internal_pointer_reset(Z_ARRVAL_P(code));
00959               zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_ns);
00960               zend_hash_move_forward(Z_ARRVAL_P(code));
00961               zend_hash_get_current_data(Z_ARRVAL_P(code), (void**)&t_code);
00962               if (Z_TYPE_PP(t_ns) == IS_STRING && Z_TYPE_PP(t_code) == IS_STRING) {
00963                 fault_code_ns = Z_STRVAL_PP(t_ns);
00964                 fault_code = Z_STRVAL_PP(t_code);
00965                 fault_code_len = Z_STRLEN_PP(t_code);
00966               } else {
00967                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
00968                      return;
00969               }
00970        } else  {
00971               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
00972               return;
00973        }
00974        if (fault_code != NULL && fault_code_len == 0) {
00975               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fault code");
00976               return;
00977        }
00978        if (name != NULL && name_len == 0) {
00979               name = NULL;
00980        }
00981 
00982        set_soap_fault(this_ptr, fault_code_ns, fault_code, fault_string, fault_actor, details, name TSRMLS_CC);
00983        if (headerfault != NULL) {
00984               add_property_zval(this_ptr, "headerfault", headerfault);
00985        }
00986 }
00987 /* }}} */
00988 
00989 
00990 #ifdef ZEND_ENGINE_2
00991 /* {{{ proto object SoapFault::SoapFault ( string faultcode, string faultstring [, string faultactor [, mixed detail [, string faultname [, mixed headerfault]]]])
00992    SoapFault constructor */
00993 PHP_METHOD(SoapFault, __toString)
00994 {
00995        zval *faultcode, *faultstring, *file, *line, *trace;
00996        char *str;
00997        int len;
00998        zend_fcall_info fci;
00999        zval fname;
01000 
01001        if (zend_parse_parameters_none() == FAILURE) {
01002               return;
01003        }
01004 
01005        faultcode   = zend_read_property(soap_fault_class_entry, this_ptr, "faultcode", sizeof("faultcode")-1, 1 TSRMLS_CC);
01006        faultstring = zend_read_property(soap_fault_class_entry, this_ptr, "faultstring", sizeof("faultstring")-1, 1 TSRMLS_CC);
01007        file = zend_read_property(soap_fault_class_entry, this_ptr, "file", sizeof("file")-1, 1 TSRMLS_CC);
01008        line = zend_read_property(soap_fault_class_entry, this_ptr, "line", sizeof("line")-1, 1 TSRMLS_CC);
01009 
01010        ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
01011 
01012        fci.size = sizeof(fci);
01013        fci.function_table = &Z_OBJCE_P(getThis())->function_table;
01014        fci.function_name = &fname;
01015        fci.symbol_table = NULL;
01016        fci.object_ptr = getThis();
01017        fci.retval_ptr_ptr = &trace;
01018        fci.param_count = 0;
01019        fci.params = NULL;
01020        fci.no_separation = 1;
01021 
01022        zend_call_function(&fci, NULL TSRMLS_CC);
01023 
01024        len = spprintf(&str, 0, "SoapFault exception: [%s] %s in %s:%ld\nStack trace:\n%s",
01025                       Z_STRVAL_P(faultcode), Z_STRVAL_P(faultstring), Z_STRVAL_P(file), Z_LVAL_P(line),
01026                       Z_STRLEN_P(trace) ? Z_STRVAL_P(trace) : "#0 {main}\n");
01027 
01028        zval_ptr_dtor(&trace);
01029 
01030        RETURN_STRINGL(str, len, 0);
01031 }
01032 /* }}} */
01033 #endif
01034 
01035 /* {{{ proto object SoapVar::SoapVar ( mixed data, int encoding [, string type_name [, string type_namespace [, string node_name [, string node_namespace]]]])
01036    SoapVar constructor */
01037 PHP_METHOD(SoapVar, SoapVar)
01038 {
01039        zval *data, *type;
01040        char *stype = NULL, *ns = NULL, *name = NULL, *namens = NULL;
01041        int stype_len = 0, ns_len = 0, name_len = 0, namens_len = 0;
01042 
01043        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) {
01044               return;
01045        }
01046 
01047        if (Z_TYPE_P(type) == IS_NULL) {
01048               add_property_long(this_ptr, "enc_type", UNKNOWN_TYPE);
01049        } else {
01050               if (zend_hash_index_exists(&SOAP_GLOBAL(defEncIndex), Z_LVAL_P(type))) {
01051                      add_property_long(this_ptr, "enc_type", Z_LVAL_P(type));
01052               } else {
01053                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type ID");
01054                      return;
01055               }
01056        }
01057 
01058        if (data) {
01059 #ifndef ZEND_ENGINE_2
01060               zval_add_ref(&data);
01061 #endif
01062               add_property_zval(this_ptr, "enc_value", data);
01063        }
01064 
01065        if (stype && stype_len > 0) {
01066               add_property_stringl(this_ptr, "enc_stype", stype, stype_len, 1);
01067        }
01068        if (ns && ns_len > 0) {
01069               add_property_stringl(this_ptr, "enc_ns", ns, ns_len, 1);
01070        }
01071        if (name && name_len > 0) {
01072               add_property_stringl(this_ptr, "enc_name", name, name_len, 1);
01073        }
01074        if (namens && namens_len > 0) {
01075               add_property_stringl(this_ptr, "enc_namens", namens, namens_len, 1);
01076        }
01077 }
01078 /* }}} */
01079 
01080 
01081 static HashTable* soap_create_typemap(sdlPtr sdl, HashTable *ht TSRMLS_DC)
01082 {
01083        zval **tmp;
01084        HashTable *ht2;
01085        HashPosition pos1, pos2;
01086        HashTable *typemap = NULL;
01087        
01088        zend_hash_internal_pointer_reset_ex(ht, &pos1);
01089        while (zend_hash_get_current_data_ex(ht, (void**)&tmp, &pos1) == SUCCESS) {
01090               char *type_name = NULL;
01091               char *type_ns = NULL;
01092               zval *to_xml = NULL;
01093               zval *to_zval = NULL;
01094               encodePtr enc, new_enc;
01095 
01096               if (Z_TYPE_PP(tmp) != IS_ARRAY) {
01097                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Wrong 'typemap' option");
01098                      return NULL;
01099               }
01100               ht2 = Z_ARRVAL_PP(tmp);
01101 
01102               zend_hash_internal_pointer_reset_ex(ht2, &pos2);
01103               while (zend_hash_get_current_data_ex(ht2, (void**)&tmp, &pos2) == SUCCESS) {
01104                      char *name = NULL;
01105                      unsigned int name_len;
01106                      ulong index;
01107 
01108                      zend_hash_get_current_key_ex(ht2, &name, &name_len, &index, 0, &pos2);
01109                      if (name) {
01110                             if (name_len == sizeof("type_name") &&
01111                                 strncmp(name, "type_name", sizeof("type_name")-1) == 0) {
01112                                    if (Z_TYPE_PP(tmp) == IS_STRING) {
01113                                           type_name = Z_STRVAL_PP(tmp);
01114                                    } else if (Z_TYPE_PP(tmp) != IS_NULL) {
01115                                    }
01116                             } else if (name_len == sizeof("type_ns") &&
01117                                 strncmp(name, "type_ns", sizeof("type_ns")-1) == 0) {
01118                                    if (Z_TYPE_PP(tmp) == IS_STRING) {
01119                                           type_ns = Z_STRVAL_PP(tmp);
01120                                    } else if (Z_TYPE_PP(tmp) != IS_NULL) {
01121                                    }
01122                             } else if (name_len == sizeof("to_xml") &&
01123                                 strncmp(name, "to_xml", sizeof("to_xml")-1) == 0) {
01124                                    to_xml = *tmp;
01125                             } else if (name_len == sizeof("from_xml") &&
01126                                 strncmp(name, "from_xml", sizeof("from_xml")-1) == 0) {
01127                                    to_zval = *tmp;
01128                             }
01129                      }
01130                      zend_hash_move_forward_ex(ht2, &pos2);
01131               }             
01132 
01133               if (type_name) {
01134                      smart_str nscat = {0};
01135 
01136                      if (type_ns) {
01137                             enc = get_encoder(sdl, type_ns, type_name);
01138                      } else {
01139                             enc = get_encoder_ex(sdl, type_name, strlen(type_name));
01140                      }
01141 
01142                      new_enc = emalloc(sizeof(encode));
01143                      memset(new_enc, 0, sizeof(encode));
01144 
01145                      if (enc) {
01146                             new_enc->details.type = enc->details.type;
01147                             new_enc->details.ns = estrdup(enc->details.ns);
01148                             new_enc->details.type_str = estrdup(enc->details.type_str);
01149                             new_enc->details.sdl_type = enc->details.sdl_type;
01150                      } else {
01151                             enc = get_conversion(UNKNOWN_TYPE);
01152                             new_enc->details.type = enc->details.type;
01153                             if (type_ns) {
01154                                    new_enc->details.ns = estrdup(type_ns);
01155                             }
01156                             new_enc->details.type_str = estrdup(type_name);
01157                      }
01158                      new_enc->to_xml = enc->to_xml;
01159                      new_enc->to_zval = enc->to_zval;
01160                      new_enc->details.map = emalloc(sizeof(soapMapping));
01161                      memset(new_enc->details.map, 0, sizeof(soapMapping));                 
01162                      if (to_xml) {
01163                             zval_add_ref(&to_xml);
01164                             new_enc->details.map->to_xml = to_xml;
01165                             new_enc->to_xml = to_xml_user;
01166                      } else if (enc->details.map && enc->details.map->to_xml) {
01167                             zval_add_ref(&enc->details.map->to_xml);
01168                             new_enc->details.map->to_xml = enc->details.map->to_xml;
01169                      }
01170                      if (to_zval) {
01171                             zval_add_ref(&to_zval);
01172                             new_enc->details.map->to_zval = to_zval;
01173                             new_enc->to_zval = to_zval_user;
01174                      } else if (enc->details.map && enc->details.map->to_zval) {
01175                             zval_add_ref(&enc->details.map->to_zval);
01176                             new_enc->details.map->to_zval = enc->details.map->to_zval;
01177                      }
01178                      if (!typemap) {
01179                             typemap = emalloc(sizeof(HashTable));
01180                             zend_hash_init(typemap, 0, NULL, delete_encoder, 0);
01181                      }
01182 
01183                      if (type_ns) {
01184                             smart_str_appends(&nscat, type_ns);
01185                             smart_str_appendc(&nscat, ':');
01186                      }
01187                      smart_str_appends(&nscat, type_name);
01188                      smart_str_0(&nscat);
01189                      zend_hash_update(typemap, nscat.c, nscat.len + 1, &new_enc, sizeof(encodePtr), NULL);
01190                      smart_str_free(&nscat);
01191               }
01192               zend_hash_move_forward_ex(ht, &pos1);
01193        }
01194        return typemap;
01195 }
01196 
01197 
01198 /* {{{ proto object SoapServer::SoapServer ( mixed wsdl [, array options])
01199    SoapServer constructor */
01200 PHP_METHOD(SoapServer, SoapServer)
01201 {
01202        soapServicePtr service;
01203        zval *wsdl = NULL, *options = NULL;
01204        int ret;
01205        int version = SOAP_1_1;
01206        long cache_wsdl;
01207        HashTable *typemap_ht = NULL;
01208 
01209        SOAP_SERVER_BEGIN_CODE();
01210 
01211        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
01212               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
01213        }
01214 
01215        if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
01216               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
01217        }
01218        
01219        service = emalloc(sizeof(soapService));
01220        memset(service, 0, sizeof(soapService));
01221        service->send_errors = 1;
01222 
01223        cache_wsdl = SOAP_GLOBAL(cache);
01224 
01225        if (options != NULL) {
01226               HashTable *ht = Z_ARRVAL_P(options);
01227               zval **tmp;
01228 
01229               if (zend_hash_find(ht, "soap_version", sizeof("soap_version"), (void**)&tmp) == SUCCESS) {
01230                      if (Z_TYPE_PP(tmp) == IS_LONG &&
01231                          (Z_LVAL_PP(tmp) == SOAP_1_1 || Z_LVAL_PP(tmp) == SOAP_1_2)) {
01232                             version = Z_LVAL_PP(tmp);
01233                      } else {
01234                             php_error_docref(NULL TSRMLS_CC, E_ERROR, "'soap_version' option must be SOAP_1_1 or SOAP_1_2");
01235                      }
01236               }
01237 
01238               if (zend_hash_find(ht, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
01239                   Z_TYPE_PP(tmp) == IS_STRING) {
01240                      service->uri = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
01241               } else if (Z_TYPE_P(wsdl) == IS_NULL) {
01242                      php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
01243               }
01244 
01245               if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS &&
01246                   Z_TYPE_PP(tmp) == IS_STRING) {
01247                      service->actor = estrndup(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
01248               }
01249 
01250               if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
01251                   Z_TYPE_PP(tmp) == IS_STRING) {
01252                      xmlCharEncodingHandlerPtr encoding;
01253               
01254                      encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
01255                      if (encoding == NULL) {
01256                             php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
01257                      } else {
01258                        service->encoding = encoding;
01259                      }
01260               }
01261 
01262               if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
01263                      Z_TYPE_PP(tmp) == IS_ARRAY) {
01264                      zval *ztmp;
01265 
01266                      ALLOC_HASHTABLE(service->class_map);
01267                      zend_hash_init(service->class_map, zend_hash_num_elements((*tmp)->value.ht), NULL, ZVAL_PTR_DTOR, 0);
01268                      zend_hash_copy(service->class_map, (*tmp)->value.ht, (copy_ctor_func_t) zval_add_ref, (void *) &ztmp, sizeof(zval *));
01269               }
01270 
01271               if (zend_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS &&
01272                      Z_TYPE_PP(tmp) == IS_ARRAY &&
01273                      zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) {
01274                      typemap_ht = Z_ARRVAL_PP(tmp);
01275               }
01276 
01277               if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
01278                      Z_TYPE_PP(tmp) == IS_LONG) {
01279                      service->features = Z_LVAL_PP(tmp);
01280               }
01281 
01282               if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
01283                   Z_TYPE_PP(tmp) == IS_LONG) {
01284                      cache_wsdl = Z_LVAL_PP(tmp);
01285               }
01286 
01287               if (zend_hash_find(ht, "send_errors", sizeof("send_errors"), (void**)&tmp) == SUCCESS &&
01288                   (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG)) {
01289                      service->send_errors = Z_LVAL_PP(tmp);
01290               }
01291 
01292        } else if (Z_TYPE_P(wsdl) == IS_NULL) {
01293               php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
01294        }
01295 
01296        service->version = version;
01297        service->type = SOAP_FUNCTIONS;
01298        service->soap_functions.functions_all = FALSE;
01299        service->soap_functions.ft = emalloc(sizeof(HashTable));
01300        zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
01301 
01302        if (Z_TYPE_P(wsdl) != IS_NULL) {
01303               service->sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
01304               if (service->uri == NULL) {
01305                      if (service->sdl->target_ns) {
01306                             service->uri = estrdup(service->sdl->target_ns);
01307                      } else {
01308                             /*FIXME*/
01309                             service->uri = estrdup("http://unknown-uri/");
01310                      }
01311               }
01312        }
01313        
01314        if (typemap_ht) {
01315               service->typemap = soap_create_typemap(service->sdl, typemap_ht TSRMLS_CC);
01316        }
01317 
01318        ret = zend_list_insert(service, le_service);
01319        add_property_resource(this_ptr, "service", ret);
01320 
01321        SOAP_SERVER_END_CODE();
01322 }
01323 /* }}} */
01324 
01325 
01326 /* {{{ proto object SoapServer::setPersistence ( int mode )
01327    Sets persistence mode of SoapServer */
01328 PHP_METHOD(SoapServer, setPersistence)
01329 {
01330        soapServicePtr service;
01331        long value;
01332 
01333        SOAP_SERVER_BEGIN_CODE();
01334 
01335        FETCH_THIS_SERVICE(service);
01336 
01337        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &value) != FAILURE) {
01338               if (service->type == SOAP_CLASS) {
01339                      if (value == SOAP_PERSISTENCE_SESSION ||
01340                             value == SOAP_PERSISTENCE_REQUEST) {
01341                             service->soap_class.persistance = value;
01342                      } else {
01343                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set persistence with bogus value (%ld)", value);
01344                             return;
01345                      }
01346               } else {
01347                      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");
01348                      return;
01349               }
01350        }
01351 
01352        SOAP_SERVER_END_CODE();
01353 }
01354 /* }}} */
01355 
01356 
01357 /* {{{ proto void SoapServer::setClass(string class_name [, mixed args])
01358    Sets class which will handle SOAP requests */
01359 PHP_METHOD(SoapServer, setClass)
01360 {
01361        soapServicePtr service;
01362        char *classname;
01363 #ifdef ZEND_ENGINE_2        
01364        zend_class_entry **ce;
01365 #else
01366        zend_class_entry *ce;
01367 #endif
01368        int classname_len, found, num_args = 0;
01369        zval ***argv = NULL;
01370 
01371        SOAP_SERVER_BEGIN_CODE();
01372 
01373        FETCH_THIS_SERVICE(service);
01374 
01375        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s*", &classname, &classname_len, &argv, &num_args) == FAILURE) {
01376               return;
01377        }
01378 
01379 #ifdef ZEND_ENGINE_2        
01380        found = zend_lookup_class(classname, classname_len, &ce TSRMLS_CC);
01381 #else
01382        char *class_name = estrdup(classname);
01383        found = zend_hash_find(EG(class_table), php_strtolower(class_name, classname_len), classname_len + 1, (void **)&ce);
01384        efree(class_name);
01385 #endif
01386        if (found != FAILURE) {
01387               service->type = SOAP_CLASS;
01388 #ifdef ZEND_ENGINE_2
01389               service->soap_class.ce = *ce;
01390 #else
01391               service->soap_class.ce = ce;
01392 #endif
01393               service->soap_class.persistance = SOAP_PERSISTENCE_REQUEST;
01394               service->soap_class.argc = num_args;
01395               if (service->soap_class.argc > 0) {
01396                      int i;
01397                      service->soap_class.argv = safe_emalloc(sizeof(zval), service->soap_class.argc, 0);
01398                      for (i = 0;i < service->soap_class.argc;i++) {
01399                             service->soap_class.argv[i] = *(argv[i]);
01400                             zval_add_ref(&service->soap_class.argv[i]);
01401                      }
01402               }
01403        } else {
01404               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to set a non existant class (%s)", classname);
01405               return;
01406        }
01407 
01408        if (argv) {
01409               efree(argv);
01410        }
01411 
01412        SOAP_SERVER_END_CODE();
01413 }
01414 /* }}} */
01415 
01416 
01417 /* {{{ proto void SoapServer::setObject(object)
01418    Sets object which will handle SOAP requests */
01419 PHP_METHOD(SoapServer, setObject)
01420 {
01421        soapServicePtr service;
01422        zval *obj;
01423 
01424        SOAP_SERVER_BEGIN_CODE();
01425 
01426        FETCH_THIS_SERVICE(service);
01427 
01428        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
01429               return;
01430        }
01431 
01432        service->type = SOAP_OBJECT;
01433 
01434        MAKE_STD_ZVAL(service->soap_object);
01435        MAKE_COPY_ZVAL(&obj, service->soap_object);
01436 
01437        SOAP_SERVER_END_CODE();
01438 }
01439 /* }}} */
01440 
01441 
01442 /* {{{ proto array SoapServer::getFunctions(void)
01443    Returns list of defined functions */
01444 PHP_METHOD(SoapServer, getFunctions)
01445 {
01446        soapServicePtr  service;
01447        HashTable      *ft = NULL;
01448 
01449        SOAP_SERVER_BEGIN_CODE();
01450 
01451        if (zend_parse_parameters_none() == FAILURE) {
01452               return;
01453        }
01454        
01455        FETCH_THIS_SERVICE(service);
01456 
01457        array_init(return_value);
01458        if (service->type == SOAP_OBJECT) {
01459               ft = &(Z_OBJCE_P(service->soap_object)->function_table);
01460        } else if (service->type == SOAP_CLASS) {
01461               ft = &service->soap_class.ce->function_table;
01462        } else if (service->soap_functions.functions_all == TRUE) {
01463               ft = EG(function_table);
01464        } else if (service->soap_functions.ft != NULL) {
01465               zval **name;
01466               HashPosition pos;
01467 
01468               zend_hash_internal_pointer_reset_ex(service->soap_functions.ft, &pos);
01469               while (zend_hash_get_current_data_ex(service->soap_functions.ft, (void **)&name, &pos) != FAILURE) {
01470                      add_next_index_string(return_value, Z_STRVAL_PP(name), 1);
01471                      zend_hash_move_forward_ex(service->soap_functions.ft, &pos);
01472               }
01473        }
01474        if (ft != NULL) {
01475               zend_function *f;
01476               HashPosition pos;
01477               zend_hash_internal_pointer_reset_ex(ft, &pos);
01478               while (zend_hash_get_current_data_ex(ft, (void **)&f, &pos) != FAILURE) {
01479                      if ((service->type != SOAP_OBJECT && service->type != SOAP_CLASS) || (f->common.fn_flags & ZEND_ACC_PUBLIC)) {
01480                             add_next_index_string(return_value, f->common.function_name, 1);
01481                      }
01482                      zend_hash_move_forward_ex(ft, &pos);
01483               }
01484        }
01485 
01486        SOAP_SERVER_END_CODE();
01487 }
01488 /* }}} */
01489 
01490 
01491 /* {{{ proto void SoapServer::addFunction(mixed functions)
01492    Adds one or several functions those will handle SOAP requests */
01493 PHP_METHOD(SoapServer, addFunction)
01494 {
01495        soapServicePtr service;
01496        zval *function_name, *function_copy;
01497        HashPosition pos;
01498 
01499        SOAP_SERVER_BEGIN_CODE();
01500 
01501        FETCH_THIS_SERVICE(service);
01502 
01503        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &function_name) == FAILURE) {
01504               return;
01505        }
01506 
01507        /* TODO: could use zend_is_callable here */
01508 
01509        if (function_name->type == IS_ARRAY) {
01510               if (service->type == SOAP_FUNCTIONS) {
01511                      zval **tmp_function, *function_copy;
01512 
01513                      if (service->soap_functions.ft == NULL) {
01514                             service->soap_functions.functions_all = FALSE;
01515                             service->soap_functions.ft = emalloc(sizeof(HashTable));
01516                             zend_hash_init(service->soap_functions.ft, zend_hash_num_elements(Z_ARRVAL_P(function_name)), NULL, ZVAL_PTR_DTOR, 0);
01517                      }
01518 
01519                      zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(function_name), &pos);
01520                      while (zend_hash_get_current_data_ex(Z_ARRVAL_P(function_name), (void **)&tmp_function, &pos) != FAILURE) {
01521                             char *key;
01522                             int   key_len;
01523                             zend_function *f;
01524 
01525                             if (Z_TYPE_PP(tmp_function) != IS_STRING) {
01526                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a function that isn't a string");
01527                                    return;
01528                             }
01529 
01530                             key_len = Z_STRLEN_PP(tmp_function);
01531                             key = emalloc(key_len + 1);
01532                             zend_str_tolower_copy(key, Z_STRVAL_PP(tmp_function), key_len);
01533 
01534                             if (zend_hash_find(EG(function_table), key, key_len+1, (void**)&f) == FAILURE) {
01535                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a non existant function '%s'", Z_STRVAL_PP(tmp_function));
01536                                    return;
01537                             }
01538 
01539                             MAKE_STD_ZVAL(function_copy);
01540                             ZVAL_STRING(function_copy, f->common.function_name, 1);
01541                             zend_hash_update(service->soap_functions.ft, key, key_len+1, &function_copy, sizeof(zval *), NULL);
01542 
01543                             efree(key);
01544                             zend_hash_move_forward_ex(Z_ARRVAL_P(function_name), &pos);
01545                      }
01546               }
01547        } else if (function_name->type == IS_STRING) {
01548               char *key;
01549               int   key_len;
01550               zend_function *f;
01551 
01552               key_len = Z_STRLEN_P(function_name);
01553               key = emalloc(key_len + 1);
01554               zend_str_tolower_copy(key, Z_STRVAL_P(function_name), key_len);
01555 
01556               if (zend_hash_find(EG(function_table), key, key_len+1, (void**)&f) == FAILURE) {
01557                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tried to add a non existant function '%s'", Z_STRVAL_P(function_name));
01558                      return;
01559               }
01560               if (service->soap_functions.ft == NULL) {
01561                      service->soap_functions.functions_all = FALSE;
01562                      service->soap_functions.ft = emalloc(sizeof(HashTable));
01563                      zend_hash_init(service->soap_functions.ft, 0, NULL, ZVAL_PTR_DTOR, 0);
01564               }
01565 
01566               MAKE_STD_ZVAL(function_copy);
01567               ZVAL_STRING(function_copy, f->common.function_name, 1);
01568               zend_hash_update(service->soap_functions.ft, key, key_len+1, &function_copy, sizeof(zval *), NULL);
01569               efree(key);
01570        } else if (function_name->type == IS_LONG) {
01571               if (Z_LVAL_P(function_name) == SOAP_FUNCTIONS_ALL) {
01572                      if (service->soap_functions.ft != NULL) {
01573                             zend_hash_destroy(service->soap_functions.ft);
01574                             efree(service->soap_functions.ft);
01575                             service->soap_functions.ft = NULL;
01576                      }
01577                      service->soap_functions.functions_all = TRUE;
01578               } else {
01579                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value passed");
01580                      return;
01581               }
01582        }
01583 
01584        SOAP_SERVER_END_CODE();
01585 }
01586 /* }}} */
01587 
01588 
01589 /* {{{ proto void SoapServer::handle ( [string soap_request])
01590    Handles a SOAP request */
01591 PHP_METHOD(SoapServer, handle)
01592 {
01593        int soap_version, old_soap_version;
01594        sdlPtr old_sdl = NULL;
01595        soapServicePtr service;
01596        xmlDocPtr doc_request=NULL, doc_return;
01597        zval function_name, **params, *soap_obj, *retval;
01598        char *fn_name, cont_len[30];
01599        int num_params = 0, size, i, call_status = 0;
01600        xmlChar *buf;
01601        HashTable *function_table;
01602        soapHeader *soap_headers = NULL;
01603        sdlFunctionPtr function;
01604        char *arg = NULL;
01605        int arg_len = 0;
01606        xmlCharEncodingHandlerPtr old_encoding;
01607        HashTable *old_class_map, *old_typemap;
01608        int old_features;
01609 
01610        SOAP_SERVER_BEGIN_CODE();
01611 
01612        FETCH_THIS_SERVICE(service);
01613        SOAP_GLOBAL(soap_version) = service->version;
01614        
01615        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &arg, &arg_len) == FAILURE) {
01616               return;
01617        }
01618 
01619        if (SG(request_info).request_method &&
01620            strcmp(SG(request_info).request_method, "GET") == 0 &&
01621            SG(request_info).query_string &&
01622            stricmp(SG(request_info).query_string, "wsdl") == 0) {
01623 
01624               if (service->sdl) {
01625 /*
01626                      char *hdr = emalloc(sizeof("Location: ")+strlen(service->sdl->source));
01627                      strcpy(hdr,"Location: ");
01628                      strcat(hdr,service->sdl->source);
01629                      sapi_add_header(hdr, sizeof("Location: ")+strlen(service->sdl->source)-1, 1);
01630                      efree(hdr);
01631 */
01632                      zval readfile, readfile_ret, *param;
01633 
01634                      INIT_ZVAL(readfile);
01635                      INIT_ZVAL(readfile_ret);
01636                      MAKE_STD_ZVAL(param);
01637 
01638                      sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
01639                      ZVAL_STRING(param, service->sdl->source, 1);
01640                      ZVAL_STRING(&readfile, "readfile", 1);
01641                      if (call_user_function(EG(function_table), NULL, &readfile, &readfile_ret, 1, &param  TSRMLS_CC) == FAILURE) {
01642                             soap_server_fault("Server", "Couldn't find WSDL", NULL, NULL, NULL TSRMLS_CC);
01643                      }
01644 
01645                      zval_ptr_dtor(&param);
01646                      zval_dtor(&readfile);
01647                      zval_dtor(&readfile_ret);
01648 
01649                      SOAP_SERVER_END_CODE();
01650                      return;
01651               } else {
01652                      soap_server_fault("Server", "WSDL generation is not supported yet", NULL, NULL, NULL TSRMLS_CC);
01653 /*
01654                      sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8"), 1);
01655                      PUTS("<?xml version=\"1.0\" ?>\n<definitions\n");
01656                      PUTS("    xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\n");
01657                      PUTS("    targetNamespace=\"");
01658                      PUTS(service->uri);
01659                      PUTS("\">\n");
01660                      PUTS("</definitions>");
01661 */
01662                      SOAP_SERVER_END_CODE();
01663                      return;
01664               }
01665        }
01666 
01667        ALLOC_INIT_ZVAL(retval);
01668 
01669        if (php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC) != SUCCESS) {
01670               php_error_docref(NULL TSRMLS_CC, E_ERROR,"ob_start failed");
01671        }
01672 
01673        if (ZEND_NUM_ARGS() == 0) {
01674               if (SG(request_info).raw_post_data) {
01675                      char *post_data = SG(request_info).raw_post_data;
01676                      int post_data_length = SG(request_info).raw_post_data_length;
01677                      zval **server_vars, **encoding;
01678 
01679                      zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
01680                      if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
01681                          Z_TYPE_PP(server_vars) == IS_ARRAY &&
01682                          zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_CONTENT_ENCODING", sizeof("HTTP_CONTENT_ENCODING"), (void **) &encoding)==SUCCESS &&
01683                          Z_TYPE_PP(encoding) == IS_STRING) {
01684                             zval func;
01685                             zval retval;
01686                             zval param;
01687                             zval *params[1];
01688 
01689                             if ((strcmp(Z_STRVAL_PP(encoding),"gzip") == 0 ||
01690                                  strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0) &&
01691                                 zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate"))) {
01692                                    ZVAL_STRING(&func, "gzinflate", 0);
01693                                    params[0] = &param;
01694                                    ZVAL_STRINGL(params[0], post_data+10, post_data_length-10, 0);
01695                                    INIT_PZVAL(params[0]);
01696                             } else if (strcmp(Z_STRVAL_PP(encoding),"deflate") == 0 &&
01697                          zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) {
01698                                    ZVAL_STRING(&func, "gzuncompress", 0);
01699                                    params[0] = &param;
01700                                    ZVAL_STRINGL(params[0], post_data, post_data_length, 0);
01701                                    INIT_PZVAL(params[0]);
01702                             } else {
01703                                    php_error_docref(NULL TSRMLS_CC, E_WARNING,"Request is compressed with unknown compression '%s'",Z_STRVAL_PP(encoding));
01704                                    return;
01705                             }
01706                             if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS &&
01707                                 Z_TYPE(retval) == IS_STRING) {
01708                                    doc_request = soap_xmlParseMemory(Z_STRVAL(retval),Z_STRLEN(retval));
01709                                    zval_dtor(&retval);
01710                             } else {
01711                                    php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't uncompress compressed request");
01712                                    return;
01713                             }
01714                      } else {
01715                             doc_request = soap_xmlParseMemory(post_data, post_data_length);
01716                      }
01717               } else {
01718                      zval_ptr_dtor(&retval);
01719                      return;
01720               }
01721        } else {
01722               doc_request = soap_xmlParseMemory(arg,arg_len);
01723        }
01724 
01725        if (doc_request == NULL) {
01726               soap_server_fault("Client", "Bad Request", NULL, NULL, NULL TSRMLS_CC);
01727        }
01728        if (xmlGetIntSubset(doc_request) != NULL) {
01729               xmlNodePtr env = get_node(doc_request->children,"Envelope");
01730               if (env && env->ns) {
01731                      if (strcmp((char*)env->ns->href, SOAP_1_1_ENV_NAMESPACE) == 0) {
01732                             SOAP_GLOBAL(soap_version) = SOAP_1_1;
01733                      } else if (strcmp((char*)env->ns->href,SOAP_1_2_ENV_NAMESPACE) == 0) {
01734                             SOAP_GLOBAL(soap_version) = SOAP_1_2;
01735                      }
01736               }
01737               xmlFreeDoc(doc_request);
01738               soap_server_fault("Server", "DTD are not supported by SOAP", NULL, NULL, NULL TSRMLS_CC);
01739        }
01740 
01741        old_sdl = SOAP_GLOBAL(sdl);
01742        SOAP_GLOBAL(sdl) = service->sdl;
01743        old_encoding = SOAP_GLOBAL(encoding);
01744        SOAP_GLOBAL(encoding) = service->encoding;
01745        old_class_map = SOAP_GLOBAL(class_map);
01746        SOAP_GLOBAL(class_map) = service->class_map;
01747        old_typemap = SOAP_GLOBAL(typemap);
01748        SOAP_GLOBAL(typemap) = service->typemap;
01749        old_features = SOAP_GLOBAL(features);
01750        SOAP_GLOBAL(features) = service->features;
01751        old_soap_version = SOAP_GLOBAL(soap_version);
01752        function = deserialize_function_call(service->sdl, doc_request, service->actor, &function_name, &num_params, &params, &soap_version, &soap_headers TSRMLS_CC);
01753        xmlFreeDoc(doc_request);
01754        
01755 #ifdef ZEND_ENGINE_2
01756        if (EG(exception)) {
01757               php_end_ob_buffer(0, 0 TSRMLS_CC);
01758               if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
01759                   instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
01760                      soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
01761               }
01762               goto fail;
01763        }
01764 #endif
01765 
01766        service->soap_headers_ptr = &soap_headers;
01767 
01768        soap_obj = NULL;
01769        if (service->type == SOAP_OBJECT) {
01770               soap_obj = service->soap_object;
01771               function_table = &((Z_OBJCE_P(soap_obj))->function_table);
01772        } else if (service->type == SOAP_CLASS) {
01773 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
01774               /* If persistent then set soap_obj from from the previous created session (if available) */
01775               if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
01776                      zval **tmp_soap;
01777 
01778                      if (PS(session_status) != php_session_active &&
01779                          PS(session_status) != php_session_disabled) {
01780                             php_session_start(TSRMLS_C);
01781                      }
01782 
01783                      /* Find the soap object and assign */
01784                      if (zend_hash_find(Z_ARRVAL_P(PS(http_session_vars)), "_bogus_session_name", sizeof("_bogus_session_name"), (void **) &tmp_soap) == SUCCESS &&
01785                          Z_TYPE_PP(tmp_soap) == IS_OBJECT &&
01786                          Z_OBJCE_PP(tmp_soap) == service->soap_class.ce) {
01787                             soap_obj = *tmp_soap;
01788                      }
01789               }
01790 #endif
01791               /* If new session or something wierd happned */
01792               if (soap_obj == NULL) {
01793                      zval *tmp_soap;
01794 
01795                      MAKE_STD_ZVAL(tmp_soap);
01796                      object_init_ex(tmp_soap, service->soap_class.ce);
01797 
01798                      /* Call constructor */
01799 #ifdef ZEND_ENGINE_2
01800                      if (zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME))) {
01801                             zval c_ret, constructor;
01802 
01803                             INIT_ZVAL(c_ret);
01804                             INIT_ZVAL(constructor);
01805 
01806                             ZVAL_STRING(&constructor, ZEND_CONSTRUCTOR_FUNC_NAME, 1);
01807                             if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE) {
01808                                    php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
01809                             }
01810                             if (EG(exception)) {
01811                                    php_end_ob_buffer(0, 0 TSRMLS_CC);
01812                                    if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
01813                                        instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
01814                                           soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
01815                                    }
01816                                    zval_dtor(&constructor);
01817                                    zval_dtor(&c_ret);
01818                                    zval_ptr_dtor(&tmp_soap);
01819                                    goto fail;
01820                             }
01821                             zval_dtor(&constructor);
01822                             zval_dtor(&c_ret);
01823                      } else {
01824 #else
01825       {
01826 #endif
01827                             int class_name_len = strlen(service->soap_class.ce->name);
01828                             char *class_name = emalloc(class_name_len+1);
01829 
01830                             memcpy(class_name, service->soap_class.ce->name,class_name_len+1);
01831                             if (zend_hash_exists(&Z_OBJCE_P(tmp_soap)->function_table, php_strtolower(class_name, class_name_len), class_name_len+1)) {
01832                                    zval c_ret, constructor;
01833 
01834                                    INIT_ZVAL(c_ret);
01835                                    INIT_ZVAL(constructor);
01836 
01837                                    ZVAL_STRING(&constructor, service->soap_class.ce->name, 1);
01838                                    if (call_user_function(NULL, &tmp_soap, &constructor, &c_ret, service->soap_class.argc, service->soap_class.argv TSRMLS_CC) == FAILURE) {
01839                                           php_error_docref(NULL TSRMLS_CC, E_ERROR, "Error calling constructor");
01840                                    }
01841 #ifdef ZEND_ENGINE_2
01842                                    if (EG(exception)) {
01843                                           php_end_ob_buffer(0, 0 TSRMLS_CC);
01844                                           if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
01845                                               instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
01846                                                  soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
01847                                           }
01848                                           zval_dtor(&constructor);
01849                                           zval_dtor(&c_ret);
01850                                           efree(class_name);
01851                                           zval_ptr_dtor(&tmp_soap);
01852                                           goto fail;
01853                                    }
01854 #endif
01855                                    zval_dtor(&constructor);
01856                                    zval_dtor(&c_ret);
01857                             }
01858                             efree(class_name);
01859                      }
01860 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
01861                      /* If session then update session hash with new object */
01862                      if (service->soap_class.persistance == SOAP_PERSISTENCE_SESSION) {
01863                             zval **tmp_soap_pp;
01864                             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) {
01865                                    soap_obj = *tmp_soap_pp;
01866                             }
01867                      } else {
01868                             soap_obj = tmp_soap;
01869                      }
01870 #else
01871                      soap_obj = tmp_soap;
01872 #endif
01873 
01874               }
01875               function_table = &((Z_OBJCE_P(soap_obj))->function_table);
01876        } else {
01877               if (service->soap_functions.functions_all == TRUE) {
01878                      function_table = EG(function_table);
01879               } else {
01880                      function_table = service->soap_functions.ft;
01881               }
01882        }
01883 
01884        doc_return = NULL;
01885 
01886        /* Process soap headers */
01887        if (soap_headers != NULL) {
01888               soapHeader *header = soap_headers;
01889               while (header != NULL) {
01890                      soapHeader *h = header;
01891 
01892                      header = header->next;
01893 #if 0
01894                      if (service->sdl && !h->function && !h->hdr) {
01895                             if (h->mustUnderstand) {
01896                                    soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC);
01897                             } else {
01898                                    continue;
01899                             }
01900                      }
01901 #endif
01902                      fn_name = estrndup(Z_STRVAL(h->function_name),Z_STRLEN(h->function_name));
01903                      if (zend_hash_exists(function_table, php_strtolower(fn_name, Z_STRLEN(h->function_name)), Z_STRLEN(h->function_name) + 1) ||
01904                          ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
01905                           zend_hash_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
01906                             if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
01907                                    call_status = call_user_function(NULL, &soap_obj, &h->function_name, &h->retval, h->num_params, h->parameters TSRMLS_CC);
01908                             } else {
01909                                    call_status = call_user_function(EG(function_table), NULL, &h->function_name, &h->retval, h->num_params, h->parameters TSRMLS_CC);
01910                             }
01911                             if (call_status != SUCCESS) {
01912                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function '%s' call failed", Z_STRVAL(h->function_name));
01913                                    return;
01914                             }
01915                             if (Z_TYPE(h->retval) == IS_OBJECT &&
01916                                 instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry TSRMLS_CC)) {
01917                                    zval *headerfault = NULL, **tmp;
01918 
01919                                    if (zend_hash_find(Z_OBJPROP(h->retval), "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS &&
01920                                        Z_TYPE_PP(tmp) != IS_NULL) {
01921                                           headerfault = *tmp;
01922                                    }
01923                                    php_end_ob_buffer(0, 0 TSRMLS_CC);
01924                                    soap_server_fault_ex(function, &h->retval, h TSRMLS_CC);
01925                                    efree(fn_name);
01926                                    if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
01927                                    goto fail;
01928 #ifdef ZEND_ENGINE_2
01929                             } else if (EG(exception)) {
01930                                    php_end_ob_buffer(0, 0 TSRMLS_CC);
01931                                    if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
01932                                        instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
01933                                           zval *headerfault = NULL, **tmp;
01934 
01935                                           if (zend_hash_find(Z_OBJPROP_P(EG(exception)), "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS &&
01936                                               Z_TYPE_PP(tmp) != IS_NULL) {
01937                                                  headerfault = *tmp;
01938                                           }
01939                                           soap_server_fault_ex(function, EG(exception), h TSRMLS_CC);
01940                                    }
01941                                    efree(fn_name);
01942                                    if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(&soap_obj);}
01943                                    goto fail;
01944 #endif
01945                             }
01946                      } else if (h->mustUnderstand) {
01947                             soap_server_fault("MustUnderstand","Header not understood", NULL, NULL, NULL TSRMLS_CC);
01948                      }
01949                      efree(fn_name);
01950               }
01951        }
01952 
01953        fn_name = estrndup(Z_STRVAL(function_name),Z_STRLEN(function_name));
01954        if (zend_hash_exists(function_table, php_strtolower(fn_name, Z_STRLEN(function_name)), Z_STRLEN(function_name) + 1) ||
01955            ((service->type == SOAP_CLASS || service->type == SOAP_OBJECT) &&
01956             zend_hash_exists(function_table, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
01957               if (service->type == SOAP_CLASS || service->type == SOAP_OBJECT) {
01958                      call_status = call_user_function(NULL, &soap_obj, &function_name, retval, num_params, params TSRMLS_CC);
01959                      if (service->type == SOAP_CLASS) {
01960 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
01961                             if (service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
01962                                    zval_ptr_dtor(&soap_obj);
01963                                    soap_obj = NULL;
01964                             }
01965 #else
01966                             zval_ptr_dtor(&soap_obj);
01967                             soap_obj = NULL;
01968 #endif
01969                      }
01970               } else {
01971                      call_status = call_user_function(EG(function_table), NULL, &function_name, retval, num_params, params TSRMLS_CC);
01972               }
01973        } else {
01974               php_error(E_ERROR, "Function '%s' doesn't exist", Z_STRVAL(function_name));
01975        }
01976        efree(fn_name);
01977 
01978 #ifdef ZEND_ENGINE_2
01979        if (EG(exception)) {
01980               php_end_ob_buffer(0, 0 TSRMLS_CC);
01981               if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
01982                   instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
01983                      soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
01984               }
01985               if (service->type == SOAP_CLASS) {
01986 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
01987                      if (soap_obj && service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
01988 #else
01989                      if (soap_obj) {
01990 #endif
01991                        zval_ptr_dtor(&soap_obj);
01992                      }
01993               }
01994               goto fail;
01995        }
01996 #endif
01997        if (call_status == SUCCESS) {
01998               char *response_name;
01999 
02000               if (Z_TYPE_P(retval) == IS_OBJECT &&
02001                   instanceof_function(Z_OBJCE_P(retval), soap_fault_class_entry TSRMLS_CC)) {
02002                      php_end_ob_buffer(0, 0 TSRMLS_CC);
02003                      soap_server_fault_ex(function, retval, NULL TSRMLS_CC);
02004                      goto fail;
02005               }
02006 
02007               if (function && function->responseName) {
02008                      response_name = estrdup(function->responseName);
02009               } else {
02010                      response_name = emalloc(Z_STRLEN(function_name) + sizeof("Response"));
02011                      memcpy(response_name,Z_STRVAL(function_name),Z_STRLEN(function_name));
02012                      memcpy(response_name+Z_STRLEN(function_name),"Response",sizeof("Response"));
02013               }
02014               doc_return = serialize_response_call(function, response_name, service->uri, retval, soap_headers, soap_version TSRMLS_CC);
02015               efree(response_name);
02016        } else {
02017               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function '%s' call failed", Z_STRVAL(function_name));
02018               return;
02019        }
02020 
02021 #ifdef ZEND_ENGINE_2
02022        if (EG(exception)) {
02023               php_end_ob_buffer(0, 0 TSRMLS_CC);
02024               if (Z_TYPE_P(EG(exception)) == IS_OBJECT &&
02025                   instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {
02026                      soap_server_fault_ex(function, EG(exception), NULL TSRMLS_CC);
02027               }
02028               if (service->type == SOAP_CLASS) {
02029 #if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
02030                      if (soap_obj && service->soap_class.persistance != SOAP_PERSISTENCE_SESSION) {
02031 #else
02032                      if (soap_obj) {
02033 #endif
02034                        zval_ptr_dtor(&soap_obj);
02035                      }
02036               }
02037               goto fail;
02038        }
02039 #endif
02040 
02041        /* Flush buffer */
02042        php_end_ob_buffer(0, 0 TSRMLS_CC);
02043 
02044        if (doc_return) {
02045               /* xmlDocDumpMemoryEnc(doc_return, &buf, &size, XML_CHAR_ENCODING_UTF8); */
02046               xmlDocDumpMemory(doc_return, &buf, &size);
02047 
02048               if (size == 0) {
02049                      php_error_docref(NULL TSRMLS_CC, E_ERROR, "Dump memory failed");
02050               }      
02051 
02052               if (soap_version == SOAP_1_2) {
02053                      sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
02054               } else {
02055                      sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
02056               }
02057 
02058               xmlFreeDoc(doc_return);
02059 
02060               if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0) &&                           
02061                   zend_hash_exists(EG(function_table), "ob_gzhandler", sizeof("ob_gzhandler"))) {
02062                      zval nm_ob_gzhandler;
02063                      zval str;
02064                      zval mode;
02065                      zval result;
02066                      zval *params[2];
02067 
02068                      INIT_ZVAL(result);
02069                      ZVAL_STRINGL(&nm_ob_gzhandler, "ob_gzhandler", sizeof("ob_gzhandler") - 1, 0);
02070                      INIT_PZVAL(&str);
02071                      ZVAL_STRINGL(&str, (char*)buf, size, 0);
02072                      params[0] = &str;
02073                      INIT_PZVAL(&mode);
02074                      ZVAL_LONG(&mode, PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END);
02075                      params[1] = &mode;
02076                      if (call_user_function(CG(function_table), NULL, &nm_ob_gzhandler, &result, 2, params TSRMLS_CC) != FAILURE &&
02077                          Z_TYPE(result) == IS_STRING &&
02078                             zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) {
02079                             xmlFree(buf);
02080                             buf = NULL;
02081                             snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", Z_STRLEN(result));
02082                             sapi_add_header(cont_len, strlen(cont_len), 1);
02083                             php_write(Z_STRVAL(result), Z_STRLEN(result) TSRMLS_CC);
02084                      }
02085                      zval_dtor(&result);
02086               }
02087               if (buf) {
02088                      snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
02089                      sapi_add_header(cont_len, strlen(cont_len), 1);
02090                      php_write(buf, size TSRMLS_CC);
02091                      xmlFree(buf);
02092               }
02093        } else {
02094               sapi_add_header("HTTP/1.1 202 Accepted", sizeof("HTTP/1.1 202 Accepted")-1, 1);
02095               sapi_add_header("Content-Length: 0", sizeof("Content-Length: 0")-1, 1);
02096        }
02097 
02098 fail:
02099        SOAP_GLOBAL(soap_version) = old_soap_version;
02100        SOAP_GLOBAL(encoding) = old_encoding;
02101        SOAP_GLOBAL(sdl) = old_sdl;
02102        SOAP_GLOBAL(class_map) = old_class_map;
02103        SOAP_GLOBAL(typemap) = old_typemap;
02104        SOAP_GLOBAL(features) = old_features;
02105 
02106        /* Free soap headers */
02107        zval_ptr_dtor(&retval);
02108        while (soap_headers != NULL) {
02109               soapHeader *h = soap_headers;
02110               int i;
02111 
02112               soap_headers = soap_headers->next;
02113               if (h->parameters) {
02114                      i = h->num_params;
02115                      while (i > 0) {
02116                             zval_ptr_dtor(&h->parameters[--i]);
02117                      }
02118                      efree(h->parameters);
02119               }
02120               zval_dtor(&h->function_name);
02121               zval_dtor(&h->retval);
02122               efree(h);
02123        }
02124        service->soap_headers_ptr = NULL;
02125 
02126        /* Free Memory */
02127        if (num_params > 0) {
02128               for (i = 0; i < num_params;i++) {
02129                      zval_ptr_dtor(&params[i]);
02130               }
02131               efree(params);
02132        }
02133        zval_dtor(&function_name);
02134 
02135        SOAP_SERVER_END_CODE();
02136 }
02137 /* }}} */
02138 
02139 
02140 /* {{{ proto SoapServer::fault ( staring code, string string [, string actor [, mixed details [, string name]]] )
02141    Issue SoapFault indicating an error */
02142 PHP_METHOD(SoapServer, fault)
02143 {
02144        char *code, *string, *actor=NULL, *name=NULL;
02145        int code_len, string_len, actor_len = 0, name_len = 0;
02146        zval* details = NULL;
02147        soapServicePtr service;
02148        xmlCharEncodingHandlerPtr old_encoding;
02149 
02150        SOAP_SERVER_BEGIN_CODE();
02151        FETCH_THIS_SERVICE(service);
02152        old_encoding = SOAP_GLOBAL(encoding);
02153        SOAP_GLOBAL(encoding) = service->encoding;
02154 
02155        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|szs",
02156            &code, &code_len, &string, &string_len, &actor, &actor_len, &details,
02157            &name, &name_len) == FAILURE) {
02158               return;
02159        }
02160 
02161        soap_server_fault(code, string, actor, details, name TSRMLS_CC);
02162 
02163        SOAP_GLOBAL(encoding) = old_encoding;
02164        SOAP_SERVER_END_CODE();
02165 }
02166 /* }}} */
02167 
02168 PHP_METHOD(SoapServer, addSoapHeader)
02169 {
02170        soapServicePtr service;
02171        zval *fault;
02172        soapHeader **p;
02173 
02174        SOAP_SERVER_BEGIN_CODE();
02175 
02176        FETCH_THIS_SERVICE(service);
02177 
02178        if (!service || !service->soap_headers_ptr) {
02179               php_error_docref(NULL TSRMLS_CC, E_WARNING, "The SoapServer::addSoapHeader function may be called only during SOAP request processing");
02180               return;
02181        }
02182 
02183        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &fault, soap_header_class_entry) == FAILURE) {
02184               return;
02185        }
02186 
02187        p = service->soap_headers_ptr;
02188        while (*p != NULL) {
02189               p = &(*p)->next;
02190        }
02191        *p = emalloc(sizeof(soapHeader));
02192        memset(*p, 0, sizeof(soapHeader));
02193        ZVAL_NULL(&(*p)->function_name);
02194        (*p)->retval = *fault;
02195        zval_copy_ctor(&(*p)->retval);
02196 
02197        SOAP_SERVER_END_CODE();
02198 }
02199 
02200 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader *hdr TSRMLS_DC)
02201 {
02202        int soap_version;
02203        xmlChar *buf;
02204        char cont_len[30];
02205        int size;
02206        xmlDocPtr doc_return;
02207        zval **agent_name;
02208        int use_http_error_status = 1;
02209 
02210        soap_version = SOAP_GLOBAL(soap_version);
02211 
02212        doc_return = serialize_response_call(function, NULL, NULL, fault, hdr, soap_version TSRMLS_CC);
02213 
02214        xmlDocDumpMemory(doc_return, &buf, &size);
02215 
02216        zend_is_auto_global("_SERVER", sizeof("_SERVER") - 1 TSRMLS_CC);
02217        if (PG(http_globals)[TRACK_VARS_SERVER] &&
02218               zend_hash_find(PG(http_globals)[TRACK_VARS_SERVER]->value.ht, "HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT"), (void **) &agent_name) == SUCCESS &&
02219               Z_TYPE_PP(agent_name) == IS_STRING) {
02220               if (strncmp(Z_STRVAL_PP(agent_name), "Shockwave Flash", sizeof("Shockwave Flash")-1) == 0) {
02221                      use_http_error_status = 0;
02222               }
02223        }
02224        /*
02225           Want to return HTTP 500 but apache wants to over write
02226           our fault code with their own handling... Figure this out later
02227        */
02228        if (use_http_error_status) {
02229               sapi_add_header("HTTP/1.1 500 Internal Service Error", sizeof("HTTP/1.1 500 Internal Service Error")-1, 1);
02230        }
02231        if (soap_version == SOAP_1_2) {
02232               sapi_add_header("Content-Type: application/soap+xml; charset=utf-8", sizeof("Content-Type: application/soap+xml; charset=utf-8")-1, 1);
02233        } else {
02234               sapi_add_header("Content-Type: text/xml; charset=utf-8", sizeof("Content-Type: text/xml; charset=utf-8")-1, 1);
02235        }
02236 
02237        if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0) &&                           
02238            zend_hash_exists(EG(function_table), "ob_gzhandler", sizeof("ob_gzhandler"))) {
02239               zval nm_ob_gzhandler;
02240               zval str;
02241               zval mode;
02242               zval result;
02243               zval *params[2];
02244 
02245               INIT_ZVAL(result);
02246               ZVAL_STRINGL(&nm_ob_gzhandler, "ob_gzhandler", sizeof("ob_gzhandler") - 1, 0);
02247               INIT_PZVAL(&str);
02248               ZVAL_STRINGL(&str, (char*)buf, size, 0);
02249               params[0] = &str;
02250               INIT_PZVAL(&mode);
02251               ZVAL_LONG(&mode, PHP_OUTPUT_HANDLER_START | PHP_OUTPUT_HANDLER_END);
02252               params[1] = &mode;
02253               if (call_user_function(CG(function_table), NULL, &nm_ob_gzhandler, &result, 2, params TSRMLS_CC) != FAILURE &&
02254                   Z_TYPE(result) == IS_STRING &&
02255                      zend_alter_ini_entry("zlib.output_compression", sizeof("zlib.output_compression"), "0", sizeof("0")-1, PHP_INI_USER, PHP_INI_STAGE_RUNTIME) == SUCCESS) {
02256                      xmlFree(buf);
02257                      buf = NULL;
02258                      snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", Z_STRLEN(result));
02259                      sapi_add_header(cont_len, strlen(cont_len), 1);
02260                      php_write(Z_STRVAL(result), Z_STRLEN(result) TSRMLS_CC);
02261               }
02262               zval_dtor(&result);
02263        }
02264        if (buf) {
02265               snprintf(cont_len, sizeof(cont_len), "Content-Length: %d", size);
02266               sapi_add_header(cont_len, strlen(cont_len), 1);
02267               php_write(buf, size TSRMLS_CC);
02268               xmlFree(buf);
02269        }
02270 
02271        xmlFreeDoc(doc_return);
02272        zend_clear_exception(TSRMLS_C);
02273 }
02274 
02275 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char* name TSRMLS_DC)
02276 {
02277        zval ret;
02278 
02279        INIT_ZVAL(ret);
02280 
02281        set_soap_fault(&ret, NULL, code, string, actor, details, name TSRMLS_CC);
02282        /* TODO: Which function */
02283        soap_server_fault_ex(NULL, &ret, NULL TSRMLS_CC);
02284        zend_bailout();
02285 }
02286 
02287 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args)
02288 {
02289        zend_bool _old_in_compilation, _old_in_execution;
02290        zend_execute_data *_old_current_execute_data;
02291        int _old_http_response_code;
02292        char *_old_http_status_line;
02293        TSRMLS_FETCH();
02294 
02295        _old_in_compilation = CG(in_compilation);
02296        _old_in_execution = EG(in_execution);
02297        _old_current_execute_data = EG(current_execute_data);
02298        _old_http_response_code = SG(sapi_headers).http_response_code;
02299        _old_http_status_line = SG(sapi_headers).http_status_line;
02300 
02301        if (!SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) {
02302               call_old_error_handler(error_num, error_filename, error_lineno, format, args);
02303               return;
02304        }
02305 
02306        if (SOAP_GLOBAL(error_object) &&
02307            Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
02308            instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_class_entry TSRMLS_CC)) {
02309 #ifdef ZEND_ENGINE_2
02310               zval **tmp;
02311               int use_exceptions = 0;
02312 
02313               if (zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
02314                    Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0) {
02315                    use_exceptions = 1;
02316               }
02317 
02318               if ((error_num == E_USER_ERROR || 
02319                    error_num == E_COMPILE_ERROR || 
02320                    error_num == E_CORE_ERROR ||
02321                    error_num == E_ERROR || 
02322                    error_num == E_PARSE) &&
02323                   use_exceptions) {
02324                      zval *fault, *exception;
02325                      char* code = SOAP_GLOBAL(error_code);
02326                      char buffer[1024];
02327                      int buffer_len;
02328                      zval outbuf, outbuflen;
02329 #ifdef va_copy
02330                      va_list argcopy;
02331 #endif
02332                      zend_object_store_bucket *old_objects;
02333                      int old = PG(display_errors);
02334 
02335                      INIT_ZVAL(outbuf);
02336                      INIT_ZVAL(outbuflen);
02337 #ifdef va_copy
02338                      va_copy(argcopy, args);
02339                      buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
02340                      va_end(argcopy);
02341 #else
02342                      buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
02343 #endif
02344                      buffer[sizeof(buffer)-1]=0;
02345                      if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
02346                             buffer_len = sizeof(buffer) - 1;
02347                      }
02348 
02349                      if (code == NULL) {
02350                             code = "Client";
02351                      }
02352                      fault = add_soap_fault(SOAP_GLOBAL(error_object), code, buffer, NULL, NULL TSRMLS_CC);
02353                      MAKE_STD_ZVAL(exception);
02354                      MAKE_COPY_ZVAL(&fault, exception);
02355                      zend_throw_exception_object(exception TSRMLS_CC);
02356 
02357                      old_objects = EG(objects_store).object_buckets;
02358                      EG(objects_store).object_buckets = NULL;
02359                      PG(display_errors) = 0;
02360                      SG(sapi_headers).http_status_line = NULL;
02361                      zend_try {
02362                             call_old_error_handler(error_num, error_filename, error_lineno, format, args);
02363                      } zend_catch {
02364                             CG(in_compilation) = _old_in_compilation;
02365                             EG(in_execution) = _old_in_execution;
02366                             EG(current_execute_data) = _old_current_execute_data;
02367                             if (SG(sapi_headers).http_status_line) {
02368                                    efree(SG(sapi_headers).http_status_line);
02369                             }
02370                             SG(sapi_headers).http_status_line = _old_http_status_line;
02371                             SG(sapi_headers).http_response_code = _old_http_response_code;
02372                      } zend_end_try();
02373                      EG(objects_store).object_buckets = old_objects;
02374                      PG(display_errors) = old;
02375                      zend_bailout();
02376               } else if (!use_exceptions ||
02377                          !SOAP_GLOBAL(error_code) ||
02378                          strcmp(SOAP_GLOBAL(error_code),"WSDL") != 0) {
02379                      /* Ignore libxml warnings during WSDL parsing */
02380                      call_old_error_handler(error_num, error_filename, error_lineno, format, args);
02381               }
02382 #else
02383               call_old_error_handler(error_num, error_filename, error_lineno, format, args);
02384 #endif
02385        } else {
02386               int old = PG(display_errors);
02387               int fault = 0;
02388               zval fault_obj;
02389 #ifdef va_copy
02390               va_list argcopy;
02391 #endif
02392 
02393               if (error_num == E_USER_ERROR || 
02394                   error_num == E_COMPILE_ERROR || 
02395                   error_num == E_CORE_ERROR ||
02396                   error_num == E_ERROR || 
02397                   error_num == E_PARSE) {
02398 
02399                      char* code = SOAP_GLOBAL(error_code);
02400                      char buffer[1024];
02401                      zval *outbuf = NULL;
02402                      zval **tmp;
02403                      soapServicePtr service;
02404 
02405                      if (code == NULL) {
02406                             code = "Server";
02407                      }
02408                      if (SOAP_GLOBAL(error_object) &&
02409                          Z_TYPE_P(SOAP_GLOBAL(error_object)) == IS_OBJECT &&
02410                          instanceof_function(Z_OBJCE_P(SOAP_GLOBAL(error_object)), soap_server_class_entry TSRMLS_CC) &&
02411                       zend_hash_find(Z_OBJPROP_P(SOAP_GLOBAL(error_object)), "service", sizeof("service"), (void **)&tmp) != FAILURE &&
02412                             (service = (soapServicePtr)zend_fetch_resource(tmp TSRMLS_CC, -1, "service", NULL, 1, le_service)) &&
02413                             !service->send_errors) {
02414                             strcpy(buffer, "Internal Error");
02415                      } else {
02416                             int buffer_len;
02417                             zval outbuflen;
02418 
02419                             INIT_ZVAL(outbuflen);
02420 
02421 #ifdef va_copy
02422                             va_copy(argcopy, args);
02423                             buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, argcopy);
02424                             va_end(argcopy);
02425 #else
02426                             buffer_len = vslprintf(buffer, sizeof(buffer)-1, format, args);
02427 #endif
02428                             buffer[sizeof(buffer)-1]=0;
02429                             if (buffer_len > sizeof(buffer) - 1 || buffer_len < 0) {
02430                                    buffer_len = sizeof(buffer) - 1;
02431                             }
02432 
02433                             /* Get output buffer and send as fault detials */
02434                             if (php_ob_get_length(&outbuflen TSRMLS_CC) != FAILURE && Z_LVAL(outbuflen) != 0) {
02435                                    ALLOC_INIT_ZVAL(outbuf);
02436                                    php_ob_get_buffer(outbuf TSRMLS_CC);
02437                             }
02438                             php_end_ob_buffer(0, 0 TSRMLS_CC);
02439 
02440                      }
02441                      INIT_ZVAL(fault_obj);
02442                      set_soap_fault(&fault_obj, NULL, code, buffer, NULL, outbuf, NULL TSRMLS_CC);
02443                      fault = 1;
02444               }
02445 
02446               PG(display_errors) = 0;
02447               SG(sapi_headers).http_status_line = NULL;
02448               zend_try {
02449                      call_old_error_handler(error_num, error_filename, error_lineno, format, args);
02450               } zend_catch {
02451                      CG(in_compilation) = _old_in_compilation;
02452                      EG(in_execution) = _old_in_execution;
02453                      EG(current_execute_data) = _old_current_execute_data;
02454                      if (SG(sapi_headers).http_status_line) {
02455                             efree(SG(sapi_headers).http_status_line);
02456                      }
02457                      SG(sapi_headers).http_status_line = _old_http_status_line;
02458                      SG(sapi_headers).http_response_code = _old_http_response_code;
02459               } zend_end_try();
02460               PG(display_errors) = old;
02461 
02462               if (fault) {
02463                      soap_server_fault_ex(NULL, &fault_obj, NULL TSRMLS_CC);
02464                      zend_bailout();
02465               }
02466        }
02467 }
02468 
02469 PHP_FUNCTION(use_soap_error_handler)
02470 {
02471        zend_bool handler = 1;
02472 
02473        ZVAL_BOOL(return_value, SOAP_GLOBAL(use_soap_error_handler));
02474        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &handler) == SUCCESS) {
02475               SOAP_GLOBAL(use_soap_error_handler) = handler;
02476        }
02477 }
02478 
02479 PHP_FUNCTION(is_soap_fault)
02480 {
02481        zval *fault;
02482 
02483        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &fault) == SUCCESS &&
02484            Z_TYPE_P(fault) == IS_OBJECT &&
02485            instanceof_function(Z_OBJCE_P(fault), soap_fault_class_entry TSRMLS_CC)) {
02486               RETURN_TRUE;
02487        }
02488        RETURN_FALSE
02489 }
02490 
02491 /* SoapClient functions */
02492 
02493 /* {{{ proto object SoapClient::SoapClient ( mixed wsdl [, array options])
02494    SoapClient constructor */
02495 PHP_METHOD(SoapClient, SoapClient)
02496 {
02497 
02498        zval *wsdl, *options = NULL;
02499        int  soap_version = SOAP_1_1;
02500        php_stream_context *context = NULL;
02501        long cache_wsdl;
02502        sdlPtr sdl = NULL;
02503        HashTable *typemap_ht = NULL;
02504 
02505        SOAP_CLIENT_BEGIN_CODE();
02506 
02507        if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "z|a", &wsdl, &options) == FAILURE) {
02508               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid parameters");
02509        }
02510 
02511        if (Z_TYPE_P(wsdl) != IS_STRING && Z_TYPE_P(wsdl) != IS_NULL) {
02512               php_error_docref(NULL TSRMLS_CC, E_ERROR, "$wsdl must be string or null");
02513        }
02514 
02515        cache_wsdl = SOAP_GLOBAL(cache);
02516 
02517        if (options != NULL) {
02518               HashTable *ht = Z_ARRVAL_P(options);
02519               zval **tmp;
02520 
02521               if (Z_TYPE_P(wsdl) == IS_NULL) {
02522                      /* Fetching non-WSDL mode options */
02523                      if (zend_hash_find(ht, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
02524                          Z_TYPE_PP(tmp) == IS_STRING) {
02525                             add_property_stringl(this_ptr, "uri", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02526                      } else {
02527                             php_error_docref(NULL TSRMLS_CC, E_ERROR, "'uri' option is required in nonWSDL mode");
02528                      }
02529 
02530                      if (zend_hash_find(ht, "style", sizeof("style"), (void**)&tmp) == SUCCESS &&
02531                                    Z_TYPE_PP(tmp) == IS_LONG &&
02532                                    (Z_LVAL_PP(tmp) == SOAP_RPC || Z_LVAL_PP(tmp) == SOAP_DOCUMENT)) {
02533                             add_property_long(this_ptr, "style", Z_LVAL_PP(tmp));
02534                      }
02535 
02536                      if (zend_hash_find(ht, "use", sizeof("use"), (void**)&tmp) == SUCCESS &&
02537                                    Z_TYPE_PP(tmp) == IS_LONG &&
02538                                    (Z_LVAL_PP(tmp) == SOAP_LITERAL || Z_LVAL_PP(tmp) == SOAP_ENCODED)) {
02539                             add_property_long(this_ptr, "use", Z_LVAL_PP(tmp));
02540                      }
02541               }
02542 
02543               if (zend_hash_find(ht, "stream_context", sizeof("stream_context"), (void**)&tmp) == SUCCESS &&
02544                             Z_TYPE_PP(tmp) == IS_RESOURCE) {
02545                      context = php_stream_context_from_zval(*tmp, 1);
02546                      zend_list_addref(context->rsrc_id);
02547               }
02548 
02549               if (zend_hash_find(ht, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
02550                   Z_TYPE_PP(tmp) == IS_STRING) {
02551                      add_property_stringl(this_ptr, "location", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02552               } else if (Z_TYPE_P(wsdl) == IS_NULL) {
02553                      php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' option is required in nonWSDL mode");
02554               }
02555 
02556               if (zend_hash_find(ht, "soap_version", sizeof("soap_version"), (void**)&tmp) == SUCCESS) {
02557                      if (Z_TYPE_PP(tmp) == IS_LONG ||
02558                          (Z_LVAL_PP(tmp) == SOAP_1_1 && Z_LVAL_PP(tmp) == SOAP_1_2)) {
02559                             soap_version = Z_LVAL_PP(tmp);
02560                      }
02561               }
02562               if (zend_hash_find(ht, "login", sizeof("login"), (void**)&tmp) == SUCCESS &&
02563                   Z_TYPE_PP(tmp) == IS_STRING) {
02564                      add_property_stringl(this_ptr, "_login", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02565                      if (zend_hash_find(ht, "password", sizeof("password"), (void**)&tmp) == SUCCESS &&
02566                          Z_TYPE_PP(tmp) == IS_STRING) {
02567                             add_property_stringl(this_ptr, "_password", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02568                      }
02569                      if (zend_hash_find(ht, "authentication", sizeof("authentication"), (void**)&tmp) == SUCCESS &&
02570                          Z_TYPE_PP(tmp) == IS_LONG &&
02571                          Z_LVAL_PP(tmp) == SOAP_AUTHENTICATION_DIGEST) {
02572                             add_property_null(this_ptr, "_digest");
02573                      }
02574               }
02575               if (zend_hash_find(ht, "proxy_host", sizeof("proxy_host"), (void**)&tmp) == SUCCESS &&
02576                   Z_TYPE_PP(tmp) == IS_STRING) {
02577                      add_property_stringl(this_ptr, "_proxy_host", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02578                      if (zend_hash_find(ht, "proxy_port", sizeof("proxy_port"), (void**)&tmp) == SUCCESS) {
02579                             convert_to_long(*tmp);
02580                             add_property_long(this_ptr, "_proxy_port", Z_LVAL_PP(tmp));
02581                      }
02582                      if (zend_hash_find(ht, "proxy_login", sizeof("proxy_login"), (void**)&tmp) == SUCCESS &&
02583                          Z_TYPE_PP(tmp) == IS_STRING) {
02584                             add_property_stringl(this_ptr, "_proxy_login", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02585                             if (zend_hash_find(ht, "proxy_password", sizeof("proxy_password"), (void**)&tmp) == SUCCESS &&
02586                                 Z_TYPE_PP(tmp) == IS_STRING) {
02587                                    add_property_stringl(this_ptr, "_proxy_password", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02588                             }
02589                      }
02590               }
02591               if (zend_hash_find(ht, "local_cert", sizeof("local_cert"), (void**)&tmp) == SUCCESS &&
02592                   Z_TYPE_PP(tmp) == IS_STRING) {
02593                 if (!context) {
02594                      context = php_stream_context_alloc();
02595                 }
02596                      php_stream_context_set_option(context, "ssl", "local_cert", *tmp);
02597                      if (zend_hash_find(ht, "passphrase", sizeof("passphrase"), (void**)&tmp) == SUCCESS &&
02598                          Z_TYPE_PP(tmp) == IS_STRING) {
02599                             php_stream_context_set_option(context, "ssl", "passphrase", *tmp);
02600                      }
02601               }
02602               if (zend_hash_find(ht, "trace", sizeof("trace"), (void**)&tmp) == SUCCESS &&
02603                   (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
02604                             Z_LVAL_PP(tmp) == 1) {
02605                      add_property_long(this_ptr, "trace", 1);
02606               }
02607 #ifdef ZEND_ENGINE_2
02608               if (zend_hash_find(ht, "exceptions", sizeof("exceptions"), (void**)&tmp) == SUCCESS &&
02609                   (Z_TYPE_PP(tmp) == IS_BOOL || Z_TYPE_PP(tmp) == IS_LONG) &&
02610                             Z_LVAL_PP(tmp) == 0) {
02611                      add_property_bool(this_ptr, "_exceptions", 0);
02612               }
02613 #endif
02614               if (zend_hash_find(ht, "compression", sizeof("compression"), (void**)&tmp) == SUCCESS &&
02615                   Z_TYPE_PP(tmp) == IS_LONG &&
02616              zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate")) &&
02617              zend_hash_exists(EG(function_table), "gzdeflate", sizeof("gzdeflate")) &&
02618              zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress")) &&
02619              zend_hash_exists(EG(function_table), "gzcompress", sizeof("gzcompress")) &&
02620              zend_hash_exists(EG(function_table), "gzencode", sizeof("gzencode"))) {
02621                      add_property_long(this_ptr, "compression", Z_LVAL_PP(tmp));
02622               }
02623               if (zend_hash_find(ht, "encoding", sizeof("encoding"), (void**)&tmp) == SUCCESS &&
02624                   Z_TYPE_PP(tmp) == IS_STRING) {
02625                      xmlCharEncodingHandlerPtr encoding;
02626               
02627                      encoding = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
02628                      if (encoding == NULL) {
02629                             php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid 'encoding' option - '%s'", Z_STRVAL_PP(tmp));
02630                      } else {
02631                             xmlCharEncCloseFunc(encoding);
02632                             add_property_stringl(this_ptr, "_encoding", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);               
02633                      }
02634               }
02635               if (zend_hash_find(ht, "classmap", sizeof("classmap"), (void**)&tmp) == SUCCESS &&
02636                      Z_TYPE_PP(tmp) == IS_ARRAY) {
02637                      zval *class_map;
02638 
02639                      MAKE_STD_ZVAL(class_map);
02640                      MAKE_COPY_ZVAL(tmp, class_map);
02641 #ifdef ZEND_ENGINE_2
02642                      Z_DELREF_P(class_map);
02643 #endif
02644                      add_property_zval(this_ptr, "_classmap", class_map);
02645               }
02646 
02647               if (zend_hash_find(ht, "typemap", sizeof("typemap"), (void**)&tmp) == SUCCESS &&
02648                      Z_TYPE_PP(tmp) == IS_ARRAY &&
02649                      zend_hash_num_elements(Z_ARRVAL_PP(tmp)) > 0) {
02650                      typemap_ht = Z_ARRVAL_PP(tmp);
02651               }
02652 
02653               if (zend_hash_find(ht, "features", sizeof("features"), (void**)&tmp) == SUCCESS &&
02654                      Z_TYPE_PP(tmp) == IS_LONG) {
02655                      add_property_long(this_ptr, "_features", Z_LVAL_PP(tmp));
02656            }
02657 
02658               if (zend_hash_find(ht, "connection_timeout", sizeof("connection_timeout"), (void**)&tmp) == SUCCESS) {
02659                      convert_to_long(*tmp);
02660                      if (Z_LVAL_PP(tmp) > 0) {
02661                             add_property_long(this_ptr, "_connection_timeout", Z_LVAL_PP(tmp));
02662                      }
02663               }
02664 
02665               if (context) {
02666                      add_property_resource(this_ptr, "_stream_context", context->rsrc_id);
02667               }
02668        
02669               if (zend_hash_find(ht, "cache_wsdl", sizeof("cache_wsdl"), (void**)&tmp) == SUCCESS &&
02670                   Z_TYPE_PP(tmp) == IS_LONG) {
02671                      cache_wsdl = Z_LVAL_PP(tmp);
02672               }
02673 
02674               if (zend_hash_find(ht, "user_agent", sizeof("user_agent"), (void**)&tmp) == SUCCESS &&
02675                   Z_TYPE_PP(tmp) == IS_STRING) {
02676                      add_property_stringl(this_ptr, "_user_agent", Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
02677               }
02678        } else if (Z_TYPE_P(wsdl) == IS_NULL) {
02679               php_error_docref(NULL TSRMLS_CC, E_ERROR, "'location' and 'uri' options are required in nonWSDL mode");
02680        }
02681 
02682        add_property_long(this_ptr, "_soap_version", soap_version);
02683 
02684        if (Z_TYPE_P(wsdl) != IS_NULL) {
02685               int    old_soap_version, ret;
02686 
02687               old_soap_version = SOAP_GLOBAL(soap_version);
02688               SOAP_GLOBAL(soap_version) = soap_version;
02689 
02690               sdl = get_sdl(this_ptr, Z_STRVAL_P(wsdl), cache_wsdl TSRMLS_CC);
02691               ret = zend_list_insert(sdl, le_sdl);
02692 
02693               add_property_resource(this_ptr, "sdl", ret);
02694 
02695               SOAP_GLOBAL(soap_version) = old_soap_version;
02696        }
02697 
02698        if (typemap_ht) {
02699               HashTable *typemap = soap_create_typemap(sdl, typemap_ht TSRMLS_CC);
02700               if (typemap) {
02701                      int ret;
02702 
02703                      ret = zend_list_insert(typemap, le_typemap);
02704                      add_property_resource(this_ptr, "typemap", ret);
02705               }
02706        }
02707        SOAP_CLIENT_END_CODE();
02708 }
02709 /* }}} */
02710 
02711 static int do_request(zval *this_ptr, xmlDoc *request, char *location, char *action, int version, int one_way, zval *response TSRMLS_DC)
02712 {
02713        int    ret = TRUE;
02714        char  *buf;
02715        int    buf_size;
02716        zval   func, param0, param1, param2, param3, param4;
02717        zval  *params[5];
02718        zval **trace;
02719        zval **fault;
02720 
02721        INIT_ZVAL(*response);
02722 
02723        xmlDocDumpMemory(request, (xmlChar**)&buf, &buf_size);
02724        if (!buf) {
02725               add_soap_fault(this_ptr, "HTTP", "Error build soap request", NULL, NULL TSRMLS_CC);
02726               return FALSE;
02727        }
02728 
02729        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
02730            Z_LVAL_PP(trace) > 0) {
02731               add_property_stringl(this_ptr, "__last_request", buf, buf_size, 1);
02732        }
02733 
02734        INIT_ZVAL(func);
02735        ZVAL_STRINGL(&func,"__doRequest",sizeof("__doRequest")-1,0);
02736        INIT_ZVAL(param0);
02737        params[0] = &param0;
02738        ZVAL_STRINGL(params[0], buf, buf_size, 0);
02739        INIT_ZVAL(param1);
02740        params[1] = &param1;
02741        if (location == NULL) {
02742               ZVAL_NULL(params[1]);
02743        } else {
02744               ZVAL_STRING(params[1], location, 0);
02745        }
02746        INIT_ZVAL(param2);
02747        params[2] = &param2;
02748        if (action == NULL) {
02749               ZVAL_NULL(params[2]);
02750        } else {
02751               ZVAL_STRING(params[2], action, 0);
02752        }
02753        INIT_ZVAL(param3);
02754        params[3] = &param3;
02755        ZVAL_LONG(params[3], version);
02756 
02757        INIT_ZVAL(param4);
02758        params[4] = &param4;
02759        ZVAL_LONG(params[4], one_way);
02760 
02761        if (call_user_function(NULL, &this_ptr, &func, response, 5, params TSRMLS_CC) != SUCCESS) {
02762               add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() failed", NULL, NULL TSRMLS_CC);
02763               ret = FALSE;
02764        } else if (Z_TYPE_P(response) != IS_STRING) {
02765               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == FAILURE) {
02766                      add_soap_fault(this_ptr, "Client", "SoapClient::__doRequest() returned non string value", NULL, NULL TSRMLS_CC);
02767               }
02768               ret = FALSE;
02769        } else if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS &&
02770            Z_LVAL_PP(trace) > 0) {
02771               add_property_stringl(this_ptr, "__last_response", Z_STRVAL_P(response), Z_STRLEN_P(response), 1);
02772        }
02773        xmlFree(buf);
02774        if (ret && zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
02775          return FALSE;
02776        }        
02777   return ret;
02778 }
02779 
02780 static void do_soap_call(zval* this_ptr,
02781                          char* function,
02782                          int function_len,
02783                          int arg_count,
02784                          zval** real_args,
02785                          zval* return_value,
02786                          char* location,
02787                          char* soap_action,
02788                          char* call_uri,
02789                          HashTable* soap_headers,
02790                          zval* output_headers
02791                          TSRMLS_DC)
02792 {
02793        zval **tmp;
02794        zval **trace;
02795        sdlPtr sdl = NULL;
02796        sdlPtr old_sdl = NULL;
02797        sdlFunctionPtr fn;
02798        xmlDocPtr request = NULL;
02799        int ret = FALSE;
02800        int soap_version;
02801        zval response;
02802        xmlCharEncodingHandlerPtr old_encoding;
02803        HashTable *old_class_map;
02804        int old_features;
02805        HashTable *old_typemap, *typemap = NULL;
02806 
02807        SOAP_CLIENT_BEGIN_CODE();
02808 
02809        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "trace", sizeof("trace"), (void **) &trace) == SUCCESS
02810               && Z_LVAL_PP(trace) > 0) {
02811               zend_hash_del(Z_OBJPROP_P(this_ptr), "__last_request", sizeof("__last_request"));
02812               zend_hash_del(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"));
02813        }
02814        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_soap_version", sizeof("_soap_version"), (void **) &tmp) == SUCCESS
02815               && Z_LVAL_PP(tmp) == SOAP_1_2) {
02816               soap_version = SOAP_1_2;
02817        } else {
02818               soap_version = SOAP_1_1;
02819        }
02820 
02821        if (location == NULL) {
02822               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS &&
02823                   Z_TYPE_PP(tmp) == IS_STRING) {
02824                 location = Z_STRVAL_PP(tmp);
02825               }
02826        }
02827 
02828        if (FIND_SDL_PROPERTY(this_ptr,tmp) != FAILURE) {
02829               FETCH_SDL_RES(sdl,tmp);
02830        }
02831        if (FIND_TYPEMAP_PROPERTY(this_ptr,tmp) != FAILURE) {
02832               FETCH_TYPEMAP_RES(typemap,tmp);
02833        }
02834 
02835        clear_soap_fault(this_ptr TSRMLS_CC);
02836 
02837        SOAP_GLOBAL(soap_version) = soap_version;
02838        old_sdl = SOAP_GLOBAL(sdl);
02839        SOAP_GLOBAL(sdl) = sdl;
02840        old_encoding = SOAP_GLOBAL(encoding);
02841        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_encoding", sizeof("_encoding"), (void **) &tmp) == SUCCESS &&
02842            Z_TYPE_PP(tmp) == IS_STRING) {
02843               SOAP_GLOBAL(encoding) = xmlFindCharEncodingHandler(Z_STRVAL_PP(tmp));
02844        } else {
02845               SOAP_GLOBAL(encoding) = NULL;
02846        }
02847        old_class_map = SOAP_GLOBAL(class_map);
02848        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_classmap", sizeof("_classmap"), (void **) &tmp) == SUCCESS &&
02849            Z_TYPE_PP(tmp) == IS_ARRAY) {
02850               SOAP_GLOBAL(class_map) = (*tmp)->value.ht;
02851        } else {
02852               SOAP_GLOBAL(class_map) = NULL;
02853        }
02854        old_typemap = SOAP_GLOBAL(typemap);
02855        SOAP_GLOBAL(typemap) = typemap;
02856        old_features = SOAP_GLOBAL(features);
02857        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_features", sizeof("_features"), (void **) &tmp) == SUCCESS &&
02858            Z_TYPE_PP(tmp) == IS_LONG) {
02859               SOAP_GLOBAL(features) = Z_LVAL_PP(tmp);
02860        } else {
02861               SOAP_GLOBAL(features) = 0;
02862        }
02863 
02864        if (sdl != NULL) {
02865               fn = get_function(sdl, function);
02866               if (fn != NULL) {
02867                      sdlBindingPtr binding = fn->binding;
02868                      int one_way = 0;
02869 
02870                      if (fn->responseName == NULL &&
02871                          fn->responseParameters == NULL &&
02872                          soap_headers == NULL) {
02873                             one_way = 1;
02874                      }
02875 
02876                      if (location == NULL) {
02877                             location = binding->location;
02878                      }
02879                      if (binding->bindingType == BINDING_SOAP) {
02880                             sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)fn->bindingAttributes;
02881                             request = serialize_function_call(this_ptr, fn, NULL, fnb->input.ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
02882                             ret = do_request(this_ptr, request, location, fnb->soapAction, soap_version, one_way, &response TSRMLS_CC);
02883                      }      else {
02884                             request = serialize_function_call(this_ptr, fn, NULL, sdl->target_ns, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
02885                             ret = do_request(this_ptr, request, location, NULL, soap_version, one_way, &response TSRMLS_CC);
02886                      }
02887 
02888                      xmlFreeDoc(request);
02889 
02890                      if (ret && Z_TYPE(response) == IS_STRING) {
02891                             encode_reset_ns();
02892                             ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), fn, NULL, return_value, output_headers TSRMLS_CC);
02893                             encode_finish();
02894                      }
02895 
02896                      zval_dtor(&response);
02897 
02898               } else {
02899                      smart_str error = {0};
02900                      smart_str_appends(&error,"Function (\"");
02901                      smart_str_appends(&error,function);
02902                      smart_str_appends(&error,"\") is not a valid method for this service");
02903                      smart_str_0(&error);
02904                      add_soap_fault(this_ptr, "Client", error.c, NULL, NULL TSRMLS_CC);
02905                      smart_str_free(&error);
02906               }
02907        } else {
02908               zval **uri;
02909               smart_str action = {0};
02910 
02911               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "uri", sizeof("uri"), (void *)&uri) == FAILURE) {
02912                      add_soap_fault(this_ptr, "Client", "Error finding \"uri\" property", NULL, NULL TSRMLS_CC);
02913               } else if (location == NULL) {
02914                      add_soap_fault(this_ptr, "Client", "Error could not find \"location\" property", NULL, NULL TSRMLS_CC);
02915               } else {
02916                      if (call_uri == NULL) {
02917                             call_uri = Z_STRVAL_PP(uri);
02918                      }
02919                      request = serialize_function_call(this_ptr, NULL, function, call_uri, real_args, arg_count, soap_version, soap_headers TSRMLS_CC);
02920 
02921                      if (soap_action == NULL) {
02922                             smart_str_appends(&action, call_uri);
02923                             smart_str_appendc(&action, '#');
02924                             smart_str_appends(&action, function);
02925                      } else {
02926                             smart_str_appends(&action, soap_action);
02927                      }
02928                      smart_str_0(&action);
02929 
02930                      ret = do_request(this_ptr, request, location, action.c, soap_version, 0, &response TSRMLS_CC);
02931 
02932                      smart_str_free(&action);
02933                      xmlFreeDoc(request);
02934 
02935                      if (ret && Z_TYPE(response) == IS_STRING) {
02936                             encode_reset_ns();
02937                             ret = parse_packet_soap(this_ptr, Z_STRVAL(response), Z_STRLEN(response), NULL, function, return_value, output_headers TSRMLS_CC);
02938                             encode_finish();
02939                      }
02940 
02941                      zval_dtor(&response);
02942               }
02943        }
02944 
02945        if (!ret) {
02946               zval** fault;
02947               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
02948                      *return_value = **fault;
02949                      zval_copy_ctor(return_value);
02950               } else {
02951                      *return_value = *add_soap_fault(this_ptr, "Client", "Unknown Error", NULL, NULL TSRMLS_CC);
02952                      zval_copy_ctor(return_value);
02953               }
02954        } else {
02955               zval** fault;
02956               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__soap_fault", sizeof("__soap_fault"), (void **) &fault) == SUCCESS) {
02957                      *return_value = **fault;
02958                      zval_copy_ctor(return_value);
02959               }
02960        }
02961 #ifdef ZEND_ENGINE_2
02962        if (!EG(exception) &&
02963            Z_TYPE_P(return_value) == IS_OBJECT &&
02964            instanceof_function(Z_OBJCE_P(return_value), soap_fault_class_entry TSRMLS_CC) &&
02965            (zend_hash_find(Z_OBJPROP_P(this_ptr), "_exceptions", sizeof("_exceptions"), (void **) &tmp) != SUCCESS ||
02966                  Z_TYPE_PP(tmp) != IS_BOOL || Z_LVAL_PP(tmp) != 0)) {
02967               zval *exception;
02968 
02969               MAKE_STD_ZVAL(exception);
02970               MAKE_COPY_ZVAL(&return_value, exception);
02971               zend_throw_exception_object(exception TSRMLS_CC);
02972        }
02973 #endif
02974        if (SOAP_GLOBAL(encoding) != NULL) {
02975               xmlCharEncCloseFunc(SOAP_GLOBAL(encoding));
02976        }
02977        SOAP_GLOBAL(features) = old_features;
02978        SOAP_GLOBAL(typemap) = old_typemap;
02979        SOAP_GLOBAL(class_map) = old_class_map;
02980        SOAP_GLOBAL(encoding) = old_encoding;
02981        SOAP_GLOBAL(sdl) = old_sdl;
02982        SOAP_CLIENT_END_CODE();
02983 }
02984 
02985 static void verify_soap_headers_array(HashTable *ht TSRMLS_DC)
02986 {
02987        zval **tmp;
02988 
02989        zend_hash_internal_pointer_reset(ht);
02990        while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
02991               if (Z_TYPE_PP(tmp) != IS_OBJECT ||
02992                   !instanceof_function(Z_OBJCE_PP(tmp), soap_header_class_entry TSRMLS_CC)) {
02993                      php_error_docref(NULL TSRMLS_CC, E_ERROR, "Invalid SOAP header");
02994               }
02995               zend_hash_move_forward(ht);
02996        }
02997 }
02998 
02999 
03000 /* {{{ proto mixed SoapClient::__call ( string function_name, array arguments [, array options [, array input_headers [, array output_headers]]])
03001    Calls a SOAP function */
03002 PHP_METHOD(SoapClient, __call)
03003 {
03004        char *function, *location=NULL, *soap_action = NULL, *uri = NULL;
03005        int function_len, i = 0;
03006        HashTable* soap_headers = NULL;
03007        zval *options = NULL;
03008        zval *headers = NULL;
03009        zval *output_headers = NULL;
03010        zval *args;
03011        zval **real_args = NULL;
03012        zval **param;
03013        int arg_count;
03014        zval **tmp;
03015        zend_bool free_soap_headers = 0;
03016 
03017        HashPosition pos;
03018 
03019        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a!zz",
03020               &function, &function_len, &args, &options, &headers, &output_headers) == FAILURE) {
03021               return;
03022        }
03023 
03024        if (options) {
03025               HashTable *hto = Z_ARRVAL_P(options);
03026               if (zend_hash_find(hto, "location", sizeof("location"), (void**)&tmp) == SUCCESS &&
03027                      Z_TYPE_PP(tmp) == IS_STRING) {
03028                      location = Z_STRVAL_PP(tmp);
03029               }
03030 
03031               if (zend_hash_find(hto, "soapaction", sizeof("soapaction"), (void**)&tmp) == SUCCESS &&
03032                      Z_TYPE_PP(tmp) == IS_STRING) {
03033                      soap_action = Z_STRVAL_PP(tmp);
03034               }
03035 
03036               if (zend_hash_find(hto, "uri", sizeof("uri"), (void**)&tmp) == SUCCESS &&
03037                      Z_TYPE_PP(tmp) == IS_STRING) {
03038                      uri = Z_STRVAL_PP(tmp);
03039               }
03040        }
03041 
03042        if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
03043        } else if (Z_TYPE_P(headers) == IS_ARRAY) {
03044               soap_headers = Z_ARRVAL_P(headers);
03045               verify_soap_headers_array(soap_headers TSRMLS_CC);
03046               free_soap_headers = 0;
03047        } else if (Z_TYPE_P(headers) == IS_OBJECT &&
03048                   instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
03049            soap_headers = emalloc(sizeof(HashTable));
03050               zend_hash_init(soap_headers, 0, NULL, ZVAL_PTR_DTOR, 0);
03051               zend_hash_next_index_insert(soap_headers, &headers, sizeof(zval*), NULL);
03052               Z_ADDREF_P(headers);
03053               free_soap_headers = 1;
03054        } else{
03055               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid SOAP header");
03056               return;
03057        }
03058 
03059        /* Add default headers */
03060        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &tmp)==SUCCESS) {
03061               HashTable *default_headers = Z_ARRVAL_P(*tmp);
03062               if (soap_headers) {
03063                      if (!free_soap_headers) {
03064                             HashTable *t =  emalloc(sizeof(HashTable));
03065                             zend_hash_init(t, 0, NULL, ZVAL_PTR_DTOR, 0);
03066                             zend_hash_copy(t, soap_headers, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
03067                             soap_headers = t;
03068                             free_soap_headers = 1;
03069                      }
03070                      zend_hash_internal_pointer_reset(default_headers);
03071                      while (zend_hash_get_current_data(default_headers, (void**)&tmp) == SUCCESS) {
03072                             Z_ADDREF_PP(tmp);
03073                             zend_hash_next_index_insert(soap_headers, tmp, sizeof(zval *), NULL);
03074                             zend_hash_move_forward(default_headers);
03075                      }
03076               } else {
03077                      soap_headers = Z_ARRVAL_P(*tmp);
03078                      free_soap_headers = 0;
03079               }
03080        }
03081        
03082        arg_count = zend_hash_num_elements(Z_ARRVAL_P(args));
03083 
03084        if (arg_count > 0) {
03085               real_args = safe_emalloc(sizeof(zval *), arg_count, 0);
03086               for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(args), &pos);
03087                      zend_hash_get_current_data_ex(Z_ARRVAL_P(args), (void **) &param, &pos) == SUCCESS;
03088                      zend_hash_move_forward_ex(Z_ARRVAL_P(args), &pos)) {
03089                             /*zval_add_ref(param);*/
03090                             real_args[i++] = *param;
03091               }
03092        }
03093        if (output_headers) {
03094               array_init(output_headers);
03095        }
03096        do_soap_call(this_ptr, function, function_len, arg_count, real_args, return_value, location, soap_action, uri, soap_headers, output_headers TSRMLS_CC);
03097        if (arg_count > 0) {
03098               efree(real_args);
03099        }
03100 
03101        if (soap_headers && free_soap_headers) {
03102               zend_hash_destroy(soap_headers);
03103               efree(soap_headers);
03104        }
03105 }
03106 /* }}} */
03107 
03108 
03109 /* {{{ proto array SoapClient::__getFunctions ( void )
03110    Returns list of SOAP functions */
03111 PHP_METHOD(SoapClient, __getFunctions)
03112 {
03113        sdlPtr sdl;
03114        HashPosition pos;
03115 
03116        FETCH_THIS_SDL(sdl);
03117 
03118        if (zend_parse_parameters_none() == FAILURE) {
03119               return;
03120        }
03121 
03122        if (sdl) {
03123               smart_str buf = {0};
03124               sdlFunctionPtr *function;
03125 
03126               array_init(return_value);
03127               zend_hash_internal_pointer_reset_ex(&sdl->functions, &pos);
03128               while (zend_hash_get_current_data_ex(&sdl->functions, (void **)&function, &pos) != FAILURE) {
03129                      function_to_string((*function), &buf);
03130                      add_next_index_stringl(return_value, buf.c, buf.len, 1);
03131                      smart_str_free(&buf);
03132                      zend_hash_move_forward_ex(&sdl->functions, &pos);
03133               }
03134        }
03135 }
03136 /* }}} */
03137 
03138 
03139 /* {{{ proto array SoapClient::__getTypes ( void )
03140    Returns list of SOAP types */
03141 PHP_METHOD(SoapClient, __getTypes)
03142 {
03143        sdlPtr sdl;
03144        HashPosition pos;
03145 
03146        FETCH_THIS_SDL(sdl);
03147        
03148        if (zend_parse_parameters_none() == FAILURE) {
03149               return;
03150        }
03151 
03152        if (sdl) {
03153               sdlTypePtr *type;
03154               smart_str buf = {0};
03155 
03156               array_init(return_value);
03157               if (sdl->types) {
03158                      zend_hash_internal_pointer_reset_ex(sdl->types, &pos);
03159                      while (zend_hash_get_current_data_ex(sdl->types, (void **)&type, &pos) != FAILURE) {
03160                             type_to_string((*type), &buf, 0);
03161                             add_next_index_stringl(return_value, buf.c, buf.len, 1);
03162                             smart_str_free(&buf);
03163                             zend_hash_move_forward_ex(sdl->types, &pos);
03164                      }
03165               }
03166        }
03167 }
03168 /* }}} */
03169 
03170 
03171 /* {{{ proto string SoapClient::__getLastRequest ( void )
03172    Returns last SOAP request */
03173 PHP_METHOD(SoapClient, __getLastRequest)
03174 {
03175        zval **tmp;
03176        
03177        if (zend_parse_parameters_none() == FAILURE) {
03178               return;
03179        }
03180 
03181        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request", sizeof("__last_request"), (void **)&tmp) == SUCCESS) {
03182               RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
03183        }
03184        RETURN_NULL();
03185 }
03186 /* }}} */
03187 
03188 
03189 /* {{{ proto object SoapClient::__getLastResponse ( void )
03190    Returns last SOAP response */
03191 PHP_METHOD(SoapClient, __getLastResponse)
03192 {
03193        zval **tmp;
03194 
03195        if (zend_parse_parameters_none() == FAILURE) {
03196               return;
03197        }
03198        
03199        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response", sizeof("__last_response"), (void **)&tmp) == SUCCESS) {
03200               RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
03201        }
03202        RETURN_NULL();
03203 }
03204 /* }}} */
03205 
03206 
03207 /* {{{ proto string SoapClient::__getLastRequestHeaders(void)
03208    Returns last SOAP request headers */
03209 PHP_METHOD(SoapClient, __getLastRequestHeaders)
03210 {
03211        zval **tmp;
03212        
03213        if (zend_parse_parameters_none() == FAILURE) {
03214               return;
03215        }
03216        
03217        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_request_headers", sizeof("__last_request_headers"), (void **)&tmp) == SUCCESS) {
03218               RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
03219        }
03220        RETURN_NULL();
03221 }
03222 /* }}} */
03223 
03224 
03225 /* {{{ proto string SoapClient::__getLastResponseHeaders(void)
03226    Returns last SOAP response headers */
03227 PHP_METHOD(SoapClient, __getLastResponseHeaders)
03228 {
03229        zval **tmp;
03230        
03231        if (zend_parse_parameters_none() == FAILURE) {
03232               return;
03233        }
03234 
03235        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__last_response_headers", sizeof("__last_response_headers"), (void **)&tmp) == SUCCESS) {
03236               RETURN_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
03237        }
03238        RETURN_NULL();
03239 }
03240 /* }}} */
03241 
03242 
03243 /* {{{ proto string SoapClient::__doRequest()
03244    SoapClient::__doRequest() */
03245 PHP_METHOD(SoapClient, __doRequest)
03246 {
03247   char *buf, *location, *action;
03248   int   buf_size, location_size, action_size;
03249   long  version;
03250   long  one_way = 0;
03251 
03252        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl|l",
03253            &buf, &buf_size,
03254            &location, &location_size,
03255            &action, &action_size,
03256            &version, &one_way) == FAILURE) {
03257               return;
03258        }
03259        if (SOAP_GLOBAL(features) & SOAP_WAIT_ONE_WAY_CALLS) {
03260               one_way = 0;
03261        }
03262        if (one_way) {
03263               if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version, NULL, NULL TSRMLS_CC)) {
03264                      RETURN_EMPTY_STRING();
03265               }
03266        } else if (make_http_soap_request(this_ptr, buf, buf_size, location, action, version,
03267            &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value) TSRMLS_CC)) {
03268               return_value->type = IS_STRING;
03269               return;
03270        }
03271        RETURN_NULL();
03272 }
03273 /* }}} */
03274 
03275 /* {{{ proto void SoapClient::__setCookie(string name [, strung value])
03276    Sets cookie thet will sent with SOAP request.
03277    The call to this function will effect all folowing calls of SOAP methods.
03278    If value is not specified cookie is removed. */
03279 PHP_METHOD(SoapClient, __setCookie)
03280 {
03281        char *name;
03282        char *val = NULL;
03283        int  name_len, val_len = 0;
03284        zval **cookies;
03285 
03286        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &name, &name_len, &val, &val_len) == FAILURE) {
03287               return;
03288        }
03289 
03290        if (val == NULL) {
03291               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == SUCCESS) {
03292                      zend_hash_del(Z_ARRVAL_PP(cookies), name, name_len+1);
03293               }
03294        } else {
03295               zval *zcookie;
03296 
03297               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), (void **)&cookies) == FAILURE) {
03298                      zval *tmp_cookies;
03299 
03300                      MAKE_STD_ZVAL(tmp_cookies);
03301                      array_init(tmp_cookies);
03302                      zend_hash_update(Z_OBJPROP_P(this_ptr), "_cookies", sizeof("_cookies"), &tmp_cookies, sizeof(zval *), (void **)&cookies);
03303               }
03304 
03305               ALLOC_INIT_ZVAL(zcookie);
03306               array_init(zcookie);
03307               add_index_stringl(zcookie, 0, val, val_len, 1);
03308               add_assoc_zval_ex(*cookies, name, name_len+1, zcookie);
03309        }
03310 }
03311 /* }}} */
03312 
03313 /* {{{ proto void SoapClient::__setSoapHeaders(array SoapHeaders)
03314    Sets SOAP headers for subsequent calls (replaces any previous
03315    values).
03316    If no value is specified, all of the headers are removed. */
03317 PHP_METHOD(SoapClient, __setSoapHeaders)
03318 {
03319        zval *headers = NULL;
03320 
03321        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &headers) == FAILURE) {
03322               return;
03323        }
03324 
03325        if (headers == NULL || Z_TYPE_P(headers) == IS_NULL) {
03326               zend_hash_del(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"));
03327        } else if (Z_TYPE_P(headers) == IS_ARRAY) {
03328               zval *default_headers;
03329 
03330               verify_soap_headers_array(Z_ARRVAL_P(headers) TSRMLS_CC);
03331               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_headers"), (void **) &default_headers)==FAILURE) {
03332                      add_property_zval(this_ptr, "__default_headers", headers);
03333               }
03334        } else if (Z_TYPE_P(headers) == IS_OBJECT &&
03335                   instanceof_function(Z_OBJCE_P(headers), soap_header_class_entry TSRMLS_CC)) {
03336               zval *default_headers;
03337               ALLOC_INIT_ZVAL(default_headers);
03338               array_init(default_headers);
03339               Z_ADDREF_P(headers);
03340               add_next_index_zval(default_headers, headers);
03341               Z_DELREF_P(default_headers);
03342               add_property_zval(this_ptr, "__default_headers", default_headers);
03343        } else{
03344               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid SOAP header");
03345        }
03346        RETURN_TRUE;
03347 }
03348 /* }}} */
03349 
03350 
03351 
03352 /* {{{ proto string SoapClient::__setLocation([string new_location])
03353    Sets the location option (the endpoint URL that will be touched by the 
03354    following SOAP requests).
03355    If new_location is not specified or null then SoapClient will use endpoint
03356    from WSDL file. 
03357    The function returns old value of location options. */
03358 PHP_METHOD(SoapClient, __setLocation)
03359 {
03360        char *location = NULL;
03361        int  location_len = 0;
03362        zval **tmp;
03363 
03364        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &location, &location_len) == FAILURE) {
03365               return;
03366        }
03367 
03368        if (zend_hash_find(Z_OBJPROP_P(this_ptr), "location", sizeof("location"),(void **) &tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
03369               RETVAL_STRINGL(Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), 1);
03370        } else {
03371          RETVAL_NULL();
03372        }
03373 
03374        if (location && location_len) {
03375               add_property_stringl(this_ptr, "location", location, location_len, 1);
03376        } else {
03377               zend_hash_del(Z_OBJPROP_P(this_ptr), "location", sizeof("location"));
03378        }
03379 }
03380 /* }}} */
03381 
03382 #ifndef ZEND_ENGINE_2
03383 static void soap_call_function_handler(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference)
03384 {
03385        zval *object = property_reference->object;
03386        zend_overloaded_element *function_name = (zend_overloaded_element *)property_reference->elements_list->tail->data;
03387        char *function = Z_STRVAL(function_name->element);
03388        zend_function *builtin_function;
03389 
03390        /*
03391           Find if the function being called is already defined...
03392          ( IMHO: zend should handle this functionality )
03393        */
03394        if (zend_hash_find(&Z_OBJCE_P(this_ptr)->function_table, function, Z_STRLEN(function_name->element) + 1, (void **) &builtin_function) == SUCCESS) {
03395               builtin_function->internal_function.handler(INTERNAL_FUNCTION_PARAM_PASSTHRU);
03396        } else {
03397               int arg_count = ZEND_NUM_ARGS();
03398               zval **arguments = (zval **) safe_emalloc(sizeof(zval *), arg_count, 0);
03399               zval **soap_headers_p
03400               HashTable *soap_headers;
03401 
03402               zend_get_parameters_array(ht, arg_count, arguments);
03403 
03404               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "__default_headers", sizeof("__default_properties"), (void **) soap_headers_p)==SUCCESS
03405                      && Z_TYPE_P(soap_headers_p)==IS_ARRAY) {
03406                      soap_headers = Z_ARRVAL_P(soap_headers_p);
03407               } else {
03408                      soap_headers = NULL;
03409               }
03410               do_soap_call(this_ptr, function, Z_STRLEN(function_name->element) + 1, arg_count, arguments, return_value, NULL, NULL, NULL, soap_headers, NULL TSRMLS_CC);
03411               efree(arguments);
03412        }
03413        zval_dtor(&function_name->element);
03414 }
03415 #endif
03416 
03417 static void clear_soap_fault(zval *obj TSRMLS_DC)
03418 {
03419        if (obj != NULL && obj->type == IS_OBJECT) {
03420               zend_hash_del(Z_OBJPROP_P(obj), "__soap_fault", sizeof("__soap_fault"));
03421        }
03422 }
03423 
03424 zval* add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail TSRMLS_DC)
03425 {
03426        zval *fault;
03427        ALLOC_INIT_ZVAL(fault);
03428        set_soap_fault(fault, NULL, fault_code, fault_string, fault_actor, fault_detail, NULL TSRMLS_CC);
03429 #ifdef ZEND_ENGINE_2
03430        Z_DELREF_P(fault);
03431 #endif
03432        add_property_zval(obj, "__soap_fault", fault);
03433        return fault;
03434 }
03435 
03436 static void set_soap_fault(zval *obj, char *fault_code_ns, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, char *name TSRMLS_DC)
03437 {
03438        if (Z_TYPE_P(obj) != IS_OBJECT) {
03439               object_init_ex(obj, soap_fault_class_entry);
03440        }
03441        
03442        add_property_string(obj, "faultstring", fault_string ? fault_string : "", 1);
03443 #ifdef ZEND_ENGINE_2
03444        zend_update_property_string(zend_exception_get_default(TSRMLS_C), obj, "message", sizeof("message")-1, (fault_string ? fault_string : "") TSRMLS_CC);
03445 #endif
03446        
03447        if (fault_code != NULL) {
03448               int soap_version = SOAP_GLOBAL(soap_version);
03449 
03450               if (fault_code_ns) {
03451                      add_property_string(obj, "faultcode", fault_code, 1);
03452                      add_property_string(obj, "faultcodens", fault_code_ns, 1);
03453               } else {
03454                      if (soap_version == SOAP_1_1) {
03455                             add_property_string(obj, "faultcode", fault_code, 1);
03456                             if (strcmp(fault_code,"Client") == 0 ||
03457                                 strcmp(fault_code,"Server") == 0 ||
03458                                 strcmp(fault_code,"VersionMismatch") == 0 ||
03459                               strcmp(fault_code,"MustUnderstand") == 0) {
03460                                    add_property_string(obj, "faultcodens", SOAP_1_1_ENV_NAMESPACE, 1);
03461                             }
03462                      } else if (soap_version == SOAP_1_2) {
03463                             if (strcmp(fault_code,"Client") == 0) {
03464                                    add_property_string(obj, "faultcode", "Sender", 1);
03465                                    add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
03466                             } else if (strcmp(fault_code,"Server") == 0) {
03467                                    add_property_string(obj, "faultcode", "Receiver", 1);
03468                                    add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
03469                             } else if (strcmp(fault_code,"VersionMismatch") == 0 ||
03470                                        strcmp(fault_code,"MustUnderstand") == 0 ||
03471                                        strcmp(fault_code,"DataEncodingUnknown") == 0) {
03472                                    add_property_string(obj, "faultcode", fault_code, 1);
03473                                    add_property_string(obj, "faultcodens", SOAP_1_2_ENV_NAMESPACE, 1);
03474                             } else {
03475                                    add_property_string(obj, "faultcode", fault_code, 1);
03476                             }
03477                      }
03478               }
03479        }
03480        if (fault_actor != NULL) {
03481               add_property_string(obj, "faultactor", fault_actor, 1);
03482        }
03483        if (fault_detail != NULL) {
03484               add_property_zval(obj, "detail", fault_detail);
03485        }
03486        if (name != NULL) {
03487               add_property_string(obj, "_name", name, 1);
03488        }
03489 }
03490 
03491 static void deserialize_parameters(xmlNodePtr params, sdlFunctionPtr function, int *num_params, zval ***parameters)
03492 {
03493        int cur_param = 0,num_of_params = 0;
03494        zval **tmp_parameters = NULL;
03495 
03496        if (function != NULL) {
03497               sdlParamPtr *param;
03498               xmlNodePtr val;
03499               int    use_names = 0;
03500 
03501               if (function->requestParameters == NULL) {
03502                      return;
03503               }
03504               num_of_params = zend_hash_num_elements(function->requestParameters);
03505               zend_hash_internal_pointer_reset(function->requestParameters);
03506               while (zend_hash_get_current_data(function->requestParameters, (void **)&param) == SUCCESS) {
03507                      if (get_node(params, (*param)->paramName) != NULL) {
03508                             use_names = 1;
03509                      }
03510                      zend_hash_move_forward(function->requestParameters);
03511               }
03512               if (use_names) {
03513                      tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0);
03514                      zend_hash_internal_pointer_reset(function->requestParameters);
03515                      while (zend_hash_get_current_data(function->requestParameters, (void **)&param) == SUCCESS) {
03516                             val = get_node(params, (*param)->paramName);
03517                             if (!val) {
03518                                    /* TODO: may be "nil" is not OK? */
03519                                    MAKE_STD_ZVAL(tmp_parameters[cur_param]);
03520                                    ZVAL_NULL(tmp_parameters[cur_param]);
03521                             } else {
03522                                    tmp_parameters[cur_param] = master_to_zval((*param)->encode, val);
03523                             }
03524                             cur_param++;
03525 
03526                             zend_hash_move_forward(function->requestParameters);
03527                      }
03528                      (*parameters) = tmp_parameters;
03529                      (*num_params) = num_of_params;
03530                      return;
03531               }
03532        }
03533        if (params) {
03534               xmlNodePtr trav;
03535 
03536               num_of_params = 0;
03537               trav = params;
03538               while (trav != NULL) {
03539                      if (trav->type == XML_ELEMENT_NODE) {
03540                             num_of_params++;
03541                      }
03542                      trav = trav->next;
03543               }
03544 
03545               if (num_of_params == 1 &&
03546                   function &&
03547                   function->binding &&
03548                   function->binding->bindingType == BINDING_SOAP &&
03549                   ((sdlSoapBindingFunctionPtr)function->bindingAttributes)->style == SOAP_DOCUMENT &&
03550                   (function->requestParameters == NULL ||
03551                    zend_hash_num_elements(function->requestParameters) == 0) &&
03552                   strcmp(params->name, function->functionName) == 0) {
03553                      num_of_params = 0;
03554               } else if (num_of_params > 0) {
03555                      tmp_parameters = safe_emalloc(num_of_params, sizeof(zval *), 0);
03556 
03557                      trav = params;
03558                      while (trav != 0 && cur_param < num_of_params) {
03559                             if (trav->type == XML_ELEMENT_NODE) {
03560                                    encodePtr enc;
03561                                    sdlParamPtr *param = NULL;
03562                                    if (function != NULL &&
03563                                        zend_hash_index_find(function->requestParameters, cur_param, (void **)&param) == FAILURE) {
03564                                           TSRMLS_FETCH();
03565                                           soap_server_fault("Client", "Error cannot find parameter", NULL, NULL, NULL TSRMLS_CC);
03566                                    }
03567                                    if (param == NULL) {
03568                                           enc = NULL;
03569                                    } else {
03570                                           enc = (*param)->encode;
03571                                    }
03572                                    tmp_parameters[cur_param] = master_to_zval(enc, trav);
03573                                    cur_param++;
03574                             }
03575                             trav = trav->next;
03576                      }
03577               }
03578        }
03579        if (num_of_params > cur_param) {
03580               TSRMLS_FETCH();
03581               soap_server_fault("Client","Missing parameter", NULL, NULL, NULL TSRMLS_CC);
03582        }
03583        (*parameters) = tmp_parameters;
03584        (*num_params) = num_of_params;
03585 }
03586 
03587 static sdlFunctionPtr find_function(sdlPtr sdl, xmlNodePtr func, zval* function_name)
03588 {
03589        sdlFunctionPtr function;
03590 
03591        function = get_function(sdl, (char*)func->name);
03592        if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
03593               sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
03594               if (fnb->style == SOAP_DOCUMENT) {
03595                      if (func->children != NULL ||
03596                          (function->requestParameters != NULL &&
03597                           zend_hash_num_elements(function->requestParameters) > 0)) {
03598                             function = NULL;
03599                      }
03600               }
03601        }
03602        if (sdl != NULL && function == NULL) {
03603               function = get_doc_function(sdl, func);
03604        }
03605 
03606        INIT_ZVAL(*function_name);
03607        if (function != NULL) {
03608               ZVAL_STRING(function_name, (char *)function->functionName, 1);
03609        } else {
03610               ZVAL_STRING(function_name, (char *)func->name, 1);
03611        }
03612 
03613        return function;
03614 }
03615 
03616 static sdlFunctionPtr deserialize_function_call(sdlPtr sdl, xmlDocPtr request, char* actor, zval *function_name, int *num_params, zval ***parameters, int *version, soapHeader **headers TSRMLS_DC)
03617 {
03618        char* envelope_ns = NULL;
03619        xmlNodePtr trav,env,head,body,func;
03620        xmlAttrPtr attr;
03621        sdlFunctionPtr function;
03622 
03623        encode_reset_ns();
03624 
03625        /* Get <Envelope> element */
03626        env = NULL;
03627        trav = request->children;
03628        while (trav != NULL) {
03629               if (trav->type == XML_ELEMENT_NODE) {
03630                      if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_1_ENV_NAMESPACE)) {
03631                             env = trav;
03632                             *version = SOAP_1_1;
03633                             envelope_ns = SOAP_1_1_ENV_NAMESPACE;
03634                             SOAP_GLOBAL(soap_version) = SOAP_1_1;
03635                      } else if (env == NULL && node_is_equal_ex(trav,"Envelope",SOAP_1_2_ENV_NAMESPACE)) {
03636                             env = trav;
03637                             *version = SOAP_1_2;
03638                             envelope_ns = SOAP_1_2_ENV_NAMESPACE;
03639                             SOAP_GLOBAL(soap_version) = SOAP_1_2;
03640                      } else {
03641                             soap_server_fault("VersionMismatch", "Wrong Version", NULL, NULL, NULL TSRMLS_CC);
03642                      }
03643               }
03644               trav = trav->next;
03645        }
03646        if (env == NULL) {
03647               soap_server_fault("Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, NULL TSRMLS_CC);
03648        }
03649 
03650        attr = env->properties;
03651        while (attr != NULL) {
03652               if (attr->ns == NULL) {
03653                      soap_server_fault("Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
03654               } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
03655                      if (*version == SOAP_1_2) {
03656                             soap_server_fault("Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, NULL TSRMLS_CC);
03657                      } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
03658                             soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
03659                      }
03660               }
03661               attr = attr->next;
03662        }
03663 
03664        /* Get <Header> element */
03665        head = NULL;
03666        trav = env->children;
03667        while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
03668               trav = trav->next;
03669        }
03670        if (trav != NULL && node_is_equal_ex(trav,"Header",envelope_ns)) {
03671               head = trav;
03672               trav = trav->next;
03673        }
03674 
03675        /* Get <Body> element */
03676        body = NULL;
03677        while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
03678               trav = trav->next;
03679        }
03680        if (trav != NULL && node_is_equal_ex(trav,"Body",envelope_ns)) {
03681               body = trav;
03682               trav = trav->next;
03683        }
03684        while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
03685               trav = trav->next;
03686        }
03687        if (body == NULL) {
03688               soap_server_fault("Client", "Body must be present in a SOAP envelope", NULL, NULL, NULL TSRMLS_CC);
03689        }
03690        attr = body->properties;
03691        while (attr != NULL) {
03692               if (attr->ns == NULL) {
03693                      if (*version == SOAP_1_2) {
03694                             soap_server_fault("Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
03695                      }
03696               } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
03697                      if (*version == SOAP_1_2) {
03698                             soap_server_fault("Client", "encodingStyle cannot be specified on the Body", NULL, NULL, NULL TSRMLS_CC);
03699                      } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
03700                             soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
03701                      }
03702               }
03703               attr = attr->next;
03704        }
03705 
03706        if (trav != NULL && *version == SOAP_1_2) {
03707               soap_server_fault("Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, NULL TSRMLS_CC);
03708        }
03709 
03710        func = NULL;
03711        trav = body->children;
03712        while (trav != NULL) {
03713               if (trav->type == XML_ELEMENT_NODE) {
03714 /*
03715                      if (func != NULL) {
03716                             soap_server_fault("Client", "looks like we got \"Body\" with several functions call", NULL, NULL, NULL TSRMLS_CC);
03717                      }
03718 */
03719                      func = trav;
03720                      break; /* FIXME: the rest of body is ignored */
03721               }
03722               trav = trav->next;
03723        }
03724        if (func == NULL) {
03725               function = get_doc_function(sdl, NULL);
03726               if (function != NULL) {
03727                      INIT_ZVAL(*function_name);
03728                      ZVAL_STRING(function_name, (char *)function->functionName, 1);
03729               } else {
03730                      soap_server_fault("Client", "looks like we got \"Body\" without function call", NULL, NULL, NULL TSRMLS_CC);
03731               }
03732        } else {
03733               if (*version == SOAP_1_1) {
03734                      attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
03735                      if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
03736                             soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
03737                      }
03738               } else {
03739                      attr = get_attribute_ex(func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
03740                      if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
03741                             soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
03742                      }
03743               }
03744               function = find_function(sdl, func, function_name);
03745               if (sdl != NULL && function == NULL) {
03746                      if (*version == SOAP_1_2) {
03747                             soap_server_fault("rpc:ProcedureNotPresent","Procedure not present", NULL, NULL, NULL TSRMLS_CC);
03748                      } else {
03749                             php_error(E_ERROR, "Procedure '%s' not present", func->name);
03750                      }
03751               }
03752        }
03753 
03754        *headers = NULL;
03755        if (head) {
03756               soapHeader *h, *last = NULL;
03757 
03758               attr = head->properties;
03759               while (attr != NULL) {
03760                      if (attr->ns == NULL) {
03761                             soap_server_fault("Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, NULL TSRMLS_CC);
03762                      } else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
03763                             if (*version == SOAP_1_2) {
03764                                    soap_server_fault("Client", "encodingStyle cannot be specified on the Header", NULL, NULL, NULL TSRMLS_CC);
03765                             } else if (strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
03766                                    soap_server_fault("Client", "Unknown data encoding style", NULL, NULL, NULL TSRMLS_CC);
03767                             }
03768                      }
03769                      attr = attr->next;
03770               }
03771               trav = head->children;
03772               while (trav != NULL) {
03773                      if (trav->type == XML_ELEMENT_NODE) {
03774                             xmlNodePtr hdr_func = trav;
03775                             int mustUnderstand = 0;
03776 
03777                             if (*version == SOAP_1_1) {
03778                                    attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_1_ENV_NAMESPACE);
03779                                    if (attr && strcmp((char*)attr->children->content,SOAP_1_1_ENC_NAMESPACE) != 0) {
03780                                           soap_server_fault("Client","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
03781                                    }
03782                                    attr = get_attribute_ex(hdr_func->properties,"actor",envelope_ns);
03783                                    if (attr != NULL) {
03784                                           if (strcmp((char*)attr->children->content,SOAP_1_1_ACTOR_NEXT) != 0 &&
03785                                               (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
03786                                             goto ignore_header;
03787                                           }
03788                                    }
03789                             } else if (*version == SOAP_1_2) {
03790                                    attr = get_attribute_ex(hdr_func->properties,"encodingStyle",SOAP_1_2_ENV_NAMESPACE);
03791                                    if (attr && strcmp((char*)attr->children->content,SOAP_1_2_ENC_NAMESPACE) != 0) {
03792                                           soap_server_fault("DataEncodingUnknown","Unknown Data Encoding Style", NULL, NULL, NULL TSRMLS_CC);
03793                                    }
03794                                    attr = get_attribute_ex(hdr_func->properties,"role",envelope_ns);
03795                                    if (attr != NULL) {
03796                                           if (strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_UNLIMATERECEIVER) != 0 &&
03797                                               strcmp((char*)attr->children->content,SOAP_1_2_ACTOR_NEXT) != 0 &&
03798                                               (actor == NULL || strcmp((char*)attr->children->content,actor) != 0)) {
03799                                             goto ignore_header;
03800                                           }
03801                                    }
03802                             }
03803                             attr = get_attribute_ex(hdr_func->properties,"mustUnderstand",envelope_ns);
03804                             if (attr) {
03805                                    if (strcmp((char*)attr->children->content,"1") == 0 ||
03806                                        strcmp((char*)attr->children->content,"true") == 0) {
03807                                           mustUnderstand = 1;
03808                                    } else if (strcmp((char*)attr->children->content,"0") == 0 ||
03809                                               strcmp((char*)attr->children->content,"false") == 0) {
03810                                           mustUnderstand = 0;
03811                                    } else {
03812                                           soap_server_fault("Client","mustUnderstand value is not boolean", NULL, NULL, NULL TSRMLS_CC);
03813                                    }
03814                             }
03815                             h = emalloc(sizeof(soapHeader));
03816                             memset(h, 0, sizeof(soapHeader));
03817                             h->mustUnderstand = mustUnderstand;
03818                             h->function = find_function(sdl, hdr_func, &h->function_name);
03819                             if (!h->function && sdl && function && function->binding && function->binding->bindingType == BINDING_SOAP) {
03820                                    sdlSoapBindingFunctionHeaderPtr *hdr;
03821                                    sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
03822                                    if (fnb->input.headers) {
03823                                           smart_str key = {0};
03824 
03825                                           if (hdr_func->ns) {
03826                                                  smart_str_appends(&key, (char*)hdr_func->ns->href);
03827                                                  smart_str_appendc(&key, ':');
03828                                           }
03829                                           smart_str_appendl(&key, Z_STRVAL(h->function_name), Z_STRLEN(h->function_name));
03830                                           smart_str_0(&key);
03831                                           if (zend_hash_find(fnb->input.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
03832                                                  h->hdr = *hdr;
03833                                           }
03834                                           smart_str_free(&key);
03835                                    }
03836                             }
03837                             if (h->hdr) {
03838                                    h->num_params = 1;
03839                                    h->parameters = emalloc(sizeof(zval*));
03840                                    h->parameters[0] = master_to_zval(h->hdr->encode, hdr_func);
03841                             } else {
03842                                    if (h->function && h->function->binding && h->function->binding->bindingType == BINDING_SOAP) {
03843                                           sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)h->function->bindingAttributes;
03844                                           if (fnb->style == SOAP_RPC) {
03845                                                  hdr_func = hdr_func->children;
03846                                           }
03847                                    }
03848                                    deserialize_parameters(hdr_func, h->function, &h->num_params, &h->parameters);
03849                             }
03850                             INIT_ZVAL(h->retval);
03851                             if (last == NULL) {
03852                                    *headers = h;
03853                             } else {
03854                                    last->next = h;
03855                             }
03856                             last = h;
03857                      }
03858 ignore_header:
03859                      trav = trav->next;
03860               }
03861        }
03862 
03863        if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
03864               sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
03865               if (fnb->style == SOAP_RPC) {
03866                      func = func->children;
03867               }
03868        } else {
03869               func = func->children;
03870        }
03871        deserialize_parameters(func, function, num_params, parameters);
03872        
03873        encode_finish();
03874 
03875        return function;
03876 }
03877 
03878 static int serialize_response_call2(xmlNodePtr body, sdlFunctionPtr function, char *function_name, char *uri, zval *ret, int version, int main TSRMLS_DC)
03879 {
03880        xmlNodePtr method = NULL, param;
03881        sdlParamPtr parameter = NULL;
03882        int param_count;
03883        int style, use;
03884        xmlNsPtr ns = NULL;
03885 
03886        if (function != NULL && function->binding->bindingType == BINDING_SOAP) {
03887               sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
03888 
03889               style = fnb->style;
03890               use = fnb->output.use;
03891               if (style == SOAP_RPC) {
03892                      ns = encode_add_ns(body, fnb->output.ns);
03893                      if (function->responseName) {
03894                             method = xmlNewChild(body, ns, BAD_CAST(function->responseName), NULL);
03895                      } else if (function->responseParameters) {
03896                             method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
03897                      }
03898               }
03899        } else {
03900               style = main?SOAP_RPC:SOAP_DOCUMENT;
03901               use = main?SOAP_ENCODED:SOAP_LITERAL;
03902               if (style == SOAP_RPC) {
03903                      ns = encode_add_ns(body, uri);
03904                      method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
03905               }
03906        }
03907 
03908        if (function != NULL) {
03909               if (function->responseParameters) {
03910                      param_count = zend_hash_num_elements(function->responseParameters);
03911               } else {
03912                 param_count = 0;
03913               }
03914        } else {
03915          param_count = 1;
03916        }
03917 
03918        if (param_count == 1) {
03919               parameter = get_param(function, NULL, 0, TRUE);
03920 
03921               if (style == SOAP_RPC) {
03922                 xmlNode *rpc_result;
03923                      if (main && version == SOAP_1_2) {
03924                             xmlNs *rpc_ns = xmlNewNs(body, BAD_CAST(RPC_SOAP12_NAMESPACE), BAD_CAST(RPC_SOAP12_NS_PREFIX));
03925                             rpc_result = xmlNewChild(method, rpc_ns, BAD_CAST("result"), NULL);
03926                             param = serialize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
03927                             xmlNodeSetContent(rpc_result,param->name);
03928                      } else {
03929                             param = serialize_parameter(parameter, ret, 0, "return", use, method TSRMLS_CC);
03930                      }
03931               } else {
03932                      param = serialize_parameter(parameter, ret, 0, "return", use, body TSRMLS_CC);
03933                      if (function && function->binding->bindingType == BINDING_SOAP) {
03934                             if (parameter && parameter->element) {
03935                                    ns = encode_add_ns(param, parameter->element->namens);
03936                                    xmlNodeSetName(param, BAD_CAST(parameter->element->name));
03937                                    xmlSetNs(param, ns);
03938                             }
03939                      } else if (strcmp((char*)param->name,"return") == 0) {
03940                             ns = encode_add_ns(param, uri);
03941                             xmlNodeSetName(param, BAD_CAST(function_name));
03942                             xmlSetNs(param, ns);
03943                      }
03944               }
03945        } else if (param_count > 1 && Z_TYPE_P(ret) == IS_ARRAY) {
03946               HashPosition pos;
03947               zval **data;
03948               int i = 0;
03949 
03950               zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(ret), &pos);
03951               while (zend_hash_get_current_data_ex(Z_ARRVAL_P(ret), (void **)&data, &pos) != FAILURE) {
03952                      char *param_name = NULL;
03953                      unsigned int param_name_len;
03954                      ulong param_index = i;
03955 
03956                      zend_hash_get_current_key_ex(Z_ARRVAL_P(ret), &param_name, &param_name_len, &param_index, 0, &pos);
03957                      parameter = get_param(function, param_name, param_index, TRUE);
03958                      if (style == SOAP_RPC) {
03959                             param = serialize_parameter(parameter, *data, i, param_name, use, method TSRMLS_CC);
03960                      } else {
03961                             param = serialize_parameter(parameter, *data, i, param_name, use, body TSRMLS_CC);
03962                             if (function && function->binding->bindingType == BINDING_SOAP) {
03963                                    if (parameter && parameter->element) {
03964                                           ns = encode_add_ns(param, parameter->element->namens);
03965                                           xmlNodeSetName(param, BAD_CAST(parameter->element->name));
03966                                           xmlSetNs(param, ns);
03967                                    }
03968                             }
03969                      }
03970 
03971                      zend_hash_move_forward_ex(Z_ARRVAL_P(ret), &pos);
03972                      i++;
03973               }
03974        }
03975        if (use == SOAP_ENCODED && version == SOAP_1_2 && method != NULL) {
03976               xmlSetNsProp(method, body->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
03977        }
03978        return use;
03979 }
03980 
03981 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name, char *uri, zval *ret, soapHeader* headers, int version TSRMLS_DC)
03982 {
03983        xmlDocPtr doc;
03984        xmlNodePtr envelope = NULL, body, param;
03985        xmlNsPtr ns = NULL;
03986        int use = SOAP_LITERAL;
03987        xmlNodePtr head = NULL;
03988 
03989        encode_reset_ns();
03990 
03991        doc = xmlNewDoc(BAD_CAST("1.0"));
03992        doc->charset = XML_CHAR_ENCODING_UTF8;
03993        doc->encoding = xmlCharStrdup("UTF-8");
03994 
03995        if (version == SOAP_1_1) {
03996               envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
03997               ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
03998               xmlSetNs(envelope,ns);
03999        } else if (version == SOAP_1_2) {
04000               envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
04001               ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
04002               xmlSetNs(envelope,ns);
04003        } else {
04004               soap_server_fault("Server", "Unknown SOAP version", NULL, NULL, NULL TSRMLS_CC);
04005        }
04006        xmlDocSetRootElement(doc, envelope);
04007 
04008        if (Z_TYPE_P(ret) == IS_OBJECT &&
04009            instanceof_function(Z_OBJCE_P(ret), soap_fault_class_entry TSRMLS_CC)) {
04010          char *detail_name;
04011               HashTable* prop;
04012               zval **tmp;
04013               sdlFaultPtr fault = NULL;
04014               char *fault_ns = NULL;
04015 
04016               prop = Z_OBJPROP_P(ret);
04017 
04018               if (headers &&
04019                   zend_hash_find(prop, "headerfault", sizeof("headerfault"), (void**)&tmp) == SUCCESS) {
04020                      encodePtr hdr_enc = NULL;
04021                      int hdr_use = SOAP_LITERAL;
04022                      zval *hdr_ret  = *tmp;
04023                      char *hdr_ns   = headers->hdr?headers->hdr->ns:NULL;
04024                      char *hdr_name = Z_STRVAL(headers->function_name);
04025 
04026                      head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
04027                      if (Z_TYPE_P(hdr_ret) == IS_OBJECT &&
04028                          instanceof_function(Z_OBJCE_P(hdr_ret), soap_header_class_entry TSRMLS_CC)) {
04029                             HashTable* ht = Z_OBJPROP_P(hdr_ret);
04030                             sdlSoapBindingFunctionHeaderPtr *hdr;
04031                             smart_str key = {0};
04032 
04033                             if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS &&
04034                            Z_TYPE_PP(tmp) == IS_STRING) {
04035                                    smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
04036                                    smart_str_appendc(&key, ':');
04037                                    hdr_ns = Z_STRVAL_PP(tmp);
04038                             }
04039                             if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS &&
04040                                 Z_TYPE_PP(tmp) == IS_STRING) {
04041                                    smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
04042                                    hdr_name = Z_STRVAL_PP(tmp);
04043                             }
04044                             smart_str_0(&key);
04045                             if (headers->hdr && headers->hdr->headerfaults &&
04046                                 zend_hash_find(headers->hdr->headerfaults, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
04047                                    hdr_enc = (*hdr)->encode;
04048                                    hdr_use = (*hdr)->use;
04049                             }
04050                             smart_str_free(&key);
04051                             if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
04052                                    hdr_ret = *tmp;
04053                             } else {
04054                                    hdr_ret = NULL;
04055                             }
04056                      }
04057 
04058                      if (headers->function) {
04059                             if (serialize_response_call2(head, headers->function, Z_STRVAL(headers->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) {
04060                                    use = SOAP_ENCODED;
04061                             }
04062                      } else {
04063                             xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head);
04064                             if (hdr_name) {
04065                                    xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
04066                             }
04067                             if (hdr_ns) {
04068                                    xmlNsPtr nsptr = encode_add_ns(xmlHdr, hdr_ns);
04069                                    xmlSetNs(xmlHdr, nsptr);
04070                             }
04071                      }
04072               }
04073 
04074               body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
04075               param = xmlNewChild(body, ns, BAD_CAST("Fault"), NULL);
04076 
04077               if (zend_hash_find(prop, "faultcodens", sizeof("faultcodens"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
04078                      fault_ns = Z_STRVAL_PP(tmp);
04079               }
04080               use = SOAP_LITERAL;
04081               if (zend_hash_find(prop, "_name", sizeof("_name"), (void**)&tmp) == SUCCESS && Z_TYPE_PP(tmp) == IS_STRING) {
04082                      sdlFaultPtr *tmp_fault;
04083                      if (function && function->faults &&
04084                          zend_hash_find(function->faults, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)+1, (void**)&tmp_fault) == SUCCESS) {
04085                        fault = *tmp_fault;
04086                             if (function->binding &&
04087                                 function->binding->bindingType == BINDING_SOAP &&
04088                                 fault->bindingAttributes) {
04089                                    sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
04090                                    use = fb->use;
04091                                    if (fault_ns == NULL) {
04092                                           fault_ns = fb->ns;
04093                                    }
04094                             }
04095                      }
04096               } else if (function && function->faults &&
04097                          zend_hash_num_elements(function->faults) == 1) {
04098 
04099                      zend_hash_internal_pointer_reset(function->faults);
04100                      zend_hash_get_current_data(function->faults, (void**)&fault);
04101                      fault = *(sdlFaultPtr*)fault;
04102                      if (function->binding &&
04103                          function->binding->bindingType == BINDING_SOAP &&
04104                          fault->bindingAttributes) {
04105                             sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
04106                             use = fb->use;
04107                             if (fault_ns == NULL) {
04108                               fault_ns = fb->ns;
04109                             }
04110                      }
04111               }
04112 
04113               if (fault_ns == NULL &&
04114                   fault && 
04115                   fault->details && 
04116                   zend_hash_num_elements(fault->details) == 1) {
04117                      sdlParamPtr sparam;
04118 
04119                      zend_hash_internal_pointer_reset(fault->details);
04120                      zend_hash_get_current_data(fault->details, (void**)&sparam);
04121                      sparam = *(sdlParamPtr*)sparam;
04122                      if (sparam->element) {
04123                             fault_ns = sparam->element->namens;
04124                      }
04125               }
04126 
04127               if (version == SOAP_1_1) {
04128                      if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) {
04129                             int new_len;
04130                             xmlNodePtr node = xmlNewNode(NULL, BAD_CAST("faultcode"));
04131                             char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
04132                             xmlAddChild(param, node);
04133                             if (fault_ns) {
04134                                    xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
04135                                    xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
04136                                    xmlNodeSetContent(node, code);
04137                                    xmlFree(code);
04138                             } else {      
04139                                    xmlNodeSetContentLen(node, BAD_CAST(str), new_len);
04140                             }
04141                             efree(str);
04142                      }
04143                      if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
04144                             xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param);
04145                             xmlNodeSetName(node, BAD_CAST("faultstring"));
04146                      }
04147                      if (zend_hash_find(prop, "faultactor", sizeof("faultactor"), (void**)&tmp) == SUCCESS) {
04148                             xmlNodePtr node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, param);
04149                             xmlNodeSetName(node, BAD_CAST("faultactor"));
04150                      }
04151                      detail_name = "detail";
04152               } else {
04153                      if (zend_hash_find(prop, "faultcode", sizeof("faultcode"), (void**)&tmp) == SUCCESS) {
04154                             int new_len;
04155                             xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Code"), NULL);
04156                             char *str = php_escape_html_entities((unsigned char*)Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp), &new_len, 0, 0, NULL TSRMLS_CC);
04157                             node = xmlNewChild(node, ns, BAD_CAST("Value"), NULL);
04158                             if (fault_ns) {
04159                                    xmlNsPtr nsptr = encode_add_ns(node, fault_ns);
04160                                    xmlChar *code = xmlBuildQName(BAD_CAST(str), nsptr->prefix, NULL, 0);
04161                                    xmlNodeSetContent(node, code);
04162                                    xmlFree(code);
04163                             } else {      
04164                                    xmlNodeSetContentLen(node, BAD_CAST(str), new_len);
04165                             }
04166                             efree(str);
04167                      }
04168                      if (zend_hash_find(prop, "faultstring", sizeof("faultstring"), (void**)&tmp) == SUCCESS) {
04169                             xmlNodePtr node = xmlNewChild(param, ns, BAD_CAST("Reason"), NULL);
04170                             node = master_to_xml(get_conversion(IS_STRING), *tmp, SOAP_LITERAL, node);
04171                             xmlNodeSetName(node, BAD_CAST("Text"));
04172                             xmlSetNs(node, ns);
04173                      }
04174                      detail_name = SOAP_1_2_ENV_NS_PREFIX":Detail";
04175               }
04176               if (fault && fault->details && zend_hash_num_elements(fault->details) == 1) {
04177                      xmlNodePtr node;
04178                      zval *detail = NULL;
04179                      sdlParamPtr sparam;
04180                      xmlNodePtr x;
04181 
04182                      if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS &&
04183                          Z_TYPE_PP(tmp) != IS_NULL) {
04184                             detail = *tmp;
04185                      }
04186                      node = xmlNewNode(NULL, BAD_CAST(detail_name));
04187                      xmlAddChild(param, node);
04188 
04189                      zend_hash_internal_pointer_reset(fault->details);
04190                      zend_hash_get_current_data(fault->details, (void**)&sparam);
04191                      sparam = *(sdlParamPtr*)sparam;
04192 
04193                      if (detail &&
04194                          Z_TYPE_P(detail) == IS_OBJECT &&
04195                          sparam->element &&
04196                          zend_hash_num_elements(Z_OBJPROP_P(detail)) == 1 &&
04197                          zend_hash_find(Z_OBJPROP_P(detail), sparam->element->name, strlen(sparam->element->name)+1, (void**)&tmp) == SUCCESS) {
04198                             detail = *tmp;
04199                      }
04200 
04201                      x = serialize_parameter(sparam, detail, 1, NULL, use, node TSRMLS_CC);
04202 
04203                      if (function &&
04204                          function->binding &&
04205                          function->binding->bindingType == BINDING_SOAP &&
04206                          function->bindingAttributes) {
04207                             sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
04208                             if (fnb->style == SOAP_RPC && !sparam->element) {
04209                               if (fault->bindingAttributes) {
04210                                           sdlSoapBindingFunctionFaultPtr fb = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
04211                                           if (fb->ns) {
04212                                                  xmlNsPtr ns = encode_add_ns(x, fb->ns);
04213                                                  xmlSetNs(x, ns);
04214                                           }
04215                                    }
04216                             } else {
04217                                    if (sparam->element) {
04218                                           ns = encode_add_ns(x, sparam->element->namens);
04219                                           xmlNodeSetName(x, BAD_CAST(sparam->element->name));
04220                                           xmlSetNs(x, ns);
04221                                    }
04222                             }
04223                      }
04224                      if (use == SOAP_ENCODED && version == SOAP_1_2) {
04225                             xmlSetNsProp(x, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
04226                      }
04227               } else if (zend_hash_find(prop, "detail", sizeof("detail"), (void**)&tmp) == SUCCESS &&
04228                   Z_TYPE_PP(tmp) != IS_NULL) {
04229                      serialize_zval(*tmp, NULL, detail_name, use, param TSRMLS_CC);
04230               }
04231        } else {
04232 
04233               if (headers) {
04234                      soapHeader *h;
04235 
04236                      head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
04237                      h = headers;
04238                      while (h != NULL) {
04239                             if (Z_TYPE(h->retval) != IS_NULL) {
04240                                    encodePtr hdr_enc = NULL;
04241                                    int hdr_use = SOAP_LITERAL;
04242                                    zval *hdr_ret = &h->retval;
04243                                    char *hdr_ns   = h->hdr?h->hdr->ns:NULL;
04244                                    char *hdr_name = Z_STRVAL(h->function_name);
04245 
04246 
04247                                    if (Z_TYPE(h->retval) == IS_OBJECT &&
04248                                        instanceof_function(Z_OBJCE(h->retval), soap_header_class_entry TSRMLS_CC)) {
04249                                           HashTable* ht = Z_OBJPROP(h->retval);
04250                                           zval **tmp;
04251                                           sdlSoapBindingFunctionHeaderPtr *hdr;
04252                                           smart_str key = {0};
04253 
04254                                           if (zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&tmp) == SUCCESS &&
04255                                          Z_TYPE_PP(tmp) == IS_STRING) {
04256                                                  smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
04257                                                  smart_str_appendc(&key, ':');
04258                                                  hdr_ns = Z_STRVAL_PP(tmp);
04259                                           }
04260                                           if (zend_hash_find(ht, "name", sizeof("name"), (void**)&tmp) == SUCCESS &&
04261                                               Z_TYPE_PP(tmp) == IS_STRING) {
04262                                                  smart_str_appendl(&key, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
04263                                                  hdr_name = Z_STRVAL_PP(tmp);
04264                                           }
04265                                           smart_str_0(&key);
04266                                           if (function && function->binding && function->binding->bindingType == BINDING_SOAP) {
04267                                                  sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
04268 
04269                                                  if (fnb->output.headers &&
04270                                                      zend_hash_find(fnb->output.headers, key.c, key.len+1, (void**)&hdr) == SUCCESS) {
04271                                                         hdr_enc = (*hdr)->encode;
04272                                                         hdr_use = (*hdr)->use;
04273                                                  }
04274                                           }
04275                                           smart_str_free(&key);
04276                                           if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
04277                                                  hdr_ret = *tmp;
04278                                           } else {
04279                                                  hdr_ret = NULL;
04280                                           }
04281                                    }
04282 
04283                                    if (h->function) {
04284                                           if (serialize_response_call2(head, h->function, Z_STRVAL(h->function_name), uri, hdr_ret, version, 0 TSRMLS_CC) == SOAP_ENCODED) {
04285                                                  use = SOAP_ENCODED;
04286                                           }
04287                                    } else {
04288                                           xmlNodePtr xmlHdr = master_to_xml(hdr_enc, hdr_ret, hdr_use, head);
04289                                           if (hdr_name) {
04290                                                  xmlNodeSetName(xmlHdr, BAD_CAST(hdr_name));
04291                                           }
04292                                           if (hdr_ns) {
04293                                                  xmlNsPtr nsptr = encode_add_ns(xmlHdr,hdr_ns);
04294                                                  xmlSetNs(xmlHdr, nsptr);
04295                                           }
04296                                    }
04297                             }
04298                             h = h->next;
04299                      }
04300 
04301                      if (head->children == NULL) {
04302                             xmlUnlinkNode(head);
04303                             xmlFreeNode(head);
04304                      }
04305               }
04306 
04307               body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
04308 
04309               if (serialize_response_call2(body, function, function_name, uri, ret, version, 1 TSRMLS_CC) == SOAP_ENCODED) {
04310                      use = SOAP_ENCODED;
04311               }
04312 
04313        }
04314 
04315        if (use == SOAP_ENCODED) {
04316               xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
04317               if (version == SOAP_1_1) {
04318                      xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
04319                      xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
04320               } else if (version == SOAP_1_2) {
04321                      xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
04322               }
04323        }
04324 
04325        encode_finish();
04326 
04327        if (function && function->responseName == NULL && 
04328            body->children == NULL && head == NULL) {
04329               xmlFreeDoc(doc);
04330               return NULL;
04331        }
04332        return doc;
04333 }
04334 
04335 static xmlDocPtr serialize_function_call(zval *this_ptr, sdlFunctionPtr function, char *function_name, char *uri, zval **arguments, int arg_count, int version, HashTable *soap_headers TSRMLS_DC)
04336 {
04337        xmlDoc *doc;
04338        xmlNodePtr envelope = NULL, body, method = NULL, head = NULL;
04339        xmlNsPtr ns = NULL;
04340        zval **zstyle, **zuse;
04341        int i, style, use;
04342        HashTable *hdrs = NULL;
04343 
04344        encode_reset_ns();
04345 
04346        doc = xmlNewDoc(BAD_CAST("1.0"));
04347        doc->encoding = xmlCharStrdup("UTF-8");
04348        doc->charset = XML_CHAR_ENCODING_UTF8;
04349        if (version == SOAP_1_1) {
04350               envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
04351               ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENV_NAMESPACE), BAD_CAST(SOAP_1_1_ENV_NS_PREFIX));
04352               xmlSetNs(envelope, ns);
04353        } else if (version == SOAP_1_2) {
04354               envelope = xmlNewDocNode(doc, NULL, BAD_CAST("Envelope"), NULL);
04355               ns = xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENV_NAMESPACE), BAD_CAST(SOAP_1_2_ENV_NS_PREFIX));
04356               xmlSetNs(envelope, ns);
04357        } else {
04358               soap_error0(E_ERROR, "Unknown SOAP version");
04359        }
04360        xmlDocSetRootElement(doc, envelope);
04361 
04362        if (soap_headers) {
04363               head = xmlNewChild(envelope, ns, BAD_CAST("Header"), NULL);
04364        }
04365 
04366        body = xmlNewChild(envelope, ns, BAD_CAST("Body"), NULL);
04367 
04368        if (function && function->binding->bindingType == BINDING_SOAP) {
04369               sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)function->bindingAttributes;
04370 
04371               hdrs = fnb->input.headers;
04372               style = fnb->style;
04373               /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
04374               /*style = SOAP_RPC;*/
04375               use = fnb->input.use;
04376               if (style == SOAP_RPC) {
04377                      ns = encode_add_ns(body, fnb->input.ns);
04378                      if (function->requestName) {
04379                             method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
04380                      } else {
04381                             method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
04382                      }
04383               }
04384        } else {
04385               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "style", sizeof("style"), (void **)&zstyle) == SUCCESS) {
04386                      style = Z_LVAL_PP(zstyle);
04387               } else {
04388                      style = SOAP_RPC;
04389               }
04390               /*FIXME: how to pass method name if style is SOAP_DOCUMENT */
04391               /*style = SOAP_RPC;*/
04392               if (style == SOAP_RPC) {
04393                      ns = encode_add_ns(body, uri);
04394                      if (function_name) {
04395                             method = xmlNewChild(body, ns, BAD_CAST(function_name), NULL);
04396                      } else if (function && function->requestName) {
04397                             method = xmlNewChild(body, ns, BAD_CAST(function->requestName), NULL);
04398                      } else if (function && function->functionName) {
04399                             method = xmlNewChild(body, ns, BAD_CAST(function->functionName), NULL);
04400                      } else {
04401                             method = body;
04402                      }
04403               } else {
04404                      method = body;
04405               }
04406 
04407               if (zend_hash_find(Z_OBJPROP_P(this_ptr), "use", sizeof("use"), (void **)&zuse) == SUCCESS &&
04408                        Z_LVAL_PP(zuse) == SOAP_LITERAL) {
04409                      use = SOAP_LITERAL;
04410               } else {
04411                      use = SOAP_ENCODED;
04412               }
04413        }
04414 
04415        for (i = 0;i < arg_count;i++) {
04416               xmlNodePtr param;
04417               sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
04418 
04419               if (style == SOAP_RPC) {
04420                      param = serialize_parameter(parameter, arguments[i], i, NULL, use, method TSRMLS_CC);
04421               } else if (style == SOAP_DOCUMENT) {
04422                      param = serialize_parameter(parameter, arguments[i], i, NULL, use, body TSRMLS_CC);
04423                      if (function && function->binding->bindingType == BINDING_SOAP) {
04424                             if (parameter && parameter->element) {
04425                                    ns = encode_add_ns(param, parameter->element->namens);
04426                                    xmlNodeSetName(param, BAD_CAST(parameter->element->name));
04427                                    xmlSetNs(param, ns);
04428                             }
04429                      }
04430               }
04431        }
04432 
04433        if (function && function->requestParameters) {
04434               int n = zend_hash_num_elements(function->requestParameters);
04435 
04436               if (n > arg_count) {
04437                      for (i = arg_count; i < n; i++) {
04438                             xmlNodePtr param;
04439                             sdlParamPtr parameter = get_param(function, NULL, i, FALSE);
04440 
04441                             if (style == SOAP_RPC) {
04442                                    param = serialize_parameter(parameter, NULL, i, NULL, use, method TSRMLS_CC);
04443                             } else if (style == SOAP_DOCUMENT) {
04444                                    param = serialize_parameter(parameter, NULL, i, NULL, use, body TSRMLS_CC);
04445                                    if (function && function->binding->bindingType == BINDING_SOAP) {
04446                                           if (parameter && parameter->element) {
04447                                                  ns = encode_add_ns(param, parameter->element->namens);
04448                                                  xmlNodeSetName(param, BAD_CAST(parameter->element->name));
04449                                                  xmlSetNs(param, ns);
04450                                           }
04451                                    }
04452                             }
04453                      }
04454               }
04455        }
04456 
04457        if (head) {
04458               zval** header;
04459 
04460               zend_hash_internal_pointer_reset(soap_headers);
04461               while (zend_hash_get_current_data(soap_headers,(void**)&header) == SUCCESS) {
04462                      HashTable *ht = Z_OBJPROP_PP(header);
04463                      zval **name, **ns, **tmp;
04464 
04465                      if (zend_hash_find(ht, "name", sizeof("name"), (void**)&name) == SUCCESS &&
04466                          Z_TYPE_PP(name) == IS_STRING &&
04467                          zend_hash_find(ht, "namespace", sizeof("namespace"), (void**)&ns) == SUCCESS &&
04468                          Z_TYPE_PP(ns) == IS_STRING) {
04469                             xmlNodePtr h;
04470                             xmlNsPtr nsptr;
04471                             int hdr_use = SOAP_LITERAL;
04472                             encodePtr enc = NULL;
04473 
04474                             if (hdrs) {
04475                                    smart_str key = {0};
04476                                    sdlSoapBindingFunctionHeaderPtr *hdr;
04477 
04478                                    smart_str_appendl(&key, Z_STRVAL_PP(ns), Z_STRLEN_PP(ns));
04479                                    smart_str_appendc(&key, ':');
04480                                    smart_str_appendl(&key, Z_STRVAL_PP(name), Z_STRLEN_PP(name));
04481                                    smart_str_0(&key);
04482                                    if (zend_hash_find(hdrs, key.c, key.len+1,(void**)&hdr) == SUCCESS) {
04483                                           hdr_use = (*hdr)->use;
04484                                           enc = (*hdr)->encode;
04485                                           if (hdr_use == SOAP_ENCODED) {
04486                                                  use = SOAP_ENCODED;
04487                                           }
04488                                    }
04489                                    smart_str_free(&key);
04490                             }
04491 
04492                             if (zend_hash_find(ht, "data", sizeof("data"), (void**)&tmp) == SUCCESS) {
04493                                    h = master_to_xml(enc, *tmp, hdr_use, head);
04494                                    xmlNodeSetName(h, BAD_CAST(Z_STRVAL_PP(name)));
04495                             } else {
04496                                    h = xmlNewNode(NULL, BAD_CAST(Z_STRVAL_PP(name)));
04497                                    xmlAddChild(head, h);
04498                             }
04499                             nsptr = encode_add_ns(h, Z_STRVAL_PP(ns));
04500                             xmlSetNs(h, nsptr);
04501 
04502                             if (zend_hash_find(ht, "mustUnderstand", sizeof("mustUnderstand"), (void**)&tmp) == SUCCESS &&
04503                                 Z_TYPE_PP(tmp) == IS_BOOL && Z_LVAL_PP(tmp)) {
04504                                    if (version == SOAP_1_1) {
04505                                           xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("1"));
04506                                    } else {
04507                                           xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":mustUnderstand"), BAD_CAST("true"));
04508                                    }
04509                             }
04510                             if (zend_hash_find(ht, "actor", sizeof("actor"), (void**)&tmp) == SUCCESS) {
04511                                    if (Z_TYPE_PP(tmp) == IS_STRING) {
04512                                           if (version == SOAP_1_1) {
04513                                                  xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(Z_STRVAL_PP(tmp)));
04514                                           } else {
04515                                                  xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(Z_STRVAL_PP(tmp)));
04516                                           }
04517                                    } else if (Z_TYPE_PP(tmp) == IS_LONG) {
04518                                           if (version == SOAP_1_1) {
04519                                                  if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
04520                                                         xmlSetProp(h, BAD_CAST(SOAP_1_1_ENV_NS_PREFIX":actor"), BAD_CAST(SOAP_1_1_ACTOR_NEXT));
04521                                                  }
04522                                           } else {
04523                                                  if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NEXT) {
04524                                                         xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NEXT));
04525                                                  } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_NONE) {
04526                                                         xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_NONE));
04527                                                  } else if (Z_LVAL_PP(tmp) == SOAP_ACTOR_UNLIMATERECEIVER) {
04528                                                         xmlSetProp(h, BAD_CAST(SOAP_1_2_ENV_NS_PREFIX":role"), BAD_CAST(SOAP_1_2_ACTOR_UNLIMATERECEIVER));
04529                                                  }
04530                                           }
04531                                    }
04532                             }
04533                      }
04534                      zend_hash_move_forward(soap_headers);
04535               }
04536        }
04537 
04538        if (use == SOAP_ENCODED) {
04539               xmlNewNs(envelope, BAD_CAST(XSD_NAMESPACE), BAD_CAST(XSD_NS_PREFIX));
04540               if (version == SOAP_1_1) {
04541                      xmlNewNs(envelope, BAD_CAST(SOAP_1_1_ENC_NAMESPACE), BAD_CAST(SOAP_1_1_ENC_NS_PREFIX));
04542                      xmlSetNsProp(envelope, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_1_ENC_NAMESPACE));
04543               } else if (version == SOAP_1_2) {
04544                      xmlNewNs(envelope, BAD_CAST(SOAP_1_2_ENC_NAMESPACE), BAD_CAST(SOAP_1_2_ENC_NS_PREFIX));
04545                      if (method) {
04546                             xmlSetNsProp(method, envelope->ns, BAD_CAST("encodingStyle"), BAD_CAST(SOAP_1_2_ENC_NAMESPACE));
04547                      }
04548               }
04549        }
04550 
04551        encode_finish();
04552 
04553        return doc;
04554 }
04555 
04556 static xmlNodePtr serialize_parameter(sdlParamPtr param, zval *param_val, int index, char *name, int style, xmlNodePtr parent TSRMLS_DC)
04557 {
04558        char *paramName;
04559        xmlNodePtr xmlParam;
04560        char paramNameBuf[10];
04561 
04562        if (param_val &&
04563            Z_TYPE_P(param_val) == IS_OBJECT &&
04564            Z_OBJCE_P(param_val) == soap_param_class_entry) {
04565               zval **param_name;
04566               zval **param_data;
04567 
04568               if (zend_hash_find(Z_OBJPROP_P(param_val), "param_name", sizeof("param_name"), (void **)&param_name) == SUCCESS &&
04569                   zend_hash_find(Z_OBJPROP_P(param_val), "param_data", sizeof("param_data"), (void **)&param_data) == SUCCESS) {
04570                      param_val = *param_data;
04571                      name = Z_STRVAL_PP(param_name);
04572               }
04573        }
04574 
04575        if (param != NULL && param->paramName != NULL) {
04576               paramName = param->paramName;
04577        } else {
04578               if (name == NULL) {
04579                      paramName = paramNameBuf;
04580                      snprintf(paramName, sizeof(paramNameBuf), "param%d",index);
04581               } else {
04582                      paramName = name;
04583               }
04584        }
04585 
04586        xmlParam = serialize_zval(param_val, param, paramName, style, parent TSRMLS_CC);
04587 
04588        return xmlParam;
04589 }
04590 
04591 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent TSRMLS_DC)
04592 {
04593        xmlNodePtr xmlParam;
04594        encodePtr enc;
04595        zval defval;
04596 
04597        if (param != NULL) {
04598               enc = param->encode;
04599               if (val == NULL) {
04600                      if (param->element) {
04601                             if (param->element->fixed) {
04602                                    ZVAL_STRING(&defval, param->element->fixed, 0);
04603                                    val = &defval;
04604                             } else if (param->element->def && !param->element->nillable) {
04605                                    ZVAL_STRING(&defval, param->element->def, 0);
04606                                    val = &defval;
04607                             }
04608                      }
04609               }
04610        } else {
04611               enc = NULL;
04612        }
04613        xmlParam = master_to_xml(enc, val, style, parent);
04614        if (!strcmp((char*)xmlParam->name, "BOGUS")) {
04615               xmlNodeSetName(xmlParam, BAD_CAST(paramName));
04616        }
04617        return xmlParam;
04618 }
04619 
04620 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int response)
04621 {
04622        sdlParamPtr *tmp;
04623        HashTable   *ht;
04624 
04625        if (function == NULL) {
04626               return NULL;
04627        }
04628 
04629        if (response == FALSE) {
04630               ht = function->requestParameters;
04631        } else {
04632               ht = function->responseParameters;
04633        }
04634 
04635        if (ht == NULL) {
04636          return NULL;
04637        }
04638 
04639        if (param_name != NULL) {
04640               if (zend_hash_find(ht, param_name, strlen(param_name), (void **)&tmp) != FAILURE) {
04641                      return *tmp;
04642               } else {
04643                      HashPosition pos;
04644               
04645                      zend_hash_internal_pointer_reset_ex(ht, &pos);
04646                      while (zend_hash_get_current_data_ex(ht, (void **)&tmp, &pos) != FAILURE) {
04647                             if ((*tmp)->paramName && strcmp(param_name, (*tmp)->paramName) == 0) {
04648                                    return *tmp;
04649                             }
04650                             zend_hash_move_forward_ex(ht, &pos);
04651                      }
04652               }
04653        } else {
04654               if (zend_hash_index_find(ht, index, (void **)&tmp) != FAILURE) {
04655                      return (*tmp);
04656               }
04657        }
04658        return NULL;
04659 }
04660 
04661 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name)
04662 {
04663        sdlFunctionPtr *tmp;
04664 
04665        int len = strlen(function_name);
04666        char *str = estrndup(function_name,len);
04667        php_strtolower(str,len);
04668        if (sdl != NULL) {
04669               if (zend_hash_find(&sdl->functions, str, len+1, (void **)&tmp) != FAILURE) {
04670                      efree(str);
04671                      return (*tmp);
04672               } else if (sdl->requests != NULL && zend_hash_find(sdl->requests, str, len+1, (void **)&tmp) != FAILURE) {
04673                      efree(str);
04674                      return (*tmp);
04675               }
04676        }
04677        efree(str);
04678        return NULL;
04679 }
04680 
04681 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr params)
04682 {
04683        if (sdl) {
04684               sdlFunctionPtr *tmp;
04685               sdlParamPtr    *param;
04686 
04687               zend_hash_internal_pointer_reset(&sdl->functions);
04688               while (zend_hash_get_current_data(&sdl->functions, (void**)&tmp) == SUCCESS) {
04689                      if ((*tmp)->binding && (*tmp)->binding->bindingType == BINDING_SOAP) {
04690                             sdlSoapBindingFunctionPtr fnb = (sdlSoapBindingFunctionPtr)(*tmp)->bindingAttributes;
04691                             if (fnb->style == SOAP_DOCUMENT) {
04692                                    if (params == NULL) {
04693                                           if ((*tmp)->requestParameters == NULL ||
04694                                               zend_hash_num_elements((*tmp)->requestParameters) == 0) {
04695                                             return *tmp;
04696                                           }
04697                                    } else if ((*tmp)->requestParameters != NULL &&
04698                                               zend_hash_num_elements((*tmp)->requestParameters) > 0) {
04699                                           int ok = 1;
04700                                           xmlNodePtr node = params;
04701 
04702                                           zend_hash_internal_pointer_reset((*tmp)->requestParameters);
04703                                           while (zend_hash_get_current_data((*tmp)->requestParameters, (void**)&param) == SUCCESS) {
04704                                                  if ((*param)->element) {
04705                                                         if (strcmp((*param)->element->name, (char*)node->name) != 0) {
04706                                                                ok = 0;
04707                                                                break;
04708                                                         }
04709                                                         if ((*param)->element->namens != NULL && node->ns != NULL) {
04710                                                                if (strcmp((*param)->element->namens, (char*)node->ns->href) != 0) {
04711                                                                       ok = 0;
04712                                                                       break;
04713                                                                }
04714                                                         } else if ((void*)(*param)->element->namens != (void*)node->ns) {
04715                                                                ok = 0;
04716                                                                break;
04717                                                         }
04718                                                  } else if (strcmp((*param)->paramName, (char*)node->name) != 0) {
04719                                                         ok = 0;
04720                                                         break;
04721                                                  }
04722                                                  zend_hash_move_forward((*tmp)->requestParameters);
04723                                                  node = node->next;
04724                                           }
04725                                           if (ok /*&& node == NULL*/) {
04726                                                  return (*tmp);
04727                                           }
04728                                    }
04729                             }
04730                      }
04731                      zend_hash_move_forward(&sdl->functions);
04732               }
04733        }
04734        return NULL;
04735 }
04736 
04737 static void function_to_string(sdlFunctionPtr function, smart_str *buf)
04738 {
04739        int i = 0;
04740        HashPosition pos;
04741        sdlParamPtr *param;
04742 
04743        if (function->responseParameters &&
04744            zend_hash_num_elements(function->responseParameters) > 0) {
04745               if (zend_hash_num_elements(function->responseParameters) == 1) {
04746                      zend_hash_internal_pointer_reset(function->responseParameters);
04747                      zend_hash_get_current_data(function->responseParameters, (void**)&param);
04748                      if ((*param)->encode && (*param)->encode->details.type_str) {
04749                             smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
04750                             smart_str_appendc(buf, ' ');
04751                      } else {
04752                             smart_str_appendl(buf, "UNKNOWN ", 8);
04753                      }
04754               } else {
04755                      i = 0;
04756                      smart_str_appendl(buf, "list(", 5);
04757                      zend_hash_internal_pointer_reset_ex(function->responseParameters, &pos);
04758                      while (zend_hash_get_current_data_ex(function->responseParameters, (void **)&param, &pos) != FAILURE) {
04759                             if (i > 0) {
04760                                    smart_str_appendl(buf, ", ", 2);
04761                             }
04762                             if ((*param)->encode && (*param)->encode->details.type_str) {
04763                                    smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
04764                             } else {
04765                                    smart_str_appendl(buf, "UNKNOWN", 7);
04766                             }
04767                             smart_str_appendl(buf, " $", 2);
04768                             smart_str_appendl(buf, (*param)->paramName, strlen((*param)->paramName));
04769                             zend_hash_move_forward_ex(function->responseParameters, &pos);
04770                             i++;
04771                      }
04772                      smart_str_appendl(buf, ") ", 2);
04773               }
04774        } else {
04775               smart_str_appendl(buf, "void ", 5);
04776        }
04777 
04778        smart_str_appendl(buf, function->functionName, strlen(function->functionName));
04779 
04780        smart_str_appendc(buf, '(');
04781        if (function->requestParameters) {
04782               i = 0;
04783               zend_hash_internal_pointer_reset_ex(function->requestParameters, &pos);
04784               while (zend_hash_get_current_data_ex(function->requestParameters, (void **)&param, &pos) != FAILURE) {
04785                      if (i > 0) {
04786                             smart_str_appendl(buf, ", ", 2);
04787                      }
04788                      if ((*param)->encode && (*param)->encode->details.type_str) {
04789                             smart_str_appendl(buf, (*param)->encode->details.type_str, strlen((*param)->encode->details.type_str));
04790                      } else {
04791                             smart_str_appendl(buf, "UNKNOWN", 7);
04792                      }
04793                      smart_str_appendl(buf, " $", 2);
04794                      smart_str_appendl(buf, (*param)->paramName, strlen((*param)->paramName));
04795                      zend_hash_move_forward_ex(function->requestParameters, &pos);
04796                      i++;
04797               }
04798        }
04799        smart_str_appendc(buf, ')');
04800        smart_str_0(buf);
04801 }
04802 
04803 static void model_to_string(sdlContentModelPtr model, smart_str *buf, int level)
04804 {
04805        int i;
04806 
04807        switch (model->kind) {
04808               case XSD_CONTENT_ELEMENT:
04809                      type_to_string(model->u.element, buf, level);
04810                      smart_str_appendl(buf, ";\n", 2);
04811                      break;
04812               case XSD_CONTENT_ANY:
04813                      for (i = 0;i < level;i++) {
04814                             smart_str_appendc(buf, ' ');
04815                      }
04816                      smart_str_appendl(buf, "<anyXML> any;\n", sizeof("<anyXML> any;\n")-1);
04817                      break;
04818               case XSD_CONTENT_SEQUENCE:
04819               case XSD_CONTENT_ALL:
04820               case XSD_CONTENT_CHOICE: {
04821                      sdlContentModelPtr *tmp;
04822 
04823                      zend_hash_internal_pointer_reset(model->u.content);
04824                      while (zend_hash_get_current_data(model->u.content, (void**)&tmp) == SUCCESS) {
04825                             model_to_string(*tmp, buf, level);
04826                             zend_hash_move_forward(model->u.content);
04827                      }
04828                      break;
04829               }
04830               case XSD_CONTENT_GROUP:
04831                      model_to_string(model->u.group->model, buf, level);
04832               default:
04833                 break;
04834        }
04835 }
04836 
04837 static void type_to_string(sdlTypePtr type, smart_str *buf, int level)
04838 {
04839        int i;
04840        smart_str spaces = {0};
04841        HashPosition pos;
04842 
04843        for (i = 0;i < level;i++) {
04844               smart_str_appendc(&spaces, ' ');
04845        }
04846        smart_str_appendl(buf, spaces.c, spaces.len);
04847 
04848        switch (type->kind) {
04849               case XSD_TYPEKIND_SIMPLE:
04850                      if (type->encode) {
04851                             smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
04852                             smart_str_appendc(buf, ' ');
04853                      } else {
04854                             smart_str_appendl(buf, "anyType ", sizeof("anyType ")-1);
04855                      }
04856                      smart_str_appendl(buf, type->name, strlen(type->name));
04857                      break;
04858               case XSD_TYPEKIND_LIST:
04859                      smart_str_appendl(buf, "list ", 5);
04860                      smart_str_appendl(buf, type->name, strlen(type->name));
04861                      if (type->elements) {
04862                             sdlTypePtr *item_type;
04863 
04864                             smart_str_appendl(buf, " {", 2);
04865                             zend_hash_internal_pointer_reset_ex(type->elements, &pos);
04866                             if (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) {
04867                                    smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name));
04868                             }
04869                             smart_str_appendc(buf, '}');
04870                      }
04871                      break;
04872               case XSD_TYPEKIND_UNION:
04873                      smart_str_appendl(buf, "union ", 6);
04874                      smart_str_appendl(buf, type->name, strlen(type->name));
04875                      if (type->elements) {
04876                             sdlTypePtr *item_type;
04877                             int first = 0;
04878 
04879                             smart_str_appendl(buf, " {", 2);
04880                             zend_hash_internal_pointer_reset_ex(type->elements, &pos);
04881                             while (zend_hash_get_current_data_ex(type->elements, (void **)&item_type, &pos) != FAILURE) {
04882                                    if (!first) {
04883                                           smart_str_appendc(buf, ',');
04884                                           first = 0;
04885                                    }
04886                                    smart_str_appendl(buf, (*item_type)->name, strlen((*item_type)->name));
04887                                    zend_hash_move_forward_ex(type->elements, &pos);
04888                             }
04889                             smart_str_appendc(buf, '}');
04890                      }
04891                      break;
04892               case XSD_TYPEKIND_COMPLEX:
04893               case XSD_TYPEKIND_RESTRICTION:
04894               case XSD_TYPEKIND_EXTENSION:
04895                      if (type->encode &&
04896                          (type->encode->details.type == IS_ARRAY ||
04897                           type->encode->details.type == SOAP_ENC_ARRAY)) {
04898                        sdlAttributePtr *attr;
04899                        sdlExtraAttributePtr *ext;
04900 
04901                             if (type->attributes &&
04902                                 zend_hash_find(type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
04903                                   sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
04904                                   (void **)&attr) == SUCCESS &&
04905                                   zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
04906                                    char *end = strchr((*ext)->val, '[');
04907                                    int len;
04908                                    if (end == NULL) {
04909                                           len = strlen((*ext)->val);
04910                                    } else {
04911                                           len = end-(*ext)->val;
04912                                    }
04913                                    if (len == 0) {
04914                                           smart_str_appendl(buf, "anyType", sizeof("anyType")-1);
04915                                    } else {
04916                                           smart_str_appendl(buf, (*ext)->val, len);
04917                                    }
04918                                    smart_str_appendc(buf, ' ');
04919                                    smart_str_appendl(buf, type->name, strlen(type->name));
04920                                    if (end != NULL) {
04921                                           smart_str_appends(buf, end);
04922                                    }
04923                             } else {
04924                                    sdlTypePtr elementType;
04925                                    if (type->attributes &&
04926                                        zend_hash_find(type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
04927                                          sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
04928                                          (void **)&attr) == SUCCESS &&
04929                                          zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
04930                                           smart_str_appends(buf, (*ext)->val);
04931                                           smart_str_appendc(buf, ' ');
04932                                    } else if (type->elements &&
04933                                               zend_hash_num_elements(type->elements) == 1 &&
04934                                               (zend_hash_internal_pointer_reset(type->elements),
04935                                                zend_hash_get_current_data(type->elements, (void**)&elementType) == SUCCESS) &&
04936                                               (elementType = *(sdlTypePtr*)elementType) != NULL &&
04937                                               elementType->encode && elementType->encode->details.type_str) {
04938                                           smart_str_appends(buf, elementType->encode->details.type_str);
04939                                           smart_str_appendc(buf, ' ');
04940                                    } else {
04941                                           smart_str_appendl(buf, "anyType ", 8);
04942                                    }
04943                                    smart_str_appendl(buf, type->name, strlen(type->name));
04944                                    if (type->attributes &&
04945                                        zend_hash_find(type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
04946                                          sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
04947                                          (void **)&attr) == SUCCESS &&
04948                                          zend_hash_find((*attr)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":arraySize"), (void **)&ext) == SUCCESS) {
04949                                           smart_str_appendc(buf, '[');
04950                                           smart_str_appends(buf, (*ext)->val);
04951                                           smart_str_appendc(buf, ']');
04952                                    } else {
04953                                           smart_str_appendl(buf, "[]", 2);
04954                                    }
04955                             }
04956                      } else {
04957                             smart_str_appendl(buf, "struct ", 7);
04958                             smart_str_appendl(buf, type->name, strlen(type->name));
04959                             smart_str_appendc(buf, ' ');
04960                             smart_str_appendl(buf, "{\n", 2);
04961                             if ((type->kind == XSD_TYPEKIND_RESTRICTION ||
04962                                  type->kind == XSD_TYPEKIND_EXTENSION) && type->encode) {
04963                                    encodePtr enc = type->encode;
04964                                    while (enc && enc->details.sdl_type &&
04965                                           enc != enc->details.sdl_type->encode &&
04966                                           enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
04967                                           enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
04968                                           enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
04969                                           enc = enc->details.sdl_type->encode;
04970                                    }
04971                                    if (enc) {
04972                                           smart_str_appendl(buf, spaces.c, spaces.len);
04973                                           smart_str_appendc(buf, ' ');
04974                                           smart_str_appendl(buf, type->encode->details.type_str, strlen(type->encode->details.type_str));
04975                                           smart_str_appendl(buf, " _;\n", 4);
04976                                    }
04977                             }
04978                             if (type->model) {
04979                                    model_to_string(type->model, buf, level+1);
04980                             }
04981                             if (type->attributes) {
04982                                    sdlAttributePtr *attr;
04983 
04984                                    zend_hash_internal_pointer_reset_ex(type->attributes, &pos);
04985                                    while (zend_hash_get_current_data_ex(type->attributes, (void **)&attr, &pos) != FAILURE) {
04986                                           smart_str_appendl(buf, spaces.c, spaces.len);
04987                                           smart_str_appendc(buf, ' ');
04988                                           if ((*attr)->encode && (*attr)->encode->details.type_str) {
04989                                                  smart_str_appends(buf, (*attr)->encode->details.type_str);
04990                                                  smart_str_appendc(buf, ' ');
04991                                           } else {
04992                                                  smart_str_appendl(buf, "UNKNOWN ", 8);
04993                                           }
04994                                           smart_str_appends(buf, (*attr)->name);
04995                                           smart_str_appendl(buf, ";\n", 2);
04996                                           zend_hash_move_forward_ex(type->attributes, &pos);
04997                                    }
04998                             }
04999                             smart_str_appendl(buf, spaces.c, spaces.len);
05000                             smart_str_appendc(buf, '}');
05001                      }
05002                      break;
05003               default:
05004                      break;
05005        }
05006        smart_str_free(&spaces);
05007        smart_str_0(buf);
05008 }
05009 
05010 static void delete_url(void *handle)
05011 {
05012        php_url_free((php_url*)handle);
05013 }
05014 
05015 static void delete_service(void *data)
05016 {
05017        soapServicePtr service = (soapServicePtr)data;
05018 
05019        if (service->soap_functions.ft) {
05020               zend_hash_destroy(service->soap_functions.ft);
05021               efree(service->soap_functions.ft);
05022        }
05023 
05024        if (service->typemap) {
05025               zend_hash_destroy(service->typemap);
05026               efree(service->typemap);
05027        }
05028 
05029        if (service->soap_class.argc) {
05030               int i;
05031               for (i = 0; i < service->soap_class.argc;i++) {
05032                      zval_ptr_dtor(&service->soap_class.argv[i]);
05033               }
05034               efree(service->soap_class.argv);
05035        }
05036 
05037        if (service->actor) {
05038               efree(service->actor);
05039        }
05040        if (service->uri) {
05041               efree(service->uri);
05042        }
05043        if (service->sdl) {
05044               delete_sdl(service->sdl);
05045        }
05046        if (service->encoding) {
05047               xmlCharEncCloseFunc(service->encoding);
05048        }
05049        if (service->class_map) {
05050               zend_hash_destroy(service->class_map);
05051               FREE_HASHTABLE(service->class_map);
05052        }
05053        if (service->soap_object) {
05054               zval_ptr_dtor(&service->soap_object);
05055        }
05056        efree(service);
05057 }
05058 
05059 static void delete_hashtable(void *data)
05060 {
05061        HashTable *ht = (HashTable*)data;
05062        zend_hash_destroy(ht);
05063        efree(ht);
05064 }