PHP Cross Reference
Main Menu
/repository/ php-src/ ext/ soap/ soap.c
CVS Log
CVS Blame

changes to
this file in
the last:
day
week
month
  1 /*
  2   +----------------------------------------------------------------------+
  3   | PHP Version 5                                                        |
  4   +----------------------------------------------------------------------+
  5   | Copyright (c) 1997-2008 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.247 2008/07/22 01:46:43 felipe 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 #include "ext/libxml/php_libxml.h"
 31 
 32 typedef struct _soapHeader {
 33         sdlFunctionPtr                    function;
 34         zval                              function_name;
 35         int                               mustUnderstand;
 36         int                               num_params;
 37         zval                            **parameters;
 38         zval                              retval;
 39         sdlSoapBindingFunctionHeaderPtr   hdr;
 40         struct _soapHeader               *next;
 41 } soapHeader;
 42 
 43 /* Local functions */
 44 static void function_to_string(sdlFunctionPtr function, smart_str *buf);
 45 static void type_to_string(sdlTypePtr type, smart_str *buf, int level);
 46 
 47 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);
 48 static void soap_server_fault(char* code, char* string, char *actor, zval* details, char *name TSRMLS_DC);
 49 static void soap_server_fault_ex(sdlFunctionPtr function, zval* fault, soapHeader* hdr TSRMLS_DC);
 50 
 51 static sdlParamPtr get_param(sdlFunctionPtr function, char *param_name, int index, int);
 52 static sdlFunctionPtr get_function(sdlPtr sdl, const char *function_name);
 53 static sdlFunctionPtr get_doc_function(sdlPtr sdl, xmlNodePtr node);
 54 
 55 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);
 56 static xmlDocPtr serialize_response_call(sdlFunctionPtr function, char *function_name,char *uri,zval *ret, soapHeader *headers, int version TSRMLS_DC);
 57 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);
 58 static xmlNodePtr serialize_parameter(sdlParamPtr param,zval *param_val,int index,char *name, int style, xmlNodePtr parent TSRMLS_DC);
 59 static xmlNodePtr serialize_zval(zval *val, sdlParamPtr param, char *paramName, int style, xmlNodePtr parent TSRMLS_DC);
 60 
 61 static void soap_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args);
 62 
 63 #define SOAP_SERVER_BEGIN_CODE() \
 64         zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
 65         char* _old_error_code = SOAP_GLOBAL(error_code);\
 66         zval* _old_error_object = SOAP_GLOBAL(error_object);\
 67         int _old_soap_version = SOAP_GLOBAL(soap_version);\
 68         SOAP_GLOBAL(use_soap_error_handler) = 1;\
 69         SOAP_GLOBAL(error_code) = "Server";\
 70         SOAP_GLOBAL(error_object) = this_ptr;
 71 
 72 #define SOAP_SERVER_END_CODE() \
 73         SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
 74         SOAP_GLOBAL(error_code) = _old_error_code;\
 75         SOAP_GLOBAL(error_object) = _old_error_object;\
 76         SOAP_GLOBAL(soap_version) = _old_soap_version;
 77 
 78 #define SOAP_CLIENT_BEGIN_CODE() \
 79         zend_bool _old_handler = SOAP_GLOBAL(use_soap_error_handler);\
 80         char* _old_error_code = SOAP_GLOBAL(error_code);\
 81         zval* _old_error_object = SOAP_GLOBAL(error_object);\
 82         int _old_soap_version = SOAP_GLOBAL(soap_version);\
 83         zend_bool _old_in_compilation = CG(in_compilation); \
 84         zend_bool _old_in_execution = EG(in_execution); \
 85         zend_execute_data *_old_current_execute_data = EG(current_execute_data); \
 86         int _bailout = 0;\
 87         SOAP_GLOBAL(use_soap_error_handler) = 1;\
 88         SOAP_GLOBAL(error_code) = "Client";\
 89         SOAP_GLOBAL(error_object) = this_ptr;\
 90         zend_try {
 91 
 92 #define SOAP_CLIENT_END_CODE() \
 93         } zend_catch {\
 94                 CG(in_compilation) = _old_in_compilation; \
 95                 EG(in_execution) = _old_in_execution; \
 96                 EG(current_execute_data) = _old_current_execute_data; \
 97                 if (EG(exception) == NULL || \
 98                     Z_TYPE_P(EG(exception)) != IS_OBJECT || \
 99                     !instanceof_function(Z_OBJCE_P(EG(exception)), soap_fault_class_entry TSRMLS_CC)) {\
100                         _bailout = 1;\
101                 }\
102         } zend_end_try();\
103         SOAP_GLOBAL(use_soap_error_handler) = _old_handler;\
104         SOAP_GLOBAL(error_code) = _old_error_code;\
105         SOAP_GLOBAL(error_object) = _old_error_object;\
106         SOAP_GLOBAL(soap_version) = _old_soap_version;\
107         if (_bailout) {\
108                 zend_bailout();\
109         }
110 
111 #define HTTP_RAW_POST_DATA "HTTP_RAW_POST_DATA"
112 
113 #define ZERO_PARAM() \
114         if (zend_parse_parameters_none() == FAILURE) \
115                 return;
116 
117 static zend_class_entry* soap_client_class_entry;
118 static zend_class_entry* soap_server_class_entry;
119 static zend_class_entry* soap_fault_class_entry;
120 static zend_class_entry* soap_header_class_entry;
121 static zend_class_entry* soap_param_class_entry;
122 zend_class_entry* soap_var_class_entry;
123 
124 ZEND_DECLARE_MODULE_GLOBALS(soap)
125 
126 static void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
127 
128 #ifdef va_copy
129 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
130 { \
131         va_list copy; \
132         va_copy(copy, args); \
133         old_error_handler(error_num, error_filename, error_lineno, format, copy); \
134         va_end(copy); \
135 }
136 #else
137 #define call_old_error_handler(error_num, error_filename, error_lineno, format, args) \
138 { \
139         old_error_handler(error_num, error_filename, error_lineno, format, args); \
140 }
141 #endif
142 
143 #define PHP_SOAP_SERVER_CLASSNAME "SoapServer"
144 #define PHP_SOAP_CLIENT_CLASSNAME "SoapClient"
145 #define PHP_SOAP_VAR_CLASSNAME    "SoapVar"
146 #define PHP_SOAP_FAULT_CLASSNAME  "SoapFault"
147 #define PHP_SOAP_PARAM_CLASSNAME  "SoapParam"
148 #define PHP_SOAP_HEADER_CLASSNAME "SoapHeader"
149 
150 PHP_RINIT_FUNCTION(soap);
151 PHP_MINIT_FUNCTION(soap);
152 PHP_MSHUTDOWN_FUNCTION(soap);
153 PHP_MINFO_FUNCTION(soap);
154 
155 /*
156   Registry Functions
157   TODO: this!
158 */
159 PHP_FUNCTION(soap_encode_to_xml);
160 PHP_FUNCTION(soap_encode_to_zval);
161 PHP_FUNCTION(use_soap_error_handler);
162 PHP_FUNCTION(is_soap_fault);
163 
164 
165 /* Server Functions */
166 PHP_METHOD(SoapServer, SoapServer);
167 PHP_METHOD(SoapServer, setClass);
168 PHP_METHOD(SoapServer, setObject);
169 PHP_METHOD(SoapServer, addFunction);
170 PHP_METHOD(SoapServer, getFunctions);
171 PHP_METHOD(SoapServer, handle);
172 PHP_METHOD(SoapServer, setPersistence);
173 PHP_METHOD(SoapServer, fault);
174 PHP_METHOD(SoapServer, addSoapHeader);
175 
176 /* Client Functions */
177 PHP_METHOD(SoapClient, SoapClient);
178 PHP_METHOD(SoapClient, __call);
179 PHP_METHOD(SoapClient, __getLastRequest);
180 PHP_METHOD(SoapClient, __getLastResponse);
181 PHP_METHOD(SoapClient, __getLastRequestHeaders);
182 PHP_METHOD(SoapClient, __getLastResponseHeaders);
183 PHP_METHOD(SoapClient, __getFunctions);
184 PHP_METHOD(SoapClient, __getTypes);
185 PHP_METHOD(SoapClient, __doRequest);
186 PHP_METHOD(SoapClient, __setCookie);
187 PHP_METHOD(SoapClient, __getCookies);
188 PHP_METHOD(SoapClient, __setLocation);
189 PHP_METHOD(SoapClient, __setSoapHeaders);
190 
191 /* SoapVar Functions */
192 PHP_METHOD(SoapVar, SoapVar);
193 
194 /* SoapFault Functions */
195 PHP_METHOD(SoapFault, SoapFault);
196 PHP_METHOD(SoapFault, __toString);
197 
198 /* SoapParam Functions */
199 PHP_METHOD(SoapParam, SoapParam);
200 
201 /* SoapHeader Functions */
202 PHP_METHOD(SoapHeader, SoapHeader);
203 
204 #define SOAP_CTOR(class_name, func_name, arginfo, flags) ZEND_FENTRY(__construct, ZEND_MN(class_name##_##func_name), arginfo, flags)
205 
206 /* {{{ arginfo */
207 static
208 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapparam_soapparam, 0, 0, 2)
209         ZEND_ARG_INFO(0, data)
210         ZEND_ARG_INFO(0, name)
211 ZEND_END_ARG_INFO()
212 
213 static
214 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapheader_soapheader, 0, 0, 2)
215         ZEND_ARG_INFO(0, namespace)
216         ZEND_ARG_INFO(0, name)
217         ZEND_ARG_INFO(0, data)
218         ZEND_ARG_INFO(0, mustunderstand)
219         ZEND_ARG_INFO(0, actor)
220 ZEND_END_ARG_INFO()
221 
222 static
223 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapfault_soapfault, 0, 0, 2)
224         ZEND_ARG_INFO(0, faultcode)
225         ZEND_ARG_INFO(0, faultstring)
226         ZEND_ARG_INFO(0, faultactor)
227         ZEND_ARG_INFO(0, detail)
228         ZEND_ARG_INFO(0, faultname)
229         ZEND_ARG_INFO(0, headerfault)
230 ZEND_END_ARG_INFO()
231 
232 static
233 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapvar_soapvar, 0, 0, 2)
234         ZEND_ARG_INFO(0, data)
235         ZEND_ARG_INFO(0, encoding)
236         ZEND_ARG_INFO(0, type_name)
237         ZEND_ARG_INFO(0, type_namespace)
238         ZEND_ARG_INFO(0, node_name)
239         ZEND_ARG_INFO(0, node_namespace)
240 ZEND_END_ARG_INFO()
241 
242 static
243 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_fault, 0, 0, 2)
244         ZEND_ARG_INFO(0, code)
245         ZEND_ARG_INFO(0, string)
246         ZEND_ARG_INFO(0, actor)
247         ZEND_ARG_INFO(0, details)
248         ZEND_ARG_INFO(0, name)
249 ZEND_END_ARG_INFO()
250 
251 static
252 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addsoapheader, 0, 0, 1)
253         ZEND_ARG_INFO(0, object)
254 ZEND_END_ARG_INFO()
255 
256 static
257 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_soapserver, 0, 0, 1)
258         ZEND_ARG_INFO(0, wsdl)
259         ZEND_ARG_INFO(0, options)
260 ZEND_END_ARG_INFO()
261 
262 static
263 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setpersistence, 0, 0, 1)
264         ZEND_ARG_INFO(0, mode)
265 ZEND_END_ARG_INFO()
266 
267 static
268 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setclass, 0, 0, 1)
269         ZEND_ARG_INFO(0, class_name)
270         ZEND_ARG_INFO(0, args)
271 ZEND_END_ARG_INFO()
272 
273 static
274 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_setobject, 0, 0, 1)
275         ZEND_ARG_INFO(0, object)
276 ZEND_END_ARG_INFO()
277 
278 static
279 ZEND_BEGIN_ARG_INFO(arginfo_soapserver_getfunctions, 0)
280 ZEND_END_ARG_INFO()
281 
282 static
283 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_addfunction, 0, 0, 1)
284         ZEND_ARG_INFO(0, functions)
285 ZEND_END_ARG_INFO()
286 
287 static
288 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapserver_handle, 0, 0, 0)
289         ZEND_ARG_INFO(0, soap_request)
290 ZEND_END_ARG_INFO()
291 
292 static
293 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient_soapclient, 0, 0, 1)
294         ZEND_ARG_INFO(0, wsdl)
295         ZEND_ARG_INFO(0, options)
296 ZEND_END_ARG_INFO()
297 
298 static
299 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___call, 0, 0, 2)
300         ZEND_ARG_INFO(0, function_name)
301         ZEND_ARG_INFO(0, arguments)
302 ZEND_END_ARG_INFO()
303 
304 static
305 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___soapcall, 0, 0, 2)
306         ZEND_ARG_INFO(0, function_name)
307         ZEND_ARG_INFO(0, arguments)
308         ZEND_ARG_INFO(0, options)
309         ZEND_ARG_INFO(0, input_headers)
310         ZEND_ARG_INFO(1, output_headers)
311 ZEND_END_ARG_INFO()
312 
313 static
314 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getfunctions, 0)
315 ZEND_END_ARG_INFO()
316 
317 static
318 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___gettypes, 0)
319 ZEND_END_ARG_INFO()
320 
321 static
322 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequest, 0)
323 ZEND_END_ARG_INFO()
324 
325 static
326 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponse, 0)
327 ZEND_END_ARG_INFO()
328 
329 static
330 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastrequestheaders, 0)
331 ZEND_END_ARG_INFO()
332 
333 static
334 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getlastresponseheaders, 0)
335 ZEND_END_ARG_INFO()
336 
337 static
338 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___dorequest, 0, 0, 4)
339         ZEND_ARG_INFO(0, request)
340         ZEND_ARG_INFO(0, location)
341         ZEND_ARG_INFO(0, action)
342         ZEND_ARG_INFO(0, version)
343         ZEND_ARG_INFO(0, one_way)
344 ZEND_END_ARG_INFO()
345 
346 static
347 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setcookie, 0, 0, 1)
348         ZEND_ARG_INFO(0, name)
349         ZEND_ARG_INFO(0, value)
350 ZEND_END_ARG_INFO()
351 
352 static
353 ZEND_BEGIN_ARG_INFO(arginfo_soapclient___getcookie, 0)
354 ZEND_END_ARG_INFO()
355 
356 static
357 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setsoapheaders, 0, 0, 1)
358         ZEND_ARG_INFO(0, soapheaders)
359 ZEND_END_ARG_INFO()
360 
361 static
362 ZEND_BEGIN_ARG_INFO_EX(arginfo_soapclient___setlocation, 0, 0, 0)
363         ZEND_ARG_INFO(0, new_location)
364 ZEND_END_ARG_INFO()
365 
366 static 
367 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_use_soap_error_handler, 0, 0, 0)
368         ZEND_ARG_INFO(0, handler)
369 ZEND_END_ARG_INFO()
370 
371 static 
372 ZEND_BEGIN_ARG_INFO_EX(arginfo_soap_is_soap_fault, 0, 0, 1)
373         ZEND_ARG_INFO(0, object)
374 ZEND_END_ARG_INFO()
375 /* }}} */
376 
377 static const zend_function_entry soap_functions[] = {
378         PHP_FE(use_soap_error_handler,  arginfo_soap_use_soap_error_handler)
379         PHP_FE(is_soap_fault,                   arginfo_soap_is_soap_fault)
380         {NULL, NULL, NULL}
381 };
382 
383 static const zend_function_entry soap_fault_functions[] = {
384         SOAP_CTOR(SoapFault, SoapFault, arginfo_soapfault_soapfault, 0)
385         PHP_ME(SoapFault, __toString, NULL, 0)
386         {NULL, NULL, NULL}
387 };
388 
389 static const zend_function_entry soap_server_functions[] = {
390         SOAP_CTOR(SoapServer, SoapServer,       arginfo_soapserver_soapserver, 0)
391         PHP_ME(SoapServer, setPersistence,      arginfo_soapserver_setpersistence, 0)
392         PHP_ME(SoapServer, setClass,            arginfo_soapserver_setclass, 0)
393         PHP_ME(SoapServer, setObject,           arginfo_soapserver_setobject, 0)
394         PHP_ME(SoapServer, addFunction,         arginfo_soapserver_addfunction, 0)
395         PHP_ME(SoapServer, getFunctions,        arginfo_soapserver_getfunctions, 0)
396         PHP_ME(SoapServer, handle,                      arginfo_soapserver_handle, 0)
397         PHP_ME(SoapServer, fault,                       arginfo_soapserver_fault, 0)
398         PHP_ME(SoapServer, addSoapHeader,       arginfo_soapserver_addsoapheader, 0)
399         {NULL, NULL, NULL}
400 };
401 
402 static const zend_function_entry soap_client_functions[] = {
403         SOAP_CTOR(SoapClient, SoapClient, arginfo_soapclient_soapclient, 0)
404         PHP_ME(SoapClient, __call, arginfo_soapclient___call, 0)
405         ZEND_FENTRY(__soapCall, ZEND_MN(SoapClient___call), arginfo_soapclient___soapcall, 0)
406         PHP_ME(SoapClient, __getLastRequest,                    arginfo_soapclient___getlastrequest, 0)
407         PHP_ME(SoapClient, __getLastResponse,                   arginfo_soapclient___getlastresponse, 0)
408         PHP_ME(SoapClient, __getLastRequestHeaders,             arginfo_soapclient___getlastrequestheaders, 0)
409         PHP_ME(SoapClient, __getLastResponseHeaders,    arginfo_soapclient___getlastresponseheaders, 0)
410         PHP_ME(SoapClient, __getFunctions,                              arginfo_soapclient___getfunctions, 0)
411         PHP_ME(SoapClient, __getTypes,                                  arginfo_soapclient___gettypes, 0)
412         PHP_ME(SoapClient, __doRequest,                                 arginfo_soapclient___dorequest, 0)
413         PHP_ME(SoapClient, __setCookie,                                 arginfo_soapclient___setcookie, 0)
414         PHP_ME(SoapClient, __getCookies,                                arginfo_soapclient___getcookie, 0)
415         PHP_ME(SoapClient, __setLocation,                               arginfo_soapclient___setlocation, 0)
416         PHP_ME(SoapClient, __setSoapHeaders,                    arginfo_soapclient___setsoapheaders, 0)
417         {NULL, NULL, NULL}
418 };
419 
420 static const zend_function_entry soap_var_functions[] = {
421         SOAP_CTOR(SoapVar, SoapVar, arginfo_soapvar_soapvar, 0)
422         {NULL, NULL, NULL}
423 };
424 
425 static const zend_function_entry soap_param_functions[] = {
426         SOAP_CTOR(SoapParam, SoapParam, arginfo_soapparam_soapparam, 0)
427         {NULL, NULL, NULL}
428 };
429 
430 static const zend_function_entry soap_header_functions[] = {
431         SOAP_CTOR(SoapHeader, SoapHeader, arginfo_soapheader_soapheader, 0)
432         {NULL, NULL, NULL}
433 };
434 
435 zend_module_entry soap_module_entry = {
436 #ifdef STANDARD_MODULE_HEADER
437   STANDARD_MODULE_HEADER,
438 #endif
439   "soap",
440   soap_functions,
441   PHP_MINIT(soap),
442   PHP_MSHUTDOWN(soap),
443   PHP_RINIT(soap),
444   NULL,
445   PHP_MINFO(soap),
446 #ifdef STANDARD_MODULE_HEADER
447   NO_VERSION_YET,
448 #endif
449   STANDARD_MODULE_PROPERTIES,
450 };
451 
452 #ifdef COMPILE_DL_SOAP
453 ZEND_GET_MODULE(soap)
454 #endif
455 
456 char* soap_unicode_to_string(UChar *ustr, int ustr_len TSRMLS_DC)
457 {
458         int dummy;
459 
460         return php_libxml_unicode_to_string(ustr, ustr_len, &dummy TSRMLS_CC);
461 }
462 
463 void soap_decode_string(zval *ret, char* str TSRMLS_DC)
464 {
465         if (UG(unicode)) {
466                 /* TODO: unicode support */
467                 ZVAL_STRING(ret, str, 1);
468                 zval_string_to_unicode_ex(ret, UG(utf8_conv) TSRMLS_CC);
469         } else if (SOAP_GLOBAL(encoding) != NULL) {
470                 xmlBufferPtr in  = xmlBufferCreateStatic(str, strlen(str));
471                 xmlBufferPtr out = xmlBufferCreate();
472                 int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
473 
474                 if (n >= 0) {
475                         ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
476                 } else {
477                         ZVAL_STRING(ret, str, 1);
478                 }
479                 xmlBufferFree(out);
480                 xmlBufferFree(in);
481         } else {
482                 ZVAL_STRING(ret, str, 1);
483         }
484 }
485 
486 char* soap_encode_string_ex(zend_uchar type, zstr data, int len TSRMLS_DC)
487 {
488         char *str;
489         int new_len;
490 
491         if (type == IS_UNICODE) {
492                 str = soap_unicode_to_string(data.u, len TSRMLS_CC);
493         } else {
494                 str = estrndup(data.s, len);
495                 new_len = len;
496 
497                 if (SOAP_GLOBAL(encoding) != NULL) {
498                         xmlBufferPtr in  = xmlBufferCreateStatic(str, new_len);
499                         xmlBufferPtr out = xmlBufferCreate();
500                         int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
501 
502                         if (n >= 0) {
503                                 efree(str);
504                                 str = estrdup((char*)xmlBufferContent(out));
505                         }
506                         xmlBufferFree(out);
507                         xmlBufferFree(in);
508                 }
509                 if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
510                         char *err = emalloc(new_len + 8);
511                         char c;
512                         int i;
513                 
514                         memcpy(err, str, new_len+1);
515                         for (i = 0; (c = err[i++]);) {
516                                 if ((c & 0x80) == 0) {
517                                 } else if ((c & 0xe0) == 0xc0) {
518                                         if ((err[i] & 0xc0) != 0x80) {
519                                                 break;
520                                         }
521                                         i++;
522                                 } else if ((c & 0xf0) == 0xe0) {
523                                         if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80) {
524                                                 break;
525                                         }
526                                         i += 2;
527                                 } else if ((c & 0xf8) == 0xf0) {
528                                         if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80 || (err[i+2] & 0xc0) != 0x80) {
529                                                 break;
530                                         }
531                                         i += 3;
532                                 } else {
533                                         break;
534                                 }
535                         }
536                         if (c) {
537                                 err[i-1] = '\\';
538                                 err[i++] = 'x';
539                                 err[i++] = ((unsigned char)c >> 4) + ((((unsigned char)c >> 4) > 9) ? ('a' - 10) : '');
540                                 err[i++] = (c & 15) + (((c & 15) > 9) ? ('a' - 10) : '');
541                                 err[i++] = '.';
542                                 err[i++] = '.';
543                                 err[i++] = '.';
544                                 err[i++] = 0;
545                         }
546 
547                         soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", err);
548                 }
549         }
550         return str;
551 }
552 
553 char* soap_encode_string(zval *data, int* len TSRMLS_DC)
554 {
555         char *str;
556         int new_len;
557 
558         if (Z_TYPE_P(data) == IS_UNICODE) {
559                 str = soap_unicode_to_string(Z_USTRVAL_P(data), Z_USTRLEN_P(data) TSRMLS_CC);
560                 new_len = strlen(str);
561         } else {
562                 if (Z_TYPE_P(data) == IS_STRING) {
563                         str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
564                         new_len = Z_STRLEN_P(data);
565                 } else {
566                         zval tmp = *data;
567 
568                         zval_copy_ctor(&tmp);
569                         convert_to_string(&tmp);
570                         str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
571                         new_len = Z_STRLEN(tmp);
572                         zval_dtor(&tmp);
573                 }
574 
575                 if (SOAP_GLOBAL(encoding) != NULL) {
576                         xmlBufferPtr in  = xmlBufferCreateStatic(str, new_len);
577                         xmlBufferPtr out = xmlBufferCreate();
578                         int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
579 
580                         if (n >= 0) {
581                                 efree(str);
582                                 str = estrdup((char*)xmlBufferContent(out));
583                                 new_len = n;
584                         }
585                         xmlBufferFree(out);
586                         xmlBufferFree(in);
587                 }
588                 if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
589                         char *err = emalloc(new_len + 8);
590                         char c;
591                         int i;
592                 
593                         memcpy(err, str, new_len+1);
594                         for (i = 0; (c = err[i++]);) {
595                                 if ((c & 0x80) == 0) {
596                                 } else if ((c & 0xe0) == 0xc0) {
597                                         if ((err[i] & 0xc0) != 0x80) {
598                                                 break;
599                                         }
600                                         i++;
601                                 } else if ((c & 0xf0) == 0xe0) {
602                                         if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80) {
603                                                 break;
604                                         }
605                                         i += 2;
606                                 } else if ((c & 0xf8) == 0xf0) {
607                                         if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80 || (err[i+2] & 0xc0) != 0x80) {
608                                                 break;
609                                         }
610                                         i += 3;
611                                 } else {
612                                         break;
613                                 }
614                         }
615                         if (c) {
616                                 err[i-1] = '\\';
617                                 err[i++] = 'x';
618                                 err[i++] = ((unsigned char)c >> 4) + ((((unsigned char)c >> 4) > 9) ? ('a' - 10) : '');
619                                 err[i++] = (c & 15) + (((c & 15) > 9) ? ('a' - 10) : '');
620                                 err[i++] = '.';
621                                 err[i++] = '.';
622                                 err[i++] = '.';
623                                 err[i++] = 0;
624                         }
625 
626                         soap_error1(E_ERROR,  "Encoding: string '%s' is not a valid utf-8 string", err);
627                 }
628         }
629         if (len) {
630                 *len = new_len;
631         }
632         return str;
633 }
634 
635 ZEND_INI_MH(OnUpdateCacheEnabled)
636 {
637         if (OnUpdateBool(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC) == FAILURE) {
638                 return FAILURE;
639         }
640         if (SOAP_GLOBAL(cache_enabled)) {
641                 SOAP_GLOBAL(cache) = SOAP_GLOBAL(cache_mode);
642         } else {
643                 SOAP_GLOBAL(cache) = 0;
644         }
645         return SUCCESS;
646 }
647 
648 ZEND_INI_MH(OnUpdateCacheMode)
649 {
650         char *p;
651 #ifndef ZTS
652         char *base = (char *) mh_arg2;
653 #else
654         char *base = (char *) ts_resource(*((int *) mh_arg2));
655 #endif
656 
657         p = (char*) (base+(size_t) mh_arg1);
658 
659         *p = (char)atoi(new_value);
660 
661         if (SOAP_GLOBAL(cache_enabled)) {
662                 SOAP_GLOBAL(cache) = SOAP_GLOBAL(cache_mode);
663         } else {
664                 SOAP_GLOBAL(cache) = 0;
665         }
666         return SUCCESS;
667 }
668 
669 PHP_INI_BEGIN()
670 STD_PHP_INI_ENTRY("soap.wsdl_cache_enabled",     "1", PHP_INI_ALL, OnUpdateCacheEnabled,
671                   cache_enabled, zend_soap_globals, soap_globals)
672 STD_PHP_INI_ENTRY("soap.wsdl_cache_dir",         "/tmp", PHP_INI_ALL, OnUpdateString,
673                   cache_dir, zend_soap_globals, soap_globals)
674 STD_PHP_INI_ENTRY("soap.wsdl_cache_ttl",         "86400", PHP_INI_ALL, OnUpdateLong,
675                   cache_ttl, zend_soap_globals, soap_globals)
676 STD_PHP_INI_ENTRY("soap.wsdl_cache",             "1", PHP_INI_ALL, OnUpdateCacheMode,
677                   cache_mode, zend_soap_globals, soap_globals)
678 STD_PHP_INI_ENTRY("soap.wsdl_cache_limit",       "5", PHP_INI_ALL, OnUpdateLong,
679                   cache_limit, zend_soap_globals, soap_globals)
680 PHP_INI_END()
681 
682 static HashTable defEnc, defEncIndex, defEncNs;
683 
684 static void php_soap_prepare_globals()
685 {
686         int i;
687         encodePtr enc;
688 
689         zend_hash_init(&defEnc, 0, NULL, NULL, 1);
690         zend_hash_init(&defEncIndex, 0, NULL, NULL, 1);
691         zend_hash_init(&defEncNs, 0, NULL, NULL, 1);
692 
693         i = 0;
694         do {
695                 enc = &defaultEncoding[i];
696 
697                 /* If has a ns and a str_type then index it */
698                 if (defaultEncoding[i].details.type_str) {
699                         if (defaultEncoding[i].details.ns != NULL) {
700                                 char *ns_type;
701                                 spprintf(&ns_type, 0, "%s:%s", defaultEncoding[i].details.ns, defaultEncoding[i].details.type_str);
702                                 zend_hash_add(&defEnc, ns_type, strlen(ns_type) + 1, &enc, sizeof(encodePtr), NULL);
703                                 efree(ns_type);
704                         } else {
705                                 zend_hash_add(&defEnc, defaultEncoding[i].details.type_str, strlen(defaultEncoding[i].details.type_str) + 1, &enc, sizeof(encodePtr), NULL);
706                         }
707                 }
708                 /* Index everything by number */
709                 if (!zend_hash_index_exists(&defEncIndex, defaultEncoding[i].details.type)) {
710                         zend_hash_index_update(&defEncIndex, defaultEncoding[i].details.type, &enc, sizeof(encodePtr), NULL);
711                 }
712                 i++;
713         } while (defaultEncoding[i].details.type != END_KNOWN_TYPES);
714 
715         /* hash by namespace */
716         zend_hash_add(&defEncNs, XSD_1999_NAMESPACE, sizeof(XSD_1999_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
717         zend_hash_add(&defEncNs, XSD_NAMESPACE, sizeof(XSD_NAMESPACE), XSD_NS_PREFIX, sizeof(XSD_NS_PREFIX), NULL);
718         zend_hash_add(&defEncNs, XSI_NAMESPACE, sizeof(XSI_NAMESPACE), XSI_NS_PREFIX, sizeof(XSI_NS_PREFIX), NULL);
719         zend_hash_add(&defEncNs, XML_NAMESPACE, sizeof(XML_NAMESPACE), XML_NS_PREFIX, sizeof(XML_NS_PREFIX), NULL);
720         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);
721         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);
722 }
723 
724 static void php_soap_init_globals(zend_soap_globals *soap_globals TSRMLS_DC)
725 {
726         soap_globals->defEnc = defEnc;
727         soap_globals->defEncIndex = defEncIndex;
728         soap_globals->defEncNs = defEncNs;
729         soap_globals->typemap = NULL;
730         soap_globals->use_soap_error_handler = 0;
731         soap_globals->error_code = NULL;
732         soap_globals->error_object = NULL;
733         soap_globals->sdl = NULL;
734         soap_globals->soap_version = SOAP_1_1;
735         soap_globals->mem_cache = NULL;
736         soap_globals->ref_map = NULL;
737 }
738 
739 PHP_MSHUTDOWN_FUNCTION(soap)
740 {
741         zend_error_cb = old_error_handler;
742         zend_hash_destroy(&SOAP_GLOBAL(defEnc));
743         zend_hash_destroy(&SOAP_GLOBAL(defEncIndex));
744         zend_hash_destroy(&SOAP_GLOBAL(defEncNs));
745         if (SOAP_GLOBAL(mem_cache)) {
746                 zend_hash_destroy(SOAP_GLOBAL(mem_cache));
747                 free(SOAP_GLOBAL(mem_cache));
748         }
749         UNREGISTER_INI_ENTRIES();
750         return SUCCESS;
751 }
752 
753 PHP_RINIT_FUNCTION(soap)
754 {
755         SOAP_GLOBAL(typemap) = NULL;
756         SOAP_GLOBAL(use_soap_error_handler) = 0;
757         SOAP_GLOBAL(error_code) = NULL;
758         SOAP_GLOBAL(error_object) = NULL;
759         SOAP_GLOBAL(sdl) = NULL;
760         SOAP_GLOBAL(soap_version) = SOAP_1_1;
761         SOAP_GLOBAL(encoding) = NULL;
762         SOAP_GLOBAL(class_map) = NULL;
763         SOAP_GLOBAL(features) = 0;
764         SOAP_GLOBAL(ref_map) = NULL;
765         return SUCCESS;
766 }
767 
768 static void soap_server_dtor(void *object, zend_object_handle handle TSRMLS_DC)
769 {
770         soap_server_object *service = (soap_server_object*)object;
771 
772         if (service->soap_functions.ft) {
773                 zend_hash_destroy(service->soap_functions.ft);
774                 efree(service->soap_functions.ft);
775         }
776 
777         if (service->typemap) {
778                 zend_hash_destroy(service->typemap);
779                 efree(service->typemap);
780         }
781 
782         if (service->soap_class.argc) {
783                 int i;
784                 for (i = 0; i < service->soap_class.argc;i++) {
785                         zval_ptr_dtor(&service->soap_class.argv[i]);
786                 }
787                 efree(service->soap_class.argv);
788         }
789 
790         if (service->actor) {
791                 efree(service->actor);
792         }
793         if (service->uri) {
794                 efree(service->uri);
795         }
796         if (service->sdl) {
797                 delete_sdl(service->sdl);
798         }
799         if (service->encoding) {
800                 xmlCharEncCloseFunc(service->encoding);
801         }
802         if (service->class_map) {
803                 zend_hash_destroy(service->class_map);
804                 FREE_HASHTABLE(service->class_map);
805         }
806         if (service->soap_object) {
807                 zval_ptr_dtor(&service->soap_object);
808         }
809         zend_object_std_dtor(object TSRMLS_CC);
810         efree(object);
811 }
812 
813 static zend_object_value soap_server_ctor(zend_class_entry *ce TSRMLS_DC)
814 {
815         zend_object_value new_value;
816         soap_server_object *obj = (soap_server_object*)emalloc(sizeof(soap_server_object));
817 
818         memset(obj, 0, sizeof(soap_server_object));
819 
820         zend_object_std_init(&obj->zo, ce TSRMLS_CC);
821 
822         obj->sdl = NULL;
823         obj->uri = NULL;
824         obj->typemap = NULL;
825         obj->version = SOAP_1_1;
826         obj->class_map = NULL;
827         obj->features = 0;
828         obj->encoding = NULL;
829 
830         obj->soap_functions.ft = NULL;
831         obj->soap_functions.functions_all = 1;
832 
833         obj->soap_class.ce = NULL;
834         obj->soap_class.argv = NULL;
835         obj->soap_class.argc = 0;
836         obj->soap_class.persistance = SOAP_PERSISTENCE_REQUEST;
837 
838         obj->type = SOAP_MAP_FUNCTION;
839         obj->actor = NULL;
840         obj->soap_headers_ptr = NULL;
841 
842         new_value.handle = zend_objects_store_put(obj, soap_server_dtor, NULL, NULL TSRMLS_CC);
843         new_value.handlers = zend_get_std_object_handlers();
844 
845         return new_value;
846 }
847 
848 static void soap_client_dtor(void *object, zend_object_handle handle TSRMLS_DC)
849 {
850         soap_client_object *client = (soap_client_object*)object;
851 
852         if (client->typemap) {
853                 zend_hash_destroy(client->typemap);
854                 efree(client->typemap);
855         }
856         if (client->uri) {
857                 efree(client->uri);
858         }
859         if (client->sdl) {
860                 delete_sdl(client->sdl);
861         }
862         if (client->encoding) {
863                 xmlCharEncCloseFunc(client->encoding);
864         }
865         if (client->class_map) {
866                 zend_hash_destroy(client->class_map);
867                 FREE_HASHTABLE(client->class_map);
868         }
869         if (client->location) {
870                 efree(client->location);
871         }
872         if (client->login) {
873                 efree(client->login);
874         }
875         if (client->password) {
876                 efree(client->password);
877         }
878         if (client->digest_realm) {
879                 efree(client->digest_realm);
880         }
881         if (client->digest_algorithm) {
882                 efree(client->digest_algorithm);
883