diff GEMBASSY-1.0.3/gsoap/stdsoap2.c @ 0:8300eb051bea draft

Initial upload
author ktnyt
date Fri, 26 Jun 2015 05:19:29 -0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GEMBASSY-1.0.3/gsoap/stdsoap2.c	Fri Jun 26 05:19:29 2015 -0400
@@ -0,0 +1,16999 @@
+/*
+	stdsoap2.c[pp] 2.8.17r
+
+	gSOAP runtime engine
+
+gSOAP XML Web services tools
+Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
+This part of the software is released under ONE of the following licenses:
+GPL, or the gSOAP public license, or Genivia's license for commercial use.
+--------------------------------------------------------------------------------
+Contributors:
+
+Wind River Systems Inc., for the following additions under gSOAP public license:
+  - vxWorks compatible options
+--------------------------------------------------------------------------------
+gSOAP public license.
+
+The contents of this file are subject to the gSOAP Public License Version 1.3
+(the "License"); you may not use this file except in compliance with the
+License. You may obtain a copy of the License at
+http://www.cs.fsu.edu/~engelen/soaplicense.html
+Software distributed under the License is distributed on an "AS IS" basis,
+WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+for the specific language governing rights and limitations under the License.
+
+The Initial Developer of the Original Code is Robert A. van Engelen.
+Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
+--------------------------------------------------------------------------------
+GPL license.
+
+This program is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation; either version 2 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+Place, Suite 330, Boston, MA 02111-1307 USA
+
+Author contact information:
+engelen@genivia.com / engelen@acm.org
+
+This program is released under the GPL with the additional exemption that
+compiling, linking, and/or using OpenSSL is allowed.
+--------------------------------------------------------------------------------
+A commercial use license is available from Genivia, Inc., contact@genivia.com
+--------------------------------------------------------------------------------
+*/
+
+#define GSOAP_LIB_VERSION 20817
+
+#ifdef AS400
+# pragma convert(819)	/* EBCDIC to ASCII */
+#endif
+
+#include "stdsoap2.h"
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+#include <ipcom_key_db.h>
+#endif
+#if GSOAP_VERSION != GSOAP_LIB_VERSION
+# error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE"
+#endif
+
+#ifdef __BORLANDC__
+# pragma warn -8060
+#else
+# ifdef WIN32
+#  ifdef UNDER_CE
+#   pragma comment(lib, "ws2.lib")	/* WinCE */
+#  else
+#   pragma comment(lib, "ws2_32.lib")
+#  endif
+#  pragma warning(disable : 4996) /* disable deprecation warnings */
+# endif
+#endif
+
+#ifdef __cplusplus
+SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.17r 2013-12-18 00:00:00 GMT")
+extern "C" {
+#else
+SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.17r 2013-12-18 00:00:00 GMT")
+#endif
+
+/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
+#ifndef SOAP_UNKNOWN_CHAR
+#define SOAP_UNKNOWN_CHAR (127)
+#endif
+
+/*      EOF=-1 */
+#define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */
+#define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */
+#define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */
+#define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */
+#define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */
+
+#define soap_blank(c)		((c)+1 > 0 && (c) <= 32)
+#define soap_notblank(c)	((c) > 32)
+
+#if defined(WIN32) && !defined(UNDER_CE)
+#define soap_hash_ptr(p)	((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
+#else
+#define soap_hash_ptr(p)	((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
+#endif
+
+#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
+static void soap_init_logs(struct soap*);
+#endif
+#ifdef SOAP_DEBUG
+static void soap_close_logfile(struct soap*, int);
+static void soap_set_logfile(struct soap*, int, const char*);
+#endif
+
+#ifdef SOAP_MEM_DEBUG
+static void soap_init_mht(struct soap*);
+static void soap_free_mht(struct soap*);
+static void soap_track_unlink(struct soap*, const void*);
+#endif
+
+#ifndef PALM_2
+static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
+static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
+static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
+#endif
+
+#ifndef PALM_1
+static void soap_free_ns(struct soap *soap);
+static soap_wchar soap_char(struct soap*);
+static soap_wchar soap_get_pi(struct soap*);
+static int soap_isxdigit(int);
+static void *fplugin(struct soap*, const char*);
+static size_t soap_count_attachments(struct soap *soap);
+static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
+#ifdef WITH_NTLM
+static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port);
+#endif
+#ifndef WITH_NOIDREF
+static int soap_has_copies(struct soap*, const char*, const char*);
+static void soap_init_iht(struct soap*);
+static void soap_free_iht(struct soap*);
+static void soap_init_pht(struct soap*);
+static void soap_free_pht(struct soap*);
+#endif
+#endif
+
+#ifndef WITH_LEAN
+static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
+static int soap_isnumeric(struct soap*, const char*);
+static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
+static void soap_utilize_ns(struct soap *soap, const char *tag);
+#endif
+
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
+static int soap_putdimefield(struct soap*, const char*, size_t);
+static char *soap_getdimefield(struct soap*, size_t);
+static void soap_select_mime_boundary(struct soap*);
+static int soap_valid_mime_boundary(struct soap*);
+static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
+#endif
+#endif
+
+#ifdef WITH_GZIP
+static int soap_getgziphdr(struct soap*);
+#endif
+
+#ifdef WITH_OPENSSL
+# ifndef SOAP_SSL_RSA_BITS
+#  define SOAP_SSL_RSA_BITS 2048
+# endif
+static int soap_ssl_init_done = 0;
+static int ssl_auth_init(struct soap*);
+static int ssl_verify_callback(int, X509_STORE_CTX*);
+static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
+static int ssl_password(char*, int, int, void *);
+#endif
+
+#ifdef WITH_GNUTLS
+# ifndef SOAP_SSL_RSA_BITS
+#  define SOAP_SSL_RSA_BITS 2048
+# endif
+static int soap_ssl_init_done = 0;
+static const char *ssl_verify(struct soap *soap, const char *host);
+# if defined(HAVE_PTHREAD_H)
+#  include <pthread.h>
+   /* make GNUTLS thread safe with pthreads */
+   GCRY_THREAD_OPTION_PTHREAD_IMPL;
+# elif defined(HAVE_PTH_H)
+   #include <pth.h>
+   /* make GNUTLS thread safe with PTH */
+   GCRY_THREAD_OPTION_PTH_IMPL;
+# endif
+#endif
+
+#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
+#ifndef PALM_1
+static const char *soap_decode(char*, size_t, const char*, const char*);
+#endif
+#endif
+
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static soap_wchar soap_getchunkchar(struct soap*);
+static const char *http_error(struct soap*, int);
+static int http_get(struct soap*);
+static int http_405(struct soap*);
+static int http_200(struct soap*);
+static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
+static int http_send_header(struct soap*, const char*);
+static int http_post_header(struct soap*, const char*, const char*);
+static int http_response(struct soap*, int, size_t);
+static int http_parse(struct soap*);
+static int http_parse_header(struct soap*, const char*, const char*);
+#endif
+#endif
+
+#ifndef WITH_NOIO
+
+#ifndef PALM_1
+static int fsend(struct soap*, const char*, size_t);
+static size_t frecv(struct soap*, char*, size_t);
+static int tcp_init(struct soap*);
+static const char *tcp_error(struct soap*);
+#ifndef WITH_IPV6
+static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
+#endif
+static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
+static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
+static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
+static int tcp_disconnect(struct soap*);
+static int tcp_closesocket(struct soap*, SOAP_SOCKET);
+static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
+static const char *soap_strerror(struct soap*);
+#endif
+
+#define SOAP_TCP_SELECT_RCV 0x1
+#define SOAP_TCP_SELECT_SND 0x2
+#define SOAP_TCP_SELECT_ERR 0x4
+#define SOAP_TCP_SELECT_ALL 0x7
+
+#if defined(WIN32)
+  #define SOAP_SOCKBLOCK(fd) \
+  { u_long blocking = 0; \
+    ioctlsocket(fd, FIONBIO, &blocking); \
+  }
+  #define SOAP_SOCKNONBLOCK(fd) \
+  { u_long nonblocking = 1; \
+    ioctlsocket(fd, FIONBIO, &nonblocking); \
+  }
+#elif defined(VXWORKS)
+  #define SOAP_SOCKBLOCK(fd) \
+  { u_long blocking = 0; \
+    ioctl(fd, FIONBIO, (int)(&blocking)); \
+  }
+  #define SOAP_SOCKNONBLOCK(fd) \
+  { u_long nonblocking = 1; \
+    ioctl(fd, FIONBIO, (int)(&nonblocking)); \
+  }
+#elif defined(__VMS)
+  #define SOAP_SOCKBLOCK(fd) \
+  { int blocking = 0; \
+    ioctl(fd, FIONBIO, &blocking); \
+  }
+  #define SOAP_SOCKNONBLOCK(fd) \
+  { int nonblocking = 1; \
+    ioctl(fd, FIONBIO, &nonblocking); \
+  }
+#elif defined(PALM)
+  #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
+  #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
+#elif defined(SYMBIAN)
+  #define SOAP_SOCKBLOCK(fd) \
+  { long blocking = 0; \
+    ioctl(fd, 0/*FIONBIO*/, &blocking); \
+  }
+  #define SOAP_SOCKNONBLOCK(fd) \
+  { long nonblocking = 1; \
+    ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
+  }
+#else
+  #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
+  #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
+#endif
+
+#endif
+
+#if defined(PALM) && !defined(PALM_2)
+unsigned short errno;
+#endif
+
+#ifndef PALM_1
+static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
+static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
+static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
+static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
+static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
+#endif
+
+#ifndef PALM_1
+const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}};
+const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
+#endif
+
+#ifndef WITH_LEAN
+static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
+/* Alternative indentation form for SOAP_XML_INDENT:
+static const char soap_indent[21] = "\n                   ";
+*/
+#endif
+
+#ifndef SOAP_CANARY
+# define SOAP_CANARY (0xC0DE)
+#endif
+
+static const char soap_padding[4] = "\0\0\0";
+#define SOAP_STR_PADDING (soap_padding)
+#define SOAP_STR_EOS (soap_padding)
+#define SOAP_NON_NULL (soap_padding)
+
+#ifndef WITH_LEAN
+static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
+{ { 160, "nbsp" },
+  { 161, "iexcl" },
+  { 162, "cent" },
+  { 163, "pound" },
+  { 164, "curren" },
+  { 165, "yen" },
+  { 166, "brvbar" },
+  { 167, "sect" },
+  { 168, "uml" },
+  { 169, "copy" },
+  { 170, "ordf" },
+  { 171, "laquo" },
+  { 172, "not" },
+  { 173, "shy" },
+  { 174, "reg" },
+  { 175, "macr" },
+  { 176, "deg" },
+  { 177, "plusmn" },
+  { 178, "sup2" },
+  { 179, "sup3" },
+  { 180, "acute" },
+  { 181, "micro" },
+  { 182, "para" },
+  { 183, "middot" },
+  { 184, "cedil" },
+  { 185, "sup1" },
+  { 186, "ordm" },
+  { 187, "raquo" },
+  { 188, "frac14" },
+  { 189, "frac12" },
+  { 190, "frac34" },
+  { 191, "iquest" },
+  { 192, "Agrave" },
+  { 193, "Aacute" },
+  { 194, "Acirc" },
+  { 195, "Atilde" },
+  { 196, "Auml" },
+  { 197, "Aring" },
+  { 198, "AElig" },
+  { 199, "Ccedil" },
+  { 200, "Egrave" },
+  { 201, "Eacute" },
+  { 202, "Ecirc" },
+  { 203, "Euml" },
+  { 204, "Igrave" },
+  { 205, "Iacute" },
+  { 206, "Icirc" },
+  { 207, "Iuml" },
+  { 208, "ETH" },
+  { 209, "Ntilde" },
+  { 210, "Ograve" },
+  { 211, "Oacute" },
+  { 212, "Ocirc" },
+  { 213, "Otilde" },
+  { 214, "Ouml" },
+  { 215, "times" },
+  { 216, "Oslash" },
+  { 217, "Ugrave" },
+  { 218, "Uacute" },
+  { 219, "Ucirc" },
+  { 220, "Uuml" },
+  { 221, "Yacute" },
+  { 222, "THORN" },
+  { 223, "szlig" },
+  { 224, "agrave" },
+  { 225, "aacute" },
+  { 226, "acirc" },
+  { 227, "atilde" },
+  { 228, "auml" },
+  { 229, "aring" },
+  { 230, "aelig" },
+  { 231, "ccedil" },
+  { 232, "egrave" },
+  { 233, "eacute" },
+  { 234, "ecirc" },
+  { 235, "euml" },
+  { 236, "igrave" },
+  { 237, "iacute" },
+  { 238, "icirc" },
+  { 239, "iuml" },
+  { 240, "eth" },
+  { 241, "ntilde" },
+  { 242, "ograve" },
+  { 243, "oacute" },
+  { 244, "ocirc" },
+  { 245, "otilde" },
+  { 246, "ouml" },
+  { 247, "divide" },
+  { 248, "oslash" },
+  { 249, "ugrave" },
+  { 250, "uacute" },
+  { 251, "ucirc" },
+  { 252, "uuml" },
+  { 253, "yacute" },
+  { 254, "thorn" },
+  { 255, "yuml" },
+  {   0, NULL }
+};
+#endif
+
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+static const struct soap_code_map h_error_codes[] =
+{
+#ifdef HOST_NOT_FOUND
+  { HOST_NOT_FOUND, "Host not found" },
+#endif
+#ifdef TRY_AGAIN
+  { TRY_AGAIN, "Try Again" },
+#endif
+#ifdef NO_RECOVERY
+  { NO_RECOVERY, "No Recovery" },
+#endif
+#ifdef NO_DATA
+  { NO_DATA, "No Data" },
+#endif
+#ifdef NO_ADDRESS
+  { NO_ADDRESS, "No Address" },
+#endif
+  { 0, NULL }
+};
+#endif
+#endif
+
+#ifndef WITH_NOHTTP
+#ifndef WITH_LEAN
+static const struct soap_code_map h_http_error_codes[] =
+{ { 200, "OK" },
+  { 201, "Created" },
+  { 202, "Accepted" },
+  { 203, "Non-Authoritative Information" },
+  { 204, "No Content" },
+  { 205, "Reset Content" },
+  { 206, "Partial Content" },
+  { 300, "Multiple Choices" },
+  { 301, "Moved Permanently" },
+  { 302, "Found" },
+  { 303, "See Other" },
+  { 304, "Not Modified" },
+  { 305, "Use Proxy" },
+  { 307, "Temporary Redirect" },
+  { 400, "Bad Request" },
+  { 401, "Unauthorized" },
+  { 402, "Payment Required" },
+  { 403, "Forbidden" },
+  { 404, "Not Found" },
+  { 405, "Method Not Allowed" },
+  { 406, "Not Acceptable" },
+  { 407, "Proxy Authentication Required" },
+  { 408, "Request Time-out" },
+  { 409, "Conflict" },
+  { 410, "Gone" },
+  { 411, "Length Required" },
+  { 412, "Precondition Failed" },
+  { 413, "Request Entity Too Large" },
+  { 414, "Request-URI Too Large" },
+  { 415, "Unsupported Media Type" },
+  { 416, "Requested range not satisfiable" },
+  { 417, "Expectation Failed" },
+  { 500, "Internal Server Error" },
+  { 501, "Not Implemented" },
+  { 502, "Bad Gateway" },
+  { 503, "Service Unavailable" },
+  { 504, "Gateway Time-out" },
+  { 505, "HTTP Version not supported" },
+  {   0, NULL }
+};
+#endif
+#endif
+
+#ifdef WITH_OPENSSL
+static const struct soap_code_map h_ssl_error_codes[] =
+{
+#define _SSL_ERROR(e) { e, #e }
+  _SSL_ERROR(SSL_ERROR_SSL),
+  _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
+  _SSL_ERROR(SSL_ERROR_WANT_READ),
+  _SSL_ERROR(SSL_ERROR_WANT_WRITE),
+  _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
+  _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
+  _SSL_ERROR(SSL_ERROR_SYSCALL),
+  { 0, NULL }
+};
+#endif
+
+#ifndef WITH_LEANER
+static const struct soap_code_map mime_codes[] =
+{ { SOAP_MIME_7BIT,		"7bit" },
+  { SOAP_MIME_8BIT,		"8bit" },
+  { SOAP_MIME_BINARY,		"binary" },
+  { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
+  { SOAP_MIME_BASE64,		"base64" },
+  { SOAP_MIME_IETF_TOKEN,	"ietf-token" },
+  { SOAP_MIME_X_TOKEN,		"x-token" },
+  { 0,				NULL }
+};
+#endif
+
+#ifdef WIN32
+static int tcp_done = 0;
+#endif
+
+#if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
+extern int h_errno;
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static int
+fsend(struct soap *soap, const char *s, size_t n)
+{ register int nwritten, err;
+  SOAP_SOCKET sk;
+#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
+  if (soap->os)
+  { soap->os->write(s, (std::streamsize)n);
+    if (soap->os->good())
+      return SOAP_OK;
+    soap->errnum = 0;
+    return SOAP_EOF;
+  }
+#endif
+  sk = soap->sendsk;
+  if (!soap_valid_socket(sk))
+    sk = soap->socket;
+  while (n)
+  { if (soap_valid_socket(sk))
+    {
+      if (soap->send_timeout)
+      { for (;;)
+        { register int r;
+#ifdef WITH_OPENSSL
+          if (soap->ssl)
+            r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
+          else
+#endif
+#ifdef WITH_GNUTLS
+          if (soap->session)
+            r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
+          else
+#endif
+            r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
+          if (r > 0)
+            break;
+          if (!r)
+            return SOAP_EOF;
+          err = soap->errnum;
+          if (!err)
+            return soap->error;
+          if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
+            return SOAP_EOF;
+        }
+      }
+#ifdef WITH_OPENSSL
+      if (soap->ssl)
+        nwritten = SSL_write(soap->ssl, s, (int)n);
+      else if (soap->bio)
+        nwritten = BIO_write(soap->bio, s, (int)n);
+      else
+#endif
+#ifdef WITH_GNUTLS
+      if (soap->session)
+        nwritten = gnutls_record_send(soap->session, s, n);
+      else
+#endif
+#ifndef WITH_LEAN
+      if ((soap->omode & SOAP_IO_UDP))
+      { if (soap->peerlen)
+          nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
+        else
+          nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
+        /* retry and back-off algorithm */
+        /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
+        if (nwritten < 0)
+        { int udp_repeat;
+          int udp_delay;
+          if ((soap->connect_flags & SO_BROADCAST))
+            udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
+          else
+            udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
+          udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
+          do
+          { tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
+            if (soap->peerlen)
+              nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
+            else
+              nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
+            udp_delay <<= 1;
+            if (udp_delay > 500) /* UDP_UPPER_DELAY */
+              udp_delay = 500;
+          }
+          while (nwritten < 0 && --udp_repeat > 0);
+        }
+        if (nwritten < 0)
+        { err = soap_socket_errno(sk);
+          if (err && err != SOAP_EINTR)
+          { soap->errnum = err;
+            return SOAP_EOF;
+          }
+          nwritten = 0; /* and call write() again */
+        }
+      }
+      else
+#endif
+#if !defined(PALM) && !defined(AS400)
+        nwritten = send(sk, s, (int)n, soap->socket_flags);
+#else
+        nwritten = send(sk, (void*)s, n, soap->socket_flags);
+#endif
+      if (nwritten <= 0)
+      {
+        register int r = 0;
+        err = soap_socket_errno(sk);
+#ifdef WITH_OPENSSL
+        if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
+        { soap->errnum = err;
+          return SOAP_EOF;
+        }
+#endif
+#ifdef WITH_GNUTLS
+        if (soap->session)
+        { if (nwritten == GNUTLS_E_INTERRUPTED)
+            err = SOAP_EINTR;
+          else if (nwritten == GNUTLS_E_AGAIN)
+            err = SOAP_EAGAIN;
+        }
+#endif
+        if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
+        {
+#if defined(WITH_OPENSSL)
+          if (soap->ssl && r == SSL_ERROR_WANT_READ)
+            r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
+          else
+#elif defined(WITH_GNUTLS)
+          if (soap->session && !gnutls_record_get_direction(soap->session))
+            r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
+          else
+#endif
+            r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
+          if (!r && soap->send_timeout)
+            return SOAP_EOF;
+          if (r < 0)
+            return SOAP_EOF;
+        }
+        else if (err && err != SOAP_EINTR)
+        { soap->errnum = err;
+          return SOAP_EOF;
+        }
+        nwritten = 0; /* and call write() again */
+      }
+    }
+    else
+    {
+#ifdef WITH_FASTCGI
+      nwritten = fwrite((void*)s, 1, n, stdout);
+      fflush(stdout);
+#else
+#ifdef UNDER_CE
+      nwritten = fwrite(s, 1, n, soap->sendfd);
+#else
+#ifdef VXWORKS
+#ifdef WMW_RPM_IO
+      if (soap->rpmreqid)
+        nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
+      else
+#endif
+        nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
+#else
+#ifdef WIN32
+      nwritten = _write(soap->sendfd, s, (unsigned int)n);
+#else
+      nwritten = write(soap->sendfd, s, (unsigned int)n);
+#endif
+#endif
+#endif
+#endif
+      if (nwritten <= 0)
+      {
+#ifndef WITH_FASTCGI
+        err = soap_errno;
+#else
+        err = EOF;
+#endif
+        if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
+        { soap->errnum = err;
+          return SOAP_EOF;
+        }
+        nwritten = 0; /* and call write() again */
+      }
+    }
+    n -= nwritten;
+    s += nwritten;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send_raw(struct soap *soap, const char *s, size_t n)
+{ if (!n)
+    return SOAP_OK;
+#ifndef WITH_LEANER
+  if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n)))
+    return soap->error;
+  if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)))
+    return soap->error;
+#endif
+  if (soap->mode & SOAP_IO_LENGTH)
+    soap->count += n;
+  else if (soap->mode & SOAP_IO)
+  { register size_t i = SOAP_BUFLEN - soap->bufidx;
+    while (n >= i)
+    { memcpy(soap->buf + soap->bufidx, s, i);
+      soap->bufidx = SOAP_BUFLEN;
+      if (soap_flush(soap))
+        return soap->error;
+      s += i;
+      n -= i;
+      i = SOAP_BUFLEN;
+    }
+    memcpy(soap->buf + soap->bufidx, s, n);
+    soap->bufidx += n;
+  }
+  else
+    return soap_flush_raw(soap, s, n);
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_flush(struct soap *soap)
+{ register size_t n = soap->bufidx;
+  if (n)
+  {
+#ifndef WITH_LEANER
+    if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
+    { register int r;
+      if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)))
+        return soap->error = r;
+    }
+#endif
+    soap->bufidx = 0;
+#ifdef WITH_ZLIB
+    if (soap->mode & SOAP_ENC_ZLIB)
+    { soap->d_stream->next_in = (Byte*)soap->buf;
+      soap->d_stream->avail_in = (unsigned int)n;
+#ifdef WITH_GZIP
+      soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
+#endif
+      do
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
+        if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
+          return soap->error = SOAP_ZLIB_ERROR;
+        }
+        if (!soap->d_stream->avail_out)
+        { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
+            return soap->error;
+          soap->d_stream->next_out = (Byte*)soap->z_buf;
+          soap->d_stream->avail_out = SOAP_BUFLEN;
+        }
+      } while (soap->d_stream->avail_in);
+    }
+    else
+#endif
+      return soap_flush_raw(soap, soap->buf, n);
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_flush_raw(struct soap *soap, const char *s, size_t n)
+{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
+  { register char *t;
+    if (!(t = (char*)soap_push_block(soap, NULL, n)))
+      return soap->error = SOAP_EOM;
+    memcpy(t, s, n);
+    return SOAP_OK;
+  }
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+  { char t[16];
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(t, sizeof(t), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
+#else
+    sprintf(t, &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
+#endif
+    DBGMSG(SENT, t, strlen(t));
+    if ((soap->error = soap->fsend(soap, t, strlen(t))))
+      return soap->error;
+    soap->chunksize += n;
+  }
+  DBGMSG(SENT, s, n);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, soap->socket, soap->sendfd));
+#endif
+  return soap->error = soap->fsend(soap, s, n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send(struct soap *soap, const char *s)
+{ if (s)
+    return soap_send_raw(soap, s, strlen(s));
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send2(struct soap *soap, const char *s1, const char *s2)
+{ if (soap_send(soap, s1))
+    return soap->error;
+  return soap_send(soap, s2);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
+{ if (soap_send(soap, s1)
+   || soap_send(soap, s2))
+    return soap->error;
+  return soap_send(soap, s3);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static size_t
+frecv(struct soap *soap, char *s, size_t n)
+{ register int r;
+  register int retries = 100; /* max 100 retries with non-blocking sockets */
+  SOAP_SOCKET sk;
+  soap->errnum = 0;
+#if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
+  if (soap->is)
+  { if (soap->is->good())
+      return soap->is->read(s, (std::streamsize)n).gcount();
+    return 0;
+  }
+#endif
+  sk = soap->recvsk;
+  if (!soap_valid_socket(sk))
+    sk = soap->socket;
+  if (soap_valid_socket(sk))
+  { for (;;)
+    {
+#ifdef WITH_OPENSSL
+      register int err = 0;
+#endif
+#ifdef WITH_OPENSSL
+      if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
+#else
+      if (soap->recv_timeout)
+#endif
+      { for (;;)
+        { r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
+          if (r > 0)
+            break;
+          if (!r)
+            return 0;
+          r = soap->errnum;
+          if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
+            return 0;
+        }
+      }
+#ifdef WITH_OPENSSL
+      if (soap->ssl)
+      { r = SSL_read(soap->ssl, s, (int)n);
+        if (r > 0)
+          return (size_t)r;
+        err = SSL_get_error(soap->ssl, r);
+        if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
+          return 0;
+      }
+      else if (soap->bio)
+      { r = BIO_read(soap->bio, s, (int)n);
+        if (r > 0)
+          return (size_t)r;
+        return 0;
+      }
+      else
+#endif
+#ifdef WITH_GNUTLS
+      if (soap->session)
+      { r = (int)gnutls_record_recv(soap->session, s, n);
+        if (r >= 0)
+          return (size_t)r;
+      }
+      else
+#endif
+      {
+#ifndef WITH_LEAN
+        if ((soap->omode & SOAP_IO_UDP))
+        { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
+          memset((void*)&soap->peer, 0, sizeof(soap->peer));
+          r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k);	/* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
+          soap->peerlen = (size_t)k;
+#ifndef WITH_IPV6
+          soap->ip = ntohl(soap->peer.sin_addr.s_addr);
+#endif
+        }
+        else
+#endif
+          r = recv(sk, s, (int)n, soap->socket_flags);
+#ifdef PALM
+        /* CycleSyncDisplay(curStatusMsg); */
+#endif
+        if (r >= 0)
+          return (size_t)r;
+        r = soap_socket_errno(sk);
+        if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
+        { soap->errnum = r;
+          return 0;
+        }
+      }
+#if defined(WITH_OPENSSL)
+      if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
+        r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
+      else
+#elif defined(WITH_GNUTLS)
+      if (soap->session && gnutls_record_get_direction(soap->session))
+        r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
+      else
+#endif
+        r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
+      if (!r && soap->recv_timeout)
+        return 0;
+      if (r < 0)
+      { r = soap->errnum;
+        if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
+          return 0;
+      }
+      if (retries-- <= 0)
+        return 0;
+#ifdef PALM
+      r = soap_socket_errno(sk);
+      if (r != SOAP_EINTR && retries-- <= 0)
+      { soap->errnum = r;
+        return 0;
+      }
+#endif
+    }
+  }
+#ifdef WITH_FASTCGI
+  return fread(s, 1, n, stdin);
+#else
+#ifdef UNDER_CE
+  return fread(s, 1, n, soap->recvfd);
+#else
+#ifdef WMW_RPM_IO
+  if (soap->rpmreqid)
+    r = httpBlockRead(soap->rpmreqid, s, n);
+  else
+#endif
+#ifdef WIN32
+    r = _read(soap->recvfd, s, (unsigned int)n);
+#else
+    r = read(soap->recvfd, s, (unsigned int)n);
+#endif
+  if (r >= 0)
+    return (size_t)r;
+  soap->errnum = soap_errno;
+  return 0;
+#endif
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static soap_wchar
+soap_getchunkchar(struct soap *soap)
+{ if (soap->bufidx < soap->buflen)
+    return soap->buf[soap->bufidx++];
+  soap->bufidx = 0;
+  soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, soap->socket, soap->recvfd));
+  DBGMSG(RECV, soap->buf, soap->buflen);
+  if (soap->buflen)
+    return soap->buf[soap->bufidx++];
+  return EOF;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+soap_isxdigit(int c)
+{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv_raw(struct soap *soap)
+{ register size_t ret;
+#if !defined(WITH_LEANER) || defined(WITH_ZLIB)
+  register int r;
+#endif
+#ifdef WITH_ZLIB
+  if (soap->mode & SOAP_ENC_ZLIB)
+  { if (soap->d_stream->next_out == Z_NULL)
+    { soap->bufidx = soap->buflen = 0;
+      return EOF;
+    }
+    if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
+      soap->d_stream->next_out = (Byte*)soap->buf;
+      soap->d_stream->avail_out = SOAP_BUFLEN;
+      r = inflate(soap->d_stream, Z_NO_FLUSH);
+      if (r == Z_NEED_DICT && soap->z_dict)
+        r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
+      if (r == Z_OK || r == Z_STREAM_END)
+      { soap->bufidx = 0;
+        ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
+        if (soap->zlib_in == SOAP_ZLIB_GZIP)
+          soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
+        if (r == Z_STREAM_END)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
+          soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
+          soap->d_stream->next_out = Z_NULL;
+        }
+        if (ret)
+        { soap->count += ret;
+          DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
+          DBGMSG(RECV, soap->buf, ret);
+          DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
+#ifndef WITH_LEANER
+          if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
+            return soap->error = r;
+#endif
+          return SOAP_OK;
+        }
+      }
+      else if (r != Z_BUF_ERROR)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
+        soap->d_stream->next_out = Z_NULL;
+        return soap->error = SOAP_ZLIB_ERROR;
+      }
+    }
+zlib_again:
+    if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
+    { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
+      soap->buflen = soap->z_buflen;
+    }
+    DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
+  }
+#endif
+#ifndef WITH_NOHTTP
+  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
+  { for (;;)
+    { register soap_wchar c;
+      char *t, tmp[17];
+      if (soap->chunksize)
+      { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
+        DBGMSG(RECV, soap->buf, ret);
+        soap->bufidx = 0;
+        soap->chunksize -= ret;
+        break;
+      }
+      t = tmp;
+      if (!soap->chunkbuflen)
+      { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, soap->socket));
+        DBGMSG(RECV, soap->buf, ret);
+        soap->bufidx = 0;
+        if (!ret)
+        { soap->ahead = EOF;
+          return EOF;
+        }
+      }
+      else
+        soap->bufidx = soap->buflen;
+      soap->buflen = soap->chunkbuflen;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
+      while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
+      { if ((int)c == EOF)
+        { soap->ahead = EOF;
+          return EOF;
+        }
+      }
+      do
+        *t++ = (char)c;
+      while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1);
+      while ((int)c != EOF && c != '\n')
+        c = soap_getchunkchar(soap);
+      if ((int)c == EOF)
+      { soap->ahead = EOF;
+        return EOF;
+      }
+      *t = '\0';
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
+      soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16);
+      if (!soap->chunksize)
+      { soap->bufidx = soap->buflen = soap->chunkbuflen = 0;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
+        while ((int)c != EOF && c != '\n')
+          c = soap_getchunkchar(soap);
+        ret = 0;
+        soap->ahead = EOF;
+        break;
+      }
+      soap->buflen = soap->bufidx + soap->chunksize;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
+      if (soap->buflen > soap->chunkbuflen)
+      { soap->buflen = soap->chunkbuflen;
+        soap->chunksize -= soap->buflen - soap->bufidx;
+        soap->chunkbuflen = 0;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
+      }
+      else if (soap->chunkbuflen)
+        soap->chunksize = 0;
+      ret = soap->buflen - soap->bufidx;
+      if (ret)
+        break;
+    }
+  }
+  else
+#endif
+  { soap->bufidx = 0;
+    soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, soap->socket, soap->recvfd));
+    DBGMSG(RECV, soap->buf, ret);
+  }
+#ifdef WITH_ZLIB
+  if (soap->mode & SOAP_ENC_ZLIB)
+  { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
+    soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
+    soap->d_stream->avail_in = (unsigned int)ret;
+    soap->d_stream->next_out = (Byte*)soap->buf;
+    soap->d_stream->avail_out = SOAP_BUFLEN;
+    r = inflate(soap->d_stream, Z_NO_FLUSH);
+    if (r == Z_NEED_DICT && soap->z_dict)
+      r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
+    if (r == Z_OK || r == Z_STREAM_END)
+    { soap->bufidx = 0;
+      soap->z_buflen = soap->buflen;
+      soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
+      if (soap->zlib_in == SOAP_ZLIB_GZIP)
+        soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
+      if (ret && !soap->buflen && r != Z_STREAM_END)
+        goto zlib_again;
+      ret = soap->buflen;
+      if (r == Z_STREAM_END)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
+        soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
+        soap->d_stream->next_out = Z_NULL;
+      }
+      DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
+      DBGMSG(RECV, soap->buf, ret);
+#ifndef WITH_LEANER
+      if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
+        return soap->error = r;
+#endif
+    }
+    else
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
+      soap->d_stream->next_out = Z_NULL;
+      return soap->error = SOAP_ZLIB_ERROR;
+    }
+  }
+#endif
+#ifndef WITH_LEANER
+  if (soap->fpreparerecv
+#ifdef WITH_ZLIB
+   && soap->zlib_in == SOAP_ZLIB_NONE
+#endif
+   && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
+    return soap->error = r;
+#endif
+  soap->count += ret;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=%lu (+%lu)\n", (unsigned long)soap->count, (unsigned long)ret));
+  return !ret;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv(struct soap *soap)
+{
+#ifndef WITH_LEANER
+  if (soap->mode & SOAP_ENC_DIME)
+  { if (soap->dime.buflen)
+    { char *s;
+      int i;
+      unsigned char tmp[12];
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
+      soap->count += soap->dime.buflen - soap->buflen;
+      soap->buflen = soap->dime.buflen;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
+      for (i = -(long)soap->dime.size&3; i > 0; i--)
+      { soap->bufidx++;
+        if (soap->bufidx >= soap->buflen)
+          if (soap_recv_raw(soap))
+            return EOF;
+      }
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
+      s = (char*)tmp;
+      for (i = 12; i > 0; i--)
+      { *s++ = soap->buf[soap->bufidx++];
+        if (soap->bufidx >= soap->buflen)
+          if (soap_recv_raw(soap))
+            return EOF;
+      }
+      soap->dime.flags = tmp[0] & 0x7;
+      soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
+      if (soap->dime.flags & SOAP_DIME_CF)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
+        soap->dime.chunksize = soap->dime.size;
+        if (soap->buflen - soap->bufidx >= soap->dime.size)
+        { soap->dime.buflen = soap->buflen;
+          soap->buflen = soap->bufidx + soap->dime.chunksize;
+        }
+        else
+          soap->dime.chunksize -= soap->buflen - soap->bufidx;
+      }
+      else
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
+        soap->dime.buflen = 0;
+        soap->dime.chunksize = 0;
+      }
+      soap->count = soap->buflen - soap->bufidx;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
+      return SOAP_OK;
+    }
+    if (soap->dime.chunksize)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
+      if (soap_recv_raw(soap))
+        return EOF;
+      if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
+      { soap->dime.buflen = soap->buflen;
+        soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
+        soap->buflen = soap->bufidx + soap->dime.chunksize;
+      }
+      else
+        soap->dime.chunksize -= soap->buflen - soap->bufidx;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%lu\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned long)soap->count));
+      return SOAP_OK;
+    }
+  }
+  while (soap->ffilterrecv)
+  { int err, last = soap->filterstop;
+    if (last)
+      soap->bufidx = soap->buflen = 0;
+    if ((err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf))))
+      return soap->error = err;
+    if (soap->buflen)
+    { soap->bufidx = 0;
+      soap->filterstop = last;
+      return SOAP_OK;
+    }
+    if (last)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", last));
+      soap->filterstop = SOAP_OK;
+      return last;
+    }
+    soap->filterstop = soap_recv_raw(soap); /* do not call again after EOF */
+  }
+#endif
+  return soap_recv_raw(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_getchar(struct soap *soap)
+{ register soap_wchar c;
+  c = soap->ahead;
+  if (c)
+  { if (c != EOF)
+      soap->ahead = 0;
+    return c;
+  }
+  return soap_get1(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const struct soap_code_map*
+SOAP_FMAC2
+soap_code(const struct soap_code_map *code_map, const char *str)
+{ if (code_map && str)
+  { while (code_map->string)
+    { if (!strcmp(str, code_map->string)) /* case sensitive */
+        return code_map;
+      code_map++;
+    }
+  }
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+long
+SOAP_FMAC2
+soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
+{ if (code_map)
+  { while (code_map->string)
+    { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
+        return code_map->code;
+      code_map++;
+    }
+  }
+  return other;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_code_str(const struct soap_code_map *code_map, long code)
+{ if (!code_map)
+    return NULL;
+  while (code_map->code != code && code_map->string)
+    code_map++;
+  return code_map->string;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+long
+SOAP_FMAC2
+soap_code_bits(const struct soap_code_map *code_map, const char *str)
+{ register long bits = 0;
+  if (code_map)
+  { while (str && *str)
+    { const struct soap_code_map *p;
+      for (p = code_map; p->string; p++)
+      { register size_t n = strlen(p->string);
+        if (!strncmp(p->string, str, n) && soap_blank((soap_wchar)str[n]))
+        { bits |= p->code;
+          str += n;
+          while (*str > 0 && *str <= 32)
+            str++;
+          break;
+        }
+      }
+      if (!p->string)
+        return 0;
+    }
+  }
+  return bits;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
+{ register char *t = soap->tmpbuf;
+  if (code_map)
+  { while (code_map->string)
+    { if (code_map->code & code)
+      { register const char *s = code_map->string;
+        if (t != soap->tmpbuf)
+          *t++ = ' ';
+        while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
+          *t++ = *s++;
+        if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
+          break;
+      }
+      code_map++;
+    }
+  }
+  *t = '\0';
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static soap_wchar
+soap_char(struct soap *soap)
+{ char tmp[8];
+  register int i;
+  register soap_wchar c;
+  register char *s = tmp;
+  for (i = 0; i < 7; i++)
+  { c = soap_get1(soap);
+    if (c == ';' || (int)c == EOF)
+      break;
+    *s++ = (char)c;
+  }
+  *s = '\0';
+  if (*tmp == '#')
+  { if (tmp[1] == 'x' || tmp[1] == 'X')
+      return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
+    return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
+  }
+  if (!strcmp(tmp, "lt"))
+    return '<';
+  if (!strcmp(tmp, "gt"))
+    return '>';
+  if (!strcmp(tmp, "amp"))
+    return '&';
+  if (!strcmp(tmp, "quot"))
+    return '"';
+  if (!strcmp(tmp, "apos"))
+    return '\'';
+#ifndef WITH_LEAN
+  return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
+#else
+  return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifdef WITH_LEAN
+#ifndef PALM_1
+soap_wchar
+soap_get0(struct soap *soap)
+{ if (soap->bufidx >= soap->buflen && soap_recv(soap))
+    return EOF;
+  return (unsigned char)soap->buf[soap->bufidx];
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef WITH_LEAN
+#ifndef PALM_1
+soap_wchar
+soap_get1(struct soap *soap)
+{ if (soap->bufidx >= soap->buflen && soap_recv(soap))
+    return EOF;
+  return (unsigned char)soap->buf[soap->bufidx++];
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_get(struct soap *soap)
+{ register soap_wchar c;
+  c = soap->ahead;
+  if (c)
+  { if ((int)c != EOF)
+      soap->ahead = 0;
+  }
+  else
+    c = soap_get1(soap);
+  while ((int)c != EOF)
+  { if (soap->cdata)
+    { if (c == ']')
+      { c = soap_get1(soap);
+        if (c == ']')
+        { c = soap_get0(soap);
+          if (c == '>')
+          { soap->cdata = 0;
+            c = soap_get1(soap);
+            c = soap_get1(soap);
+          }
+          else
+          { soap_unget(soap, ']');
+            return ']';
+          }
+        }
+        else
+        { soap_revget1(soap);
+          return ']';
+        }
+      }
+      else
+        return c;
+    }
+    switch (c)
+    { case '<':
+        do c = soap_get1(soap);
+        while (soap_blank(c));
+        if (c == '!' || c == '?' || c == '%')
+        { register int k = 1;
+          if (c == '!')
+          { c = soap_get1(soap);
+            if (c == '[')
+            { do c = soap_get1(soap);
+              while ((int)c != EOF && c != '[');
+              if ((int)c == EOF)
+                break;
+              soap->cdata = 1;
+              c = soap_get1(soap);
+              continue;
+            }
+            if (c == '-' && (c = soap_get1(soap)) == '-')
+            { do
+              { c = soap_get1(soap);
+                if (c == '-' && (c = soap_get1(soap)) == '-')
+                  break;
+              } while ((int)c != EOF);
+            }
+          }
+          else if (c == '?')
+            c = soap_get_pi(soap);
+          while ((int)c != EOF)
+          { if (c == '<')
+              k++;
+            else if (c == '>')
+            { if (--k <= 0)
+                break;
+            }
+            c = soap_get1(soap);
+          }
+          if ((int)c == EOF)
+            break;
+          c = soap_get1(soap);
+          continue;
+        }
+        if (c == '/')
+          return SOAP_TT;
+        soap_revget1(soap);
+        return SOAP_LT;
+      case '>':
+        return SOAP_GT;
+      case '"':
+        return SOAP_QT;
+      case '\'':
+        return SOAP_AP;
+      case '&':
+        return soap_char(soap) | 0x80000000;
+    }
+    break;
+  }
+  return c;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static soap_wchar
+soap_get_pi(struct soap *soap)
+{ char buf[64];
+  register char *s = buf;
+  register int i = sizeof(buf);
+  register soap_wchar c = soap_getchar(soap);
+  /* This is a quick way to parse XML PI and we could use a callback instead to
+   * enable applications to intercept processing instructions */
+  while ((int)c != EOF && c != '?')
+  { if (--i > 0)
+    { if (soap_blank(c))
+        c = ' ';
+      *s++ = (char)c;
+    }
+    c = soap_getchar(soap);
+  }
+  *s = '\0';
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
+  if (!strncmp(buf, "xml ", 4))
+  { s = strstr(buf, " encoding=");
+    if (s && s[10])
+    { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
+       || !soap_tag_cmp(s + 11, "latin1*"))
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
+        soap->mode |= SOAP_ENC_LATIN;
+      }
+      else if (!soap_tag_cmp(s + 11, "utf-8*"))
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
+        soap->mode &= ~SOAP_ENC_LATIN;
+      }
+    }
+  }
+  if ((int)c != EOF)
+    c = soap_getchar(soap);
+  return c;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_move(struct soap *soap, size_t n)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %lu bytes forward\n", (unsigned long)n));
+  for (; n; n--)
+    if ((int)soap_getchar(soap) == EOF)
+      return SOAP_EOF;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_tell(struct soap *soap)
+{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_pututf8(struct soap *soap, register unsigned long c)
+{ char tmp[16];
+  if (c < 0x80 && c > 0)
+  { *tmp = (char)c;
+    return soap_send_raw(soap, tmp, 1);
+  }
+#ifndef WITH_LEAN
+  if (c >= 0x80)
+  { register char *t = tmp;
+    if (c < 0x0800)
+      *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
+    else
+    { if (c < 0x010000)
+        *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
+      else
+      { if (c < 0x200000)
+          *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
+        else
+        { if (c < 0x04000000)
+            *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
+          else
+          { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
+            *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
+          }
+          *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
+        }
+        *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
+      }
+      *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
+    }
+    *t++ = (char)(0x80 | (c & 0x3F));
+    *t = '\0';
+  }
+  else
+#endif
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(tmp, sizeof(tmp), "&#%lu;", c);
+#else
+    sprintf(tmp, "&#%lu;", c);
+#endif
+  return soap_send(soap, tmp);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+soap_wchar
+SOAP_FMAC2
+soap_getutf8(struct soap *soap)
+{ register soap_wchar c, c1, c2, c3, c4;
+  c = soap->ahead;
+  if (c >= 0x80)
+    soap->ahead = 0;
+  else
+    c = soap_get(soap);
+  if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN))
+    return c;
+  c1 = soap_get1(soap);
+  if (c1 < 0x80)
+  { soap_revget1(soap); /* doesn't look like this is UTF8 */
+    return c;
+  }
+  c1 &= 0x3F;
+  if (c < 0xE0)
+    return ((soap_wchar)(c & 0x1F) << 6) | c1;
+  c2 = (soap_wchar)soap_get1(soap) & 0x3F;
+  if (c < 0xF0)
+    return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
+  c3 = (soap_wchar)soap_get1(soap) & 0x3F;
+  if (c < 0xF8)
+    return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
+  c4 = (soap_wchar)soap_get1(soap) & 0x3F;
+  if (c < 0xFC)
+    return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
+  return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_puthex(struct soap *soap, const unsigned char *s, int n)
+{ char d[2];
+  register int i;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
+      return soap->error;
+    return SOAP_OK;
+  }
+#endif
+  for (i = 0; i < n; i++)
+  { register int m = *s++;
+    d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
+    m &= 0x0F;
+    d[1] = (char)(m + (m > 9 ? '7' : '0'));
+    if (soap_send_raw(soap, d, 2))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+unsigned char*
+SOAP_FMAC2
+soap_gethex(struct soap *soap, int *n)
+{
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { soap->dom->data = soap_string_in(soap, 0, -1, -1);
+    return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
+  }
+#endif
+#ifdef WITH_FAST
+  soap->labidx = 0;
+  for (;;)
+  { register char *s;
+    register size_t i, k;
+    if (soap_append_lab(soap, NULL, 0))
+      return NULL;
+    s = soap->labbuf + soap->labidx;
+    k = soap->lablen - soap->labidx;
+    soap->labidx = soap->lablen;
+    for (i = 0; i < k; i++)
+    { register char d1, d2;
+      register soap_wchar c;
+      c = soap_get(soap);
+      if (soap_isxdigit(c))
+      { d1 = (char)c;
+        c = soap_get(soap);
+        if (soap_isxdigit(c))
+          d2 = (char)c;
+        else
+        { soap->error = SOAP_TYPE;
+          return NULL;
+        }
+      }
+      else
+      { unsigned char *p;
+        soap_unget(soap, c);
+        if (n)
+          *n = (int)(soap->lablen + i - k);
+        p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
+        if (p)
+          memcpy(p, soap->labbuf, soap->lablen + i - k);
+        return p;
+      }
+      *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
+    }
+  }
+#else
+  if (soap_new_block(soap) == NULL)
+    return NULL;
+  for (;;)
+  { register int i;
+    register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
+    if (!s)
+    { soap_end_block(soap, NULL);
+      return NULL;
+    }
+    for (i = 0; i < SOAP_BLKLEN; i++)
+    { register char d1, d2;
+      register soap_wchar c = soap_get(soap);
+      if (soap_isxdigit(c))
+      { d1 = (char)c;
+        c = soap_get(soap);
+        if (soap_isxdigit(c))
+          d2 = (char)c;
+        else
+        { soap_end_block(soap, NULL);
+          soap->error = SOAP_TYPE;
+          return NULL;
+        }
+      }
+      else
+      { unsigned char *p;
+        soap_unget(soap, c);
+        if (n)
+          *n = (int)soap_size_block(soap, NULL, i);
+        p = (unsigned char*)soap_save_block(soap, NULL, 0);
+        return p;
+      }
+      *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
+    }
+  }
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putbase64(struct soap *soap, const unsigned char *s, int n)
+{ register int i;
+  register unsigned long m;
+  char d[4];
+  if (!s)
+    return SOAP_OK;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
+      return soap->error;
+    return SOAP_OK;
+  }
+#endif
+  for (; n > 2; n -= 3, s += 3)
+  { m = s[0];
+    m = (m << 8) | s[1];
+    m = (m << 8) | s[2];
+    for (i = 4; i > 0; m >>= 6)
+      d[--i] = soap_base64o[m & 0x3F];
+    if (soap_send_raw(soap, d, 4))
+      return soap->error;
+  }
+  if (n > 0)
+  { m = 0;
+    for (i = 0; i < n; i++)
+      m = (m << 8) | *s++;
+    for (; i < 3; i++)
+      m <<= 8;
+    for (i++; i > 0; m >>= 6)
+      d[--i] = soap_base64o[m & 0x3F];
+    for (i = 3; i > n; i--)
+      d[i] = '=';
+    if (soap_send_raw(soap, d, 4))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+unsigned char*
+SOAP_FMAC2
+soap_getbase64(struct soap *soap, int *n, int malloc_flag)
+{ (void)malloc_flag;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { soap->dom->data = soap_string_in(soap, 0, -1, -1);
+    return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
+  }
+#endif
+#ifdef WITH_FAST
+  soap->labidx = 0;
+  for (;;)
+  { register size_t i, k;
+    register char *s;
+    if (soap_append_lab(soap, NULL, 2))
+      return NULL;
+    s = soap->labbuf + soap->labidx;
+    k = soap->lablen - soap->labidx;
+    soap->labidx = 3 * (soap->lablen / 3);
+    if (!s)
+      return NULL;
+    if (k > 2)
+    { for (i = 0; i < k - 2; i += 3)
+      { register unsigned long m = 0;
+        register int j = 0;
+        do
+        { register soap_wchar c = soap_get(soap);
+          if (c < SOAP_AP)
+            c &= 0x7FFFFFFF;
+          if (c == '=' || c < 0)
+          { unsigned char *p;
+            switch (j)
+            { case 2:
+                *s++ = (char)((m >> 4) & 0xFF);
+                i++;
+                break;
+              case 3:
+                *s++ = (char)((m >> 10) & 0xFF);
+                *s++ = (char)((m >> 2) & 0xFF);
+                i += 2;
+            }
+            if (n)
+              *n = (int)(soap->lablen + i - k);
+            p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
+            if (p)
+              memcpy(p, soap->labbuf, soap->lablen + i - k);
+            if (c >= 0)
+            { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
+                ;
+            }
+            soap_unget(soap, c);
+            return p;
+          }
+          c -= '+';
+          if (c >= 0 && c <= 79)
+          { register int b = soap_base64i[c];
+            if (b >= 64)
+            { soap->error = SOAP_TYPE;
+              return NULL;
+            }
+            m = (m << 6) + b;
+            j++;
+          }
+          else if (!soap_blank(c + '+'))
+          { soap->error = SOAP_TYPE;
+            return NULL;
+          }
+        } while (j < 4);
+        *s++ = (char)((m >> 16) & 0xFF);
+        *s++ = (char)((m >> 8) & 0xFF);
+        *s++ = (char)(m & 0xFF);
+      }
+    }
+  }
+#else
+  if (soap_new_block(soap) == NULL)
+    return NULL;
+  for (;;)
+  { register int i;
+    register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
+    if (!s)
+    { soap_end_block(soap, NULL);
+      return NULL;
+    }
+    for (i = 0; i < SOAP_BLKLEN; i++)
+    { register unsigned long m = 0;
+      register int j = 0;
+      do
+      { register soap_wchar c = soap_get(soap);
+        if (c == '=' || c < 0)
+        { unsigned char *p;
+          i *= 3;
+          switch (j)
+          { case 2:
+              *s++ = (char)((m >> 4) & 0xFF);
+              i++;
+              break;
+            case 3:
+              *s++ = (char)((m >> 10) & 0xFF);
+              *s++ = (char)((m >> 2) & 0xFF);
+              i += 2;
+          }
+          if (n)
+            *n = (int)soap_size_block(soap, NULL, i);
+          p = (unsigned char*)soap_save_block(soap, NULL, 0);
+          if (c >= 0)
+          { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
+              ;
+          }
+          soap_unget(soap, c);
+          return p;
+        }
+        c -= '+';
+        if (c >= 0 && c <= 79)
+        { int b = soap_base64i[c];
+          if (b >= 64)
+          { soap->error = SOAP_TYPE;
+            return NULL;
+          }
+          m = (m << 6) + b;
+          j++;
+        }
+        else if (!soap_blank(c))
+        { soap->error = SOAP_TYPE;
+          return NULL;
+        }
+      } while (j < 4);
+      *s++ = (char)((m >> 16) & 0xFF);
+      *s++ = (char)((m >> 8) & 0xFF);
+      *s++ = (char)(m & 0xFF);
+    }
+  }
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
+{ /* Check MTOM xop:Include element (within hex/base64Binary) */
+  /* TODO: this code to be obsoleted with new import/xop.h conventions */
+  short body = soap->body; /* should save type too? */
+  if (!soap_peek_element(soap))
+  { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL))
+    { if (soap_dime_forward(soap, ptr, size, id, type, options)
+       || (soap->body && soap_element_end_in(soap, "xop:Include")))
+        return soap->error;
+    }
+  }
+  soap->body = body;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
+{ struct soap_xlist *xp;
+  *ptr = NULL;
+  *size = 0;
+  *id = NULL;
+  *type = NULL;
+  *options = NULL;
+  if (!*soap->href)
+    return SOAP_OK;
+  *id = soap_strdup(soap, soap->href);
+  xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
+  if (!xp)
+    return soap->error = SOAP_EOM;
+  xp->next = soap->xlist;
+  xp->ptr = ptr;
+  xp->size = size;
+  xp->id = *id;
+  xp->type = type;
+  xp->options = options;
+  soap->xlist = xp;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_strdup(struct soap *soap, const char *s)
+{ char *t = NULL;
+  if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
+    strcpy(t, s);
+  return t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+wchar_t *
+SOAP_FMAC2
+soap_wstrdup(struct soap *soap, const wchar_t *s)
+{ wchar_t *t = NULL;
+  if (s)
+  { size_t n = 0;
+    while (s[n])
+      n++;
+    if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1))))
+      memcpy(t, s, sizeof(wchar_t)*(n+1));
+  }
+  return t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap_blist*
+SOAP_FMAC2
+soap_new_block(struct soap *soap)
+{ struct soap_blist *p;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
+  if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  p->next = soap->blist;
+  p->ptr = NULL;
+  p->size = 0;
+  soap->blist = p;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
+{ char *p;
+  if (!b)
+    b = soap->blist;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n));
+  if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  *(char**)p = b->ptr;
+  *(size_t*)(p + sizeof(char*)) = n;
+  b->ptr = p;
+  b->size += n;
+  return p + sizeof(char*) + sizeof(size_t);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_pop_block(struct soap *soap, struct soap_blist *b)
+{ char *p;
+  if (!b)
+    b = soap->blist;
+  if (!b->ptr)
+    return;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
+  p = b->ptr;
+  b->size -= *(size_t*)(p + sizeof(char*));
+  b->ptr = *(char**)p;
+  SOAP_FREE(soap, p);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_update_pointers(struct soap *soap, char *start, char *end, char *p1, char *p2)
+{
+#ifndef WITH_NOIDREF
+  int i;
+  register struct soap_ilist *ip = NULL;
+  register struct soap_flist *fp = NULL;
+#ifndef WITH_LEANER
+  register struct soap_xlist *xp = NULL;
+#endif
+  register void *p, **q;
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = ip->next)
+    { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
+        ip->ptr = (char*)ip->ptr + (p1-p2);
+      }
+      for (q = &ip->link; q; q = (void**)p)
+      { p = *q;
+        if (p && (char*)p >= start && (char*)p < end)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
+          *q = (char*)p + (p1-p2);
+        }
+      }
+      for (q = &ip->copy; q; q = (void**)p)
+      { p = *q;
+        if (p && (char*)p >= start && (char*)p < end)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
+          *q = (char*)p + (p1-p2);
+        }
+      }
+      for (fp = ip->flist; fp; fp = fp->next)
+      { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
+          fp->ptr = (char*)fp->ptr + (p1-p2);
+        }
+      }
+    }
+  }
+#ifndef WITH_LEANER
+  for (xp = soap->xlist; xp; xp = xp->next)
+  { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id ? xp->id : SOAP_STR_EOS, xp->ptr, (char*)xp->ptr + (p1-p2)));
+      xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
+      xp->size = (int*)((char*)xp->size + (p1-p2));
+      xp->type = (char**)((char*)xp->type + (p1-p2));
+      xp->options = (char**)((char*)xp->options + (p1-p2));
+    }
+  }
+#endif
+#else
+  (void)soap; (void)start; (void)end; (void)p1; (void)p2;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_1
+static int
+soap_has_copies(struct soap *soap, register const char *start, register const char *end)
+{ register int i;
+  register struct soap_ilist *ip = NULL;
+  register struct soap_flist *fp = NULL;
+  register const char *p;
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = ip->next)
+    { for (p = (const char*)ip->copy; p; p = *(const char**)p)
+        if (p >= start && p < end)
+          return SOAP_ERR;
+      for (fp = ip->flist; fp; fp = fp->next)
+        if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
+          return SOAP_ERR;
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_resolve(struct soap *soap)
+{ register int i;
+  register struct soap_ilist *ip = NULL;
+  register struct soap_flist *fp = NULL;
+  short flag;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = ip->next)
+    { if (ip->ptr)
+      { register void *p, **q, *r;
+        q = (void**)ip->link;
+        ip->link = NULL;
+        r = ip->ptr;
+        DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
+        while (q)
+        { p = *q;
+          *q = r;
+          DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
+          q = (void**)p;
+        }
+      }
+      else if (*ip->id == '#')
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
+        strcpy(soap->id, ip->id + 1);
+        return soap->error = SOAP_MISSING_ID;
+      }
+    }
+  }
+  do
+  { flag = 0;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
+    for (i = 0; i < SOAP_IDHASH; i++)
+    { for (ip = soap->iht[i]; ip; ip = ip->next)
+      { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
+        { if (ip->copy)
+          { register void *p, **q = (void**)ip->copy;
+            DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
+            ip->copy = NULL;
+            do
+            { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
+              p = *q;
+              memcpy(q, ip->ptr, ip->size);
+              q = (void**)p;
+            } while (q);
+            flag = 1;
+          }
+          for (fp = ip->flist; fp; fp = ip->flist)
+          { register unsigned int k = fp->level;
+            register void *p = ip->ptr;
+            DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id));
+            while (ip->level < k)
+            { register void **q = (void**)soap_malloc(soap, sizeof(void*));
+              if (!q)
+                return soap->error;
+              *q = p;
+              DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
+              p = (void*)q;
+              k--;
+            }
+            if (fp->fcopy)
+              fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
+            else
+              soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
+            ip->flist = fp->next;
+            SOAP_FREE(soap, fp);
+            flag = 1;
+          }
+        }
+      }
+    }
+  } while (flag);
+#ifdef SOAP_DEBUG
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = ip->next)
+    { if (ip->copy || ip->flist)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id));
+      }
+    }
+  }
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
+{ if (!b)
+    b = soap->blist;
+  if (b->ptr)
+  { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n;
+    *(size_t*)(b->ptr + sizeof(char*)) = n;
+  }
+  return b->size;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_first_block(struct soap *soap, struct soap_blist *b)
+{ char *p, *q, *r;
+  if (!b)
+    b = soap->blist;
+  p = b->ptr;
+  if (!p)
+    return NULL;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
+  r = NULL;
+  do
+  { q = *(char**)p;
+    *(char**)p = r;
+    r = p;
+    p = q;
+  } while (p);
+  b->ptr = r;
+  return r + sizeof(char*) + sizeof(size_t);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_next_block(struct soap *soap, struct soap_blist *b)
+{ char *p;
+  if (!b)
+    b = soap->blist;
+  p = b->ptr;
+  if (p)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
+    b->ptr = *(char**)p;
+    SOAP_FREE(soap, p);
+    if (b->ptr)
+      return b->ptr + sizeof(char*) + sizeof(size_t);
+  }
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_block_size(struct soap *soap, struct soap_blist *b)
+{ if (!b)
+    b = soap->blist;
+  return *(size_t*)(b->ptr + sizeof(char*));
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_end_block(struct soap *soap, struct soap_blist *b)
+{ char *p, *q;
+  if (!b)
+    b = soap->blist;
+  if (b)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
+    for (p = b->ptr; p; p = q)
+    { q = *(char**)p;
+      SOAP_FREE(soap, p);
+    }
+    if (soap->blist == b)
+      soap->blist = b->next;
+    else
+    { struct soap_blist *bp;
+      for (bp = soap->blist; bp; bp = bp->next)
+      { if (bp->next == b)
+        { bp->next = b->next;
+          break;
+        }
+      }
+    }
+    SOAP_FREE(soap, b);
+  }
+  DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
+{ register size_t n;
+  register char *q, *s;
+  if (!b)
+    b = soap->blist;
+  if (b->size)
+  { if (!p)
+      p = (char*)soap_malloc(soap, b->size);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)b->size, b->ptr, p));
+    if (p)
+    { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
+      { n = soap_block_size(soap, b);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
+#ifndef WITH_NOIDREF
+        if (flag)
+          soap_update_pointers(soap, q, q + n, s, q);
+#endif
+        memcpy(s, q, n);
+        s += n;
+      }
+    }
+    else
+      soap->error = SOAP_EOM;
+  }
+  soap_end_block(soap, b);
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putsize(struct soap *soap, const char *type, int size)
+{ return soap_putsizes(soap, type, &size, 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
+{ return soap_putsizesoffsets(soap, type, size, NULL, dim);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
+{ register int i;
+  register size_t l;
+  if (!type || strlen(type) + 13 > sizeof(soap->type)) /* prevent overruns */
+    return NULL;
+  if (soap->version == 2)
+  { 
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
+#else
+    sprintf(soap->type, "%s[%d", type, size[0]);
+#endif
+    for (i = 1; i < dim; i++)
+    { 
+#ifdef HAVE_SNPRINTF
+      l = strlen(soap->type);
+      soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, " %d", size[i]);
+#else
+      if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
+        return NULL;
+      sprintf(soap->type + l, " %d", size[i]);
+#endif
+    }
+  }
+  else
+  { if (offset)
+    {
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0] + offset[0]);
+#else
+      sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
+#endif
+      for (i = 1; i < dim; i++)
+      {
+#ifdef HAVE_SNPRINTF
+        l = strlen(soap->type);
+        soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i] + offset[i]);
+#else
+        if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
+          return NULL;
+        sprintf(soap->type + l, ",%d", size[i] + offset[i]);
+#endif
+      }
+    }
+    else
+    { 
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
+#else
+      sprintf(soap->type, "%s[%d", type, size[0]);
+#endif
+      for (i = 1; i < dim; i++)
+      {
+#ifdef HAVE_SNPRINTF
+        l = strlen(soap->type);
+        soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i]);
+#else
+        if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
+          return NULL;
+        sprintf(soap->type + l, ",%d", size[i]);
+#endif
+      }
+    }
+  }
+  strcat(soap->type, "]");
+  return soap->type;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putoffset(struct soap *soap, int offset)
+{ return soap_putoffsets(soap, &offset, 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_putoffsets(struct soap *soap, const int *offset, int dim)
+{ register int i;
+  register size_t l;
+#ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, "[%d", offset[0]);
+#else
+  if (sizeof(soap->arrayOffset) < 13) /* prevent overruns */
+    return NULL;
+  sprintf(soap->arrayOffset, "[%d", offset[0]);
+#endif
+  for (i = 1; i < dim; i++)
+  {
+#ifdef HAVE_SNPRINTF
+    l = strlen(soap->arrayOffset);
+    soap_snprintf(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, ",%d", offset[i]);
+#else
+    if ((l = strlen(soap->arrayOffset)) + 13 > sizeof(soap->arrayOffset))
+      return NULL;
+    sprintf(soap->arrayOffset + l, ",%d", offset[i]);
+#endif
+  }
+  strcat(soap->arrayOffset, "]");
+  return soap->arrayOffset;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_size(const int *size, int dim)
+{ register int i, n = size[0];
+  for (i = 1; i < dim; i++)
+    n *= size[i];
+  return n;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
+{ register int i, j = 0;
+  if (offset)
+    for (i = 0; i < dim && attr && *attr; i++)
+    { attr++;
+      j *= size[i];
+      j += offset[i] = (int)soap_strtol(attr, NULL, 10);
+      attr = strchr(attr, ',');
+    }
+  else
+    for (i = 0; i < dim && attr && *attr; i++)
+    { attr++;
+      j *= size[i];
+      j += (int)soap_strtol(attr, NULL, 10);
+      attr = strchr(attr, ',');
+    }
+  return j;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getsize(const char *attr1, const char *attr2, int *j)
+{ register int n, k;
+  char *s;
+  *j = 0;
+  if (!*attr1)
+    return -1;
+  if (*attr1 == '[')
+    attr1++;
+  n = 1;
+  for (;;)
+  { k = (int)soap_strtol(attr1, &s, 10);
+    n *= k;
+    if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
+      return -1;
+    attr1 = strchr(s, ',');
+    if (!attr1)
+      attr1 = strchr(s, ' ');
+    if (attr2 && *attr2)
+    { attr2++;
+      *j *= k;
+      k = (int)soap_strtol(attr2, &s, 10);
+      *j += k;
+      if (k < 0)
+        return -1;
+      attr2 = s;
+    }
+    if (!attr1)
+      break;
+    attr1++;
+  }
+  return n - *j;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getsizes(const char *attr, int *size, int dim)
+{ register int i, k, n;
+  if (!*attr)
+    return -1;
+  i = (int)strlen(attr);
+  n = 1;
+  do
+  { for (i = i-1; i >= 0; i--)
+      if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
+        break;
+    k = (int)soap_strtol(attr + i + 1, NULL, 10);
+    n *= size[--dim] = k;
+    if (k < 0 || n > SOAP_MAXARRAYSIZE)
+      return -1;
+  } while (i >= 0 && attr[i] != '[');
+  return n;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getposition(const char *attr, int *pos)
+{ register int i, n;
+  if (!*attr)
+    return -1;
+  n = 0;
+  i = 1;
+  do
+  { pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
+    while (attr[i] && attr[i] != ',' && attr[i] != ']')
+      i++;
+    if (attr[i] == ',')
+      i++;
+  } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
+  return n;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+struct soap_nlist *
+SOAP_FMAC2
+soap_push_namespace(struct soap *soap, const char *id, const char *ns)
+{ register struct soap_nlist *np;
+  register struct Namespace *p;
+  register short i = -1;
+  register size_t n, k;
+  n = strlen(id);
+  k = strlen(ns) + 1;
+  p = soap->local_namespaces;
+  if (p)
+  { for (i = 0; p->id; p++, i++)
+    { if (p->ns && !strcmp(ns, p->ns))
+        break;
+      if (p->out)
+      { if (!strcmp(ns, p->out))
+          break;
+      }
+      else if (p->in)
+      { if (!soap_tag_cmp(ns, p->in))
+        { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
+            strcpy(p->out, ns);
+          break;
+        }
+      }
+    }
+    if (!p || !p->id)
+      i = -1;
+  }
+  if (i >= 0)
+    k = 0;
+  np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
+  if (!np)
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  np->next = soap->nlist;
+  soap->nlist = np;
+  np->level = soap->level;
+  np->index = i;
+  strcpy((char*)np->id, id);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
+  if (i < 0)
+  { np->ns = strcpy((char*)np->id + n + 1, ns);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
+  }
+  else
+  { np->ns = NULL;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
+  }
+  return np;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_pop_namespace(struct soap *soap)
+{ register struct soap_nlist *np, *nq;
+  for (np = soap->nlist; np && np->level >= soap->level; np = nq)
+  { nq = np->next;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
+    SOAP_FREE(soap, np);
+  }
+  soap->nlist = np;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
+{ register struct soap_nlist *np = soap->nlist;
+  const char *s;
+  while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
+    np = np->next;
+  if (np)
+  { if (!(soap->mode & SOAP_XML_IGNORENS))
+      if (np->index < 0
+       || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))
+        return SOAP_NAMESPACE;
+    return SOAP_OK;
+  }
+  if (n1 == 0)
+    return (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;
+  if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
+   || (soap->mode & SOAP_XML_IGNORENS))
+    return SOAP_OK;
+  return soap->error = SOAP_SYNTAX_ERROR;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_current_namespace(struct soap *soap, const char *tag)
+{ register struct soap_nlist *np;
+  register const char *s;
+  if (!tag || !strncmp(tag, "xml", 3))
+    return NULL;
+  np = soap->nlist;
+  if (!(s = strchr(tag, ':')))
+  { while (np && *np->id) /* find default namespace, if present */
+      np = np->next;
+  }
+  else
+  { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
+      np = np->next;
+    if (!np)
+      soap->error = SOAP_NAMESPACE;
+  }
+  if (np)
+  { if (np->index >= 0)
+      return soap->namespaces[np->index].ns;
+    if (np->ns)
+      return soap_strdup(soap, np->ns);
+  }
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_tag_cmp(const char *s, const char *t)
+{ for (;;)
+  { register int c1 = *s;
+    register int c2 = *t;
+    if (!c1 || c1 == '"')
+      break;
+    if (c2 != '-')
+    { if (c1 != c2)
+      { if (c1 >= 'A' && c1 <= 'Z')
+          c1 += 'a' - 'A';
+        if (c2 >= 'A' && c2 <= 'Z')
+          c2 += 'a' - 'A';
+      }
+      if (c1 != c2)
+      { if (c2 != '*')
+          return 1;
+        c2 = *++t;
+        if (!c2)
+          return 0;
+        if (c2 >= 'A' && c2 <= 'Z')
+          c2 += 'a' - 'A';
+        for (;;)
+        { c1 = *s;
+          if (!c1 || c1 == '"')
+            break;
+          if (c1 >= 'A' && c1 <= 'Z')
+            c1 += 'a' - 'A';
+          if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
+            return 0;
+          s++;
+        }
+        break;
+      }
+    }
+    s++;
+    t++;
+  }
+  if (*t == '*' && !t[1])
+    return 0;
+  return *t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
+{ register const char *s, *t;
+  register int err;
+  if (!tag1 || !tag2 || !*tag2)
+    return SOAP_OK;
+  s = strchr(tag1, ':');
+  t = strchr(tag2, ':');
+  if (t)
+  { if (s)
+    { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
+        return SOAP_TAG_MISMATCH;
+      if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
+        if (err == SOAP_NAMESPACE)
+          return SOAP_TAG_MISMATCH;
+        return err;
+      }
+    }
+    else if (!t[1])
+    { err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);
+      if (err == SOAP_NAMESPACE)
+        return SOAP_TAG_MISMATCH;
+    }
+    else if (SOAP_STRCMP(tag1, t + 1))
+    { return SOAP_TAG_MISMATCH;
+    }
+    else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
+      if (err == SOAP_NAMESPACE)
+        return SOAP_TAG_MISMATCH;
+      return err;
+    }
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
+    return SOAP_OK;
+  }
+  if (s)
+  { if (SOAP_STRCMP(s + 1, tag2))
+      return SOAP_TAG_MISMATCH;
+  }
+  else if (SOAP_STRCMP(tag1, tag2))
+    return SOAP_TAG_MISMATCH;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_match_array(struct soap *soap, const char *type)
+{ if (*soap->arrayType)
+    if (soap_match_tag(soap, soap->arrayType, type)
+     && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
+     && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
+    )
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
+      return SOAP_TAG_MISMATCH;
+    }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************\
+ *
+ *	SSL/TLS
+ *
+\******************************************************************************/
+
+/******************************************************************************/
+#ifdef WITH_OPENSSL
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_rand()
+{ unsigned char buf[4];
+  if (!soap_ssl_init_done)
+    soap_ssl_init();
+  RAND_pseudo_bytes(buf, 4);
+  return *(int*)buf;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
+#else
+soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
+#endif
+{ int err;
+  soap->keyfile = keyfile;
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+  soap->keyid = keyid;
+#endif
+  soap->password = password;
+  soap->cafile = cafile;
+  soap->capath = capath;
+  soap->crlfile = NULL;
+#ifdef WITH_OPENSSL
+  soap->dhfile = dhfile;
+  soap->randfile = randfile;
+#endif
+  soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
+#ifdef WITH_GNUTLS
+  if (dhfile)
+  { char *s;
+    int n = (int)soap_strtoul(dhfile, &s, 10);
+    if (!soap->dh_params)
+      gnutls_dh_params_init(&soap->dh_params);
+    /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
+    if (n >= 512 && s && *s == '\0')
+      gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n);
+    else
+    { unsigned int dparams_len;
+      unsigned char dparams_buf[1024];
+      FILE *fd = fopen(dhfile, "r");
+      if (!fd)
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
+      dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd);
+      fclose(fd);
+      gnutls_datum_t dparams = { dparams_buf, dparams_len };
+      if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM))
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
+    }
+  }
+  else
+  { if (!soap->rsa_params)
+      gnutls_rsa_params_init(&soap->rsa_params);
+    gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS);
+  }
+  if (soap->session)
+  { gnutls_deinit(soap->session);
+    soap->session = NULL;
+  }
+  if (soap->xcred)
+  { gnutls_certificate_free_credentials(soap->xcred);
+    soap->xcred = NULL;
+  }
+#endif
+  err = soap->fsslauth(soap);
+#ifdef WITH_OPENSSL
+  if (!err)
+  { if (sid)
+      SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
+    else
+      SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
+  }
+#endif
+  return err;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *randfile)
+#else
+soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile)
+#endif
+{ soap->keyfile = keyfile;
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+  soap->keyid = keyid;
+#endif
+  soap->password = password;
+  soap->cafile = cafile;
+  soap->capath = capath;
+  soap->ssl_flags = SOAP_SSL_CLIENT | flags;
+#ifdef WITH_OPENSSL
+  soap->dhfile = NULL;
+  soap->randfile = randfile;
+  soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
+#endif
+#ifdef WITH_GNUTLS
+  if (soap->session)
+  { gnutls_deinit(soap->session);
+    soap->session = NULL;
+  }
+  if (soap->xcred)
+  { gnutls_certificate_free_credentials(soap->xcred);
+    soap->xcred = NULL;
+  }
+#endif
+  return soap->fsslauth(soap);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_ssl_init()
+{ /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
+  if (!soap_ssl_init_done)
+  { soap_ssl_init_done = 1;
+#ifdef WITH_OPENSSL
+    SSL_library_init();
+    OpenSSL_add_all_algorithms(); /* 2.8.1 change (wsseapi.c) */
+    OpenSSL_add_all_digests();
+#ifndef WITH_LEAN
+    SSL_load_error_strings();
+#endif
+    if (!RAND_load_file("/dev/urandom", 1024))
+    { char buf[1024];
+      RAND_seed(buf, sizeof(buf));
+      while (!RAND_status())
+      { int r = rand();
+        RAND_seed(&r, sizeof(int));
+      }
+    }
+#endif
+#ifdef WITH_GNUTLS
+# if defined(HAVE_PTHREAD_H)
+    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+# elif defined(HAVE_PTH_H)
+    gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
+# endif
+    gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
+    gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
+    gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */
+    gnutls_global_init();
+#endif
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+#ifndef PALM_1
+SOAP_FMAC1
+const char *
+SOAP_FMAC2
+soap_ssl_error(struct soap *soap, int ret)
+{
+#ifdef WITH_OPENSSL
+  int err = SSL_get_error(soap->ssl, ret);
+  const char *msg = soap_code_str(h_ssl_error_codes, err);
+  if (msg)
+    strcpy(soap->msgbuf, msg);
+  else
+    return ERR_error_string(err, soap->msgbuf);
+  if (ERR_peek_error())
+  { unsigned long r;
+    strcat(soap->msgbuf, "\n");
+    while ((r = ERR_get_error()))
+      ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
+  }
+  else
+  { switch (ret)
+    { case 0:
+        strcpy(soap->msgbuf, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information.");
+        break;
+      case -1:
+#ifdef HAVE_SNPRINTF
+        soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error observed by underlying SSL/TLS BIO: %s", strerror(errno));
+#else
+        { const char *s = strerror(errno);
+          size_t l = strlen(s);
+          sprintf(soap->msgbuf, "Error observed by underlying SSL/TLS BIO: %s", l + 44 < sizeof(soap->msgbuf) ? s : SOAP_STR_EOS);
+        }
+#endif
+        break;
+    }
+  }
+  return soap->msgbuf;
+#endif
+#ifdef WITH_GNUTLS
+  return gnutls_strerror(ret);
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+#ifndef PALM_1
+static int
+ssl_auth_init(struct soap *soap)
+{
+#ifdef WITH_OPENSSL
+  long flags;
+  int mode;
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+  EVP_PKEY* pkey;
+#endif
+  if (!soap_ssl_init_done)
+    soap_ssl_init();
+  ERR_clear_error();
+  if (!soap->ctx)
+  { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR);
+    /* The following alters the behavior of SSL read/write: */
+#if 0
+    SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
+#endif
+  }
+  if (soap->randfile)
+  { if (!RAND_load_file(soap->randfile, -1))
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR);
+  }
+  if (soap->cafile || soap->capath)
+  { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
+    if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
+      SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
+  }
+  if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
+  { if (!SSL_CTX_set_default_verify_paths(soap->ctx))
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
+  }
+/* This code assumes a typical scenario, see alternative code below */
+  if (soap->keyfile)
+  { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR);
+    if (soap->password)
+    { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
+      SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
+    }
+    if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
+#ifndef WM_SECURE_KEY_STORAGE
+    if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
+#endif
+  }
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+  if (NULL == (pkey = ipcom_key_db_pkey_get(soap->keyid)))
+    return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR);
+  if (0 == SSL_CTX_use_PrivateKey(soap->ctx, pkey))
+    return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR);
+#endif
+/* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
+#if 0
+  if (soap->password)
+  { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
+    SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
+  }
+  if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
+  { if (soap->keyfile)
+    { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR);
+      if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
+    }
+  }
+#endif
+  if ((soap->ssl_flags & SOAP_SSL_RSA))
+  { RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL);
+    if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
+    { if (rsa)
+        RSA_free(rsa);
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR);
+    }
+    RSA_free(rsa);
+  }
+  else if (soap->dhfile)
+  { DH *dh = 0;
+    char *s;
+    int n = (int)soap_strtoul(soap->dhfile, &s, 10);
+    /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
+    if (n >= 512 && s && *s == '\0')
+#if defined(VXWORKS)
+      DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL);
+#else
+      dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
+#endif
+    else
+    { BIO *bio;
+      bio = BIO_new_file(soap->dhfile, "r");
+      if (!bio)
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR);
+      dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
+      BIO_free(bio);
+    }
+    if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
+    { if (dh)
+        DH_free(dh);
+      return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR);
+    }
+    DH_free(dh);
+  }
+  flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); /* disable SSL v2 */
+  if ((soap->ssl_flags & SOAP_SSLv3))
+    flags |= SSL_OP_NO_TLSv1;
+  if ((soap->ssl_flags & SOAP_TLSv1))
+    flags |= SSL_OP_NO_SSLv3;
+#ifdef SSL_OP_NO_TICKET
+  /* TLS extension is enabled by default in OPENSSL v0.9.8k
+     Disable it by adding SSL_OP_NO_TICKET */
+  flags |= SSL_OP_NO_TICKET;
+#endif
+  SSL_CTX_set_options(soap->ctx, flags);
+  if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
+    mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
+  else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
+    mode = SSL_VERIFY_PEER;
+  else
+    mode = SSL_VERIFY_NONE;
+  SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
+#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
+  SSL_CTX_set_verify_depth(soap->ctx, 1);
+#else
+  SSL_CTX_set_verify_depth(soap->ctx, 9);
+#endif
+#endif
+#ifdef WITH_GNUTLS
+  int ret;
+  if (!soap_ssl_init_done)
+    soap_ssl_init();
+  if (!soap->xcred)
+  { gnutls_certificate_allocate_credentials(&soap->xcred);
+    if (soap->cafile)
+    { if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0)
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
+    }
+    if (soap->crlfile)
+    { if (gnutls_certificate_set_x509_crl_file(soap->xcred, soap->crlfile, GNUTLS_X509_FMT_PEM) < 0)
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR);
+    }
+    if (soap->keyfile)
+    { if (gnutls_certificate_set_x509_key_file(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM) < 0) /* TODO: GNUTLS need to concat cert and key in single key file */
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
+    }
+  }
+  if ((soap->ssl_flags & SOAP_SSL_CLIENT))
+  { gnutls_init(&soap->session, GNUTLS_CLIENT);
+    if (soap->cafile || soap->crlfile || soap->keyfile)
+    { ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL);
+      if (ret < 0)
+        return soap_set_receiver_error(soap, soap_ssl_error(soap, ret), "SSL/TLS set priority error", SOAP_SSL_ERROR);
+      gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
+    }
+    else
+    { if (!soap->acred)
+        gnutls_anon_allocate_client_credentials(&soap->acred);
+      gnutls_init(&soap->session, GNUTLS_CLIENT);
+      gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL);
+      gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred);
+    }
+  }
+  else
+  { if (!soap->keyfile)
+      return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR);
+    if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params)
+      gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params);
+    else if (soap->dh_params)
+      gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params);
+    if (!soap->cache)
+      gnutls_priority_init(&soap->cache, "NORMAL", NULL);
+    gnutls_init(&soap->session, GNUTLS_SERVER);
+    gnutls_priority_set(soap->session, soap->cache);
+    gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
+    if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
+      gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST);
+    gnutls_session_enable_compatibility_mode(soap->session);
+    if ((soap->ssl_flags & SOAP_TLSv1))
+    { int protocol_priority[] = { GNUTLS_TLS1_0, 0 };
+      if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS)
+        return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR);
+    }
+  }
+#endif
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef WITH_OPENSSL
+#ifndef PALM_1
+static int
+ssl_password(char *buf, int num, int rwflag, void *userdata)
+{ if (num < (int)strlen((char*)userdata) + 1)
+    return 0;
+  return (int)strlen(strcpy(buf, (char*)userdata));
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef WITH_OPENSSL
+#ifndef PALM_1
+static int
+ssl_verify_callback(int ok, X509_STORE_CTX *store)
+{
+#ifdef SOAP_DEBUG
+  if (!ok)
+  { char buf[1024];
+    int err = X509_STORE_CTX_get_error(store);
+    X509 *cert = X509_STORE_CTX_get_current_cert(store);
+    fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(err));
+    X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
+    fprintf(stderr, "certificate issuer %s\n", buf);
+    X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
+    fprintf(stderr, "certificate subject %s\n", buf);
+    /* accept self signed certificates and certificates out of date */
+    switch (err)
+    { case X509_V_ERR_CERT_NOT_YET_VALID:
+      case X509_V_ERR_CERT_HAS_EXPIRED:
+      case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+      case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+        X509_STORE_CTX_set_error(store, X509_V_OK);
+        ok = 1;
+    }
+  }
+#endif
+  /* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */
+  return ok;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef WITH_OPENSSL
+#ifndef PALM_1
+static int
+ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
+{ ok = ssl_verify_callback(ok, store);
+  if (!ok)
+  { /* accept self signed certificates and certificates out of date */
+    switch (X509_STORE_CTX_get_error(store))
+    { case X509_V_ERR_CERT_NOT_YET_VALID:
+      case X509_V_ERR_CERT_HAS_EXPIRED:
+      case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+      case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+        X509_STORE_CTX_set_error(store, X509_V_OK);
+        ok = 1;
+    }
+  }
+  /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
+  return ok;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef WITH_GNUTLS
+static const char *
+ssl_verify(struct soap *soap, const char *host)
+{ unsigned int status;
+  const char *err = NULL;
+  int r = gnutls_certificate_verify_peers2(soap->session, &status);
+  if (r < 0)
+    err = "Certificate verify error";
+  else if ((status & GNUTLS_CERT_INVALID))
+    err = "The certificate is not trusted";
+  else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND))
+    err = "The certificate hasn't got a known issuer";
+  else if ((status & GNUTLS_CERT_REVOKED))
+    err = "The certificate has been revoked";
+  else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509)
+  { gnutls_x509_crt_t cert;
+    const gnutls_datum_t *cert_list;
+    unsigned int cert_list_size;
+    if (gnutls_x509_crt_init(&cert) < 0)
+      err = "Could not get X509 certificates";
+    else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL)
+      err = "Could not get X509 certificates";
+    else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
+      err = "Error parsing X509 certificate";
+    else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
+      err = "The certificate has expired";
+    else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL))
+      err = "The certificate is not yet activated";
+    else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
+    { if (!gnutls_x509_crt_check_hostname(cert, host))
+        err = "Certificate host name mismatch";
+    }
+    gnutls_x509_crt_deinit(cert);
+  }
+  return err;
+}
+#endif
+
+/******************************************************************************/
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+#ifndef WITH_NOIO
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_ssl_accept(struct soap *soap)
+{ SOAP_SOCKET sk = soap->socket;
+#ifdef WITH_OPENSSL
+  BIO *bio;
+  int retries, r, s;
+  if (!soap_valid_socket(sk))
+    return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
+  soap->ssl_flags &= ~SOAP_SSL_CLIENT;
+  if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
+    return soap->error;
+  if (!soap->ssl)
+  { soap->ssl = SSL_new(soap->ctx);
+    if (!soap->ssl)
+      return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
+  }
+  else
+    SSL_clear(soap->ssl);
+  bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
+  SSL_set_bio(soap->ssl, bio, bio);
+  /* Set SSL sockets to non-blocking */
+  retries = 0;
+  if (soap->accept_timeout)
+  { SOAP_SOCKNONBLOCK(sk)
+    retries = 10*soap->accept_timeout;
+  }
+  if (retries <= 0)
+    retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
+  while ((r = SSL_accept(soap->ssl)) <= 0)
+  { int err;
+    if (retries-- <= 0)
+      break;
+    err = SSL_get_error(soap->ssl, r);
+    if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
+    { if (err == SSL_ERROR_WANT_READ)
+        s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
+      else
+        s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
+      if (s < 0)
+        break;
+    }
+    else
+    { soap->errnum = soap_socket_errno(sk);
+      break;
+    }
+  }
+  if (r <= 0)
+  { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
+    soap_closesock(soap);
+    return SOAP_SSL_ERROR;
+  }
+  if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
+  { X509 *peer;
+    int err;
+    if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
+    { soap_closesock(soap);
+      return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR);
+    }
+    peer = SSL_get_peer_certificate(soap->ssl);
+    if (!peer)
+    { soap_closesock(soap);
+      return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
+    }
+    X509_free(peer);
+  }
+#endif
+#ifdef WITH_GNUTLS
+  int retries = 0, r;
+  if (!soap_valid_socket(sk))
+    return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
+  soap->ssl_flags &= ~SOAP_SSL_CLIENT;
+  if (!soap->session && (soap->error = soap->fsslauth(soap)))
+  { soap_closesock(soap);
+    return soap->error;
+  }
+  gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
+  /* Set SSL sockets to non-blocking */
+  if (soap->accept_timeout)
+  { SOAP_SOCKNONBLOCK(sk)
+    retries = 10*soap->accept_timeout;
+  }
+  if (retries <= 0)
+    retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
+  while ((r = gnutls_handshake(soap->session)))
+  { int s;
+    /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
+    if (retries-- <= 0)
+      break;
+    if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
+    { if (!gnutls_record_get_direction(soap->session))
+        s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
+      else
+        s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
+      if (s < 0)
+        break;
+    }
+    else
+    { soap->errnum = soap_socket_errno(sk);
+      break;
+    }
+  }
+  if (r)
+  { soap_closesock(soap);
+    return soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
+  }
+  if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
+  { const char *err = ssl_verify(soap, NULL);
+    if (err)
+    { soap_closesock(soap);
+      return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
+    }
+  }
+#endif
+  if (soap->recv_timeout || soap->send_timeout)
+    SOAP_SOCKNONBLOCK(sk)
+  else
+    SOAP_SOCKBLOCK(sk)
+  soap->imode |= SOAP_ENC_SSL;
+  soap->omode |= SOAP_ENC_SSL;
+  return SOAP_OK;
+}
+#endif
+#endif
+#endif
+
+/******************************************************************************\
+ *
+ *	TCP/UDP [SSL/TLS] IPv4 and IPv6
+ *
+\******************************************************************************/
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static int
+tcp_init(struct soap *soap)
+{ soap->errmode = 1;
+#ifdef WIN32
+  if (tcp_done)
+    return 0;
+  else
+  { WSADATA w;
+    if (WSAStartup(MAKEWORD(1, 1), &w))
+      return -1;
+    tcp_done = 1;
+  }
+#endif
+  return 0;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static const char*
+tcp_error(struct soap *soap)
+{ register const char *msg = NULL;
+  switch (soap->errmode)
+  { case 0:
+      msg = soap_strerror(soap);
+      break;
+    case 1:
+      msg = "WSAStartup failed";
+      break;
+    case 2:
+    {
+#ifndef WITH_LEAN
+      msg = soap_code_str(h_error_codes, soap->errnum);
+      if (!msg)
+#endif
+      {
+#ifdef HAVE_SNPRINTF
+        soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "TCP/UDP IP error %d", soap->errnum);
+#else
+        sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
+#endif
+        msg = soap->msgbuf;
+      }
+    }
+  }
+  return msg;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_IPV6
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static int
+tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
+{ soap_int32 iadd = -1;
+  struct hostent hostent, *host = &hostent;
+#ifdef VXWORKS
+  int hostint;
+  /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
+  iadd = inet_addr((char*)addr);
+#else
+#if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
+  struct hostent_data ht_data;
+#endif
+#ifdef AS400
+  iadd = inet_addr((void*)addr);
+#else
+  iadd = inet_addr(addr);
+#endif
+#endif
+  if (iadd != -1)
+  { memcpy(inaddr, &iadd, sizeof(iadd));
+    return SOAP_OK;
+  }
+#if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) || defined(__ANDROID__)
+  if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
+    host = NULL;
+#elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
+  memset((void*)&ht_data, 0, sizeof(ht_data));
+  if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
+  { host = NULL;
+    soap->errnum = h_errno;
+  }
+#elif defined(HAVE_GETHOSTBYNAME_R)
+  host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
+#elif defined(VXWORKS)
+  /* If the DNS resolver library resolvLib has been configured in the vxWorks
+   * image, a query for the host IP address is sent to the DNS server, if the
+   * name was not found in the local host table. */
+  hostint = hostGetByName((char*)addr);
+  if (hostint == ERROR)
+  { host = NULL;
+    soap->errnum = soap_errno;
+  }
+#else
+#ifdef AS400
+  if (!(host = gethostbyname((void*)addr)))
+    soap->errnum = h_errno;
+#else
+  if (!(host = gethostbyname(addr)))
+    soap->errnum = h_errno;
+#endif
+#endif
+  if (!host)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
+    return SOAP_ERR;
+  }
+#ifdef VXWORKS
+  inaddr->s_addr = hostint;
+#else
+  memcpy(inaddr, host->h_addr, host->h_length);
+#endif
+  return SOAP_OK;
+}
+#endif
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static SOAP_SOCKET
+tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
+{
+#ifdef WITH_IPV6
+  struct addrinfo hints, *res, *ressave;
+#endif
+  SOAP_SOCKET sk;
+  int err = 0;
+#ifndef WITH_LEAN
+#ifndef WIN32
+  int len = SOAP_BUFLEN;
+#else
+  int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
+#endif
+  int set = 1;
+#endif
+#if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+  int retries;
+#endif
+  if (soap_valid_socket(soap->socket))
+    soap->fclosesocket(soap, soap->socket);
+  soap->socket = SOAP_INVALID_SOCKET;
+  if (tcp_init(soap))
+  { soap->errnum = 0;
+    soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  soap->errmode = 0;
+#ifdef WITH_IPV6
+  memset((void*)&hints, 0, sizeof(hints));
+  hints.ai_family = PF_UNSPEC;
+#ifndef WITH_LEAN
+  if ((soap->omode & SOAP_IO_UDP))
+    hints.ai_socktype = SOCK_DGRAM;
+  else
+#endif
+    hints.ai_socktype = SOCK_STREAM;
+  soap->errmode = 2;
+  if (soap->proxy_host)
+    err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
+  else
+    err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
+  if (err)
+  { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  ressave = res;
+again:
+  sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+  soap->errmode = 0;
+#else
+#ifndef WITH_LEAN
+again:
+#endif
+#ifndef WITH_LEAN
+  if ((soap->omode & SOAP_IO_UDP))
+    sk = socket(AF_INET, SOCK_DGRAM, 0);
+  else
+#endif
+    sk = socket(AF_INET, SOCK_STREAM, 0);
+#endif
+  if (!soap_valid_socket(sk))
+  {
+#ifdef WITH_IPV6
+    if (res->ai_next)
+    { res = res->ai_next;
+      goto again;
+    }
+#endif
+    soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+#ifdef SOCKET_CLOSE_ON_EXEC
+#ifdef WIN32
+#ifndef UNDER_CE
+  SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
+#endif
+#else
+  fcntl(sk, F_SETFD, 1);
+#endif
+#endif
+#ifndef WITH_LEAN
+  if (soap->connect_flags == SO_LINGER)
+  { struct linger linger;
+    memset((void*)&linger, 0, sizeof(linger));
+    linger.l_onoff = 1;
+    linger.l_linger = soap->linger_time;
+    if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
+    { soap->errnum = soap_socket_errno(sk);
+      soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
+      soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+      freeaddrinfo(ressave);
+#endif
+      return SOAP_INVALID_SOCKET;
+    }
+  }
+  else if (soap->connect_flags && setsockopt(sk, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+  if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+  if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+  if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+#ifdef TCP_KEEPIDLE
+  if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+#ifdef TCP_KEEPINTVL
+  if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+#ifdef TCP_KEEPCNT
+  if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, (SOAP_SOCKET)sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+#ifdef TCP_NODELAY
+  if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno(sk);
+    soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
+    soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+    freeaddrinfo(ressave);
+#endif
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+#ifdef WITH_IPV6
+  if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
+  { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
+    in6addr->sin6_scope_id = soap->ipv6_multicast_if;
+  }
+#endif
+#ifdef IP_MULTICAST_TTL
+  if ((soap->omode & SOAP_IO_UDP))
+  { if (soap->ipv4_multicast_ttl)
+    { unsigned char ttl = soap->ipv4_multicast_ttl;
+      if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
+      { soap->errnum = soap_socket_errno(sk);
+        soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
+        soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+    }
+    if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
+    { if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
+#ifndef WINDOWS
+      { soap->errnum = soap_socket_errno(sk);
+        soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
+        soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+#else
+#ifndef IP_MULTICAST_IF
+#define IP_MULTICAST_IF 2
+#endif
+      if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
+      { soap->errnum = soap_socket_errno(sk);
+        soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
+        soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+#endif
+    }
+  }
+#endif
+#endif
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", sk, host, port));
+#ifndef WITH_IPV6
+  soap->peerlen = sizeof(soap->peer);
+  memset((void*)&soap->peer, 0, sizeof(soap->peer));
+  soap->peer.sin_family = AF_INET;
+  soap->errmode = 2;
+  if (soap->proxy_host)
+  { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
+    { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
+      soap->fclosesocket(soap, sk);
+      return SOAP_INVALID_SOCKET;
+    }
+    soap->peer.sin_port = htons((short)soap->proxy_port);
+  }
+  else
+  { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
+    { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
+      soap->fclosesocket(soap, sk);
+      return SOAP_INVALID_SOCKET;
+    }
+    soap->peer.sin_port = htons((short)port);
+  }
+  soap->errmode = 0;
+#ifndef WITH_LEAN
+  if ((soap->omode & SOAP_IO_UDP))
+    return sk;
+#endif
+#else
+  if ((soap->omode & SOAP_IO_UDP))
+  { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen);
+    soap->peerlen = res->ai_addrlen;
+    freeaddrinfo(ressave);
+    return sk;
+  }
+#endif
+#ifndef WITH_LEAN
+  if (soap->connect_timeout)
+    SOAP_SOCKNONBLOCK(sk)
+  else
+    SOAP_SOCKBLOCK(sk)
+  retries = 10;
+#endif
+  for (;;)
+  {
+#ifdef WITH_IPV6
+    if (connect(sk, res->ai_addr, (int)res->ai_addrlen))
+#else
+    if (connect(sk, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
+#endif
+    { err = soap_socket_errno(sk);
+#ifndef WITH_LEAN
+      if (err == SOAP_EADDRINUSE)
+      { soap->fclosesocket(soap, sk);
+        if (retries-- > 0)
+          goto again;
+      }
+      else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
+      {
+        SOAP_SOCKLEN_T k;
+        for (;;)
+        { register int r;
+          r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout);
+          if (r > 0)
+            break;
+          if (!r)
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
+            soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
+            soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+            freeaddrinfo(ressave);
+#endif
+            return SOAP_INVALID_SOCKET;
+          }
+          r = soap->errnum = soap_socket_errno(sk);
+          if (r != SOAP_EINTR)
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
+            soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
+            soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+            freeaddrinfo(ressave);
+#endif
+            return SOAP_INVALID_SOCKET;
+          }
+        }
+        k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
+        if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum)	/* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
+          break;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
+        if (!soap->errnum)
+          soap->errnum = soap_socket_errno(sk);
+        soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
+        soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+        freeaddrinfo(ressave);
+#endif
+        return SOAP_INVALID_SOCKET;
+      }
+#endif
+#ifdef WITH_IPV6
+      if (res->ai_next)
+      { res = res->ai_next;
+        soap->fclosesocket(soap, sk);
+        goto again;
+      }
+#endif
+      if (err && err != SOAP_EINTR)
+      { soap->errnum = err;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
+        soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
+        soap->fclosesocket(soap, sk);
+#ifdef WITH_IPV6
+        freeaddrinfo(ressave);
+#endif
+        return SOAP_INVALID_SOCKET;
+      }
+    }
+    else
+      break;
+  }
+#ifdef WITH_IPV6
+  soap->peerlen = 0; /* IPv6: already connected so use send() */
+  freeaddrinfo(ressave);
+#endif
+  soap->socket = sk;
+  soap->imode &= ~SOAP_ENC_SSL;
+  soap->omode &= ~SOAP_ENC_SSL;
+  if (!soap_tag_cmp(endpoint, "https:*"))
+  {
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+#ifdef WITH_OPENSSL
+    BIO *bio;
+#endif
+    int r;
+    if (soap->proxy_host)
+    { soap_mode m = soap->mode; /* preserve settings */
+      soap_mode om = soap->omode; /* make sure we only parse HTTP */
+      size_t n = soap->count; /* save the content length */
+      const char *userid, *passwd;
+      int status = soap->status; /* save the current status/command */
+      short keep_alive = soap->keep_alive; /* save the KA status */
+      soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
+      soap->omode |= SOAP_IO_BUFFER;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint));
+#ifdef WITH_NTLM
+      if (soap->ntlm_challenge)
+      { if (soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port))
+          return soap->error;
+      }
+#endif
+      if (soap_begin_send(soap))
+      { soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+      soap->status = SOAP_CONNECT;
+      soap->keep_alive = 1;
+      if ((soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0))
+       || soap_end_send_flush(soap))
+      { soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+      soap->keep_alive = keep_alive;
+      soap->omode = om;
+      om = soap->imode;
+      soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
+      userid = soap->userid; /* preserve */
+      passwd = soap->passwd; /* preserve */
+      if ((soap->error = soap->fparse(soap)))
+      { soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+      soap->status = status; /* restore */
+      soap->userid = userid; /* restore */
+      soap->passwd = passwd; /* restore */
+      soap->imode = om; /* restore */
+      soap->count = n; /* restore */
+      if (soap_begin_send(soap))
+      { soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+      if (endpoint)
+      { strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); /* restore */
+        soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
+      }
+      soap->mode = m;
+    }
+#ifdef WITH_OPENSSL
+    soap->ssl_flags |= SOAP_SSL_CLIENT;
+    if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
+      soap->fclosesocket(soap, sk);
+      soap->error = SOAP_SSL_ERROR;
+      return SOAP_INVALID_SOCKET;
+    }
+    if (!soap->ssl)
+    { soap->ssl = SSL_new(soap->ctx);
+      if (!soap->ssl)
+      { soap->fclosesocket(soap, sk);
+        soap->error = SOAP_SSL_ERROR;
+        return SOAP_INVALID_SOCKET;
+      }
+    }
+    else
+      SSL_clear(soap->ssl);
+    if (soap->session)
+    { if (!strcmp(soap->session_host, host) && soap->session_port == port)
+        SSL_set_session(soap->ssl, soap->session);
+      SSL_SESSION_free(soap->session);
+      soap->session = NULL;
+    }
+    soap->imode |= SOAP_ENC_SSL;
+    soap->omode |= SOAP_ENC_SSL;
+    bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
+    SSL_set_bio(soap->ssl, bio, bio);
+    /* Connect timeout: set SSL sockets to non-blocking */
+    retries = 0;
+    if (soap->connect_timeout)
+    { SOAP_SOCKNONBLOCK(sk)
+      retries = 10*soap->connect_timeout;
+    }
+    else
+      SOAP_SOCKBLOCK(sk)
+    if (retries <= 0)
+      retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
+    /* Try connecting until success or timeout (when nonblocking) */
+    do
+    { if ((r = SSL_connect(soap->ssl)) <= 0)
+      { int err = SSL_get_error(soap->ssl, r);
+        if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
+        { register int s;
+          if (err == SSL_ERROR_WANT_READ)
+            s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
+          else
+            s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
+          if (s < 0)
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
+            soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
+            soap->fclosesocket(soap, sk);
+            return SOAP_INVALID_SOCKET;
+          }
+          if (s == 0 && retries-- <= 0)
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
+            soap_set_sender_error(soap, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
+            soap->fclosesocket(soap, sk);
+            return SOAP_INVALID_SOCKET;
+          }
+        }
+        else
+        { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR);
+          soap->fclosesocket(soap, sk);
+          return SOAP_INVALID_SOCKET;
+        }
+      }
+    } while (!SSL_is_init_finished(soap->ssl));
+    /* Set SSL sockets to nonblocking */
+    SOAP_SOCKNONBLOCK(sk)
+    /* Check server credentials when required */
+    if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
+    { int err;
+      if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
+      { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
+        soap->fclosesocket(soap, sk);
+        return SOAP_INVALID_SOCKET;
+      }
+      if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
+      { X509_NAME *subj;
+        STACK_OF(CONF_VALUE) *val = NULL;
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
+        GENERAL_NAMES *names = NULL;
+#else
+        int ext_count;
+#endif
+        int ok = 0;
+        X509 *peer = SSL_get_peer_certificate(soap->ssl);
+        if (!peer)
+        { soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
+          soap->fclosesocket(soap, sk);
+          return SOAP_INVALID_SOCKET;
+        }
+#if (OPENSSL_VERSION_NUMBER < 0x0090800fL)
+        ext_count = X509_get_ext_count(peer);
+        if (ext_count > 0)
+        { int i;
+          for (i = 0; i < ext_count; i++)
+          { X509_EXTENSION *ext = X509_get_ext(peer, i);
+            const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
+            if (ext_str && !strcmp(ext_str, "subjectAltName"))
+            { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
+              unsigned char *data;
+              if (!meth)
+                break;
+              data = ext->value->data;
+              if (data)
+              {
+#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
+                void *ext_data;
+                if (meth->it)
+                  ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
+                else
+                { /* OpenSSL is not portable at this point (?):
+                     Some compilers appear to prefer
+                       meth->d2i(NULL, (const unsigned char**)&data, ...
+                     and others prefer
+                       meth->d2i(NULL, &data, ext->value->length);
+                  */
+                  ext_data = meth->d2i(NULL, &data, ext->value->length);
+                }
+                if (ext_data)
+                  val = meth->i2v(meth, ext_data, NULL);
+        	else
+        	  val = NULL;
+                if (meth->it)
+                  ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
+                else
+                  meth->ext_free(ext_data);
+#else
+                void *ext_data = meth->d2i(NULL, &data, ext->value->length);
+                if (ext_data)
+                  val = meth->i2v(meth, ext_data, NULL);
+                meth->ext_free(ext_data);
+#endif
+        	if (val)
+                { int j;
+                  for (j = 0; j < sk_CONF_VALUE_num(val); j++)
+                  { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
+                    if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
+                    { ok = 1;
+                      break;
+                    }
+                  }
+                  sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
+                }
+              }
+            }
+            if (ok)
+              break;
+          }
+        }
+#else
+        names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
+        if (names)
+        { val = i2v_GENERAL_NAMES(NULL, names, val);
+          sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
+        }
+        if (val)
+        { int j;
+          for (j = 0; j < sk_CONF_VALUE_num(val); j++)
+          { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
+            if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
+            { ok = 1;
+              break;
+            }
+          }
+          sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
+        }
+#endif
+        if (!ok && (subj = X509_get_subject_name(peer)))
+        { int i = -1;
+          do
+          { ASN1_STRING *name;
+            i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
+            if (i == -1)
+              break;
+            name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
+            if (name)
+            { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name)))
+                ok = 1;
+              else
+              { unsigned char *tmp = NULL;
+                ASN1_STRING_to_UTF8(&tmp, name);
+                if (tmp)
+                { if (!soap_tag_cmp(host, (const char*)tmp))
+                    ok = 1;
+                  else if (tmp[0] == '*') /* wildcard domain */
+                  { const char *t = strchr(host, '.');
+                    if (t && !soap_tag_cmp(t, (const char*)tmp+1))
+                      ok = 1;
+                  }
+                  OPENSSL_free(tmp);
+                }
+              }
+            }
+          } while (!ok);
+        }
+        X509_free(peer);
+        if (!ok)
+        { soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
+          soap->fclosesocket(soap, sk);
+          return SOAP_INVALID_SOCKET;
+        }
+      }
+    }
+#endif
+#ifdef WITH_GNUTLS
+    soap->ssl_flags |= SOAP_SSL_CLIENT;
+    if (!soap->session && (soap->error = soap->fsslauth(soap)))
+    { soap->fclosesocket(soap, sk);
+      return SOAP_INVALID_SOCKET;
+    }
+    gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
+    /* Set SSL sockets to non-blocking */
+    if (soap->connect_timeout)
+    { SOAP_SOCKNONBLOCK(sk)
+      retries = 10*soap->connect_timeout;
+    }
+    else
+      SOAP_SOCKBLOCK(sk)
+    if (retries <= 0)
+      retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
+    while ((r = gnutls_handshake(soap->session)))
+    { int s;
+      /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
+      if (retries-- <= 0)
+        break;
+      if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
+      { if (!gnutls_record_get_direction(soap->session))
+          s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
+        else
+          s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
+        if (s < 0)
+          break;
+      }
+      else
+      { soap->errnum = soap_socket_errno(sk);
+        break;
+      }
+    }
+    if (r)
+    { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
+      soap->fclosesocket(soap, sk);
+      return SOAP_INVALID_SOCKET;
+    }
+    if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
+    { const char *err = ssl_verify(soap, host);
+      if (err)
+      { soap->fclosesocket(soap, sk);
+        soap->error = soap_set_sender_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
+        return SOAP_INVALID_SOCKET;
+      }
+    }
+#endif
+#else
+    soap->fclosesocket(soap, sk);
+    soap->error = SOAP_SSL_ERROR;
+    return SOAP_INVALID_SOCKET;
+#endif
+  }
+  if (soap->recv_timeout || soap->send_timeout)
+    SOAP_SOCKNONBLOCK(sk)
+  else
+    SOAP_SOCKBLOCK(sk)
+  return sk;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static int
+tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
+{ int r;
+  struct timeval tv;
+  fd_set fd[3], *rfd, *sfd, *efd;
+  int retries = 0;
+  int eintr = SOAP_MAXEINTR;
+  soap->errnum = 0;
+#ifndef WIN32
+#if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
+  /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */
+  if (1)
+#else
+  /* if fd max set size exceeded, use poll() */
+  if ((int)sk >= (int)FD_SETSIZE)
+#endif
+#ifdef HAVE_POLL
+  { struct pollfd pollfd;
+    pollfd.fd = (int)sk;
+    pollfd.events = 0;
+    if (flags & SOAP_TCP_SELECT_RCV)
+      pollfd.events |= POLLIN;
+    if (flags & SOAP_TCP_SELECT_SND)
+      pollfd.events |= POLLOUT;
+    if (flags & SOAP_TCP_SELECT_ERR)
+      pollfd.events |= POLLERR;
+    if (timeout <= 0)
+      timeout /= -1000; /* -usec -> ms */
+    else
+    { retries = timeout - 1;
+      timeout = 1000;
+    }
+    do
+    { r = poll(&pollfd, 1, timeout);
+      if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
+        continue;
+    } while (r == 0 && retries--);
+    if (r > 0)
+    { r = 0;
+      if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN))
+        r |= SOAP_TCP_SELECT_RCV;
+      if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT))
+        r |= SOAP_TCP_SELECT_SND;
+      if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR))
+        r |= SOAP_TCP_SELECT_ERR;
+    }
+    return r;
+  }
+#else
+  { soap->error = SOAP_FD_EXCEEDED;
+    return -1;
+  }
+#endif
+#endif
+  if (timeout > 0)
+    retries = timeout - 1;
+  do
+  { rfd = sfd = efd = NULL;
+    if (flags & SOAP_TCP_SELECT_RCV)
+    { rfd = &fd[0];
+      FD_ZERO(rfd);
+      FD_SET(sk, rfd);
+    }
+    if (flags & SOAP_TCP_SELECT_SND)
+    { sfd = &fd[1];
+      FD_ZERO(sfd);
+      FD_SET(sk, sfd);
+    }
+    if (flags & SOAP_TCP_SELECT_ERR)
+    { efd = &fd[2];
+      FD_ZERO(efd);
+      FD_SET(sk, efd);
+    }
+    if (timeout <= 0)
+    { tv.tv_sec = -timeout / 1000000;
+      tv.tv_usec = -timeout % 1000000;
+    }
+    else
+    { tv.tv_sec = 1;
+      tv.tv_usec = 0;
+    }
+    r = select((int)sk + 1, rfd, sfd, efd, &tv);
+    if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
+      continue;
+  } while (r == 0 && retries--);
+  if (r > 0)
+  { r = 0;
+    if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd))
+      r |= SOAP_TCP_SELECT_RCV;
+    if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd))
+      r |= SOAP_TCP_SELECT_SND;
+    if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd))
+      r |= SOAP_TCP_SELECT_ERR;
+  }
+  return r;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static SOAP_SOCKET
+tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
+{ SOAP_SOCKET sk;
+  (void)soap;
+  sk = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
+#ifdef SOCKET_CLOSE_ON_EXEC
+#ifdef WIN32
+#ifndef UNDER_CE
+  SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
+#endif
+#else
+  fcntl(sk, F_SETFD, FD_CLOEXEC);
+#endif
+#endif
+  return sk;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static int
+tcp_disconnect(struct soap *soap)
+{
+#ifdef WITH_OPENSSL
+  if (soap->ssl)
+  { int r, s = 0;
+    if (soap->session)
+    { SSL_SESSION_free(soap->session);
+      soap->session = NULL;
+    }
+    if (*soap->host)
+    { soap->session = SSL_get1_session(soap->ssl);
+      if (soap->session)
+      { strcpy(soap->session_host, soap->host);
+        soap->session_port = soap->port;
+      }
+    }
+    r = SSL_shutdown(soap->ssl);
+    /* SSL shutdown does not work when reads are pending, non-blocking */
+    if (r == 0)
+    { while (SSL_want_read(soap->ssl))
+      { if (SSL_read(soap->ssl, NULL, 0)
+         || soap_socket_errno(soap->socket) != SOAP_EAGAIN)
+        { r = SSL_shutdown(soap->ssl);
+          break;
+        }
+      }
+    }
+    if (r == 0)
+    { if (soap_valid_socket(soap->socket))
+      { if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR))
+        {
+#if !defined(WITH_LEAN) && !defined(WIN32)
+          /*
+          wait up to 5 seconds for close_notify to be sent by peer (if peer not
+          present, this avoids calling SSL_shutdown() which has a lengthy return
+          timeout)
+          */
+          r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5);
+          if (r <= 0)
+          { soap->errnum = 0;
+            DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
+            soap->fclosesocket(soap, soap->socket);
+            soap->socket = SOAP_INVALID_SOCKET;
+            ERR_remove_state(0);
+            SSL_free(soap->ssl);
+            soap->ssl = NULL;
+            return SOAP_OK;
+          }
+#else
+          r = SSL_shutdown(soap->ssl);
+#endif
+        }
+      }
+    }
+    if (r != 1)
+    { s = ERR_get_error();
+      if (s)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
+        if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
+        { soap->fclosesocket(soap, soap->socket);
+          soap->socket = SOAP_INVALID_SOCKET;
+        }
+      }
+    }
+    SSL_free(soap->ssl);
+    soap->ssl = NULL;
+    if (s)
+      return SOAP_SSL_ERROR;
+    ERR_remove_state(0);
+  }
+#endif
+#ifdef WITH_GNUTLS
+  if (soap->session)
+  { gnutls_bye(soap->session, GNUTLS_SHUT_RDWR);
+    gnutls_deinit(soap->session);
+    soap->session = NULL;
+  }
+#endif
+  if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
+  { soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR);
+    soap->fclosesocket(soap, soap->socket);
+    soap->socket = SOAP_INVALID_SOCKET;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static int
+tcp_closesocket(struct soap *soap, SOAP_SOCKET sk)
+{ (void)soap;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk));
+  return soap_closesocket(sk);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static int
+tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how)
+{ (void)soap;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how));
+  return shutdown(sk, how);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+SOAP_FMAC1
+SOAP_SOCKET
+SOAP_FMAC2
+soap_bind(struct soap *soap, const char *host, int port, int backlog)
+{
+#ifdef WITH_IPV6
+  struct addrinfo *addrinfo = NULL;
+  struct addrinfo hints;
+  struct addrinfo res;
+  int err;
+#ifdef WITH_NO_IPV6_V6ONLY
+  int unset = 0;
+#endif
+#endif
+#ifndef WITH_LEAN
+#ifndef WIN32
+  int len = SOAP_BUFLEN;
+#else
+  int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
+#endif
+  int set = 1;
+#endif
+  if (soap_valid_socket(soap->master))
+  { soap->fclosesocket(soap, soap->master);
+    soap->master = SOAP_INVALID_SOCKET;
+  }
+  soap->socket = SOAP_INVALID_SOCKET;
+  soap->errmode = 1;
+  if (tcp_init(soap))
+  { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#ifdef WITH_IPV6
+  memset((void*)&hints, 0, sizeof(hints));
+  hints.ai_family = PF_UNSPEC;
+#ifndef WITH_LEAN
+  if ((soap->omode & SOAP_IO_UDP))
+    hints.ai_socktype = SOCK_DGRAM;
+  else
+#endif
+    hints.ai_socktype = SOCK_STREAM;
+  hints.ai_flags = AI_PASSIVE;
+  soap->errmode = 2;
+  err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
+  if (err || !addrinfo)
+  { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  res = *addrinfo;
+  memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
+  soap->peerlen = addrinfo->ai_addrlen;
+  res.ai_addr = (struct sockaddr*)&soap->peer;
+  res.ai_addrlen = soap->peerlen;
+  freeaddrinfo(addrinfo);
+  soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
+#else
+#ifndef WITH_LEAN
+  if ((soap->omode & SOAP_IO_UDP))
+    soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
+  else
+#endif
+    soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
+#endif
+  soap->errmode = 0;
+  if (!soap_valid_socket(soap->master))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  soap->port = port;
+#ifndef WITH_LEAN
+  if ((soap->omode & SOAP_IO_UDP))
+    soap->socket = soap->master;
+#endif
+#ifdef SOCKET_CLOSE_ON_EXEC
+#ifdef WIN32
+#ifndef UNDER_CE
+  SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
+#endif
+#else
+  fcntl(soap->master, F_SETFD, 1);
+#endif
+#endif
+#ifndef WITH_LEAN
+  if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#ifdef TCP_NODELAY
+  if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+#endif
+#ifdef WITH_IPV6
+#ifdef WITH_IPV6_V6ONLY
+  if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&set, sizeof(int)))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "setsockopt set IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+#ifdef WITH_NO_IPV6_V6ONLY
+  if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&unset, sizeof(int)))
+  { soap->errnum = soap_socket_errno(soap->master);
+    soap_set_receiver_error(soap, tcp_error(soap), "setsockopt unset IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+  soap->errmode = 0;
+  if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
+  { soap->errnum = soap_socket_errno(soap->master);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
+    soap_closesock(soap);
+    soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#else
+  soap->peerlen = sizeof(soap->peer);
+  memset((void*)&soap->peer, 0, sizeof(soap->peer));
+  soap->peer.sin_family = AF_INET;
+  soap->errmode = 2;
+  if (host)
+  { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
+    { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
+      return SOAP_INVALID_SOCKET;
+    }
+  }
+  else
+    soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
+  soap->peer.sin_port = htons((short)port);
+  soap->errmode = 0;
+  if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
+  { soap->errnum = soap_socket_errno(soap->master);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
+    soap_closesock(soap);
+    soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#endif
+  if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
+  { soap->errnum = soap_socket_errno(soap->master);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
+    soap_closesock(soap);
+    soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+  return soap->master;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_poll(struct soap *soap)
+{
+#ifndef WITH_LEAN
+  register int r;
+  if (soap_valid_socket(soap->socket))
+  { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
+    if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
+      r = -1;
+  }
+  else if (soap_valid_socket(soap->master))
+    r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0);
+  else
+    return SOAP_OK; /* OK when no socket! */
+  if (r > 0)
+  {
+#ifdef WITH_OPENSSL
+    if (soap->imode & SOAP_ENC_SSL)
+    {
+      if (soap_valid_socket(soap->socket)
+       && (r & SOAP_TCP_SELECT_SND)
+       && (!(r & SOAP_TCP_SELECT_RCV)
+        || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
+        return SOAP_OK;
+    }
+    else
+#endif
+    { int t;
+      if (soap_valid_socket(soap->socket)
+       && (r & SOAP_TCP_SELECT_SND)
+       && (!(r & SOAP_TCP_SELECT_RCV)
+        || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0))
+        return SOAP_OK;
+    }
+  }
+  else if (r < 0)
+  { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
+    { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
+      return soap->error = SOAP_TCP_ERROR;
+    }
+  }
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
+  return SOAP_EOF;
+#else
+  return SOAP_OK;
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+SOAP_FMAC1
+SOAP_SOCKET
+SOAP_FMAC2
+soap_accept(struct soap *soap)
+{ int n = (int)sizeof(soap->peer);
+  register int err;
+#ifndef WITH_LEAN
+#ifndef WIN32
+  int len = SOAP_BUFLEN;
+#else
+  int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
+#endif
+  int set = 1;
+#endif
+  soap->error = SOAP_OK;
+  memset((void*)&soap->peer, 0, sizeof(soap->peer));
+  soap->socket = SOAP_INVALID_SOCKET;
+  soap->errmode = 0;
+  soap->keep_alive = 0;
+  if (!soap_valid_socket(soap->master))
+  { soap->errnum = 0;
+    soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
+    return SOAP_INVALID_SOCKET;
+  }
+#ifndef WITH_LEAN
+  if ((soap->omode & SOAP_IO_UDP))
+    return soap->socket = soap->master;
+#endif
+  for (;;)
+  { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
+    { for (;;)
+      { register int r;
+        r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60);
+        if (r > 0)
+          break;
+        if (!r && soap->accept_timeout)
+        { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
+          return SOAP_INVALID_SOCKET;
+        }
+        if (r < 0)
+        { r = soap->errnum;
+          if (r != SOAP_EINTR)
+          { soap_closesock(soap);
+            soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
+            return SOAP_INVALID_SOCKET;
+          }
+        }
+      }
+    }
+    if (soap->accept_timeout)
+      SOAP_SOCKNONBLOCK(soap->master)
+    else
+      SOAP_SOCKBLOCK(soap->master)
+    soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
+    soap->peerlen = (size_t)n;
+    if (soap_valid_socket(soap->socket))
+    {
+#ifdef WITH_IPV6
+      unsigned int ip1, ip2, ip3, ip4;
+      char port[16];
+      getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), port, 16, NI_NUMERICHOST | NI_NUMERICSERV);
+      sscanf(soap->host, "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
+      soap->ip = (unsigned long)ip1 << 24 | (unsigned long)ip2 << 16 | (unsigned long)ip3 << 8 | (unsigned long)ip4;
+      soap->port = soap_strtol(port, NULL, 10);
+#else
+      soap->ip = ntohl(soap->peer.sin_addr.s_addr);
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->host, sizeof(soap->host), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
+#else
+      sprintf(soap->host, "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
+#endif
+      soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
+#endif
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", soap->socket, soap->port, soap->host));
+#ifndef WITH_LEAN
+      if (soap->accept_flags == SO_LINGER)
+      { struct linger linger;
+        memset((void*)&linger, 0, sizeof(linger));
+        linger.l_onoff = 1;
+        linger.l_linger = soap->linger_time;
+        if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
+        { soap->errnum = soap_socket_errno(soap->socket);
+          soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
+          soap_closesock(soap);
+          return SOAP_INVALID_SOCKET;
+        }
+      }
+      else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
+      { soap->errnum = soap_socket_errno(soap->socket);
+        soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
+        soap_closesock(soap);
+        return SOAP_INVALID_SOCKET;
+      }
+      if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
+      { soap->errnum = soap_socket_errno(soap->socket);
+        soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
+        soap_closesock(soap);
+        return SOAP_INVALID_SOCKET;
+      }
+      if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
+      { soap->errnum = soap_socket_errno(soap->socket);
+        soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
+        soap_closesock(soap);
+        return SOAP_INVALID_SOCKET;
+      }
+      if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
+      { soap->errnum = soap_socket_errno(soap->socket);
+        soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
+        soap_closesock(soap);
+        return SOAP_INVALID_SOCKET;
+      }
+#ifdef TCP_NODELAY
+      if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
+      { soap->errnum = soap_socket_errno(soap->socket);
+        soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
+        soap_closesock(soap);
+        return SOAP_INVALID_SOCKET;
+      }
+#endif
+#endif
+      soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
+      if (soap->send_timeout || soap->recv_timeout)
+        SOAP_SOCKNONBLOCK(soap->socket)
+      else
+        SOAP_SOCKBLOCK(soap->socket)
+      return soap->socket;
+    }
+    err = soap_socket_errno(soap->socket);
+    if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
+    { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
+      soap->errnum = err;
+      soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
+      soap_closesock(soap);
+      return SOAP_INVALID_SOCKET;
+    }
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_closesock(struct soap *soap)
+{ register int status = soap->error;
+#ifndef WITH_LEANER
+  if (status) /* close on error: attachment state is not to be trusted */
+  { soap->mime.first = NULL;
+    soap->mime.last = NULL;
+    soap->dime.first = NULL;
+    soap->dime.last = NULL;
+  }
+#endif
+  if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
+    return soap->error;
+  if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
+  { if (soap->fclose && (soap->error = soap->fclose(soap)))
+      return soap->error;
+    soap->keep_alive = 0;
+  }
+#ifdef WITH_ZLIB
+  if (!(soap->mode & SOAP_MIME_POSTCHECK))
+  { if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
+      deflateEnd(soap->d_stream);
+    else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
+      inflateEnd(soap->d_stream);
+    soap->zlib_state = SOAP_ZLIB_NONE;
+  }
+#endif
+  return soap->error = status;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_force_closesock(struct soap *soap)
+{ soap->keep_alive = 0;
+  if (soap_valid_socket(soap->socket))
+    return soap_closesocket(soap->socket);
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_cleanup(struct soap *soap)
+{ soap_done(soap);
+#ifdef WIN32
+  if (!tcp_done)
+    return;
+  tcp_done = 0;
+  WSACleanup();
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_done(struct soap *soap)
+{
+#ifdef SOAP_DEBUG
+  int i;
+#endif
+  if (soap_check_state(soap))
+    return;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : ""));
+  soap_free_temp(soap);
+  while (soap->clist)
+  { struct soap_clist *p = soap->clist->next;
+    SOAP_FREE(soap, soap->clist);
+    soap->clist = p;
+  }
+  if (soap->state == SOAP_INIT)
+    soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
+  soap->keep_alive = 0; /* to force close the socket */
+  if (soap->master == soap->socket) /* do not close twice */
+    soap->master = SOAP_INVALID_SOCKET;
+  soap_closesock(soap);
+#ifdef WITH_COOKIES
+  soap_free_cookies(soap);
+#endif
+  while (soap->plugins)
+  { register struct soap_plugin *p = soap->plugins->next;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
+    if (soap->plugins->fcopy || soap->state == SOAP_INIT)
+      soap->plugins->fdelete(soap, soap->plugins);
+    SOAP_FREE(soap, soap->plugins);
+    soap->plugins = p;
+  }
+  soap->fplugin = fplugin;
+  soap->fmalloc = NULL;
+#ifndef WITH_NOHTTP
+  soap->fpost = http_post;
+  soap->fget = http_get;
+  soap->fput = http_405;
+  soap->fdel = http_405;
+  soap->fopt = http_200;
+  soap->fhead = http_200;
+  soap->fform = NULL;
+  soap->fposthdr = http_post_header;
+  soap->fresponse = http_response;
+  soap->fparse = http_parse;
+  soap->fparsehdr = http_parse_header;
+#endif
+  soap->fheader = NULL;
+#ifndef WITH_NOIO
+#ifndef WITH_IPV6
+  soap->fresolve = tcp_gethost;
+#else
+  soap->fresolve = NULL;
+#endif
+  soap->faccept = tcp_accept;
+  soap->fopen = tcp_connect;
+  soap->fclose = tcp_disconnect;
+  soap->fclosesocket = tcp_closesocket;
+  soap->fshutdownsocket = tcp_shutdownsocket;
+  soap->fsend = fsend;
+  soap->frecv = frecv;
+  soap->fpoll = soap_poll;
+#else
+  soap->fopen = NULL;
+  soap->fclose = NULL;
+  soap->fpoll = NULL;
+#endif
+#ifndef WITH_LEANER
+  soap->feltbegin = NULL;
+  soap->feltendin = NULL;
+  soap->feltbegout = NULL;
+  soap->feltendout = NULL;
+  soap->fprepareinitsend = NULL;
+  soap->fprepareinitrecv = NULL;
+  soap->fpreparesend = NULL;
+  soap->fpreparerecv = NULL;
+  soap->fpreparefinalsend = NULL;
+  soap->fpreparefinalrecv = NULL;
+  soap->ffiltersend = NULL;
+  soap->ffilterrecv = NULL;
+#endif
+  soap->fseterror = NULL;
+  soap->fignore = NULL;
+  soap->fserveloop = NULL;
+#ifdef WITH_OPENSSL
+  if (soap->session)
+  { SSL_SESSION_free(soap->session);
+    soap->session = NULL;
+  }
+#endif
+  if (soap->state == SOAP_INIT)
+  { if (soap_valid_socket(soap->master))
+    { soap->fclosesocket(soap, soap->master);
+      soap->master = SOAP_INVALID_SOCKET;
+    }
+  }
+#ifdef WITH_OPENSSL
+  if (soap->ssl)
+  { SSL_free(soap->ssl);
+    soap->ssl = NULL;
+  }
+  if (soap->state == SOAP_INIT)
+  { if (soap->ctx)
+    { SSL_CTX_free(soap->ctx);
+      soap->ctx = NULL;
+    }
+  }
+  ERR_remove_state(0);
+#endif
+#ifdef WITH_GNUTLS
+  if (soap->state == SOAP_INIT)
+  { if (soap->xcred)
+    { gnutls_certificate_free_credentials(soap->xcred);
+      soap->xcred = NULL;
+    }
+    if (soap->acred)
+    { gnutls_anon_free_client_credentials(soap->acred);
+      soap->acred = NULL;
+    }
+    if (soap->cache)
+    { gnutls_priority_deinit(soap->cache);
+      soap->cache = NULL;
+    }
+    if (soap->dh_params)
+    { gnutls_dh_params_deinit(soap->dh_params);
+      soap->dh_params = NULL;
+    }
+    if (soap->rsa_params)
+    { gnutls_rsa_params_deinit(soap->rsa_params);
+      soap->rsa_params = NULL;
+    }
+  }
+  if (soap->session)
+  { gnutls_deinit(soap->session);
+    soap->session = NULL;
+  }
+#endif
+#ifdef WITH_C_LOCALE
+# ifdef WIN32
+  _free_locale(soap->c_locale);
+# else
+  freelocale(soap->c_locale);
+# endif
+#endif
+#ifdef WITH_ZLIB
+  if (soap->d_stream)
+  { SOAP_FREE(soap, (void*)soap->d_stream);
+    soap->d_stream = NULL;
+  }
+  if (soap->z_buf)
+  { SOAP_FREE(soap, (void*)soap->z_buf);
+    soap->z_buf = NULL;
+  }
+#endif
+#ifdef SOAP_DEBUG
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
+  for (i = 0; i < SOAP_MAXLOGS; i++)
+  { if (soap->logfile[i])
+    { SOAP_FREE(soap, (void*)soap->logfile[i]);
+      soap->logfile[i] = NULL;
+    }
+    soap_close_logfile(soap, i);
+  }
+  soap->state = SOAP_NONE;
+#endif
+#ifdef SOAP_MEM_DEBUG
+  soap_free_mht(soap);
+#endif
+}
+#endif
+
+/******************************************************************************\
+ *
+ *	HTTP
+ *
+\******************************************************************************/
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_parse(struct soap *soap)
+{ char header[SOAP_HDRLEN], *s;
+  unsigned short httpcmd = 0;
+  int status = 0;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
+  *soap->endpoint = '\0';
+#ifdef WITH_NTLM
+  if (!soap->ntlm_challenge)
+#endif
+  { soap->userid = NULL;
+    soap->passwd = NULL;
+    soap->authrealm = NULL;
+  }
+#ifdef WITH_NTLM
+  soap->ntlm_challenge = NULL;
+#endif
+  soap->proxy_from = NULL;
+  do
+  { soap->length = 0;
+    soap->http_content = NULL;
+    soap->action = NULL;
+    soap->status = 0;
+    soap->body = 1;
+    if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
+    { if (soap->error == SOAP_EOF)
+        return SOAP_EOF;
+      return soap->error = 414;
+    }
+    if ((s = strchr(soap->msgbuf, ' ')))
+    { soap->status = (unsigned short)soap_strtoul(s, &s, 10);
+      if (!soap_blank((soap_wchar)*s))
+        soap->status = 0;
+    }
+    else
+      soap->status = 0;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
+    for (;;)
+    { if (soap_getline(soap, header, SOAP_HDRLEN))
+      { if (soap->error == SOAP_EOF)
+        { soap->error = SOAP_OK;
+          DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
+          break;
+        }
+        return soap->error;
+      }
+      if (!*header)
+        break;
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
+      s = strchr(header, ':');
+      if (s)
+      { char *t;
+        *s = '\0';
+        do s++;
+        while (*s && *s <= 32);
+        if (*s == '"')
+          s++;
+        t = s + strlen(s) - 1;
+        while (t > s && *t <= 32)
+          t--;
+        if (t >= s && *t == '"')
+          t--;
+        t[1] = '\0';
+        if ((soap->error = soap->fparsehdr(soap, header, s)))
+        { if (soap->error < SOAP_STOP)
+            return soap->error;
+          status = soap->error;
+          soap->error = SOAP_OK;
+        }
+      }
+    }
+  } while (soap->status == 100);
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
+  s = strstr(soap->msgbuf, "HTTP/");
+  if (s && s[7] != '1')
+  { if (soap->keep_alive == 1)
+      soap->keep_alive = 0;
+    if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
+      soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */
+  }
+  if (soap->keep_alive < 0)
+    soap->keep_alive = 1;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
+  if (soap->status == 0)
+  { size_t l = 0;
+    if (s)
+    { if (!strncmp(soap->msgbuf, "POST ", l = 5))
+        httpcmd = 1;
+      else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
+        httpcmd = 2;
+      else if (!strncmp(soap->msgbuf, "GET ", l = 4))
+        httpcmd = 3;
+      else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
+        httpcmd = 4;
+      else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8))
+        httpcmd = 5;
+      else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
+        httpcmd = 6;
+    }
+    if (s && httpcmd)
+    { size_t m = strlen(soap->endpoint);
+      size_t n = m + (s - soap->msgbuf) - l - 1;
+      size_t k;
+      if (n >= sizeof(soap->endpoint))
+        n = sizeof(soap->endpoint) - 1;
+      if (m > n)
+        m = n;
+      k = n - m + 1;
+      if (k > sizeof(soap->path))
+        k = sizeof(soap->path);
+      strncpy(soap->path, soap->msgbuf + l, k);
+      soap->path[k - 1] = '\0';
+      if (*soap->path && *soap->path != '/')
+        *soap->endpoint = '\0';
+      strcat(soap->endpoint, soap->path);
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
+      if (httpcmd > 1)
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP %s handler\n", soap->msgbuf));
+        switch (httpcmd)
+        { case  2: soap->error = soap->fput(soap); break;
+          case  3: soap->error = soap->fget(soap); break;
+          case  4: soap->error = soap->fdel(soap); break;
+          case  5: soap->error = soap->fopt(soap); break;
+          case  6: soap->error = soap->fhead(soap); break;
+          default: soap->error = 405; break;
+        }
+        DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP handler return = %d\n", soap->error));
+        if (soap->error == SOAP_OK)
+          soap->error = SOAP_STOP; /* prevents further processing */
+        return soap->error;
+      }
+      if (status)
+        return soap->error = status;
+    }
+    else if (status)
+      return soap->error = status;
+    else if (s)
+      return soap->error = 405;
+    return SOAP_OK;
+  }
+#if 0
+  if (soap->length > 0 || (soap->http_content && (!soap->keep_alive || soap->recv_timeout)) || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
+#endif
+  if (soap->body)
+  { if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */
+     || soap->status == 400                          /* Bad Request */
+     || soap->status == 500)                         /* Internal Server Error */
+      return SOAP_OK;
+    /* force close afterwards in soap_closesock() */
+    soap->keep_alive = 0;
+#ifndef WITH_LEAN
+    /* read HTTP body for error details */
+    s = soap_get_http_body(soap, NULL);
+    if (s)
+      return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status);
+#endif
+  }
+  else if (soap->status >= 200 && soap->status <= 299)
+    return soap->error = soap->status;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status));
+  return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_parse_header(struct soap *soap, const char *key, const char *val)
+{ if (!soap_tag_cmp(key, "Host"))
+  {
+#if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
+    if (soap->imode & SOAP_ENC_SSL)
+      strcpy(soap->endpoint, "https://");
+    else
+#endif
+      strcpy(soap->endpoint, "http://");
+    strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
+  }
+#ifndef WITH_LEANER
+  else if (!soap_tag_cmp(key, "Content-Type"))
+  { const char *action;
+    soap->http_content = soap_strdup(soap, val);
+    if (soap_get_header_attribute(soap, val, "application/dime"))
+      soap->imode |= SOAP_ENC_DIME;
+    else if (soap_get_header_attribute(soap, val, "multipart/related")
+          || soap_get_header_attribute(soap, val, "multipart/form-data"))
+    { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
+      soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
+      soap->imode |= SOAP_ENC_MIME;
+    }
+    action = soap_get_header_attribute(soap, val, "action");
+    if (action)
+    { if (*action == '"')
+      { soap->action = soap_strdup(soap, action + 1);
+        if (*soap->action)
+          soap->action[strlen(soap->action) - 1] = '\0';
+      }
+      else
+        soap->action = soap_strdup(soap, action);
+    }
+  }
+#endif
+  else if (!soap_tag_cmp(key, "Content-Length"))
+  { soap->length = soap_strtoul(val, NULL, 10);
+    if (!soap->length)
+      soap->body = 0;
+  }
+  else if (!soap_tag_cmp(key, "Content-Encoding"))
+  { if (!soap_tag_cmp(val, "deflate"))
+#ifdef WITH_ZLIB
+      soap->zlib_in = SOAP_ZLIB_DEFLATE;
+#else
+      return SOAP_ZLIB_ERROR;
+#endif
+    else if (!soap_tag_cmp(val, "gzip"))
+#ifdef WITH_GZIP
+      soap->zlib_in = SOAP_ZLIB_GZIP;
+#else
+      return SOAP_ZLIB_ERROR;
+#endif
+  }
+#ifdef WITH_ZLIB
+  else if (!soap_tag_cmp(key, "Accept-Encoding"))
+  {
+#ifdef WITH_GZIP
+    if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
+      soap->zlib_out = SOAP_ZLIB_GZIP;
+    else
+#endif
+    if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
+      soap->zlib_out = SOAP_ZLIB_DEFLATE;
+    else
+      soap->zlib_out = SOAP_ZLIB_NONE;
+  }
+#endif
+  else if (!soap_tag_cmp(key, "Transfer-Encoding"))
+  { soap->imode &= ~SOAP_IO;
+    if (!soap_tag_cmp(val, "chunked"))
+      soap->imode |= SOAP_IO_CHUNK;
+  }
+  else if (!soap_tag_cmp(key, "Connection"))
+  { if (!soap_tag_cmp(val, "keep-alive"))
+      soap->keep_alive = -soap->keep_alive;
+    else if (!soap_tag_cmp(val, "close"))
+      soap->keep_alive = 0;
+  }
+#ifndef WITH_LEAN
+  else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization"))
+  {
+#ifdef WITH_NTLM
+    if (!soap_tag_cmp(val, "NTLM*"))
+      soap->ntlm_challenge = soap_strdup(soap, val + 4);
+    else
+#endif
+    if (!soap_tag_cmp(val, "Basic *"))
+    { int n;
+      char *s;
+      soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
+      soap->tmpbuf[n] = '\0';
+      if ((s = strchr(soap->tmpbuf, ':')))
+      { *s = '\0';
+        soap->userid = soap_strdup(soap, soap->tmpbuf);
+        soap->passwd = soap_strdup(soap, s + 1);
+      }
+    }
+  }
+  else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate"))
+  {
+#ifdef WITH_NTLM
+    if (!soap_tag_cmp(val, "NTLM*"))
+      soap->ntlm_challenge = soap_strdup(soap, val + 4);
+    else
+#endif
+      soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
+  }
+  else if (!soap_tag_cmp(key, "Expect"))
+  { if (!soap_tag_cmp(val, "100-continue"))
+    { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
+       || (soap->error = soap->fposthdr(soap, NULL, NULL)))
+        return soap->error;
+    }
+  }
+#endif
+  else if (!soap_tag_cmp(key, "SOAPAction"))
+  { if (*val == '"')
+    { soap->action = soap_strdup(soap, val + 1);
+      if (*soap->action)
+        soap->action[strlen(soap->action) - 1] = '\0';
+    }
+    else
+      soap->action = soap_strdup(soap, val);
+  }
+  else if (!soap_tag_cmp(key, "Location"))
+  { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
+    soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
+  }
+  else if (!soap_tag_cmp(key, "X-Forwarded-For"))
+  { soap->proxy_from = soap_strdup(soap, val);
+  }
+#ifdef WITH_COOKIES
+  else if (!soap_tag_cmp(key, "Cookie")
+   || !soap_tag_cmp(key, "Cookie2")
+   || !soap_tag_cmp(key, "Set-Cookie")
+   || !soap_tag_cmp(key, "Set-Cookie2"))
+  { soap_getcookies(soap, val);
+  }
+#endif
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
+{ register const char *s = line;
+  if (s)
+  { while (*s)
+    { register short flag;
+      s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
+      flag = soap_tag_cmp(soap->tmpbuf, key);
+      s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
+      if (!flag)
+        return soap->tmpbuf;
+    }
+  }
+  return NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_decode_key(char *buf, size_t len, const char *val)
+{ return soap_decode(buf, len, val, "=,;");
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_decode_val(char *buf, size_t len, const char *val)
+{ if (*val != '=')
+  { *buf = '\0';
+    return val;
+  }
+  return soap_decode(buf, len, val + 1, ",;");
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
+#ifndef PALM_1
+static const char*
+soap_decode(char *buf, size_t len, const char *val, const char *sep)
+{ const char *s;
+  char *t = buf;
+  size_t i = len;
+  for (s = val; *s; s++)
+    if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
+      break;
+  if (len > 0)
+  { if (*s == '"')
+    { s++;
+      while (*s && *s != '"' && --i)
+        *t++ = *s++;
+    }
+    else
+    { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --i)
+      { if (*s == '%' && s[1] && s[2])
+        { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
+                + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
+          s += 3;
+        }
+        else
+          *t++ = *s++;
+      }
+    }
+    buf[len - 1] = '\0'; /* appease */
+  }
+  *t = '\0';
+  while (*s && !strchr(sep, *s))
+    s++;
+  return s;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static const char*
+http_error(struct soap *soap, int status)
+{ register const char *msg = SOAP_STR_EOS;
+  (void)soap;
+#ifndef WITH_LEAN
+  msg = soap_code_str(h_http_error_codes, status);
+  if (!msg)
+    msg = SOAP_STR_EOS;
+#endif
+  return msg;
+}
+#endif
+#endif
+
+/******************************************************************************/
+
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_get(struct soap *soap)
+{ (void)soap;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n"));
+  return SOAP_GET_METHOD;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_405(struct soap *soap)
+{ (void)soap;
+  return 405;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_200(struct soap *soap)
+{ return soap_send_empty_response(soap, 200);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
+{ register const char *s;
+  register int err;
+  switch (soap->status)
+  { case SOAP_GET: 
+      s = "GET";
+      break;
+    case SOAP_PUT: 
+      s = "PUT";
+      break;
+    case SOAP_DEL: 
+      s = "DELETE";
+      break;
+    case SOAP_CONNECT:
+      s = "CONNECT";
+      break;
+    default:
+      s = "POST";
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)"));
+#ifdef PALM
+  if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8))
+#else
+  if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
+#endif
+    return SOAP_OK;
+  if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80
+   || strlen(host) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
+    return soap->error = SOAP_EOM; /* prevent overrun (note that 'host' and 'soap->host' are substrings of 'endpoint') */
+  if (soap->status == SOAP_CONNECT)
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
+#else
+    sprintf(soap->tmpbuf, "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
+#endif
+  }
+  else if (soap->proxy_host && endpoint)
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s HTTP/%s", s, endpoint, soap->http_version);
+#else
+    sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
+#endif
+  }
+  else
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
+#else
+    sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
+#endif
+  }
+  if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+    return err;
+#ifdef WITH_OPENSSL
+  if ((soap->ssl && port != 443) || (!soap->ssl && port != 80))
+#else
+  if (port != 80)
+#endif
+  {
+#ifdef WITH_IPV6
+    if (*host != '[' && strchr(host, ':'))
+    {
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]:%d", host, port); /* RFC 2732 */
+#else
+      sprintf(soap->tmpbuf, "[%s]:%d", host, port); /* RFC 2732 */
+#endif
+    }
+    else
+#endif
+    {
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s:%d", host, port);
+#else
+      sprintf(soap->tmpbuf, "%s:%d", host, port);
+#endif
+    }
+  }
+  else
+  {
+#ifdef WITH_IPV6
+    if (*host != '[' && strchr(host, ':'))
+    {
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]", host); /* RFC 2732 */
+#else
+      sprintf(soap->tmpbuf, "[%s]", host); /* RFC 2732 */
+#endif
+    }
+    else
+#endif
+      strcpy(soap->tmpbuf, host);
+  }
+  if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)))
+    return err;
+  if ((err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8")))
+    return err;
+  if ((err = soap_puthttphdr(soap, SOAP_OK, count)))
+    return err;
+#ifdef WITH_ZLIB
+#ifdef WITH_GZIP
+  if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
+#else
+  if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
+#endif
+    return err;
+#endif
+#ifndef WITH_LEAN
+#ifdef WITH_NTLM
+  if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf))
+  { if (*soap->ntlm_challenge)
+    { 
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "NTLM %s", soap->ntlm_challenge);
+#else
+      sprintf(soap->tmpbuf, "NTLM %s", soap->ntlm_challenge);
+#endif
+      if (soap->proxy_host)
+      { if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
+          return err;
+      }
+      else if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
+        return err;
+    }
+  }
+  else
+  {
+#endif
+  if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
+  { strcpy(soap->tmpbuf, "Basic ");
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->userid, soap->passwd);
+#else
+    sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
+#endif
+    soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
+    if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
+      return err;
+  }
+  if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
+  { strcpy(soap->tmpbuf, "Basic ");
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
+#else
+    sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
+#endif
+    soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
+    if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
+      return err;
+  }
+#ifdef WITH_NTLM
+  }
+#endif
+#endif
+#ifdef WITH_COOKIES
+#ifdef WITH_OPENSSL
+  if (soap_putcookies(soap, host, path, soap->ssl != NULL))
+    return soap->error;
+#else
+  if (soap_putcookies(soap, host, path, 0))
+    return soap->error;
+#endif
+#endif
+  if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL)
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "\"%s\"", action);
+#else
+    sprintf(soap->tmpbuf, "\"%s\"", strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
+#endif
+    if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
+      return err;
+  }
+  return soap->fposthdr(soap, NULL, NULL);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_send_header(struct soap *soap, const char *s)
+{ register const char *t;
+  do
+  { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
+    if (!t)
+      t = s + strlen(s);
+    if (soap_send_raw(soap, s, t - s))
+      return soap->error;
+    s = t + 1;
+  } while (*t);
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_post_header(struct soap *soap, const char *key, const char *val)
+{ if (key)
+  { if (http_send_header(soap, key))
+      return soap->error;
+    if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
+      return soap->error;
+  }
+  return soap_send_raw(soap, "\r\n", 2);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+static int
+http_response(struct soap *soap, int status, size_t count)
+{ register int err;
+  char http[10];
+  int code = status;
+  const char *line;
+#ifdef WMW_RPM_IO
+  if (soap->rpmreqid)
+    httpOutputEnable(soap->rpmreqid);
+#endif
+  if (!soap->http_version || strlen(soap->http_version) > 4)
+    return soap->error = SOAP_EOM;
+#ifdef WMW_RPM_IO
+  if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
+#else
+  if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */
+#endif
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(http, sizeof(http), "HTTP/%s", soap->http_version);
+#else
+    sprintf(http, "HTTP/%s", soap->http_version);
+#endif
+  }
+  else
+    strcpy(http, "Status:");
+  if (!status || status == SOAP_HTML || status == SOAP_FILE)
+  { if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
+      code = 200;
+    else
+      code = 202;
+  }
+  else if (status < 200 || status >= 600)
+  { const char *s = *soap_faultcode(soap);
+    if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
+      code = 405;
+    else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
+      code = 400;
+    else
+      code = 500;
+  }
+  line = http_error(soap, code);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line));
+#ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %d %s", http, code, line);
+#else
+  sprintf(soap->tmpbuf, "%s %d %s", http, code, line);
+#endif
+  if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+    return err;
+#ifndef WITH_LEAN
+  if (status == 401)
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
+#else
+    sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
+#endif
+    if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
+      return err;
+  }
+  else if ((status >= 301 && status <= 303) || status == 307)
+  { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
+      return err;
+  }
+#endif
+  if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.8"))
+   || (err = soap_puthttphdr(soap, status, count)))
+    return err;
+#ifdef WITH_COOKIES
+  if (soap_putsetcookies(soap))
+    return soap->error;
+#endif
+  return soap->fposthdr(soap, NULL, NULL);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_response(struct soap *soap, int status)
+{ register size_t count;
+  if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
+   && (status == SOAP_HTML || status == SOAP_FILE))
+    soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
+  soap->status = status;
+  count = soap_count_attachments(soap);
+  if (soap_begin_send(soap))
+    return soap->error;
+#ifndef WITH_NOHTTP
+  if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
+  { register int n = soap->mode;
+    soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
+    if ((n & SOAP_IO) != SOAP_IO_FLUSH)
+      soap->mode |= SOAP_IO_BUFFER;
+    if ((soap->error = soap->fresponse(soap, status, count)))
+      return soap->error;
+#ifndef WITH_LEANER
+    if ((n & SOAP_IO) == SOAP_IO_CHUNK)
+    { if (soap_flush(soap))
+        return soap->error;
+    }
+#endif
+    soap->mode = n;
+  }
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_url(struct soap *soap, const char *s, const char *t)
+{ if (!t || (*t != '/' && *t != '?') || strlen(s) + strlen(t) >= sizeof(soap->msgbuf))
+    return s;
+  strcpy(soap->msgbuf, s);
+  strcat(soap->msgbuf, t);
+  return soap->msgbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_encode_url(const char *s, char *t, size_t len)
+{ register int c;
+  register size_t n = len;
+  while ((c = *s++) && --n > 0)
+  { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c))
+      *t++ = c;
+    else if (n > 2)
+    { *t++ = '%';
+      *t++ = (c >> 4) + (c > 159 ? '7' : '0');
+      c &= 0xF;
+      *t++ = c + (c > 9 ? '7' : '0');
+      n -= 2;
+    }
+    else
+      break;
+  }
+  *t = '\0';
+  return len - n;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_encode_url_string(struct soap *soap, const char *s)
+{ if (s)
+  { size_t n = 3*strlen(s)+1;
+    char *t = (char*)soap_malloc(soap, n);
+    if (t)
+    { soap_encode_url(s, t, n);
+      return t;
+    }
+  }
+  return SOAP_STR_EOS;
+}
+#endif
+
+/******************************************************************************\
+ *
+ *	HTTP Cookies
+ *
+\******************************************************************************/
+
+#ifdef WITH_COOKIES
+/******************************************************************************/
+SOAP_FMAC1
+struct soap_cookie*
+SOAP_FMAC2
+soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if (!domain)
+    domain = soap->cookie_domain;
+  if (!path)
+    path = soap->cookie_path;
+  if (!path)
+    path = SOAP_STR_EOS;
+  else if (*path == '/')
+    path++;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)"));
+  for (p = soap->cookies; p; p = p->next)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s='%s' domain='%s' path='%s' env=%hd\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->env));
+    if (!strcmp(p->name, name)
+     && p->domain
+     && p->path
+     && !strcmp(p->domain, domain)
+     && (!*p->path || !strncmp(p->path, path, strlen(p->path))))
+      break;
+  }
+  return p;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+struct soap_cookie*
+SOAP_FMAC2
+soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
+{ struct soap_cookie **p, *q;
+  int n;
+  if (!domain)
+    domain = soap->cookie_domain;
+  if (!path)
+    path = soap->cookie_path;
+  if (!path)
+    path = SOAP_STR_EOS;
+  else if (*path == '/')
+    path++;
+  q = soap_cookie(soap, name, domain, path);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s='%s' domain='%s' path='%s'\n", q ? SOAP_STR_EOS : "new ", name, value ? value : "(null)", domain ? domain : "(null)", path ? path : "(null)"));
+  if (!q)
+  { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
+    { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
+        strcpy(q->name, name);
+      q->value = NULL;
+      q->domain = NULL;
+      q->path = NULL;
+      q->expire = 0;
+      q->maxage = -1;
+      q->version = 1;
+      q->secure = 0;
+      q->modified = 0;
+      for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
+        if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
+          break;
+      if (n)
+      { q->next = *p;
+        *p = q;
+      }
+      else
+      { SOAP_FREE(soap, q->name);
+        SOAP_FREE(soap, q);
+        q = NULL;
+      }
+    }
+  }
+  else
+    q->modified = 1;
+  if (q)
+  { if (q->value)
+    { if (!value || strcmp(value, q->value))
+      { SOAP_FREE(soap, q->value);
+        q->value = NULL;
+      }
+    }
+    if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
+      strcpy(q->value, value);
+    if (q->domain)
+    { if (!domain || strcmp(domain, q->domain))
+      { SOAP_FREE(soap, q->domain);
+        q->domain = NULL;
+      }
+    }
+    if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
+      strcpy(q->domain, domain);
+    if (q->path)
+    { if (!path || strncmp(path, q->path, strlen(q->path)))
+      { SOAP_FREE(soap, q->path);
+        q->path = NULL;
+      }
+    }
+    if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
+      strcpy(q->path, path);
+    q->session = 1;
+    q->env = 0;
+  }
+  return q;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie **p, *q;
+  if (!domain)
+    domain = soap->cookie_domain;
+  if (!domain)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)"));
+    return;
+  }
+  if (!path)
+    path = soap->cookie_path;
+  if (!path)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie path not set\n", name ? name : "(null)"));
+    return;
+  }
+  if (*path == '/')
+    path++;
+  for (p = &soap->cookies, q = *p; q; q = *p)
+  { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
+    { if (q->value)
+        SOAP_FREE(soap, q->value);
+      if (q->domain)
+        SOAP_FREE(soap, q->domain);
+      if (q->path)
+        SOAP_FREE(soap, q->path);
+      *p = q->next;
+      SOAP_FREE(soap, q);
+    }
+    else
+      p = &q->next;
+  }
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+    return p->value;
+  return NULL;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)) && p->env)
+    return p->value;
+  return NULL;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+time_t
+SOAP_FMAC2
+soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+    return p->expire;
+  return -1;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", expire, name, domain ? domain : "(null)", path ? path : "(null)"));
+  if ((p = soap_cookie(soap, name, domain, path)))
+  { p->maxage = expire;
+    p->modified = 1;
+    return SOAP_OK;
+  }
+  return SOAP_ERR;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+  { p->session = 1;
+    p->modified = 1;
+    return SOAP_OK;
+  }
+  return SOAP_ERR;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
+{ struct soap_cookie *p;
+  if ((p = soap_cookie(soap, name, domain, path)))
+  { p->session = 0;
+    p->modified = 1;
+    return SOAP_OK;
+  }
+  return SOAP_ERR;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putsetcookies(struct soap *soap)
+{ struct soap_cookie *p;
+  char *s, tmp[4096];
+  const char *t;
+  for (p = soap->cookies; p; p = p->next)
+  {
+    if (p->modified
+#ifdef WITH_OPENSSL
+     || (!p->env && !soap->ssl == !p->secure)
+#endif
+       )
+    { s = tmp;
+      if (p->name)
+        s += soap_encode_url(p->name, s, tmp-s+4064);
+      if (p->value && *p->value)
+      { *s++ = '=';
+        s += soap_encode_url(p->value, s, tmp-s+4064);
+      }
+      if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
+      { strcpy(s, ";Domain=");
+        strcat(s, p->domain);
+      }
+      else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
+      { strcpy(s, ";Domain=");
+        strcat(s, soap->cookie_domain);
+      }
+      strcat(s, ";Path=/");
+      s += strlen(s);
+      if (p->path)
+        t = p->path;
+      else
+        t = soap->cookie_path;
+      if (t)
+      { if (*t == '/')
+          t++;
+        if ((int)strlen(t) < tmp-s+4064)
+        { if (strchr(t, '%'))	/* already URL encoded? */
+          { strcpy(s, t);
+            s += strlen(s);
+          }
+          else
+            s += soap_encode_url(t, s, tmp-s+4064);
+        }
+      }
+      if (p->version > 0 && s-tmp < 4060)
+      { 
+#ifdef HAVE_SNPRINTF
+        soap_snprintf(s, 4096 - (s-tmp), ";Version=%u", p->version);
+#else
+        sprintf(s, ";Version=%u", p->version);
+#endif
+        s += strlen(s);
+      }
+      if (p->maxage >= 0 && s-tmp < 4060)
+      {
+#ifdef HAVE_SNPRINTF
+        soap_snprintf(s, 4096 - (s-tmp), ";Max-Age=%ld", p->maxage);
+#else
+        sprintf(s, ";Max-Age=%ld", p->maxage);
+#endif
+        s += strlen(s);
+      }
+      if (s-tmp < 4073
+       && (p->secure
+#ifdef WITH_OPENSSL
+       || soap->ssl
+#endif
+         ))
+        strcpy(s, ";Secure");
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
+      if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
+        return soap->error;
+    }
+  }
+  return SOAP_OK;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
+{ struct soap_cookie **p, *q;
+  unsigned int version = 0;
+  time_t now = time(NULL);
+  char *s, tmp[4096];
+  if (!domain || !path)
+    return SOAP_OK;
+  s = tmp;
+  p = &soap->cookies;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path));
+  if (*path == '/')
+    path++;
+  while ((q = *p))
+  { if (q->expire && now > q->expire)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
+      SOAP_FREE(soap, q->name);
+      if (q->value)
+        SOAP_FREE(soap, q->value);
+      if (q->domain)
+        SOAP_FREE(soap, q->domain);
+      if (q->path)
+        SOAP_FREE(soap, q->path);
+      *p = q->next;
+      SOAP_FREE(soap, q);
+    }
+    else
+    { int flag;
+      char *t = q->domain;
+      size_t n = 0;
+      if (!t)
+        flag = 1;
+      else
+      { const char *r = strchr(t, ':');
+        if (r)
+          n = r - t;
+        else
+          n = strlen(t);
+        flag = !strncmp(t, domain, n);
+      }
+      /* domain-level cookies, cannot compile when WITH_NOIO set */
+#ifndef WITH_NOIO
+      if (!flag)
+      { struct hostent *hostent = gethostbyname((char*)domain);
+        if (hostent)
+        { const char *r = strchr(hostent->h_name, '.');
+          if (!r)
+            r = hostent->h_name;
+          flag = !strncmp(t, r, n);
+        }
+      }
+#endif
+      if (flag
+          && (!q->path || !strncmp(q->path, path, strlen(q->path)))
+          && (!q->secure || secure))
+      { size_t n = 12;
+        if (q->name)
+          n += 3*strlen(q->name);
+        if (q->value && *q->value)
+          n += 3*strlen(q->value) + 1;
+        if (q->path && *q->path)
+          n += strlen(q->path) + 9;
+        if (q->domain)
+          n += strlen(q->domain) + 11;
+        if (tmp - s + n > sizeof(tmp))
+        { if (s == tmp)
+            return SOAP_OK; /* HTTP header size overflow */
+          DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
+          if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
+            return soap->error;
+          s = tmp;
+        }
+        else if (s != tmp)
+        { strcat(s, " ");
+          s++;
+        }
+        if (q->version != version && s-tmp < 4060)
+        {
+#ifdef HAVE_SNPRINTF
+          soap_snprintf(s, 4096 - (s-tmp), "$Version=%u;", q->version);
+#else
+          sprintf(s, "$Version=%u;", q->version);
+#endif
+          version = q->version;
+          s += strlen(s);
+        }
+        if (q->name)
+          s += soap_encode_url(q->name, s, tmp+sizeof(tmp)-s-16);
+        if (q->value && *q->value)
+        { *s++ = '=';
+          s += soap_encode_url(q->value, s, tmp+sizeof(tmp)-s-16);
+        }
+        if (q->path && (s-tmp) + strlen(q->path) < 4060)
+        {
+#ifdef HAVE_SNPRINTF
+          soap_snprintf(s, 4096 - (s-tmp), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
+#else
+          sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
+#endif
+          s += strlen(s);
+        }
+        if (q->domain && (s-tmp) + strlen(q->domain) < 4060)
+        {
+#ifdef HAVE_SNPRINTF
+          soap_snprintf(s, 4096 - (s-tmp), ";$Domain=\"%s\"", q->domain);
+#else
+          sprintf(s, ";$Domain=\"%s\"", q->domain);
+#endif
+          s += strlen(s);
+        }
+      }
+      p = &q->next;
+    }
+  }
+  if (s != tmp)
+    if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
+      return soap->error;
+  return SOAP_OK;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_getcookies(struct soap *soap, const char *val)
+{ struct soap_cookie *p = NULL, *q;
+  const char *s;
+  char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
+  char *domain = NULL;
+  char *path = NULL;
+  unsigned int version = 0;
+  time_t now = time(NULL);
+  if (!val)
+    return;
+  s = val;
+  while (*s)
+  { s = soap_decode_key(tmp, sizeof(tmp), s);
+    if (!soap_tag_cmp(tmp, "$Version"))
+    { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
+      { if (p)
+          p->version = (int)soap_strtol(tmp, NULL, 10);
+        else
+          version = (int)soap_strtol(tmp, NULL, 10);
+      }
+    }
+    else if (!soap_tag_cmp(tmp, "$Path"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
+          strcpy(t, tmp);
+      }
+      else
+        t = NULL;
+      if (p)
+      { if (p->path)
+          SOAP_FREE(soap, p->path);
+        p->path = t;
+      }
+      else
+      { if (path)
+          SOAP_FREE(soap, path);
+        path = t;
+      }
+    }
+    else if (!soap_tag_cmp(tmp, "$Domain"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
+          strcpy(t, tmp);
+      }
+      else
+        t = NULL;
+      if (p)
+      { if (p->domain)
+          SOAP_FREE(soap, p->domain);
+        p->domain = t;
+      }
+      else
+      { if (domain)
+          SOAP_FREE(soap, domain);
+        domain = t;
+      }
+    }
+    else if (p && !soap_tag_cmp(tmp, "Path"))
+    { if (p->path)
+        SOAP_FREE(soap, p->path);
+      s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
+          strcpy(p->path, tmp);
+      }
+      else
+        p->path = NULL;
+    }
+    else if (p && !soap_tag_cmp(tmp, "Domain"))
+    { if (p->domain)
+        SOAP_FREE(soap, p->domain);
+      s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (*tmp)
+      { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
+          strcpy(p->domain, tmp);
+      }
+      else
+        p->domain = NULL;
+    }
+    else if (p && !soap_tag_cmp(tmp, "Version"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
+    }
+    else if (p && !soap_tag_cmp(tmp, "Max-Age"))
+    { s = soap_decode_val(tmp, sizeof(tmp), s);
+      p->expire = now + soap_strtol(tmp, NULL, 10);
+    }
+    else if (p && !soap_tag_cmp(tmp, "Expires"))
+    { struct tm T;
+      char a[3];
+      static const char mns[] = "anebarprayunulugepctovec";
+      s = soap_decode_val(tmp, sizeof(tmp), s);
+      if (strlen(tmp) > 20)
+      { memset((void*)&T, 0, sizeof(T));
+        a[0] = tmp[4];
+        a[1] = tmp[5];
+        a[2] = '\0';
+        T.tm_mday = (int)soap_strtol(a, NULL, 10);
+        a[0] = tmp[8];
+        a[1] = tmp[9];
+        T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
+        a[0] = tmp[11];
+        a[1] = tmp[12];
+        T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
+        a[0] = tmp[13];
+        a[1] = tmp[14];
+        T.tm_hour = (int)soap_strtol(a, NULL, 10);
+        a[0] = tmp[16];
+        a[1] = tmp[17];
+        T.tm_min = (int)soap_strtol(a, NULL, 10);
+        a[0] = tmp[19];
+        a[1] = tmp[20];
+        T.tm_sec = (int)soap_strtol(a, NULL, 10);
+        p->expire = soap_timegm(&T);
+      }
+    }
+    else if (p && !soap_tag_cmp(tmp, "Secure"))
+      p->secure = 1;
+    else
+    { if (p)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
+        if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
+        { q->version = p->version;
+          q->expire = p->expire;
+          q->secure = p->secure;
+          q->env = 1;
+        }
+        if (p->name)
+          SOAP_FREE(soap, p->name);
+        if (p->value)
+          SOAP_FREE(soap, p->value);
+        if (p->domain)
+          SOAP_FREE(soap, p->domain);
+        if (p->path)
+          SOAP_FREE(soap, p->path);
+        SOAP_FREE(soap, p);
+      }
+      if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
+      { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
+        strcpy(p->name, tmp);
+        s = soap_decode_val(tmp, sizeof(tmp), s);
+        if (*tmp)
+        { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
+          strcpy(p->value, tmp);
+        }
+        else
+          p->value = NULL;
+        if (domain)
+          p->domain = domain;
+        else if (*soap->host)
+        { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1);
+          strcpy(p->domain, soap->host);
+        }
+        else
+          p->domain = NULL;
+        if (path)
+          p->path = path;
+        else if (soap->path && *soap->path)
+        { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1);
+          strcpy(p->path, soap->path);
+        }
+        else
+        { p->path = (char*)SOAP_MALLOC(soap, 2);
+          strcpy(p->path, "/");
+        }
+        p->expire = 0;
+        p->secure = 0;
+        p->version = version;
+      }
+    }
+  }
+  if (p)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
+    if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
+    { q->version = p->version;
+      q->expire = p->expire;
+      q->secure = p->secure;
+      q->env = 1;
+    }
+    if (p->name)
+      SOAP_FREE(soap, p->name);
+    if (p->value)
+      SOAP_FREE(soap, p->value);
+    if (p->domain)
+      SOAP_FREE(soap, p->domain);
+    if (p->path)
+      SOAP_FREE(soap, p->path);
+    SOAP_FREE(soap, p);
+  }
+  if (domain)
+    SOAP_FREE(soap, domain);
+  if (path)
+    SOAP_FREE(soap, path);
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getenv_cookies(struct soap *soap)
+{ struct soap_cookie *p;
+  const char *s;
+  char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
+  if (!(s = getenv("HTTP_COOKIE")))
+    return SOAP_ERR;
+  do
+  { s = soap_decode_key(key, sizeof(key), s);
+    s = soap_decode_val(val, sizeof(val), s);
+    p = soap_set_cookie(soap, key, val, NULL, NULL);
+    if (p)
+      p->env = 1;
+  } while (*s);
+  return SOAP_OK;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+struct soap_cookie*
+SOAP_FMAC2
+soap_copy_cookies(struct soap *copy, const struct soap *soap)
+{ struct soap_cookie *p, **q, *r;
+  q = &r;
+  for (p = soap->cookies; p; p = p->next)
+  { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
+      return r;
+    **q = *p;
+    if (p->name)
+    { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
+        strcpy((*q)->name, p->name);
+    }
+    if (p->value)
+    { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
+        strcpy((*q)->value, p->value);
+    }
+    if (p->domain)
+    { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
+        strcpy((*q)->domain, p->domain);
+    }
+    if (p->path)
+    { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
+        strcpy((*q)->path, p->path);
+    }
+    q = &(*q)->next;
+  }
+  *q = NULL;
+  return r;
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_free_cookies(struct soap *soap)
+{ struct soap_cookie *p;
+  for (p = soap->cookies; p; p = soap->cookies)
+  { soap->cookies = p->next;
+    SOAP_FREE(soap, p->name);
+    if (p->value)
+      SOAP_FREE(soap, p->value);
+    if (p->domain)
+      SOAP_FREE(soap, p->domain);
+    if (p->path)
+      SOAP_FREE(soap, p->path);
+    SOAP_FREE(soap, p);
+  }
+}
+
+/******************************************************************************/
+#endif /* WITH_COOKIES */
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+size_t
+SOAP_FMAC2
+soap_hash(register const char *s)
+{ register size_t h = 0;
+  while (*s)
+    h = 65599*h + *s++;
+  return h % SOAP_IDHASH;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_1
+static void
+soap_init_pht(struct soap *soap)
+{ register int i;
+  soap->pblk = NULL;
+  soap->pidx = 0;
+  for (i = 0; i < (int)SOAP_PTRHASH; i++)
+    soap->pht[i] = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_versioning(soap_new)(soap_mode imode, soap_mode omode)
+{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
+  if (soap)
+    soap_versioning(soap_init)(soap, imode, omode);
+  return soap;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_free(struct soap *soap)
+{ soap_done(soap);
+  free(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_del(struct soap *soap)
+{ free(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_1
+static void
+soap_free_pht(struct soap *soap)
+{ register struct soap_pblk *pb, *next;
+  register int i;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
+  for (pb = soap->pblk; pb; pb = next)
+  { next = pb->next;
+    SOAP_FREE(soap, pb);
+  }
+  soap->pblk = NULL;
+  soap->pidx = 0;
+  for (i = 0; i < (int)SOAP_PTRHASH; i++)
+    soap->pht[i] = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
+{ register int i;
+  struct soap_plist *pp;
+  (void)soap;
+  if (soap->version == 2)
+    soap->encoding = 1;
+  if (a)
+    i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
+  else
+    i = soap_pointer_lookup(soap, p, type, &pp);
+  if (i)
+  { if (soap_is_embedded(soap, pp)
+     || soap_is_single(soap, pp))
+      return 0;
+    soap_set_embedded(soap, pp);
+  }
+  return i;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
+{ register struct soap_plist *pp;
+  *ppp = NULL;
+  if (p)
+  { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
+    { if (pp->ptr == p && pp->type == type)
+      { *ppp = pp;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
+        return pp->id;
+      }
+    }
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
+  return 0;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
+{ register size_t h;
+  register struct soap_plist *pp;
+  (void)n;
+  if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
+  { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
+    if (!pb)
+    { soap->error = SOAP_EOM;
+      return 0;
+    }
+    pb->next = soap->pblk;
+    soap->pblk = pb;
+    soap->pidx = 0;
+  }
+  *ppp = pp = &soap->pblk->plist[soap->pidx++];
+  if (a)
+    h = soap_hash_ptr(a->__ptr);
+  else
+    h = soap_hash_ptr(p);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a ? a->__ptr : NULL, a ? a->__size : 0, n, type, soap->idnum+1));
+  pp->next = soap->pht[h];
+  pp->type = type;
+  pp->mark1 = 0;
+  pp->mark2 = 0;
+  pp->ptr = p;
+  pp->array = a;
+  soap->pht[h] = pp;
+  pp->id = ++soap->idnum;
+  return pp->id;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
+{ register struct soap_plist *pp;
+  *ppp = NULL;
+  if (!p || !a->__ptr)
+    return 0;
+  for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
+  { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
+    { register int i;
+      for (i = 0; i < n; i++)
+        if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
+          break;
+      if (i == n)
+      { *ppp = pp;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
+        return pp->id;
+      }
+    }
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
+  return 0;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_begin_count(struct soap *soap)
+{ soap_free_ns(soap);
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
+    soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
+  else
+#endif
+  { soap->mode = soap->omode;
+    if ((soap->mode & SOAP_IO_UDP))
+      soap->mode |= SOAP_ENC_XML;
+    if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
+     || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
+#ifndef WITH_LEANER
+      && !soap->fpreparesend
+#endif
+      ))
+      soap->mode &= ~SOAP_IO_LENGTH;
+    else
+      soap->mode |= SOAP_IO_LENGTH;
+  }
+#ifdef WITH_ZLIB
+  if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
+  { if (!(soap->mode & SOAP_ENC_DIME))
+      soap->mode &= ~SOAP_IO_LENGTH;
+    if (soap->mode & SOAP_ENC_XML)
+      soap->mode |= SOAP_IO_BUFFER;
+    else
+      soap->mode |= SOAP_IO_STORE;
+  }
+#endif
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
+    soap->mode |= SOAP_ENC_MIME;
+  else if (!(soap->mode & SOAP_ENC_MIME))
+    soap->mode &= ~SOAP_ENC_MTOM;
+  if (soap->mode & SOAP_ENC_MIME)
+    soap_select_mime_boundary(soap);
+  soap->dime.list = soap->dime.last;	/* keep track of last DIME attachment */
+#endif
+  soap->count = 0;
+  soap->ns = 0;
+  soap->null = 0;
+  soap->position = 0;
+  soap->mustUnderstand = 0;
+  soap->encoding = 0;
+  soap->part = SOAP_BEGIN;
+  soap->event = 0;
+  soap->evlev = 0;
+  soap->idnum = 0;
+  soap_clr_attr(soap);
+  soap_set_local_namespaces(soap);
+#ifndef WITH_LEANER
+  soap->dime.count = 0; /* count # of attachments */
+  soap->dime.size = 0; /* accumulate total size of attachments */
+  if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
+    return soap->error;
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, (unsigned int)soap->mode, (unsigned long)soap->count));
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_end_count(struct soap *soap)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_IO_LENGTH))
+  { if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
+      return soap->error;
+  }
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_begin_send(struct soap *soap)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
+  soap_free_ns(soap);
+  soap->error = SOAP_OK;
+  soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
+#ifdef WITH_ZLIB
+  if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
+  { if (soap->mode & SOAP_ENC_XML)
+      soap->mode |= SOAP_IO_BUFFER;
+    else
+      soap->mode |= SOAP_IO_STORE;
+  }
+#endif
+#ifndef WITH_LEAN
+  if ((soap->mode & SOAP_IO_UDP))
+  { soap->mode |= SOAP_ENC_XML;
+    if (soap->count > SOAP_BUFLEN)
+      return soap->error = SOAP_UDP_ERROR;
+  }
+#endif
+  if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
+  { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
+      soap->mode |= SOAP_IO_BUFFER;
+    else
+      soap->mode |= SOAP_IO_STORE;
+  }
+  soap->mode &= ~SOAP_IO_LENGTH;
+  if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
+    if (soap_new_block(soap) == NULL)
+      return soap->error;
+  if (!(soap->mode & SOAP_IO_KEEPALIVE))
+    soap->keep_alive = 0;
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
+  { soap->mode |= SOAP_ENC_MIME;
+    soap->mode &= ~SOAP_ENC_DIME;
+  }
+  else if (!(soap->mode & SOAP_ENC_MIME))
+    soap->mode &= ~SOAP_ENC_MTOM;
+  if (soap->mode & SOAP_ENC_MIME)
+    soap_select_mime_boundary(soap);
+#ifdef WIN32
+#ifndef UNDER_CE
+#ifndef WITH_FASTCGI
+  if (!soap_valid_socket(soap->socket) && !soap->os) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
+#ifdef __BORLANDC__
+    setmode(soap->sendfd, _O_BINARY);
+#else
+    _setmode(soap->sendfd, _O_BINARY);
+#endif
+#endif
+#endif
+#endif
+#endif
+  if (soap->mode & SOAP_IO)
+  { soap->bufidx = 0;
+    soap->buflen = 0;
+  }
+  soap->chunksize = 0;
+  soap->ns = 0;
+  soap->null = 0;
+  soap->position = 0;
+  soap->mustUnderstand = 0;
+  soap->encoding = 0;
+  soap->idnum = 0;
+  soap->level = 0;
+  soap_clr_attr(soap);
+  soap_set_local_namespaces(soap);
+#ifdef WITH_ZLIB
+  soap->z_ratio_out = 1.0;
+  if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
+  { if (!soap->z_buf)
+      soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
+    soap->d_stream->next_out = (Byte*)soap->z_buf;
+    soap->d_stream->avail_out = SOAP_BUFLEN;
+#ifdef WITH_GZIP
+    if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
+    { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
+      soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
+      soap->d_stream->avail_out = SOAP_BUFLEN - 10;
+      soap->z_crc = crc32(0L, NULL, 0);
+      soap->zlib_out = SOAP_ZLIB_GZIP;
+      if (soap->z_dict)
+        *((Byte*)soap->z_buf + 2) = 0xff;
+      if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
+        return soap->error = SOAP_ZLIB_ERROR;
+    }
+    else
+#endif
+    if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
+      return soap->error = SOAP_ZLIB_ERROR;
+    if (soap->z_dict)
+    { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
+        return soap->error = SOAP_ZLIB_ERROR;
+    }
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
+    soap->zlib_state = SOAP_ZLIB_DEFLATE;
+  }
+#endif
+#ifdef WITH_OPENSSL
+  if (soap->ssl)
+    ERR_clear_error();
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
+  soap->part = SOAP_BEGIN;
+#ifndef WITH_LEANER
+  if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
+    return soap->error;
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_embedded(struct soap *soap, const void *p, int t)
+{ struct soap_plist *pp;
+  if (soap_pointer_lookup(soap, p, t, &pp))
+  { pp->mark1 = 1;
+    pp->mark2 = 1;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_reference(struct soap *soap, const void *p, int t)
+{ struct soap_plist *pp;
+  if (!p || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
+    return 1;
+  if (soap_pointer_lookup(soap, p, t, &pp))
+  { if (pp->mark1 == 0)
+    { pp->mark1 = 2;
+      pp->mark2 = 2;
+    }
+  }
+  else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
+    return 1;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
+  return pp->mark1;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
+{ struct soap_plist *pp;
+  if (!p || !a->__ptr || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
+    return 1;
+  if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
+  { if (pp->mark1 == 0)
+    { pp->mark1 = 2;
+      pp->mark2 = 2;
+    }
+  }
+  else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
+    return 1;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2));
+  return pp->mark1;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_embedded_id(struct soap *soap, int id, const void *p, int t)
+{ struct soap_plist *pp = NULL;
+  if (!id || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
+    return id;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
+  if (soap->version == 1 && soap->part != SOAP_IN_HEADER)
+  { if (id < 0)
+    { id = soap_pointer_lookup(soap, p, t, &pp);
+      if (id)
+      { if (soap->mode & SOAP_IO_LENGTH)
+          pp->mark1 = 2;
+        else
+          pp->mark2 = 2;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
+      }
+      return -1;
+    }
+    return id;
+  }
+  if (id < 0)
+    id = soap_pointer_lookup(soap, p, t, &pp);
+  else if (id && !soap_pointer_lookup(soap, p, t, &pp))
+    return 0;
+  if (id && pp)
+  { if (soap->mode & SOAP_IO_LENGTH)
+      pp->mark1 = 1;
+    else
+      pp->mark2 = 1;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
+  }
+  return id;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_is_embedded(struct soap *soap, struct soap_plist *pp)
+{ if (!pp)
+    return 0;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
+  if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
+  { if (soap->mode & SOAP_IO_LENGTH)
+      return pp->mark1 != 0;
+    return pp->mark2 != 0;
+  }
+  if (soap->mode & SOAP_IO_LENGTH)
+    return pp->mark1 == 1;
+  return pp->mark2 == 1;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_is_single(struct soap *soap, struct soap_plist *pp)
+{ if (soap->part == SOAP_IN_HEADER)
+    return 1;
+  if (!pp)
+    return 0;
+  if (soap->mode & SOAP_IO_LENGTH)
+    return pp->mark1 == 0;
+  return pp->mark2 == 0;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_embedded(struct soap *soap, struct soap_plist *pp)
+{ if (!pp)
+    return;
+  if (soap->mode & SOAP_IO_LENGTH)
+    pp->mark1 = 1;
+  else
+    pp->mark2 = 1;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t)
+{
+#ifndef WITH_NOIDREF
+  struct soap_plist *pp;
+  int i;
+  if (!p || !a->__ptr || (!aid && !atype))
+    return soap_element_id(soap, tag, id, p, a, n, type, t);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid ? aid : SOAP_STR_EOS, id, atype ? atype : SOAP_STR_EOS));
+  i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
+  if (!i)
+  { i = soap_pointer_enter(soap, p, a, n, t, &pp);
+    if (!i)
+    { soap->error = SOAP_EOM;
+      return -1;
+    }
+  }
+  if (id <= 0)
+    id = i;
+  if (!aid)
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->dime_id_format, id);
+#else
+    sprintf(soap->tmpbuf, soap->dime_id_format, id);
+#endif
+    aid = soap_strdup(soap, soap->tmpbuf);
+  }
+  /* Add MTOM xop:Include element when necessary */
+  /* TODO: this code to be obsoleted with new import/xop.h conventions */
+  if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
+  { if (soap_element_begin_out(soap, tag, 0, type)
+     || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
+     || soap_element_end_out(soap, tag))
+      return soap->error;
+  }
+  else if (soap_element_href(soap, tag, 0, "href", aid))
+    return soap->error;
+  if (soap->mode & SOAP_IO_LENGTH)
+  { if (pp->mark1 != 3)
+    { struct soap_multipart *content;
+      if (soap->mode & SOAP_ENC_MTOM)
+        content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
+      else
+        content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
+      if (!content)
+      { soap->error = SOAP_EOM;
+        return -1;
+      }
+      if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
+      { if (soap->mode & SOAP_ENC_MTOM)
+        { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
+          if (s)
+          { *s = '<';
+            strcpy(s + 1, aid + 4);
+            strcat(s, ">");
+            content->id = s;
+          }
+        }
+        else
+          content->id = aid + 4;
+      }
+      else
+        content->id = aid;
+      content->type = atype;
+      content->options = aoptions;
+      content->encoding = SOAP_MIME_BINARY;
+      pp->mark1 = 3;
+    }
+  }
+  else
+    pp->mark2 = 3;
+#endif
+  return -1;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_1
+static void
+soap_init_iht(struct soap *soap)
+{ register int i;
+  for (i = 0; i < SOAP_IDHASH; i++)
+    soap->iht[i] = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_1
+static void
+soap_free_iht(struct soap *soap)
+{ register int i;
+  register struct soap_ilist *ip = NULL, *p = NULL;
+  register struct soap_flist *fp = NULL, *fq = NULL;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
+  for (i = 0; i < SOAP_IDHASH; i++)
+  { for (ip = soap->iht[i]; ip; ip = p)
+    { for (fp = ip->flist; fp; fp = fq)
+      { fq = fp->next;
+        SOAP_FREE(soap, fp);
+      }
+      p = ip->next;
+      SOAP_FREE(soap, ip);
+    }
+    soap->iht[i] = NULL;
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+struct soap_ilist *
+SOAP_FMAC2
+soap_lookup(struct soap *soap, const char *id)
+{ register struct soap_ilist *ip = NULL;
+  for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
+    if (!strcmp(ip->id, id))
+      return ip;
+  return NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+struct soap_ilist *
+SOAP_FMAC2
+soap_enter(struct soap *soap, const char *id)
+{ register size_t h;
+  register struct soap_ilist *ip;
+  ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
+  if (ip)
+  { strcpy((char*)ip->id, id);
+    h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
+    ip->next = soap->iht[h];
+    soap->iht[h] = ip;
+  }
+  return ip;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_malloc(struct soap *soap, size_t n)
+{ register char *p;
+  if (!n)
+    return (void*)SOAP_NON_NULL;
+  if (!soap)
+    return SOAP_MALLOC(soap, n);
+  if (soap->fmalloc)
+    p = (char*)soap->fmalloc(soap, n);
+  else
+  { n += sizeof(short);
+    n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
+    if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
+    { soap->error = SOAP_EOM;
+      return NULL;
+    }
+    /* set the canary to detect corruption */
+    *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
+    /* keep chain of alloced cells for destruction */
+    *(void**)(p + n) = soap->alist;
+    *(size_t*)(p + n + sizeof(void*)) = n;
+    soap->alist = p + n;
+  }
+  soap->alloced = 1;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_MEM_DEBUG
+static void
+soap_init_mht(struct soap *soap)
+{ register int i;
+  for (i = 0; i < (int)SOAP_PTRHASH; i++)
+    soap->mht[i] = NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_MEM_DEBUG
+static void
+soap_free_mht(struct soap *soap)
+{ register int i;
+  register struct soap_mlist *mp, *mq;
+  for (i = 0; i < (int)SOAP_PTRHASH; i++)
+  { for (mp = soap->mht[i]; mp; mp = mq)
+    { mq = mp->next;
+      if (mp->live)
+        fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
+      free(mp);
+    }
+    soap->mht[i] = NULL;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_MEM_DEBUG
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
+{ register void *p = malloc(size);
+  if (soap)
+  { register size_t h = soap_hash_ptr(p);
+    register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
+    if (soap->fdebug[SOAP_INDEX_TEST])
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
+    }
+    mp->next = soap->mht[h];
+    mp->ptr = p;
+    mp->file = file;
+    mp->line = line;
+    mp->live = 1;
+    soap->mht[h] = mp;
+  }
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_MEM_DEBUG
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_track_free(struct soap *soap, const char *file, int line, void *p)
+{ register size_t h = soap_hash_ptr(p);
+  register struct soap_mlist *mp;
+  for (mp = soap->mht[h]; mp; mp = mp->next)
+    if (mp->ptr == p)
+      break;
+  if (mp)
+  { if (mp->live)
+    { free(p);
+      if (soap->fdebug[SOAP_INDEX_TEST])
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
+      }
+      mp->live = 0;
+    }
+    else
+      fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
+  }
+  else
+    fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_MEM_DEBUG
+static void
+soap_track_unlink(struct soap *soap, const void *p)
+{ register size_t h = soap_hash_ptr(p);
+  register struct soap_mlist *mp;
+  for (mp = soap->mht[h]; mp; mp = mp->next)
+    if (mp->ptr == p)
+      break;
+  if (mp)
+    mp->live = 0;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_dealloc(struct soap *soap, void *p)
+{ if (soap_check_state(soap))
+    return;
+  if (p)
+  { register char **q;
+    for (q = (char**)&soap->alist; *q; q = *(char***)q)
+    {
+      if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
+      {
+#ifdef SOAP_MEM_DEBUG
+        fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
+#endif
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
+        DBGHEX(TEST, *q - 200, 200);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
+        soap->error = SOAP_MOE;
+        return;
+      }
+      if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
+      { *q = **(char***)q;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
+        SOAP_FREE(soap, p);
+        return;
+      }
+    }
+    soap_delete(soap, p);
+  }
+  else
+  { register char *q;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
+    while (soap->alist)
+    { q = (char*)soap->alist;
+      if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
+      {
+#ifdef SOAP_MEM_DEBUG
+        fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
+#endif
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
+        DBGHEX(TEST, q - 200, 200);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
+        soap->error = SOAP_MOE;
+        return;
+      }
+      soap->alist = *(void**)q;
+      q -= *(size_t*)(q + sizeof(void*));
+      SOAP_FREE(soap, q);
+    }
+    /* we must assume these were deallocated: */
+    soap->http_content = NULL;
+    soap->action = NULL;
+    soap->fault = NULL;
+    soap->header = NULL;
+    soap->userid = NULL;
+    soap->passwd = NULL;
+    soap->authrealm = NULL;
+#ifdef WITH_NTLM
+    soap->ntlm_challenge = NULL;
+#endif
+#ifndef WITH_LEANER
+    soap_clr_mime(soap);
+#endif
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_delete(struct soap *soap, void *p)
+{ register struct soap_clist **cp;
+  if (soap_check_state(soap))
+    return;
+  cp = &soap->clist;
+  if (p)
+  { while (*cp)
+    { if (p == (*cp)->ptr)
+      { register struct soap_clist *q = *cp;
+        *cp = q->next;
+        if (q->fdelete(q))
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
+#ifdef SOAP_MEM_DEBUG
+          fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
+#endif
+        }
+        SOAP_FREE(soap, q);
+        return;
+      }
+      cp = &(*cp)->next;
+    }
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
+  }
+  else
+  { while (*cp)
+    { register struct soap_clist *q = *cp;
+      *cp = q->next;
+      if (q->fdelete(q))
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
+#ifdef SOAP_MEM_DEBUG
+        fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
+#endif
+      }
+      SOAP_FREE(soap, q);
+    }
+  }
+  soap->fault = NULL; /* this was possibly deallocated */
+  soap->header = NULL; /* this was possibly deallocated */
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
+{ register struct soap_clist *cp;
+  register char **q;
+#ifdef SOAP_MEM_DEBUG
+  register void *p;
+  register struct soap_mlist **mp, *mq;
+  size_t h;
+#endif
+  for (q = (char**)&soap->alist; *q; q = *(char***)q)
+  {
+    if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
+    {
+#ifdef SOAP_MEM_DEBUG
+      fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
+#endif
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
+      DBGHEX(TEST, *q - 200, 200);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
+      soap->error = SOAP_MOE;
+      return;
+    }
+#ifdef SOAP_MEM_DEBUG
+    p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
+    h = soap_hash_ptr(p);
+    for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
+    { if ((*mp)->ptr == p)
+      { mq = *mp;
+        *mp = mq->next;
+        mq->next = soap_to->mht[h];
+        soap_to->mht[h] = mq;
+        break;
+      }
+    }
+#endif
+  }
+  *q = (char*)soap_to->alist;
+  soap_to->alist = soap->alist;
+  soap->alist = NULL;
+#ifdef SOAP_MEM_DEBUG
+  cp = soap->clist;
+  while (cp)
+  { h = soap_hash_ptr(cp);
+    for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
+    { if ((*mp)->ptr == cp)
+      { mq = *mp;
+        *mp = mq->next;
+        mq->next = soap_to->mht[h];
+        soap_to->mht[h] = mq;
+        break;
+      }
+    }
+    cp = cp->next;
+  }
+#endif
+  cp = soap_to->clist;
+  if (cp)
+  { while (cp->next)
+      cp = cp->next;
+    cp->next = soap->clist;
+  }
+  else
+    soap_to->clist = soap->clist;
+  soap->clist = NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+struct soap_clist *
+SOAP_FMAC2
+soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*))
+{ register struct soap_clist *cp;
+  if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
+  { cp->next = soap->clist;
+    cp->type = t;
+    cp->size = n;
+    cp->ptr = p;
+    cp->fdelete = fdelete;
+    soap->clist = cp;
+  }
+  return cp;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_unlink(struct soap *soap, const void *p)
+{ register char **q;
+  register struct soap_clist **cp;
+  if (soap && p)
+  { for (q = (char**)&soap->alist; *q; q = *(char***)q)
+    { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
+      { *q = **(char***)q;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
+#ifdef SOAP_MEM_DEBUG
+        soap_track_unlink(soap, p);
+#endif
+        return SOAP_OK;		/* found and removed from dealloc chain */
+      }
+    }
+    for (cp = &soap->clist; *cp; cp = &(*cp)->next)
+    { if (p == (*cp)->ptr)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
+        q = (char**)*cp;
+        *cp = (*cp)->next;
+        SOAP_FREE(soap, q);
+        return SOAP_OK;		/* found and removed from dealloc chain */
+      }
+    }
+  }
+  return SOAP_ERR;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_lookup_type(struct soap *soap, const char *id)
+{ register struct soap_ilist *ip;
+  if (id && *id)
+  { ip = soap_lookup(soap, id);
+    if (ip)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
+      return ip->type;
+    }
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
+  return 0;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
+{ struct soap_ilist *ip;
+  void **q;
+  if (!p || !id || !*id)
+    return p;
+  ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
+  if (!ip)
+  { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
+      return NULL;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
+    ip->type = t;
+    ip->size = n;
+    ip->link = p;
+    ip->copy = NULL;
+    ip->flist = NULL;
+    ip->ptr = NULL;
+    ip->level = k;
+    *p = NULL;
+  }
+  else if (ip->ptr)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
+    if (ip->type != t)
+    { strcpy(soap->id, id);
+      soap->error = SOAP_HREF;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t));
+      return NULL;
+    }
+    while (ip->level < k)
+    { q = (void**)soap_malloc(soap, sizeof(void*));
+      if (!q)
+        return NULL;
+      *p = (void*)q;
+      p = q;
+      k--;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
+    }
+    *p = ip->ptr;
+  }
+  else if (ip->level > k)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
+    while (ip->level > k)
+    { void *s, **r = &ip->link;
+      q = (void**)ip->link;
+      while (q)
+      { *r = (void*)soap_malloc(soap, sizeof(void*));
+        if (!*r)
+          return NULL;
+        s = *q;
+        *q = *r;
+        r = (void**)*r;
+        q = (void**)s;
+      }
+      *r = NULL;
+      ip->size = n;
+      ip->copy = NULL;
+      ip->level = ip->level - 1;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
+    }
+    q = (void**)ip->link;
+    ip->link = p;
+    *p = (void*)q;
+  }
+  else
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
+    while (ip->level < k)
+    { q = (void**)soap_malloc(soap, sizeof(void*));
+      if (!q)
+        return NULL;
+      *p = q;
+      p = q;
+      k--;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
+    }
+    q = (void**)ip->link;
+    ip->link = p;
+    *p = (void*)q;
+  }
+  return p;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIDREF
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t))
+{ struct soap_ilist *ip;
+  if (!p || !href || !*href)
+    return p;
+  ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
+  if (!ip)
+  { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */
+      return NULL;
+    ip->type = st;
+    ip->size = n;
+    ip->link = NULL;
+    ip->copy = NULL;
+    ip->ptr = NULL;
+    ip->level = 0;
+    ip->flist = NULL;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p));
+  }
+  else if (ip->type != st || (ip->level == k && ip->size != n))
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n));
+    strcpy(soap->id, href);
+    soap->error = SOAP_HREF;
+    return NULL;
+  }
+  if (fcopy || n < sizeof(void*) || *href != '#')
+  { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
+    if (!fp)
+    { soap->error = SOAP_EOM;
+      return NULL;
+    }
+    fp->next = ip->flist;
+    fp->type = tt;
+    fp->ptr = p;
+    fp->level = k;
+    fp->len = len;
+    if (fcopy)
+      fp->fcopy = fcopy;
+    else
+      fp->fcopy = soap_fcopy;
+    ip->flist = fp;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href));
+  }
+  else
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
+    *(void**)p = ip->copy;
+    ip->copy = p;
+  }
+  return p;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void*
+SOAP_FMAC2
+soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*))
+{
+#ifndef WITH_NOIDREF
+  struct soap_ilist *ip;
+#endif
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
+  soap->alloced = 0;
+  if (!p)
+  { if (finstantiate)
+      p = finstantiate(soap, t, type, arrayType, &n);
+    else
+      p = soap_malloc(soap, n);
+    if (p)
+      soap->alloced = 1;
+  }
+#ifndef WITH_NOIDREF
+  if (!id || !*id)
+#endif
+    return p;
+#ifndef WITH_NOIDREF
+  ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
+  if (!ip)
+  { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
+      return NULL;
+    ip->type = t;
+    ip->link = NULL;
+    ip->copy = NULL;
+    ip->flist = NULL;
+    ip->size = n;
+    ip->ptr = p;
+    ip->level = k;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p));
+  }
+  else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
+    strcpy(soap->id, id);
+    soap->error = SOAP_HREF;
+    return NULL;
+  }
+  else if (ip->ptr)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
+    strcpy(soap->id, id);
+    soap->error = SOAP_DUPLICATE_ID;
+    return NULL;
+  }
+  else
+  { ip->size = n;
+    ip->ptr = p;
+    ip->level = k;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
+  }
+  return ip->ptr;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
+{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
+  memcpy(p, q, n);
+  (void)soap; (void)st; (void)tt; (void)len;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_end_send(struct soap *soap)
+{
+#ifndef WITH_LEANER
+  int err;
+  if (soap->dime.list)
+  { /* SOAP body referenced attachments must appear first */
+    soap->dime.last->next = soap->dime.first;
+    soap->dime.first = soap->dime.list->next;
+    soap->dime.list->next = NULL;
+    soap->dime.last = soap->dime.list;
+  }
+  if (!(err = soap_putdime(soap)))
+    err = soap_putmime(soap);
+  soap->mime.list = NULL;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->dime.list = NULL;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+  if (err)
+    return err;
+#endif
+  return soap_end_send_flush(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_end_send_flush(struct soap *soap)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
+  if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
+  { if (soap_flush(soap))
+#ifdef WITH_ZLIB
+    { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
+      { soap->zlib_state = SOAP_ZLIB_NONE;
+        deflateEnd(soap->d_stream);
+      }
+      return soap->error;
+    }
+#else
+      return soap->error;
+#endif
+#ifdef WITH_ZLIB
+    if (soap->mode & SOAP_ENC_ZLIB)
+    { int r;
+      soap->d_stream->avail_in = 0;
+      do
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
+        r = deflate(soap->d_stream, Z_FINISH);
+        if (soap->d_stream->avail_out != SOAP_BUFLEN)
+        { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out))
+          { soap->zlib_state = SOAP_ZLIB_NONE;
+            deflateEnd(soap->d_stream);
+            return soap->error;
+          }
+          soap->d_stream->next_out = (Byte*)soap->z_buf;
+          soap->d_stream->avail_out = SOAP_BUFLEN;
+        }
+      } while (r == Z_OK);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
+      soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
+      soap->mode &= ~SOAP_ENC_ZLIB;
+      soap->zlib_state = SOAP_ZLIB_NONE;
+      if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
+        return soap->error = SOAP_ZLIB_ERROR;
+      }
+#ifdef WITH_GZIP
+      if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
+      { soap->z_buf[0] = soap->z_crc & 0xFF;
+        soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
+        soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
+        soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
+        soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
+        soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
+        soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
+        soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
+        if (soap_flush_raw(soap, soap->z_buf, 8))
+          return soap->error;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
+      }
+#endif
+    }
+#endif
+    if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
+    { char *p;
+#ifndef WITH_NOHTTP
+      if (!(soap->mode & SOAP_ENC_XML))
+      { soap->mode--;
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
+        if (soap->status >= SOAP_POST)
+          soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
+        else if (soap->status != SOAP_STOP)
+          soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
+        if (soap->error || soap_flush(soap))
+          return soap->error;
+        soap->mode++;
+      }
+#endif
+      for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
+      { DBGMSG(SENT, p, soap_block_size(soap, NULL));
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), soap->socket, soap->sendfd));
+        if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL))))
+        { soap_end_block(soap, NULL);
+          return soap->error;
+        }
+      }
+      soap_end_block(soap, NULL);
+      if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
+        return soap->error;
+    }
+#ifndef WITH_LEANER
+    else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+    { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
+      if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
+        return soap->error;
+    }
+#endif
+  }
+#ifdef WITH_TCPFIN
+#ifdef WITH_OPENSSL
+  if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
+    soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
+#else
+  if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
+    soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
+#endif
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
+  soap->omode &= ~SOAP_SEC_WSUID;
+  soap->count = 0;
+  soap->part = SOAP_END;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_end_recv(struct soap *soap)
+{ soap->part = SOAP_END;
+#ifndef WITH_LEAN
+  soap->wsuid = NULL;		/* reset before next send */
+  soap->c14nexclude = NULL;	/* reset before next send */
+#endif
+#ifndef WITH_LEANER
+  soap->ffilterrecv = NULL;
+  if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
+  { soap->dime.first = NULL;
+    soap->dime.last = NULL;
+    return soap->error;
+  }
+  soap->dime.list = soap->dime.first;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+  /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
+  if (soap->mode & SOAP_ENC_MIME)
+  { if (soap->mode & SOAP_MIME_POSTCHECK)
+    { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n"));
+      if (!soap->keep_alive)
+        soap->keep_alive = -1;
+#ifndef WITH_NOIDREF
+      soap_resolve(soap);
+#endif
+      return SOAP_OK;
+    }
+    if (soap_getmime(soap))
+      return soap->error;
+  }
+  soap->mime.list = soap->mime.first;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = NULL;
+  if (soap->xlist)
+  { struct soap_multipart *content;
+    for (content = soap->mime.list; content; content = content->next)
+      soap_resolve_attachment(soap, content);
+  }
+#endif
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
+#ifdef WITH_ZLIB
+  if (soap->mode & SOAP_ENC_ZLIB)
+  { /* Make sure end of compressed content is reached */
+    while (soap->d_stream->next_out != Z_NULL)
+      if ((int)soap_get1(soap) == EOF)
+        break;
+    soap->mode &= ~SOAP_ENC_ZLIB;
+    memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
+    soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
+    soap->buflen = soap->z_buflen;
+    soap->zlib_state = SOAP_ZLIB_NONE;
+    if (inflateEnd(soap->d_stream) != Z_OK)
+      return soap->error = SOAP_ZLIB_ERROR;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
+#ifdef WITH_GZIP
+    if (soap->zlib_in == SOAP_ZLIB_GZIP)
+    { soap_wchar c;
+      short i;
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
+      for (i = 0; i < 8; i++)
+      { if ((int)(c = soap_get1(soap)) == EOF)
+        { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n"));
+          return soap->error = SOAP_ZLIB_ERROR;
+        }
+        soap->z_buf[i] = (char)c;
+      }
+      if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24)))
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
+        return soap->error = SOAP_ZLIB_ERROR;
+      }
+      if (soap->d_stream->total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24)))
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n"));
+        return soap->error = SOAP_ZLIB_ERROR;
+      }
+    }
+    soap->zlib_in = SOAP_ZLIB_NONE;
+#endif
+  }
+#endif
+  if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+    while (soap->ahead != EOF && !soap_recv_raw(soap))
+      ;
+#ifndef WITH_NOIDREF
+  if (soap_resolve(soap))
+    return soap->error;
+#endif
+#ifndef WITH_LEANER
+  if (soap->xlist)
+  { if (soap->mode & SOAP_ENC_MTOM)
+      return soap->error = SOAP_MIME_HREF;
+    return soap->error = SOAP_DIME_HREF;
+  }
+#endif
+  soap_free_ns(soap);
+#ifndef WITH_LEANER
+  if (soap->fpreparefinalrecv)
+    return soap->error = soap->fpreparefinalrecv(soap);
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_free_temp(struct soap *soap)
+{ register struct soap_attribute *tp, *tq;
+  register struct Namespace *ns;
+  soap_free_ns(soap);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
+  while (soap->blist)
+    soap_end_block(soap, NULL);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
+  for (tp = soap->attributes; tp; tp = tq)
+  { tq = tp->next;
+    if (tp->value)
+      SOAP_FREE(soap, tp->value);
+    SOAP_FREE(soap, tp);
+  }
+  soap->attributes = NULL;
+#ifdef WITH_FAST
+  if (soap->labbuf)
+    SOAP_FREE(soap, soap->labbuf);
+  soap->labbuf = NULL;
+  soap->lablen = 0;
+  soap->labidx = 0;
+#endif
+  ns = soap->local_namespaces;
+  if (ns)
+  { for (; ns->id; ns++)
+    { if (ns->out)
+      { SOAP_FREE(soap, ns->out);
+        ns->out = NULL;
+      }
+    }
+    SOAP_FREE(soap, soap->local_namespaces);
+    soap->local_namespaces = NULL;
+  }
+#ifndef WITH_LEANER
+  while (soap->xlist)
+  { struct soap_xlist *xp = soap->xlist->next;
+    SOAP_FREE(soap, soap->xlist);
+    soap->xlist = xp;
+  }
+#endif
+#ifndef WITH_NOIDREF
+  soap_free_pht(soap);
+  soap_free_iht(soap);
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void
+soap_free_ns(struct soap *soap)
+{ register struct soap_nlist *np, *nq;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
+  for (np = soap->nlist; np; np = nq)
+  { nq = np->next;
+    SOAP_FREE(soap, np);
+  }
+  soap->nlist = NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
+static void
+soap_init_logs(struct soap *soap)
+{ int i;
+  for (i = 0; i < SOAP_MAXLOGS; i++)
+  { soap->logfile[i] = NULL;
+    soap->fdebug[i] = NULL;
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_open_logfile(struct soap *soap, int i)
+{ if (soap->logfile[i])
+    soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+static void
+soap_close_logfile(struct soap *soap, int i)
+{ if (soap->fdebug[i])
+  { fclose(soap->fdebug[i]);
+    soap->fdebug[i] = NULL;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_close_logfiles(struct soap *soap)
+{ int i;
+  for (i = 0; i < SOAP_MAXLOGS; i++)
+    soap_close_logfile(soap, i);
+}
+#endif
+
+/******************************************************************************/
+#ifdef SOAP_DEBUG
+static void
+soap_set_logfile(struct soap *soap, int i, const char *logfile)
+{ const char *s;
+  char *t = NULL;
+  soap_close_logfile(soap, i);
+  s = soap->logfile[i];
+  soap->logfile[i] = logfile;
+  if (s)
+    SOAP_FREE(soap, (void*)s);
+  if (logfile)
+    if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
+      strcpy(t, logfile);
+  soap->logfile[i] = t;
+}
+#endif
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_recv_logfile(struct soap *soap, const char *logfile)
+{
+#ifdef SOAP_DEBUG
+  soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
+#endif
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_sent_logfile(struct soap *soap, const char *logfile)
+{
+#ifdef SOAP_DEBUG
+  soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
+#endif
+}
+
+/******************************************************************************/
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_test_logfile(struct soap *soap, const char *logfile)
+{
+#ifdef SOAP_DEBUG
+  soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
+#endif
+}
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_copy(const struct soap *soap)
+{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap*
+SOAP_FMAC2
+soap_copy_context(struct soap *copy, const struct soap *soap)
+{ if (copy == soap)
+    return copy;
+  if (soap_check_state(soap))
+    return NULL;
+  if (copy)
+  { register struct soap_plugin *p = NULL;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n"));
+#ifdef __cplusplus
+    *copy = *soap;
+#else
+    memcpy(copy, soap, sizeof(struct soap));
+#endif
+    copy->state = SOAP_COPY;
+    copy->error = SOAP_OK;
+    copy->userid = NULL;
+    copy->passwd = NULL;
+#ifdef WITH_NTLM
+    copy->ntlm_challenge = NULL;
+#endif
+    copy->nlist = NULL;
+    copy->blist = NULL;
+    copy->clist = NULL;
+    copy->alist = NULL;
+    copy->attributes = NULL;
+    copy->labbuf = NULL;
+    copy->lablen = 0;
+    copy->labidx = 0;
+#ifdef SOAP_MEM_DEBUG
+    soap_init_mht(copy);
+#endif
+#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
+    soap_init_logs(copy);
+#endif
+#ifdef SOAP_DEBUG
+    soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
+    soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
+    soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
+#endif
+    copy->namespaces = soap->local_namespaces;
+    copy->local_namespaces = NULL;
+    soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */
+    copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */
+#ifdef WITH_C_LOCALE
+# ifdef WIN32
+    copy->c_locale = _create_locale(LC_ALL, "C");
+# else
+    copy->c_locale = duplocale(soap->c_locale);
+# endif
+#else
+    copy->c_locale = NULL;
+#endif
+#ifdef WITH_OPENSSL
+    copy->bio = NULL;
+    copy->ssl = NULL;
+    copy->session = NULL;
+#endif
+#ifdef WITH_GNUTLS
+    copy->session = NULL;
+#endif
+#ifdef WITH_ZLIB
+    copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
+    copy->d_stream->zalloc = Z_NULL;
+    copy->d_stream->zfree = Z_NULL;
+    copy->d_stream->opaque = Z_NULL;
+    copy->z_buf = NULL;
+#endif
+#ifndef WITH_NOIDREF
+    soap_init_iht(copy);
+    soap_init_pht(copy);
+#endif
+    copy->header = NULL;
+    copy->fault = NULL;
+    copy->action = NULL;
+#ifndef WITH_LEAN
+#ifdef WITH_COOKIES
+    copy->cookies = soap_copy_cookies(copy, soap);
+#else
+    copy->cookies = NULL;
+#endif
+#endif
+    copy->plugins = NULL;
+    for (p = soap->plugins; p; p = p->next)
+    { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
+      if (!q)
+        return NULL;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
+      *q = *p;
+      if (p->fcopy && p->fcopy(copy, q, p))
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
+        SOAP_FREE(copy, q);
+        return NULL;
+      }
+      q->next = copy->plugins;
+      copy->plugins = q;
+    }
+  }
+  return copy;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_copy_stream(struct soap *copy, struct soap *soap)
+{ struct soap_attribute *tp = NULL, *tq;
+  if (copy == soap)
+    return;
+  copy->header = soap->header;
+  copy->mode = soap->mode;
+  copy->imode = soap->imode;
+  copy->omode = soap->omode;
+  copy->master = soap->master;
+  copy->socket = soap->socket;
+  copy->sendsk = soap->sendsk;
+  copy->recvsk = soap->recvsk;
+  copy->recv_timeout = soap->recv_timeout;
+  copy->send_timeout = soap->send_timeout;
+#if defined(__cplusplus) && !defined(WITH_LEAN)
+  copy->os = soap->os;
+  copy->is = soap->is;
+#endif
+  copy->sendfd = soap->sendfd;
+  copy->recvfd = soap->recvfd;
+  copy->bufidx = soap->bufidx;
+  copy->buflen = soap->buflen;
+  copy->ahead = soap->ahead;
+  copy->cdata = soap->cdata;
+  copy->chunksize = soap->chunksize;
+  copy->chunkbuflen = soap->chunkbuflen;
+  copy->keep_alive = soap->keep_alive;
+  copy->tcp_keep_alive = soap->tcp_keep_alive;
+  copy->tcp_keep_idle = soap->tcp_keep_idle;
+  copy->tcp_keep_intvl = soap->tcp_keep_intvl;
+  copy->tcp_keep_cnt = soap->tcp_keep_cnt;
+  copy->max_keep_alive = soap->max_keep_alive;
+#ifndef WITH_NOIO
+  copy->peer = soap->peer;
+  copy->peerlen = soap->peerlen;
+  copy->ip = soap->ip;
+  copy->port = soap->port;
+  memcpy(copy->host, soap->host, sizeof(soap->host));
+  memcpy(copy->endpoint, soap->endpoint, sizeof(soap->endpoint));
+#endif
+#ifdef WITH_OPENSSL
+  copy->bio = soap->bio;
+  copy->ctx = soap->ctx;
+  copy->ssl = soap->ssl;
+#endif
+#ifdef WITH_GNUTLS
+  copy->session = soap->session;
+#endif
+#ifdef WITH_ZLIB
+  copy->zlib_state = soap->zlib_state;
+  copy->zlib_in = soap->zlib_in;
+  copy->zlib_out = soap->zlib_out;
+  if (!copy->d_stream)
+    copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
+  if (copy->d_stream)
+    memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream));
+  copy->z_crc = soap->z_crc;
+  copy->z_ratio_in = soap->z_ratio_in;
+  copy->z_ratio_out = soap->z_ratio_out;
+  copy->z_buf = NULL;
+  copy->z_buflen = soap->z_buflen;
+  copy->z_level = soap->z_level;
+  if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
+  { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN);
+    if (copy->z_buf)
+      memcpy(copy->z_buf, soap->z_buf, SOAP_BUFLEN);
+  }
+  copy->z_dict = soap->z_dict;
+  copy->z_dict_len = soap->z_dict_len;
+#endif
+  memcpy(copy->buf, soap->buf, sizeof(soap->buf));
+  /* copy XML parser state */
+  soap_free_ns(copy);
+  soap_set_local_namespaces(copy);
+  copy->version = soap->version;
+  if (soap->nlist && soap->local_namespaces)
+  { register struct soap_nlist *np = NULL, *nq;
+    /* copy reversed nlist */
+    for (nq = soap->nlist; nq; nq = nq->next)
+    { register struct soap_nlist *nr = np;
+      size_t n = sizeof(struct soap_nlist) + strlen(nq->id);
+      np = (struct soap_nlist*)SOAP_MALLOC(copy, n);
+      if (!np)
+        break;
+      memcpy(np, nq, n);
+      np->next = nr;
+    }
+    while (np)
+    { register const char *s = np->ns;
+      copy->level = np->level; /* preserve element nesting level */
+      if (!s && np->index >= 0)
+      { s = soap->local_namespaces[np->index].out;
+        if (!s)
+          s = soap->local_namespaces[np->index].ns;
+      }
+      if (s && soap_push_namespace(copy, np->id, s) == NULL)
+        break;
+      nq = np;
+      np = np->next;
+      SOAP_FREE(copy, nq);
+    }
+  }
+  memcpy(copy->tag, soap->tag, sizeof(copy->tag));
+  memcpy(copy->id, soap->id, sizeof(copy->id));
+  memcpy(copy->href, soap->href, sizeof(copy->href));
+  memcpy(copy->type, soap->type, sizeof(copy->type));
+  copy->other = soap->other;
+  copy->root = soap->root;
+  copy->null = soap->null;
+  copy->body = soap->body;
+  copy->part = soap->part;
+  copy->mustUnderstand = soap->mustUnderstand;
+  copy->level = soap->level;
+  copy->peeked = soap->peeked;
+  /* copy attributes */
+  for (tq = soap->attributes; tq; tq = tq->next)
+  { struct soap_attribute *tr = tp;
+    size_t n = sizeof(struct soap_attribute) + strlen(tq->name);
+    tp = (struct soap_attribute*)SOAP_MALLOC(copy, n);
+    memcpy(tp, tq, n);
+    if (tp->size)
+    { tp->value = (char*)SOAP_MALLOC(copy, tp->size);
+      if (tp->value)
+        strcpy(tp->value, tq->value);
+    }
+    tp->ns = NULL;
+    tp->next = tr;
+  }
+  copy->attributes = tp;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_free_stream(struct soap *soap)
+{ soap->socket = SOAP_INVALID_SOCKET;
+  soap->sendsk = SOAP_INVALID_SOCKET;
+  soap->recvsk = SOAP_INVALID_SOCKET;
+#ifdef WITH_OPENSSL
+  soap->bio = NULL;
+  soap->ctx = NULL;
+  soap->ssl = NULL;
+#endif
+#ifdef WITH_GNUTLS
+  soap->xcred = NULL;
+  soap->acred = NULL;
+  soap->cache = NULL;
+  soap->session = NULL;
+  soap->dh_params = NULL;
+  soap->rsa_params = NULL;
+#endif
+#ifdef WITH_ZLIB
+  if (soap->z_buf)
+    SOAP_FREE(soap, soap->z_buf);
+  soap->z_buf = NULL;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_initialize(struct soap *soap)
+{ soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
+{ size_t i;
+  soap->state = SOAP_INIT;
+#ifdef SOAP_MEM_DEBUG
+  soap_init_mht(soap);
+#endif
+#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
+  soap_init_logs(soap);
+#endif
+#ifdef SOAP_DEBUG
+#ifdef TANDEM_NONSTOP
+  soap_set_test_logfile(soap, "TESTLOG");
+  soap_set_sent_logfile(soap, "SENTLOG");
+  soap_set_recv_logfile(soap, "RECVLOG");
+#else
+  soap_set_test_logfile(soap, "TEST.log");
+  soap_set_sent_logfile(soap, "SENT.log");
+  soap_set_recv_logfile(soap, "RECV.log");
+#endif
+#endif
+  soap->version = 0;
+  soap_mode(soap, imode);
+  soap_imode(soap, imode);
+  soap_omode(soap, omode);
+  soap->plugins = NULL;
+  soap->user = NULL;
+  for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++)
+    soap->data[i] = NULL;
+  soap->userid = NULL;
+  soap->passwd = NULL;
+  soap->authrealm = NULL;
+#ifdef WITH_NTLM
+  soap->ntlm_challenge = NULL;
+#endif
+#ifndef WITH_NOHTTP
+  soap->fpost = http_post;
+  soap->fget = http_get;
+  soap->fput = http_405;
+  soap->fdel = http_405;
+  soap->fopt = http_200;
+  soap->fhead = http_200;
+  soap->fform = NULL;
+  soap->fposthdr = http_post_header;
+  soap->fresponse = http_response;
+  soap->fparse = http_parse;
+  soap->fparsehdr = http_parse_header;
+#endif
+  soap->fheader = NULL;
+  soap->fconnect = NULL;
+  soap->fdisconnect = NULL;
+#ifndef WITH_NOIO
+  soap->ipv6_multicast_if = 0; /* in_addr_t value */
+  soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */
+  soap->ipv4_multicast_ttl = 0; /* 0: use default */
+#ifndef WITH_IPV6
+  soap->fresolve = tcp_gethost;
+#else
+  soap->fresolve = NULL;
+#endif
+  soap->faccept = tcp_accept;
+  soap->fopen = tcp_connect;
+  soap->fclose = tcp_disconnect;
+  soap->fclosesocket = tcp_closesocket;
+  soap->fshutdownsocket = tcp_shutdownsocket;
+  soap->fsend = fsend;
+  soap->frecv = frecv;
+  soap->fpoll = soap_poll;
+#else
+  soap->fopen = NULL;
+  soap->fclose = NULL;
+  soap->fpoll = NULL;
+#endif
+  soap->fseterror = NULL;
+  soap->fignore = NULL;
+  soap->fserveloop = NULL;
+  soap->fplugin = fplugin;
+  soap->fmalloc = NULL;
+#ifndef WITH_LEANER
+  soap->feltbegin = NULL;
+  soap->feltendin = NULL;
+  soap->feltbegout = NULL;
+  soap->feltendout = NULL;
+  soap->fprepareinitsend = NULL;
+  soap->fprepareinitrecv = NULL;
+  soap->fpreparesend = NULL;
+  soap->fpreparerecv = NULL;
+  soap->fpreparefinalsend = NULL;
+  soap->fpreparefinalrecv = NULL;
+  soap->ffiltersend = NULL;
+  soap->ffilterrecv = NULL;
+  soap->fdimereadopen = NULL;
+  soap->fdimewriteopen = NULL;
+  soap->fdimereadclose = NULL;
+  soap->fdimewriteclose = NULL;
+  soap->fdimeread = NULL;
+  soap->fdimewrite = NULL;
+  soap->fmimereadopen = NULL;
+  soap->fmimewriteopen = NULL;
+  soap->fmimereadclose = NULL;
+  soap->fmimewriteclose = NULL;
+  soap->fmimeread = NULL;
+  soap->fmimewrite = NULL;
+#endif
+  soap->float_format = "%.9G"; /* Alternative: use "%G" */
+  soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
+  soap->dime_id_format = "cid:id%d"; /* default DIME id format */
+  soap->http_version = "1.1";
+  soap->proxy_http_version = "1.0";
+  soap->http_content = NULL;
+  soap->actor = NULL;
+  soap->lang = "en";
+  soap->keep_alive = 0;
+  soap->tcp_keep_alive = 0;
+  soap->tcp_keep_idle = 0;
+  soap->tcp_keep_intvl = 0;
+  soap->tcp_keep_cnt = 0;
+  soap->max_keep_alive = SOAP_MAXKEEPALIVE;
+  soap->recv_timeout = 0;
+  soap->send_timeout = 0;
+  soap->connect_timeout = 0;
+  soap->accept_timeout = 0;
+  soap->socket_flags = 0;
+  soap->connect_flags = 0;
+  soap->bind_flags = 0;
+  soap->accept_flags = 0;
+  soap->linger_time = 0;
+  soap->ip = 0;
+  soap->labbuf = NULL;
+  soap->lablen = 0;
+  soap->labidx = 0;
+  soap->encodingStyle = NULL;
+#ifndef WITH_NONAMESPACES
+  soap->namespaces = namespaces;
+#else
+  soap->namespaces = NULL;
+#endif
+  soap->local_namespaces = NULL;
+  soap->nlist = NULL;
+  soap->blist = NULL;
+  soap->clist = NULL;
+  soap->alist = NULL;
+  soap->attributes = NULL;
+  soap->header = NULL;
+  soap->fault = NULL;
+  soap->master = SOAP_INVALID_SOCKET;
+  soap->socket = SOAP_INVALID_SOCKET;
+  soap->sendsk = SOAP_INVALID_SOCKET;
+  soap->recvsk = SOAP_INVALID_SOCKET;
+  soap->os = NULL;
+  soap->is = NULL;
+#ifndef WITH_LEANER
+  soap->dom = NULL;
+  soap->dime.list = NULL;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+  soap->mime.list = NULL;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = NULL;
+  soap->mime.start = NULL;
+  soap->xlist = NULL;
+#endif
+#ifndef UNDER_CE
+  soap->recvfd = 0;
+  soap->sendfd = 1;
+#else
+  soap->recvfd = stdin;
+  soap->sendfd = stdout;
+#endif
+  soap->host[0] = '\0';
+  soap->port = 0;
+  soap->action = NULL;
+  soap->proxy_host = NULL;
+  soap->proxy_port = 8080;
+  soap->proxy_userid = NULL;
+  soap->proxy_passwd = NULL;
+  soap->prolog = NULL;
+#ifdef WITH_ZLIB
+  soap->zlib_state = SOAP_ZLIB_NONE;
+  soap->zlib_in = SOAP_ZLIB_NONE;
+  soap->zlib_out = SOAP_ZLIB_NONE;
+  soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
+  soap->d_stream->zalloc = Z_NULL;
+  soap->d_stream->zfree = Z_NULL;
+  soap->d_stream->opaque = Z_NULL;
+  soap->z_buf = NULL;
+  soap->z_level = 6;
+  soap->z_dict = NULL;
+  soap->z_dict_len = 0;
+#endif
+#ifndef WITH_LEAN
+  soap->wsuid = NULL;
+  soap->c14nexclude = NULL;
+  soap->cookies = NULL;
+  soap->cookie_domain = NULL;
+  soap->cookie_path = NULL;
+  soap->cookie_max = 32;
+#endif
+#ifdef WMW_RPM_IO
+  soap->rpmreqid = NULL;
+#endif
+#ifdef PALM
+  palmNetLibOpen();
+#endif
+#ifndef WITH_NOIDREF
+  soap_init_iht(soap);
+  soap_init_pht(soap);
+#endif
+#ifdef WITH_OPENSSL
+  if (!soap_ssl_init_done)
+    soap_ssl_init();
+  soap->fsslauth = ssl_auth_init;
+  soap->fsslverify = ssl_verify_callback;
+  soap->bio = NULL;
+  soap->ssl = NULL;
+  soap->ctx = NULL;
+  soap->session = NULL;
+  soap->ssl_flags = SOAP_SSL_DEFAULT;
+  soap->keyfile = NULL;
+  soap->keyid = NULL;
+  soap->password = NULL;
+  soap->cafile = NULL;
+  soap->capath = NULL;
+  soap->crlfile = NULL;
+  soap->dhfile = NULL;
+  soap->randfile = NULL;
+#endif
+#ifdef WITH_GNUTLS
+  if (!soap_ssl_init_done)
+    soap_ssl_init();
+  soap->fsslauth = ssl_auth_init;
+  soap->fsslverify = NULL;
+  soap->xcred = NULL;
+  soap->acred = NULL;
+  soap->cache = NULL;
+  soap->session = NULL;
+  soap->ssl_flags = SOAP_SSL_DEFAULT;
+  soap->keyfile = NULL;
+  soap->keyid = NULL;
+  soap->password = NULL;
+  soap->cafile = NULL;
+  soap->capath = NULL;
+  soap->crlfile = NULL;
+  soap->dh_params = NULL;
+  soap->rsa_params = NULL;
+#endif
+#ifdef WITH_C_LOCALE
+# ifdef WIN32
+  soap->c_locale = _create_locale(LC_ALL, "C");
+# else
+  soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL);
+# endif
+#else
+  soap->c_locale = NULL;
+#endif
+  soap->buflen = 0;
+  soap->bufidx = 0;
+#ifndef WITH_LEANER
+  soap->dime.chunksize = 0;
+  soap->dime.buflen = 0;
+#endif
+  soap->null = 0;
+  soap->position = 0;
+  soap->encoding = 0;
+  soap->mustUnderstand = 0;
+  soap->ns = 0;
+  soap->part = SOAP_END;
+  soap->event = 0;
+  soap->evlev = 0;
+  soap->alloced = 0;
+  soap->count = 0;
+  soap->length = 0;
+  soap->cdata = 0;
+  soap->peeked = 0;
+  soap->ahead = 0;
+  soap->idnum = 0;
+  soap->level = 0;
+  soap->endpoint[0] = '\0';
+  soap->error = SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_begin(struct soap *soap)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
+  if (!soap->keep_alive)
+  { soap->buflen = 0;
+    soap->bufidx = 0;
+  }
+  soap->null = 0;
+  soap->position = 0;
+  soap->encoding = 0;
+  soap->mustUnderstand = 0;
+  soap->mode = 0;
+  soap->ns = 0;
+  soap->part = SOAP_END;
+  soap->event = 0;
+  soap->evlev = 0;
+  soap->alloced = 0;
+  soap->count = 0;
+  soap->length = 0;
+  soap->cdata = 0;
+  soap->error = SOAP_OK;
+  soap->peeked = 0;
+  soap->ahead = 0;
+  soap->idnum = 0;
+  soap->level = 0;
+  soap->endpoint[0] = '\0';
+  soap->encodingStyle = SOAP_STR_EOS;
+#ifndef WITH_LEANER
+  soap->dime.chunksize = 0;
+  soap->dime.buflen = 0;
+#endif
+  soap_free_temp(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_end(struct soap *soap)
+{ if (soap_check_state(soap))
+    return;
+  soap_free_temp(soap);
+  soap_dealloc(soap, NULL);
+  while (soap->clist)
+  { register struct soap_clist *cp = soap->clist->next;
+    SOAP_FREE(soap, soap->clist);
+    soap->clist = cp;
+  }
+  soap_closesock(soap);
+#ifdef SOAP_DEBUG
+  soap_close_logfiles(soap);
+#endif
+#ifdef PALM
+  palmNetLibClose();
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_version(struct soap *soap, short version)
+{ soap_set_local_namespaces(soap);
+  if (soap->version != version)
+  { if (version == 1)
+    { soap->local_namespaces[0].ns = soap_env1;
+      soap->local_namespaces[1].ns = soap_enc1;
+    }
+    else if (version == 2)
+    { soap->local_namespaces[0].ns = soap_env2;
+      soap->local_namespaces[1].ns = soap_enc2;
+    }
+    soap->version = version;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_namespaces(struct soap *soap, const struct Namespace *p)
+{ register struct Namespace *ns = soap->local_namespaces;
+  register struct soap_nlist *np, *nq, *nr;
+  register unsigned int level = soap->level;
+  soap->namespaces = p;
+  soap->local_namespaces = NULL;
+  soap_set_local_namespaces(soap);
+  /* reverse the namespace list */
+  np = soap->nlist;
+  soap->nlist = NULL;
+  if (np)
+  { nq = np->next;
+    np->next = NULL;
+    while (nq)
+    { nr = nq->next;
+      nq->next = np;
+      np = nq;
+      nq = nr;
+    }
+  }
+  /* then push on new stack */
+  while (np)
+  { register const char *s;
+    soap->level = np->level; /* preserve element nesting level */
+    s = np->ns;
+    if (!s && np->index >= 0 && ns)
+    { s = ns[np->index].out;
+      if (!s)
+        s = ns[np->index].ns;
+    }
+    if (s && soap_push_namespace(soap, np->id, s) == NULL)
+      return soap->error;
+    nq = np;
+    np = np->next;
+    SOAP_FREE(soap, nq);
+  }
+  if (ns)
+  { register int i;
+    for (i = 0; ns[i].id; i++)
+    { if (ns[i].out)
+      { SOAP_FREE(soap, ns[i].out);
+        ns[i].out = NULL;
+      }
+    }
+    SOAP_FREE(soap, ns);
+  }
+  soap->level = level; /* restore level */
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_local_namespaces(struct soap *soap)
+{ if (soap->namespaces && !soap->local_namespaces)
+  { register const struct Namespace *ns1;
+    register struct Namespace *ns2;
+    register size_t n = 1;
+    for (ns1 = soap->namespaces; ns1->id; ns1++)
+      n++;
+    n *= sizeof(struct Namespace);
+    ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
+    if (ns2)
+    { memcpy(ns2, soap->namespaces, n);
+      if (ns2[0].ns)
+      { if (!strcmp(ns2[0].ns, soap_env1))
+          soap->version = 1;
+        else if (!strcmp(ns2[0].ns, soap_env2))
+          soap->version = 2;
+      }
+      soap->local_namespaces = ns2;
+      for (; ns2->id; ns2++)
+        ns2->out = NULL;
+    }
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+#ifndef PALM_1
+SOAP_FMAC1
+const char *
+SOAP_FMAC2
+soap_tagsearch(const char *big, const char *little)
+{ if (little)
+  { register size_t n = strlen(little);
+    register const char *s = big;
+    while (s)
+    { register const char *t = s;
+      register size_t i;
+      for (i = 0; i < n; i++, t++)
+      { if (*t != little[i])
+          break;
+      }
+      if (*t == '\0' || *t == ' ')
+      { if (i == n || (i && little[i-1] == ':'))
+          return s;
+      }
+      s = strchr(t, ' ');
+      if (s)
+        s++;
+    }
+  }
+  return NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap_nlist *
+SOAP_FMAC2
+soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
+{ register struct soap_nlist *np;
+  for (np = soap->nlist; np; np = np->next)
+  { if (!strncmp(np->id, tag, n) && !np->id[n])
+      return np;
+  }
+  return NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+static struct soap_nlist *
+soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
+{ register struct soap_nlist *np;
+  size_t n, k;
+  if (soap_tagsearch(soap->c14nexclude, id))
+    return NULL;
+  if (!utilized)
+  { for (np = soap->nlist; np; np = np->next)
+    { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
+        break;
+    }
+    if (np)
+    { if ((np->level < soap->level || !np->ns) && np->index == 1)
+        utilized = 1;
+      else
+        return NULL;
+    }
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns ? ns : "(null)", utilized));
+  n = strlen(id);
+  if (ns)
+    k = strlen(ns);
+  else
+    k = 0;
+  np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
+  if (!np)
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  np->next = soap->nlist;
+  soap->nlist = np;
+  strcpy((char*)np->id, id);
+  if (ns)
+    np->ns = strcpy((char*)np->id + n + 1, ns);
+  else
+    np->ns = NULL;
+  np->level = soap->level;
+  np->index = utilized;
+  return np;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+static void
+soap_utilize_ns(struct soap *soap, const char *tag)
+{ register struct soap_nlist *np;
+  size_t n = 0;
+  const char *t = strchr(tag, ':');
+  if (t)
+  { n = t - tag;
+    if (n >= sizeof(soap->tmpbuf))
+      n = sizeof(soap->tmpbuf) - 1;
+  }
+  np = soap_lookup_ns(soap, tag, n);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
+  if (np)
+  { if (np->index <= 0)
+      soap_push_ns(soap, np->id, np->ns, 1);
+  }
+  else if (strncmp(tag, "xml", 3))
+  { strncpy(soap->tmpbuf, tag, n);
+    soap->tmpbuf[n] = '\0';
+    soap_push_ns(soap, soap->tmpbuf, NULL, 1);
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element(struct soap *soap, const char *tag, int id, const char *type)
+{
+#ifndef WITH_LEAN
+  register const char *s;
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id, type ? type : SOAP_STR_EOS));
+  soap->level++;
+#ifdef WITH_DOM
+#ifndef WITH_LEAN
+  if (soap->wsuid && soap_tagsearch(soap->wsuid, tag))
+  { size_t i;
+    for (s = tag, i = 0; *s && i < sizeof(soap->tag) - 1; s++, i++)
+      soap->tag[i] = *s == ':' ? '-' : *s;
+    soap->tag[i] = '\0';
+    if (soap_set_attr(soap, "wsu:Id", soap->tag, 1))
+      return soap->error;
+  }
+  if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
+  { if (soap->evlev >= soap->level)
+      soap->evlev = 0;
+    if (soap->event == SOAP_SEC_BEGIN && !soap->evlev)
+    { register struct soap_nlist *np;
+      /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
+      for (np = soap->nlist; np; np = np->next)
+      { if (np->index == 2)
+        { struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1);
+          if (np1)
+            np1->index = 0;
+        }
+      }
+      soap->evlev = soap->level;
+    }
+  }
+#endif
+  if (soap->mode & SOAP_XML_DOM)
+  { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
+    if (!elt)
+      return soap->error;
+    elt->soap = soap;
+    elt->next = NULL;
+    elt->prnt = soap->dom;
+    elt->name = soap_strdup(soap, tag);
+    elt->elts = NULL;
+    elt->atts = NULL;
+    elt->nstr = NULL;
+    elt->data = NULL;
+    elt->wide = NULL;
+    elt->node = NULL;
+    elt->type = 0;
+    elt->head = NULL;
+    elt->tail = NULL;
+    if (soap->dom)
+    { struct soap_dom_element *p = soap->dom->elts;
+      if (p)
+      { while (p->next)
+          p = p->next;
+        p->next = elt;
+      }
+      else
+        soap->dom->elts = elt;
+    }
+    soap->dom = elt;
+  }
+  else
+  {
+#endif
+#ifndef WITH_LEAN
+    if (!soap->ns)
+    { if (!(soap->mode & SOAP_XML_CANONICAL)
+       && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
+        return soap->error;
+    }
+    else if (soap->mode & SOAP_XML_INDENT)
+    { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
+        return soap->error;
+      soap->body = 1;
+    }
+    if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
+    { struct Namespace *ns = soap->local_namespaces;
+      size_t n = s - tag;
+      if (soap_send_raw(soap, "<", 1)
+       || soap_send(soap, s + 1))
+        return soap->error;
+      if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
+        ns = NULL;
+      for (; ns && ns->id; ns++)
+      { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
+        { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
+          if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
+            return soap->error;
+          break;
+        }
+      }
+    }
+    else
+#endif
+    if (soap_send_raw(soap, "<", 1)
+     || soap_send(soap, tag))
+      return soap->error;
+#ifdef WITH_DOM
+  }
+#endif
+  if (!soap->ns)
+  { struct Namespace *ns = soap->local_namespaces;
+    int k = -1;
+    if (ns)
+    {
+#ifndef WITH_LEAN
+      if ((soap->mode & SOAP_XML_DEFAULTNS))
+      { if (soap->version)
+          k = 4; /* first four required entries */
+        else if (!(soap->mode & SOAP_XML_NOTYPE) || (soap->mode & SOAP_XML_NIL))
+        { ns += 2;
+          k = 2; /* next two entries */
+        }
+        else
+          k = 0; /* no entries */
+      }
+#endif
+      while (k-- && ns->id)
+      { if (*ns->id && (ns->out || ns->ns))
+        {
+#ifdef HAVE_SNPRINTF
+          soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", ns->id);
+#else
+          sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
+#endif
+          if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
+            return soap->error;
+        }
+        ns++;
+      }
+    }
+  }
+  soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table  */
+#ifndef WITH_LEAN
+  if (soap->mode & SOAP_XML_CANONICAL)
+    soap_utilize_ns(soap, tag);
+#endif
+  if (id > 0)
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "_%d", id);
+#else
+    sprintf(soap->tmpbuf, "_%d", id);
+#endif
+    if (soap->version == 2)
+    { if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
+        return soap->error;
+    }
+    else if (soap_attribute(soap, "id", soap->tmpbuf))
+      return soap->error;
+  }
+  if (type && *type && !(soap->mode & SOAP_XML_NOTYPE) && soap->part != SOAP_IN_HEADER)
+  { const char *t = type;
+#ifndef WITH_LEAN
+    if (soap->mode & SOAP_XML_DEFAULTNS)
+    { t = strchr(type, ':');
+      if (t)
+        t++;
+      else
+        t = type;
+    }
+#endif
+    if (soap->attributes ? soap_set_attr(soap, "xsi:type", t, 1) : soap_attribute(soap, "xsi:type", t))
+      return soap->error;
+#ifndef WITH_LEAN
+    if (soap->mode & SOAP_XML_CANONICAL)
+      soap_utilize_ns(soap, type);
+#endif
+  }
+  if (soap->null && soap->position > 0)
+  { register int i;
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, "[%d", soap->positions[0]);
+#else
+    sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
+#endif
+    for (i = 1; i < soap->position; i++)
+    { register size_t l = strlen(soap->tmpbuf);
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf)-l-1, ",%d", soap->positions[i]);
+#else
+      if (l + 13 < sizeof(soap->tmpbuf))
+        sprintf(soap->tmpbuf + l, ",%d", soap->positions[i]);
+#endif
+    }
+    strcat(soap->tmpbuf, "]");
+    if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
+      return soap->error;
+  }
+  if (soap->mustUnderstand)
+  { if (soap->actor && *soap->actor)
+    { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
+        return soap->error;
+    }
+    if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
+      return soap->error;
+    soap->mustUnderstand = 0;
+  }
+  if (soap->encoding)
+  { if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id)
+    { if (!*soap->encodingStyle)
+      { if (soap->local_namespaces[1].out)
+          soap->encodingStyle = soap->local_namespaces[1].out;
+        else
+          soap->encodingStyle = soap->local_namespaces[1].ns;
+      }
+      if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
+        return soap->error;
+    }
+    else
+      soap->encodingStyle = NULL;
+    soap->encoding = 0;
+  }
+  soap->null = 0;
+  soap->position = 0;
+  if (soap->event == SOAP_SEC_BEGIN)
+    soap->event = 0;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
+{ if (*tag == '-')
+    return SOAP_OK;
+  if (soap_element(soap, tag, id, type))
+    return soap->error;
+#ifdef WITH_DOM
+  if (soap_element_start_end_out(soap, NULL))
+    return soap->error;
+  if (soap->feltbegout)
+    return soap->error = soap->feltbegout(soap, tag);
+  return SOAP_OK;
+#else
+  return soap_element_start_end_out(soap, NULL);
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+#ifndef HAVE_STRRCHR
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_strrchr(const char *s, int t)
+{ register char *r = NULL;
+  while (*s)
+    if (*s++ == t)
+      r = (char*)s - 1;
+  return r;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+#ifndef HAVE_STRTOL
+SOAP_FMAC1
+long
+SOAP_FMAC2
+soap_strtol(const char *s, char **t, int b)
+{ register long n = 0;
+  register int c;
+  while (*s > 0 && *s <= 32)
+    s++;
+  if (b == 10)
+  { short neg = 0;
+    if (*s == '-')
+    { s++;
+      neg = 1;
+    }
+    else if (*s == '+')
+      s++;
+    while ((c = *s) && c >= '0' && c <= '9')
+    { if (n >= 214748364 && (n > 214748364 || c >= '8'))
+        break;
+      n *= 10;
+      n += c - '0';
+      s++;
+    }
+    if (neg)
+      n = -n;
+  }
+  else /* assume b == 16 and value is always positive */
+  { while ((c = *s))
+    { if (c >= '0' && c <= '9')
+        c -= '0';
+      else if (c >= 'A' && c <= 'F')
+        c -= 'A' - 10;
+      else if (c >= 'a' && c <= 'f')
+        c -= 'a' - 10;
+      if (n > 0x07FFFFFF)
+        break;
+      n <<= 4;
+      n += c;
+      s++;
+    }
+  }
+  if (t)
+    *t = (char*)s;
+  return n;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+#ifndef HAVE_STRTOUL
+SOAP_FMAC1
+unsigned long
+SOAP_FMAC2
+soap_strtoul(const char *s, char **t, int b)
+{ unsigned long n = 0;
+  register int c;
+  while (*s > 0 && *s <= 32)
+    s++;
+  if (b == 10)
+  { if (*s == '+')
+      s++;
+    while ((c = *s) && c >= '0' && c <= '9')
+    { if (n >= 429496729 && (n > 429496729 || c >= '6'))
+        break;
+      n *= 10;
+      n += c - '0';
+      s++;
+    }
+  }
+  else /* b == 16 */
+  { while ((c = *s))
+    { if (c >= '0' && c <= '9')
+        c -= '0';
+      else if (c >= 'A' && c <= 'F')
+        c -= 'A' - 10;
+      else if (c >= 'a' && c <= 'f')
+        c -= 'a' - 10;
+      if (n > 0x0FFFFFFF)
+        break;
+      n <<= 4;
+      n += c;
+      s++;
+    }
+  }
+  if (t)
+    *t = (char*)s;
+  return n;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
+{ if (!type || !*type)
+    return soap_element_begin_out(soap, tag, id, NULL);
+  if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
+    return soap->error;
+  if (soap->version == 2)
+  { const char *s;
+    s = soap_strrchr(type, '[');
+    if (s && (size_t)(s - type) < sizeof(soap->tmpbuf))
+    { strncpy(soap->tmpbuf, type, s - type);
+      soap->tmpbuf[s - type] = '\0';
+      if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
+        return soap->error;
+      s++;
+      if (*s)
+      { strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
+        soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
+        soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0';
+        if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf))
+          return soap->error;
+      }
+    }
+  }
+  else
+  { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
+      return soap->error;
+    if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
+      return soap->error;
+  }
+#ifndef WITH_LEAN
+  if ((soap->mode & SOAP_XML_CANONICAL))
+    soap_utilize_ns(soap, type);
+#endif
+  return soap_element_start_end_out(soap, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_start_end_out(struct soap *soap, const char *tag)
+{ register struct soap_attribute *tp;
+#ifndef WITH_LEAN
+  if (soap->mode & SOAP_XML_CANONICAL)
+  { struct soap_nlist *np;
+    for (tp = soap->attributes; tp; tp = tp->next)
+    { if (tp->visible && tp->name)
+        soap_utilize_ns(soap, tp->name);
+    }
+    for (np = soap->nlist; np; np = np->next)
+    { if (np->index == 1 && np->ns)
+      { if (*(np->id))
+        {
+#ifdef HAVE_SNPRINTF
+          soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", np->id);
+#else
+          sprintf(soap->tmpbuf, "xmlns:%s", np->id);
+#endif
+        }
+        else
+          strcpy(soap->tmpbuf, "xmlns");
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
+        soap_set_attr(soap, soap->tmpbuf, np->ns, 1);
+        np->index = 2;
+      }
+    }
+  }
+#endif
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { register struct soap_dom_attribute **att;
+    att = &soap->dom->atts;
+    for (tp = soap->attributes; tp; tp = tp->next)
+    { if (tp->visible)
+      { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
+        if (!*att)
+          return soap->error;
+        (*att)->next = NULL;
+        (*att)->nstr = NULL;
+        (*att)->name = soap_strdup(soap, tp->name);
+        (*att)->data = soap_strdup(soap, tp->value);
+        (*att)->wide = NULL;
+        (*att)->soap = soap;
+        att = &(*att)->next;
+        tp->visible = 0;
+      }
+    }
+    return SOAP_OK;
+  }
+#endif
+  for (tp = soap->attributes; tp; tp = tp->next)
+  { if (tp->visible)
+    {
+#ifndef WITH_LEAN
+      const char *s;
+      if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':')))
+      { size_t n = s - tp->name;
+        if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
+          s++;
+        else
+          s = tp->name;
+        if (soap_send(soap, " ") || soap_send(soap, s))
+          return soap->error;
+      }
+      else
+#endif
+      if (soap_send(soap, " ") || soap_send(soap, tp->name))
+        return soap->error;
+      if (tp->visible == 2 && tp->value)
+        if (soap_send_raw(soap, "=\"", 2)
+         || soap_string_out(soap, tp->value, tp->flag)
+         || soap_send_raw(soap, "\"", 1))
+          return soap->error;
+      tp->visible = 0;
+    }
+  }
+  if (tag)
+  {
+#ifndef WITH_LEAN
+    if (soap->mode & SOAP_XML_CANONICAL)
+    { if (soap_send_raw(soap, ">", 1)
+       || soap_element_end_out(soap, tag))
+        return soap->error;
+      return SOAP_OK;
+    }
+#endif
+    soap->level--;	/* decrement level just before /> */
+    return soap_send_raw(soap, "/>", 2);
+  }
+  return soap_send_raw(soap, ">", 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_end_out(struct soap *soap, const char *tag)
+{
+#ifndef WITH_LEAN
+  const char *s;
+#endif
+  if (*tag == '-')
+    return SOAP_OK;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
+#ifdef WITH_DOM
+  if (soap->feltendout && (soap->error = soap->feltendout(soap, tag)))
+    return soap->error;
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { if (soap->dom->prnt)
+      soap->dom = soap->dom->prnt;
+    return SOAP_OK;
+  }
+#endif
+#ifndef WITH_LEAN
+  if (soap->mode & SOAP_XML_CANONICAL)
+    soap_pop_namespace(soap);
+  if (soap->mode & SOAP_XML_INDENT)
+  { if (!soap->body)
+    { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
+        return soap->error;
+    }
+    soap->body = 0;
+  }
+  if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
+  { soap_pop_namespace(soap);
+    tag = s + 1;
+  }
+#endif
+  if (soap_send_raw(soap, "</", 2)
+   || soap_send(soap, tag))
+    return soap->error;
+  soap->level--;	/* decrement level just before > */
+  return soap_send_raw(soap, ">", 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_ref(struct soap *soap, const char *tag, int id, int href)
+{ register const char *s = "ref";
+  register int n = 1;
+  if (soap->version == 1)
+  { s = "href";
+    n = 0;
+  }
+  else if (soap->version == 2)
+    s = "SOAP-ENC:ref";
+#ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->href, sizeof(soap->href), "#_%d", href);
+#else
+  sprintf(soap->href, "#_%d", href);
+#endif
+  return soap_element_href(soap, tag, id, s, soap->href + n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
+  if (soap_element(soap, tag, id, NULL)
+   || soap_attribute(soap, ref, val)
+   || soap_element_start_end_out(soap, tag))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
+{ struct soap_attribute *tp = NULL;
+  for (tp = soap->attributes; tp; tp = tp->next)
+    if (tp->visible)
+      break;
+  if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
+  { if (soap_element(soap, tag, id, type)
+     || (!tp && soap_attribute(soap, "xsi:nil", "true")))
+      return soap->error;
+    return soap_element_start_end_out(soap, tag);
+  }
+  soap->null = 1;
+  soap->position = 0;
+  soap->mustUnderstand = 0;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_nil(struct soap *soap, const char *tag)
+{ if (soap_element(soap, tag, -1, NULL)
+   || ((soap->mode & SOAP_XML_NIL) && soap_attribute(soap, "xsi:nil", "true")))
+    return soap->error;
+  return soap_element_start_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t)
+{ if (!p)
+  { soap->error = soap_element_null(soap, tag, id, type);
+    return -1;
+  }
+#ifndef WITH_NOIDREF
+  if ((!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
+    return 0;
+  if (id < 0)
+  { struct soap_plist *pp;
+    if (a)
+      id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
+    else
+      id = soap_pointer_lookup(soap, p, t, &pp);
+    if (id)
+    { if (soap_is_embedded(soap, pp))
+      { soap_element_ref(soap, tag, 0, id);
+        return -1;
+      }
+      if (soap_is_single(soap, pp))
+        return 0;
+      soap_set_embedded(soap, pp);
+    }
+  }
+  return id;
+#else
+  return 0;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_result(struct soap *soap, const char *tag)
+{ if (soap->version == 2 && soap->encodingStyle)
+  { if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
+     || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
+     || soap_element_start_end_out(soap, NULL)
+     || soap_string_out(soap, tag, 0)
+     || soap_element_end_out(soap, "SOAP-RPC:result"))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_check_result(struct soap *soap, const char *tag)
+{ if (soap->version == 2 && soap->encodingStyle)
+  { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
+    /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
+  }
+  (void)tag;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_attribute(struct soap *soap, const char *name, const char *value)
+{
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
+  { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
+    if (!a)
+      return soap->error;
+    a->next = soap->dom->atts;
+    a->nstr = NULL;
+    a->name = soap_strdup(soap, name);
+    a->data = soap_strdup(soap, value);
+    a->wide = NULL;
+    a->soap = soap;
+    soap->dom->atts = a;
+    return SOAP_OK;
+  }
+#endif
+#ifndef WITH_LEAN
+  if (soap->mode & SOAP_XML_CANONICAL)
+  { /* push namespace */
+    if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
+      soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0);
+    else if (soap_set_attr(soap, name, value, 1))
+      return soap->error;
+  }
+  else
+#endif
+  { if (soap_send(soap, " ") || soap_send(soap, name))
+      return soap->error;
+    if (value)
+      if (soap_send_raw(soap, "=\"", 2)
+       || soap_string_out(soap, value, 1)
+       || soap_send_raw(soap, "\"", 1))
+        return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
+{ if (!soap_peek_element(soap))
+  { if (soap->other)
+      return soap->error = SOAP_TAG_MISMATCH;
+    if (tag && *tag == '-')
+      return SOAP_OK;
+    if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
+    { soap->peeked = 0;
+      if (type && *soap->type && soap_match_tag(soap, soap->type, type))
+        return soap->error = SOAP_TYPE;
+      if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
+        return soap->error = SOAP_NULL;
+      if (soap->body)
+        soap->level++;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS ));
+      soap->error = SOAP_OK;
+    }
+  }
+  else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
+    soap->error = SOAP_OK;
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_element_end_in(struct soap *soap, const char *tag)
+{ register soap_wchar c;
+  register char *s;
+  register int n = 0;
+  if (tag && *tag == '-')
+    return SOAP_OK;
+  if (soap->error == SOAP_NO_TAG)
+    soap->error = SOAP_OK;
+#ifdef WITH_DOM
+  /* this whitespace or mixed content is significant for DOM */
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
+      return soap->error;
+    if (soap->dom->prnt)
+      soap->dom = soap->dom->prnt;
+  }
+#endif
+  if (soap->peeked)
+  { if (*soap->tag)
+      n++;
+    soap->peeked = 0;
+  }
+  do
+  { while (((c = soap_get(soap)) != SOAP_TT))
+    { if ((int)c == EOF)
+        return soap->error = SOAP_CHK_EOF;
+      if (c == SOAP_LT)
+        n++;
+      else if (c == '/')
+      { c = soap_get(soap);
+        if (c == SOAP_GT)
+          n--;
+        else
+          soap_unget(soap, c);
+      }
+    }
+  } while (n--);
+  s = soap->tag;
+  n = sizeof(soap->tag);
+  while (soap_notblank(c = soap_get(soap)))
+  { if (--n > 0)
+      *s++ = (char)c;
+  }
+  *s = '\0';
+  if ((int)c == EOF)
+    return soap->error = SOAP_CHK_EOF;
+  while (soap_blank(c))
+    c = soap_get(soap);
+  if (c != SOAP_GT)
+    return soap->error = SOAP_SYNTAX_ERROR;
+#ifndef WITH_LEAN
+#ifdef WITH_DOM
+  if (soap->feltendin)
+  { soap->level--;
+    return soap->error = soap->feltendin(soap, soap->tag, tag);
+  }
+#endif
+  if (tag && (soap->mode & SOAP_XML_STRICT))
+  { soap_pop_namespace(soap);
+    if (soap_match_tag(soap, soap->tag, tag))
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS));
+      return soap->error = SOAP_SYNTAX_ERROR;
+    }
+  }
+#endif
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS));
+  soap->level--;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char *
+SOAP_FMAC2
+soap_attr_value(struct soap *soap, const char *name, int flag)
+{ register struct soap_attribute *tp;
+  if (*name == '-')
+    return SOAP_STR_EOS;
+  for (tp = soap->attributes; tp; tp = tp->next)
+  { if (tp->visible && !soap_match_tag(soap, tp->name, name))
+      break;
+  }
+  if (tp)
+  { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
+      soap->error = SOAP_PROHIBITED;
+    else
+      return tp->value;
+  }
+  else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
+    soap->error = SOAP_REQUIRED;
+  else
+    soap->error = SOAP_OK;
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
+{ register struct soap_attribute *tp;
+  if (*name == '-')
+    return SOAP_OK;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS));
+  for (tp = soap->attributes; tp; tp = tp->next)
+  { if (!strcmp(tp->name, name))
+      break;
+  }
+  if (!tp)
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
+    if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
+      return soap->error = SOAP_EOM;
+    tp->ns = NULL;
+#ifndef WITH_LEAN
+    if ((soap->mode & SOAP_XML_CANONICAL))
+    { struct soap_attribute **tpp = &soap->attributes;
+      const char *s = strchr(name, ':');
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name));
+      if (!strncmp(name, "xmlns", 5))
+      { for (; *tpp; tpp = &(*tpp)->next)
+          if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
+            break;
+      }
+      else if (!s)
+      { for (; *tpp; tpp = &(*tpp)->next)
+          if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
+            break;
+      }
+      else
+      { struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
+        if (np)
+          tp->ns = np->ns;
+        else
+        { struct soap_attribute *tq;
+          for (tq = soap->attributes; tq; tq = tq->next)
+          { if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name])
+            { tp->ns = tq->ns;
+              break;
+            }
+          }
+        }
+        for (; *tpp; tpp = &(*tpp)->next)
+        { int k;
+          if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
+            break;
+        }
+      }
+      tp->next = *tpp;
+      *tpp = tp;
+    }
+    else
+#endif
+    { tp->next = soap->attributes;
+      soap->attributes = tp;
+    }
+    strcpy((char*)tp->name, name);
+    tp->value = NULL;
+  }
+  else if (tp->visible)
+  { return SOAP_OK;
+  }
+  else if (value && tp->value && tp->size <= strlen(value))
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
+    SOAP_FREE(soap, tp->value);
+    tp->value = NULL;
+    tp->ns = NULL;
+  }
+  if (value)
+  { if (!tp->value)
+    { tp->size = strlen(value) + 1;
+      if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
+        return soap->error = SOAP_EOM;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value));
+    }
+    strcpy(tp->value, value);
+    if (!strncmp(tp->name, "xmlns:", 6))
+      tp->ns = tp->value;
+    tp->visible = 2;
+    tp->flag = (short)flag;
+#ifndef WITH_LEAN
+    if (!strcmp(name, "wsu:Id"))
+    { soap->event = SOAP_SEC_BEGIN;
+      strncpy(soap->id, value, sizeof(soap->id));
+      soap->id[sizeof(soap->id) - 1] = '\0';
+    }
+#endif
+  }
+  else
+    tp->visible = 1;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_attr(struct soap *soap)
+{ register struct soap_attribute *tp;
+#ifndef WITH_LEAN
+  if ((soap->mode & SOAP_XML_CANONICAL))
+  { while (soap->attributes)
+    { tp = soap->attributes->next;
+      if (soap->attributes->value)
+        SOAP_FREE(soap, soap->attributes->value);
+      SOAP_FREE(soap, soap->attributes);
+      soap->attributes = tp;
+    }
+  }
+  else
+#endif
+  { for (tp = soap->attributes; tp; tp = tp->next)
+      tp->visible = 0;
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static int
+soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
+{ register size_t i;
+  for (i = 0; i < n; i++)
+  { register soap_wchar c = soap_get(soap);
+    switch (c)
+    {
+    case SOAP_TT:
+      *s++ = '<';
+      soap_unget(soap, '/');
+      break;
+    case SOAP_LT:
+      *s++ = '<';
+      break;
+    case SOAP_GT:
+      if (d == ' ')
+      { soap_unget(soap, c);
+        *s = '\0';
+        return SOAP_OK;
+      }
+      *s++ = '>';
+      break;
+    case SOAP_QT:
+      if (c == d)
+      { *s = '\0';
+        return SOAP_OK;
+      }
+      *s++ = '"';
+      break;
+    case SOAP_AP:
+      if (c == d)
+      { *s = '\0';
+        return SOAP_OK;
+      }
+      *s++ = '\'';
+      break;
+    case '\t':
+    case '\n':
+    case '\r':
+    case ' ':
+    case '/':
+      if (d == ' ')
+      { soap_unget(soap, c);
+        *s = '\0';
+        return SOAP_OK;
+      }
+    default:
+      if ((int)c == EOF)
+      { *s = '\0';
+        return soap->error = SOAP_CHK_EOF;
+      }
+      *s++ = (char)c;
+    }
+  }
+  return soap->error = SOAP_EOM;
+}
+#endif
+
+/******************************************************************************/
+#ifdef WITH_FAST
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_store_lab(struct soap *soap, const char *s, size_t n)
+{ soap->labidx = 0;
+  return soap_append_lab(soap, s, n);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef WITH_FAST
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_append_lab(struct soap *soap, const char *s, size_t n)
+{ if (soap->labidx + n >= soap->lablen)
+  { register char *t = soap->labbuf;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen));
+    if (soap->lablen == 0)
+      soap->lablen = SOAP_LABLEN;
+    while (soap->labidx + n >= soap->lablen)
+      soap->lablen <<= 1;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen));
+    soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
+    if (!soap->labbuf)
+    { if (t)
+        SOAP_FREE(soap, t);
+      return soap->error = SOAP_EOM;
+    }
+    if (t)
+    { memcpy(soap->labbuf, t, soap->labidx);
+      SOAP_FREE(soap, t);
+    }
+  }
+  if (s)
+  { memcpy(soap->labbuf + soap->labidx, s, n);
+    soap->labidx += n;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_peek_element(struct soap *soap)
+{
+#ifdef WITH_DOM
+  register struct soap_dom_attribute **att = NULL;
+  register char *lead = NULL;
+#endif
+  register struct soap_attribute *tp, *tq = NULL;
+  register const char *t;
+  register char *s;
+  register soap_wchar c;
+  register int i;
+  if (soap->peeked)
+  { if (!*soap->tag)
+      return soap->error = SOAP_NO_TAG;
+    return SOAP_OK;
+  }
+  soap->peeked = 1;
+  soap->id[0] = '\0';
+  soap->href[0] = '\0';
+  soap->type[0] = '\0';
+  soap->arrayType[0] = '\0';
+  soap->arraySize[0] = '\0';
+  soap->arrayOffset[0] = '\0';
+  soap->other = 0;
+  soap->root = -1;
+  soap->position = 0;
+  soap->null = 0;
+  soap->mustUnderstand = 0;
+  /* UTF-8 BOM? */
+  c = soap_getchar(soap);
+  if (c == 0xEF && soap_get0(soap) == 0xBB)
+  { c = soap_get1(soap);
+    if ((c = soap_get1(soap)) == 0xBF)
+      soap->mode &= ~SOAP_ENC_LATIN;
+    else
+      soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */
+  }
+  else if ((c == 0xFE && soap_get0(soap) == 0xFF)  /* UTF-16 BE */
+        || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
+    return soap->error = SOAP_UTF_ERROR;
+  else
+    soap_unget(soap, c);
+  c = soap_get(soap);
+#ifdef WITH_DOM
+  /* whitespace leading to tag is not insignificant for DOM */
+  if (soap_blank(c))
+  { soap->labidx = 0;
+    do
+    { if (soap_append_lab(soap, NULL, 0))
+        return soap->error;
+      s = soap->labbuf + soap->labidx;
+      i = soap->lablen - soap->labidx;
+      soap->labidx = soap->lablen;
+      while (soap_blank(c) && i--)
+      { *s++ = c;
+        c = soap_get(soap);
+      }
+    }
+    while (soap_blank(c));
+    *s = '\0';
+    lead = soap->labbuf;
+  }
+#else
+  /* skip space */
+  while (soap_blank(c))
+    c = soap_get(soap);
+#endif
+  if (c != SOAP_LT)
+  { *soap->tag = '\0';
+    if ((int)c == EOF)
+      return soap->error = SOAP_CHK_EOF;
+    soap_unget(soap, c);
+#ifdef WITH_DOM
+    /* whitespace leading to end tag is significant for DOM */
+    if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+    { if (lead && *lead)
+        soap->dom->tail = soap_strdup(soap, lead);
+      else
+        soap->dom->tail = (char*)SOAP_STR_EOS;
+    }
+#endif
+    return soap->error = SOAP_NO_TAG;
+  }
+  do c = soap_get1(soap);
+  while (soap_blank(c));
+  s = soap->tag;
+  i = sizeof(soap->tag);
+  while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
+  { if (--i > 0)
+      *s++ = (char)c;
+    c = soap_get1(soap);
+  }
+  *s = '\0';
+  while (soap_blank(c))
+    c = soap_get1(soap);
+#ifdef WITH_DOM
+  if (soap->mode & SOAP_XML_DOM)
+  { register struct soap_dom_element *elt;
+    elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
+    if (!elt)
+      return soap->error;
+    elt->next = NULL;
+    elt->nstr = NULL;
+    elt->name = soap_strdup(soap, soap->tag);
+    elt->prnt = soap->dom;
+    elt->elts = NULL;
+    elt->atts = NULL;
+    elt->data = NULL;
+    elt->wide = NULL;
+    elt->type = 0;
+    elt->node = NULL;
+    elt->head = soap_strdup(soap, lead);
+    elt->tail = NULL;
+    elt->soap = soap;
+    if (soap->dom)
+    { struct soap_dom_element *p = soap->dom->elts;
+      if (p)
+      { while (p->next)
+          p = p->next;
+        p->next = elt;
+      }
+      else
+        soap->dom->elts = elt;
+    }
+    soap->dom = elt;
+    att = &elt->atts;
+  }
+#endif
+  soap_pop_namespace(soap);
+  for (tp = soap->attributes; tp; tp = tp->next)
+    tp->visible = 0;
+  while ((int)c != EOF && c != '>' && c != '/')
+  { s = soap->tmpbuf;
+    i = sizeof(soap->tmpbuf);
+    while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
+    { if (--i > 0)
+        *s++ = (char)c;
+      c = soap_get1(soap);
+    }
+    *s = '\0';
+    if (i == sizeof(soap->tmpbuf))
+      return soap->error = SOAP_SYNTAX_ERROR;
+#ifdef WITH_DOM
+    /* add attribute name to dom */
+    if (att)
+    { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
+       if (!*att)
+         return soap->error;
+       (*att)->next = NULL;
+       (*att)->nstr = NULL;
+       (*att)->name = soap_strdup(soap, soap->tmpbuf);
+       (*att)->data = NULL;
+       (*att)->wide = NULL;
+       (*att)->soap = soap;
+    }
+#endif
+    if (!strncmp(soap->tmpbuf, "xmlns", 5))
+    { if (soap->tmpbuf[5] == ':')
+        t = soap->tmpbuf + 6;
+      else if (soap->tmpbuf[5])
+        t = NULL;
+      else
+        t = SOAP_STR_EOS;
+    }
+    else
+      t = NULL;
+    tq = NULL;
+    for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
+    { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
+        break;
+    }
+    if (!tp)
+    { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
+      if (!tp)
+        return soap->error = SOAP_EOM;
+      strcpy((char*)tp->name, soap->tmpbuf);
+      tp->value = NULL;
+      tp->size = 0;
+      tp->ns = NULL;
+      /* if attribute name is qualified, append it to the end of the list */
+      if (tq && strchr(soap->tmpbuf, ':'))
+      { tq->next = tp;
+        tp->next = NULL;
+      }
+      else
+      { tp->next = soap->attributes;
+        soap->attributes = tp;
+      }
+    }
+    while (soap_blank(c))
+      c = soap_get1(soap);
+    if (c == '=')
+    { do c = soap_getutf8(soap);
+      while (soap_blank(c));
+      if (c != SOAP_QT && c != SOAP_AP)
+      { soap_unget(soap, c);
+        c = ' '; /* blank delimiter */
+      }
+      if (soap_getattrval(soap, tp->value, tp->size, c))
+      {
+#ifdef WITH_FAST
+        if (soap->error != SOAP_EOM)
+          return soap->error;
+        soap->error = SOAP_OK;
+        if (soap_store_lab(soap, tp->value, tp->size))
+          return soap->error;
+        if (tp->value)
+          SOAP_FREE(soap, tp->value);
+        tp->value = NULL;
+        for (;;)
+        { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
+          { if (soap->error != SOAP_EOM)
+              return soap->error;
+            soap->error = SOAP_OK;
+            soap->labidx = soap->lablen;
+            if (soap_append_lab(soap, NULL, 0))
+              return soap->error;
+          }
+          else
+            break;
+        }
+        if (soap->labidx)
+          tp->size = soap->lablen;
+        else
+        { tp->size = strlen(soap->labbuf) + 1;
+          if (tp->size < SOAP_LABLEN)
+            tp->size = SOAP_LABLEN;
+        }
+        if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
+          return soap->error = SOAP_EOM;
+        strcpy(tp->value, soap->labbuf);
+#else
+        size_t n;
+        if (soap->error != SOAP_EOM)
+          return soap->error;
+        soap->error = SOAP_OK;
+        if (soap_new_block(soap) == NULL)
+          return soap->error;
+        for (;;)
+        { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN)))
+            return soap->error;
+          if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
+          { if (soap->error != SOAP_EOM)
+              return soap->error;
+            soap->error = SOAP_OK;
+          }
+          else
+            break;
+        }
+        n = tp->size + soap->blist->size;
+        if (!(s = (char*)SOAP_MALLOC(soap, n)))
+          return soap->error = SOAP_EOM;
+        if (tp->value)
+        { memcpy(s, tp->value, tp->size);
+          SOAP_FREE(soap, tp->value);
+        }
+        soap_save_block(soap, NULL, s + tp->size, 0);
+        tp->value = s;
+        tp->size = n;
+#endif
+      }
+      do c = soap_get1(soap);
+      while (soap_blank(c));
+      tp->visible = 2; /* seen this attribute w/ value */
+#ifdef WITH_DOM
+      if (att)
+        (*att)->data = soap_strdup(soap, tp->value);
+#endif
+    }
+    else
+      tp->visible = 1; /* seen this attribute w/o value */
+#ifdef WITH_DOM
+    if (att)
+      att = &(*att)->next;
+#endif
+    if (t && tp->value)
+    { if (soap_push_namespace(soap, t, tp->value) == NULL)
+        return soap->error;
+    }
+  }
+#ifdef WITH_DOM
+  if (att)
+  { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
+    for (att = &soap->dom->atts; *att; att = &(*att)->next)
+      (*att)->nstr = soap_current_namespace(soap, (*att)->name);
+  }
+#endif
+  if ((int)c == EOF)
+    return soap->error = SOAP_CHK_EOF;
+  if (!(soap->body = (c != '/')))
+    do c = soap_get1(soap);
+    while (soap_blank(c));
+#ifdef WITH_DOM
+  if (soap->mode & SOAP_XML_DOM)
+  { if (!soap->body && soap->dom->prnt)
+      soap->dom = soap->dom->prnt;
+  }
+#endif
+  for (tp = soap->attributes; tp; tp = tp->next)
+  { if (tp->visible && tp->value)
+    {
+#ifndef WITH_NOIDREF
+      if (!strcmp(tp->name, "id"))
+      { if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE))
+         || (soap->mode & SOAP_XML_GRAPH))
+        { *soap->id = '#';
+          strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
+          soap->id[sizeof(soap->id) - 1] = '\0';
+        }
+      }
+      else if (!strcmp(tp->name, "href"))
+      { if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE))
+         || (soap->mode & SOAP_XML_GRAPH)
+         || (soap->mode & SOAP_ENC_MTOM)
+         || (soap->mode & SOAP_ENC_DIME))
+        { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
+          soap->href[sizeof(soap->href) - 1] = '\0';
+        }
+      }
+      else if (!strcmp(tp->name, "ref"))
+      { if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE))
+         || (soap->mode & SOAP_XML_GRAPH))
+        { *soap->href = '#';
+          strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
+          soap->href[sizeof(soap->href) - 1] = '\0';
+        }
+      }
+      else
+#endif
+      if (!soap_match_tag(soap, tp->name, "xsi:type"))
+      { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
+        soap->type[sizeof(soap->type) - 1] = '\0';
+      }
+      else if ((!soap_match_tag(soap, tp->name, "xsi:null")
+             || !soap_match_tag(soap, tp->name, "xsi:nil"))
+            && (!strcmp(tp->value, "1")
+             || !strcmp(tp->value, "true")))
+      { soap->null = 1;
+      }
+      else if (soap->version == 1)
+      { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
+        { s = soap_strrchr(tp->value, '[');
+          if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
+          { strncpy(soap->arrayType, tp->value, s - tp->value);
+            soap->arrayType[s - tp->value] = '\0';
+            strncpy(soap->arraySize, s, sizeof(soap->arraySize));
+          }
+          else
+            strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType));
+          soap->arraySize[sizeof(soap->arraySize) - 1] = '\0';
+          soap->arrayType[sizeof(soap->arrayType) - 1] = '\0';
+        }
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
+          strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
+          soap->position = soap_getposition(tp->value, soap->positions);
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
+          soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
+              && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
+          soap->mustUnderstand = 1;
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
+        { if ((!soap->actor || strcmp(soap->actor, tp->value))
+           && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
+            soap->other = 1;
+        }
+      }
+      else if (soap->version == 2)
+      {
+#ifndef WITH_NOIDREF
+        if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id"))
+        { *soap->id = '#';
+          strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
+          soap->id[sizeof(soap->id) - 1] = '\0';
+        }
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
+        { *soap->href = '#';
+          strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
+          soap->href[sizeof(soap->href) - 1] = '\0';
+        }
+        else
+#endif
+        if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
+          strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
+          strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
+              && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
+          soap->mustUnderstand = 1;
+        else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
+        { if ((!soap->actor || strcmp(soap->actor, tp->value))
+           && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
+            soap->other = 1;
+        }
+      }
+      else
+      { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
+          soap->mustUnderstand = 1;
+      }
+    }
+  }
+#ifdef WITH_DOM
+  if (soap->feltbegin)
+    return soap->error = soap->feltbegin(soap, soap->tag);
+#endif
+  return soap->error = SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_retry(struct soap *soap)
+{ soap->error = SOAP_OK;
+  soap_revert(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_revert(struct soap *soap)
+{ if (!soap->peeked)
+  { soap->peeked = 1;
+    if (soap->body)
+      soap->level--;
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level));
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_string_out(struct soap *soap, const char *s, int flag)
+{ register const char *t;
+  register soap_wchar c;
+  register soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { soap->dom->data = soap_strdup(soap, s);
+    return SOAP_OK;
+  }
+#endif
+  if (flag == 2 || soap->mode & SOAP_C_UTFSTRING)
+    mask = 0;
+  t = s;
+  while ((c = *t++))
+  { switch (c)
+    {
+    case 0x09:
+      if (flag)
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
+          return soap->error;
+        s = t;
+      }
+      break;
+    case 0x0A:
+      if (flag || !(soap->mode & SOAP_XML_CANONICAL))
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
+          return soap->error;
+        s = t;
+      }
+      break;
+    case 0x0D:
+      if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xD;", 5))
+        return soap->error;
+      s = t;
+      break;
+    case '&':
+      if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
+        return soap->error;
+      s = t;
+      break;
+    case '<':
+      if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
+        return soap->error;
+      s = t;
+      break;
+    case '>':
+      if (!flag)
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
+          return soap->error;
+        s = t;
+      }
+      break;
+    case '"':
+      if (flag)
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
+          return soap->error;
+        s = t;
+      }
+      break;
+    default:
+#ifndef WITH_LEANER
+#ifdef HAVE_MBTOWC
+      if (soap->mode & SOAP_C_MBSTRING)
+      { wchar_t wc;
+        register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
+        if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80))
+        { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc))
+            return soap->error;
+          s = t += m - 1;
+          continue;
+        }
+      }
+#endif
+#endif
+#ifndef WITH_NOSTRINGTOUTF8
+      if ((c & mask) || !(c & 0xFFFFFFE0UL))
+      { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
+          return soap->error;
+        s = t;
+      }
+#endif
+    }
+  }
+  return soap_send_raw(soap, s, t - s - 1);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
+{ register char *s;
+  char *t = NULL;
+  register size_t i;
+  register long l = 0;
+  register int n = 0, f = 0, m = 0;
+  register soap_wchar c;
+#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
+  char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
+#else
+  char buf[8];
+#endif
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
+  if (soap->peeked && *soap->tag)
+  {
+#ifndef WITH_LEAN
+    struct soap_attribute *tp;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
+    t = soap->tmpbuf;
+    *t = '<';
+    strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
+    t[sizeof(soap->tmpbuf) - 1] = '\0';
+    t += strlen(t);
+    for (tp = soap->attributes; tp; tp = tp->next)
+    { if (tp->visible)
+      { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
+          break;
+        *t++ = ' ';
+        strcpy(t, tp->name);
+        t += strlen(t);
+        if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
+          break; /* too many or large attribute values */
+        if (tp->value)
+        { *t++ = '=';
+          *t++ = '"';
+          strcpy(t, tp->value);
+          t += strlen(t);
+          *t++ = '"';
+        }
+      }
+    }
+    if (!soap->body)
+      *t++ = '/';
+    *t++ = '>';
+    *t = '\0';
+    t = soap->tmpbuf;
+    m = (int)strlen(soap->tmpbuf);
+#endif
+    if (soap->body)
+      n = 1;
+    f = 1;
+    soap->peeked = 0;
+  }
+#ifdef WITH_CDATA
+  if (!flag)
+  { register int state = 0;
+#ifdef WITH_FAST
+    soap->labidx = 0;			/* use look-aside buffer */
+#else
+    if (soap_new_block(soap) == NULL)
+      return NULL;
+#endif
+    for (;;)
+    {
+#ifdef WITH_FAST
+      register size_t k;
+      if (soap_append_lab(soap, NULL, 0))	/* allocate more space in look-aside buffer if necessary */
+        return NULL;
+      s = soap->labbuf + soap->labidx;	/* space to populate */
+      k = soap->lablen - soap->labidx;	/* number of bytes available */
+      soap->labidx = soap->lablen;	/* claim this space */
+#else
+      register size_t k = SOAP_BLKLEN;
+      if (!(s = (char*)soap_push_block(soap, NULL, k)))
+        return NULL;
+#endif
+      for (i = 0; i < k; i++)
+      { if (m > 0)
+        { *s++ = *t++;	/* copy multibyte characters */
+          m--;
+          continue;
+        }
+        c = soap_getchar(soap);
+        if ((int)c == EOF)
+          goto end;
+        if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN))
+        { if ((c & 0x7FFFFFFF) >= 0x80)
+          { soap_unget(soap, c);
+            c = soap_getutf8(soap);
+          }
+          if ((c & 0x7FFFFFFF) >= 0x80 && (!flag || (soap->mode & SOAP_C_UTFSTRING)))
+          { c &= 0x7FFFFFFF;
+            t = buf;
+            if (c < 0x0800)
+              *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
+            else
+            { if (c < 0x010000)
+                *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
+              else
+              { if (c < 0x200000)
+                  *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
+                else
+                { if (c < 0x04000000)
+                    *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
+                  else
+                  { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
+                    *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
+                  }
+                  *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
+                }
+                *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
+              }
+              *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
+            }
+            *t++ = (char)(0x80 | (c & 0x3F));
+            m = (int)(t - buf) - 1;
+            t = buf;
+            *s++ = *t++;
+            continue;
+          }
+        }
+        switch (state)
+        { case 1:
+            if (c == ']')
+              state = 4;
+            *s++ = (char)c;
+            continue;
+          case 2:
+            if (c == '-')
+              state = 6;
+            *s++ = (char)c;
+            continue;
+          case 3:
+            if (c == '?')
+              state = 8;
+            *s++ = (char)c;
+            continue;
+          /* CDATA */
+          case 4:
+            if (c == ']')
+              state = 5;
+            else
+              state = 1;
+            *s++ = (char)c;
+            continue;
+          case 5:
+            if (c == '>')
+              state = 0;
+	    else if (c != ']')
+              state = 1;
+            *s++ = (char)c;
+            continue;
+          /* comment */
+          case 6:
+            if (c == '-')
+              state = 7;
+            else
+              state = 2;
+            *s++ = (char)c;
+            continue;
+          case 7:
+            if (c == '>')
+              state = 0;
+            else if (c != '-')
+              state = 2;
+            *s++ = (char)c;
+            continue;
+          /* PI */
+          case 8:
+            if (c == '>')
+              state = 0;
+            else if (c != '?')
+              state = 3;
+            *s++ = (char)c;
+            continue;
+        }
+        switch (c)
+        {
+        case SOAP_TT:
+          if (n == 0)
+            goto end;
+          n--;
+          *s++ = '<';
+          t = (char*)"/";
+          m = 1;
+          break;
+        case SOAP_LT:
+          if (f && n == 0)
+            goto end;
+          n++;
+          *s++ = '<';
+          break;
+        case SOAP_GT:
+          *s++ = '>';
+          break;
+        case SOAP_QT:
+          *s++ = '"';
+          break;
+        case SOAP_AP:
+          *s++ = '\'';
+          break;
+        case '/':
+          if (n > 0)
+          { c = soap_getchar(soap);
+            if (c == '>')
+              n--;
+            soap_unget(soap, c);
+          }
+          *s++ = '/';
+          break;
+        case '<':
+          c = soap_getchar(soap);
+          if (c == '/')
+          { if (n == 0)
+            { c = SOAP_TT;
+              goto end;
+            }
+            n--;
+          }
+          else if (c == '!')
+          { c = soap_getchar(soap);
+            if (c == '[')
+            { do c = soap_getchar(soap);
+              while ((int)c != EOF && c != '[');
+              if ((int)c == EOF)
+                 goto end;
+              t = (char*)"![CDATA[";
+              m = 8;
+              state = 1;
+            }
+            else if (c == '-')
+            { if ((c = soap_getchar(soap)) == '-')
+                state = 2;
+              t = (char*)"!-";
+              m = 2;
+              soap_unget(soap, c);
+            }
+            else
+            { t = (char*)"!";
+              m = 1;
+              soap_unget(soap, c);
+            }
+            *s++ = '<';
+            break;
+          }
+          else if (c == '?')
+            state = 3;
+          else if (f && n == 0)
+          { soap_revget1(soap);
+            c = '<';
+            goto end;
+          }
+          else
+            n++;
+          soap_unget(soap, c);
+          *s++ = '<';
+          break;
+        case '>':
+          *s++ = '>';
+          break;
+        case '"':
+          *s++ = '"';
+          break;
+        default:
+#ifndef WITH_LEANER
+#ifdef HAVE_WCTOMB
+          if (soap->mode & SOAP_C_MBSTRING)
+          { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
+            if (m >= 1 && m <= (int)MB_CUR_MAX)
+            { t = buf;
+              *s++ = *t++;
+              m--;
+            }
+            else
+            { *s++ = SOAP_UNKNOWN_CHAR;
+              m = 0;
+            }
+          }
+          else
+#endif
+#endif
+            *s++ = (char)(c & 0xFF);
+        }
+        l++;
+        if (maxlen >= 0 && l > maxlen)
+        { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
+          soap->error = SOAP_LENGTH;
+          return NULL;
+        }
+      }
+    }
+  }
+#endif
+#ifdef WITH_FAST
+  soap->labidx = 0;			/* use look-aside buffer */
+#else
+  if (soap_new_block(soap) == NULL)
+    return NULL;
+#endif
+  for (;;)
+  {
+#ifdef WITH_FAST
+    register size_t k;
+    if (soap_append_lab(soap, NULL, 0))	/* allocate more space in look-aside buffer if necessary */
+      return NULL;
+    s = soap->labbuf + soap->labidx;	/* space to populate */
+    k = soap->lablen - soap->labidx;	/* number of bytes available */
+    soap->labidx = soap->lablen;	/* claim this space */
+#else
+    register size_t k = SOAP_BLKLEN;
+    if (!(s = (char*)soap_push_block(soap, NULL, k)))
+      return NULL;
+#endif
+    for (i = 0; i < k; i++)
+    { if (m > 0)
+      { *s++ = *t++;	/* copy multibyte characters */
+        m--;
+        continue;
+      }
+#ifndef WITH_CDATA
+      if (!flag)
+        c = soap_getchar(soap);
+      else
+#endif
+      if ((soap->mode & SOAP_C_UTFSTRING))
+      { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
+        { c &= 0x7FFFFFFF;
+          t = buf;
+          if (c < 0x0800)
+            *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
+          else
+          { if (c < 0x010000)
+              *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
+            else
+            { if (c < 0x200000)
+                *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
+              else
+              { if (c < 0x04000000)
+                  *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
+                else
+                { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
+                  *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
+                }
+                *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
+              }
+              *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
+            }
+            *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
+          }
+          *t++ = (char)(0x80 | (c & 0x3F));
+          m = (int)(t - buf) - 1;
+          t = buf;
+          *s++ = *t++;
+          continue;
+        }
+      }
+      else
+        c = soap_getutf8(soap);
+      switch (c)
+      {
+      case SOAP_TT:
+        if (n == 0)
+          goto end;
+        n--;
+        *s++ = '<';
+        t = (char*)"/";
+        m = 1;
+        break;
+      case SOAP_LT:
+        if (f && n == 0)
+          goto end;
+        n++;
+        *s++ = '<';
+        break;
+      case SOAP_GT:
+        *s++ = '>';
+        break;
+      case SOAP_QT:
+        *s++ = '"';
+        break;
+      case SOAP_AP:
+        *s++ = '\'';
+        break;
+      case '/':
+        if (n > 0)
+        { if (!flag)
+	  { c = soap_getchar(soap);
+            if (c == '>')
+              n--;
+	  }
+	  else
+	  { c = soap_get(soap);
+            if (c == SOAP_GT)
+              n--;
+	  }
+          soap_unget(soap, c);
+        }
+        *s++ = '/';
+        break;
+      case (soap_wchar)('<' | 0x80000000):
+        if (flag)
+          *s++ = '<';
+        else
+        { *s++ = '&';
+          t = (char*)"lt;";
+          m = 3;
+        }
+        break;
+      case (soap_wchar)('>' | 0x80000000):
+        if (flag)
+          *s++ = '>';
+        else
+        { *s++ = '&';
+          t = (char*)"gt;";
+          m = 3;
+        }
+        break;
+      case (soap_wchar)('&' | 0x80000000):
+        if (flag)
+          *s++ = '&';
+        else
+        { *s++ = '&';
+          t = (char*)"amp;";
+          m = 4;
+        }
+        break;
+      case (soap_wchar)('"' | 0x80000000):
+        if (flag)
+          *s++ = '"';
+        else
+        { *s++ = '&';
+          t = (char*)"quot;";
+          m = 5;
+        }
+        break;
+      case (soap_wchar)('\'' | 0x80000000):
+        if (flag)
+          *s++ = '\'';
+        else
+        { *s++ = '&';
+          t = (char*)"apos;";
+          m = 5;
+        }
+        break;
+      default:
+        if ((int)c == EOF)
+          goto end;
+#ifndef WITH_CDATA
+        if (c == '<' && !flag)
+        {   if (f && n == 0)
+              goto end;
+            c = soap_getchar(soap);
+            soap_unget(soap, c);
+            if (c == '/')
+            { c = SOAP_TT;
+	      if (n == 0)
+                goto end;
+              n--;
+            }
+            else
+              n++;
+            *s++ = '<';
+            break;
+        }
+        else
+#endif
+#ifndef WITH_LEANER
+#ifdef HAVE_WCTOMB
+        if (soap->mode & SOAP_C_MBSTRING)
+        { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
+          if (m >= 1 && m <= (int)MB_CUR_MAX)
+          { t = buf;
+            *s++ = *t++;
+            m--;
+          }
+          else
+          { *s++ = SOAP_UNKNOWN_CHAR;
+            m = 0;
+          }
+        }
+        else
+#endif
+#endif
+          *s++ = (char)(c & 0xFF);
+      }
+      l++;
+      if (maxlen >= 0 && l > maxlen)
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
+        soap->error = SOAP_LENGTH;
+        return NULL;
+      }
+    }
+  }
+end:
+  soap_unget(soap, c);
+  *s = '\0';
+#ifdef WITH_FAST
+  t = soap_strdup(soap, soap->labbuf);
+#else
+  soap_size_block(soap, NULL, i + 1);
+  t = soap_save_block(soap, NULL, 0);
+#endif
+  if (l < minlen)
+  { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
+    soap->error = SOAP_LENGTH;
+    return NULL;
+  }
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { if (flag == 3)
+      soap->dom->tail = t;
+    else
+      soap->dom->data = t;
+  }
+#endif
+  if (flag == 2)
+    if (soap_s2QName(soap, t, &t, minlen, maxlen))
+      return NULL;
+  return t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
+{ const char *t;
+  char tmp;
+  register soap_wchar c;
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+  { wchar_t *r = (wchar_t*)s;
+    int n = 1;
+    while (*r++)
+      n++;
+    soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
+    while (n--)
+      *r++ = *s++;
+    return SOAP_OK;
+  }
+#endif
+  while ((c = *s++))
+  { switch (c)
+    {
+    case 0x09:
+      if (flag)
+        t = "&#x9;";
+      else
+        t = "\t";
+      break;
+    case 0x0A:
+      if (flag || !(soap->mode & SOAP_XML_CANONICAL))
+        t = "&#xA;";
+      else
+        t = "\n";
+      break;
+    case 0x0D:
+      t = "&#xD;";
+      break;
+    case '&':
+      t = "&amp;";
+      break;
+    case '<':
+      t = "&lt;";
+      break;
+    case '>':
+      if (flag)
+        t = ">";
+      else
+        t = "&gt;";
+      break;
+    case '"':
+      if (flag)
+        t = "&quot;";
+      else
+        t = "\"";
+      break;
+    default:
+      if (c >= 0x20 && c < 0x80)
+      { tmp = (char)c;
+        if (soap_send_raw(soap, &tmp, 1))
+          return soap->error;
+      }
+      else
+      { /* check for UTF16 encoding when wchar_t is too small to hold UCS */
+        if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
+        { register soap_wchar d = *s++;
+          if ((d & 0xFC00) == 0xDC00)
+            c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
+          else
+            c = 0xFFFD; /* Malformed */
+        }
+        if (soap_pututf8(soap, (unsigned long)c))
+          return soap->error;
+      }
+      continue;
+    }
+    if (soap_send(soap, t))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_2
+SOAP_FMAC1
+wchar_t *
+SOAP_FMAC2
+soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
+{ wchar_t *s;
+  register int i, n = 0, f = 0;
+  register long l = 0;
+  register soap_wchar c;
+  char *t = NULL;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
+  if (soap->peeked)
+  { if (*soap->tag)
+    {
+#ifndef WITH_LEAN
+      struct soap_attribute *tp;
+      t = soap->tmpbuf;
+      *t = '<';
+      strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
+      t[sizeof(soap->tmpbuf) - 1] = '\0';
+      t += strlen(t);
+      for (tp = soap->attributes; tp; tp = tp->next)
+      { if (tp->visible)
+        { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
+            break;
+          *t++ = ' ';
+          strcpy(t, tp->name);
+          t += strlen(t);
+          if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
+            break;
+          if (tp->value)
+          { *t++ = '=';
+            *t++ = '"';
+            strcpy(t, tp->value);
+            t += strlen(t);
+            *t++ = '"';
+          }
+        }
+      }
+      if (!soap->body)
+        *t++ = '/';
+      *t++ = '>';
+      *t = '\0';
+      t = soap->tmpbuf;
+#endif
+      if (soap->body)
+        n = 1;
+      f = 1;
+      soap->peeked = 0;
+    }
+  }
+  if (soap_new_block(soap) == NULL)
+    return NULL;
+  for (;;)
+  { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN)))
+      return NULL;
+    for (i = 0; i < SOAP_BLKLEN; i++)
+    { if (t)
+      { *s++ = (wchar_t)*t++;
+        if (!*t)
+          t = NULL;
+        continue;
+      }
+      c = soap_getutf8(soap);
+      switch (c)
+      {
+      case SOAP_TT:
+        if (n == 0)
+          goto end;
+        n--;
+        *s++ = '<';
+        soap_unget(soap, '/');
+        break;
+      case SOAP_LT:
+        if (f && n == 0)
+          goto end;
+        n++;
+        *s++ = '<';
+        break;
+      case SOAP_GT:
+        *s++ = '>';
+        break;
+      case SOAP_QT:
+        *s++ = '"';
+        break;
+      case SOAP_AP:
+        *s++ = '\'';
+        break;
+      case '/':
+        if (n > 0)
+        { c = soap_getutf8(soap);
+          if (c == SOAP_GT)
+            n--;
+          soap_unget(soap, c);
+        }
+        *s++ = '/';
+        break;
+      case '<':
+        if (flag)
+          *s++ = (soap_wchar)'<';
+        else
+        { *s++ = (soap_wchar)'&';
+          t = (char*)"lt;";
+        }
+        break;
+      case '>':
+        if (flag)
+          *s++ = (soap_wchar)'>';
+        else
+        { *s++ = (soap_wchar)'&';
+          t = (char*)"gt;";
+        }
+        break;
+      case '"':
+        if (flag)
+          *s++ = (soap_wchar)'"';
+        else
+        { *s++ = (soap_wchar)'&';
+          t = (char*)"quot;";
+        }
+        break;
+      default:
+        if ((int)c == EOF)
+          goto end;
+        /* use UTF16 encoding when wchar_t is too small to hold UCS */
+        if (sizeof(wchar_t) < 4 && c > 0xFFFF)
+        { register soap_wchar c1, c2;
+          c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
+          c2 = 0xDC00 + (c & 0x3FF);
+          c = c1;
+          soap_unget(soap, c2);
+        }
+        *s++ = (wchar_t)c & 0x7FFFFFFF;
+      }
+      l++;
+      if (maxlen >= 0 && l > maxlen)
+      { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
+        soap->error = SOAP_LENGTH;
+        return NULL;
+      }
+    }
+  }
+end:
+  soap_unget(soap, c);
+  *s = '\0';
+  soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
+  if (l < minlen)
+  { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
+    soap->error = SOAP_LENGTH;
+    return NULL;
+  }
+  s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+    soap->dom->wide = s;
+#endif
+  return s;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_int2s(struct soap *soap, int n)
+{ return soap_long2s(soap, (long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2int(struct soap *soap, const char *s, int *p)
+{ if (s)
+  { long n;
+    char *r;
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+    soap_reset_errno;
+#endif
+#endif
+    n = soap_strtol(s, &r, 10);
+    if (s == r || *r
+#ifndef WITH_LEAN
+     || n != (int)n
+#endif
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+     || soap_errno == SOAP_ERANGE
+#endif
+#endif
+    )
+      soap->error = SOAP_TYPE;
+    *p = (int)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int *
+SOAP_FMAC2
+soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
+  else if (p)
+  { if (soap_s2int(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_long2s(struct soap *soap, long n)
+{
+#ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%ld", n);
+#else
+  sprintf(soap->tmpbuf, "%ld", n);
+#endif
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2long(struct soap *soap, const char *s, long *p)
+{ if (s)
+  { char *r;
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+    soap_reset_errno;
+#endif
+#endif
+    *p = soap_strtol(s, &r, 10);
+    if (s == r || *r
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+     || soap_errno == SOAP_ERANGE
+#endif
+#endif
+    )
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+long *
+SOAP_FMAC2
+soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
+  else if (p)
+  { if (soap_s2long(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_LONG642s(struct soap *soap, LONG64 n)
+{
+#ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_LONG_FORMAT, n);
+#else
+  sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
+#endif
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
+{ if (s)
+  {
+#ifdef HAVE_STRTOLL
+    char *r;
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+    soap_reset_errno;
+#endif
+#endif
+    *p = soap_strtoll(s, &r, 10);
+    if (s == r || *r
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+       || soap_errno == SOAP_ERANGE
+#endif
+#endif
+      )
+#else
+# ifdef HAVE_SSCANF
+    if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
+# endif
+#endif
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+LONG64 *
+SOAP_FMAC2
+soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":integer")
+   && soap_match_tag(soap, soap->type, ":positiveInteger")
+   && soap_match_tag(soap, soap->type, ":negativeInteger")
+   && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
+   && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
+   && soap_match_tag(soap, soap->type, ":long")
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
+  else if (p)
+  { if (soap_s2LONG64(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_byte2s(struct soap *soap, char n)
+{ return soap_long2s(soap, (long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2byte(struct soap *soap, const char *s, char *p)
+{ if (s)
+  { long n;
+    char *r;
+    n = soap_strtol(s, &r, 10);
+    if (s == r || *r || n < -128 || n > 127)
+      soap->error = SOAP_TYPE;
+    *p = (char)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
+  else if (p)
+  { if (soap_s2byte(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_short2s(struct soap *soap, short n)
+{ return soap_long2s(soap, (long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2short(struct soap *soap, const char *s, short *p)
+{ if (s)
+  { long n;
+    char *r;
+    n = soap_strtol(s, &r, 10);
+    if (s == r || *r || n < -32768 || n > 32767)
+      soap->error = SOAP_TYPE;
+    *p = (short)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+short *
+SOAP_FMAC2
+soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
+  else if (p)
+  { if (soap_s2short(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_float2s(struct soap *soap, float n)
+{ char *s;
+  if (soap_isnan((double)n))
+    return "NaN";
+  if (soap_ispinff(n))
+    return "INF";
+  if (soap_isninff(n))
+    return "-INF";
+#if defined(HAVE_SPRINTF_L)
+# ifdef WIN32
+  _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, soap->c_locale, n);
+# else
+  sprintf_l(soap->tmpbuf, soap->c_locale, soap->float_format, n);
+# endif
+#else
+# ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->float_format, n);
+# else
+  sprintf(soap->tmpbuf, soap->float_format, n);
+# endif
+  s = strchr(soap->tmpbuf, ',');	/* convert decimal comma to DP */
+  if (s)
+    *s = '.';
+#endif
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_float2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2float(struct soap *soap, const char *s, float *p)
+{ if (s)
+  { if (!*s)
+      return soap->error = SOAP_TYPE;
+    if (!soap_tag_cmp(s, "INF"))
+      *p = FLT_PINFTY;
+    else if (!soap_tag_cmp(s, "+INF"))
+      *p = FLT_PINFTY;
+    else if (!soap_tag_cmp(s, "-INF"))
+      *p = FLT_NINFTY;
+    else if (!soap_tag_cmp(s, "NaN"))
+      *p = FLT_NAN;
+    else
+    {
+/* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
+#if defined(HAVE_STRTOD_L)
+      char *r;
+# ifdef WIN32
+      *p = (float)_strtod_l(s, &r, soap->c_locale);
+# else
+      *p = (float)strtod_l(s, &r, soap->c_locale);
+# endif
+      if (*r)
+#elif defined(HAVE_STRTOD)
+      char *r;
+      *p = (float)strtod(s, &r);
+      if (*r)
+#elif defined(HAVE_STRTOF_L)
+      char *r;
+      *p = strtof_l((char*)s, &r, soap->c_locale);
+      if (*r)
+#elif defined(HAVE_STRTOF)
+      char *r;
+      *p = strtof((char*)s, &r);
+      if (*r)
+#endif
+      {
+#if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
+        if (sscanf_l(s, soap->c_locale, "%f", p) != 1)
+          soap->error = SOAP_TYPE;
+#elif defined(HAVE_SSCANF)
+        if (sscanf(s, "%f", p) != 1)
+          soap->error = SOAP_TYPE;
+#else
+        soap->error = SOAP_TYPE;
+#endif
+      }
+    }
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+static int soap_isnumeric(struct soap *soap, const char *type)
+{ if (soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":float")
+   && soap_match_tag(soap, soap->type, ":double")
+   && soap_match_tag(soap, soap->type, ":decimal")
+   && soap_match_tag(soap, soap->type, ":integer")
+   && soap_match_tag(soap, soap->type, ":positiveInteger")
+   && soap_match_tag(soap, soap->type, ":negativeInteger")
+   && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
+   && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
+   && soap_match_tag(soap, soap->type, ":long")
+   && soap_match_tag(soap, soap->type, ":int")
+   && soap_match_tag(soap, soap->type, ":short")
+   && soap_match_tag(soap, soap->type, ":byte")
+   && soap_match_tag(soap, soap->type, ":unsignedLong")
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return SOAP_ERR;
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+float *
+SOAP_FMAC2
+soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type != '\0' && soap_isnumeric(soap, type))
+    return NULL;
+#endif
+  p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
+  else if (p)
+  { if (soap_s2float(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_double2s(struct soap *soap, double n)
+{ char *s;
+  if (soap_isnan(n))
+    return "NaN";
+  if (soap_ispinfd(n))
+    return "INF";
+  if (soap_isninfd(n))
+    return "-INF";
+#if defined(HAVE_SPRINTF_L)
+# ifdef WIN32
+  _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, soap->c_locale, n);
+# else
+  sprintf_l(soap->tmpbuf, soap->c_locale, soap->double_format, n);
+# endif
+#else
+# ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->double_format, n);
+#else
+  sprintf(soap->tmpbuf, soap->double_format, n);
+#endif
+  s = strchr(soap->tmpbuf, ',');	/* convert decimal comma to DP */
+  if (s)
+    *s = '.';
+#endif
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_double2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2double(struct soap *soap, const char *s, double *p)
+{ if (s)
+  { if (!*s)
+      return soap->error = SOAP_TYPE;
+    if (!soap_tag_cmp(s, "INF"))
+      *p = DBL_PINFTY;
+    else if (!soap_tag_cmp(s, "+INF"))
+      *p = DBL_PINFTY;
+    else if (!soap_tag_cmp(s, "-INF"))
+      *p = DBL_NINFTY;
+    else if (!soap_tag_cmp(s, "NaN"))
+      *p = DBL_NAN;
+    else
+    {
+#if defined(HAVE_STRTOD_L)
+      char *r;
+# ifdef WIN32
+      *p = _strtod_l(s, &r, soap->c_locale);
+# else
+      *p = strtod_l(s, &r, soap->c_locale);
+# endif
+      if (*r)
+#elif defined(HAVE_STRTOD)
+      char *r;
+      *p = strtod(s, &r);
+      if (*r)
+#endif
+      {
+#if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
+        if (sscanf_l(s, soap->c_locale, "%lf", p) != 1)
+          soap->error = SOAP_TYPE;
+#elif defined(HAVE_SSCANF)
+        if (sscanf(s, "%lf", p) != 1)
+          soap->error = SOAP_TYPE;
+#else
+        soap->error = SOAP_TYPE;
+#endif
+      }
+    }
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+double *
+SOAP_FMAC2
+soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type != '\0' && soap_isnumeric(soap, type))
+    return NULL;
+#endif
+  p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
+  else if (p)
+  { if (soap_s2double(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedByte2s(struct soap *soap, unsigned char n)
+{ return soap_unsignedLong2s(soap, (unsigned long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
+{ if (s)
+  { unsigned long n;
+    char *r;
+    n = soap_strtoul(s, &r, 10);
+    if (s == r || *r || n > 255)
+      soap->error = SOAP_TYPE;
+    *p = (unsigned char)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+unsigned char *
+SOAP_FMAC2
+soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
+  else if (p)
+  { if (soap_s2unsignedByte(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedShort2s(struct soap *soap, unsigned short n)
+{ return soap_unsignedLong2s(soap, (unsigned long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
+{ if (s)
+  { unsigned long n;
+    char *r;
+    n = soap_strtoul(s, &r, 10);
+    if (s == r || *r || n > 65535)
+      soap->error = SOAP_TYPE;
+    *p = (unsigned short)n;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+unsigned short *
+SOAP_FMAC2
+soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
+  else if (p)
+  { if (soap_s2unsignedShort(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedInt2s(struct soap *soap, unsigned int n)
+{ return soap_unsignedLong2s(soap, (unsigned long)n);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
+{ if (s)
+  { char *r;
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+    soap_reset_errno;
+#endif
+#endif
+    *p = (unsigned int)soap_strtoul(s, &r, 10);
+    if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+     || soap_errno == SOAP_ERANGE
+#endif
+#endif
+    )
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+unsigned int *
+SOAP_FMAC2
+soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
+  else if (p)
+  { if (soap_s2unsignedInt(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_unsignedLong2s(struct soap *soap, unsigned long n)
+{
+#ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", n);
+#else
+  sprintf(soap->tmpbuf, "%lu", n);
+#endif
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
+{ if (s)
+  { char *r;
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+    soap_reset_errno;
+#endif
+#endif
+    *p = soap_strtoul(s, &r, 10);
+    if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+     || soap_errno == SOAP_ERANGE
+#endif
+#endif
+    )
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+unsigned long *
+SOAP_FMAC2
+soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+#ifndef WITH_LEAN
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+#endif
+  p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
+  else if (p)
+  { if (soap_s2unsignedLong(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_ULONG642s(struct soap *soap, ULONG64 n)
+{
+#ifdef HAVE_SNPRINTF
+  soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_ULONG_FORMAT, n);
+#else
+  sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
+#endif
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
+{ if (s)
+  {
+#ifdef HAVE_STRTOULL
+    char *r;
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+    soap_reset_errno;
+#endif
+#endif
+    *p = soap_strtoull(s, &r, 10);
+    if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
+#ifndef WITH_NOIO
+#ifndef WITH_LEAN
+       || soap_errno == SOAP_ERANGE
+#endif
+#endif
+      )
+#else
+#ifdef HAVE_SSCANF
+    if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
+#endif
+#endif
+      soap->error = SOAP_TYPE;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+ULONG64 *
+SOAP_FMAC2
+soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":positiveInteger")
+   && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
+   && soap_match_tag(soap, soap->type, ":unsignedLong")
+   && soap_match_tag(soap, soap->type, ":unsignedInt")
+   && soap_match_tag(soap, soap->type, ":unsignedShort")
+   && soap_match_tag(soap, soap->type, ":unsignedByte"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+  p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
+  else if (p)
+  { if (soap_s2ULONG64(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
+{ if (s)
+  { long l = (long)strlen(s);
+    if ((maxlen >= 0 && l > maxlen) || l < minlen)
+      return soap->error = SOAP_LENGTH;
+    if (!(*t = soap_strdup(soap, s)))
+      return soap->error = SOAP_EOM;
+    if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
+    { char *r = *t;
+      /* remove non-ASCII chars */
+      for (s = *t; *s; s++)
+        if (!(*s & 0x80))
+          *r++ = *s;
+      *r = '\0';
+    }
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
+{ if (s)
+  { long l = (long)strlen(s);
+    if ((maxlen >= 0 && l > maxlen) || l < minlen)
+      return soap->error = SOAP_LENGTH;
+    soap->labidx = 0;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
+    /* convert (by prefix normalize prefix) all QNames in s */
+    for (;;)
+    { size_t n;
+      struct soap_nlist *np;
+      register const char *p;
+      /* skip blanks */
+      while (*s && soap_blank((soap_wchar)*s))
+        s++;
+      if (!*s)
+        break;
+      /* find next QName */
+      n = 1;
+      while (s[n] && !soap_blank((soap_wchar)s[n]))
+        n++;
+      np = soap->nlist;
+      /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
+      if (!np || *s == '#' || !strncmp(s, "xml:", 4))
+      { soap_append_lab(soap, s, n);
+      }
+      else /* we normalize the QName by replacing its prefix */
+      { const char *q;
+        for (p = s; *p && p < s + n; p++)
+          if (*p == ':')
+            break;
+        if (*p == ':')
+        { size_t k = p - s;
+          while (np && (strncmp(np->id, s, k) || np->id[k]))
+            np = np->next;
+          p++;
+        }
+        else
+        { while (np && *np->id)
+            np = np->next;
+          p = s;
+        }
+        /* replace prefix */
+        if (np)
+        { if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id))
+          { size_t k = strlen(q);
+            if (q[k-1] != '_')
+              soap_append_lab(soap, q, k);
+            else
+            { soap_append_lab(soap, "\"", 1);
+              soap_append_lab(soap, soap->local_namespaces[np->index].ns, strlen(soap->local_namespaces[np->index].ns));
+              soap_append_lab(soap, "\"", 1);
+            }
+          }
+          else if (np->ns)
+          { soap_append_lab(soap, "\"", 1);
+            soap_append_lab(soap, np->ns, strlen(np->ns));
+            soap_append_lab(soap, "\"", 1);
+          }
+          else
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s, np->index, np->ns ? np->ns : SOAP_STR_EOS));
+            return soap->error = SOAP_NAMESPACE;
+          }
+        }
+        else if (s[n]) /* no namespace, part of string */
+        { soap_append_lab(soap, s, n);
+        }
+        else /* no namespace: assume "" namespace */
+        { soap_append_lab(soap, "\"\"", 2);
+        }
+        soap_append_lab(soap, ":", 1);
+        soap_append_lab(soap, p, n - (p-s));
+      }
+      /* advance to next and add spacing */
+      s += n;
+      if (*s)
+        soap_append_lab(soap, " ", 1);
+    }
+    soap_append_lab(soap, SOAP_STR_EOS, 1);
+    *t = soap_strdup(soap, soap->labbuf);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t));
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_QName2s(struct soap *soap, const char *s)
+{ const char *t = NULL;
+  if (s)
+  { soap->labidx = 0;
+    for (;;)
+    { size_t n;
+      /* skip blanks */
+      while (*s && soap_blank((soap_wchar)*s))
+        s++;
+      if (!*s)
+        break;
+      /* find next QName */
+      n = 1;
+      while (s[n] && !soap_blank((soap_wchar)s[n]))
+        n++;
+      /* normal prefix: pass string as is */
+      if (*s != '"')
+      {
+#ifndef WITH_LEAN
+        if ((soap->mode & SOAP_XML_CANONICAL))
+          soap_utilize_ns(soap, s);
+        if ((soap->mode & SOAP_XML_DEFAULTNS))
+        { const char *r = strchr(s, ':');
+          if (r && soap->nlist && !strncmp(soap->nlist->id, s, r-s) && !soap->nlist->id[r-s])
+          { n -= r-s + 1;
+            s = r + 1;
+          }
+        }
+#endif
+        soap_append_lab(soap, s, n);
+      }
+      else /* URL-based string prefix */
+      { const char *q;
+        s++;
+        q = strchr(s, '"');
+        if (q)
+        { struct Namespace *p = soap->local_namespaces;
+          if (p)
+          { for (; p->id; p++)
+            { if (p->ns)
+                if (!soap_tag_cmp(s, p->ns))
+                  break;
+              if (p->in)
+                if (!soap_tag_cmp(s, p->in))
+                  break;
+            }
+          }
+          /* URL is in the namespace table? */
+          if (p && p->id)
+          { const char *r = p->id;
+#ifndef WITH_LEAN
+            if ((soap->mode & SOAP_XML_DEFAULTNS) && soap->nlist && !strcmp(soap->nlist->id, r))
+              q++;
+            else
+#endif
+              soap_append_lab(soap, r, strlen(r));
+          }
+          else /* not in namespace table: create xmlns binding */
+          { char *r = soap_strdup(soap, s);
+            r[q-s] = '\0';
+#ifdef HAVE_SNPRINTF
+            soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:_%d", soap->idnum++);
+#else
+            sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
+#endif
+            soap_set_attr(soap, soap->tmpbuf, r, 1);
+            soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6));
+          }
+          soap_append_lab(soap, q + 1, n - (q-s) - 1);
+        }
+      }
+      /* advance to next and add spacing */
+      s += n;
+      if (*s)
+        soap_append_lab(soap, " ", 1);
+    }
+    soap_append_lab(soap, SOAP_STR_EOS, 1);
+    t = soap_strdup(soap, soap->labbuf);
+  }
+  return t;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen)
+{ if (s)
+  { long l;
+    wchar_t *r;
+    *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
+    if (!r)
+      return soap->error = SOAP_EOM;
+    if (soap->mode & SOAP_ENC_LATIN)
+    { while (*s)
+        *r++ = (wchar_t)*s++;
+    }
+    else
+    { /* Convert UTF8 to wchar */
+      while (*s)
+      { register soap_wchar c, c1, c2, c3, c4;
+        c = (unsigned char)*s++;
+        if (c < 0x80)
+          *r++ = (wchar_t)c;
+        else
+        { c1 = (soap_wchar)*s++ & 0x3F;
+          if (c < 0xE0)
+            *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
+          else
+          { c2 = (soap_wchar)*s++ & 0x3F;
+            if (c < 0xF0)
+              *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
+            else
+            { c3 = (soap_wchar)*s++ & 0x3F;
+              if (c < 0xF8)
+                *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
+              else
+              { c4 = (soap_wchar)*s++ & 0x3F;
+                if (c < 0xFC)
+                  *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
+                else
+                  *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
+              }
+            }
+          }
+        }
+      }
+    }
+    *r = L'\0';
+    l = (long)(r - *t);
+    if ((maxlen >= 0 && l > maxlen) || l < minlen)
+      return soap->error = SOAP_LENGTH;
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_wchar2s(struct soap *soap, const wchar_t *s)
+{ register soap_wchar c;
+  register char *r, *t;
+  const wchar_t *q = s;
+  size_t n = 0;
+  while ((c = *q++))
+  { if (c > 0 && c < 0x80)
+      n++;
+    else
+      n += 6;
+  }
+  r = t = (char*)soap_malloc(soap, n + 1);
+  if (r)
+  { /* Convert wchar to UTF8 */
+    while ((c = *s++))
+    { if (c > 0 && c < 0x80)
+        *t++ = (char)c;
+      else
+      { if (c < 0x0800)
+          *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
+        else
+        { if (c < 0x010000)
+            *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
+          else
+          { if (c < 0x200000)
+              *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
+            else
+            { if (c < 0x04000000)
+                *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
+              else
+              { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
+                *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
+              }
+              *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
+            }
+            *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
+          }
+          *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
+        }
+        *t++ = (char)(0x80 | (c & 0x3F));
+      }
+    }
+    *t = '\0';
+  }
+  return r;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
+{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
+  if (id < 0)
+    return soap->error;
+  if (!**p && (soap->mode & SOAP_C_NILSTRING))
+    return soap_element_null(soap, tag, id, type);
+  if (soap_element_begin_out(soap, tag, id, type)
+   || soap_string_out(soap, *p, 0)
+   || soap_element_end_out(soap, tag))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char **
+SOAP_FMAC2
+soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
+{ (void)type;
+  if (soap_element_begin_in(soap, tag, 1, NULL))
+  { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
+      return NULL;
+    soap->error = SOAP_OK;
+  }
+  if (!p)
+  { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
+      return NULL;
+  }
+  if (soap->null)
+    *p = NULL;
+  else if (soap->body)
+  { *p = soap_string_in(soap, flag, minlen, maxlen);
+    if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
+      return NULL;
+    if (!**p && tag && *tag == '-')
+    { soap->error = SOAP_NO_TAG;
+      return NULL;
+    }
+  }
+  else if (tag && *tag == '-')
+  { soap->error = SOAP_NO_TAG;
+    return NULL;
+  }
+  else if (!*soap->href && minlen > 0)
+  { soap->error = SOAP_LENGTH;
+    return NULL;
+  }
+  else
+    *p = soap_strdup(soap, SOAP_STR_EOS);
+  if (*soap->href)
+    p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
+{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
+  if (id < 0)
+    return soap->error;
+  if (!**p && (soap->mode & SOAP_C_NILSTRING))
+    return soap_element_null(soap, tag, id, type);
+  if (soap_element_begin_out(soap, tag, id, type)
+   || soap_wstring_out(soap, *p, 0)
+   || soap_element_end_out(soap, tag))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_2
+SOAP_FMAC1
+wchar_t **
+SOAP_FMAC2
+soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
+{ (void)type;
+  if (soap_element_begin_in(soap, tag, 1, NULL))
+  { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
+      return NULL;
+    soap->error = SOAP_OK;
+  }
+  if (!p)
+  { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
+      return NULL;
+  }
+  if (soap->body)
+  { *p = soap_wstring_in(soap, 1, minlen, maxlen);
+    if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
+      return NULL;
+    if (!**p && tag && *tag == '-')
+    { soap->error = SOAP_NO_TAG;
+      return NULL;
+    }
+  }
+  else if (tag && *tag == '-')
+  { soap->error = SOAP_NO_TAG;
+    return NULL;
+  }
+  else if (soap->null)
+    *p = NULL;
+  else
+    *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
+  if (*soap->href)
+    p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+time_t
+SOAP_FMAC2
+soap_timegm(struct tm *T)
+{
+#if defined(HAVE_TIMEGM)
+  return timegm(T);
+#else
+  time_t t, g, z;
+  struct tm tm;
+  t = mktime(T);
+  if (t == (time_t)-1)
+    return (time_t)-1;
+#ifdef HAVE_GMTIME_R
+  gmtime_r(&t, &tm);
+#else
+  tm = *gmtime(&t);
+#endif
+  tm.tm_isdst = 0;
+  g = mktime(&tm);
+  if (g == (time_t)-1)
+    return (time_t)-1;
+  z = g - t;
+  return t - z;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_dateTime2s(struct soap *soap, time_t n)
+{ struct tm T, *pT = &T;
+#if defined(HAVE_GMTIME_R)
+  if (gmtime_r(&n, pT))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
+#elif defined(HAVE_GMTIME)
+  if ((pT = gmtime(&n)))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
+#elif defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)
+#if defined(HAVE_LOCALTIME_R)
+  if (localtime_r(&n, pT))
+  { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
+    memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
+    soap->tmpbuf[22] = ':';                           /* 2000-03-01T02:00:00+03:00 */
+  }
+#else
+  if ((pT = localtime(&n)))
+  { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
+    memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
+    soap->tmpbuf[22] = ':';                           /* 2000-03-01T02:00:00+03:00 */
+  }
+#endif
+#elif defined(HAVE_GETTIMEOFDAY)
+  struct timezone tz;
+  memset((void*)&tz, 0, sizeof(tz));
+#if defined(HAVE_LOCALTIME_R)
+  if (localtime_r(&n, pT))
+  { struct timeval tv;
+    gettimeofday(&tv, &tz);
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#else
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#endif
+  }
+#else
+  if ((pT = localtime(&n)))
+  { struct timeval tv;
+    gettimeofday(&tv, &tz);
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#else
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#endif
+  }
+#endif
+#elif defined(HAVE_FTIME)
+  struct timeb t;
+  memset((void*)&t, 0, sizeof(t));
+#if defined(HAVE_LOCALTIME_R)
+  if (localtime_r(&n, pT))
+  {
+#ifdef __BORLANDC__
+    ::ftime(&t);
+#else
+    ftime(&t);
+#endif
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#else
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#endif
+  }
+#else
+  if ((pT = localtime(&n)))
+  {
+#ifdef __BORLANDC__
+    ::ftime(&t);
+#else
+    ftime(&t);
+#endif
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#else
+    sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#endif
+  }
+#endif
+#elif defined(HAVE_LOCALTIME_R)
+  if (localtime_r(&n, pT))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#else
+  if ((pT = localtime(&n)))
+    strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#endif
+  else
+    strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
+  return soap->tmpbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
+{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
+   || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
+    return soap->error;
+  return soap_element_end_out(soap, tag);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
+{ if (s)
+  { char zone[32];
+    struct tm T;
+    const char *t;
+    *zone = '\0';
+    memset((void*)&T, 0, sizeof(T));
+    if (strchr(s, '-'))
+      t = "%d-%d-%dT%d:%d:%d%31s";
+    else if (strchr(s, ':'))
+      t = "%4d%2d%2dT%d:%d:%d%31s";
+    else /* parse non-XSD-standard alternative ISO 8601 format */
+      t = "%4d%2d%2dT%2d%2d%2d%31s";
+    if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6)
+      return soap->error = SOAP_TYPE;
+    if (T.tm_year == 1)
+      T.tm_year = 70;
+    else
+      T.tm_year -= 1900;
+    T.tm_mon--;
+    if (*zone == '.')
+    { for (s = zone + 1; *s; s++)
+        if (*s < '0' || *s > '9')
+          break;
+    }
+    else
+      s = zone;
+    if (*s)
+    {
+#ifndef WITH_NOZONE
+      if (*s == '+' || *s == '-')
+      { int h = 0, m = 0;
+        if (s[3] == ':')
+        { /* +hh:mm */
+          sscanf(s, "%d:%d", &h, &m);
+          if (h < 0)
+            m = -m;
+        }
+        else /* +hhmm */
+        { m = (int)soap_strtol(s, NULL, 10);
+          h = m / 100;
+          m = m % 100;
+        }
+        T.tm_min -= m;
+        T.tm_hour -= h;
+        /* put hour and min in range */
+        T.tm_hour += T.tm_min / 60;
+        T.tm_min %= 60;
+        if (T.tm_min < 0)
+        { T.tm_min += 60;
+          T.tm_hour--;
+        }
+        T.tm_mday += T.tm_hour / 24;
+        T.tm_hour %= 24;
+        if (T.tm_hour < 0)
+        { T.tm_hour += 24;
+          T.tm_mday--;
+        }
+        /* note: day of the month may be out of range, timegm() handles it */
+      }
+#endif
+      *p = soap_timegm(&T);
+    }
+    else /* no UTC or timezone, so assume we got a localtime */
+    { T.tm_isdst = -1;
+      *p = mktime(&T);
+    }
+  }
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+time_t *
+SOAP_FMAC2
+soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
+{ if (soap_element_begin_in(soap, tag, 0, NULL))
+    return NULL;
+  if (*soap->type
+   && soap_match_tag(soap, soap->type, type)
+   && soap_match_tag(soap, soap->type, ":dateTime"))
+  { soap->error = SOAP_TYPE;
+    soap_revert(soap);
+    return NULL;
+  }
+  p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
+  if (*soap->href)
+    p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
+  else if (p)
+  { if (soap_s2dateTime(soap, soap_value(soap), p))
+      return NULL;
+  }
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
+{ int i;
+  const char *t = NULL;
+  if (tag && *tag != '-')
+  { if (soap->local_namespaces && (t = strchr(tag, ':')))
+    { size_t n = t - tag;
+      if (n >= sizeof(soap->tmpbuf))
+        n = sizeof(soap->tmpbuf) - 1;
+      strncpy(soap->tmpbuf, tag, n);
+      soap->tmpbuf[n] = '\0';
+      for (i = 0; soap->local_namespaces[i].id; i++)
+        if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
+          break;
+      t++;
+      if (soap_element(soap, t, 0, type)
+       || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
+       || soap_element_start_end_out(soap, NULL))
+        return soap->error;
+    }
+    else
+    { t = tag;
+      if (soap_element_begin_out(soap, t, 0, type))
+        return soap->error;
+    }
+  }
+  if (p && *p)
+  { if (soap_send(soap, *p)) /* send as-is */
+      return soap->error;
+  }
+  if (t)
+    return soap_element_end_out(soap, t);
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+char **
+SOAP_FMAC2
+soap_inliteral(struct soap *soap, const char *tag, char **p)
+{ if (soap_element_begin_in(soap, tag, 1, NULL))
+  { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
+      return NULL;
+    soap->error = SOAP_OK;
+  }
+  if (!p)
+  { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
+      return NULL;
+  }
+  if (soap->body || (tag && *tag == '-'))
+  { *p = soap_string_in(soap, 0, -1, -1);
+    if (!*p)
+      return NULL;
+    if (!**p && tag && *tag == '-')
+    { soap->error = SOAP_NO_TAG;
+      return NULL;
+    }
+  }
+  else if (soap->null)
+    *p = NULL;
+  else
+    *p = soap_strdup(soap, SOAP_STR_EOS);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
+{ int i;
+  const char *t = NULL;
+  if (tag && *tag != '-')
+  { if (soap->local_namespaces && (t = strchr(tag, ':')))
+    { size_t n = t - tag;
+      if (n >= sizeof(soap->tmpbuf))
+        n = sizeof(soap->tmpbuf) - 1;
+      strncpy(soap->tmpbuf, tag, n);
+      soap->tmpbuf[n] = '\0';
+      for (i = 0; soap->local_namespaces[i].id; i++)
+        if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
+          break;
+      t++;
+      if (soap_element(soap, t, 0, type)
+       || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
+       || soap_element_start_end_out(soap, NULL))
+        return soap->error;
+    }
+    else
+    { t = tag;
+      if (soap_element_begin_out(soap, t, 0, type))
+        return soap->error;
+    }
+  }
+  if (p)
+  { wchar_t c;
+    const wchar_t *s = *p;
+    while ((c = *s++))
+    { if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */
+        return soap->error;
+    }
+  }
+  if (t)
+    return soap_element_end_out(soap, t);
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_2
+SOAP_FMAC1
+wchar_t **
+SOAP_FMAC2
+soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
+{ if (soap_element_begin_in(soap, tag, 1, NULL))
+  { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
+      return NULL;
+    soap->error = SOAP_OK;
+  }
+  if (!p)
+  { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
+      return NULL;
+  }
+  if (soap->body)
+  { *p = soap_wstring_in(soap, 0, -1, -1);
+    if (!*p)
+      return NULL;
+    if (!**p && tag && *tag == '-')
+    { soap->error = SOAP_NO_TAG;
+      return NULL;
+    }
+  }
+  else if (tag && *tag == '-')
+  { soap->error = SOAP_NO_TAG;
+    return NULL;
+  }
+  else if (soap->null)
+    *p = NULL;
+  else
+    *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
+  if (soap->body && soap_element_end_in(soap, tag))
+    return NULL;
+  return p;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+const char *
+SOAP_FMAC2
+soap_value(struct soap *soap)
+{ register size_t i;
+  register soap_wchar c = 0;
+  register char *s = soap->tmpbuf;
+  if (!soap->body)
+    return SOAP_STR_EOS;
+  do c = soap_get(soap);
+  while (soap_blank(c));
+  for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
+  { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
+      break;
+    *s++ = (char)c;
+    c = soap_get(soap);
+  }
+  for (s--; i > 0; i--, s--)
+  { if (!soap_blank((soap_wchar)*s))
+      break;
+  }
+  s[1] = '\0';
+  soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
+  if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
+    soap_unget(soap, c);
+  else if (soap->mode & SOAP_XML_STRICT)
+  { soap->error = SOAP_LENGTH;
+    return NULL;
+  }
+#ifdef WITH_DOM
+  if ((soap->mode & SOAP_XML_DOM) && soap->dom)
+    soap->dom->data = soap_strdup(soap, soap->tmpbuf);
+#endif
+  return soap->tmpbuf; /* return non-null pointer */
+}
+#endif
+
+/******************************************************************************/
+#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getline(struct soap *soap, char *s, int len)
+{ int i = len;
+  soap_wchar c = 0;
+  for (;;)
+  { while (--i > 0)
+    { c = soap_getchar(soap);
+      if (c == '\r' || c == '\n')
+        break;
+      if ((int)c == EOF)
+        return soap->error = SOAP_CHK_EOF;
+      *s++ = (char)c;
+    }
+    *s = '\0';
+    if (c != '\n')
+      c = soap_getchar(soap); /* got \r or something else, now get \n */
+    if (c == '\n')
+    { if (i + 1 == len) /* empty line: end of HTTP/MIME header */
+        break;
+      c = soap_get0(soap);
+      if (c != ' ' && c != '\t') /* HTTP line continuation? */
+        break;
+    }
+    else if ((int)c == EOF)
+      return soap->error = SOAP_CHK_EOF;
+    if (i <= 0)
+      return soap->error = SOAP_HDR;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static size_t
+soap_count_attachments(struct soap *soap)
+{
+#ifndef WITH_LEANER
+  register struct soap_multipart *content;
+  register size_t count = soap->count;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
+  if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
+  { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
+    for (content = soap->dime.first; content; content = content->next)
+    { count += 12 + ((content->size+3)&(~3));
+      if (content->id)
+        count += ((strlen(content->id)+3)&(~3));
+      if (content->type)
+        count += ((strlen(content->type)+3)&(~3));
+      if (content->options)
+        count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
+    }
+  }
+  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
+  { register size_t n = strlen(soap->mime.boundary);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
+    for (content = soap->mime.first; content; content = content->next)
+    { register const char *s;
+      /* count \r\n--boundary\r\n */
+      count += 6 + n;
+      /* count Content-Type: ...\r\n */
+      if (content->type)
+        count += 16 + strlen(content->type);
+      /* count Content-Transfer-Encoding: ...\r\n */
+      s = soap_code_str(mime_codes, content->encoding);
+      if (s)
+        count += 29 + strlen(s);
+      /* count Content-ID: ...\r\n */
+      if (content->id)
+        count += 14 + strlen(content->id);
+      /* count Content-Location: ...\r\n */
+      if (content->location)
+        count += 20 + strlen(content->location);
+      /* count Content-Description: ...\r\n */
+      if (content->description)
+        count += 23 + strlen(content->description);
+      /* count \r\n...content */
+      count += 2 + content->size;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
+    }
+    /* count \r\n--boundary-- */
+    count += 6 + n;
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=%lu\n", (unsigned long)count));
+  return count;
+#else
+  return soap->count;
+#endif
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static int
+soap_putdimefield(struct soap *soap, const char *s, size_t n)
+{ if (soap_send_raw(soap, s, n))
+    return soap->error;
+  return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+char *
+SOAP_FMAC2
+soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
+{ size_t n;
+  char *s = NULL;
+  if (option)
+  { n = strlen(option);
+    s = (char*)soap_malloc(soap, n + 5);
+    if (s)
+    { s[0] = (char)(optype >> 8);
+      s[1] = (char)(optype & 0xFF);
+      s[2] = (char)(n >> 8);
+      s[3] = (char)(n & 0xFF);
+      strcpy(s + 4, option);
+    }
+  }
+  return s;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putdimehdr(struct soap *soap)
+{ unsigned char tmp[12];
+  size_t optlen = 0, idlen = 0, typelen = 0;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS));
+  if (soap->dime.options)
+    optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
+  if (soap->dime.id)
+  { idlen = strlen(soap->dime.id);
+    if (idlen > 0x0000FFFF)
+      idlen = 0x0000FFFF;
+  }
+  if (soap->dime.type)
+  { typelen = strlen(soap->dime.type);
+    if (typelen > 0x0000FFFF)
+      typelen = 0x0000FFFF;
+  }
+  tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
+  tmp[1] = soap->dime.flags & 0xF0;
+  tmp[2] = (char)(optlen >> 8);
+  tmp[3] = (char)(optlen & 0xFF);
+  tmp[4] = (char)(idlen >> 8);
+  tmp[5] = (char)(idlen & 0xFF);
+  tmp[6] = (char)(typelen >> 8);
+  tmp[7] = (char)(typelen & 0xFF);
+  tmp[8] = (char)(soap->dime.size >> 24);
+  tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
+  tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
+  tmp[11] = (char)(soap->dime.size & 0xFF);
+  if (soap_send_raw(soap, (char*)tmp, 12)
+   || soap_putdimefield(soap, soap->dime.options, optlen)
+   || soap_putdimefield(soap, soap->dime.id, idlen)
+   || soap_putdimefield(soap, soap->dime.type, typelen))
+    return soap->error;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putdime(struct soap *soap)
+{ struct soap_multipart *content;
+  if (!(soap->mode & SOAP_ENC_DIME))
+    return SOAP_OK;
+  for (content = soap->dime.first; content; content = content->next)
+  { void *handle;
+    soap->dime.size = content->size;
+    soap->dime.id = content->id;
+    soap->dime.type = content->type;
+    soap->dime.options = content->options;
+    soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
+    if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
+    { size_t size = content->size;
+      if (!handle)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
+        return soap->error;
+      }
+      if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
+      { size_t chunksize = sizeof(soap->tmpbuf);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
+        do
+        { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
+          DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
+          if (size < chunksize)
+          { soap->dime.flags &= ~SOAP_DIME_CF;
+            if (!content->next)
+              soap->dime.flags |= SOAP_DIME_ME;
+          }
+          else
+            soap->dime.flags |= SOAP_DIME_CF;
+          soap->dime.size = size;
+          if (soap_putdimehdr(soap)
+           || soap_putdimefield(soap, soap->tmpbuf, size))
+            break;
+          if (soap->dime.id)
+          { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
+            soap->dime.id = NULL;
+            soap->dime.type = NULL;
+            soap->dime.options = NULL;
+          }
+        } while (size >= chunksize);
+      }
+      else
+      { if (!content->next)
+          soap->dime.flags |= SOAP_DIME_ME;
+        if (soap_putdimehdr(soap))
+          return soap->error;
+        do
+        { size_t bufsize;
+          if (size < sizeof(soap->tmpbuf))
+            bufsize = size;
+          else
+            bufsize = sizeof(soap->tmpbuf);
+          if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
+            soap->error = SOAP_CHK_EOF;
+            break;
+          }
+          if (soap_send_raw(soap, soap->tmpbuf, bufsize))
+            break;
+          size -= bufsize;
+        } while (size);
+        DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
+        soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
+      }
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
+      if (soap->fdimereadclose)
+        soap->fdimereadclose(soap, handle);
+    }
+    else
+    { if (!content->next)
+        soap->dime.flags |= SOAP_DIME_ME;
+      if (soap_putdimehdr(soap)
+       || soap_putdimefield(soap, (char*)content->ptr, content->size))
+        return soap->error;
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static char *
+soap_getdimefield(struct soap *soap, size_t n)
+{ register soap_wchar c;
+  register size_t i;
+  register char *s;
+  register char *p = NULL;
+  if (n)
+  { p = (char*)soap_malloc(soap, n + 1);
+    if (p)
+    { s = p;
+      for (i = n; i > 0; i--)
+      { if ((int)(c = soap_get1(soap)) == EOF)
+        { soap->error = SOAP_CHK_EOF;
+          return NULL;
+        }
+        *s++ = (char)c;
+      }
+      *s = '\0';
+      if ((soap->error = soap_move(soap, (size_t)(-(long)n&3))))
+        return NULL;
+    }
+    else
+      soap->error = SOAP_EOM;
+  }
+  return p;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getdimehdr(struct soap *soap)
+{ register soap_wchar c;
+  register char *s;
+  register int i;
+  unsigned char tmp[12];
+  size_t optlen, idlen, typelen;
+  if (!(soap->mode & SOAP_ENC_DIME))
+    return soap->error = SOAP_DIME_END;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
+  if (soap->dime.buflen || soap->dime.chunksize)
+  { if (soap_move(soap, soap->dime.size - soap_tell(soap)))
+      return soap->error = SOAP_CHK_EOF;
+    soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
+    return SOAP_OK;
+  }
+  s = (char*)tmp;
+  for (i = 12; i > 0; i--)
+  { if ((int)(c = soap_getchar(soap)) == EOF)
+      return soap->error = SOAP_CHK_EOF;
+    *s++ = (char)c;
+  }
+  if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
+    return soap->error = SOAP_DIME_MISMATCH;
+  soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
+  optlen = (tmp[2] << 8) | tmp[3];
+  idlen = (tmp[4] << 8) | tmp[5];
+  typelen = (tmp[6] << 8) | tmp[7];
+  soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
+  if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
+    return soap->error;
+  if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
+    return soap->error;
+  if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
+    return soap->error;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id='%s', type='%s', options='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "", soap->dime.options ? soap->dime.options+4 : SOAP_STR_EOS));
+  if (soap->dime.flags & SOAP_DIME_ME)
+    soap->mode &= ~SOAP_ENC_DIME;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getdime(struct soap *soap)
+{ while (soap->dime.flags & SOAP_DIME_CF)
+  { if (soap_getdimehdr(soap))
+      return soap->error;
+    if (soap_move(soap, soap->dime.size))
+      return soap->error = SOAP_EOF;
+  }
+  if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap))))
+    return soap->error = SOAP_EOF;
+  for (;;)
+  { register struct soap_multipart *content;
+    if (soap_getdimehdr(soap))
+      break;
+    if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
+    { const char *id, *type, *options;
+      size_t size, n;
+      if (!soap->dime.ptr)
+        return soap->error;
+      id = soap->dime.id;
+      type = soap->dime.type;
+      options = soap->dime.options;
+      for (;;)
+      { size = soap->dime.size;
+        for (;;)
+        { n = soap->buflen - soap->bufidx;
+          if (size < n)
+            n = size;
+          if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
+            break;
+          size -= n;
+          if (!size)
+          { soap->bufidx += n;
+            break;
+          }
+          if (soap_recv(soap))
+          { soap->error = SOAP_EOF;
+            goto end;
+          }
+        }
+        if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
+        { soap->error = SOAP_EOF;
+          break;
+        }
+        if (!(soap->dime.flags & SOAP_DIME_CF))
+          break;
+        if (soap_getdimehdr(soap))
+          break;
+      }
+end:
+      if (soap->fdimewriteclose)
+        soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
+      soap->dime.size = 0;
+      soap->dime.id = id;
+      soap->dime.type = type;
+      soap->dime.options = options;
+    }
+    else if (soap->dime.flags & SOAP_DIME_CF)
+    { const char *id, *type, *options;
+      id = soap->dime.id;
+      type = soap->dime.type;
+      options = soap->dime.options;
+      if (soap_new_block(soap) == NULL)
+        return SOAP_EOM;
+      for (;;)
+      { register soap_wchar c;
+        register size_t i;
+        register char *s;
+        if (soap->dime.size > SOAP_MAXDIMESIZE)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE));
+          return soap->error = SOAP_DIME_ERROR;
+        }
+        s = (char*)soap_push_block(soap, NULL, soap->dime.size);
+        if (!s)
+          return soap->error = SOAP_EOM;
+        for (i = soap->dime.size; i > 0; i--)
+        { if ((int)(c = soap_get1(soap)) == EOF)
+            return soap->error = SOAP_EOF;
+          *s++ = (char)c;
+        }
+        if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
+          return soap->error = SOAP_EOF;
+        if (!(soap->dime.flags & SOAP_DIME_CF))
+          break;
+        if (soap_getdimehdr(soap))
+          return soap->error;
+      }
+      soap->dime.size = soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */
+      if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0)))
+        return soap->error;
+      soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated */
+      soap->dime.id = id;
+      soap->dime.type = type;
+      soap->dime.options = options;
+    }
+    else
+      soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
+    content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
+    if (!content)
+      return soap->error = SOAP_EOM;
+    content->id = soap->dime.id;
+    content->type = soap->dime.type;
+    content->options = soap->dime.options;
+    if (soap->error)
+      return soap->error;
+    soap_resolve_attachment(soap, content);
+  }
+  if (soap->error != SOAP_DIME_END)
+    return soap->error;
+  return soap->error = SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getmimehdr(struct soap *soap)
+{ struct soap_multipart *content;
+  do
+  { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
+      return soap->error;
+  }
+  while (!*soap->msgbuf);
+  if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
+  { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
+    /* remove white space */
+    while (soap_blank((soap_wchar)*s))
+      s--;
+    s[1] = '\0';
+    if (soap->mime.boundary)
+    { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
+        return soap->error = SOAP_MIME_ERROR;
+    }
+    else
+      soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
+    if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
+      return soap->error;
+  }
+  if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
+    return soap->error = SOAP_EOM;
+  content = soap->mime.last;
+  for (;;)
+  { register char *key = soap->msgbuf;
+    register char *val;
+    if (!*key)
+      break;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
+    val = strchr(soap->msgbuf, ':');
+    if (val)
+    { *val = '\0';
+      do val++;
+      while (*val && *val <= 32);
+      if (!soap_tag_cmp(key, "Content-ID"))
+        content->id = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Location"))
+        content->location = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Disposition"))
+        content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
+      else if (!soap_tag_cmp(key, "Content-Type"))
+        content->type = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Description"))
+        content->description = soap_strdup(soap, val);
+      else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
+        content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
+    }
+    if (soap_getline(soap, key, sizeof(soap->msgbuf)))
+      return soap->error;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_getmime(struct soap *soap)
+{ while (soap_get_mime_attachment(soap, NULL))
+    ;
+  return soap->error;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_post_check_mime_attachments(struct soap *soap)
+{ soap->imode |= SOAP_MIME_POSTCHECK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_check_mime_attachments(struct soap *soap)
+{ if (soap->mode & SOAP_MIME_POSTCHECK)
+    return soap_get_mime_attachment(soap, NULL) != NULL;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap_multipart *
+SOAP_FMAC2
+soap_get_mime_attachment(struct soap *soap, void *handle)
+{ register soap_wchar c = 0;
+  register size_t i, m = 0;
+  register char *s, *t = NULL;
+  register struct soap_multipart *content;
+  register short flag = 0;
+  if (!(soap->mode & SOAP_ENC_MIME))
+    return NULL;
+  content = soap->mime.last;
+  if (!content)
+  { if (soap_getmimehdr(soap))
+      return NULL;
+    content = soap->mime.last;
+  }
+  else if (content != soap->mime.first)
+  { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
+    { if (!content->ptr)
+        return NULL;
+    }
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id='%s' type='%s'\n", content->id ? content->id : SOAP_STR_EOS, content->type ? content->type : SOAP_STR_EOS));
+  if (!content->ptr && soap_new_block(soap) == NULL)
+  { soap->error = SOAP_EOM;
+    return NULL;
+  }
+  for (;;)
+  { if (content->ptr)
+      s = soap->tmpbuf;
+    else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf))))
+    { soap->error = SOAP_EOM;
+      return NULL;
+    }
+    for (i = 0; i < sizeof(soap->tmpbuf); i++)
+    { if (m > 0)
+      { *s++ = *t++;
+        m--;
+      }
+      else
+      { if (!flag)
+        { c = soap_get1(soap);
+          if ((int)c == EOF)
+          { if (content->ptr && soap->fmimewriteclose)
+              soap->fmimewriteclose(soap, (void*)content->ptr);
+            soap->error = SOAP_CHK_EOF;
+            return NULL;
+          }
+        }
+        if (flag || c == '\r')
+        { t = soap->msgbuf;
+          memset(t, 0, sizeof(soap->msgbuf));
+          strcpy(t, "\n--");
+          if (soap->mime.boundary)
+            strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
+          do c = soap_getchar(soap);
+          while (c == *t++);
+          if ((int)c == EOF)
+          { if (content->ptr && soap->fmimewriteclose)
+              soap->fmimewriteclose(soap, (void*)content->ptr);
+            soap->error = SOAP_CHK_EOF;
+            return NULL;
+          }
+          if (!*--t)
+            goto end;
+          *t = (char)c;
+          flag = (c == '\r');
+          m = t - soap->msgbuf + 1 - flag;
+          t = soap->msgbuf;
+          c = '\r';
+        }
+        *s++ = (char)c;
+      }
+    }
+    if (content->ptr && soap->fmimewrite)
+    { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
+        break;
+    }
+  }
+end:
+  *s = '\0'; /* make 0-terminated */
+  if (content->ptr)
+  { if (!soap->error && soap->fmimewrite)
+      soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
+    if (soap->fmimewriteclose)
+      soap->fmimewriteclose(soap, (void*)content->ptr);
+    if (soap->error)
+      return NULL;
+  }
+  else
+  { content->size = soap_size_block(soap, NULL, i+1) - 1; /* last block with '\0' */
+    content->ptr = soap_save_block(soap, NULL, NULL, 0);
+  }
+  soap_resolve_attachment(soap, content);
+  if (c == '-' && soap_getchar(soap) == '-')
+  { soap->mode &= ~SOAP_ENC_MIME;
+    if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
+    { if (soap->keep_alive < 0)
+        soap->keep_alive = 0;
+      soap_closesock(soap);
+      return NULL;
+    }
+  }
+  else
+  { while (c != '\r' && (int)c != EOF && soap_blank(c))
+      c = soap_getchar(soap);
+    if (c != '\r' || soap_getchar(soap) != '\n')
+    { soap->error = SOAP_MIME_ERROR;
+      return NULL;
+    }
+    if (soap_getmimehdr(soap))
+      return NULL;
+  }
+  return content;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_match_cid(struct soap *soap, const char *s, const char *t)
+{ register size_t n;
+  if (!s)
+    return 1;
+  if (!strcmp(s, t))
+    return 0;
+  if (!strncmp(s, "cid:", 4))
+    s += 4;
+  n = strlen(t);
+  if (*t == '<')
+  { t++;
+    n -= 2;
+  }
+  if (!strncmp(s, t, n) && !s[n])
+    return 0;
+  soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
+  if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
+    return 0;
+  return 1;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static void
+soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
+{ if (content->id)
+  { register struct soap_xlist **xp = &soap->xlist;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id));
+    while (*xp)
+    { register struct soap_xlist *xq = *xp;
+      if (!soap_match_cid(soap, xq->id, content->id))
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id));
+        *xp = xq->next;
+        *xq->ptr = (unsigned char*)content->ptr;
+        *xq->size = (int)content->size;
+        *xq->type = (char*)content->type;
+        if (content->options)
+          *xq->options = (char*)content->options;
+        else
+          *xq->options = (char*)content->description;
+        SOAP_FREE(soap, xq);
+      }
+      else
+        xp = &(*xp)->next;
+    }
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
+{ const char *s;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS));
+  if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
+    return soap->error;
+  if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
+    return soap->error;
+  s = soap_code_str(mime_codes, content->encoding);
+  if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
+    return soap->error;
+  if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
+    return soap->error;
+  if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
+    return soap->error;
+  if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
+    return soap->error;
+  return soap_send_raw(soap, "\r\n", 2);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_putmime(struct soap *soap)
+{ struct soap_multipart *content;
+  if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
+    return SOAP_OK;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
+  for (content = soap->mime.first; content; content = content->next)
+  { void *handle;
+    if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
+    { size_t size = content->size;
+      if (!handle)
+      { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
+        return soap->error;
+      }
+      if (soap_putmimehdr(soap, content))
+        return soap->error;
+      if (!size)
+      { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
+          do
+          { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
+            DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
+            if (soap_send_raw(soap, soap->tmpbuf, size))
+              break;
+          } while (size);
+        }
+        else
+        { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
+        }
+      }
+      else
+      { do
+        { size_t bufsize;
+          if (size < sizeof(soap->tmpbuf))
+            bufsize = size;
+          else
+            bufsize = sizeof(soap->tmpbuf);
+          if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
+          { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
+            soap->error = SOAP_EOF;
+            break;
+          }
+          if (soap_send_raw(soap, soap->tmpbuf, bufsize))
+            break;
+          size -= bufsize;
+        } while (size);
+      }
+      if (soap->fmimereadclose)
+        soap->fmimereadclose(soap, handle);
+    }
+    else
+    { if (soap_putmimehdr(soap, content)
+       || soap_send_raw(soap, content->ptr, content->size))
+        return soap->error;
+    }
+  }
+  return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_dime(struct soap *soap)
+{ soap->omode |= SOAP_ENC_DIME;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_mime(struct soap *soap, const char *boundary, const char *start)
+{ soap->omode |= SOAP_ENC_MIME;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = soap_strdup(soap, boundary);
+  soap->mime.start = soap_strdup(soap, start);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_dime(struct soap *soap)
+{ soap->omode &= ~SOAP_ENC_DIME;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_clr_mime(struct soap *soap)
+{ soap->omode &= ~SOAP_ENC_MIME;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = NULL;
+  soap->mime.start = NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static struct soap_multipart*
+soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
+{ struct soap_multipart *content;
+  content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
+  if (content)
+  { content->next = NULL;
+    content->ptr = ptr;
+    content->size = size;
+    content->id = NULL;
+    content->type = NULL;
+    content->options = NULL;
+    content->encoding = SOAP_MIME_NONE;
+    content->location = NULL;
+    content->description = NULL;
+    if (!*first)
+      *first = content;
+    if (*last)
+      (*last)->next = content;
+    *last = content;
+  }
+  return content;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
+{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
+  if (!content)
+    return SOAP_EOM;
+  content->id = soap_strdup(soap, id);
+  content->type = soap_strdup(soap, type);
+  content->options = soap_dime_option(soap, optype, option);
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
+{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
+  if (!content)
+    return SOAP_EOM;
+  content->id = soap_strdup(soap, id);
+  content->type = soap_strdup(soap, type);
+  content->encoding = encoding;
+  content->location = soap_strdup(soap, location);
+  content->description = soap_strdup(soap, description);
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+SOAP_FMAC1
+struct soap_multipart*
+SOAP_FMAC2
+soap_next_multipart(struct soap_multipart *content)
+{ if (content)
+    return content->next;
+  return NULL;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static void
+soap_select_mime_boundary(struct soap *soap)
+{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
+  { register char *s = soap->mime.boundary;
+    register size_t n = 0;
+    if (s)
+      n = strlen(s);
+    if (n < 16)
+    { n = 64;
+      s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
+      if (!s)
+        return;
+    }
+    strcpy(s, "==");
+    s += 2;
+    n -= 4;
+    while (n)
+    { *s++ = soap_base64o[soap_random & 0x3F];
+      n--;
+    }
+    strcpy(s, "==");
+  }
+  if (!soap->mime.start)
+    soap->mime.start = "<SOAP-ENV:Envelope>";
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEANER
+#ifndef PALM_1
+static int
+soap_valid_mime_boundary(struct soap *soap)
+{ register struct soap_multipart *content;
+  register size_t k;
+  if (soap->fmimeread)
+    return SOAP_OK;
+  k = strlen(soap->mime.boundary);
+  for (content = soap->mime.first; content; content = content->next)
+  { if (content->ptr && content->size >= k)
+    { register const char *p = (const char*)content->ptr;
+      register size_t i;
+      for (i = 0; i < content->size - k; i++, p++)
+      { if (!strncmp(p, soap->mime.boundary, k))
+          return SOAP_ERR;
+      }
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef WITH_GZIP
+#ifndef PALM_1
+static int
+soap_getgziphdr(struct soap *soap)
+{ int i;
+  soap_wchar c = 0, f = 0;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
+  for (i = 0; i < 9; i++)
+  { if ((int)(c = soap_get1(soap) == EOF))
+      return soap->error = SOAP_ZLIB_ERROR;
+    if (i == 1 && c == 8)
+      soap->z_dict = 0;
+    if (i == 2)
+      f = c;
+  }
+  if (f & 0x04) /* FEXTRA */
+  { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
+    { if ((int)soap_get1(soap) == EOF)
+        return soap->error = SOAP_ZLIB_ERROR;
+    }
+  }
+  if (f & 0x08) /* skip FNAME */
+  { do
+      c = soap_get1(soap);
+    while (c && (int)c != EOF);
+  }
+  if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
+  { do
+      c = soap_get1(soap);
+    while (c && (int)c != EOF);
+  }
+  if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
+  { if ((int)(c = soap_get1(soap)) != EOF)
+      c = soap_get1(soap);
+  }
+  if ((int)c == EOF)
+    return soap->error = SOAP_ZLIB_ERROR;
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_begin_serve(struct soap *soap)
+{
+#ifdef WITH_FASTCGI
+  if (FCGI_Accept() < 0)
+  { soap->error = SOAP_EOF;
+    return soap_send_fault(soap);
+  }
+#endif
+  soap_begin(soap);
+  if (soap_begin_recv(soap)
+   || soap_envelope_begin_in(soap)
+   || soap_recv_header(soap)
+   || soap_body_begin_in(soap))
+  { if (soap->error < SOAP_STOP)
+    {
+#ifdef WITH_FASTCGI
+      soap_send_fault(soap);
+#else
+      return soap_send_fault(soap);
+#endif
+    }
+    return soap_closesock(soap);
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_begin_recv(struct soap *soap)
+{ register soap_wchar c;
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", soap->socket, soap->recvfd));
+  soap->error = SOAP_OK;
+  soap->filterstop = SOAP_OK;
+  soap_free_temp(soap);
+  soap_set_local_namespaces(soap);
+  soap->version = 0;	/* don't assume we're parsing SOAP content by default */
+#ifndef WITH_NOIDREF
+  soap_free_iht(soap);
+#endif
+  if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
+    soap->omode |= SOAP_IO_CHUNK;
+  soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME);
+  soap->mode = soap->imode;
+  if (!soap->keep_alive)
+  { soap->buflen = 0;
+    soap->bufidx = 0;
+  }
+  if (!(soap->mode & SOAP_IO_KEEPALIVE))
+    soap->keep_alive = 0;
+  soap->ahead = 0;
+  soap->peeked = 0;
+  soap->level = 0;
+  soap->part = SOAP_BEGIN;
+  soap->alloced = 0;
+  soap->body = 1;
+  soap->count = 0;
+  soap->length = 0;
+  soap->cdata = 0;
+  *soap->endpoint = '\0';
+  soap->action = NULL;
+  soap->header = NULL;
+  soap->fault = NULL;
+  soap->status = 0;
+  soap->fform = NULL;
+#ifndef WITH_LEANER
+  soap->dom = NULL;
+  soap->dime.chunksize = 0;
+  soap->dime.buflen = 0;
+  soap->dime.list = NULL;
+  soap->dime.first = NULL;
+  soap->dime.last = NULL;
+  soap->mime.list = NULL;
+  soap->mime.first = NULL;
+  soap->mime.last = NULL;
+  soap->mime.boundary = NULL;
+  soap->mime.start = NULL;
+#endif
+#ifdef WIN32
+#ifndef UNDER_CE
+#ifndef WITH_FASTCGI
+  if (!soap_valid_socket(soap->socket) && !soap->is) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
+#ifdef __BORLANDC__
+    setmode(soap->recvfd, _O_BINARY);
+#else
+    _setmode(soap->recvfd, _O_BINARY);
+#endif
+#endif
+#endif
+#endif
+#ifdef WITH_ZLIB
+  soap->mode &= ~SOAP_ENC_ZLIB;
+  soap->zlib_in = SOAP_ZLIB_NONE;
+  soap->zlib_out = SOAP_ZLIB_NONE;
+  soap->d_stream->next_in = Z_NULL;
+  soap->d_stream->avail_in = 0;
+  soap->d_stream->next_out = (Byte*)soap->buf;
+  soap->d_stream->avail_out = SOAP_BUFLEN;
+  soap->z_ratio_in = 1.0;
+#endif
+#ifdef WITH_OPENSSL
+  if (soap->ssl)
+    ERR_clear_error();
+#endif
+#ifndef WITH_LEANER
+  if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
+    return soap->error;
+#endif
+  c = soap_getchar(soap);
+#ifdef WITH_GZIP
+  if (c == 0x1F)
+  { if (soap_getgziphdr(soap))
+      return soap->error;
+    if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
+      return soap->error = SOAP_ZLIB_ERROR;
+    if (soap->z_dict)
+    { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
+        return soap->error = SOAP_ZLIB_ERROR;
+    }
+    soap->zlib_state = SOAP_ZLIB_INFLATE;
+    soap->mode |= SOAP_ENC_ZLIB;
+    soap->zlib_in = SOAP_ZLIB_GZIP;
+    soap->z_crc = crc32(0L, NULL, 0);
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
+    if (!soap->z_buf)
+      soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
+    memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
+    /* should not chunk over plain transport, so why bother to check? */
+    /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
+    /*   soap->z_buflen = soap->bufidx; */
+    /* else */
+    soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
+    soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
+    soap->z_buflen = soap->buflen;
+    soap->buflen = soap->bufidx;
+    c = ' ';
+  }
+#endif
+  while (soap_blank(c))
+    c = soap_getchar(soap);
+#ifndef WITH_LEANER
+  if (c == '-' && soap_get0(soap) == '-')
+    soap->mode |= SOAP_ENC_MIME;
+  else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
+    soap->mode |= SOAP_ENC_DIME;
+  else
+#endif
+  { /* skip BOM */
+    if (c == 0xEF && soap_get0(soap) == 0xBB)
+    { c = soap_get1(soap);
+      if ((c = soap_get1(soap)) == 0xBF)
+      { soap->mode &= ~SOAP_ENC_LATIN;
+        c = soap_getchar(soap);
+      }
+      else
+        c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */
+    }
+    else if ((c == 0xFE && soap_get0(soap) == 0xFF)  /* UTF-16 BE */
+          || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
+      return soap->error = SOAP_UTF_ERROR;
+    /* skip space */
+    while (soap_blank(c))
+      c = soap_getchar(soap);
+  }
+  if ((int)c == EOF)
+    return soap->error = SOAP_CHK_EOF;
+  soap_unget(soap, c);
+#ifndef WITH_NOHTTP
+  /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
+  if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_XML)))
+  { soap_mode m = soap->imode;
+    soap->mode &= ~SOAP_IO;
+    soap->error = soap->fparse(soap);
+    if (soap->error && soap->error < SOAP_STOP)
+    { soap->keep_alive = 0; /* force close later */
+      return soap->error;
+    }
+    if (soap->error == SOAP_STOP)
+    { if (soap->fform)
+      { soap->error = soap->fform(soap);
+        if (soap->error == SOAP_OK)
+          soap->error = SOAP_STOP; /* prevents further processing */
+      }
+      return soap->error;
+    }
+    soap->mode = soap->imode; /* if imode is changed, effectuate */
+    soap->imode = m; /* restore imode */
+#ifdef WITH_ZLIB
+    soap->mode &= ~SOAP_ENC_ZLIB;
+#endif
+    if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
+    { soap->chunkbuflen = soap->buflen;
+      soap->buflen = soap->bufidx;
+      soap->chunksize = 0;
+    }
+    /* Note: fparse should not use soap_unget to push back last char */
+#if 0
+    if (soap->status > 200 && soap->length == 0 && !(soap->http_content && (!soap->keep_alive || soap->recv_timeout)) && (soap->imode & SOAP_IO) != SOAP_IO_CHUNK)
+#endif
+    if (soap->status && !soap->body)
+      return soap->error = soap->status;
+#ifdef WITH_ZLIB
+    if (soap->zlib_in != SOAP_ZLIB_NONE)
+    {
+#ifdef WITH_GZIP
+      if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
+      { c = soap_get1(soap);
+        if (c == (int)EOF)
+          return soap->error = SOAP_EOF;
+        if (c == 0x1F)
+        { if (soap_getgziphdr(soap))
+            return soap->error;
+          if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
+            return soap->error = SOAP_ZLIB_ERROR;
+          soap->z_crc = crc32(0L, NULL, 0);
+          DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
+        }
+        else
+        { soap_revget1(soap);
+          if (inflateInit(soap->d_stream) != Z_OK)
+            return soap->error = SOAP_ZLIB_ERROR;
+          soap->zlib_in = SOAP_ZLIB_DEFLATE;
+        }
+      }
+      else
+#endif
+      if (inflateInit(soap->d_stream) != Z_OK)
+        return soap->error = SOAP_ZLIB_ERROR;
+      if (soap->z_dict)
+      { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
+          return soap->error = SOAP_ZLIB_ERROR;
+      }
+      soap->zlib_state = SOAP_ZLIB_INFLATE;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
+      soap->mode |= SOAP_ENC_ZLIB;
+      if (!soap->z_buf)
+        soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
+      memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
+      soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
+      soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
+      soap->z_buflen = soap->buflen;
+      soap->buflen = soap->bufidx;
+    }
+#endif
+#ifndef WITH_LEANER
+    if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
+    { int r;
+      DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n"));
+      if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx)))
+        return soap->error = r;
+    }
+#endif
+    if (soap_get0(soap) == (int)EOF)
+    { if (soap->status == 0 || soap->status == 200)
+        return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */
+      return soap->error = soap->status;
+    }
+    if (soap->error)
+    { if (soap->error == SOAP_FORM && soap->fform)
+      { soap->error = soap->fform(soap);
+        if (soap->error == SOAP_OK)
+          soap->error = SOAP_STOP; /* prevents further processing */
+      }
+      return soap->error;
+    }
+  }
+#endif
+#ifndef WITH_LEANER
+  if (soap->mode & SOAP_ENC_MIME)
+  { do /* skip preamble */
+    { if ((int)(c = soap_getchar(soap)) == EOF)
+        return soap->error = SOAP_CHK_EOF;
+    } while (c != '-' || soap_get0(soap) != '-');
+    soap_unget(soap, c);
+    if (soap_getmimehdr(soap))
+      return soap->error;
+    if (soap->mime.start)
+    { do
+      { if (!soap->mime.last->id)
+          break;
+        if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
+          break;
+      } while (soap_get_mime_attachment(soap, NULL));
+    }
+    if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
+      soap->mode |= SOAP_ENC_DIME;
+  }
+  if (soap->mode & SOAP_ENC_DIME)
+  { if (soap_getdimehdr(soap))
+      return soap->error;
+    if (soap->dime.flags & SOAP_DIME_CF)
+    { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
+      soap->dime.chunksize = soap->dime.size;
+      if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
+      { soap->dime.buflen = soap->buflen;
+        soap->buflen = soap->bufidx + soap->dime.chunksize;
+      }
+      else
+        soap->dime.chunksize -= soap->buflen - soap->bufidx;
+    }
+    soap->count = soap->buflen - soap->bufidx;
+  }
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_begin_out(struct soap *soap)
+{
+#ifndef WITH_LEANER
+  size_t n = 0;
+  if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 )
+  { const char *s;
+    if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
+      s = "application/dime";
+    else if (soap->version == 2)
+    { if (soap->mode & SOAP_ENC_MTOM)
+        s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
+      else
+        s = "application/soap+xml; charset=utf-8";
+    }
+    else if (soap->mode & SOAP_ENC_MTOM)
+      s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
+    else
+      s = "text/xml; charset=utf-8";
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
+#else
+    sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
+#endif
+    n = strlen(soap->tmpbuf);
+    if (soap_send_raw(soap, soap->tmpbuf, n))
+      return soap->error;
+  }
+  if (soap->mode & SOAP_IO_LENGTH)
+    soap->dime.size = soap->count;	/* DIME in MIME correction */
+  if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
+  { if (soap_putdimehdr(soap))
+      return soap->error;
+  }
+#endif
+  if (soap->version == 0)
+    return SOAP_OK;
+  soap->part = SOAP_IN_ENVELOPE;
+  return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_end_out(struct soap *soap)
+{ if (soap->version == 0)
+    return SOAP_OK;
+  if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
+   || soap_send_raw(soap, "\r\n", 2))	/* 2.8: always emit \r\n */
+    return soap->error;
+#ifndef WITH_LEANER
+  if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
+  { soap->dime.size = soap->count - soap->dime.size;	/* DIME in MIME correction */
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->id, sizeof(soap->id), soap->dime_id_format, 0);
+#else
+    sprintf(soap->id, soap->dime_id_format, 0);
+#endif
+    soap->dime.id = soap->id;
+    if (soap->local_namespaces)
+    { if (soap->local_namespaces[0].out)
+        soap->dime.type = (char*)soap->local_namespaces[0].out;
+      else
+        soap->dime.type = (char*)soap->local_namespaces[0].ns;
+    }
+    soap->dime.options = NULL;
+    soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
+    if (!soap->dime.first)
+      soap->dime.flags |= SOAP_DIME_ME;
+    soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
+  }
+  if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
+    return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
+#endif
+  soap->part = SOAP_END_ENVELOPE;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+#ifndef PALM_1
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_get_http_body(struct soap *soap, size_t *len)
+{ if (len)
+    *len = 0;
+#ifndef WITH_LEAN
+  register size_t l = 0, n = 0;
+  register char *s;
+  /* get HTTP body length */
+  if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
+  { n = soap->length;
+    if (!n)
+      return NULL;
+  }
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Parsing HTTP body (mode=0x%x,len=%lu)\n", soap->mode, (unsigned long)n));
+#ifdef WITH_FAST
+  soap->labidx = 0;			/* use look-aside buffer */
+#else
+  if (soap_new_block(soap) == NULL)
+    return NULL;
+#endif
+  for (;;)
+  {
+#ifdef WITH_FAST
+    register size_t i, k;
+    if (soap_append_lab(soap, NULL, 0))	/* allocate more space in look-aside buffer if necessary */
+      return NULL;
+    s = soap->labbuf + soap->labidx;	/* space to populate */
+    k = soap->lablen - soap->labidx;	/* number of bytes available */
+    soap->labidx = soap->lablen;	/* claim this space */
+#else
+    register size_t i, k = SOAP_BLKLEN;
+    if (!(s = (char*)soap_push_block(soap, NULL, k)))
+      return NULL;
+#endif
+    for (i = 0; i < k; i++)
+    { register soap_wchar c;
+      l++;
+      if (n > 0 && l > n)
+        goto end;
+      c = soap_get1(soap);
+      if ((int)c == EOF)
+        goto end;
+      *s++ = (char)(c & 0xFF);
+    }
+  }
+end:
+  *s = '\0';
+  if (len)
+    *len = l - 1; /* len excludes terminating \0 */
+#ifdef WITH_FAST
+  if ((s = (char*)soap_malloc(soap, l)))
+    memcpy(s, soap->labbuf, l);
+#else
+  soap_size_block(soap, NULL, i+1);
+  s = soap_save_block(soap, NULL, 0);
+#endif
+  return s;
+#else
+  return NULL;
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_begin_in(struct soap *soap)
+{ register struct Namespace *p;
+  soap->part = SOAP_IN_ENVELOPE;
+  if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
+  { if (soap->error == SOAP_TAG_MISMATCH)
+    { if (!soap_element_begin_in(soap, "Envelope", 0, NULL))
+        soap->error = SOAP_VERSIONMISMATCH;
+      else if (soap->status == 0 || (soap->status >= 200 && soap->status <= 299))
+        return SOAP_OK; /* allow non-SOAP XML content to be captured */
+      soap->error = soap->status;
+    }
+    else if (soap->status)
+      soap->error = soap->status;
+    return soap->error;
+  }
+  p = soap->local_namespaces;
+  if (p)
+  { const char *ns = p[0].out;
+    if (!ns)
+      ns = p[0].ns;
+    if (!strcmp(ns, soap_env1))
+    { soap->version = 1; /* make sure we use SOAP 1.1 */
+      if (p[1].out)
+        SOAP_FREE(soap, p[1].out);
+      if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
+        strcpy(p[1].out, soap_enc1);
+    }
+    else if (!strcmp(ns, soap_env2))
+    { soap->version = 2; /* make sure we use SOAP 1.2 */
+      if (p[1].out)
+        SOAP_FREE(soap, p[1].out);
+      if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
+        strcpy(p[1].out, soap_enc2);
+    }
+  }
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_envelope_end_in(struct soap *soap)
+{ if (soap->version == 0)
+    return SOAP_OK;
+  soap->part = SOAP_END_ENVELOPE;
+  return soap_element_end_in(soap, "SOAP-ENV:Envelope");
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_begin_out(struct soap *soap)
+{ if (soap->version == 1)
+    soap->encoding = 1;
+#ifndef WITH_LEAN
+  if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
+    return soap->error;
+#endif
+  if (soap->version == 0)
+    return SOAP_OK;
+  soap->part = SOAP_IN_BODY;
+  return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_end_out(struct soap *soap)
+{ if (soap->version == 0)
+    return SOAP_OK;
+  if (soap_element_end_out(soap, "SOAP-ENV:Body"))
+    return soap->error;
+  soap->part = SOAP_END_BODY;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_begin_in(struct soap *soap)
+{ if (soap->version == 0)
+    return SOAP_OK;
+  soap->part = SOAP_IN_BODY;
+  if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
+    return soap->error;
+  if (!soap->body)
+    soap->part = SOAP_NO_BODY;
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_body_end_in(struct soap *soap)
+{ if (soap->version == 0)
+    return SOAP_OK;
+  if (soap->part == SOAP_NO_BODY)
+    return soap->error = SOAP_OK;
+  soap->part = SOAP_END_BODY;
+  return soap_element_end_in(soap, "SOAP-ENV:Body");
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv_header(struct soap *soap)
+{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
+    soap->error = SOAP_OK;
+  if (soap->error == SOAP_OK && soap->fheader)
+    soap->error = soap->fheader(soap);
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_endpoint(struct soap *soap, const char *endpoint)
+{ register const char *s;
+  register size_t i, n;
+  soap->endpoint[0] = '\0';
+  soap->host[0] = '\0';
+  soap->path[0] = '/';
+  soap->path[1] = '\0';
+  soap->port = 80;
+  if (!endpoint || !*endpoint)
+    return;
+#ifdef WITH_OPENSSL
+  if (!soap_tag_cmp(endpoint, "https:*"))
+    soap->port = 443;
+#endif
+  strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint));
+  soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
+  s = strchr(endpoint, ':');
+  if (s && s[1] == '/' && s[2] == '/')
+    s += 3;
+  else
+    s = endpoint;
+  n = strlen(s);
+  if (n >= sizeof(soap->host))
+    n = sizeof(soap->host) - 1;
+#ifdef WITH_IPV6
+  if (s[0] == '[')
+  { s++;
+    for (i = 0; i < n; i++)
+    { if (s[i] == ']')
+      { s++;
+        --n;
+        break;
+      }
+      soap->host[i] = s[i];
+    }
+  }
+  else
+  { for (i = 0; i < n; i++)
+    { soap->host[i] = s[i];
+      if (s[i] == '/' || s[i] == ':')
+        break;
+    }
+  }
+#else
+  for (i = 0; i < n; i++)
+  { soap->host[i] = s[i];
+    if (s[i] == '/' || s[i] == ':')
+      break;
+  }
+#endif
+  soap->host[i] = '\0';
+  if (s[i] == ':')
+  { soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
+    for (i++; i < n; i++)
+      if (s[i] == '/')
+        break;
+  }
+  if (i < n && s[i])
+  { strncpy(soap->path, s + i, sizeof(soap->path));
+    soap->path[sizeof(soap->path) - 1] = '\0';
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_connect(struct soap *soap, const char *endpoint, const char *action)
+{ return soap_connect_command(soap, SOAP_POST, endpoint, action);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
+{ char *endpoint;
+  const char *s;
+  if (endpoints && (s = strchr(endpoints, ' ')))
+  { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1);
+    for (;;)
+    { strncpy(endpoint, endpoints, s - endpoints);
+      endpoint[s - endpoints] = '\0';
+      if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
+        break;
+      if (!*s)
+        break;
+      soap->error = SOAP_OK;
+      while (*s == ' ')
+        s++;
+      endpoints = s;
+      s = strchr(endpoints, ' ');
+      if (!s)
+        s = endpoints + strlen(endpoints);
+    }
+    SOAP_FREE(soap, endpoint);
+  }
+  else
+    soap_try_connect_command(soap, http_command, endpoints, action);
+  return soap->error;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static int
+soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
+{ char host[sizeof(soap->host)];
+  int port;
+  size_t count;
+  soap->error = SOAP_OK;
+  strcpy(host, soap->host); /* save previous host name: if != then reconnect */
+  port = soap->port; /* save previous port to compare */
+  soap->status = http_command;
+  soap_set_endpoint(soap, endpoint);
+#ifndef WITH_LEANER
+  if (soap->fconnect)
+  { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
+      return soap->error;
+  }
+  else
+#endif
+  soap->action = soap_strdup(soap, action);
+  if (soap->fopen && *soap->host)
+  { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
+    { soap->error = SOAP_OK;
+#ifndef WITH_LEAN
+      if (!strncmp(endpoint, "soap.udp:", 9))
+        soap->omode |= SOAP_IO_UDP;
+      else
+#endif
+      { soap->keep_alive = 0; /* to force close */
+        soap->omode &= ~SOAP_IO_UDP; /* to force close */
+      }
+      soap_closesock(soap);
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint?endpoint:"(null)", soap->host, soap->path, soap->port));
+      if (!soap->keep_alive || !soap_valid_socket(soap->socket))
+      { soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
+        if (soap->error)
+          return soap->error;
+        soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
+      }
+    }
+  }
+#ifdef WITH_NTLM
+  if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port))
+    return soap->error;
+#endif
+  count = soap_count_attachments(soap);
+  if (soap_begin_send(soap))
+    return soap->error;
+  if (http_command == SOAP_GET)
+  { soap->mode &= ~SOAP_IO;
+    soap->mode |= SOAP_IO_BUFFER;
+  }
+#ifndef WITH_NOHTTP
+  if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
+  { unsigned int k = soap->mode;
+    soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
+    if ((k & SOAP_IO) != SOAP_IO_FLUSH)
+      soap->mode |= SOAP_IO_BUFFER;
+    if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
+      return soap->error;
+#ifndef WITH_LEANER
+    if ((k & SOAP_IO) == SOAP_IO_CHUNK)
+    { if (soap_flush(soap))
+        return soap->error;
+    }
+#endif
+    soap->mode = k;
+  }
+  if (http_command == SOAP_GET || http_command == SOAP_DEL)
+    return soap_end_send_flush(soap);
+#endif
+  return SOAP_OK;
+}
+#endif
+
+/******************************************************************************/
+#ifdef WITH_NTLM
+#ifndef PALM_1
+static int
+soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port)
+{ /* requires libntlm from http://www.nongnu.org/libntlm/ */
+  const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid);
+  const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd);
+  struct SOAP_ENV__Header *oldheader;
+  if (soap->ntlm_challenge && userid && passwd && soap->authrealm)
+  { tSmbNtlmAuthRequest req;  
+    tSmbNtlmAuthResponse res;
+    tSmbNtlmAuthChallenge ch;
+    short k = soap->keep_alive;
+    size_t l = soap->length;
+    size_t c = soap->count;
+    soap_mode m = soap->mode, o = soap->omode;
+    int s = soap->status;
+    char *a = soap->action;
+    short v = soap->version;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge));
+    if (!*soap->ntlm_challenge)
+    { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
+      /* S -> C   401 Unauthorized
+                  WWW-Authenticate: NTLM
+      */
+      buildSmbNtlmAuthRequest(&req, userid, soap->authrealm);
+      soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&req, NULL, SmbLength(&req));
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
+      /* C -> S   GET ...
+                  Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
+      */
+      soap->omode = SOAP_IO_BUFFER;
+      if (soap_begin_send(soap))
+        return soap->error;
+      soap->keep_alive = 1;
+      soap->status = command;
+      if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0)
+       || soap_end_send_flush(soap))
+        return soap->error;
+      soap->mode = m;
+      soap->keep_alive = k;
+      DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n"));
+      oldheader = soap->header;
+      if (soap_begin_recv(soap))
+        if (soap->error == SOAP_EOF)
+          return soap->error;
+      soap_end_recv(soap);
+      soap->header = oldheader;
+      soap->length = l;
+      if (soap->status != 401 && soap->status != 407)
+        return soap->error = SOAP_NTLM_ERROR;
+      soap->error = SOAP_OK;
+    }
+    /* S -> C   401 Unauthorized
+                WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
+    */
+    soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL);
+    buildSmbNtlmAuthResponse(&ch, &res, userid, passwd);
+    soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&res, NULL, SmbLength(&res));
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
+    /* C -> S   GET ...
+                Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
+    */
+    soap->userid = NULL;
+    soap->passwd = NULL;
+    soap->proxy_userid = NULL;
+    soap->proxy_passwd = NULL;
+    soap->keep_alive = k;
+    soap->length = l;
+    soap->count = c;
+    soap->mode = m;
+    soap->omode = o;
+    soap->status = s;
+    soap->action = a;
+    soap->version = v;
+  }
+  return SOAP_OK;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
+{ register int i;
+  register unsigned long m;
+  register char *p;
+  if (!t)
+    t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
+  if (!t)
+    return NULL;
+  p = t;
+  t[0] = '\0';
+  if (!s)
+    return p;
+  for (; n > 2; n -= 3, s += 3)
+  { m = s[0];
+    m = (m << 8) | s[1];
+    m = (m << 8) | s[2];
+    for (i = 4; i > 0; m >>= 6)
+      t[--i] = soap_base64o[m & 0x3F];
+    t += 4;
+  }
+  t[0] = '\0';
+  if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
+  { m = 0;
+    for (i = 0; i < n; i++)
+      m = (m << 8) | *s++;
+    for (; i < 3; i++)
+      m <<= 8;
+    for (i = 4; i > 0; m >>= 6)
+      t[--i] = soap_base64o[m & 0x3F];
+    for (i = 3; i > n; i--)
+      t[i] = '=';
+    t[4] = '\0';
+  }
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
+{ register size_t i, j;
+  register soap_wchar c;
+  register unsigned long m;
+  register const char *p;
+  if (!s || !*s)
+  { if (n)
+      *n = 0;
+    if (soap->error)
+      return NULL;
+    return SOAP_NON_NULL;
+  }
+  if (!t)
+  { l = (strlen(s) + 3) / 4 * 3 + 1;	/* make sure enough space for \0 */
+    t = (char*)soap_malloc(soap, l);
+  }
+  if (!t)
+    return NULL;
+  p = t;
+  if (n)
+    *n = 0;
+  for (i = 0; ; i += 3, l -= 3)
+  { m = 0;
+    j = 0;
+    while (j < 4)
+    { c = *s++;
+      if (c == '=' || !c)
+      { if (l >= j - 1)
+        { switch (j)
+          { case 2:
+              *t++ = (char)((m >> 4) & 0xFF);
+              i++;
+              l--;
+              break;
+            case 3:
+              *t++ = (char)((m >> 10) & 0xFF);
+              *t++ = (char)((m >> 2) & 0xFF);
+              i += 2;
+              l -= 2;
+          }
+        }
+        if (n)
+          *n = (int)i;
+        if (l)
+          *t = '\0';
+        return p;
+      }
+      c -= '+';
+      if (c >= 0 && c <= 79)
+      { int b = soap_base64i[c];
+        if (b >= 64)
+        { soap->error = SOAP_TYPE;
+          return NULL;
+        }
+        m = (m << 6) + b;
+        j++;
+      }
+      else if (!soap_blank(c + '+'))
+      { soap->error = SOAP_TYPE;
+        return NULL;
+      }
+    }
+    if (l < 3)
+    { if (n)
+        *n = (int)i;
+      if (l)
+        *t = '\0';
+      return p;
+    }
+    *t++ = (char)((m >> 16) & 0xFF);
+    *t++ = (char)((m >> 8) & 0xFF);
+    *t++ = (char)(m & 0xFF);
+  }
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
+{ register char *p;
+  if (!t)
+    t = (char*)soap_malloc(soap, 2 * n + 1);
+  if (!t)
+    return NULL;
+  p = t;
+  t[0] = '\0';
+  if (s)
+  { for (; n > 0; n--)
+    { register int m = *s++;
+      *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
+      m &= 0x0F;
+      *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
+    }
+  }
+  *t++ = '\0';
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
+{ register const char *p;
+  if (!s || !*s)
+  { if (n)
+      *n = 0;
+    if (soap->error)
+      return NULL;
+    return SOAP_NON_NULL;
+  }
+  if (!t)
+  { l = strlen(s) / 2 + 1;	/* make sure enough space for \0 */
+    t = (char*)soap_malloc(soap, l);
+  }
+  if (!t)
+    return NULL;
+  p = t;
+  while (l)
+  { register int d1, d2;
+    d1 = *s++;
+    if (!d1)
+      break;
+    d2 = *s++;
+    if (!d2)
+      break;
+    *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
+    l--;
+  }
+  if (n)
+    *n = (int)(t - p);
+  if (l)
+    *t = '\0';
+  return p;
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_puthttphdr(struct soap *soap, int status, size_t count)
+{ if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT)
+  { register const char *s = "text/xml; charset=utf-8";
+    register int err = SOAP_OK;
+#ifndef WITH_LEANER
+    register const char *r = NULL;
+#endif
+    if ((status == SOAP_FILE || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE) && soap->http_content && !strchr(s, 10) && !strchr(s, 13))
+      s = soap->http_content;
+    else if (status == SOAP_HTML)
+      s = "text/html; charset=utf-8";
+    else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
+    { if (soap->version == 2)
+        s = "application/soap+xml; charset=utf-8";
+    }
+#ifndef WITH_LEANER
+    if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
+    { if (soap->mode & SOAP_ENC_MTOM)
+      { if (soap->version == 2)
+          r = "application/soap+xml";
+        else
+          r = "text/xml";
+        s = "application/xop+xml";
+      }
+      else
+        s = "application/dime";
+    }
+    if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80)
+    { register const char *t;
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
+#else
+      sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
+#endif
+      t = strchr(s, ';');
+      if (t)
+        strncat(soap->tmpbuf, s, t - s);
+      else
+        strcat(soap->tmpbuf, s);
+      if (soap->mime.start && strlen(soap->tmpbuf) + strlen(soap->mime.start) + 11 < sizeof(soap->tmpbuf))
+      { strcat(soap->tmpbuf, "\"; start=\"");
+        strcat(soap->tmpbuf, soap->mime.start);
+      }
+      strcat(soap->tmpbuf, "\"");
+      if (r && strlen(soap->tmpbuf) + strlen(r) + 15 < sizeof(soap->tmpbuf))
+      { strcat(soap->tmpbuf, "; start-info=\"");
+        strcat(soap->tmpbuf, r);
+        strcat(soap->tmpbuf, "\"");
+      }
+    }
+    else
+      strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
+    soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
+    s = soap->tmpbuf;
+    if (status == SOAP_OK && soap->version == 2 && soap->action && strlen(soap->action) + strlen(s) < sizeof(soap->tmpbuf) - 80)
+    {
+#ifdef HAVE_SNPRINTF
+      size_t l = strlen(s);
+      soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "; action=\"%s\"", soap->action);
+#else
+      sprintf(soap->tmpbuf + strlen(s), "; action=\"%s\"", soap->action);
+#endif
+    }
+#endif
+    if ((err = soap->fposthdr(soap, "Content-Type", s)))
+      return err;
+#ifdef WITH_ZLIB
+    if ((soap->omode & SOAP_ENC_ZLIB))
+    {
+#ifdef WITH_GZIP
+      err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
+#else
+      err = soap->fposthdr(soap, "Content-Encoding", "deflate");
+#endif
+      if (err)
+        return err;
+    }
+#endif
+#ifndef WITH_LEANER
+    if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
+      err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
+    else
+#endif
+    if (s)
+    {
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", (unsigned long)count);
+#else
+      sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
+#endif
+      err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
+    }
+    if (err)
+      return err;
+  }
+  return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+static const char*
+soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
+{ if (!t)
+    t = SOAP_STR_EOS;
+  if (*soap->tag)
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s in element '%s'", s, t ? t : SOAP_STR_EOS, soap->tag);
+#else
+    if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
+      sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag);
+    else
+      sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
+#endif
+  }
+  else
+  {
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s", s, t ? t : SOAP_STR_EOS);
+#else
+    if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
+      sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t);
+    else
+      sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
+#endif
+  }
+  return soap->msgbuf;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_fault(struct soap *soap)
+{ const char **c = soap_faultcode(soap);
+  const char **s = soap_faultstring(soap);
+  if (soap->fseterror)
+    soap->fseterror(soap, c, s);
+  if (!*c)
+  { if (soap->version == 2)
+      *c = "SOAP-ENV:Sender";
+    else
+      *c = "SOAP-ENV:Client";
+  }
+  if (*s)
+    return;
+  switch (soap->error)
+  {
+#ifndef WITH_LEAN
+    case SOAP_CLI_FAULT:
+      *s = "Client fault";
+      break;
+    case SOAP_SVR_FAULT:
+      *s = "Server fault";
+      break;
+    case SOAP_TAG_MISMATCH:
+      *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
+      break;
+    case SOAP_TYPE:
+      *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
+      break;
+    case SOAP_SYNTAX_ERROR:
+      *s = "Well-formedness violation";
+      break;
+    case SOAP_NO_TAG:
+      *s = "No tag: no XML root element or missing SOAP message body element";
+      break;
+    case SOAP_MUSTUNDERSTAND:
+      *c = "SOAP-ENV:MustUnderstand";
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "The data in element '%s' must be understood but cannot be handled", soap->tag);
+#else
+      strncpy(soap->msgbuf, soap->tag, sizeof(soap->msgbuf));
+      soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
+#endif
+      *s = soap->msgbuf;
+      break;
+    case SOAP_VERSIONMISMATCH:
+      *c = "SOAP-ENV:VersionMismatch";
+      *s = "Invalid SOAP message or SOAP version mismatch";
+      break;
+    case SOAP_DATAENCODINGUNKNOWN:
+      *c = "SOAP-ENV:DataEncodingUnknown";
+      *s = "Unsupported SOAP data encoding";
+      break;
+    case SOAP_NAMESPACE:
+      *s = soap_set_validation_fault(soap, "namespace error", NULL);
+      break;
+    case SOAP_USER_ERROR:
+      *s = "User data error";
+      break;
+    case SOAP_FATAL_ERROR:
+      *s = "Fatal error";
+      break;
+    case SOAP_NO_METHOD:
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
+#else
+      sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
+#endif
+      *s = soap->msgbuf;
+      break;
+    case SOAP_NO_DATA:
+      *s = "Data required for operation";
+      break;
+    case SOAP_GET_METHOD:
+      *s = "HTTP GET method not implemented";
+      break;
+    case SOAP_PUT_METHOD:
+      *s = "HTTP PUT method not implemented";
+      break;
+    case SOAP_HTTP_METHOD:
+      *s = "HTTP method not implemented";
+      break;
+    case SOAP_EOM:
+      *s = "Out of memory";
+      break;
+    case SOAP_MOE:
+      *s = "Memory overflow or memory corruption error";
+      break;
+    case SOAP_HDR:
+      *s = "Header line too long";
+      break;
+    case SOAP_IOB:
+      *s = "Array index out of bounds";
+      break;
+    case SOAP_NULL:
+      *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
+      break;
+    case SOAP_DUPLICATE_ID:
+      *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id);
+      if (soap->version == 2)
+        *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
+      break;
+    case SOAP_MISSING_ID:
+      *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
+      if (soap->version == 2)
+        *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
+      break;
+    case SOAP_HREF:
+      *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id);
+      break;
+    case SOAP_FAULT:
+      break;
+#ifndef WITH_NOIO
+    case SOAP_UDP_ERROR:
+      *s = "Message too large for UDP packet";
+      break;
+    case SOAP_TCP_ERROR:
+      *s = tcp_error(soap);
+      break;
+#endif
+    case SOAP_HTTP_ERROR:
+      *s = "An HTTP processing error occurred";
+      break;
+    case SOAP_NTLM_ERROR:
+      *s = "An HTTP NTLM authentication error occurred";
+      break;
+    case SOAP_SSL_ERROR:
+#ifdef WITH_OPENSSL
+      *s = "SSL/TLS error";
+#else
+      *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
+#endif
+      break;
+    case SOAP_PLUGIN_ERROR:
+      *s = "Plugin registry error";
+      break;
+    case SOAP_DIME_ERROR:
+      *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE";
+      break;
+    case SOAP_DIME_HREF:
+      *s = "DIME href to missing attachment";
+      break;
+    case SOAP_DIME_MISMATCH:
+      *s = "DIME version/transmission error";
+      break;
+    case SOAP_DIME_END:
+      *s = "End of DIME error";
+      break;
+    case SOAP_MIME_ERROR:
+      *s = "MIME format error";
+      break;
+    case SOAP_MIME_HREF:
+      *s = "MIME href to missing attachment";
+      break;
+    case SOAP_MIME_END:
+      *s = "End of MIME error";
+      break;
+    case SOAP_ZLIB_ERROR:
+#ifdef WITH_ZLIB
+#ifdef HAVE_SNPRINTF
+      soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
+#else
+      sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
+#endif
+      *s = soap->msgbuf;
+#else
+      *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
+#endif
+      break;
+    case SOAP_REQUIRED:
+      *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
+      break;
+    case SOAP_PROHIBITED:
+      *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
+      break;
+    case SOAP_OCCURS:
+      *s = soap_set_validation_fault(soap, "occurrence violation", NULL);
+      break;
+    case SOAP_LENGTH:
+      *s = soap_set_validation_fault(soap, "content range or length violation", NULL);
+      break;
+    case SOAP_FD_EXCEEDED:
+      *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
+      break;
+    case SOAP_UTF_ERROR:
+      *s = "UTF content encoding error";
+      break;
+    case SOAP_STOP:
+      *s = "Stopped: no response sent or received (informative)";
+      break;
+#endif
+    case SOAP_EOF:
+#ifndef WITH_NOIO
+      *s = soap_strerror(soap); /* *s = soap->msgbuf */
+#ifndef WITH_LEAN
+      if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
+      { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
+        memcpy(soap->msgbuf, "End of file or no input: ", 25);
+      }
+#endif
+      break;
+#else
+      *s = "End of file or no input";
+      break;
+#endif
+    default:
+#ifndef WITH_NOHTTP
+#ifndef WITH_LEAN
+      if (soap->error > 200 && soap->error < 600)
+      { 
+#ifdef HAVE_SNPRINTF
+        soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
+#else
+        sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
+#endif
+        *s = soap->msgbuf;
+      }
+      else
+#endif
+#endif
+      {
+#ifdef HAVE_SNPRINTF
+        soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error %d", soap->error);
+#else
+        sprintf(soap->msgbuf, "Error %d", soap->error);
+#endif
+        *s = soap->msgbuf;
+      }
+    }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send_fault(struct soap *soap)
+{ register int status = soap->error;
+  if (status == SOAP_OK || status == SOAP_STOP)
+    return soap_closesock(soap);
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
+  soap->keep_alive = 0; /* to terminate connection */
+  soap_set_fault(soap);
+  if (soap->error < 200 && soap->error != SOAP_FAULT)
+    soap->header = NULL;
+  if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
+  { register int r = 1;
+#ifndef WITH_NOIO
+    if (soap->fpoll && soap->fpoll(soap))
+      r = 0;
+#ifndef WITH_LEAN
+    else if (soap_valid_socket(soap->socket))
+    { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
+      if (r > 0)
+      { int t;
+        if (!(r & SOAP_TCP_SELECT_SND)
+         || ((r & SOAP_TCP_SELECT_RCV)
+          && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0))
+          r = 0;
+      }
+    }
+#endif
+#endif
+    if (r > 0)
+    { soap->error = SOAP_OK;
+      soap->encodingStyle = NULL; /* no encodingStyle in Faults */
+      soap_serializeheader(soap);
+      soap_serializefault(soap);
+      soap_begin_count(soap);
+      if (soap->mode & SOAP_IO_LENGTH)
+      { soap_envelope_begin_out(soap);
+        soap_putheader(soap);
+        soap_body_begin_out(soap);
+        soap_putfault(soap);
+        soap_body_end_out(soap);
+        soap_envelope_end_out(soap);
+      }
+      soap_end_count(soap);
+      if (soap_response(soap, status)
+       || soap_envelope_begin_out(soap)
+       || soap_putheader(soap)
+       || soap_body_begin_out(soap)
+       || soap_putfault(soap)
+       || soap_body_end_out(soap)
+       || soap_envelope_end_out(soap))
+        return soap_closesock(soap);
+      soap_end_send(soap);
+    }
+  }
+  soap->error = status;
+  return soap_closesock(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv_fault(struct soap *soap, int check)
+{ register int status = soap->error;
+  DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n"));
+  if (!check)
+  { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
+    if (soap->error != SOAP_NO_TAG
+     && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
+      return soap->error;
+  }
+  else if (soap->version == 0) /* check == 1 but no SOAP: do not parse SOAP Fault */
+    return SOAP_OK;
+  soap->error = SOAP_OK;
+  if (soap_getfault(soap))
+  { /* check flag set: check if SOAP Fault is present, if not just return */
+    if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
+      return soap->error = SOAP_OK;
+    DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed at level %u tag '%s'\n", soap->level, soap->tag));
+    *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
+    soap->error = status;
+    soap_set_fault(soap);
+  }
+  else
+  { register const char *s = *soap_faultcode(soap);
+    if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
+      status = SOAP_SVR_FAULT;
+    else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
+      status = SOAP_CLI_FAULT;
+    else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
+      status = SOAP_MUSTUNDERSTAND;
+    else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
+      status = SOAP_VERSIONMISMATCH;
+    else
+    { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
+      status = SOAP_FAULT;
+    }
+    if (!soap_body_end_in(soap))
+      soap_envelope_end_in(soap);
+  }
+  soap_end_recv(soap);
+  soap->error = status;
+  return soap_closesock(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_send_empty_response(struct soap *soap, int httpstatuscode)
+{ register soap_mode m = soap->omode;
+  if (!(m & SOAP_IO_UDP))
+  { soap->count = 0;
+    if ((m & SOAP_IO) == SOAP_IO_CHUNK)
+      soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
+    soap_response(soap, httpstatuscode);
+    soap_end_send(soap); /* force end of sends */
+    soap->error = SOAP_STOP; /* stops the server (from returning a response) */
+    soap->omode = m;
+  }
+  return soap_closesock(soap);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOHTTP
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_recv_empty_response(struct soap *soap)
+{ if (!(soap->omode & SOAP_IO_UDP))
+  { if (!soap_begin_recv(soap))
+    {
+#ifndef WITH_LEAN
+      if (soap->body)
+        soap_get_http_body(soap, NULL); /* read (empty?) HTTP body and discard */
+#endif
+      soap_end_recv(soap);
+    }
+    else if (soap->error == SOAP_NO_DATA || soap->error == 202)
+      soap->error = SOAP_OK;
+  }
+  return soap_closesock(soap);
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_NOIO
+#ifndef PALM_1
+static const char*
+soap_strerror(struct soap *soap)
+{ register int err = soap->errnum;
+  *soap->msgbuf = '\0';
+  if (err)
+  {
+#ifndef WIN32
+# ifdef HAVE_STRERROR_R
+#  ifdef _GNU_SOURCE
+    return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */
+#  else
+    strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */
+#  endif
+# else
+    return strerror(err);
+# endif
+#else
+#ifndef UNDER_CE
+    DWORD len;
+    *soap->msgbuf = '\0';
+    len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL);
+#else
+    DWORD i, len;
+    *soap->msgbuf = '\0';
+    len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
+    for (i = 0; i <= len; i++)
+    { if (((TCHAR*)soap->msgbuf)[i] < 0x80)
+        soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
+      else
+        soap->msgbuf[i] = '?';
+    }
+#endif
+#endif
+  }
+  else
+  { char *s = soap->msgbuf;
+#ifndef WITH_LEAN
+    int rt = soap->recv_timeout, st = soap->send_timeout;
+    int ru = ' ', su = ' ';
+#endif
+    strcpy(s, "Operation interrupted or timed out");
+#ifndef WITH_LEAN
+    if (rt < 0)
+    { rt = -rt;
+      ru = 'u';
+    }
+    if (st < 0)
+    { st = -st;
+      su = 'u';
+    }
+    if (rt)
+    {
+#ifdef HAVE_SNPRINTF
+      size_t l = strlen(s);
+      soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs recv delay)", rt, ru);
+#else
+      sprintf(s + strlen(s), " (%d%cs recv delay)", rt, ru);
+#endif
+    }
+    if (st)
+    {
+#ifdef HAVE_SNPRINTF
+      size_t l = strlen(s);
+      soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs send delay)", st, su);
+#else
+      sprintf(s + strlen(s), " (%d%cs send delay)", st, su);
+#endif
+    }
+#endif
+  }
+  return soap->msgbuf;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static int
+soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
+{ *soap_faultcode(soap) = faultcode;
+  if (faultsubcodeQName)
+    *soap_faultsubcode(soap) = faultsubcodeQName;
+  *soap_faultstring(soap) = faultstring;
+  if (faultdetailXML && *faultdetailXML)
+  { register const char **s = soap_faultdetail(soap);
+    if (s)
+      *s = faultdetailXML;
+  }
+  return soap->error = soaperror;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
+{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
+{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+static int
+soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
+{ char *r = NULL, *s = NULL, *t = NULL;
+  if (faultsubcodeQName)
+    r = soap_strdup(soap, faultsubcodeQName);
+  if (faultstring)
+    s = soap_strdup(soap, faultstring);
+  if (faultdetailXML)
+    t = soap_strdup(soap, faultdetailXML);
+  return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
+{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
+{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
+{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
+{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+#ifndef WITH_NOSTDLIB
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_print_fault(struct soap *soap, FILE *fd)
+{ if (soap_check_state(soap))
+    fprintf(fd, "Error: soap struct state not initialized\n");
+  else if (soap->error)
+  { const char **c, *v = NULL, *s, *d;
+    c = soap_faultcode(soap);
+    if (!*c)
+      soap_set_fault(soap);
+    if (soap->version == 2)
+      v = soap_check_faultsubcode(soap);
+    s = *soap_faultstring(soap);
+    d = soap_check_faultdetail(soap);
+    fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
+  }
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifdef __cplusplus
+#ifndef WITH_LEAN
+#ifndef WITH_NOSTDLIB
+#ifndef WITH_COMPAT
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_stream_fault(struct soap *soap, std::ostream& os)
+{ if (soap_check_state(soap))
+    os << "Error: soap struct state not initialized\n";
+  else if (soap->error)
+  { const char **c, *v = NULL, *s, *d;
+    c = soap_faultcode(soap);
+    if (!*c)
+      soap_set_fault(soap);
+    if (soap->version == 2)
+      v = soap_check_faultsubcode(soap);
+    s = *soap_faultstring(soap);
+    d = soap_check_faultdetail(soap);
+    os << (soap->version ? "SOAP 1." : "Error ")
+       << (soap->version ? (int)soap->version : soap->error)
+       << " fault: " << *c
+       << "[" << (v ? v : "no subcode") << "]"
+       << std::endl
+       << "\"" << (s ? s : "[no reason]") << "\""
+       << std::endl
+       << "Detail: " << (d ? d : "[no detail]")
+       << std::endl;
+  }
+}
+#endif
+#endif
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef WITH_LEAN
+#ifndef WITH_NOSTDLIB
+SOAP_FMAC1
+char*
+SOAP_FMAC2
+soap_sprint_fault(struct soap *soap, char *buf, size_t len)
+{ if (soap_check_state(soap))
+  { strncpy(buf, "Error: soap struct not initialized", len);
+    buf[len - 1] = '\0';
+  }
+  else if (soap->error)
+  { const char **c, *v = NULL, *s, *d;
+    c = soap_faultcode(soap);
+    if (!*c)
+      soap_set_fault(soap);
+    if (soap->version == 2)
+      v = *soap_faultsubcode(soap);
+    s = *soap_faultstring(soap);
+    d = soap_check_faultdetail(soap);
+#ifdef HAVE_SNPRINTF
+    soap_snprintf(buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
+#else
+    if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d ? strlen(d) : 0))
+      sprintf(buf, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
+    else if (len > 40)
+      sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c);
+    else
+      buf[0] = '\0';
+#endif
+  }
+  return buf;
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+#ifndef WITH_NOSTDLIB
+SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_print_fault_location(struct soap *soap, FILE *fd)
+{
+#ifndef WITH_LEAN
+  int i, j, c1, c2;
+  if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN)
+  { i = (int)soap->bufidx - 1;
+    if (i <= 0)
+      i = 0;
+    c1 = soap->buf[i];
+    soap->buf[i] = '\0';
+    if ((int)soap->buflen >= i + 1024)
+      j = i + 1023;
+    else
+      j = (int)soap->buflen - 1;
+    c2 = soap->buf[j];
+    soap->buf[j] = '\0';
+    fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
+    if (soap->bufidx < soap->buflen)
+      fprintf(fd, "%s\n", soap->buf + soap->bufidx);
+    soap->buf[i] = (char)c1;
+    soap->buf[j] = (char)c2;
+  }
+#endif
+}
+#endif
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
+{ register struct soap_plugin *p;
+  register int r;
+  if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
+    return soap->error = SOAP_EOM;
+  p->id = NULL;
+  p->data = NULL;
+  p->fcopy = NULL;
+  p->fdelete = NULL;
+  r = fcreate(soap, p, arg);
+  if (!r && p->fdelete)
+  { p->next = soap->plugins;
+    soap->plugins = p;
+    DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
+    return SOAP_OK;
+  }
+  DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id ? p->id : "?", r));
+  SOAP_FREE(soap, p);
+  return r;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+static void *
+fplugin(struct soap *soap, const char *id)
+{ register struct soap_plugin *p;
+  for (p = soap->plugins; p; p = p->next)
+    if (p->id == id || !strcmp(p->id, id))
+      return p->data;
+  return NULL;
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_2
+SOAP_FMAC1
+void *
+SOAP_FMAC2
+soap_lookup_plugin(struct soap *soap, const char *id)
+{ return soap->fplugin(soap, id);
+}
+#endif
+
+/******************************************************************************/
+#ifdef __cplusplus
+}
+#endif
+
+/******************************************************************************\
+ *
+ *	C++ soap struct methods
+ *
+\******************************************************************************/
+
+#ifdef __cplusplus
+soap::soap()
+{ soap_init(this);
+}
+#endif
+
+/******************************************************************************/
+#ifdef __cplusplus
+soap::soap(soap_mode m)
+{ soap_init1(this, m);
+}
+#endif
+
+/******************************************************************************/
+#ifdef __cplusplus
+soap::soap(soap_mode im, soap_mode om)
+{ soap_init2(this, im, om);
+}
+#endif
+
+/******************************************************************************/
+#ifdef __cplusplus
+soap::soap(const struct soap& soap)
+{ soap_copy_context(this, &soap);
+}
+#endif
+
+/******************************************************************************/
+#ifdef __cplusplus
+soap::~soap()
+{ soap_destroy(this);
+  soap_end(this);
+  soap_done(this);
+}
+#endif
+
+/******************************************************************************/