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