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