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