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