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