Main Page | Namespace List | Class Hierarchy | Data Structures | File List | Data Fields | Globals | Related Pages

stdsoap2.cpp

Go to the documentation of this file.
00001 /*
00002 
00003 stdsoap2.c[pp] 2.7.8c
00004 
00005 gSOAP runtime
00006 
00007 gSOAP XML Web services tools
00008 Copyright (C) 2000-2006, Robert van Engelen, Genivia Inc., All Rights Reserved.
00009 This part of the software is released under one of the following licenses:
00010 GPL, the gSOAP public license, or Genivia's license for commercial use.
00011 --------------------------------------------------------------------------------
00012 Contributors:
00013 
00014 Wind River Systems Inc., for the following additions under gSOAP public license:
00015   - vxWorks compatible  (#define VXWORKS)
00016 --------------------------------------------------------------------------------
00017 gSOAP public license.
00018 
00019 The contents of this file are subject to the gSOAP Public License Version 1.3
00020 (the "License"); you may not use this file except in compliance with the
00021 License. You may obtain a copy of the License at
00022 http://www.cs.fsu.edu/~engelen/soaplicense.html
00023 Software distributed under the License is distributed on an "AS IS" basis,
00024 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00025 for the specific language governing rights and limitations under the License.
00026 
00027 The Initial Developer of the Original Code is Robert A. van Engelen.
00028 Copyright (C) 2000-2006, Robert van Engelen, Genivia Inc., All Rights Reserved.
00029 --------------------------------------------------------------------------------
00030 GPL license.
00031 
00032 This program is free software; you can redistribute it and/or modify it under
00033 the terms of the GNU General Public License as published by the Free Software
00034 Foundation; either version 2 of the License, or (at your option) any later
00035 version.
00036 
00037 This program is distributed in the hope that it will be useful, but WITHOUT ANY
00038 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
00039 PARTICULAR PURPOSE. See the GNU General Public License for more details.
00040 
00041 You should have received a copy of the GNU General Public License along with
00042 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00043 Place, Suite 330, Boston, MA 02111-1307 USA
00044 
00045 Author contact information:
00046 engelen@genivia.com / engelen@acm.org
00047 --------------------------------------------------------------------------------
00048 A commercial use license is available from Genivia, Inc., contact@genivia.com
00049 --------------------------------------------------------------------------------
00050 
00051 Installation note:
00052 
00053 Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
00054 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
00055 tab (the project file needs to be selected in the file view) and add
00056 "wsock32.lib" to the "Object/library modules" entry
00057 
00058 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
00059 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
00060 when locally allocated data exceeds 64K.
00061 
00062 */
00063 
00064 #ifdef AS400
00065 # pragma convert(819)   /* EBCDIC to ASCII */
00066 #endif
00067 
00068 #include "stdsoap2.h"
00069 
00070 #ifdef __cplusplus
00071 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.8c 2006-06-24 12:00:00 GMT")
00072 extern "C" {
00073 #else
00074 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.8c 2006-06-24 12:00:00 GMT")
00075 #endif
00076 
00077 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
00078 #ifndef SOAP_UNKNOWN_CHAR
00079 #define SOAP_UNKNOWN_CHAR (127)
00080 #endif
00081 
00082 /*      EOF=-1 */
00083 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
00084 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
00085 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
00086 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
00087 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
00088 
00089 #define soap_blank(c)           ((c) >= 0 && (c) <= 32)
00090 #define soap_notblank(c)        ((c) > 32)
00091 #define soap_hash_ptr(p)        (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1))
00092 
00093 #ifdef SOAP_DEBUG
00094 static void soap_init_logs(struct soap*);
00095 static void soap_close_logfile(struct soap*, int);
00096 static void soap_set_logfile(struct soap*, int, const char*);
00097 static void soap_free_mht(struct soap*);
00098 static void soap_track_unlink(struct soap*, const void*);
00099 #endif
00100 
00101 #ifndef PALM_2
00102 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
00103 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
00104 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
00105 #endif
00106 
00107 #ifndef PALM_1
00108 static soap_wchar soap_char(struct soap*);
00109 static soap_wchar soap_get_pi(struct soap*);
00110 static int soap_isxdigit(int);
00111 static void *fplugin(struct soap*, const char*);
00112 #ifndef WITH_NOIDREF
00113 static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
00114 static int soap_has_copies(struct soap*, const char*, const char*);
00115 static void soap_init_iht(struct soap*);
00116 static void soap_free_iht(struct soap*);
00117 static void soap_init_pht(struct soap*);
00118 static void soap_free_pht(struct soap*);
00119 #endif
00120 #endif
00121 
00122 #ifndef WITH_LEAN
00123 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
00124 static int soap_isnumeric(struct soap*, const char*);
00125 static time_t soap_timegm(struct tm*);
00126 static struct soap_nlist *soap_lookup_ns(struct soap *soap, const char *tag, size_t n);
00127 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
00128 static void soap_pop_ns(struct soap *soap);
00129 static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
00130 #endif
00131 
00132 #ifndef WITH_LEANER
00133 #ifndef PALM_1
00134 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
00135 static int soap_putdimefield(struct soap*, const char*, size_t);
00136 static char *soap_getdimefield(struct soap*, size_t);
00137 static void soap_select_mime_boundary(struct soap*);
00138 static int soap_valid_mime_boundary(struct soap*);
00139 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
00140 #endif
00141 #endif
00142 
00143 #ifdef WITH_GZIP
00144 static int soap_getgziphdr(struct soap*);
00145 #endif
00146 
00147 #ifdef WITH_OPENSSL
00148 static int ssl_init_done = 0;
00149 static int ssl_auth_init(struct soap*);
00150 static int ssl_verify_callback(int, X509_STORE_CTX*);
00151 static int ssl_password(char*, int, int, void *);
00152 /* This callback is included for future references. It should not be deleted
00153 static DH *ssl_tmp_dh(SSL*, int, int);
00154 */
00155 #endif
00156 
00157 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
00158 #ifndef PALM_1
00159 static const char *soap_decode(char*, size_t, const char*, const char*);
00160 #endif
00161 #endif
00162 
00163 #ifndef WITH_NOHTTP
00164 #ifndef PALM_1
00165 static soap_wchar soap_getchunkchar(struct soap*);
00166 static const char *http_error(struct soap*, int);
00167 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
00168 static int http_get(struct soap*);
00169 static int http_send_header(struct soap*, const char*);
00170 static int http_post_header(struct soap*, const char*, const char*);
00171 static int http_response(struct soap*, int, size_t);
00172 static int http_parse(struct soap*);
00173 static int http_parse_header(struct soap*, const char*, const char*);
00174 #endif
00175 #endif
00176 
00177 #ifndef WITH_NOIO
00178 #ifndef PALM_1
00179 static int fsend(struct soap*, const char*, size_t);
00180 static size_t frecv(struct soap*, char*, size_t);
00181 static int tcp_init(struct soap*);
00182 static const char *tcp_error(struct soap*);
00183 #ifndef WITH_IPV6
00184 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
00185 #endif
00186 static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
00187 static int tcp_accept(struct soap*, int, struct sockaddr*, int*);
00188 static int tcp_disconnect(struct soap*);
00189 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
00190 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
00191 static const char *soap_strerror(struct soap*);
00192 #endif
00193 #endif
00194 
00195 #if defined(PALM) && !defined(PALM_2)
00196 unsigned short errno;
00197 #endif
00198 
00199 #ifndef PALM_1
00200 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
00201 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
00202 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
00203 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
00204 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
00205 #endif
00206 
00207 #ifndef PALM_1
00208 const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
00209 static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00210 static 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";
00211 #endif
00212 
00213 #ifndef WITH_LEAN
00214 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
00215 /* Alternative indentation form for SOAP_XML_INDENT:
00216 static const char soap_indent[21] = "\n                   ";
00217 */
00218 #endif
00219 
00220 #ifndef SOAP_CANARY
00221 # define SOAP_CANARY (0xC0DE)
00222 #endif
00223 
00224 static const char soap_padding[4] = "\0\0\0";
00225 #define SOAP_STR_PADDING (soap_padding)
00226 #define SOAP_STR_EOS (soap_padding)
00227 #define SOAP_NON_NULL (soap_padding)
00228 
00229 #ifndef WITH_LEAN
00230 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
00231 { { 160, "nbsp" },
00232   { 161, "iexcl" },
00233   { 162, "cent" },
00234   { 163, "pound" },
00235   { 164, "curren" },
00236   { 165, "yen" },
00237   { 166, "brvbar" },
00238   { 167, "sect" },
00239   { 168, "uml" },
00240   { 169, "copy" },
00241   { 170, "ordf" },
00242   { 171, "laquo" },
00243   { 172, "not" },
00244   { 173, "shy" },
00245   { 174, "reg" },
00246   { 175, "macr" },
00247   { 176, "deg" },
00248   { 177, "plusmn" },
00249   { 178, "sup2" },
00250   { 179, "sup3" },
00251   { 180, "acute" },
00252   { 181, "micro" },
00253   { 182, "para" },
00254   { 183, "middot" },
00255   { 184, "cedil" },
00256   { 185, "sup1" },
00257   { 186, "ordm" },
00258   { 187, "raquo" },
00259   { 188, "frac14" },
00260   { 189, "frac12" },
00261   { 190, "frac34" },
00262   { 191, "iquest" },
00263   { 192, "Agrave" },
00264   { 193, "Aacute" },
00265   { 194, "Acirc" },
00266   { 195, "Atilde" },
00267   { 196, "Auml" },
00268   { 197, "Aring" },
00269   { 198, "AElig" },
00270   { 199, "Ccedil" },
00271   { 200, "Egrave" },
00272   { 201, "Eacute" },
00273   { 202, "Ecirc" },
00274   { 203, "Euml" },
00275   { 204, "Igrave" },
00276   { 205, "Iacute" },
00277   { 206, "Icirc" },
00278   { 207, "Iuml" },
00279   { 208, "ETH" },
00280   { 209, "Ntilde" },
00281   { 210, "Ograve" },
00282   { 211, "Oacute" },
00283   { 212, "Ocirc" },
00284   { 213, "Otilde" },
00285   { 214, "Ouml" },
00286   { 215, "times" },
00287   { 216, "Oslash" },
00288   { 217, "Ugrave" },
00289   { 218, "Uacute" },
00290   { 219, "Ucirc" },
00291   { 220, "Uuml" },
00292   { 221, "Yacute" },
00293   { 222, "THORN" },
00294   { 223, "szlig" },
00295   { 224, "agrave" },
00296   { 225, "aacute" },
00297   { 226, "acirc" },
00298   { 227, "atilde" },
00299   { 228, "auml" },
00300   { 229, "aring" },
00301   { 230, "aelig" },
00302   { 231, "ccedil" },
00303   { 232, "egrave" },
00304   { 233, "eacute" },
00305   { 234, "ecirc" },
00306   { 235, "euml" },
00307   { 236, "igrave" },
00308   { 237, "iacute" },
00309   { 238, "icirc" },
00310   { 239, "iuml" },
00311   { 240, "eth" },
00312   { 241, "ntilde" },
00313   { 242, "ograve" },
00314   { 243, "oacute" },
00315   { 244, "ocirc" },
00316   { 245, "otilde" },
00317   { 246, "ouml" },
00318   { 247, "divide" },
00319   { 248, "oslash" },
00320   { 249, "ugrave" },
00321   { 250, "uacute" },
00322   { 251, "ucirc" },
00323   { 252, "uuml" },
00324   { 253, "yacute" },
00325   { 254, "thorn" },
00326   { 255, "yuml" },
00327   {   0, NULL }
00328 };
00329 #endif
00330 
00331 #ifndef WITH_NOIO
00332 #ifndef WITH_LEAN
00333 static const struct soap_code_map h_error_codes[] =
00334 {
00335 #ifdef HOST_NOT_FOUND   
00336   { HOST_NOT_FOUND, "Host not found" },
00337 #endif
00338 #ifdef TRY_AGAIN
00339   { TRY_AGAIN, "Try Again" },
00340 #endif
00341 #ifdef NO_RECOVERY  
00342   { NO_RECOVERY, "No Recovery" },
00343 #endif
00344 #ifdef NO_DATA
00345   { NO_DATA, "No Data" },
00346 #endif
00347 #ifdef NO_ADDRESS
00348   { NO_ADDRESS, "No Address" },
00349 #endif
00350   { 0, NULL }
00351 };
00352 #endif
00353 #endif
00354 
00355 #ifndef WITH_NOHTTP
00356 #ifndef WITH_LEAN
00357 static const struct soap_code_map h_http_error_codes[] =
00358 { { 200, "OK" },
00359   { 201, "Created" },
00360   { 202, "Accepted" },
00361   { 203, "Non-Authoritative Information" },
00362   { 204, "No Content" },
00363   { 205, "Reset Content" },
00364   { 206, "Partial Content" },
00365   { 300, "Multiple Choices" },
00366   { 301, "Moved Permanently" },
00367   { 302, "Found" },
00368   { 303, "See Other" },
00369   { 304, "Not Modified" },
00370   { 305, "Use Proxy" },
00371   { 307, "Temporary Redirect" },
00372   { 400, "Bad Request" },
00373   { 401, "Unauthorized" },
00374   { 402, "Payment Required" },
00375   { 403, "Forbidden" },
00376   { 404, "Not Found" },
00377   { 405, "Method Not Allowed" },
00378   { 406, "Not Acceptable" },
00379   { 407, "Proxy Authentication Required" },
00380   { 408, "Request Time-out" },
00381   { 409, "Conflict" },
00382   { 410, "Gone" },
00383   { 411, "Length Required" },
00384   { 412, "Precondition Failed" },
00385   { 413, "Request Entity Too Large" },
00386   { 414, "Request-URI Too Large" },
00387   { 415, "Unsupported Media Type" },
00388   { 416, "Requested range not satisfiable" },
00389   { 417, "Expectation Failed" },
00390   { 500, "Internal Server Error" },
00391   { 501, "Not Implemented" },
00392   { 502, "Bad Gateway" },
00393   { 503, "Service Unavailable" },
00394   { 504, "Gateway Time-out" },
00395   { 505, "HTTP Version not supported" },
00396   {   0, NULL }
00397 };
00398 #endif
00399 #endif
00400 
00401 #ifdef WITH_OPENSSL
00402 static const struct soap_code_map h_ssl_error_codes[] =
00403 {
00404 #define _SSL_ERROR(e) { e, #e }
00405   _SSL_ERROR(SSL_ERROR_SSL),
00406   _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
00407   _SSL_ERROR(SSL_ERROR_WANT_READ),
00408   _SSL_ERROR(SSL_ERROR_WANT_WRITE),
00409   _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
00410   _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
00411   _SSL_ERROR(SSL_ERROR_SYSCALL),
00412   { 0, NULL }
00413 };
00414 #endif
00415 
00416 #ifndef WITH_LEANER
00417 static const struct soap_code_map mime_codes[] =
00418 { { SOAP_MIME_7BIT,             "7bit" },
00419   { SOAP_MIME_8BIT,             "8bit" },
00420   { SOAP_MIME_BINARY,           "binary" },
00421   { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
00422   { SOAP_MIME_BASE64,           "base64" },
00423   { SOAP_MIME_IETF_TOKEN,       "ietf-token" },
00424   { SOAP_MIME_X_TOKEN,          "x-token" },
00425   { 0,                          NULL }
00426 };
00427 #endif
00428 
00429 #ifdef WIN32
00430 static int tcp_done = 0;
00431 #endif
00432 
00433 /******************************************************************************/
00434 #ifndef WITH_NOIO
00435 #ifndef PALM_1
00436 static int
00437 fsend(struct soap *soap, const char *s, size_t n)
00438 { register int nwritten;
00439 #if defined(__cplusplus) && !defined(WITH_LEAN)
00440   if (soap->os)
00441   { soap->os->write(s, n);
00442     if (soap->os->good())
00443       return SOAP_OK;
00444     return SOAP_EOF;
00445   }
00446 #endif
00447   while (n)
00448   { if (soap_valid_socket(soap->socket))
00449     { 
00450 #ifndef WITH_LEAN
00451       if (soap->send_timeout)
00452       { struct timeval timeout;
00453         fd_set fd;
00454         if (soap->send_timeout > 0)
00455         { timeout.tv_sec = soap->send_timeout;
00456           timeout.tv_usec = 0;
00457         }
00458         else
00459         { timeout.tv_sec = -soap->send_timeout/1000000;
00460           timeout.tv_usec = -soap->send_timeout%1000000;
00461         }
00462 #ifndef WIN32
00463         if ((int)soap->socket > FD_SETSIZE)
00464           return SOAP_FD_EXCEEDED;      /* Hint: MUST increase FD_SETSIZE */
00465 #endif
00466         FD_ZERO(&fd);
00467         FD_SET((SOAP_SOCKET)soap->socket, &fd);
00468         for (;;)
00469         { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout);
00470           if (r > 0)
00471             break;
00472           if (!r)
00473           { soap->errnum = 0;
00474             return SOAP_EOF;
00475           }
00476           if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
00477           { soap->errnum = soap_socket_errno;
00478             return SOAP_EOF;
00479           }
00480         }
00481       }
00482 #endif
00483 #ifdef WITH_OPENSSL
00484       if (soap->ssl)
00485         nwritten = SSL_write(soap->ssl, s, n);
00486       else if (soap->bio)
00487         nwritten = BIO_write(soap->bio, s, n);
00488       else
00489 #endif
00490 #ifdef WITH_UDP
00491       if ((soap->omode & SOAP_IO_UDP))
00492       { if (soap->peerlen)
00493           nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
00494         else
00495           nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
00496         /* retry and back-off algorithm */
00497         /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
00498         if (nwritten < 0)
00499         { struct timeval timeout;
00500           fd_set fd;
00501           int udp_repeat;
00502           int udp_delay;
00503 #ifndef WIN32
00504           if ((int)soap->socket > FD_SETSIZE)
00505             return SOAP_FD_EXCEEDED;    /* Hint: MUST increase FD_SETSIZE */
00506 #endif
00507           if ((soap->connect_flags & SO_BROADCAST))
00508             udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
00509           else
00510             udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
00511           udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
00512           do
00513           { timeout.tv_sec = 0;
00514             timeout.tv_usec = 1000 * udp_delay; /* ms */
00515             FD_ZERO(&fd);
00516             FD_SET((SOAP_SOCKET)soap->socket, &fd);
00517             select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout);
00518             if (soap->peerlen)
00519               nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
00520             else
00521               nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
00522             udp_delay <<= 1;
00523             if (udp_delay > 500) /* UDP_UPPER_DELAY */
00524               udp_delay = 500;
00525           }
00526           while (nwritten < 0 && --udp_repeat > 0);
00527         }
00528       }
00529       else
00530 #endif
00531 #if !defined(PALM) && !defined(AS400)
00532         nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
00533 #else
00534         nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags);
00535 #endif
00536       if (nwritten <= 0)
00537       {
00538 #ifdef WITH_OPENSSL
00539         int err;
00540         if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
00541           return SOAP_EOF;
00542 #endif
00543         if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN)
00544         { soap->errnum = soap_socket_errno;
00545           return SOAP_EOF;
00546         }
00547         nwritten = 0; /* and call write() again */
00548       }
00549     }
00550     else
00551     {
00552 #ifdef WITH_FASTCGI
00553       nwritten = fwrite((void*)s, 1, n, stdout);
00554       fflush(stdout);
00555 #else
00556 #ifdef UNDER_CE
00557       nwritten = fwrite(s, 1, n, soap->sendfd);
00558 #else
00559 #ifdef VXWORKS
00560 #ifdef WMW_RPM_IO
00561       if (soap->rpmreqid)
00562         nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; 
00563       else
00564 #endif
00565         nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
00566 #else
00567       nwritten = write((SOAP_SOCKET)soap->sendfd, s, n);
00568 #endif
00569 #endif
00570 #endif
00571       if (nwritten <= 0)
00572       { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN)
00573         { soap->errnum = soap_errno;
00574           return SOAP_EOF;
00575         }
00576         nwritten = 0; /* and call write() again */
00577       }
00578     }
00579     n -= nwritten;
00580     s += nwritten;
00581   }
00582   return SOAP_OK;
00583 }
00584 #endif
00585 #endif
00586 
00587 /******************************************************************************/
00588 #ifndef PALM_1
00589 SOAP_FMAC1
00590 int
00591 SOAP_FMAC2
00592 soap_send_raw(struct soap *soap, const char *s, size_t n)
00593 { if (!n)
00594     return SOAP_OK;
00595   if (soap->mode & SOAP_IO_LENGTH)
00596   { soap->count += n;
00597 #ifndef WITH_LEANER
00598     if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
00599       return soap->error = soap->fpreparesend(soap, s, n);
00600 #endif
00601     return SOAP_OK;
00602   }
00603   if (soap->mode & SOAP_IO)
00604   { register size_t i = SOAP_BUFLEN - soap->bufidx;
00605     while (n >= i)
00606     { memcpy(soap->buf + soap->bufidx, s, i);
00607       soap->bufidx = SOAP_BUFLEN;
00608       if (soap_flush(soap))
00609         return soap->error;
00610       s += i;
00611       n -= i;
00612       i = SOAP_BUFLEN;
00613     }
00614     memcpy(soap->buf + soap->bufidx, s, n);
00615     soap->bufidx += n;
00616     return SOAP_OK;
00617   }
00618   return soap_flush_raw(soap, s, n);
00619 }
00620 #endif
00621 
00622 /******************************************************************************/
00623 #ifndef PALM_1
00624 SOAP_FMAC1
00625 int
00626 SOAP_FMAC2
00627 soap_flush(struct soap *soap)
00628 { register int n = soap->bufidx;
00629   if (n)
00630   { soap->bufidx = 0;
00631 #ifdef WITH_ZLIB
00632     if (soap->mode & SOAP_ENC_ZLIB)
00633     { soap->d_stream.next_in = (Byte*)soap->buf;
00634       soap->d_stream.avail_in = (unsigned int)n;
00635 #ifdef WITH_GZIP
00636       soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
00637 #endif
00638       do
00639       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in));
00640         if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK)
00641         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
00642           return soap->error = SOAP_ZLIB_ERROR;
00643         }
00644         if (!soap->d_stream.avail_out)
00645         { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
00646             return soap->error;
00647           soap->d_stream.next_out = (Byte*)soap->z_buf;
00648           soap->d_stream.avail_out = SOAP_BUFLEN;
00649         }
00650       } while (soap->d_stream.avail_in);
00651     }
00652     else
00653 #endif
00654       return soap_flush_raw(soap, soap->buf, n);
00655   }
00656   return SOAP_OK;
00657 }
00658 #endif
00659 
00660 /******************************************************************************/
00661 #ifndef PALM_1
00662 SOAP_FMAC1
00663 int
00664 SOAP_FMAC2
00665 soap_flush_raw(struct soap *soap, const char *s, size_t n)
00666 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
00667   { register char *t;
00668     if (!(t = (char*)soap_push_block(soap, n)))
00669       return soap->error = SOAP_EOM;
00670     memcpy(t, s, n);
00671 #ifndef WITH_LEANER
00672     if (soap->fpreparesend)
00673       return soap->error = soap->fpreparesend(soap, s, n);
00674 #endif
00675     return SOAP_OK;
00676   }
00677 #ifndef WITH_LEANER
00678   if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
00679   { char t[16];
00680     sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
00681     DBGMSG(SENT, t, strlen(t));
00682     if ((soap->error = soap->fsend(soap, t, strlen(t))))
00683       return soap->error;
00684     soap->chunksize += n;
00685   }
00686   DBGMSG(SENT, s, n);
00687 #endif
00688   return soap->error = soap->fsend(soap, s, n);
00689 }
00690 #endif
00691 
00692 /******************************************************************************/
00693 #ifndef PALM_1
00694 SOAP_FMAC1
00695 int
00696 SOAP_FMAC2
00697 soap_send(struct soap *soap, const char *s)
00698 { if (s)
00699     return soap_send_raw(soap, s, strlen(s));
00700   return SOAP_OK;
00701 }
00702 #endif
00703 
00704 /******************************************************************************/
00705 #ifndef WITH_LEANER
00706 #ifndef PALM_1
00707 SOAP_FMAC1
00708 int
00709 SOAP_FMAC2
00710 soap_send2(struct soap *soap, const char *s1, const char *s2)
00711 { if (soap_send(soap, s1))
00712     return soap->error;
00713   return soap_send(soap, s2);
00714 }
00715 #endif
00716 #endif
00717 
00718 /******************************************************************************/
00719 #ifndef WITH_LEANER
00720 #ifndef PALM_1
00721 SOAP_FMAC1
00722 int
00723 SOAP_FMAC2
00724 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
00725 { if (soap_send(soap, s1)
00726    || soap_send(soap, s2))
00727     return soap->error;
00728   return soap_send(soap, s3);
00729 }
00730 #endif
00731 #endif
00732 
00733 /******************************************************************************/
00734 #ifndef WITH_NOIO
00735 #ifndef PALM_1
00736 static size_t
00737 frecv(struct soap *soap, char *s, size_t n)
00738 { register int r;
00739 #ifdef PALM
00740   register int timeouts = 0;  
00741 #endif
00742   soap->errnum = 0;
00743 #if defined(__cplusplus) && !defined(WITH_LEAN)
00744   if (soap->is)
00745   { if (soap->is->good())
00746       return soap->is->read(s, n).gcount();
00747     return 0;
00748   }
00749 #endif
00750   if (soap_valid_socket(soap->socket))
00751   { for (;;)
00752     { 
00753 #ifndef WITH_LEAN
00754       if (soap->recv_timeout)
00755       { struct timeval timeout;
00756         fd_set fd;
00757         if (soap->recv_timeout > 0)
00758         { timeout.tv_sec = soap->recv_timeout;
00759           timeout.tv_usec = 0;
00760         }
00761         else
00762         { timeout.tv_sec = -soap->recv_timeout/1000000;
00763           timeout.tv_usec = -soap->recv_timeout%1000000;
00764         }
00765 #ifndef WIN32
00766         if ((int)soap->socket > FD_SETSIZE)
00767         { soap->error = SOAP_FD_EXCEEDED;
00768           return 0;     /* Hint: MUST increase FD_SETSIZE */
00769         }
00770 #endif
00771         FD_ZERO(&fd);
00772         FD_SET((SOAP_SOCKET)soap->socket, &fd);
00773         for (;;)
00774         { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
00775           if (r > 0)
00776             break;
00777           if (!r)
00778           { soap->errnum = 0;
00779             return 0;
00780           }
00781           if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
00782           { soap->errnum = soap_socket_errno;
00783             return 0;
00784           }
00785         }
00786       }
00787 #endif
00788 #ifdef WITH_OPENSSL
00789       if (soap->ssl)
00790       { int err;
00791         r = SSL_read(soap->ssl, s, n);
00792         if (r > 0)
00793           return (size_t)r;
00794         err = SSL_get_error(soap->ssl, r);
00795         if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
00796           return 0;
00797       }
00798       else if (soap->bio)
00799       { r = BIO_read(soap->bio, s, n);
00800         if (r > 0)
00801           return (size_t)r;
00802         return 0;
00803       }
00804       else
00805 #endif
00806       { 
00807 #ifdef WITH_UDP
00808         if ((soap->omode & SOAP_IO_UDP))
00809         { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
00810           memset((void*)&soap->peer, 0, sizeof(soap->peer));
00811           r = recvfrom((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
00812           soap->peerlen = (size_t)k;
00813 #ifndef WITH_IPV6
00814           soap->ip = ntohl(soap->peer.sin_addr.s_addr);
00815 #endif
00816         }
00817         else
00818 #endif
00819           r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
00820 #ifdef PALM
00821         /* CycleSyncDisplay(curStatusMsg); */
00822 #endif
00823         if (r >= 0)
00824           return (size_t)r;
00825         if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN && soap_socket_errno != SOAP_EWOULDBLOCK)
00826         { soap->errnum = soap_socket_errno;
00827           return 0;
00828         }
00829       }
00830 #ifndef WITH_LEAN
00831       { struct timeval timeout;
00832         fd_set fd;
00833         timeout.tv_sec = 0;
00834         timeout.tv_usec = 10000;
00835 #ifndef WIN32
00836         if ((int)soap->socket > FD_SETSIZE)
00837         { soap->error = SOAP_FD_EXCEEDED;
00838           return 0;     /* Hint: MUST increase FD_SETSIZE */
00839         }
00840 #endif
00841         FD_ZERO(&fd);
00842         FD_SET((SOAP_SOCKET)soap->socket, &fd);
00843 #ifdef WITH_OPENSSL
00844         if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE)
00845           r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout);
00846         else
00847           r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
00848 #else
00849         r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
00850 #endif
00851         if (r < 0 && soap_socket_errno != SOAP_EINTR)
00852         { soap->errnum = soap_socket_errno;
00853           return 0;
00854         }
00855       }
00856 #endif
00857 #ifdef PALM
00858       if (r < 0 && soap_socket_errno == SOAP_EINTR)
00859       { timeouts++;
00860         if (timeouts > 10)
00861         { soap->errnum = soap_socket_errno;
00862           return 0;
00863         }
00864       }
00865 #endif
00866     }
00867   }
00868 #ifdef WITH_FASTCGI
00869   return fread(s, 1, n, stdin);
00870 #else
00871 #ifdef UNDER_CE
00872   return fread(s, 1, n, soap->recvfd);
00873 #else
00874 #ifdef WMW_RPM_IO
00875   if (soap->rpmreqid)
00876     r = httpBlockRead(soap->rpmreqid, s, n);
00877   else
00878 #endif
00879   r = read((SOAP_SOCKET)soap->recvfd, s, n);
00880   if (r >= 0)
00881     return (size_t)r;
00882   soap->errnum = soap_errno;
00883   return 0;
00884 #endif
00885 #endif
00886 }
00887 #endif
00888 #endif
00889 
00890 /******************************************************************************/
00891 #ifndef WITH_NOHTTP
00892 #ifndef PALM_1
00893 static soap_wchar
00894 soap_getchunkchar(struct soap *soap)
00895 { if (soap->bufidx < soap->buflen)
00896     return soap->buf[soap->bufidx++];
00897   soap->bufidx = 0;
00898   soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
00899   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket));
00900   DBGMSG(RECV, soap->buf, soap->buflen);
00901   if (soap->buflen)
00902     return soap->buf[soap->bufidx++];
00903   return EOF;
00904 }
00905 #endif
00906 #endif
00907 
00908 /******************************************************************************/
00909 #ifndef PALM_1
00910 static int
00911 soap_isxdigit(int c)
00912 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
00913 }
00914 #endif
00915 
00916 /******************************************************************************/
00917 #ifndef PALM_1
00918 SOAP_FMAC1
00919 int
00920 SOAP_FMAC2
00921 soap_recv_raw(struct soap *soap)
00922 { register size_t ret;
00923 #ifdef WITH_ZLIB
00924   if (soap->mode & SOAP_ENC_ZLIB)
00925   { if (soap->d_stream.next_out == Z_NULL)
00926       return EOF;
00927     if (soap->d_stream.avail_in || !soap->d_stream.avail_out)
00928     { register int r;
00929       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
00930       soap->d_stream.next_out = (Byte*)soap->buf;
00931       soap->d_stream.avail_out = SOAP_BUFLEN;
00932       r = inflate(&soap->d_stream, Z_NO_FLUSH);
00933       if (r == Z_OK || r == Z_STREAM_END)
00934       { soap->bufidx = 0;
00935         soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out;
00936         if (soap->zlib_in == SOAP_ZLIB_GZIP)
00937           soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
00938         if (r == Z_STREAM_END)
00939         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
00940           soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
00941           soap->d_stream.next_out = Z_NULL;
00942         }
00943         if (soap->buflen)
00944         { soap->count += soap->buflen;
00945           return SOAP_OK;
00946         }
00947       }
00948       else if (r != Z_BUF_ERROR)
00949       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
00950         soap->d_stream.next_out = Z_NULL;
00951         soap->error = SOAP_ZLIB_ERROR;
00952         return EOF;
00953       }
00954     }
00955 zlib_again:
00956     if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
00957     { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
00958       soap->buflen = soap->z_buflen;
00959     }
00960   }
00961 #endif
00962 #ifndef WITH_NOHTTP
00963   if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
00964   { 
00965 chunk_again:
00966     if (soap->chunksize)
00967     { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
00968       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
00969       DBGMSG(RECV, soap->buf, ret);
00970       soap->bufidx = 0;
00971       soap->chunksize -= ret;
00972     }
00973     else
00974     { register soap_wchar c;
00975       char *t, tmp[8];
00976       t = tmp;
00977       if (!soap->chunkbuflen)
00978       { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
00979         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
00980         DBGMSG(RECV, soap->buf, ret);
00981         soap->bufidx = 0;
00982         if (!ret)
00983           return soap->ahead = EOF;
00984       }
00985       else
00986         soap->bufidx = soap->buflen;
00987       soap->buflen = soap->chunkbuflen;
00988       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
00989       while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
00990         if ((int)c == EOF)
00991           return soap->ahead = EOF;
00992       do
00993         *t++ = (char)c;
00994       while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
00995       while ((int)c != EOF && c != '\n')
00996         c = soap_getchunkchar(soap);
00997       if ((int)c == EOF)
00998         return soap->ahead = EOF;
00999       *t = '\0';
01000       soap->chunksize = soap_strtoul(tmp, &t, 16);
01001       if (!soap->chunksize)
01002       { soap->chunkbuflen = 0;
01003         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
01004         while ((int)c != EOF && c != '\n')
01005           c = soap_getchunkchar(soap);
01006         return soap->ahead = EOF;
01007       }
01008       soap->buflen = soap->bufidx + soap->chunksize;
01009       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
01010       if (soap->buflen > soap->chunkbuflen)
01011       { soap->buflen = soap->chunkbuflen;
01012         soap->chunksize -= soap->buflen - soap->bufidx;
01013         soap->chunkbuflen = 0;
01014         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
01015       }
01016       else if (soap->chunkbuflen)
01017         soap->chunksize = 0;
01018       ret = soap->buflen - soap->bufidx;
01019       if (!ret)
01020         goto chunk_again;
01021     }
01022   }
01023   else
01024 #endif
01025   { soap->bufidx = 0;
01026     soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
01027     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket));
01028     DBGMSG(RECV, soap->buf, ret);
01029   }
01030 #ifndef WITH_LEANER
01031   if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret)))
01032     return soap->error;
01033 #endif
01034 #ifdef WITH_ZLIB
01035   if (soap->mode & SOAP_ENC_ZLIB)
01036   { register int r;
01037     memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
01038     soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
01039     soap->d_stream.avail_in = (unsigned int)ret;
01040     soap->d_stream.next_out = (Byte*)soap->buf;
01041     soap->d_stream.avail_out = SOAP_BUFLEN;
01042     r = inflate(&soap->d_stream, Z_NO_FLUSH);
01043     if (r == Z_OK || r == Z_STREAM_END)
01044     { soap->bufidx = 0;
01045       soap->z_buflen = soap->buflen;
01046       soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out;
01047       if (soap->zlib_in == SOAP_ZLIB_GZIP)
01048         soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
01049       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret));
01050       if (!ret)
01051         goto zlib_again;
01052       if (r == Z_STREAM_END)
01053       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
01054         soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
01055         soap->d_stream.next_out = Z_NULL;
01056       }
01057     }
01058     else
01059     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:""));
01060       soap->d_stream.next_out = Z_NULL;
01061       soap->error = SOAP_ZLIB_ERROR;
01062       return EOF;
01063     }
01064   }
01065 #endif
01066   soap->count += ret;
01067   return !ret;
01068 }
01069 #endif
01070 
01071 /******************************************************************************/
01072 #ifndef PALM_1
01073 SOAP_FMAC1
01074 int
01075 SOAP_FMAC2
01076 soap_recv(struct soap *soap)
01077 { 
01078 #ifndef WITH_LEANER
01079   if (soap->mode & SOAP_ENC_DIME)
01080   { if (soap->dime.buflen)
01081     { char *s;
01082       int i;
01083       unsigned char tmp[12];
01084       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
01085       soap->count += soap->dime.buflen - soap->buflen;
01086       soap->buflen = soap->dime.buflen;
01087       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
01088       for (i = -(long)soap->dime.size&3; i > 0; i--)
01089       { soap->bufidx++;
01090         if (soap->bufidx >= soap->buflen)
01091           if (soap_recv_raw(soap))
01092             return EOF;
01093       }
01094       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
01095       s = (char*)tmp;
01096       for (i = 12; i > 0; i--)
01097       { *s++ = soap->buf[soap->bufidx++];
01098         if (soap->bufidx >= soap->buflen)
01099           if (soap_recv_raw(soap))
01100             return EOF;
01101       }
01102       soap->dime.flags = tmp[0] & 0x7;
01103       soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
01104       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
01105       if (soap->dime.flags & SOAP_DIME_CF)
01106       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
01107         soap->dime.chunksize = soap->dime.size;
01108         if (soap->buflen - soap->bufidx >= soap->dime.size)
01109         { soap->dime.buflen = soap->buflen;
01110           soap->buflen = soap->bufidx + soap->dime.chunksize;
01111         }
01112         else
01113           soap->dime.chunksize -= soap->buflen - soap->bufidx;
01114       }
01115       else
01116       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
01117         soap->dime.buflen = 0;
01118         soap->dime.chunksize = 0;
01119       }
01120       soap->count = soap->buflen - soap->bufidx;
01121       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
01122       return SOAP_OK;
01123     }
01124     if (soap->dime.chunksize)
01125     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
01126       if (soap_recv_raw(soap))
01127         return EOF;
01128       if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
01129       { soap->dime.buflen = soap->buflen;
01130         soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
01131         soap->buflen = soap->bufidx + soap->dime.chunksize;
01132       }
01133       else
01134         soap->dime.chunksize -= soap->buflen - soap->bufidx;
01135       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count));
01136       return SOAP_OK;
01137     }
01138   }
01139 #endif
01140   return soap_recv_raw(soap);
01141 }
01142 #endif
01143 
01144 /******************************************************************************/
01145 #ifndef PALM_1
01146 SOAP_FMAC1
01147 soap_wchar
01148 SOAP_FMAC2
01149 soap_getchar(struct soap *soap)
01150 { register soap_wchar c;
01151   c = soap->ahead;
01152   if (c)
01153   { if (c != EOF)
01154       soap->ahead = 0;
01155     return c;
01156   }
01157   return soap_get1(soap);
01158 }
01159 #endif
01160 
01161 /******************************************************************************/
01162 #ifndef PALM_1
01163 SOAP_FMAC1
01164 const struct soap_code_map*
01165 SOAP_FMAC2
01166 soap_code(const struct soap_code_map *map, const char *str)
01167 { if (map && str)
01168   { while (map->string)
01169     { if (!strcmp(str, map->string)) /* case sensitive */
01170         return map;
01171       map++;
01172     }
01173   }
01174   return NULL;
01175 }
01176 #endif
01177 
01178 /******************************************************************************/
01179 #ifndef PALM_1
01180 SOAP_FMAC1
01181 long
01182 SOAP_FMAC2
01183 soap_code_int(const struct soap_code_map *map, const char *str, long other)
01184 { if (map)
01185   { while (map->string)
01186     { if (!soap_tag_cmp(str, map->string)) /* case insensitive */
01187         return map->code;
01188       map++;
01189     }
01190   }
01191   return other;
01192 }
01193 #endif
01194 
01195 /******************************************************************************/
01196 #ifndef PALM_1
01197 SOAP_FMAC1
01198 const char*
01199 SOAP_FMAC2
01200 soap_code_str(const struct soap_code_map *map, long code)
01201 { if (!map)
01202     return NULL;
01203   while (map->code != code && map->string)
01204     map++;
01205   return map->string;
01206 }
01207 #endif
01208 
01209 /******************************************************************************/
01210 #ifndef PALM_1
01211 SOAP_FMAC1
01212 long
01213 SOAP_FMAC2
01214 soap_code_bits(const struct soap_code_map *map, const char *str)
01215 { register long bits = 0;
01216   if (map)
01217   { while (str && *str)
01218     { const struct soap_code_map *p;
01219       for (p = map; p->string; p++)
01220       { register size_t n = strlen(p->string);
01221         if (!strncmp(p->string, str, n) && soap_blank(str[n]))
01222         { bits |= p->code;
01223           str += n;
01224           while (*str > 0 && *str <= 32)
01225             str++;
01226           break;
01227         }
01228       }
01229       if (!p->string)
01230         return 0;
01231     }
01232   }
01233   return bits;
01234 }
01235 #endif
01236 
01237 /******************************************************************************/
01238 #ifndef PALM_1
01239 SOAP_FMAC1
01240 const char*
01241 SOAP_FMAC2
01242 soap_code_list(struct soap *soap, const struct soap_code_map *map, long code)
01243 { register char *t = soap->tmpbuf;
01244   if (map)
01245   { while (map->string)
01246     { if (map->code & code)
01247       { register const char *s = map->string;
01248         if (t != soap->tmpbuf)
01249           *t++ = ' ';
01250         while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
01251           *t++ = *s++;
01252         if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
01253           break;
01254       }
01255       map++;
01256     }
01257   }
01258   *t = '\0';
01259   return soap->tmpbuf;
01260 }
01261 #endif
01262 
01263 /******************************************************************************/
01264 #ifndef PALM_1
01265 static soap_wchar
01266 soap_char(struct soap *soap)
01267 { char tmp[8];
01268   register int i;
01269   register soap_wchar c;
01270   register char *s = tmp;
01271   for (i = 0; i < 7; i++)
01272   { c = soap_get1(soap);
01273     if (c == ';' || (int)c == EOF)
01274       break;
01275     *s++ = (char)c;
01276   }
01277   *s = '\0';
01278   if (*tmp == '#')
01279   { if (tmp[1] == 'x' || tmp[1] == 'X')
01280       return soap_strtol(tmp + 2, NULL, 16);
01281     return atol(tmp + 1);
01282   }
01283   if (!strcmp(tmp, "lt"))
01284     return '<';
01285   if (!strcmp(tmp, "gt"))
01286     return '>';
01287   if (!strcmp(tmp, "amp"))
01288     return '&';
01289   if (!strcmp(tmp, "quot"))
01290     return '"';
01291   if (!strcmp(tmp, "apos"))
01292     return '\'';
01293 #ifndef WITH_LEAN
01294   return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
01295 #else
01296   return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
01297 #endif
01298 }
01299 #endif
01300 
01301 /******************************************************************************/
01302 #ifdef WITH_LEAN
01303 #ifndef PALM_1
01304 soap_wchar
01305 soap_get0(struct soap *soap)
01306 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
01307     return EOF;
01308   return (unsigned char)soap->buf[soap->bufidx];
01309 }
01310 #endif
01311 #endif
01312 
01313 /******************************************************************************/
01314 #ifdef WITH_LEAN
01315 #ifndef PALM_1
01316 soap_wchar
01317 soap_get1(struct soap *soap)
01318 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
01319     return EOF;
01320   return (unsigned char)soap->buf[soap->bufidx++];
01321 }
01322 #endif
01323 #endif
01324 
01325 /******************************************************************************/
01326 #ifndef PALM_1
01327 SOAP_FMAC1
01328 soap_wchar
01329 SOAP_FMAC2
01330 soap_get(struct soap *soap)
01331 { register soap_wchar c;
01332   c = soap->ahead;
01333   if (c)
01334   { if ((int)c != EOF)
01335       soap->ahead = 0;
01336   }
01337   else
01338     c = soap_get1(soap);
01339   while ((int)c != EOF)
01340   { if (soap->cdata)
01341     { if (c == ']')
01342       { c = soap_get1(soap);
01343         if (c == ']')
01344         { c = soap_get0(soap);
01345           if (c == '>')
01346           { soap->cdata = 0;
01347             soap_get1(soap);
01348             c = soap_get1(soap);
01349           }
01350           else
01351           { soap_unget(soap, ']');
01352             return ']';
01353           }
01354         }
01355         else
01356         { soap_revget1(soap);
01357           return ']';
01358         }
01359       }
01360       else
01361         return c;
01362     }
01363     switch (c)
01364     { case '<':
01365         do c = soap_get1(soap);
01366         while (soap_blank(c));
01367         if (c == '!' || c == '?' || c == '%')
01368         { register int k = 1;
01369           if (c == '!')
01370           { c = soap_get1(soap);
01371             if (c == '[')
01372             { do c = soap_get1(soap);
01373               while ((int)c != EOF && c != '[');
01374               if ((int)c == EOF)
01375                 break;
01376               soap->cdata = 1;
01377               c = soap_get1(soap);
01378               continue;
01379             }
01380             if (c == '-' && (c = soap_get1(soap)) == '-')
01381             { do
01382               { c = soap_get1(soap);
01383                 if (c == '-' && (c = soap_get1(soap)) == '-')
01384                   break;
01385               } while ((int)c != EOF);
01386             }
01387           }
01388           else if (c == '?')
01389             c = soap_get_pi(soap);
01390           while ((int)c != EOF)
01391           { if (c == '<')
01392               k++;
01393             else if (c == '>')
01394             { if (--k <= 0)
01395                 break;
01396             }
01397             c = soap_get1(soap);
01398           }
01399           if ((int)c == EOF)
01400             break;
01401           c = soap_get1(soap);
01402           continue;
01403         }
01404         if (c == '/')
01405           return SOAP_TT;
01406         soap_revget1(soap);
01407         return SOAP_LT;
01408       case '>':
01409         return SOAP_GT;
01410       case '"':
01411         return SOAP_QT;
01412       case '\'':
01413         return SOAP_AP;
01414       case '&':
01415         return soap_char(soap) | 0x80000000;
01416     }
01417     break;
01418   }
01419   return c;
01420 }
01421 #endif
01422 
01423 /******************************************************************************/
01424 #ifndef PALM_1
01425 static soap_wchar
01426 soap_get_pi(struct soap *soap)
01427 { char buf[64];
01428   register char *s = buf;
01429   register int i = sizeof(buf);
01430   register soap_wchar c = soap_getchar(soap);
01431   /* This is a quick way to parse XML PI and we could use a callback instead to
01432    * enable applications to intercept processing instructions */
01433   while ((int)c != EOF && c != '?')
01434   { if (--i > 0)
01435     { if (soap_blank(c))
01436         c = ' ';
01437       *s++ = (char)c;
01438     }
01439     c = soap_getchar(soap);
01440   }
01441   *s = '\0';
01442   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
01443   if (!strncmp(buf, "xml ", 4))
01444   { s = strstr(buf, " encoding=");
01445     if (s && s[10])
01446     { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
01447        || !soap_tag_cmp(s + 11, "latin1*"))
01448       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
01449         soap->mode |= SOAP_ENC_LATIN;
01450       }
01451       else if (!soap_tag_cmp(s + 11, "utf-8*"))
01452       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
01453         soap->mode &= ~SOAP_ENC_LATIN;
01454       }
01455     }
01456   }
01457   if ((int)c != EOF)
01458     c = soap_getchar(soap);
01459   return c;
01460 }
01461 #endif
01462 
01463 /******************************************************************************/
01464 #ifndef WITH_LEANER
01465 #ifndef PALM_1
01466 SOAP_FMAC1
01467 int
01468 SOAP_FMAC2
01469 soap_move(struct soap *soap, long n)
01470 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
01471   for (; n > 0; n--)
01472     if ((int)soap_getchar(soap) == EOF)
01473       return SOAP_EOF;
01474   return SOAP_OK;
01475 }
01476 #endif
01477 #endif
01478 
01479 /******************************************************************************/
01480 #ifndef WITH_LEANER
01481 #ifndef PALM_1
01482 SOAP_FMAC1
01483 size_t
01484 SOAP_FMAC2
01485 soap_tell(struct soap *soap)
01486 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
01487 }
01488 #endif
01489 #endif
01490 
01491 /******************************************************************************/
01492 #ifndef PALM_1
01493 SOAP_FMAC1
01494 int
01495 SOAP_FMAC2
01496 soap_pututf8(struct soap *soap, register unsigned long c)
01497 { char tmp[16];
01498   if (c > 0 && c < 0x80)
01499   { *tmp = (char)c;
01500     return soap_send_raw(soap, tmp, 1);
01501   }
01502 #ifndef WITH_LEAN
01503   if (soap->mode & SOAP_XML_CANONICAL)
01504   { register char *t = tmp;
01505     if (c < 0x0800)
01506       *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
01507     else
01508     { if (c < 0x010000)
01509         *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
01510       else
01511       { if (c < 0x200000)
01512           *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
01513         else
01514         { if (c < 0x04000000)
01515             *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
01516           else
01517           { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
01518             *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
01519           }
01520           *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
01521         }     
01522         *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
01523       }
01524       *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
01525     }
01526     *t++ = (char)(0x80 | (c & 0x3F));
01527     *t = '\0';
01528   }
01529   else
01530 #endif
01531     sprintf(tmp, "&#%lu;", c);
01532   return soap_send(soap, tmp);
01533 }
01534 #endif
01535 
01536 /******************************************************************************/
01537 #ifndef PALM_1
01538 SOAP_FMAC1
01539 soap_wchar
01540 SOAP_FMAC2
01541 soap_getutf8(struct soap *soap)
01542 { register soap_wchar c, c1, c2, c3, c4;
01543   c = soap->ahead;
01544   if (c > 0xFF)
01545   { soap->ahead = 0;
01546     return c;
01547   }
01548 again:
01549   c = soap_get(soap);
01550   if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
01551     return c;
01552   c1 = soap_get1(soap);
01553   if (c1 < 0x80)
01554   { soap_revget1(soap); /* doesn't look like this is UTF8 */
01555     return c;
01556   }
01557   c1 &= 0x3F;
01558   if (c < 0xE0)
01559     return ((soap_wchar)(c & 0x1F) << 6) | c1;
01560   c2 = (soap_wchar)soap_get1(soap) & 0x3F;
01561   if (c == 0xEF && c1 == 0x3B && c2 == 0x3F)    /* ignore UTF-8 BOM */
01562     goto again;
01563   if (c < 0xF0)
01564     return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
01565   c3 = (soap_wchar)soap_get1(soap) & 0x3F;
01566   if (c < 0xF8)
01567     return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
01568   c4 = (soap_wchar)soap_get1(soap) & 0x3F;
01569   if (c < 0xFC)
01570     return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
01571   return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
01572 }
01573 #endif
01574 
01575 /******************************************************************************/
01576 #ifndef PALM_1
01577 SOAP_FMAC1
01578 int
01579 SOAP_FMAC2
01580 soap_puthex(struct soap *soap, const unsigned char *s, int n)
01581 { char d[2];
01582   register int i;
01583 #ifdef WITH_DOM
01584   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01585   { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
01586       return soap->error;
01587     return SOAP_OK;
01588   }
01589 #endif
01590   for (i = 0; i < n; i++)
01591   { register int m = *s++;
01592     d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
01593     m &= 0x0F;
01594     d[1] = (char)(m + (m > 9 ? '7' : '0'));
01595     if (soap_send_raw(soap, d, 2))
01596       return soap->error;
01597   }
01598   return SOAP_OK;
01599 }
01600 #endif
01601 
01602 /******************************************************************************/
01603 #ifndef PALM_1
01604 SOAP_FMAC1
01605 unsigned char*
01606 SOAP_FMAC2
01607 soap_gethex(struct soap *soap, int *n)
01608 {
01609 #ifdef WITH_DOM
01610   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01611   { soap->dom->data = soap_string_in(soap, 0, -1, -1);
01612     return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
01613   }
01614 #endif
01615 #ifdef WITH_FAST
01616   soap->labidx = 0;
01617   for (;;)
01618   { register char *s;
01619     register int i, k;
01620     if (soap_append_lab(soap, NULL, 0))
01621       return NULL;
01622     s = soap->labbuf + soap->labidx;
01623     k = soap->lablen - soap->labidx;
01624     soap->labidx = soap->lablen;
01625     for (i = 0; i < k; i++)
01626     { register char d1, d2;
01627       register soap_wchar c;
01628       c = soap_get(soap);
01629       if (soap_isxdigit(c))
01630       { d1 = (char)c;
01631         c = soap_get(soap); 
01632         if (soap_isxdigit(c))
01633           d2 = (char)c;
01634         else 
01635         { soap->error = SOAP_TYPE;
01636           return NULL;
01637         }
01638       }
01639       else
01640       { unsigned char *p;
01641         soap_unget(soap, c);
01642         if (n)
01643           *n = (int)(soap->lablen - k + i);
01644         p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
01645         if (p)
01646           memcpy(p, soap->labbuf, soap->lablen - k + i);
01647         return p;
01648       }
01649       *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
01650     }
01651   }
01652 #else
01653   if (soap_new_block(soap))
01654     return NULL;
01655   for (;;)
01656   { register int i;
01657     register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN);
01658     if (!s)
01659     { soap_end_block(soap);
01660       return NULL;
01661     }
01662     for (i = 0; i < SOAP_BLKLEN; i++)
01663     { register char d1, d2;
01664       register soap_wchar c = soap_get(soap);
01665       if (soap_isxdigit(c))
01666       { d1 = (char)c;
01667         c = soap_get(soap); 
01668         if (soap_isxdigit(c))
01669           d2 = (char)c;
01670         else 
01671         { soap_end_block(soap);
01672           soap->error = SOAP_TYPE;
01673           return NULL;
01674         }
01675       }
01676       else
01677       { unsigned char *p;
01678         soap_unget(soap, c);
01679         if (n)
01680           *n = soap_size_block(soap, i);
01681         p = (unsigned char*)soap_save_block(soap, NULL, 0);
01682         return p;
01683       }
01684       *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
01685     }
01686   }
01687 #endif
01688 }
01689 #endif
01690 
01691 /******************************************************************************/
01692 #ifndef PALM_1
01693 SOAP_FMAC1
01694 int
01695 SOAP_FMAC2
01696 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
01697 { register int i;
01698   register unsigned long m;
01699   char d[4];
01700   if (!s)
01701     return SOAP_OK;
01702 #ifdef WITH_DOM
01703   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01704   { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
01705       return soap->error;
01706     return SOAP_OK;
01707   }
01708 #endif
01709   for (; n > 2; n -= 3, s += 3)
01710   { m = s[0];
01711     m = (m << 8) | s[1];
01712     m = (m << 8) | s[2];
01713     for (i = 4; i > 0; m >>= 6)
01714       d[--i] = soap_base64o[m & 0x3F];
01715     if (soap_send_raw(soap, d, 4))
01716       return soap->error;
01717   }
01718   if (n > 0)
01719   { m = 0;
01720     for (i = 0; i < n; i++)
01721       m = (m << 8) | *s++;
01722     for (; i < 3; i++)
01723       m <<= 8;
01724     for (i++; i > 0; m >>= 6)
01725       d[--i] = soap_base64o[m & 0x3F];
01726     for (i = 3; i > n; i--)
01727       d[i] = '=';
01728     if (soap_send_raw(soap, d, 4))
01729       return soap->error;
01730   }
01731   return SOAP_OK;
01732 }
01733 #endif
01734 
01735 /******************************************************************************/
01736 #ifndef PALM_1
01737 SOAP_FMAC1
01738 unsigned char*
01739 SOAP_FMAC2
01740 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
01741 { 
01742 #ifdef WITH_DOM
01743   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
01744   { soap->dom->data = soap_string_in(soap, 0, -1, -1);
01745     return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
01746   }
01747 #endif
01748 #ifdef WITH_FAST
01749   soap->labidx = 0;
01750   for (;;)
01751   { register int i, k;
01752     register char *s;
01753     if (soap_append_lab(soap, NULL, 2))
01754       return NULL;
01755     s = soap->labbuf + soap->labidx;
01756     k = soap->lablen - soap->labidx;
01757     soap->labidx = 3 * (soap->lablen / 3);
01758     if (!s)
01759       return NULL;
01760     for (i = 0; i < k - 2; i += 3)
01761     { register unsigned long m = 0;
01762       register int j = 0;
01763       do
01764       { register soap_wchar c = soap_get(soap);
01765         if (c == '=' || c < 0)
01766         { unsigned char *p;
01767           switch (j)
01768           { case 2:
01769               *s++ = (char)((m >> 4) & 0xFF);
01770               i++;
01771               break;
01772             case 3:
01773               *s++ = (char)((m >> 10) & 0xFF);
01774               *s++ = (char)((m >> 2) & 0xFF);
01775               i += 2;
01776           }
01777           if (n)
01778             *n = (int)(soap->lablen - k + i);
01779           p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
01780           if (p)
01781             memcpy(p, soap->labbuf, soap->lablen - k + i);
01782           if (c >= 0)
01783           { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
01784               ;
01785           }
01786           soap_unget(soap, c);
01787           return p;
01788         }
01789         c -= '+';
01790         if (c >= 0 && c <= 79)
01791         { m = (m << 6) + soap_base64i[c];
01792           j++;
01793         }
01794       } while (j < 4);
01795       *s++ = (char)((m >> 16) & 0xFF);
01796       *s++ = (char)((m >> 8) & 0xFF);
01797       *s++ = (char)(m & 0xFF);
01798     }
01799   }
01800 #else
01801   if (soap_new_block(soap))
01802     return NULL;
01803   for (;;)
01804   { register int i;
01805     register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
01806     if (!s)
01807     { soap_end_block(soap);
01808       return NULL;
01809     }
01810     for (i = 0; i < SOAP_BLKLEN; i++)
01811     { register unsigned long m = 0;
01812       register int j = 0;
01813       do
01814       { register soap_wchar c = soap_get(soap);
01815         if (c == '=' || c < 0)
01816         { unsigned char *p;
01817           i *= 3;
01818           switch (j)
01819           { case 2:
01820               *s++ = (char)((m >> 4) & 0xFF);
01821               i++;
01822               break;
01823             case 3:
01824               *s++ = (char)((m >> 10) & 0xFF);
01825               *s++ = (char)((m >> 2) & 0xFF);
01826               i += 2;
01827           }
01828           if (n)
01829             *n = (int)soap_size_block(soap, i);
01830           p = (unsigned char*)soap_save_block(soap, NULL, 0);
01831           if (c >= 0)
01832           { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
01833               ;
01834           }
01835           soap_unget(soap, c);
01836           return p;
01837         }
01838         c -= '+';
01839         if (c >= 0 && c <= 79)
01840         { m = (m << 6) + soap_base64i[c];
01841           j++;
01842         }
01843       } while (j < 4);
01844       *s++ = (char)((m >> 16) & 0xFF);
01845       *s++ = (char)((m >> 8) & 0xFF);
01846       *s++ = (char)(m & 0xFF);
01847     }
01848   }
01849 #endif
01850 }
01851 #endif
01852 
01853 /******************************************************************************/
01854 #ifndef WITH_LEANER
01855 #ifndef PALM_1
01856 SOAP_FMAC1
01857 int
01858 SOAP_FMAC2
01859 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
01860 { /* Check MTOM xop:Include element (within hex/base64Binary) */
01861   /* TODO: this code to be obsoleted with new import/xop.h conventions */
01862   int body = soap->body; /* should save type too? */
01863   if (!soap_peek_element(soap))
01864   { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href)
01865     { if (soap_dime_forward(soap, ptr, size, id, type, options))
01866         return soap->error;
01867     }
01868     if (soap->body && soap_element_end_in(soap, NULL))
01869       return soap->error;
01870   }
01871   soap->body = body;
01872   return SOAP_OK;
01873 }
01874 #endif
01875 #endif
01876 
01877 /******************************************************************************/
01878 #ifndef WITH_LEANER
01879 #ifndef PALM_1
01880 SOAP_FMAC1
01881 int
01882 SOAP_FMAC2
01883 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
01884 { struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
01885   *ptr = NULL;
01886   *size = 0;
01887   *id = soap_strdup(soap, soap->href);
01888   *type = NULL;
01889   *options = NULL;
01890   if (!xp)
01891     return soap->error = SOAP_EOM;
01892   xp->next = soap->xlist;
01893   xp->ptr = ptr;
01894   xp->size = size;
01895   xp->id = *id;
01896   xp->type = type;
01897   xp->options = options;
01898   soap->xlist = xp;
01899   return SOAP_OK;
01900 }
01901 #endif
01902 #endif
01903 
01904 /******************************************************************************/
01905 #ifndef PALM_1
01906 SOAP_FMAC1
01907 char *
01908 SOAP_FMAC2
01909 soap_strdup(struct soap *soap, const char *s)
01910 { char *t = NULL;
01911   if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
01912     strcpy(t, s);
01913   return t;
01914 }
01915 #endif
01916 
01917 /******************************************************************************/
01918 #ifndef PALM_1
01919 SOAP_FMAC1
01920 int
01921 SOAP_FMAC2
01922 soap_new_block(struct soap *soap)
01923 { struct soap_blist *p;
01924   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
01925   if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
01926     return SOAP_EOM;   
01927   p->next = soap->blist; 
01928   p->ptr = NULL;
01929   p->size = 0;
01930   soap->blist = p;
01931   return SOAP_OK;
01932 }
01933 #endif
01934 
01935 /******************************************************************************/
01936 #ifndef PALM_1
01937 SOAP_FMAC1
01938 void*
01939 SOAP_FMAC2
01940 soap_push_block(struct soap *soap, size_t n)
01941 { char *p;
01942   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n));
01943   if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
01944   { soap->error = SOAP_EOM;
01945     return NULL;
01946   }
01947   *(char**)p = soap->blist->ptr;
01948   *(size_t*)(p + sizeof(char*)) = n;
01949   soap->blist->ptr = p;
01950   soap->blist->size += n;
01951   return p + sizeof(char*) + sizeof(size_t);
01952 }
01953 #endif
01954 
01955 /******************************************************************************/
01956 #ifndef PALM_1
01957 SOAP_FMAC1
01958 void
01959 SOAP_FMAC2
01960 soap_pop_block(struct soap *soap)
01961 { char *p;
01962   if (!soap->blist->ptr)
01963     return;
01964   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
01965   p = soap->blist->ptr;
01966   soap->blist->size -= *(size_t*)(p + sizeof(char*));
01967   soap->blist->ptr = *(char**)p;
01968   SOAP_FREE(soap, p);
01969 }
01970 #endif
01971 
01972 /******************************************************************************/
01973 #ifndef WITH_NOIDREF
01974 #ifndef PALM_1
01975 static void
01976 soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
01977 { int i;
01978   register struct soap_ilist *ip;
01979   register struct soap_flist *fp;
01980 #ifndef WITH_LEANER
01981   register struct soap_xlist *xp;
01982 #endif
01983   register void *p, **q;
01984   for (i = 0; i < SOAP_IDHASH; i++)
01985   { for (ip = soap->iht[i]; ip; ip = ip->next)
01986     { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
01987       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
01988         ip->ptr = (char*)ip->ptr + (p1-p2);
01989       }
01990       for (q = &ip->link; q; q = (void**)p)
01991       { p = *q;
01992         if (p && (char*)p >= start && (char*)p < end)
01993         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
01994           *q = (char*)p + (p1-p2);
01995         }
01996       }
01997       for (q = &ip->copy; q; q = (void**)p)
01998       { p = *q;
01999         if (p && (char*)p >= start && (char*)p < end)
02000         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
02001           *q = (char*)p + (p1-p2);
02002         }
02003       }
02004       for (fp = ip->flist; fp; fp = fp->next)
02005       { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
02006         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
02007           fp->ptr = (char*)fp->ptr + (p1-p2);
02008         }
02009       }
02010     }
02011   }
02012 #ifndef WITH_LEANER
02013   for (xp = soap->xlist; xp; xp = xp->next)
02014   { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
02015     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2)));
02016       xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
02017       xp->size = (int*)((char*)xp->size + (p1-p2));
02018       xp->type = (char**)((char*)xp->type + (p1-p2));
02019       xp->options = (char**)((char*)xp->options + (p1-p2));
02020     }
02021   }
02022 #endif
02023 }
02024 #endif
02025 #endif
02026 
02027 /******************************************************************************/
02028 #ifndef WITH_NOIDREF
02029 #ifndef PALM_1
02030 static int
02031 soap_has_copies(struct soap *soap, register const char *start, register const char *end)
02032 { register int i;
02033   register struct soap_ilist *ip;
02034   register struct soap_flist *fp;
02035   register const char *p;
02036   for (i = 0; i < SOAP_IDHASH; i++)
02037   { for (ip = soap->iht[i]; ip; ip = ip->next)
02038     { for (p = (const char*)ip->copy; p; p = *(const char**)p)
02039         if (p >= start && p < end)
02040           return SOAP_ERR;
02041       for (fp = ip->flist; fp; fp = fp->next)
02042         if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
02043           return SOAP_ERR;
02044     }
02045   }
02046   return SOAP_OK;
02047 }
02048 #endif
02049 #endif
02050 
02051 /******************************************************************************/
02052 #ifndef WITH_NOIDREF
02053 #ifndef PALM_1
02054 SOAP_FMAC1
02055 int
02056 SOAP_FMAC2
02057 soap_resolve(struct soap *soap)
02058 { register int i;
02059   register struct soap_ilist *ip;
02060   register struct soap_flist *fp;
02061   short flag;
02062   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
02063   for (i = 0; i < SOAP_IDHASH; i++)
02064   { for (ip = soap->iht[i]; ip; ip = ip->next)
02065     { if (ip->ptr)
02066       { register void *p, **q, *r;
02067         q = (void**)ip->link;
02068         ip->link = NULL;
02069         r = ip->ptr;
02070         DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
02071         while (q)
02072         { p = *q;
02073           *q = r;
02074           DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
02075           q = (void**)p;
02076         }
02077       }
02078       else if (*ip->id == '#')
02079       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
02080         strcpy(soap->id, ip->id + 1);
02081         return soap->error = SOAP_MISSING_ID;
02082       }
02083     }
02084   }
02085   do
02086   { flag = 0;
02087     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
02088     for (i = 0; i < SOAP_IDHASH; i++)
02089     { for (ip = soap->iht[i]; ip; ip = ip->next)
02090       { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
02091         { if (ip->copy)
02092           { register void *p, **q = (void**)ip->copy;
02093             DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
02094             ip->copy = NULL;
02095             do
02096             { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
02097               p = *q;
02098               memcpy(q, ip->ptr, ip->size);
02099               q = (void**)p;
02100             } while (q);
02101             flag = 1;
02102           }
02103           for (fp = ip->flist; fp; fp = ip->flist)
02104           { register unsigned int k = fp->level;
02105             register void *p = ip->ptr;
02106             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));
02107             while (ip->level < k)
02108             { register void **q = (void**)soap_malloc(soap, sizeof(void*));  
02109               if (!q)
02110                 return soap->error;
02111               *q = p;
02112               DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
02113               p = (void*)q;
02114               k--;
02115             }
02116             if (fp->fcopy)
02117               fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
02118             else
02119               soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
02120             ip->flist = fp->next;
02121             SOAP_FREE(soap, fp);
02122             flag = 1;
02123           }
02124         }
02125       }
02126     }
02127   } while (flag);
02128 #ifdef SOAP_DEBUG
02129   for (i = 0; i < SOAP_IDHASH; i++)
02130   { for (ip = soap->iht[i]; ip; ip = ip->next)
02131     { if (ip->copy || ip->flist)
02132       { 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));
02133       }
02134     }
02135   }
02136 #endif
02137   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
02138   return SOAP_OK;
02139 }
02140 #endif
02141 #endif
02142 
02143 /******************************************************************************/
02144 #ifndef PALM_1
02145 SOAP_FMAC1
02146 size_t
02147 SOAP_FMAC2
02148 soap_size_block(struct soap *soap, size_t n)
02149 { if (soap->blist->ptr)
02150   { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n;
02151     *(size_t*)(soap->blist->ptr + sizeof(char*)) = n;
02152   }
02153   return soap->blist->size;
02154 }
02155 #endif
02156 
02157 /******************************************************************************/
02158 #ifndef PALM_1
02159 SOAP_FMAC1
02160 char*
02161 SOAP_FMAC2
02162 soap_first_block(struct soap *soap)
02163 { char *p, *q, *r;
02164   p = soap->blist->ptr;
02165   if (!p)
02166     return NULL;
02167   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
02168   r = NULL;
02169   do
02170   { q = *(char**)p;
02171     *(char**)p = r;
02172     r = p;
02173     p = q;
02174   } while (p);
02175   soap->blist->ptr = r;
02176   return r + sizeof(char*) + sizeof(size_t);
02177 }
02178 #endif
02179 
02180 /******************************************************************************/
02181 #ifndef PALM_1
02182 SOAP_FMAC1
02183 char*
02184 SOAP_FMAC2
02185 soap_next_block(struct soap *soap)
02186 { char *p;
02187   p = soap->blist->ptr;
02188   if (p)
02189   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
02190     soap->blist->ptr = *(char**)p;
02191     SOAP_FREE(soap, p);
02192     if (soap->blist->ptr)
02193       return soap->blist->ptr + sizeof(char*) + sizeof(size_t);
02194   }
02195   return NULL;
02196 }
02197 #endif
02198 
02199 /******************************************************************************/
02200 #ifndef PALM_1
02201 SOAP_FMAC1
02202 size_t
02203 SOAP_FMAC2
02204 soap_block_size(struct soap *soap)
02205 { return *(size_t*)(soap->blist->ptr + sizeof(char*));
02206 }
02207 #endif
02208 
02209 /******************************************************************************/
02210 #ifndef PALM_1
02211 SOAP_FMAC1
02212 void
02213 SOAP_FMAC2
02214 soap_end_block(struct soap *soap)
02215 { struct soap_blist *bp;
02216   char *p, *q;
02217   bp = soap->blist;
02218   if (bp)
02219   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
02220     for (p = bp->ptr; p; p = q)
02221     { q = *(char**)p;
02222       SOAP_FREE(soap, p);
02223     }
02224     soap->blist = bp->next;
02225     SOAP_FREE(soap, bp);
02226   }
02227   DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
02228 }
02229 #endif
02230 
02231 /******************************************************************************/
02232 #ifndef PALM_1
02233 SOAP_FMAC1
02234 char*
02235 SOAP_FMAC2
02236 soap_save_block(struct soap *soap, char *p, int flag)
02237 { register size_t n;
02238   register char *q, *s;
02239   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p));
02240   if (soap->blist->size)
02241   { if (!p)
02242       p = (char*)soap_malloc(soap, soap->blist->size);
02243     if (p)
02244     { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap))
02245       { n = soap_block_size(soap);
02246 #ifndef WITH_NOIDREF
02247         if (flag)
02248           soap_update_ptrs(soap, q, q + n, s, q);
02249 #endif
02250         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
02251         memcpy(s, q, n);
02252         s += n;
02253       }
02254     }
02255     else
02256       soap->error = SOAP_EOM;
02257   }
02258   soap_end_block(soap);
02259   return p;
02260 }
02261 #endif
02262 
02263 /******************************************************************************/
02264 #ifndef PALM_2
02265 SOAP_FMAC1
02266 char *
02267 SOAP_FMAC2
02268 soap_putsize(struct soap *soap, const char *type, int size)
02269 { return soap_putsizes(soap, type, &size, 1);
02270 }
02271 #endif
02272 
02273 /******************************************************************************/
02274 #ifndef PALM_2
02275 SOAP_FMAC1
02276 char *
02277 SOAP_FMAC2
02278 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
02279 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
02280 }
02281 #endif
02282 
02283 /******************************************************************************/
02284 #ifndef PALM_2
02285 SOAP_FMAC1
02286 char *
02287 SOAP_FMAC2
02288 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
02289 { int i;
02290   if (!type)
02291     return NULL;
02292   if (soap->version == 2)
02293   { sprintf(soap->type, "%s[%d", type, size[0]);
02294     for (i = 1; i < dim; i++)
02295       sprintf(soap->type + strlen(soap->type), " %d", size[i]);
02296   }
02297   else
02298   { if (offset)
02299     { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
02300       for (i = 1; i < dim; i++)
02301         sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
02302     }
02303     else
02304     { sprintf(soap->type, "%s[%d", type, size[0]);
02305       for (i = 1; i < dim; i++)
02306         sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
02307     }
02308     strcat(soap->type, "]");
02309   }
02310   return soap->type;
02311 }
02312 #endif
02313 
02314 /******************************************************************************/
02315 #ifndef PALM_2
02316 SOAP_FMAC1
02317 char *
02318 SOAP_FMAC2
02319 soap_putoffset(struct soap *soap, int offset)
02320 { return soap_putoffsets(soap, &offset, 1);
02321 }
02322 #endif
02323 
02324 /******************************************************************************/
02325 #ifndef PALM_2
02326 SOAP_FMAC1
02327 char *
02328 SOAP_FMAC2
02329 soap_putoffsets(struct soap *soap, const int *offset, int dim)
02330 { register int i;
02331   sprintf(soap->arrayOffset, "[%d", offset[0]);
02332   for (i = 1; i < dim; i++)
02333     sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
02334   strcat(soap->arrayOffset, "]");
02335   return soap->arrayOffset;
02336 }
02337 #endif
02338 
02339 /******************************************************************************/
02340 #ifndef PALM_2
02341 SOAP_FMAC1
02342 int
02343 SOAP_FMAC2
02344 soap_size(const int *size, int dim)
02345 { register int i, n = size[0];
02346   for (i = 1; i < dim; i++)
02347     n *= size[i];
02348   return n;
02349 }
02350 #endif
02351 
02352 /******************************************************************************/
02353 #ifndef PALM_2
02354 SOAP_FMAC1
02355 int
02356 SOAP_FMAC2
02357 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
02358 { register int i, j = 0;
02359   if (offset)
02360     for (i = 0; i < dim && attr && *attr; i++)
02361     { attr++;
02362       j *= size[i];
02363       j += offset[i] = (int)atol(attr);
02364       attr = strchr(attr, ',');
02365     }
02366   else
02367     for (i = 0; i < dim && attr && *attr; i++)
02368     { attr++;
02369       j *= size[i];
02370       j += (int)atol(attr);
02371       attr = strchr(attr, ',');
02372     }
02373   return j;
02374 }
02375 #endif
02376 
02377 /******************************************************************************/
02378 #ifndef PALM_2
02379 SOAP_FMAC1
02380 int
02381 SOAP_FMAC2
02382 soap_getsize(const char *attr1, const char *attr2, int *j)
02383 { register int n, k;
02384   char *s;
02385   *j = 0;
02386   if (!*attr1)
02387     return -1;
02388   if (*attr1 == '[')
02389     attr1++;
02390   n = 1;
02391   for (;;)
02392   { k = (int)soap_strtol(attr1, &s, 10);
02393     n *= k;
02394     if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
02395       return -1;
02396     attr1 = strchr(s, ',');
02397     if (!attr1)
02398       attr1 = strchr(s, ' ');
02399     if (attr2 && *attr2)
02400     { attr2++;
02401       *j *= k;
02402       k = (int)soap_strtol(attr2, &s, 10);
02403       *j += k;
02404       if (k < 0)
02405         return -1;
02406       attr2 = s;
02407     }
02408     if (!attr1)
02409       break;
02410     attr1++;
02411   }
02412   return n - *j;
02413 }
02414 #endif
02415 
02416 /******************************************************************************/
02417 #ifndef PALM_2
02418 SOAP_FMAC1
02419 int
02420 SOAP_FMAC2
02421 soap_getsizes(const char *attr, int *size, int dim)
02422 { register int i, k, n;
02423   if (!*attr)
02424     return -1;
02425   i = strlen(attr);
02426   n = 1;
02427   do
02428   { for (i = i-1; i >= 0; i--)
02429       if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
02430         break;
02431     k = (int)atol(attr + i + 1);
02432     n *= size[--dim] = k;
02433     if (k < 0 || n > SOAP_MAXARRAYSIZE)
02434       return -1;
02435   } while (i >= 0 && attr[i] != '[');
02436   return n;
02437 }
02438 #endif
02439 
02440 /******************************************************************************/
02441 #ifndef PALM_2
02442 SOAP_FMAC1
02443 int
02444 SOAP_FMAC2
02445 soap_getposition(const char *attr, int *pos)
02446 { register int i, n;
02447   if (!*attr)
02448     return -1;
02449   n = 0;
02450   i = 1;
02451   do
02452   { pos[n++] = (int)atol(attr + i);
02453     while (attr[i] && attr[i] != ',' && attr[i] != ']')
02454       i++;
02455     if (attr[i] == ',')
02456       i++;
02457   } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
02458   return n;
02459 }
02460 #endif
02461 
02462 /******************************************************************************/
02463 #ifndef PALM_2
02464 SOAP_FMAC1
02465 int
02466 SOAP_FMAC2
02467 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
02468 { register struct soap_nlist *np;
02469   register struct Namespace *p;
02470   register short i = -1;
02471   register size_t n, k;
02472   n = strlen(id);
02473   k = strlen(ns) + 1;
02474   p = soap->local_namespaces;
02475   if (p)
02476   { for (i = 0; p->id; p++, i++)
02477     { if (p->ns && !strcmp(ns, p->ns))
02478       { if (p->out)
02479         { SOAP_FREE(soap, p->out);
02480           p->out = NULL;
02481         }
02482         break;
02483       }
02484       if (p->out)
02485       { if (!strcmp(ns, p->out))
02486           break;
02487       }
02488       else if (p->in)
02489       { if (!soap_tag_cmp(ns, p->in))
02490         { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
02491             strcpy(p->out, ns);
02492           break;
02493         }
02494       }
02495     }
02496     if (!p || !p->id)
02497       i = -1;
02498   }
02499   if (i >= 0)
02500     k = 0;
02501   np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
02502   if (!np)
02503     return soap->error = SOAP_EOM;
02504   np->next = soap->nlist;
02505   soap->nlist = np;
02506   np->level = soap->level;
02507   np->index = i;
02508   strcpy(np->id, id);
02509   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
02510   if (i < 0)
02511   { np->ns = np->id + n + 1;
02512     strcpy(np->ns, ns);
02513     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
02514   }
02515   else
02516   { np->ns = NULL;
02517     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
02518   }
02519   return SOAP_OK;
02520 }
02521 #endif
02522 
02523 /******************************************************************************/
02524 #ifndef PALM_2
02525 SOAP_FMAC1
02526 void
02527 SOAP_FMAC2
02528 soap_pop_namespace(struct soap *soap)
02529 { register struct soap_nlist *np;
02530   while (soap->nlist && soap->nlist->level >= soap->level)
02531   { np = soap->nlist->next;
02532     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id));
02533     SOAP_FREE(soap, soap->nlist);
02534     soap->nlist = np;
02535   }
02536 }
02537 #endif
02538 
02539 /******************************************************************************/
02540 #ifndef PALM_2
02541 SOAP_FMAC1
02542 int
02543 SOAP_FMAC2
02544 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) 
02545 { register struct soap_nlist *np = soap->nlist;
02546   while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
02547     np = np->next;
02548   if (np)
02549   { if (np->index < 0
02550      || (soap->local_namespaces[np->index].id
02551       && (strncmp(soap->local_namespaces[np->index].id, id2, n2)
02552        || soap->local_namespaces[np->index].id[n2])))
02553       return SOAP_NAMESPACE;
02554     return SOAP_OK;
02555   }
02556   if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2))
02557     return SOAP_OK;
02558   return SOAP_SYNTAX_ERROR; 
02559 }
02560 #endif
02561 
02562 /******************************************************************************/
02563 #ifndef PALM_2
02564 SOAP_FMAC1
02565 const char*
02566 SOAP_FMAC2
02567 soap_current_namespace(struct soap *soap, const char *tag)
02568 { register struct soap_nlist *np;
02569   register const char *s;
02570   np = soap->nlist;
02571   if (!(s = strchr(tag, ':')))
02572   { while (np && *np->id) /* find default namespace, if present */
02573       np = np->next;
02574   }
02575   else
02576   { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
02577       np = np->next;
02578     if (!np)
02579       soap->error = SOAP_NAMESPACE;
02580   }
02581   if (np)
02582   { if (np->index >= 0)
02583       return soap->namespaces[np->index].ns;
02584     if (np->ns)
02585       return soap_strdup(soap, np->ns);
02586   }
02587   return NULL;
02588 }
02589 #endif
02590 
02591 /******************************************************************************/
02592 #ifndef PALM_2
02593 SOAP_FMAC1
02594 int
02595 SOAP_FMAC2
02596 soap_tag_cmp(const char *s, const char *t)
02597 { for (;;)
02598   { register int c1 = *s;
02599     register int c2 = *t;
02600     if (!c1 || c1 == '"')
02601       break;
02602     if (c2 != '-')
02603     { if (c1 != c2)
02604       { if (c1 >= 'A' && c1 <= 'Z')
02605           c1 += 'a' - 'A';
02606         if (c2 >= 'A' && c2 <= 'Z')
02607           c2 += 'a' - 'A';
02608       }
02609       if (c1 != c2)
02610       { if (c2 != '*')
02611           return 1;
02612         c2 = *++t;
02613         if (!c2)
02614           return 0;
02615         if (c2 >= 'A' && c2 <= 'Z')
02616           c2 += 'a' - 'A';
02617         for (;;)
02618         { c1 = *s;
02619           if (!c1 || c1 == '"')
02620             break;
02621           if (c1 >= 'A' && c1 <= 'Z')
02622             c1 += 'a' - 'A';
02623           if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
02624             return 0;
02625           s++;
02626         }
02627         break;
02628       }
02629     }
02630     s++;
02631     t++;
02632   }
02633   if (*t == '*' && !t[1])
02634     return 0;
02635   return *t;
02636 }
02637 #endif
02638 
02639 /******************************************************************************/
02640 #ifndef PALM_2
02641 SOAP_FMAC1
02642 int
02643 SOAP_FMAC2
02644 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
02645 { register const char *s, *t;
02646   if (!tag1 || !tag2 || !*tag2)
02647     return SOAP_OK;
02648   s = strchr(tag1, ':');
02649   t = strchr(tag2, ':');
02650   if (t)
02651   { if (s)
02652     { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
02653         return SOAP_TAG_MISMATCH;
02654       if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))
02655       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
02656         return SOAP_TAG_MISMATCH;
02657       }
02658     } 
02659     else if (SOAP_STRCMP(tag1, t + 1))
02660       return SOAP_TAG_MISMATCH;
02661     else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2))
02662     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
02663       return SOAP_TAG_MISMATCH;
02664     }
02665     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
02666     return SOAP_OK;
02667   }
02668   if (s)
02669   { if (SOAP_STRCMP(s + 1, tag2))
02670       return SOAP_TAG_MISMATCH;
02671   }
02672   else if (SOAP_STRCMP(tag1, tag2))
02673     return SOAP_TAG_MISMATCH;
02674   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
02675   return SOAP_OK;
02676 }
02677 #endif
02678 
02679 /******************************************************************************/
02680 #ifndef PALM_2
02681 SOAP_FMAC1
02682 int
02683 SOAP_FMAC2
02684 soap_match_array(struct soap *soap, const char *type)
02685 { if (*soap->arrayType)
02686     if (soap_match_tag(soap, soap->arrayType, type)
02687      && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
02688      && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
02689     )
02690     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
02691       return SOAP_TAG_MISMATCH;
02692     }
02693   return SOAP_OK;
02694 }
02695 #endif
02696 
02697 /******************************************************************************\
02698  *
02699  *      SSL
02700  *
02701 \******************************************************************************/
02702 
02703 #ifdef WITH_OPENSSL
02704 /******************************************************************************/
02705 #ifndef PALM_2
02706 SOAP_FMAC1
02707 int
02708 SOAP_FMAC2
02709 soap_rand()
02710 { unsigned char buf[4];
02711   if (!ssl_init_done)
02712     soap_ssl_init();
02713   RAND_pseudo_bytes(buf, 4);
02714   return *(int*)buf;
02715 }
02716 #endif
02717 
02718 /******************************************************************************/
02719 #ifndef PALM_2
02720 SOAP_FMAC1
02721 int
02722 SOAP_FMAC2
02723 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)
02724 { int err;
02725   soap->keyfile = keyfile;
02726   soap->password = password;
02727   soap->cafile = cafile;
02728   soap->capath = capath;
02729   soap->dhfile = dhfile;
02730   soap->rsa = (dhfile == NULL);
02731   soap->randfile = randfile;
02732   soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION);
02733   if (!(err = soap->fsslauth(soap)))
02734   { if (sid)
02735       SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid));
02736   }
02737   return err; 
02738 }
02739 #endif
02740 
02741 /******************************************************************************/
02742 #ifndef PALM_2
02743 SOAP_FMAC1
02744 int
02745 SOAP_FMAC2
02746 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)
02747 { soap->keyfile = keyfile;
02748   soap->password = password;
02749   soap->cafile = cafile;
02750   soap->capath = capath;
02751   soap->dhfile = NULL;
02752   soap->rsa = 0;
02753   soap->randfile = randfile;
02754   soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION);
02755   return soap->fsslauth(soap);
02756 }
02757 #endif
02758 
02759 /******************************************************************************/
02760 #ifndef PALM_2
02761 SOAP_FMAC1
02762 void
02763 SOAP_FMAC2
02764 soap_ssl_init()
02765 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
02766   if (!ssl_init_done)
02767   { ssl_init_done = 1;
02768     SSL_library_init();
02769 #ifndef WITH_LEAN
02770     SSL_load_error_strings();
02771 #endif
02772     if (!RAND_load_file("/dev/urandom", 1024))
02773     { char buf[1024];
02774       RAND_seed(buf, sizeof(buf));
02775       while (!RAND_status())
02776       { int r = rand();
02777         RAND_seed(&r, sizeof(int));
02778       }
02779     }
02780   }
02781 }
02782 #endif
02783 
02784 /******************************************************************************/
02785 #ifndef PALM_1
02786 SOAP_FMAC1
02787 const char *
02788 SOAP_FMAC2
02789 soap_ssl_error(struct soap *soap, int ret)
02790 { int err = SSL_get_error(soap->ssl, ret);
02791   const char *msg = soap_code_str(h_ssl_error_codes, err);
02792   if (msg)
02793     strcpy(soap->msgbuf, msg);
02794   else
02795     return ERR_error_string(err, soap->msgbuf);
02796   if (ERR_peek_error())
02797   { unsigned long r;
02798     strcat(soap->msgbuf, "\n");
02799     while ((r = ERR_get_error()))
02800       ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
02801   } 
02802   else
02803   { switch (ret)
02804     { case 0:
02805         strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
02806         break;
02807       case -1:
02808         sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));  
02809         break;
02810     }
02811   }
02812   return soap->msgbuf;
02813 }
02814 #endif
02815 
02816 /******************************************************************************/
02817 #ifndef PALM_1
02818 static int
02819 ssl_password(char *buf, int num, int rwflag, void *userdata)
02820 { if (num < (int)strlen((char*)userdata) + 1)
02821     return 0;
02822   return strlen(strcpy(buf, (char*)userdata));
02823 }
02824 #endif
02825 
02826 /******************************************************************************/
02827 /* This callback is included for future references. It should not be deleted
02828 #ifndef PALM_2
02829 static DH *
02830 ssl_tmp_dh(SSL *ssl, int is_export, int keylength)
02831 { static DH *dh512 = NULL;
02832   static DH *dh1024 = NULL;
02833   DH *dh;
02834   switch (keylength)
02835   { case 512:
02836       if (!dh512)
02837       { BIO *bio = BIO_new_file("dh512.pem", "r");
02838         if (bio)
02839         { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
02840           BIO_free(bio);
02841           return dh512;
02842         }
02843       }
02844       else
02845         return dh512;
02846     default:
02847       if (!dh1024)
02848       { BIO *bio = BIO_new_file("dh1024.pem", "r");
02849         if (bio)
02850         { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
02851           BIO_free(bio);
02852         }
02853       }
02854       dh = dh1024;
02855   }
02856   return dh;
02857 }
02858 #endif
02859 */
02860 
02861 /******************************************************************************/
02862 #ifndef PALM_1
02863 static int
02864 ssl_auth_init(struct soap *soap)
02865 { if (!ssl_init_done)
02866     soap_ssl_init();
02867   if (!soap->ctx)
02868   { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
02869       return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
02870   }
02871   if (soap->randfile)
02872   { if (!RAND_load_file(soap->randfile, -1))
02873       return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
02874   }
02875   if (soap->cafile || soap->capath)
02876   { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
02877       return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR);
02878     if (soap->cafile && soap->require_client_auth)
02879       SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
02880   }
02881   if (!SSL_CTX_set_default_verify_paths(soap->ctx))
02882     return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
02883 /* See below */
02884   if (soap->keyfile)
02885   { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
02886       return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
02887     if (soap->password)
02888     { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
02889       SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
02890     }
02891     if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
02892       return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
02893   }
02894 /* Suggested alternative approach to check cafile first before the key file:
02895   if (soap->password)
02896   { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
02897     SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
02898   }
02899   if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
02900   { if (soap->keyfile)
02901     { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
02902         return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR);
02903       if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
02904         return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
02905     }
02906   }
02907 */
02908   if (soap->rsa)
02909   { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
02910     if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
02911     { if (rsa)
02912         RSA_free(rsa);
02913       return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
02914     }
02915     RSA_free(rsa);
02916   }
02917   else if (soap->dhfile)
02918   { DH *dh = 0;
02919     BIO *bio;
02920     bio = BIO_new_file(soap->dhfile, "r");
02921     if (!bio)
02922       return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
02923     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
02924     BIO_free(bio);
02925     if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
02926     { if (dh)
02927         DH_free(dh);
02928       return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
02929     }
02930     DH_free(dh);
02931   }
02932   SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
02933   SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify);
02934 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
02935   SSL_CTX_set_verify_depth(soap->ctx, 1); 
02936 #else
02937   SSL_CTX_set_verify_depth(soap->ctx, 9); 
02938 #endif  
02939   return SOAP_OK;
02940 }
02941 #endif
02942 
02943 /******************************************************************************/
02944 #ifndef PALM_1
02945 static int
02946 ssl_verify_callback(int ok, X509_STORE_CTX *store)
02947 {
02948 #ifdef SOAP_DEBUG
02949   if (!ok) 
02950   { char data[256];
02951     X509 *cert = X509_STORE_CTX_get_current_cert(store);
02952     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(X509_STORE_CTX_get_error(store)));
02953     X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
02954     fprintf(stderr, "certificate issuer %s\n", data);
02955     X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
02956     fprintf(stderr, "certificate subject %s\n", data);
02957   }
02958 #endif
02959   /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
02960   return ok;
02961 }
02962 #endif
02963 
02964 /******************************************************************************/
02965 #ifndef PALM_1
02966 SOAP_FMAC1
02967 int
02968 SOAP_FMAC2
02969 soap_ssl_accept(struct soap *soap)
02970 { BIO *bio;
02971   int i, r;
02972   if (!soap_valid_socket(soap->socket))
02973     return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
02974   if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
02975     return SOAP_INVALID_SOCKET;
02976   if (!soap->ssl)
02977   { soap->ssl = SSL_new(soap->ctx);
02978     if (!soap->ssl)
02979       return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
02980   }
02981   else
02982     SSL_clear(soap->ssl);
02983   soap->imode |= SOAP_ENC_SSL;
02984   soap->omode |= SOAP_ENC_SSL;
02985 #if defined(WIN32)
02986   { u_long nonblocking = 1;
02987     ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking);
02988   }
02989 #elif defined(VXWORKS)
02990   { u_long nonblocking = 1;
02991     ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&nonblocking);
02992   }
02993 #else
02994   fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK);
02995 #endif
02996   bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE);
02997   SSL_set_bio(soap->ssl, bio, bio);
02998   i = 100; /* 100 * 0.1 ms retries */
02999   while ((r = SSL_accept(soap->ssl)) <= 0)
03000   { int err = SSL_get_error(soap->ssl, r);
03001     if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
03002     { struct timeval timeout;
03003       fd_set fd;
03004       if (i-- <= 0)
03005         break;
03006       timeout.tv_sec = 0;
03007       timeout.tv_usec = 100000;
03008 #ifndef WIN32
03009       if ((int)soap->socket > FD_SETSIZE)
03010         return SOAP_FD_EXCEEDED;        /* Hint: MUST increase FD_SETSIZE */
03011 #endif
03012       FD_ZERO(&fd);
03013       FD_SET((SOAP_SOCKET)soap->socket, &fd);
03014       r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
03015       if (r < 0 && soap_socket_errno != SOAP_EINTR)
03016       { soap->errnum = soap_socket_errno;
03017         return SOAP_EOF;
03018       }
03019     }
03020     else
03021     { soap->errnum = err;
03022       break;
03023     }
03024   }
03025 #if defined(WIN32)
03026   { u_long blocking = 0;
03027     ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
03028   }
03029 #elif defined(VXWORKS)
03030   { u_long blocking = 0;
03031     ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&blocking);
03032   }
03033 #else
03034   fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
03035 #endif
03036   if (r <= 0)
03037   { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
03038     soap_closesock(soap);
03039     return SOAP_SSL_ERROR;
03040   }
03041   if (soap->require_client_auth)
03042   { X509 *peer;
03043     int err;
03044     if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
03045     { soap_closesock(soap);
03046       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);
03047     }
03048     peer = SSL_get_peer_certificate(soap->ssl);
03049     if (!peer)
03050     { soap_closesock(soap);
03051       return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
03052     }
03053     X509_free(peer);
03054   }
03055   return SOAP_OK;
03056 }
03057 #endif
03058 
03059 /******************************************************************************/
03060 #endif /* WITH_OPENSSL */
03061 
03062 /******************************************************************************/
03063 #ifndef WITH_NOIO
03064 #ifndef PALM_1
03065 static int
03066 tcp_init(struct soap *soap)
03067 { soap->errmode = 1;
03068 #ifdef WIN32
03069   if (tcp_done)
03070     return 0;
03071   else
03072   { WSADATA w;
03073     if (WSAStartup(MAKEWORD(1, 1), &w))
03074       return -1;
03075     tcp_done = 1;
03076   }
03077 #endif
03078   return 0;
03079 }
03080 #endif
03081 #endif
03082 
03083 /******************************************************************************/
03084 #ifndef PALM_1
03085 SOAP_FMAC1
03086 void
03087 SOAP_FMAC2
03088 soap_done(struct soap *soap)
03089 { 
03090 #ifdef SOAP_DEBUG
03091   int i;
03092 #endif
03093   if (soap_check_state(soap))
03094     return;
03095   soap_free(soap);
03096   while (soap->clist)
03097   { struct soap_clist *p = soap->clist->next;
03098     SOAP_FREE(soap, soap->clist);
03099     soap->clist = p;
03100   }
03101   soap->keep_alive = 0; /* to force close the socket */
03102   soap_closesock(soap);
03103 #ifdef WITH_COOKIES
03104   soap_free_cookies(soap);
03105 #endif
03106   while (soap->plugins)
03107   { register struct soap_plugin *p = soap->plugins->next;
03108     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
03109     if (soap->plugins->fcopy || soap->state == SOAP_INIT)
03110       soap->plugins->fdelete(soap, soap->plugins);
03111     SOAP_FREE(soap, soap->plugins);
03112     soap->plugins = p;
03113   }
03114   soap->fplugin = fplugin;
03115 #ifndef WITH_NOHTTP
03116   soap->fpost = http_post;
03117   soap->fget = http_get;
03118   soap->fform = NULL;
03119   soap->fposthdr = http_post_header;
03120   soap->fresponse = http_response;
03121   soap->fparse = http_parse;
03122   soap->fparsehdr = http_parse_header;
03123 #endif
03124   soap->fheader = NULL;
03125 #ifndef WITH_NOIO
03126 #ifndef WITH_IPV6
03127   soap->fresolve = tcp_gethost;
03128 #else
03129   soap->fresolve = NULL;
03130 #endif
03131   soap->faccept = tcp_accept;
03132   soap->fopen = tcp_connect;
03133   soap->fclose = tcp_disconnect;
03134   soap->fclosesocket = tcp_closesocket;
03135   soap->fshutdownsocket = tcp_shutdownsocket;
03136   soap->fsend = fsend;
03137   soap->frecv = frecv;
03138   soap->fpoll = soap_poll;
03139 #else
03140   soap->fopen = NULL;
03141   soap->fclose = NULL;
03142   soap->fpoll = NULL;
03143 #endif
03144 #ifndef WITH_LEANER
03145   soap->fprepareinit = NULL;
03146   soap->fpreparesend = NULL;
03147   soap->fpreparerecv = NULL;
03148   soap->fpreparefinal = NULL;
03149 #endif
03150   soap->fseterror = NULL;
03151   soap->fignore = NULL;
03152   soap->fserveloop = NULL;
03153 #ifdef WITH_OPENSSL
03154   if (soap->session)
03155   { SSL_SESSION_free(soap->session);
03156     soap->session = NULL;
03157   }
03158 #endif
03159   if (soap->state == SOAP_INIT)
03160   { if (soap_valid_socket(soap->master))
03161     { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
03162       soap->master = SOAP_INVALID_SOCKET;
03163     }
03164 #ifdef WITH_OPENSSL
03165     if (soap->ctx)
03166     { SSL_CTX_free(soap->ctx);
03167       soap->ctx = NULL;
03168     }
03169 #endif
03170   }
03171 #ifdef SOAP_DEBUG
03172   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
03173   for (i = 0; i < SOAP_MAXLOGS; i++)
03174   { if (soap->logfile[i])
03175     { SOAP_FREE(soap, (void*)soap->logfile[i]);
03176       soap->logfile[i] = NULL;
03177     }
03178     soap_close_logfile(soap, i);
03179   }
03180   soap_free_mht(soap);
03181   soap->state = 0;
03182 #endif
03183 }
03184 #endif
03185 
03186 /******************************************************************************/
03187 #ifndef WITH_NOIO
03188 #ifndef PALM_2
03189 SOAP_FMAC1
03190 void
03191 SOAP_FMAC2
03192 soap_cleanup(struct soap *soap)
03193 { soap_done(soap);
03194 #ifdef WIN32
03195   if (!tcp_done)
03196     return;
03197   tcp_done = 0;
03198   WSACleanup();
03199 #endif
03200 }
03201 #endif
03202 #endif
03203 
03204 /******************************************************************************/
03205 #ifndef WITH_NOIO
03206 #ifndef PALM_1
03207 static const char*
03208 tcp_error(struct soap *soap)
03209 { register const char *msg = NULL;
03210   switch (soap->errmode)
03211   { case 0:
03212       msg = soap_strerror(soap);
03213       break;
03214     case 1:
03215       msg = "WSAStartup failed";
03216       break;
03217     case 2:
03218     {
03219 #ifndef WITH_LEAN
03220       msg = soap_code_str(h_error_codes, soap->errnum);
03221       if (!msg)
03222 #endif
03223       { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
03224         msg = soap->msgbuf;
03225       }
03226     }
03227   }
03228   return msg;
03229 }
03230 #endif
03231 #endif
03232 
03233 /******************************************************************************/
03234 #ifndef WITH_NOHTTP
03235 #ifndef PALM_1
03236 static const char*
03237 http_error(struct soap *soap, int status)
03238 { register const char *msg = SOAP_STR_EOS;
03239 #ifndef WITH_LEAN
03240   msg = soap_code_str(h_http_error_codes, status);
03241   if (!msg)
03242     msg = SOAP_STR_EOS;
03243 #endif
03244   return msg;
03245 }
03246 #endif
03247 #endif
03248 
03249 /******************************************************************************/
03250 #ifndef WITH_IPV6
03251 #ifndef WITH_NOIO
03252 #ifndef PALM_1
03253 static int
03254 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
03255 { soap_int32 iadd = -1;
03256   struct hostent hostent, *host = &hostent;
03257 #ifdef VXWORKS
03258   int hostint;
03259   /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
03260   iadd = inet_addr((char*)addr);
03261 #else
03262 #if defined(_AIXVERSION_431) || defined(TRU64)
03263   struct hostent_data ht_data;
03264 #endif
03265 #ifdef AS400
03266   iadd = inet_addr((void*)addr);
03267 #else
03268   iadd = inet_addr(addr);
03269 #endif
03270 #endif
03271   if (iadd != -1)
03272   { memcpy(inaddr, &iadd, sizeof(iadd));
03273     return SOAP_OK;
03274   }
03275 #if defined(__GLIBC__)
03276   if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
03277     host = NULL;
03278 #elif defined(_AIXVERSION_431) || defined(TRU64)
03279   memset((void*)&ht_data, 0, sizeof(ht_data));
03280   if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
03281   { host = NULL;
03282     soap->errnum = h_errno;
03283   }
03284 #elif defined(HAVE_GETHOSTBYNAME_R)
03285   host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
03286 #elif defined(VXWORKS)
03287   /* If the DNS resolver library resolvLib has been configured in the vxWorks
03288    * image, a query for the host IP address is sent to the DNS server, if the
03289    * name was not found in the local host table. */
03290   hostint = hostGetByName((char*)addr);
03291   if (hostint == ERROR)
03292   { host = NULL;
03293     soap->errnum = soap_errno; 
03294   }
03295 #else
03296 #ifdef AS400
03297   if (!(host = gethostbyname((void*)addr)))
03298     soap->errnum = h_errno;
03299 #else
03300   if (!(host = gethostbyname(addr)))
03301     soap->errnum = h_errno;
03302 #endif
03303 #endif
03304   if (!host)
03305   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
03306     return SOAP_ERR;
03307   }
03308 #ifdef VXWORKS
03309   inaddr->s_addr = hostint;
03310 #else
03311   memcpy(inaddr, host->h_addr, host->h_length);
03312 #endif
03313   return SOAP_OK;
03314 }
03315 #endif
03316 #endif
03317 #endif
03318 
03319 /******************************************************************************/
03320 #ifndef WITH_NOIO
03321 #ifndef PALM_1
03322 static int
03323 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
03324 {
03325 #ifdef WITH_IPV6
03326   struct addrinfo hints, *res, *ressave;
03327   int err;
03328 #endif
03329   register int fd;
03330 #ifndef WITH_LEAN
03331   int len = SOAP_BUFLEN;
03332   int set = 1;
03333 #endif
03334   if (soap_valid_socket(soap->socket))
03335     soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
03336   soap->socket = SOAP_INVALID_SOCKET;
03337   if (tcp_init(soap))
03338   { soap->errnum = 0;
03339     soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
03340     return SOAP_INVALID_SOCKET;
03341   }
03342   soap->errmode = 0;
03343 #ifdef WITH_IPV6
03344   memset((void*)&hints, 0, sizeof(hints));
03345   hints.ai_family = PF_UNSPEC;
03346 #ifdef WITH_UDP
03347   if ((soap->omode & SOAP_IO_UDP))
03348     hints.ai_socktype = SOCK_DGRAM;
03349   else
03350 #endif
03351     hints.ai_socktype = SOCK_STREAM;
03352   soap->errmode = 2;
03353   if (soap->proxy_host)
03354     err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
03355   else
03356     err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
03357   if (err)
03358   { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
03359     return SOAP_INVALID_SOCKET;
03360   }
03361   ressave = res;
03362 again:
03363   fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol);
03364   soap->errmode = 0;
03365 #else
03366 #ifdef WITH_UDP
03367   if ((soap->omode & SOAP_IO_UDP))
03368     fd = (int)socket(AF_INET, SOCK_DGRAM, 0);
03369   else
03370 #endif
03371     fd = (int)socket(AF_INET, SOCK_STREAM, 0);
03372 #endif
03373   if (fd < 0)
03374   { soap->errnum = soap_socket_errno;
03375     soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
03376     return SOAP_INVALID_SOCKET;
03377   }
03378 #ifdef SOCKET_CLOSE_ON_EXEC
03379 #ifdef WIN32
03380 #ifndef UNDER_CE
03381   SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
03382 #endif
03383 #else
03384   fcntl(fd, F_SETFD, 1);
03385 #endif
03386 #endif
03387 #ifndef WITH_LEAN
03388   if (soap->connect_flags == SO_LINGER)
03389   { struct linger linger;
03390     memset((void*)&linger, 0, sizeof(linger));
03391     linger.l_onoff = 1;
03392     linger.l_linger = 0;
03393     if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
03394     { soap->errnum = soap_socket_errno;
03395       soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
03396       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03397       return SOAP_INVALID_SOCKET;
03398     }
03399   }
03400   else if (soap->connect_flags && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
03401   { soap->errnum = soap_socket_errno;
03402     soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
03403     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03404     return SOAP_INVALID_SOCKET;
03405   }
03406   if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
03407   { soap->errnum = soap_socket_errno;
03408     soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
03409     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03410     return SOAP_INVALID_SOCKET;
03411   }
03412   if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
03413   { soap->errnum = soap_socket_errno;
03414     soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
03415     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03416     return SOAP_INVALID_SOCKET;
03417   }
03418   if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
03419   { soap->errnum = soap_socket_errno;
03420     soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
03421     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03422     return SOAP_INVALID_SOCKET;
03423   }
03424 #ifdef TCP_NODELAY
03425   if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
03426   { soap->errnum = soap_socket_errno;
03427     soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
03428     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03429     return SOAP_INVALID_SOCKET;
03430   }
03431 #endif
03432 #endif
03433   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
03434 #ifndef WITH_IPV6
03435   soap->peerlen = sizeof(soap->peer);
03436   memset((void*)&soap->peer, 0, sizeof(soap->peer));
03437   soap->peer.sin_family = AF_INET;
03438   soap->errmode = 2;
03439   if (soap->proxy_host)
03440   { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
03441     { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
03442       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03443       return SOAP_INVALID_SOCKET;
03444     }
03445     soap->peer.sin_port = htons((short)soap->proxy_port);
03446   }
03447   else
03448   { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
03449     { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
03450       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03451       return SOAP_INVALID_SOCKET;
03452     }
03453     soap->peer.sin_port = htons((short)port);
03454   }
03455   soap->errmode = 0;
03456   if ((soap->omode & SOAP_IO_UDP))
03457     return fd;
03458 #endif
03459 #ifndef WITH_LEAN
03460   if (soap->connect_timeout)
03461 #if defined(WIN32)
03462   { u_long nonblocking = 1;
03463     ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
03464   }
03465 #elif defined(VXWORKS)
03466   { u_long nonblocking = 1;
03467     ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */
03468   }
03469 #else
03470     fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
03471 #endif
03472   else
03473 #if defined(WIN32)
03474   { u_long blocking = 0;
03475     ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
03476   }
03477 #elif defined(VXWORKS)
03478   { u_long blocking = 0;
03479     ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
03480   }
03481 #else
03482     fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
03483 #endif
03484 #endif
03485   for (;;)
03486   { 
03487 #ifdef WITH_IPV6
03488     if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen))
03489 #else
03490     if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
03491 #endif
03492     { 
03493 #ifndef WITH_LEAN
03494       if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK))
03495       { struct timeval timeout;
03496         SOAP_SOCKLEN_T k;
03497         fd_set fds;
03498         if (soap->connect_timeout > 0)
03499         { timeout.tv_sec = soap->connect_timeout;
03500           timeout.tv_usec = 0;
03501         }
03502         else
03503         { timeout.tv_sec = -soap->connect_timeout/1000000;
03504           timeout.tv_usec = -soap->connect_timeout%1000000;
03505         }
03506 #ifndef WIN32
03507         if ((int)soap->socket > FD_SETSIZE)
03508         { soap->error = SOAP_FD_EXCEEDED;
03509           return SOAP_INVALID_SOCKET;   /* Hint: MUST increase FD_SETSIZE */
03510         }
03511 #endif
03512         FD_ZERO(&fds);
03513         FD_SET((SOAP_SOCKET)fd, &fds);
03514         for (;;)
03515         { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout);
03516           if (r > 0)
03517             break;
03518           if (!r)
03519           { soap->errnum = 0;
03520             DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
03521             soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03522             soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03523             return SOAP_INVALID_SOCKET;
03524           }
03525           if (soap_socket_errno != SOAP_EINTR)
03526           { soap->errnum = soap_socket_errno;
03527             DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
03528             soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03529             soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03530             return SOAP_INVALID_SOCKET;
03531           }
03532         }
03533         k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
03534         if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum)      /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
03535           break;
03536         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
03537         soap->errnum = soap_socket_errno;
03538         soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03539         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03540         return SOAP_INVALID_SOCKET;
03541       }
03542       else
03543 #endif
03544 #ifdef WITH_IPV6
03545       if (res->ai_next)
03546       { res = res->ai_next;
03547         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03548         goto again;
03549       }
03550       else
03551 #endif
03552       if (soap_socket_errno != SOAP_EINTR)
03553       { soap->errnum = soap_socket_errno;
03554         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
03555         soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03556         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03557         return SOAP_INVALID_SOCKET;
03558       }
03559     }  
03560     else
03561       break;
03562   }
03563 #ifdef WITH_IPV6
03564   soap->peerlen = 0; /* IPv6: already connected so use send() */
03565   freeaddrinfo(ressave);
03566 #endif
03567 #ifndef WITH_LEAN
03568   if (soap->connect_timeout)
03569 #if defined(WIN32)
03570   { u_long blocking = 0;
03571     ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
03572   }
03573 #elif defined(VXWORKS)
03574   { u_long blocking = 0;
03575     ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
03576   }
03577 #else
03578     fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
03579 #endif
03580 #endif
03581   soap->socket = fd;
03582   soap->imode &= ~SOAP_ENC_SSL;
03583   soap->omode &= ~SOAP_ENC_SSL;
03584   if (!soap_tag_cmp(endpoint, "https:*"))
03585   {
03586 #ifdef WITH_OPENSSL
03587     BIO *bio;
03588     int r;
03589     if (soap->proxy_host)
03590     { unsigned int k = soap->omode; /* make sure we only parse HTTP */
03591       size_t n = soap->count; /* save the content length */
03592       char *userid, *passwd;
03593       soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
03594       soap->omode |= SOAP_IO_BUFFER;
03595       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n"));
03596       sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version);
03597       if (soap_begin_send(soap)
03598        || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
03599       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03600         return SOAP_INVALID_SOCKET;
03601       }
03602 #ifndef WITH_LEAN
03603       if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
03604       { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
03605         strcpy(soap->tmpbuf, "Basic ");
03606         soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
03607         if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
03608         { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03609           return soap->error;
03610         }
03611       }
03612 #endif
03613       if ((soap->error = soap->fposthdr(soap, NULL, NULL))
03614        || soap_flush(soap))
03615       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03616         return SOAP_INVALID_SOCKET;
03617       }
03618       soap->omode = k;
03619       k = soap->imode;
03620       soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
03621       userid = soap->userid; /* preserve */
03622       passwd = soap->passwd; /* preserve */
03623       if ((soap->error = soap->fparse(soap)))
03624       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03625         return SOAP_INVALID_SOCKET;
03626       }
03627       soap->userid = userid; /* restore */
03628       soap->passwd = passwd; /* restore */
03629       soap->imode = k; /* restore */
03630       soap->count = n; /* restore */
03631       if (soap_begin_send(soap))
03632       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03633         return SOAP_INVALID_SOCKET;
03634       }
03635     }
03636     if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
03637     { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
03638       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03639       return SOAP_INVALID_SOCKET;
03640     }
03641     soap->ssl = SSL_new(soap->ctx);
03642     if (!soap->ssl)
03643     { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03644       soap->error = SOAP_SSL_ERROR;
03645       return SOAP_INVALID_SOCKET;
03646     }
03647     if (soap->session)
03648     { if (!strcmp(soap->session_host, host) && soap->session_port == port)
03649         SSL_set_session(soap->ssl, soap->session);
03650       SSL_SESSION_free(soap->session);
03651       soap->session = NULL;
03652     }
03653     soap->imode |= SOAP_ENC_SSL;
03654     soap->omode |= SOAP_ENC_SSL;
03655     bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE);
03656     SSL_set_bio(soap->ssl, bio, bio);
03657 #ifndef WITH_LEAN
03658     if (soap->connect_timeout)
03659 #if defined(WIN32)
03660     { u_long nonblocking = 1;
03661       ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
03662     }
03663 #elif defined(VXWORKS)
03664     { u_long nonblocking = 1;
03665       ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking));
03666     }
03667 #else
03668       fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
03669 #endif
03670 #endif
03671     for (;;)
03672     { if ((r = SSL_connect(soap->ssl)) <= 0)
03673       { int err = SSL_get_error(soap->ssl, r);
03674         if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
03675         { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR);
03676           soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03677           return SOAP_INVALID_SOCKET;
03678         }
03679         if (soap->connect_timeout)
03680         { struct timeval timeout;
03681           fd_set fds;
03682           if (soap->connect_timeout > 0)
03683           { timeout.tv_sec = soap->connect_timeout;
03684             timeout.tv_usec = 0;
03685           }
03686           else
03687           { timeout.tv_sec = -soap->connect_timeout/1000000;
03688             timeout.tv_usec = -soap->connect_timeout%1000000;
03689           }
03690 #ifndef WIN32
03691           if ((int)soap->socket > FD_SETSIZE)
03692           { soap->error = SOAP_FD_EXCEEDED;
03693             return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
03694           }
03695 #endif
03696           FD_ZERO(&fds);
03697           FD_SET((SOAP_SOCKET)fd, &fds);
03698           for (;;)
03699           { int r = select((SOAP_SOCKET)(fd + 1), &fds, NULL, &fds, &timeout);
03700             if (r > 0)
03701               break;
03702             if (!r)
03703             { soap->errnum = 0;
03704               DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
03705               soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
03706               soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03707               return SOAP_INVALID_SOCKET;
03708             }
03709           }
03710           continue;
03711         }
03712       }
03713       break;
03714     }
03715 #ifndef WITH_LEAN
03716     if (soap->connect_timeout)
03717 #ifdef WIN32
03718     { u_long blocking = 0;
03719       ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
03720     }
03721 #elif defined(VXWORKS)
03722     { u_long blocking = 0;
03723       ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
03724     }
03725 #else
03726       fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
03727 #endif
03728 #endif
03729     if (soap->require_server_auth)
03730     { X509 *peer;
03731       X509_NAME *subj;
03732       int ext_count;
03733       int err;
03734       int ok = 0;
03735       if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
03736       { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
03737         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03738         return SOAP_INVALID_SOCKET;
03739       }
03740       peer = SSL_get_peer_certificate(soap->ssl);
03741       if (!peer)
03742       { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
03743         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03744         return SOAP_INVALID_SOCKET;
03745       }
03746       ext_count = X509_get_ext_count(peer);
03747       if (ext_count > 0)
03748       { int i;
03749         for (i = 0; i < ext_count; i++)
03750         { X509_EXTENSION *ext = X509_get_ext(peer, i);
03751           const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
03752           if (!strcmp(ext_str, "subjectAltName"))
03753           { int j;
03754             STACK_OF(CONF_VALUE) *val;
03755             X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext);
03756             if (!meth)
03757               break;
03758             val = meth->i2v(meth, meth->d2i(NULL, (unsigned char**)&ext->value->data, ext->value->length), NULL);
03759             for (j = 0; j < sk_CONF_VALUE_num(val); j++)
03760             { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
03761               if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
03762               { ok = 1;
03763                 break;
03764               }
03765             }
03766           }
03767           if (ok)
03768             break;
03769         }
03770       }
03771       if (!ok && (subj = X509_get_subject_name(peer)))
03772       { X509_NAME_get_text_by_NID(subj, NID_commonName, soap->msgbuf, sizeof(soap->msgbuf));
03773         if (soap_tag_cmp(soap->msgbuf, host))
03774         { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
03775           soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03776           X509_free(peer);
03777           return SOAP_INVALID_SOCKET;
03778         }
03779       }
03780       X509_free(peer);
03781     }
03782 #else
03783     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
03784     soap->error = SOAP_SSL_ERROR;
03785     return SOAP_INVALID_SOCKET;
03786 #endif
03787   }
03788   return fd;
03789 }
03790 #endif
03791 #endif
03792 
03793 /******************************************************************************/
03794 #ifndef WITH_NOIO
03795 #ifndef PALM_1
03796 SOAP_FMAC1
03797 int
03798 SOAP_FMAC2
03799 soap_bind(struct soap *soap, const char *host, int port, int backlog)
03800 {
03801 #ifdef WITH_IPV6
03802   struct addrinfo *addrinfo = NULL;
03803   struct addrinfo hints;
03804   struct addrinfo res;
03805   int err;
03806 #endif
03807 #ifndef WITH_LEAN
03808   int len = SOAP_BUFLEN;
03809   int set = 1;
03810 #endif
03811   if (soap_valid_socket(soap->master))
03812   { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
03813     soap->master = SOAP_INVALID_SOCKET;
03814   }
03815   soap->socket = SOAP_INVALID_SOCKET;
03816   soap->errmode = 1;
03817   if (tcp_init(soap))
03818   { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
03819     return SOAP_INVALID_SOCKET;
03820   }
03821 #ifdef WITH_IPV6
03822   memset((void*)&hints, 0, sizeof(hints));
03823   hints.ai_family = PF_UNSPEC;
03824 #ifdef WITH_UDP
03825   if ((soap->omode & SOAP_IO_UDP))
03826     hints.ai_socktype = SOCK_DGRAM;
03827   else
03828 #endif
03829     hints.ai_socktype = SOCK_STREAM;
03830   hints.ai_flags = AI_PASSIVE;
03831   soap->errmode = 2;
03832   err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
03833   if (addrinfo)
03834   { res = *addrinfo;
03835     soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr);
03836     soap->peerlen = addrinfo->ai_addrlen;
03837     res.ai_addr = (struct sockaddr*)&soap->peer;
03838     res.ai_addrlen = soap->peerlen;
03839     freeaddrinfo(addrinfo);
03840   }
03841   if (err)
03842   { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
03843     return SOAP_INVALID_SOCKET;
03844   }
03845   soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol);
03846 #else
03847 #ifdef WITH_UDP
03848   if ((soap->omode & SOAP_IO_UDP))
03849     soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
03850   else
03851 #endif
03852     soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
03853 #endif
03854   soap->errmode = 0;
03855   if (!soap_valid_socket(soap->master))
03856   { soap->errnum = soap_socket_errno;
03857     soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
03858     return SOAP_INVALID_SOCKET;
03859   }
03860 #ifdef WITH_UDP
03861   if ((soap->omode & SOAP_IO_UDP))
03862     soap->socket = soap->master;
03863 #endif
03864 #ifdef SOCKET_CLOSE_ON_EXEC
03865 #ifdef WIN32
03866 #ifndef UNDER_CE
03867   SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
03868 #endif
03869 #else
03870   fcntl(soap->master, F_SETFD, 1);
03871 #endif
03872 #endif
03873 #ifndef WITH_LEAN
03874   if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
03875   { soap->errnum = soap_socket_errno;
03876     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
03877     return SOAP_INVALID_SOCKET;
03878   }
03879   if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
03880   { soap->errnum = soap_socket_errno;
03881     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
03882     return SOAP_INVALID_SOCKET;
03883   }
03884   if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
03885   { soap->errnum = soap_socket_errno;
03886     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
03887     return SOAP_INVALID_SOCKET;
03888   }
03889   if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
03890   { soap->errnum = soap_socket_errno;
03891     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
03892     return SOAP_INVALID_SOCKET;
03893   }
03894 #ifdef TCP_NODELAY
03895   if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
03896   { soap->errnum = soap_socket_errno;
03897     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
03898     return SOAP_INVALID_SOCKET;
03899   }
03900 #endif
03901 #endif
03902 #ifdef WITH_IPV6
03903   soap->errmode = 0;
03904   if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen))
03905   { soap->errnum = soap_socket_errno;
03906     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
03907     soap_closesock(soap);
03908     soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
03909     return SOAP_INVALID_SOCKET;
03910   }  
03911 #else
03912   soap->peerlen = sizeof(soap->peer);
03913   memset((void*)&soap->peer, 0, sizeof(soap->peer));
03914   soap->peer.sin_family = AF_INET;
03915   soap->errmode = 2;
03916   if (host)
03917   { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
03918     { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
03919       return SOAP_INVALID_SOCKET;
03920     }
03921   }
03922   else
03923     soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
03924   soap->peer.sin_port = htons((short)port);
03925   soap->errmode = 0;
03926   if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen))
03927   { soap->errnum = soap_socket_errno;
03928     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
03929     soap_closesock(soap);
03930     soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
03931     return SOAP_INVALID_SOCKET;
03932   }
03933 #endif
03934   if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog))
03935   { soap->errnum = soap_socket_errno;
03936     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
03937     soap_closesock(soap);
03938     soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
03939     return SOAP_INVALID_SOCKET;
03940   }  
03941   return soap->master;
03942 }
03943 #endif
03944 #endif
03945 
03946 /******************************************************************************/
03947 #ifndef WITH_NOIO
03948 #ifndef PALM_1
03949 SOAP_FMAC1
03950 int
03951 SOAP_FMAC2
03952 soap_poll(struct soap *soap)
03953 { 
03954 #ifndef WITH_LEAN
03955   struct timeval timeout;
03956   fd_set rfd, sfd, xfd;
03957   int r;
03958   timeout.tv_sec = 0;
03959   timeout.tv_usec = 0;
03960 #ifndef WIN32
03961   if ((int)soap->socket > FD_SETSIZE)
03962     return SOAP_FD_EXCEEDED;    /* Hint: MUST increase FD_SETSIZE */
03963 #endif
03964   FD_ZERO(&rfd);
03965   FD_ZERO(&sfd);
03966   FD_ZERO(&xfd);
03967   if (soap_valid_socket(soap->socket))
03968   { FD_SET((SOAP_SOCKET)soap->socket, &rfd);
03969     FD_SET((SOAP_SOCKET)soap->socket, &sfd);
03970     FD_SET((SOAP_SOCKET)soap->socket, &xfd);
03971     r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout);
03972     if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd))
03973       r = -1;
03974   }
03975   else if (soap_valid_socket(soap->master))
03976   { FD_SET((SOAP_SOCKET)soap->master, &sfd);
03977     r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout);
03978   }
03979   else
03980     return SOAP_OK;
03981   if (r > 0)
03982   {
03983 #ifdef WITH_OPENSSL
03984     if (soap->imode & SOAP_ENC_SSL)
03985     {
03986       if (soap_valid_socket(soap->socket)
03987        && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
03988        && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
03989         || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
03990         return SOAP_OK;
03991     }
03992     else
03993 #endif
03994       if (soap_valid_socket(soap->socket)
03995        && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
03996        && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
03997         || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
03998         return SOAP_OK;
03999   }
04000   else if (r < 0)
04001   { soap->errnum = soap_socket_errno;
04002     if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR)
04003     { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
04004       return soap->error = SOAP_TCP_ERROR;
04005     }
04006   }
04007   else
04008     soap->errnum = 0;
04009   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
04010   return SOAP_EOF;
04011 #else
04012   return SOAP_OK;
04013 #endif
04014 }
04015 #endif
04016 #endif
04017 
04018 /******************************************************************************/
04019 #ifndef WITH_NOIO
04020 #ifndef PALM_1
04021 static int
04022 tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n)
04023 { int fd;
04024   fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n);      /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
04025 #ifdef SOCKET_CLOSE_ON_EXEC
04026 #ifdef WIN32
04027 #ifndef UNDER_CE
04028   SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
04029 #endif
04030 #else
04031   fcntl(fd, F_SETFD, FD_CLOEXEC);
04032 #endif
04033 #endif
04034   return fd;
04035 }
04036 #endif
04037 #endif
04038 
04039 /******************************************************************************/
04040 #ifndef WITH_NOIO
04041 #ifndef PALM_1
04042 SOAP_FMAC1
04043 int
04044 SOAP_FMAC2
04045 soap_accept(struct soap *soap)
04046 { int n = (int)sizeof(soap->peer);
04047 #ifndef WITH_LEAN
04048   int len = SOAP_BUFLEN;
04049   int set = 1;
04050 #endif
04051   soap->error = SOAP_OK;
04052 #ifdef WITH_UDP
04053   if ((soap->omode & SOAP_IO_UDP))
04054     return soap->socket = soap->master;
04055 #endif
04056   memset((void*)&soap->peer, 0, sizeof(soap->peer));
04057   soap->socket = SOAP_INVALID_SOCKET;
04058   soap->errmode = 0;
04059   soap->keep_alive = 0;
04060   if (soap_valid_socket(soap->master))
04061   { for (;;)
04062     { 
04063 #ifndef WITH_LEAN
04064       if (soap->accept_timeout)
04065       { struct timeval timeout;
04066         fd_set fd;
04067         if (soap->accept_timeout > 0)
04068         { timeout.tv_sec = soap->accept_timeout;
04069           timeout.tv_usec = 0;
04070         }
04071         else
04072         { timeout.tv_sec = -soap->accept_timeout/1000000;
04073           timeout.tv_usec = -soap->accept_timeout%1000000;
04074         }
04075 #ifndef WIN32
04076         if ((int)soap->socket > FD_SETSIZE)
04077         { soap->error = SOAP_FD_EXCEEDED;
04078           return SOAP_INVALID_SOCKET;   /* Hint: MUST increase FD_SETSIZE */
04079         }
04080 #endif
04081         FD_ZERO(&fd);
04082         FD_SET((SOAP_SOCKET)soap->master, &fd);
04083         for (;;)
04084         { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout);
04085           if (r > 0)
04086             break;
04087           if (!r)
04088           { soap->errnum = 0;
04089             soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
04090             return SOAP_INVALID_SOCKET;
04091           }
04092           if (soap_socket_errno != SOAP_EINTR)
04093           { soap->errnum = soap_socket_errno;
04094             soap_closesock(soap);
04095             soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
04096             return SOAP_INVALID_SOCKET;
04097           }
04098         }
04099 #if defined(WIN32)
04100         { u_long nonblocking = 1;
04101           ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking);
04102         }
04103 #elif defined(VXWORKS)
04104         { u_long nonblocking = 1;
04105           ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&nonblocking));
04106         }
04107 #else
04108         fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK);
04109 #endif
04110       }
04111       else
04112 #if defined(WIN32)
04113       { u_long blocking = 0;
04114         ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
04115       }
04116 #elif defined(VXWORKS)
04117       { u_long blocking = 0;
04118         ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking));
04119       }
04120 #else
04121         fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
04122 #endif
04123 #endif
04124       soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
04125       soap->peerlen = (size_t)n;
04126       if (soap_valid_socket(soap->socket))
04127       {
04128 #ifdef WITH_IPV6
04129 /* Use soap->host to store the numeric form of the remote host */
04130         getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); 
04131         DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
04132         soap->ip = 0; /* info stored in soap->peer and soap->host */
04133         soap->port = 0; /* info stored in soap->peer and soap->host */
04134 #else
04135         soap->ip = ntohl(soap->peer.sin_addr.s_addr);
04136         soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
04137         DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF));
04138 #endif
04139 #ifndef WITH_LEAN
04140         if (soap->accept_flags == SO_LINGER)
04141         { struct linger linger;
04142           memset((void*)&linger, 0, sizeof(linger));
04143           linger.l_onoff = 1;
04144           linger.l_linger = 0;
04145           if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
04146           { soap->errnum = soap_socket_errno;
04147             soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
04148             soap_closesock(soap);
04149             return SOAP_INVALID_SOCKET;
04150           }
04151         }
04152         else if (soap->accept_flags && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
04153         { soap->errnum = soap_socket_errno;
04154           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
04155           soap_closesock(soap);
04156           return SOAP_INVALID_SOCKET;
04157         }
04158         if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
04159         { soap->errnum = soap_socket_errno;
04160           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
04161           soap_closesock(soap);
04162           return SOAP_INVALID_SOCKET;
04163         }
04164         if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
04165         { soap->errnum = soap_socket_errno;
04166           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
04167           soap_closesock(soap);
04168           return SOAP_INVALID_SOCKET;
04169         }
04170         if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
04171         { soap->errnum = soap_socket_errno;
04172           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
04173           soap_closesock(soap);
04174           return SOAP_INVALID_SOCKET;
04175         }
04176 #ifdef TCP_NODELAY
04177         if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
04178         { soap->errnum = soap_socket_errno;
04179           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
04180           soap_closesock(soap);
04181           return SOAP_INVALID_SOCKET;
04182         }
04183 #endif
04184 #endif
04185         if (soap->accept_timeout)
04186         {
04187 #if defined(WIN32)
04188           u_long blocking = 0;
04189           ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
04190           ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
04191 #elif defined(VXWORKS)
04192           u_long blocking = 0;
04193           ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking));
04194           ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&blocking));
04195 #elif defined(PALM)
04196           fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK);
04197           fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK);
04198 #elif defined(SYMBIAN)
04199           long blocking = 0;
04200           ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking);
04201 #else
04202           fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
04203           fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
04204 #endif
04205         }
04206         soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
04207         return soap->socket;
04208       }
04209       if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
04210       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
04211         soap->errnum = soap_socket_errno;
04212         soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
04213         soap_closesock(soap);
04214         return SOAP_INVALID_SOCKET;
04215       }
04216     }
04217   }
04218   else
04219   { soap->errnum = 0;
04220     soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
04221     return SOAP_INVALID_SOCKET;
04222   }
04223 }
04224 #endif
04225 #endif
04226 
04227 /******************************************************************************/
04228 #ifndef WITH_NOIO
04229 #ifndef PALM_1
04230 static int
04231 tcp_disconnect(struct soap *soap)
04232 {
04233 #ifdef WITH_OPENSSL
04234   if (soap->ssl)
04235   { int r, s = 0;
04236     if (soap->session)
04237       SSL_SESSION_free(soap->session);
04238     if (*soap->host)
04239     { soap->session = SSL_get1_session(soap->ssl);
04240       if (soap->session)
04241       { strcpy(soap->session_host, soap->host);
04242         soap->session_port = soap->port;
04243       }
04244     }
04245     r = SSL_shutdown(soap->ssl);
04246     if (r != 1)
04247     { s = ERR_get_error();
04248       if (s)
04249       { if (soap_valid_socket(soap->socket))
04250         { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1);
04251           soap->socket = SOAP_INVALID_SOCKET;
04252         }
04253         r = SSL_shutdown(soap->ssl);
04254       }
04255     }
04256     DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
04257     SSL_free(soap->ssl);
04258     soap->ssl = NULL;
04259     if (s)
04260       return SOAP_SSL_ERROR;
04261     ERR_remove_state(0);
04262   }
04263 #endif
04264   if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
04265   { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2);
04266     soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
04267     soap->socket = SOAP_INVALID_SOCKET;
04268   }
04269   return SOAP_OK;
04270 }
04271 #endif
04272 #endif
04273 
04274 /******************************************************************************/
04275 #ifndef WITH_NOIO
04276 #ifndef PALM_1
04277 static int
04278 tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
04279 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd));
04280   return soap_closesocket(fd);
04281 }
04282 #endif
04283 #endif
04284 
04285 /******************************************************************************/
04286 #ifndef WITH_NOIO
04287 #ifndef PALM_1
04288 static int
04289 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
04290 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how));
04291   return shutdown(fd, how);
04292 }
04293 #endif
04294 #endif
04295 
04296 /******************************************************************************/
04297 #ifndef PALM_1
04298 SOAP_FMAC1
04299 int
04300 SOAP_FMAC2
04301 soap_closesock(struct soap *soap)
04302 { register int status = soap->error;
04303   if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
04304   { if (soap->fclose && (soap->error = soap->fclose(soap)))
04305       return soap->error;
04306     soap->keep_alive = 0;
04307   }
04308 #ifdef WITH_ZLIB
04309   if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
04310     deflateEnd(&soap->d_stream);
04311   else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
04312     inflateEnd(&soap->d_stream);
04313   soap->zlib_state = SOAP_ZLIB_NONE;
04314 #endif
04315   return soap->error = status;
04316 }
04317 #endif
04318 
04319 /******************************************************************************/
04320 #ifndef WITH_NOIDREF
04321 #ifndef PALM_2
04322 SOAP_FMAC1
04323 size_t
04324 SOAP_FMAC2
04325 soap_hash(register const char *s)
04326 { register size_t h = 0;
04327   while (*s)
04328     h = 65599*h + *s++;
04329   return h % SOAP_IDHASH;
04330 }
04331 #endif
04332 #endif
04333 
04334 /******************************************************************************/
04335 #ifndef WITH_NOIDREF
04336 #ifndef PALM_1
04337 static void
04338 soap_init_pht(struct soap *soap)
04339 { register int i;
04340   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n"));
04341   soap->pblk = NULL;
04342   soap->pidx = 0;
04343   for (i = 0; i < (int)SOAP_PTRHASH; i++)
04344     soap->pht[i] = NULL;
04345 }
04346 #endif
04347 #endif
04348 
04349 /******************************************************************************/
04350 #ifndef PALM_1
04351 SOAP_FMAC1
04352 struct soap*
04353 SOAP_FMAC2
04354 soap_new1(soap_mode mode)
04355 { return soap_new2(mode, mode);
04356 }
04357 #endif
04358 
04359 /******************************************************************************/
04360 #ifndef PALM_1
04361 SOAP_FMAC1
04362 struct soap*
04363 SOAP_FMAC2
04364 soap_new()
04365 { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
04366 }
04367 #endif
04368 
04369 /******************************************************************************/
04370 #ifndef PALM_1
04371 SOAP_FMAC1
04372 struct soap*
04373 SOAP_FMAC2
04374 soap_new2(soap_mode imode, soap_mode omode)
04375 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
04376   if (soap)
04377     soap_init2(soap, imode, omode);
04378   return soap;
04379 }
04380 #endif
04381 
04382 /******************************************************************************/
04383 #ifndef PALM_1
04384 SOAP_FMAC1
04385 void
04386 SOAP_FMAC2
04387 soap_del(struct soap *soap)
04388 { free(soap);
04389 }
04390 #endif
04391 
04392 /******************************************************************************/
04393 #ifndef WITH_NOIDREF
04394 #ifndef PALM_1
04395 static void
04396 soap_free_pht(struct soap *soap)
04397 { register struct soap_pblk *pb, *next;
04398   register int i;
04399   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
04400   for (pb = soap->pblk; pb; pb = next)
04401   { next = pb->next;
04402     SOAP_FREE(soap, pb);
04403   }
04404   soap->pblk = NULL;
04405   soap->pidx = 0;
04406   for (i = 0; i < (int)SOAP_PTRHASH; i++)
04407     soap->pht[i] = NULL;
04408 }
04409 #endif
04410 #endif
04411 
04412 /******************************************************************************/
04413 #ifndef WITH_NOIDREF
04414 #ifndef PALM_2
04415 SOAP_FMAC1
04416 int
04417 SOAP_FMAC2
04418 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
04419 { register int i;
04420   struct soap_plist *pp;
04421   if (soap->version != 1)
04422     soap->encoding = 1;
04423   if (a)
04424     i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
04425   else
04426     i = soap_pointer_lookup(soap, p, type, &pp);
04427   if (i)
04428   { if (soap_is_embedded(soap, pp)
04429      || soap_is_single(soap, pp))
04430       return 0;
04431     soap_set_embedded(soap, pp);
04432   }
04433   return i;
04434 }
04435 #endif
04436 #endif
04437 
04438 /******************************************************************************/
04439 #ifndef WITH_NOIDREF
04440 #ifndef PALM_2
04441 SOAP_FMAC1
04442 int
04443 SOAP_FMAC2
04444 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
04445 { register struct soap_plist *pp;
04446   *ppp = NULL;
04447   if (p)
04448   { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
04449     { if (pp->ptr == p && pp->type == type)
04450       { *ppp = pp;
04451         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
04452         return pp->id;
04453       }
04454     }
04455   }
04456   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
04457   return 0;
04458 }
04459 #endif
04460 #endif
04461 
04462 /******************************************************************************/
04463 #ifndef WITH_NOIDREF
04464 #ifndef PALM_2
04465 SOAP_FMAC1
04466 int
04467 SOAP_FMAC2
04468 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
04469 { register int h;
04470   register struct soap_plist *pp;
04471   if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
04472   { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
04473     if (!pb)
04474     { soap->error = SOAP_EOM;
04475       return 0;
04476     }
04477     pb->next = soap->pblk;
04478     soap->pblk = pb;
04479     soap->pidx = 0;
04480   }
04481   *ppp = pp = &soap->pblk->plist[soap->pidx++];
04482   if (a)
04483     h = soap_hash_ptr(a->__ptr);
04484   else
04485     h = soap_hash_ptr(p);
04486   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));
04487   pp->next = soap->pht[h];
04488   pp->type = type;
04489   pp->mark1 = 0;
04490   pp->mark2 = 0;
04491   pp->ptr = p;
04492   pp->array = a;
04493   soap->pht[h] = pp;
04494   pp->id = ++soap->idnum;
04495   return pp->id;
04496 }
04497 #endif
04498 #endif
04499 
04500 /******************************************************************************/
04501 #ifndef WITH_NOIDREF
04502 #ifndef PALM_2
04503 SOAP_FMAC1
04504 int
04505 SOAP_FMAC2
04506 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
04507 { register struct soap_plist *pp;
04508   *ppp = NULL;
04509   if (!p || !a->__ptr)
04510     return 0;
04511   for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
04512   { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
04513     { register int i;
04514       for (i = 0; i < n; i++)
04515         if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
04516           break;
04517       if (i == n)
04518       { *ppp = pp;
04519         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
04520         return pp->id;
04521       }
04522     }
04523   }
04524   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
04525   return 0;
04526 }
04527 #endif
04528 #endif
04529 
04530 /******************************************************************************/
04531 #ifndef PALM_1
04532 SOAP_FMAC1
04533 int
04534 SOAP_FMAC2
04535 soap_begin_count(struct soap *soap)
04536 {
04537 #ifndef WITH_LEANER
04538   if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
04539     soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
04540   else
04541 #endif
04542   { soap->mode = soap->omode;
04543     if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
04544      || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
04545 #ifndef WITH_LEANER
04546       && !soap->fpreparesend
04547 #endif
04548       ))
04549       soap->mode &= ~SOAP_IO_LENGTH;
04550     else
04551       soap->mode |= SOAP_IO_LENGTH;
04552   }
04553 #ifdef WITH_ZLIB
04554   if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
04555   { if (!(soap->mode & SOAP_ENC_DIME))
04556       soap->mode &= ~SOAP_IO_LENGTH;
04557     if (soap->mode & SOAP_ENC_XML)
04558       soap->mode |= SOAP_IO_BUFFER;
04559     else
04560       soap->mode |= SOAP_IO_STORE;
04561   }
04562 #endif
04563   if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
04564     soap->mode |= SOAP_XML_TREE;
04565 #ifndef WITH_LEANER
04566   if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
04567     soap->mode |= SOAP_ENC_MIME;
04568   else
04569     soap->mode &= ~SOAP_ENC_MTOM;
04570   if (soap->mode & SOAP_ENC_MIME)
04571     soap_select_mime_boundary(soap);
04572   soap->dime.list = soap->dime.last;    /* keep track of last DIME attachment */
04573 #endif
04574   soap->count = 0;
04575   soap->ns = 0;
04576   soap->null = 0;
04577   soap->position = 0;
04578   soap->mustUnderstand = 0;
04579   soap->encoding = 0;
04580   soap->part = SOAP_BEGIN;
04581   soap->idnum = 0;
04582   soap_clr_attr(soap);
04583   soap_set_local_namespaces(soap);
04584   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
04585 #ifndef WITH_LEANER
04586   soap->dime.count = 0; /* count # of attachments */
04587   soap->dime.size = 0; /* accumulate total size of attachments */
04588   if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
04589     return soap->error = soap->fprepareinit(soap);   
04590 #endif
04591   return SOAP_OK;
04592 }
04593 #endif
04594 
04595 /******************************************************************************/
04596 #ifndef PALM_1
04597 SOAP_FMAC1
04598 int
04599 SOAP_FMAC2
04600 soap_end_count(struct soap *soap)
04601 { 
04602 #ifndef WITH_LEANER
04603   if (soap->fpreparefinal)
04604     return soap->error = soap->fpreparefinal(soap);
04605 #endif
04606   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
04607   return SOAP_OK;
04608 }
04609 #endif
04610 
04611 /******************************************************************************/
04612 #ifndef PALM_1
04613 SOAP_FMAC1
04614 int
04615 SOAP_FMAC2
04616 soap_begin_send(struct soap *soap)
04617 { soap->error = SOAP_OK;
04618   soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
04619 #ifdef WITH_ZLIB
04620   if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
04621   { if (soap->mode & SOAP_ENC_XML)
04622       soap->mode |= SOAP_IO_BUFFER;
04623     else
04624       soap->mode |= SOAP_IO_STORE;
04625   }
04626 #endif
04627 #ifdef WITH_UDP
04628   if ((soap->mode & SOAP_IO_UDP))
04629   { soap->mode |= SOAP_ENC_XML;
04630     if (soap->count > SOAP_BUFLEN)
04631       return soap->error = SOAP_UDP_ERROR;
04632   }
04633 #endif
04634   if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
04635   { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
04636       soap->mode |= SOAP_IO_BUFFER;
04637     else
04638       soap->mode |= SOAP_IO_STORE;
04639   }
04640   soap->mode &= ~SOAP_IO_LENGTH;
04641   if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
04642     soap_new_block(soap);
04643   if (!(soap->mode & SOAP_IO_KEEPALIVE))
04644     soap->keep_alive = 0;
04645   if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
04646     soap->mode |= SOAP_XML_TREE;
04647 #ifndef WITH_LEANER
04648   if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
04649   { soap->mode |= SOAP_ENC_MIME;
04650     soap->mode &= ~SOAP_ENC_DIME;
04651   }
04652   else
04653     soap->mode &= ~SOAP_ENC_MTOM;
04654   if (soap->mode & SOAP_ENC_MIME)
04655     soap_select_mime_boundary(soap);
04656 #ifdef WIN32
04657 #ifndef UNDER_CE
04658 #ifndef WITH_FASTCGI
04659   if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
04660 #ifdef __BORLANDC__
04661     setmode((SOAP_SOCKET)soap->sendfd, O_BINARY);
04662 #else
04663     _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY);
04664 #endif
04665 #endif
04666 #endif
04667 #endif
04668 #endif
04669   if (soap->mode & SOAP_IO)
04670   { soap->bufidx = 0;
04671     soap->buflen = 0;
04672   }
04673   soap->chunksize = 0;
04674   soap->ns = 0;
04675   soap->null = 0;
04676   soap->position = 0;
04677   soap->mustUnderstand = 0;
04678   soap->encoding = 0;
04679   soap->idnum = 0;
04680   soap->level = 0;
04681   soap_clr_attr(soap);
04682   soap_set_local_namespaces(soap);
04683 #ifdef WITH_ZLIB
04684   soap->z_ratio_out = 1.0;
04685   if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
04686   {
04687 #ifdef WITH_GZIP
04688     memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
04689     soap->d_stream.next_out = (Byte*)soap->z_buf + 10;
04690     soap->d_stream.avail_out = SOAP_BUFLEN - 10;
04691     soap->z_crc = crc32(0L, NULL, 0);
04692     if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
04693 #else
04694     soap->d_stream.next_out = (Byte*)soap->z_buf;
04695     soap->d_stream.avail_out = SOAP_BUFLEN;
04696     if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK)
04697 #endif
04698       return soap->error = SOAP_ZLIB_ERROR;
04699     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
04700     soap->zlib_state = SOAP_ZLIB_DEFLATE;
04701   }
04702 #endif
04703   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
04704   soap->part = SOAP_BEGIN;
04705 #ifndef WITH_LEANER
04706   if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE)
04707     soap->fprepareinit(soap);   
04708 #endif
04709   return SOAP_OK;
04710 }
04711 #endif
04712 
04713 /******************************************************************************/
04714 #ifndef WITH_NOIDREF
04715 #ifndef PALM_2
04716 SOAP_FMAC1
04717 void
04718 SOAP_FMAC2
04719 soap_embedded(struct soap *soap, const void *p, int t)
04720 { struct soap_plist *pp;
04721   if (soap_pointer_lookup(soap, p, t, &pp))
04722   { pp->mark1 = 1;
04723     pp->mark2 = 1;
04724     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
04725   }
04726 }
04727 #endif
04728 #endif
04729 
04730 /******************************************************************************/
04731 #ifndef WITH_NOIDREF
04732 #ifndef PALM_2
04733 SOAP_FMAC1
04734 int
04735 SOAP_FMAC2
04736 soap_reference(struct soap *soap, const void *p, int t)
04737 { struct soap_plist *pp;
04738   if (!p || (soap->mode & SOAP_XML_TREE))
04739     return 1;
04740   if (soap_pointer_lookup(soap, p, t, &pp))
04741   { if (pp->mark1 == 0)
04742     { pp->mark1 = 2;
04743       pp->mark2 = 2;
04744     }
04745   }
04746   else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
04747   { pp->mark1 = 0;
04748     pp->mark2 = 0;
04749   }
04750   else
04751     return 1;
04752   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
04753   return pp->mark1;
04754 }
04755 #endif
04756 #endif
04757 
04758 /******************************************************************************/
04759 #ifndef WITH_NOIDREF
04760 #ifndef PALM_2
04761 SOAP_FMAC1
04762 int
04763 SOAP_FMAC2
04764 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
04765 { register int i;
04766   struct soap_plist *pp;
04767   if (!p || !a->__ptr)
04768     return 1;
04769   i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
04770   if (i)
04771   { if (pp->mark1 == 0)
04772     { pp->mark1 = 2;
04773       pp->mark2 = 2;
04774     }
04775   }
04776   else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
04777     return 1;
04778   else
04779   { pp->mark1 = 0;
04780     pp->mark2 = 0;
04781   }
04782   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));
04783   return pp->mark1;
04784 }
04785 #endif
04786 #endif
04787 
04788 /******************************************************************************/
04789 #ifndef WITH_NOIDREF
04790 #ifndef PALM_2
04791 SOAP_FMAC1
04792 int
04793 SOAP_FMAC2
04794 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
04795 { struct soap_plist *pp;
04796   if (soap->mode & SOAP_XML_TREE)
04797     return id;
04798   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
04799   if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
04800   { if (id < 0)
04801     { id = soap_pointer_lookup(soap, p, t, &pp);
04802       if (id)
04803       { if (soap->mode & SOAP_IO_LENGTH)
04804           pp->mark1 = 2;
04805         else
04806           pp->mark2 = 2;
04807         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));
04808       }
04809       return -1;
04810     }
04811     return id;
04812   }
04813   if (id < 0)
04814     id = soap_pointer_lookup(soap, p, t, &pp);
04815   else if (id && !soap_pointer_lookup(soap, p, t, &pp))
04816     return 0;
04817   if (id && pp)
04818   { if (soap->mode & SOAP_IO_LENGTH)
04819       pp->mark1 = 1;
04820     else
04821       pp->mark2 = 1;
04822     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));
04823   }
04824   return id;
04825 }
04826 #endif
04827 #endif
04828 
04829 /******************************************************************************/
04830 #ifndef WITH_NOIDREF
04831 #ifndef PALM_2
04832 SOAP_FMAC1
04833 int
04834 SOAP_FMAC2
04835 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
04836 { if (!pp)
04837     return 0;
04838   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
04839   if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
04840   { if (soap->mode & SOAP_IO_LENGTH)
04841       return pp->mark1 != 0;
04842     return pp->mark2 != 0;
04843   }
04844   if (soap->mode & SOAP_IO_LENGTH)
04845     return pp->mark1 == 1;
04846   return pp->mark2 == 1;
04847 }
04848 #endif
04849 #endif
04850 
04851 /******************************************************************************/
04852 #ifndef WITH_NOIDREF
04853 #ifndef PALM_2
04854 SOAP_FMAC1
04855 int
04856 SOAP_FMAC2
04857 soap_is_single(struct soap *soap, struct soap_plist *pp)
04858 { if (soap->part == SOAP_IN_HEADER)
04859     return 1;
04860   if (!pp)
04861     return 0;
04862   if (soap->mode & SOAP_IO_LENGTH)
04863     return pp->mark1 == 0;
04864   return pp->mark2 == 0;
04865 }
04866 #endif
04867 #endif
04868 
04869 /******************************************************************************/
04870 #ifndef WITH_NOIDREF
04871 #ifndef PALM_2
04872 SOAP_FMAC1
04873 void
04874 SOAP_FMAC2
04875 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
04876 { if (!pp)
04877     return;
04878   if (soap->mode & SOAP_IO_LENGTH)
04879     pp->mark1 = 1;
04880   else
04881     pp->mark2 = 1;
04882 }
04883 #endif
04884 #endif
04885 
04886 /******************************************************************************/
04887 #ifndef WITH_NOIDREF
04888 #ifndef WITH_LEANER
04889 #ifndef PALM_1
04890 SOAP_FMAC1
04891 int
04892 SOAP_FMAC2
04893 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) 
04894 { struct soap_plist *pp;
04895   int i;
04896   if (!p || !a->__ptr || (!aid && !atype))
04897     return soap_element_id(soap, tag, id, p, a, n, type, t);
04898   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:""));
04899   i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
04900   if (!i)
04901   { i = soap_pointer_enter(soap, p, a, n, t, &pp);
04902     if (!i)
04903     { soap->error = SOAP_EOM;
04904       return -1;
04905     }
04906   }
04907   if (id <= 0)
04908     id = i;
04909   if (!aid)
04910   { sprintf(soap->tmpbuf, soap->dime_id_format, id);
04911     aid = soap_strdup(soap, soap->tmpbuf);
04912   }
04913   /* Add MTOM xop:Include element when necessary */
04914   /* TODO: this code to be obsoleted with new import/xop.h conventions */
04915   if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
04916   { if (soap_element_begin_out(soap, tag, 0, type)
04917      || soap_element_href(soap, "xop:Include", 0, "href", aid)
04918      || soap_element_end_out(soap, tag))
04919       return soap->error;
04920   }
04921   else if (soap_element_href(soap, tag, 0, "href", aid))
04922     return soap->error;
04923   if (soap->mode & SOAP_IO_LENGTH)
04924   { if (pp->mark1 != 3)
04925     { struct soap_multipart *content;
04926       if (soap->mode & SOAP_ENC_MTOM)
04927         content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
04928       else
04929         content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
04930       if (!content)
04931       { soap->error = SOAP_EOM;
04932         return -1;
04933       }
04934       if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
04935       { if (soap->mode & SOAP_ENC_MTOM)
04936         { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
04937           if (s)
04938           { *s = '<';
04939             strcpy(s + 1, aid + 4);
04940             strcat(s, ">");
04941             content->id = s;
04942           }
04943         }
04944         else
04945           content->id = aid + 4;
04946       }
04947       else
04948         content->id = aid;
04949       content->type = atype;
04950       content->options = aoptions;
04951       content->encoding = SOAP_MIME_BINARY;
04952       pp->mark1 = 3;
04953     }
04954   }
04955   else
04956     pp->mark2 = 3;
04957   return -1;
04958 }
04959 #endif
04960 #endif
04961 #endif
04962 
04963 /******************************************************************************/
04964 #ifndef WITH_NOIDREF
04965 #ifndef PALM_1
04966 static void
04967 soap_init_iht(struct soap *soap)
04968 { register int i;
04969   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n"));
04970   for (i = 0; i < SOAP_IDHASH; i++)
04971     soap->iht[i] = NULL;
04972 }
04973 #endif
04974 #endif
04975 
04976 /******************************************************************************/
04977 #ifndef WITH_NOIDREF
04978 #ifndef PALM_1
04979 static void
04980 soap_free_iht(struct soap *soap)
04981 { register int i;
04982   register struct soap_ilist *ip, *p;
04983   register struct soap_flist *fp, *fq;
04984   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
04985   for (i = 0; i < SOAP_IDHASH; i++)
04986   { for (ip = soap->iht[i]; ip; ip = p)
04987     { for (fp = ip->flist; fp; fp = fq)
04988       { fq = fp->next;
04989         SOAP_FREE(soap, fp);
04990       }
04991       p = ip->next;
04992       SOAP_FREE(soap, ip);
04993     }
04994     soap->iht[i] = NULL;
04995   }
04996 }
04997 #endif
04998 #endif
04999 
05000 /******************************************************************************/
05001 #ifndef WITH_NOIDREF
05002 #ifndef PALM_2
05003 SOAP_FMAC1
05004 struct soap_ilist *
05005 SOAP_FMAC2
05006 soap_lookup(struct soap *soap, const char *id)
05007 { register struct soap_ilist *ip;
05008   for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
05009     if (!strcmp(ip->id, id))
05010       return ip;
05011   return NULL;
05012 }
05013 #endif
05014 #endif
05015 
05016 /******************************************************************************/
05017 #ifndef WITH_NOIDREF
05018 #ifndef PALM_2
05019 SOAP_FMAC1
05020 struct soap_ilist *
05021 SOAP_FMAC2
05022 soap_enter(struct soap *soap, const char *id)
05023 { register size_t h;
05024   register struct soap_ilist *ip;
05025   ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
05026   if (ip)
05027   { h = soap_hash(id);
05028     strcpy(ip->id, id);
05029     ip->next = soap->iht[h];
05030     soap->iht[h] = ip;
05031     return ip;
05032   }
05033   return NULL;
05034 }
05035 #endif
05036 #endif
05037 
05038 /******************************************************************************/
05039 #ifndef PALM_2
05040 SOAP_FMAC1
05041 void*
05042 SOAP_FMAC2
05043 soap_malloc(struct soap *soap, size_t n)
05044 { register char *p;
05045   if (!n)
05046     return (void*)SOAP_NON_NULL;
05047   if (!soap)
05048     return SOAP_MALLOC(soap, n);
05049 #ifdef SOAP_DEBUG
05050   n += sizeof(short);
05051 #endif
05052   n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
05053   if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
05054   { soap->error = SOAP_EOM;
05055     return NULL;
05056   }
05057   /* keep chain of alloced cells for later destruction */
05058   soap->alloced = 1;
05059 #ifdef SOAP_DEBUG
05060   /* set the canary to detect corruption */
05061   *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY;
05062 #endif
05063   *(void**)(p + n) = soap->alist;
05064   *(size_t*)(p + n + sizeof(void*)) = n;
05065   soap->alist = p + n;
05066   return p;
05067 }
05068 #endif
05069 
05070 /******************************************************************************/
05071 #ifdef SOAP_DEBUG
05072 static void
05073 soap_init_mht(struct soap *soap)
05074 { register int i;
05075   for (i = 0; i < (int)SOAP_PTRHASH; i++)
05076     soap->mht[i] = NULL;
05077 }
05078 #endif
05079 
05080 /******************************************************************************/
05081 #ifdef SOAP_DEBUG
05082 static void
05083 soap_free_mht(struct soap *soap)
05084 { register int i;
05085   register struct soap_mlist *mp, *mq;
05086   for (i = 0; i < (int)SOAP_PTRHASH; i++)
05087   { for (mp = soap->mht[i]; mp; mp = mq)
05088     { mq = mp->next;
05089       if (mp->live)
05090         fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
05091       free(mp);
05092     }
05093     soap->mht[i] = NULL;
05094   }
05095 }
05096 #endif
05097 
05098 /******************************************************************************/
05099 #ifdef SOAP_DEBUG
05100 SOAP_FMAC1
05101 void*
05102 SOAP_FMAC2
05103 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
05104 { register void *p = malloc(size);
05105   if (soap)
05106   { register int h = soap_hash_ptr(p);
05107     register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
05108     if (soap->fdebug[SOAP_INDEX_TEST])
05109       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
05110     mp->next = soap->mht[h];
05111     mp->ptr = p;
05112     mp->file = file;
05113     mp->line = line;
05114     mp->live = 1;
05115     soap->mht[h] = mp;
05116   }
05117   return p;
05118 }
05119 #endif
05120 
05121 /******************************************************************************/
05122 #ifdef SOAP_DEBUG
05123 SOAP_FMAC1
05124 void
05125 SOAP_FMAC2
05126 soap_track_free(struct soap *soap, const char *file, int line, void *p)
05127 { register int h = soap_hash_ptr(p);
05128   register struct soap_mlist *mp;
05129   for (mp = soap->mht[h]; mp; mp = mp->next)
05130     if (mp->ptr == p)
05131       break;
05132   if (mp)
05133   { if (mp->live)
05134     { free(p);
05135       if (soap->fdebug[SOAP_INDEX_TEST])
05136         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
05137       mp->live = 0;
05138     }
05139     else
05140       fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
05141   }
05142   else
05143     fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
05144 }
05145 #endif
05146 
05147 /******************************************************************************/
05148 #ifdef SOAP_DEBUG
05149 static void
05150 soap_track_unlink(struct soap *soap, const void *p)
05151 { register int h = soap_hash_ptr(p);
05152   register struct soap_mlist *mp;
05153   for (mp = soap->mht[h]; mp; mp = mp->next)
05154     if (mp->ptr == p)
05155       break;
05156   if (mp)
05157     mp->live = 0;
05158 }
05159 #endif
05160 
05161 /******************************************************************************/
05162 #ifndef PALM_2
05163 SOAP_FMAC1
05164 void
05165 SOAP_FMAC2
05166 soap_dealloc(struct soap *soap, void *p)
05167 { if (!soap)
05168     return;
05169   if (p)
05170   { register char **q;
05171     for (q = (char**)&soap->alist; *q; q = *(char***)q)
05172     { 
05173 #ifdef SOAP_DEBUG
05174       if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY)
05175       { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
05176         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
05177         DBGHEX(TEST, *q - 200, 200);
05178         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
05179         return;
05180       }
05181 #endif
05182       if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
05183       { *q = **(char***)q;
05184         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
05185         SOAP_FREE(soap, p);
05186         return;
05187       }
05188     }
05189     soap_delete(soap, p);
05190   }
05191   else
05192   { register char *q;
05193     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
05194     while (soap->alist)
05195     { q = (char*)soap->alist;
05196 #ifdef SOAP_DEBUG
05197       if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY)
05198       { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
05199         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
05200         DBGHEX(TEST, q - 200, 200);
05201         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
05202         return;
05203       }
05204 #endif
05205       soap->alist = *(void**)q;
05206       q -= *(size_t*)(q + sizeof(void*));
05207       SOAP_FREE(soap, q);
05208     }
05209   }
05210   /* we must assume these were deallocated: */
05211   soap->action = NULL;
05212   soap->fault = NULL;
05213   soap->header = NULL;
05214   soap->userid = NULL;
05215   soap->passwd = NULL;
05216   soap->authrealm = NULL;
05217 #ifndef WITH_LEANER
05218   soap_clr_mime(soap);
05219 #endif
05220 }
05221 #endif
05222 
05223 /******************************************************************************/
05224 #ifndef PALM_2
05225 SOAP_FMAC1
05226 void
05227 SOAP_FMAC2
05228 soap_delete(struct soap *soap, void *p)
05229 { register struct soap_clist **cp;
05230   if (soap_check_state(soap))
05231     return;
05232   cp = &soap->clist;
05233   if (p)
05234   { while (*cp)
05235     { if (p == (*cp)->ptr)
05236       { register struct soap_clist *q = *cp;
05237         *cp = q->next;
05238         q->fdelete(q);
05239         SOAP_FREE(soap, q);
05240         return;
05241       }
05242       cp = &(*cp)->next;
05243     }
05244     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
05245   }
05246   else
05247   { while (*cp)
05248     { register struct soap_clist *q = *cp;
05249       *cp = q->next;
05250       q->fdelete(q);
05251       SOAP_FREE(soap, q);
05252     }
05253   }
05254 }
05255 #endif
05256 
05257 /******************************************************************************/
05258 #ifndef PALM_2
05259 SOAP_FMAC1
05260 struct soap_clist *
05261 SOAP_FMAC2
05262 soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*))
05263 { register struct soap_clist *cp;
05264   if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
05265   { cp->next = soap->clist;
05266     cp->type = t;
05267     cp->size = n; 
05268     cp->ptr = p;
05269     cp->fdelete = fdelete;
05270     soap->clist = cp;
05271   }
05272   return cp;
05273 }
05274 #endif
05275 
05276 /******************************************************************************/
05277 #ifndef PALM_2
05278 SOAP_FMAC1
05279 void
05280 SOAP_FMAC2
05281 soap_unlink(struct soap *soap, const void *p)
05282 { register char **q;
05283   register struct soap_clist **cp;
05284   if (!soap || !p)
05285     return;
05286   for (q = (char**)&soap->alist; *q; q = *(char***)q)
05287   { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
05288     { *q = **(char***)q;
05289       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
05290 #ifdef SOAP_DEBUG
05291       soap_track_unlink(soap, p);
05292 #endif
05293       return;
05294     }
05295   }
05296   for (cp = &soap->clist; *cp; cp = &(*cp)->next)
05297   { if (p == (*cp)->ptr)
05298     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
05299       q = (char**)*cp;
05300       *cp = (*cp)->next;
05301       SOAP_FREE(soap, q);
05302       return;
05303     }
05304   }
05305 }
05306 #endif
05307 
05308 /******************************************************************************/
05309 #ifndef WITH_NOIDREF
05310 #ifndef PALM_2
05311 SOAP_FMAC1
05312 int
05313 SOAP_FMAC2
05314 soap_lookup_type(struct soap *soap, const char *id)
05315 { register struct soap_ilist *ip;
05316   if (id && *id)
05317   { ip = soap_lookup(soap, id);
05318     if (ip)
05319     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
05320       return ip->type;
05321     }
05322   }
05323   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
05324   return 0;
05325 }
05326 #endif
05327 #endif
05328 
05329 /******************************************************************************/
05330 #ifndef WITH_NOIDREF
05331 #ifndef PALM_2
05332 SOAP_FMAC1
05333 void*
05334 SOAP_FMAC2
05335 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
05336 { struct soap_ilist *ip;
05337   void **q;
05338   if (!p || !id || !*id)
05339     return p;
05340   ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
05341   if (!ip)
05342   { ip = soap_enter(soap, id); /* new hash table entry for string id */
05343     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
05344     ip->type = t;
05345     ip->size = n; 
05346     ip->link = p;
05347     ip->copy = NULL;
05348     ip->flist = NULL;
05349     ip->ptr = NULL;
05350     ip->level = k;
05351     *p = NULL;
05352   }
05353   else if (ip->ptr)
05354   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
05355     if (ip->type != t)
05356     { strcpy(soap->id, id);
05357       soap->error = SOAP_HREF;
05358       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t));
05359       return NULL;
05360     }
05361     while (ip->level < k)
05362     { q = (void**)soap_malloc(soap, sizeof(void*));  
05363       if (!q)
05364         return NULL;
05365       *p = (void*)q;
05366       p = q;
05367       k--;
05368       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
05369     }
05370     *p = ip->ptr;
05371   }
05372   else if (ip->level > k)
05373   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
05374     while (ip->level > k)
05375     { void *s, **r = &ip->link;
05376       q = (void**)ip->link;
05377       while (q)
05378       { *r = (void*)soap_malloc(soap, sizeof(void*));
05379         s = *q;
05380         *q = *r;
05381         r = (void**)*r;
05382         q = (void**)s;
05383       }
05384       *r = NULL;
05385       ip->size = n; 
05386       ip->copy = NULL;
05387       ip->level = ip->level - 1;
05388       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
05389     }
05390     q = (void**)ip->link;
05391     ip->link = p;
05392     *p = (void*)q;
05393   }
05394   else
05395   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
05396     while (ip->level < k)
05397     { q = (void**)soap_malloc(soap, sizeof(void*));  
05398       *p = q;
05399       p = q;
05400       k--;
05401       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
05402     }
05403     q = (void**)ip->link;
05404     ip->link = p;
05405     *p = (void*)q;
05406   }
05407   return p;
05408 }
05409 #endif
05410 #endif
05411 
05412 /******************************************************************************/
05413 #ifndef WITH_NOIDREF
05414 #ifndef PALM_2
05415 SOAP_FMAC1
05416 void*
05417 SOAP_FMAC2
05418 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))
05419 { struct soap_ilist *ip;
05420   if (!p || !href || !*href)
05421     return p;
05422   ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
05423   if (!ip)
05424   { ip = soap_enter(soap, href); /* new hash table entry for string id */
05425     ip->type = st;
05426     ip->size = n;
05427     ip->link = NULL;
05428     ip->copy = NULL;
05429     ip->ptr = NULL;
05430     ip->level = 0;
05431     ip->flist = NULL;
05432     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));
05433   }
05434   else if (ip->type != st || (ip->level == k && ip->size != n))
05435   { 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));
05436     strcpy(soap->id, href);
05437     soap->error = SOAP_HREF;
05438     return NULL;
05439   }
05440   if (fcopy || n < sizeof(void*) || *href != '#')
05441   { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
05442     if (!fp)
05443     { soap->error = SOAP_EOM;
05444       return NULL;
05445     }
05446     fp->next = ip->flist;
05447     fp->type = tt;
05448     fp->ptr = p;
05449     fp->level = k;
05450     fp->len = len;
05451     if (fcopy)
05452       fp->fcopy = fcopy;
05453     else
05454       fp->fcopy = soap_fcopy;
05455     ip->flist = fp;
05456     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));
05457   }
05458   else
05459   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
05460     *(void**)p = ip->copy;
05461     ip->copy = p;
05462   }
05463   return p;
05464 }
05465 #endif
05466 #endif
05467 
05468 /******************************************************************************/
05469 #ifndef PALM_2
05470 SOAP_FMAC1
05471 void*
05472 SOAP_FMAC2
05473 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*))
05474 {
05475 #ifndef WITH_NOIDREF
05476   struct soap_ilist *ip;
05477 #endif
05478   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
05479   soap->alloced = 0;
05480   if (!p)
05481   { if (finstantiate)
05482       p = finstantiate(soap, t, type, arrayType, &n);
05483     else
05484       p = soap_malloc(soap, n);
05485     if (p)
05486       soap->alloced = 1;
05487   }
05488 #ifndef WITH_NOIDREF
05489   if (!id || !*id)
05490 #endif
05491     return p;
05492 #ifndef WITH_NOIDREF
05493   ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
05494   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
05495   if (!ip)
05496   { ip = soap_enter(soap, id); /* new hash table entry for string id */
05497     ip->type = t;
05498     ip->link = NULL;
05499     ip->copy = NULL;
05500     ip->flist = NULL;
05501     ip->size = n;
05502     ip->ptr = p;
05503     ip->level = k;
05504     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));
05505   }
05506   else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
05507   { 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));
05508     strcpy(soap->id, id);
05509     soap->error = SOAP_HREF;
05510     return NULL;
05511   }
05512   else if (ip->ptr)
05513   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
05514     strcpy(soap->id, id);
05515     soap->error = SOAP_DUPLICATE_ID;
05516     return NULL;
05517   }
05518   else 
05519   { ip->size = n;
05520     ip->ptr = p;
05521     ip->level = k;
05522     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));
05523   }
05524   return ip->ptr;
05525 #endif
05526 }
05527 #endif
05528 
05529 /******************************************************************************/
05530 #ifndef PALM_2
05531 SOAP_FMAC1
05532 void
05533 SOAP_FMAC2
05534 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
05535 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
05536   memcpy(p, q, n);
05537 }
05538 #endif
05539 
05540 /******************************************************************************/
05541 #ifndef PALM_1
05542 SOAP_FMAC1
05543 int
05544 SOAP_FMAC2
05545 soap_end_send(struct soap *soap)
05546 { 
05547 #ifndef WITH_LEANER
05548   if (soap->dime.list)
05549   { /* SOAP body referenced attachments must appear first */
05550     soap->dime.last->next = soap->dime.first;
05551     soap->dime.first = soap->dime.list->next;
05552     soap->dime.list->next = NULL;
05553     soap->dime.last = soap->dime.list;
05554   }
05555   if (soap_putdime(soap) || soap_putmime(soap))
05556     return soap->error;
05557   soap->mime.list = NULL;
05558   soap->mime.first = NULL;
05559   soap->mime.last = NULL;
05560   soap->dime.list = NULL;
05561   soap->dime.first = NULL;
05562   soap->dime.last = NULL;
05563 #endif
05564   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n"));
05565   if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
05566   { if (soap_flush(soap))
05567 #ifdef WITH_ZLIB
05568     { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
05569       { soap->zlib_state = SOAP_ZLIB_NONE;
05570         deflateEnd(&soap->d_stream);
05571       }
05572       return soap->error;
05573     }
05574 #else
05575       return soap->error;
05576 #endif
05577 #ifdef WITH_ZLIB
05578     if (soap->mode & SOAP_ENC_ZLIB)
05579     { int r;
05580       soap->d_stream.avail_in = 0;
05581       do
05582       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
05583         r = deflate(&soap->d_stream, Z_FINISH);
05584         if (soap->d_stream.avail_out != SOAP_BUFLEN)
05585         { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out))
05586           { soap->zlib_state = SOAP_ZLIB_NONE;
05587             deflateEnd(&soap->d_stream);
05588             return soap->error;
05589           }
05590           soap->d_stream.next_out = (Byte*)soap->z_buf;
05591           soap->d_stream.avail_out = SOAP_BUFLEN;
05592         }
05593       } while (r == Z_OK);
05594       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
05595       soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in;
05596       soap->mode &= ~SOAP_ENC_ZLIB;
05597       soap->zlib_state = SOAP_ZLIB_NONE;
05598       if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END)
05599       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
05600         return soap->error = SOAP_ZLIB_ERROR;
05601       }
05602 #ifdef WITH_GZIP
05603       soap->z_buf[0] = soap->z_crc & 0xFF;
05604       soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
05605       soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
05606       soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
05607       soap->z_buf[4] = soap->d_stream.total_in & 0xFF;
05608       soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF;
05609       soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF;
05610       soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF;
05611       if (soap_flush_raw(soap, soap->z_buf, 8))
05612         return soap->error;
05613       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
05614 #endif
05615     }
05616 #endif
05617     if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
05618     { char *p;
05619 #ifndef WITH_NOHTTP
05620       if (!(soap->mode & SOAP_ENC_XML))
05621       { soap->mode--;
05622         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
05623         if (soap->status >= SOAP_POST)
05624           soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
05625         else if (soap->status != SOAP_STOP)
05626           soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
05627         if (soap->error || soap_flush(soap))
05628           return soap->error;
05629         soap->mode++;
05630       }
05631 #endif
05632       for (p = soap_first_block(soap); p; p = soap_next_block(soap))
05633       { DBGMSG(SENT, p, soap_block_size(soap));
05634         if ((soap->error = soap->fsend(soap, p, soap_block_size(soap))))
05635         { soap_end_block(soap);
05636           return soap->error;
05637         }
05638       }
05639       soap_end_block(soap);
05640     }
05641 #ifndef WITH_LEANER
05642     else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
05643     { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
05644       if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
05645         return soap->error;
05646     }
05647 #endif
05648   }
05649 #ifdef WITH_TCPFIN
05650 #ifdef WITH_OPENSSL
05651   if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
05652     soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
05653 #else
05654   if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
05655     soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
05656 #endif
05657 #endif
05658   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
05659   soap->omode &= ~SOAP_XML_SEC;
05660   soap->count = 0;
05661   soap->part = SOAP_END;
05662   return SOAP_OK;
05663 }
05664 #endif
05665 
05666 /******************************************************************************/
05667 #ifndef PALM_1
05668 SOAP_FMAC1
05669 int
05670 SOAP_FMAC2
05671 soap_end_recv(struct soap *soap)
05672 { soap->part = SOAP_END;
05673 #ifndef WITH_LEANER
05674   if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
05675     return soap->error;
05676   soap->dime.list = soap->dime.first;
05677   soap->dime.first = NULL;
05678   soap->dime.last = NULL;
05679   /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */
05680   if (soap->mode & SOAP_ENC_MIME)
05681   { if (soap->mode & SOAP_MIME_POSTCHECK)
05682     { soap_resolve(soap);
05683       return SOAP_OK;
05684     }
05685     if (soap_getmime(soap))
05686       return soap->error;
05687   }
05688   soap->mime.list = soap->mime.first;
05689   soap->mime.first = NULL;
05690   soap->mime.last = NULL;
05691   soap->mime.boundary = NULL;
05692 #endif
05693   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
05694 #ifdef WITH_ZLIB
05695   if (soap->mode & SOAP_ENC_ZLIB)
05696   { soap->mode &= ~SOAP_ENC_ZLIB;
05697     memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
05698     soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf;
05699     soap->buflen = soap->z_buflen;
05700     soap->zlib_state = SOAP_ZLIB_NONE;
05701     if (inflateEnd(&soap->d_stream) != Z_OK)
05702       return soap->error = SOAP_ZLIB_ERROR;
05703 #ifdef WITH_GZIP
05704     if (soap->zlib_in == SOAP_ZLIB_GZIP)
05705     { soap_wchar c;
05706       short i;
05707       for (i = 0; i < 8; i++)
05708       { if ((int)(c = soap_getchar(soap)) == EOF)
05709           return soap->error = SOAP_EOF;
05710         soap->z_buf[i] = (char)c;
05711       }
05712       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)))
05713       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
05714         return soap->error = SOAP_ZLIB_ERROR;
05715       }
05716       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)))
05717       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n"));
05718         return soap->error = SOAP_ZLIB_ERROR;
05719       }
05720     }
05721 #endif
05722   }
05723 #endif
05724   if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
05725     while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
05726       ;
05727   if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
05728     return soap->error;
05729 #ifndef WITH_NOIDREF
05730   return soap_resolve(soap);
05731 #else
05732 #ifndef WITH_LEANER
05733   if (soap->xlist)
05734   { if (soap->mode & SOAP_ENC_MTOM)
05735       return soap->error = SOAP_MIME_HREF;
05736     return soap->error = SOAP_DIME_HREF;
05737   }
05738 #endif
05739   return SOAP_OK;
05740 #endif
05741 }
05742 #endif
05743 
05744 /******************************************************************************/
05745 #ifndef PALM_1
05746 SOAP_FMAC1
05747 void
05748 SOAP_FMAC2
05749 soap_free(struct soap *soap)
05750 { register struct Namespace *ns;
05751   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
05752   while (soap->nlist)
05753   { register struct soap_nlist *np = soap->nlist->next;
05754     SOAP_FREE(soap, soap->nlist);
05755     soap->nlist = np;
05756   }
05757   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
05758   while (soap->blist)
05759     soap_end_block(soap);
05760   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
05761   while (soap->attributes)
05762   { register struct soap_attribute *tp = soap->attributes->next;
05763     if (soap->attributes->value)
05764       SOAP_FREE(soap, soap->attributes->value);
05765     SOAP_FREE(soap, soap->attributes);
05766     soap->attributes = tp;
05767   }
05768 #ifdef WITH_FAST
05769   if (soap->labbuf)
05770     SOAP_FREE(soap, soap->labbuf);
05771   soap->labbuf = NULL;
05772   soap->lablen = 0;
05773   soap->labidx = 0;
05774 #endif
05775   ns = soap->local_namespaces;
05776   if (ns)
05777   { for (; ns->id; ns++)
05778     { if (ns->out)
05779       { if (soap->encodingStyle == ns->out)
05780           soap->encodingStyle = SOAP_STR_EOS;
05781         SOAP_FREE(soap, ns->out);
05782         ns->out = NULL;
05783       }
05784       if (soap->encodingStyle == ns->ns)
05785         soap->encodingStyle = SOAP_STR_EOS;
05786     }
05787     SOAP_FREE(soap, soap->local_namespaces);
05788     soap->local_namespaces = NULL;
05789   }
05790 #ifndef WITH_LEANER
05791   while (soap->xlist)
05792   { struct soap_xlist *xp = soap->xlist->next;
05793     SOAP_FREE(soap, soap->xlist);
05794     soap->xlist = xp;
05795   }
05796 #endif
05797 #ifndef WITH_NOIDREF
05798   soap_free_pht(soap);
05799   soap_free_iht(soap);
05800 #endif
05801 }
05802 #endif
05803 
05804 /******************************************************************************/
05805 #ifdef SOAP_DEBUG
05806 static void
05807 soap_init_logs(struct soap *soap)
05808 { int i;
05809   for (i = 0; i < SOAP_MAXLOGS; i++)
05810   { soap->logfile[i] = NULL;
05811     soap->fdebug[i] = NULL;
05812   }
05813 }
05814 #endif
05815 
05816 /******************************************************************************/
05817 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
05818 SOAP_FMAC1
05819 void
05820 SOAP_FMAC2
05821 soap_open_logfile(struct soap *soap, int i)
05822 { if (soap->logfile[i])
05823     soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
05824 }
05825 #endif
05826 
05827 /******************************************************************************/
05828 #ifdef SOAP_DEBUG
05829 static void
05830 soap_close_logfile(struct soap *soap, int i)
05831 { if (soap->fdebug[i])
05832   { fclose(soap->fdebug[i]);
05833     soap->fdebug[i] = NULL;
05834   }
05835 }
05836 #endif
05837 
05838 /******************************************************************************/
05839 #ifdef SOAP_DEBUG
05840 SOAP_FMAC1
05841 void
05842 SOAP_FMAC2
05843 soap_close_logfiles(struct soap *soap)
05844 { int i;
05845   for (i = 0; i < SOAP_MAXLOGS; i++)
05846     soap_close_logfile(soap, i);
05847 }
05848 #endif
05849 
05850 /******************************************************************************/
05851 #ifdef SOAP_DEBUG
05852 static void
05853 soap_set_logfile(struct soap *soap, int i, const char *logfile)
05854 { char *s = NULL;
05855   soap_close_logfile(soap, i);
05856   if (soap->logfile[i])
05857     SOAP_FREE(soap, (void*)soap->logfile[i]);
05858   if (logfile)
05859     if ((s = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
05860       strcpy(s, logfile);
05861   soap->logfile[i] = s;
05862 }
05863 #endif
05864 
05865 /******************************************************************************/
05866 #ifdef SOAP_DEBUG
05867 SOAP_FMAC1
05868 void
05869 SOAP_FMAC2
05870 soap_set_recv_logfile(struct soap *soap, const char *logfile)
05871 { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
05872 }
05873 #endif
05874 
05875 /******************************************************************************/
05876 #ifdef SOAP_DEBUG
05877 SOAP_FMAC1
05878 void
05879 SOAP_FMAC2
05880 soap_set_sent_logfile(struct soap *soap, const char *logfile)
05881 { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
05882 }
05883 #endif
05884 
05885 /******************************************************************************/
05886 #ifdef SOAP_DEBUG
05887 SOAP_FMAC1
05888 void
05889 SOAP_FMAC2
05890 soap_set_test_logfile(struct soap *soap, const char *logfile)
05891 { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
05892 }
05893 #endif
05894 
05895 /******************************************************************************/
05896 #ifndef PALM_1
05897 SOAP_FMAC1
05898 struct soap*
05899 SOAP_FMAC2
05900 soap_copy(struct soap *soap)
05901 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
05902 }
05903 #endif
05904 
05905 /******************************************************************************/
05906 #ifndef PALM_1
05907 SOAP_FMAC1
05908 struct soap*
05909 SOAP_FMAC2
05910 soap_copy_context(struct soap *copy, struct soap *soap)
05911 { if (soap_check_state(soap))
05912     return NULL;
05913   if (copy)
05914   { register struct soap_plugin *p;
05915     memcpy(copy, soap, sizeof(struct soap));
05916     copy->state = SOAP_COPY;
05917     copy->error = SOAP_OK;
05918     copy->userid = NULL;
05919     copy->passwd = NULL;
05920     copy->nlist = NULL;
05921     copy->blist = NULL;
05922     copy->clist = NULL;
05923     copy->alist = NULL;
05924     copy->attributes = NULL;
05925 #ifdef WITH_FAST
05926     copy->labbuf = NULL;
05927     copy->lablen = 0;
05928     copy->labidx = 0;
05929 #endif
05930 #ifdef SOAP_DEBUG
05931     soap_init_mht(copy);
05932 #endif
05933     copy->local_namespaces = NULL;
05934 #ifndef WITH_NOIDREF
05935     soap_init_iht(copy);
05936     soap_init_pht(copy);
05937 #endif
05938     copy->header = NULL;
05939     copy->fault = NULL;
05940     copy->action = NULL;
05941 #ifndef WITH_LEAN
05942 #ifdef WITH_COOKIES
05943     copy->cookies = soap_copy_cookies(copy, soap);
05944 #else
05945     copy->cookies = NULL;
05946 #endif
05947 #endif
05948 #ifdef SOAP_DEBUG
05949     soap_init_logs(copy);
05950     soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
05951     soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
05952     soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
05953 #endif
05954     copy->plugins = NULL;
05955     for (p = soap->plugins; p; p = p->next)
05956     { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
05957       if (!q)
05958         return NULL;
05959       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
05960       *q = *p;
05961       if (p->fcopy && (soap->error = p->fcopy(copy, q, p)))
05962       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
05963         SOAP_FREE(copy, q);
05964         return NULL;
05965       }
05966       q->next = copy->plugins;
05967       copy->plugins = q;
05968     }
05969   }
05970   else
05971     soap->error = SOAP_EOM;
05972   return copy;
05973 }
05974 #endif
05975 
05976 /******************************************************************************/
05977 #ifndef PALM_1
05978 SOAP_FMAC1
05979 void
05980 SOAP_FMAC2
05981 soap_copy_stream(struct soap *copy, struct soap *soap)
05982 { copy->mode = soap->mode;
05983   copy->imode = soap->imode;
05984   copy->omode = soap->omode;
05985   copy->socket = soap->socket;
05986   copy->recv_timeout = soap->recv_timeout;
05987   copy->send_timeout = soap->send_timeout;
05988 #if defined(__cplusplus) && !defined(WITH_LEAN)
05989   copy->os = soap->os;
05990   copy->is = soap->is;
05991 #endif
05992   copy->sendfd = soap->sendfd;
05993   copy->recvfd = soap->recvfd;
05994   copy->bufidx = soap->bufidx;
05995   copy->buflen = soap->buflen;
05996   copy->ahead = soap->ahead;
05997   copy->cdata = soap->cdata;
05998   copy->chunksize = soap->chunksize;
05999   copy->chunkbuflen = soap->chunkbuflen;
06000   copy->keep_alive = soap->keep_alive;
06001   copy->max_keep_alive = soap->max_keep_alive;
06002   copy->peer = soap->peer;
06003   copy->peerlen = soap->peerlen;
06004 #ifdef WITH_OPENSSL
06005   copy->bio = soap->bio;
06006   copy->ssl = soap->ssl;
06007   copy->ctx = soap->ctx;
06008 #endif
06009 #ifdef WITH_ZLIB
06010   copy->zlib_state = soap->zlib_state;
06011   copy->zlib_in = soap->zlib_in;
06012   copy->zlib_out = soap->zlib_out;
06013   copy->d_stream = soap->d_stream;
06014   copy->z_buflen = soap->z_buflen;
06015   copy->z_level = soap->z_level;
06016   copy->z_crc = soap->z_crc;
06017   copy->z_ratio_in = soap->z_ratio_in;
06018   copy->z_ratio_out = soap->z_ratio_out;
06019   memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf));
06020 #endif
06021   memcpy(copy->buf, soap->buf, sizeof(soap->buf));
06022 }
06023 #endif
06024 
06025 /******************************************************************************/
06026 #ifndef PALM_1
06027 SOAP_FMAC1
06028 void
06029 SOAP_FMAC2
06030 soap_init(struct soap *soap)
06031 { soap->state = SOAP_INIT;
06032   soap->version = 0;
06033   soap_imode(soap, SOAP_IO_DEFAULT);
06034   soap_omode(soap, SOAP_IO_DEFAULT);
06035   soap->plugins = NULL;
06036   soap->user = NULL;
06037   soap->userid = NULL;
06038   soap->passwd = NULL;
06039 #ifndef WITH_NOHTTP
06040   soap->fpost = http_post;
06041   soap->fget = http_get;
06042   soap->fform = NULL;
06043   soap->fposthdr = http_post_header;
06044   soap->fresponse = http_response;
06045   soap->fparse = http_parse;
06046   soap->fparsehdr = http_parse_header;
06047 #endif
06048   soap->fheader = NULL;
06049   soap->fconnect = NULL;
06050   soap->fdisconnect = NULL;
06051 #ifndef WITH_NOIO
06052 #ifndef WITH_IPV6
06053   soap->fresolve = tcp_gethost;
06054 #else
06055   soap->fresolve = NULL;
06056 #endif
06057   soap->faccept = tcp_accept;
06058   soap->fopen = tcp_connect;
06059   soap->fclose = tcp_disconnect;
06060   soap->fclosesocket = tcp_closesocket;
06061   soap->fshutdownsocket = tcp_shutdownsocket;
06062   soap->fsend = fsend;
06063   soap->frecv = frecv;
06064   soap->fpoll = soap_poll;
06065 #else
06066   soap->fopen = NULL;
06067   soap->fclose = NULL;
06068   soap->fpoll = NULL;
06069 #endif
06070   soap->fseterror = NULL;
06071   soap->fignore = NULL;
06072   soap->fserveloop = NULL;
06073   soap->fplugin = fplugin;
06074 #ifndef WITH_LEANER
06075   soap->fprepareinit = NULL;
06076   soap->fpreparesend = NULL;
06077   soap->fpreparerecv = NULL;
06078   soap->fpreparefinal = NULL;
06079   soap->fdimereadopen = NULL;
06080   soap->fdimewriteopen = NULL;
06081   soap->fdimereadclose = NULL;
06082   soap->fdimewriteclose = NULL;
06083   soap->fdimeread = NULL;
06084   soap->fdimewrite = NULL;
06085   soap->fmimereadopen = NULL;
06086   soap->fmimewriteopen = NULL;
06087   soap->fmimereadclose = NULL;
06088   soap->fmimewriteclose = NULL;
06089   soap->fmimeread = NULL;
06090   soap->fmimewrite = NULL;
06091 #endif
06092   soap->float_format = "%G";
06093   soap->double_format = "%lG";
06094   soap->dime_id_format = "cid:id%d"; /* default DIME id format */
06095   soap->http_version = "1.1";
06096   soap->http_content = NULL;
06097   soap->actor = NULL;
06098   soap->max_keep_alive = SOAP_MAXKEEPALIVE;
06099   soap->keep_alive = 0;
06100   soap->recv_timeout = 0;
06101   soap->send_timeout = 0;
06102   soap->connect_timeout = 0;
06103   soap->accept_timeout = 0;
06104   soap->socket_flags = 0;
06105   soap->connect_flags = 0;
06106   soap->bind_flags = 0;
06107   soap->accept_flags = 0;
06108   soap->ip = 0;
06109 #ifdef WITH_FAST
06110   soap->labbuf = NULL;
06111   soap->lablen = 0;
06112   soap->labidx = 0;
06113 #endif
06114   soap->encodingStyle = SOAP_STR_EOS;
06115 #ifndef WITH_NONAMESPACES
06116   soap->namespaces = namespaces;
06117 #else
06118   soap->namespaces = NULL;
06119 #endif
06120   soap->local_namespaces = NULL;
06121   soap->nlist = NULL;
06122   soap->blist = NULL;
06123   soap->clist = NULL;
06124   soap->alist = NULL;
06125   soap->attributes = NULL;
06126   soap->header = NULL;
06127   soap->fault = NULL;
06128   soap->master = SOAP_INVALID_SOCKET;
06129   soap->socket = SOAP_INVALID_SOCKET;
06130   soap->os = NULL;
06131   soap->is = NULL;
06132 #ifndef WITH_LEANER
06133   soap->dom = NULL;
06134   soap->dime.list = NULL;
06135   soap->dime.first = NULL;
06136   soap->dime.last = NULL;
06137   soap->mime.list = NULL;
06138   soap->mime.first = NULL;
06139   soap->mime.last = NULL;
06140   soap->mime.boundary = NULL;
06141   soap->mime.start = NULL;
06142   soap->xlist = NULL;
06143 #endif
06144 #ifndef UNDER_CE
06145   soap->recvfd = 0;
06146   soap->sendfd = 1;
06147 #else
06148   soap->recvfd = stdin;
06149   soap->sendfd = stdout;
06150 #endif 
06151   soap->host[0] = '\0';
06152   soap->port = 0;
06153   soap->action = NULL;
06154   soap->proxy_host = NULL;
06155   soap->proxy_port = 8080;
06156   soap->proxy_userid = NULL;
06157   soap->proxy_passwd = NULL;
06158   soap->authrealm = NULL;
06159   soap->prolog = NULL;
06160 #ifdef WITH_OPENSSL
06161   if (!ssl_init_done)
06162     soap_ssl_init();
06163   soap->fsslauth = ssl_auth_init;
06164   soap->fsslverify = ssl_verify_callback;
06165   soap->bio = NULL;
06166   soap->ssl = NULL;
06167   soap->ctx = NULL;
06168   soap->require_server_auth = 0;
06169   soap->require_client_auth = 0;
06170   soap->rsa = 0;
06171   soap->keyfile = NULL;
06172   soap->password = NULL;
06173   soap->dhfile = NULL;
06174   soap->cafile = NULL;
06175   soap->capath = NULL;
06176   soap->crlfile = NULL;
06177   soap->randfile = NULL;
06178   soap->session = NULL;
06179 #endif
06180 #ifdef WITH_ZLIB
06181   soap->zlib_state = SOAP_ZLIB_NONE;
06182   soap->zlib_in = SOAP_ZLIB_NONE;
06183   soap->zlib_out = SOAP_ZLIB_NONE;
06184   soap->d_stream.zalloc = NULL;
06185   soap->d_stream.zfree = NULL;
06186   soap->d_stream.opaque = NULL;
06187   soap->z_level = 6;
06188 #endif
06189 #ifndef WITH_LEAN
06190   soap->c14ninclude = NULL;
06191   soap->c14nexclude = NULL;
06192   soap->cookies = NULL;
06193   soap->cookie_domain = NULL;
06194   soap->cookie_path = NULL;
06195   soap->cookie_max = 32;
06196 #endif
06197 #ifdef SOAP_DEBUG
06198   soap_init_mht(soap);
06199   soap_init_logs(soap);
06200   soap_set_recv_logfile(soap, "RECV.log");
06201   soap_set_sent_logfile(soap, "SENT.log");
06202   soap_set_test_logfile(soap, NULL);
06203 #endif
06204 #ifdef WMW_RPM_IO
06205   soap->rpmreqid = NULL;
06206 #endif
06207 #ifdef PALM
06208   palmNetLibOpen();
06209 #endif
06210 #ifndef WITH_NOIDREF
06211   soap_init_iht(soap);
06212   soap_init_pht(soap);
06213 #endif
06214   soap_begin(soap);
06215 #ifdef SOAP_DEBUG
06216   soap_set_test_logfile(soap, "TEST.log");
06217 #endif
06218 }
06219 #endif
06220 
06221 /******************************************************************************/
06222 #ifndef PALM_1
06223 SOAP_FMAC1
06224 void
06225 SOAP_FMAC2
06226 soap_init1(struct soap *soap, soap_mode mode)
06227 { soap_init2(soap, mode, mode);
06228 }
06229 #endif
06230 
06231 /******************************************************************************/
06232 #ifndef PALM_1
06233 SOAP_FMAC1
06234 void
06235 SOAP_FMAC2
06236 soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)
06237 { soap_init(soap);
06238   soap_imode(soap, imode);
06239   soap_omode(soap, omode);
06240 }
06241 #endif
06242 
06243 /******************************************************************************/
06244 #ifndef PALM_2
06245 SOAP_FMAC1
06246 void
06247 SOAP_FMAC2
06248 soap_begin(struct soap *soap)
06249 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n"));
06250   if (!soap->keep_alive)
06251   { soap->buflen = 0;
06252     soap->bufidx = 0;
06253   }
06254   soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
06255   soap->null = 0;
06256   soap->position = 0;
06257   soap->encoding = 0;
06258   soap->mustUnderstand = 0;
06259   soap->mode = 0;
06260   soap->ns = 0;
06261   soap->part = SOAP_END;
06262   soap->alloced = 0;
06263   soap->count = 0;
06264   soap->length = 0;
06265   soap->cdata = 0;
06266   soap->error = SOAP_OK;
06267   soap->peeked = 0;
06268   soap->ahead = 0;
06269   soap->idnum = 0;
06270   soap->level = 0;
06271   soap->endpoint[0] = '\0';
06272 #ifndef WITH_LEANER
06273   soap->dime.chunksize = 0;
06274   soap->dime.buflen = 0;
06275 #endif
06276   soap_free(soap);
06277 }
06278 #endif
06279 
06280 /******************************************************************************/
06281 #ifndef PALM_2
06282 SOAP_FMAC1
06283 void
06284 SOAP_FMAC2
06285 soap_end(struct soap *soap)
06286 { register struct soap_clist *cp;
06287   if (soap_check_state(soap))
06288     return;
06289   soap_free(soap);
06290   soap_dealloc(soap, NULL);
06291   while (soap->clist)
06292   { cp = soap->clist->next;
06293     SOAP_FREE(soap, soap->clist);
06294     soap->clist = cp;
06295   }
06296   soap_closesock(soap);
06297 #ifdef SOAP_DEBUG
06298   soap_close_logfiles(soap);
06299 #endif
06300 #ifdef PALM
06301   palmNetLibClose();
06302 #endif
06303 }
06304 #endif
06305 
06306 /******************************************************************************/
06307 #ifndef PALM_1
06308 SOAP_FMAC1
06309 int
06310 SOAP_FMAC2
06311 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
06312 { register struct Namespace *ns = soap->local_namespaces;
06313   register struct soap_nlist *np, *nq, *nr;
06314   register unsigned int level = soap->level;
06315   soap->namespaces = p;
06316   soap->local_namespaces = NULL;
06317   soap_set_local_namespaces(soap);
06318   /* reverse the namespace list */
06319   np = soap->nlist;
06320   soap->nlist = NULL;
06321   if (np)
06322   { nq = np->next;
06323     np->next = NULL;
06324     while (nq)
06325     { nr = nq->next;
06326       nq->next = np;
06327       np = nq;
06328       nq = nr;
06329     }
06330   }
06331   /* then push on new stack */
06332   while (np)
06333   { register const char *s;
06334     soap->level = np->level; /* preserve element nesting level */
06335     s = np->ns;
06336     if (!s && np->index >= 0 && ns)
06337     { s = ns[np->index].out;
06338       if (!s)
06339         s = ns[np->index].ns;
06340     }
06341     if (s && soap_push_namespace(soap, np->id, s))
06342       return soap->error;
06343     nq = np;
06344     np = np->next;
06345     SOAP_FREE(soap, nq);
06346   }
06347   if (ns)
06348   { register int i;
06349     for (i = 0; ns[i].id; i++)
06350     { if (ns[i].out)
06351       { SOAP_FREE(soap, ns[i].out);
06352         ns[i].out = NULL;
06353       }
06354     }
06355     SOAP_FREE(soap, ns);
06356   }
06357   soap->level = level; /* restore level */
06358   return SOAP_OK;
06359 }
06360 #endif
06361 
06362 /******************************************************************************/
06363 #ifndef PALM_1
06364 SOAP_FMAC1
06365 void
06366 SOAP_FMAC2
06367 soap_set_local_namespaces(struct soap *soap)
06368 { if (soap->namespaces && !soap->local_namespaces)
06369   { register const struct Namespace *ns1;
06370     register struct Namespace *ns2;
06371     register size_t n = 1;
06372     for (ns1 = soap->namespaces; ns1->id; ns1++)
06373       n++;
06374     n *= sizeof(struct Namespace);
06375     ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
06376     if (ns2)
06377     { memcpy(ns2, soap->namespaces, n);
06378       if (ns2[0].ns)
06379       { if (!strcmp(ns2[0].ns, soap_env1))
06380           soap->version = 1;
06381         else
06382           soap->version = 2;
06383       }
06384       soap->local_namespaces = ns2;
06385     }
06386   }
06387 }
06388 #endif
06389 
06390 /******************************************************************************/
06391 #ifndef WITH_LEAN
06392 #ifndef PALM_1
06393 SOAP_FMAC1
06394 const char *
06395 SOAP_FMAC2
06396 soap_strsearch(const char *big, const char *little)
06397 { size_t n = strlen(little);
06398   const char *s = big;
06399   while (s) 
06400   { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' '))
06401       return s;
06402     s = strchr(s, ' ');
06403     if (s)
06404       s++;
06405   }
06406   return NULL;
06407 }
06408 #endif
06409 #endif
06410 
06411 /******************************************************************************/
06412 #ifndef WITH_LEAN
06413 static struct soap_nlist *
06414 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
06415 { register struct soap_nlist *np;
06416   for (np = soap->nlist; np; np = np->next)
06417   { if (!strncmp(np->id, tag, n) && !np->id[n])
06418       return np;
06419   }
06420   return NULL;
06421 }
06422 #endif
06423 
06424 /******************************************************************************/
06425 #ifndef WITH_LEAN
06426 static struct soap_nlist *
06427 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
06428 { register struct soap_nlist *np;
06429   size_t n, k;
06430   if (soap_strsearch(soap->c14nexclude, id))
06431     return NULL;
06432   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns?ns:""));
06433   if (!utilized)
06434   { for (np = soap->nlist; np; np = np->next)
06435     { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
06436         break;
06437     }
06438     if (np)
06439     { if (np->index == 1)
06440         utilized = np->index;
06441       else
06442         return NULL;
06443     }
06444   }
06445   n = strlen(id);
06446   if (ns)
06447     k = strlen(ns);
06448   else
06449     k = 0;
06450   np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
06451   if (!np)
06452   { soap->error = SOAP_EOM;
06453     return NULL;
06454   }
06455   np->next = soap->nlist;
06456   soap->nlist = np;
06457   strcpy(np->id, id);
06458   if (ns)
06459   { np->ns = np->id + n + 1;
06460     strcpy(np->ns, ns);
06461   }
06462   else
06463     np->ns = NULL;
06464   np->level = soap->level;
06465   np->index = utilized;
06466   return np;
06467 }
06468 #endif
06469 
06470 /******************************************************************************/
06471 #ifndef WITH_LEAN
06472 static void
06473 soap_utilize_ns(struct soap *soap, const char *tag, size_t n)
06474 { register struct soap_nlist *np = soap_lookup_ns(soap, tag, n);
06475   if (np)
06476   { if (np->index == 0)
06477       soap_push_ns(soap, np->id, np->ns, 1);
06478   }
06479   else
06480   { strncpy(soap->tmpbuf, tag, n);
06481     soap->tmpbuf[n] = '\0';
06482     soap_push_ns(soap, soap->tmpbuf, NULL, 1);
06483   }
06484 }
06485 #endif
06486 
06487 /******************************************************************************/
06488 #ifndef WITH_LEAN
06489 static void
06490 soap_pop_ns(struct soap *soap)
06491 { soap_pop_namespace(soap);
06492 }
06493 #endif
06494 
06495 /******************************************************************************/
06496 #ifndef PALM_2
06497 SOAP_FMAC1
06498 int
06499 SOAP_FMAC2
06500 soap_element(struct soap *soap, const char *tag, int id, const char *type)
06501 {
06502 #ifdef WITH_XMLNS
06503   register const char *s;
06504 #endif
06505   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:""));
06506 #ifdef WITH_DOM
06507   if (soap->mode & SOAP_XML_DOM)
06508   { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
06509     if (!elt)
06510       return soap->error = SOAP_EOM;
06511     elt->soap = soap;
06512     elt->next = NULL;
06513     elt->prnt = soap->dom;
06514     elt->name = soap_strdup(soap, tag);
06515     elt->elts = NULL;
06516     elt->atts = NULL;
06517     elt->nstr = NULL;
06518     elt->data = NULL;
06519     elt->wide = NULL;
06520     elt->node = NULL;
06521     elt->type = 0;
06522     elt->head = NULL;
06523     elt->tail = NULL;
06524     if (soap->dom)
06525     { struct soap_dom_element *p = soap->dom->elts;
06526       if (p)
06527       { while (p->next)
06528           p = p->next;
06529         p->next = elt;
06530       }
06531       else
06532         soap->dom->elts = elt;
06533     }
06534     soap->dom = elt;
06535   }
06536   else
06537   {
06538 #endif
06539     soap->level++;
06540 #ifndef WITH_LEAN
06541     if (!soap->ns)
06542     { if (!(soap->mode & SOAP_XML_CANONICAL)
06543        && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
06544         return soap->error;
06545     }
06546     else if (soap->mode & SOAP_XML_INDENT)
06547     { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
06548         return soap->error;
06549       soap->body = 1;
06550     }
06551 #endif
06552 #ifdef WITH_XMLNS
06553     s = strchr(tag, ':');
06554     if (s && strncmp(tag, "SOAP-ENV", s - tag))
06555     { struct Namespace *ns = soap->local_namespaces;
06556       size_t n = s - tag;
06557       if (soap_send_raw(soap, "<", 1)
06558        || soap_send(soap, s + 1))
06559         return soap->error;
06560       if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
06561         ns = NULL;
06562       for (; ns && ns->id; ns++)
06563       { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
06564         { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
06565           if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
06566             return soap->error;
06567           break;
06568         }
06569       }   
06570     }
06571     else
06572 #endif
06573     if (soap_send_raw(soap, "<", 1)
06574      || soap_send(soap, tag))
06575       return soap->error;
06576 #ifdef WITH_DOM
06577   }
06578 #endif
06579   if (!soap->ns)
06580   { struct Namespace *ns;
06581     for (ns = soap->local_namespaces; ns && ns->id; ns++)
06582     { if (*ns->id && (ns->out || ns->ns))
06583       { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
06584         if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
06585           return soap->error;
06586       }
06587     }   
06588   }
06589   soap->ns = 1; /* start with 0 or 2, but should be one to continue */
06590 #ifndef WITH_LEAN
06591   if (soap->mode & SOAP_XML_CANONICAL)
06592   { const char *t = strchr(tag, ':');
06593     if (t)
06594       soap_utilize_ns(soap, tag, t - tag);
06595   }
06596 #endif
06597   if (id > 0)
06598   { sprintf(soap->tmpbuf, "_%d", id);
06599     if (soap_attribute(soap, "id", soap->tmpbuf))
06600       return soap->error;
06601   }
06602   if (type && *type)
06603   { if (soap_attribute(soap, "xsi:type", type))
06604       return soap->error;
06605 #ifndef WITH_LEAN
06606     if (soap->mode & SOAP_XML_CANONICAL)
06607     { const char *t = strchr(type, ':');
06608       if (t)
06609         soap_utilize_ns(soap, type, t - type);
06610     }
06611 #endif
06612   }
06613   if (soap->null && soap->position > 0)
06614   { register int i;
06615     sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
06616     for (i = 1; i < soap->position; i++)
06617       sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
06618     strcat(soap->tmpbuf, "]");
06619     if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
06620       return soap->error;
06621   }
06622   if (soap->mustUnderstand)
06623   { if (soap->actor && *soap->actor)
06624     { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
06625         return soap->error;
06626     }
06627     if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
06628       return soap->error;
06629     soap->mustUnderstand = 0;
06630   }
06631   if (soap->encoding)
06632   { if (soap->encodingStyle && soap->local_namespaces)
06633     { if (!*soap->encodingStyle)
06634       { if (soap->local_namespaces[1].out)
06635           soap->encodingStyle = soap->local_namespaces[1].out;
06636         else
06637           soap->encodingStyle = soap->local_namespaces[1].ns;
06638       }
06639       if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
06640         return soap->error;
06641     }
06642     soap->encoding = 0;
06643   }
06644   soap->null = 0;
06645   soap->position = 0;
06646   return SOAP_OK;
06647 }
06648 #endif
06649 
06650 /******************************************************************************/
06651 #ifndef PALM_2
06652 SOAP_FMAC1
06653 int
06654 SOAP_FMAC2
06655 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
06656 { if (*tag == '-')
06657     return SOAP_OK;
06658   if (soap_element(soap, tag, id, type))
06659     return soap->error;
06660   return soap_element_start_end_out(soap, NULL);
06661 }
06662 #endif
06663 
06664 /******************************************************************************/
06665 #ifndef PALM_2
06666 #ifndef HAVE_STRRCHR
06667 SOAP_FMAC1
06668 char*
06669 SOAP_FMAC2
06670 soap_strrchr(const char *s, int t)
06671 { register char *r = NULL;
06672   while (*s)
06673     if (*s++ == t)
06674       r = (char*)s - 1;
06675   return r;
06676 }
06677 #endif
06678 #endif
06679 
06680 /******************************************************************************/
06681 #ifndef PALM_2
06682 #ifndef HAVE_STRTOL
06683 SOAP_FMAC1
06684 long
06685 SOAP_FMAC2
06686 soap_strtol(const char *s, char **t, int b)
06687 { register long n = 0;
06688   register int c;
06689   while (*s > 0 && *s <= 32)
06690     s++;
06691   if (b == 10)
06692   { short neg = 0;
06693     if (*s == '-')
06694     { s++;
06695       neg = 1;
06696     }
06697     else if (*s == '+')
06698       s++;
06699     while ((c = *s) && c >= '0' && c <= '9')
06700     { if (n >= 214748364 && (n > 214748364 || c >= '8'))
06701         break;
06702       n *= 10;
06703       n += c - '0';
06704       s++;
06705     }
06706     if (neg)
06707       n = -n;
06708   }
06709   else /* b == 16 and value is always positive */
06710   { while ((c = *s))
06711     { if (c >= '0' && c <= '9')
06712         c -= '0';
06713       else if (c >= 'A' && c <= 'F')
06714         c -= 'A' - 10;
06715       else if (c >= 'a' && c <= 'f')
06716         c -= 'a' - 10;
06717       if (n > 0x07FFFFFF)
06718         break;
06719       n <<= 4;
06720       n += c;
06721       s++;
06722     }
06723   }
06724   if (t)
06725     *t = (char*)s;
06726   return n;
06727 }
06728 #endif
06729 #endif
06730 
06731 /******************************************************************************/
06732 #ifndef PALM_2
06733 #ifndef HAVE_STRTOUL
06734 SOAP_FMAC1
06735 unsigned long
06736 SOAP_FMAC2
06737 soap_strtoul(const char *s, char **t, int b)
06738 { unsigned long n = 0;
06739   register int c;
06740   while (*s > 0 && *s <= 32)
06741     s++;
06742   if (b == 10)
06743   { if (*s == '+')
06744       s++;
06745     while ((c = *s) && c >= '0' && c <= '9')
06746     { if (n >= 429496729 && (n > 429496729 || c >= '6'))
06747         break;
06748       n *= 10;
06749       n += c - '0';
06750       s++;
06751     }
06752   }
06753   else /* b == 16 */
06754   { while ((c = *s))
06755     { if (c >= '0' && c <= '9')
06756         c -= '0';
06757       else if (c >= 'A' && c <= 'F')
06758         c -= 'A' - 10;
06759       else if (c >= 'a' && c <= 'f')
06760         c -= 'a' - 10;
06761       if (n > 0x0FFFFFFF)
06762         break;
06763       n <<= 4;
06764       n += c;
06765       s++;
06766     }
06767   }
06768   if (t)
06769     *t = (char*)s;
06770   return n;
06771 }
06772 #endif
06773 #endif
06774 
06775 /******************************************************************************/
06776 #ifndef PALM_1
06777 SOAP_FMAC1
06778 int
06779 SOAP_FMAC2
06780 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
06781 { if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
06782     return soap->error;
06783   if (soap->version == 2)
06784   { const char *s;
06785     s = soap_strrchr(type, '[');
06786     if ((size_t)(s - type) < sizeof(soap->tmpbuf))
06787     { strncpy(soap->tmpbuf, type, s - type);
06788       soap->tmpbuf[s - type] = '\0';
06789       if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)))
06790         return soap->error;
06791       if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
06792         return soap->error;
06793     }
06794   }
06795   else
06796   { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset)))
06797       return soap->error;
06798     if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type)))
06799       return soap->error;
06800   }
06801 #ifndef WITH_LEAN
06802   if (type && *type && (soap->mode & SOAP_XML_CANONICAL))
06803   { const char *s = strchr(type, ':');
06804     if (s)
06805       soap_utilize_ns(soap, type, s - type);
06806   }
06807 #endif
06808   return soap_element_start_end_out(soap, NULL);
06809 }
06810 #endif
06811 
06812 /******************************************************************************/
06813 #ifndef PALM_1
06814 SOAP_FMAC1
06815 int
06816 SOAP_FMAC2
06817 soap_element_start_end_out(struct soap *soap, const char *tag)
06818 { register struct soap_attribute *tp;
06819 #ifndef WITH_LEAN
06820   if (soap->mode & SOAP_XML_CANONICAL)
06821   { struct soap_nlist *np;
06822     for (tp = soap->attributes; tp; tp = tp->next)
06823     { if (tp->visible && tp->name)
06824       { const char *s = strchr(tp->name, ':');
06825         if (s)
06826           soap_utilize_ns(soap, tp->name, s - tp->name);
06827       }
06828     }
06829     for (np = soap->nlist; np; np = np->next)
06830     { if (np->index == 1 && np->ns)
06831       { sprintf(soap->tmpbuf, "xmlns:%s", np->id);
06832         soap_set_attr(soap, soap->tmpbuf, np->ns);
06833         np->index = 2;
06834       }
06835     }
06836   }
06837 #endif
06838 #ifdef WITH_DOM
06839   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
06840   { register struct soap_dom_attribute **att;
06841     att = &soap->dom->atts;
06842     for (tp = soap->attributes; tp; tp = tp->next)
06843     { if (tp->visible)
06844       { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
06845         if (!*att)
06846           return soap->error = SOAP_EOM;
06847         (*att)->next = NULL;
06848         (*att)->nstr = NULL;
06849         (*att)->name = soap_strdup(soap, tp->name);
06850         (*att)->data = soap_strdup(soap, tp->value);
06851         (*att)->wide = NULL;
06852         (*att)->soap = soap;
06853         att = &(*att)->next;
06854         tp->visible = 0;
06855       }
06856     }
06857     return SOAP_OK;
06858   }
06859 #endif
06860   for (tp = soap->attributes; tp; tp = tp->next)
06861   { if (tp->visible)
06862     {
06863 #ifdef WITH_XMLNS
06864       const char *s = strchr(tp->name, ':');
06865       if (s)
06866       { size_t n = s - tp->name;
06867         if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
06868           s++;
06869         else
06870           s = tp->name;
06871         if (soap_send(soap, " ") || soap_send(soap, s))
06872           return soap->error;
06873       }
06874       else
06875 #endif
06876       if (soap_send(soap, " ") || soap_send(soap, tp->name))
06877         return soap->error;
06878       if (tp->visible == 2 && tp->value)
06879         if (soap_send_raw(soap, "=\"", 2)
06880          || soap_string_out(soap, tp->value, 1)
06881          || soap_send_raw(soap, "\"", 1))
06882           return soap->error;
06883       tp->visible = 0;
06884     }
06885   }
06886   if (tag)
06887   { 
06888 #ifndef WITH_LEAN
06889     if (soap->mode & SOAP_XML_CANONICAL)
06890     { if (soap_send_raw(soap, ">", 1)
06891        || soap_element_end_out(soap, tag))
06892         return soap->error;
06893       return SOAP_OK;
06894     }
06895 #endif
06896     soap->level--;      /* decrement level just before /> */
06897     if (soap_send_raw(soap, "/>", 2))
06898       return soap->error;
06899     return SOAP_OK;
06900   }
06901   return soap_send_raw(soap, ">", 1);
06902 }
06903 #endif
06904 
06905 /******************************************************************************/
06906 #ifndef PALM_1
06907 SOAP_FMAC1
06908 int
06909 SOAP_FMAC2
06910 soap_element_end_out(struct soap *soap, const char *tag)
06911 { if (*tag == '-')
06912     return SOAP_OK;
06913   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
06914 #ifdef WITH_DOM
06915   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
06916   { if (soap->dom->prnt)
06917       soap->dom = soap->dom->prnt;
06918     return SOAP_OK;
06919   }
06920 #endif
06921 #ifndef WITH_LEAN
06922   if (soap->mode & SOAP_XML_CANONICAL)
06923     soap_pop_ns(soap);
06924   if (soap->mode & SOAP_XML_INDENT)
06925   { if (!soap->body)
06926     { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
06927         return soap->error;
06928     }
06929     soap->body = 0;
06930   }
06931 #endif
06932 #ifdef WITH_XMLNS
06933   { const char *s = strchr(tag, ':');
06934     if (s && strncmp(tag, "SOAP-ENV", s - tag))
06935     { soap_pop_ns(soap);
06936       tag = s + 1;
06937     }
06938   }
06939 #endif
06940   if (soap_send_raw(soap, "</", 2)
06941    || soap_send(soap, tag))
06942     return soap->error;
06943   soap->level--;        /* decrement level just before > */
06944   return soap_send_raw(soap, ">", 1);
06945 }
06946 #endif
06947 
06948 /******************************************************************************/
06949 #ifndef PALM_1
06950 SOAP_FMAC1
06951 int
06952 SOAP_FMAC2
06953 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
06954 { register int n = 0;
06955   if (soap->version == 2)
06956     n = 1;
06957   sprintf(soap->href, "#_%d", href);
06958   return soap_element_href(soap, tag, id, "href" + n, soap->href + n);
06959 }
06960 #endif
06961 
06962 /******************************************************************************/
06963 #ifndef PALM_1
06964 SOAP_FMAC1
06965 int
06966 SOAP_FMAC2
06967 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
06968 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
06969   if (soap_element(soap, tag, id, NULL)
06970    || soap_attribute(soap, ref, val)
06971    || soap_element_start_end_out(soap, tag))
06972     return soap->error;
06973   return SOAP_OK;
06974 }
06975 #endif
06976 
06977 /******************************************************************************/
06978 #ifndef PALM_1
06979 SOAP_FMAC1
06980 int
06981 SOAP_FMAC2
06982 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
06983 { struct soap_attribute *tp;
06984   for (tp = soap->attributes; tp; tp = tp->next)
06985     if (tp->visible)
06986       break;
06987   if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
06988   { if (soap_element(soap, tag, id, type))
06989       return soap->error;
06990     if (soap->part != SOAP_IN_HEADER && soap->encodingStyle)
06991       if (soap_attribute(soap, "xsi:nil", "true"))
06992         return soap->error;
06993     return soap_element_start_end_out(soap, tag);
06994   }
06995   soap->null = 1;
06996   soap->position = 0;
06997   soap->mustUnderstand = 0;
06998   return SOAP_OK;
06999 }
07000 #endif
07001 
07002 /******************************************************************************/
07003 #ifndef PALM_1
07004 SOAP_FMAC1
07005 int
07006 SOAP_FMAC2
07007 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) 
07008 { if (!p || (a && !a->__ptr))
07009   { soap_element_null(soap, tag, id, type);
07010     return -1;
07011   }
07012 #ifndef WITH_NOIDREF
07013   if (soap->mode & SOAP_XML_TREE)
07014     return 0;
07015   if (id < 0)
07016   { struct soap_plist *pp;
07017     if (a)
07018       id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
07019     else
07020       id = soap_pointer_lookup(soap, p, t, &pp);
07021     if (id)
07022     { if (soap_is_embedded(soap, pp))
07023       { soap_element_ref(soap, tag, 0, id);
07024         return -1;
07025       }
07026       if (soap_is_single(soap, pp))
07027         return 0;
07028       soap_set_embedded(soap, pp);
07029     }
07030   }
07031   return id;
07032 #else
07033   return 0;
07034 #endif
07035 }
07036 #endif
07037 
07038 /******************************************************************************/
07039 #ifndef PALM_1
07040 SOAP_FMAC1
07041 int
07042 SOAP_FMAC2
07043 soap_element_result(struct soap *soap, const char *tag)
07044 { if (soap->version == 2 && soap->encodingStyle)
07045     if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
07046      || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
07047      || soap_element_start_end_out(soap, NULL)
07048      || soap_string_out(soap, tag, 0)
07049      || soap_element_end_out(soap, "SOAP-RPC:result"))
07050       return soap->error;
07051   return SOAP_OK;
07052 }
07053 #endif
07054 
07055 /******************************************************************************/
07056 #ifndef PALM_1
07057 SOAP_FMAC1
07058 void
07059 SOAP_FMAC2
07060 soap_check_result(struct soap *soap, const char *tag)
07061 { if (soap->version == 2 && soap->encodingStyle)
07062   { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
07063     /* should compare tag to element's QName value? */
07064   }
07065 }
07066 #endif
07067 
07068 /******************************************************************************/
07069 #ifndef PALM_2
07070 SOAP_FMAC1
07071 int
07072 SOAP_FMAC2
07073 soap_attribute(struct soap *soap, const char *name, const char *value)
07074 { 
07075 #ifdef WITH_DOM
07076   if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
07077   { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
07078     a->next = soap->dom->atts;
07079     a->nstr = NULL;
07080     a->name = soap_strdup(soap, name);
07081     a->data = soap_strdup(soap, value);
07082     a->wide = NULL;
07083     a->soap = soap;
07084     soap->dom->atts = a;
07085     return SOAP_OK;
07086   }
07087 #endif
07088 #ifndef WITH_LEAN
07089   if (soap->mode & SOAP_XML_CANONICAL)
07090   { /* TODO: consider using this code to handle default namespace bindings
07091     if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
07092     { if (name[5] == ':')
07093         soap_push_ns(soap, name + 6, value, 0);
07094       else
07095         soap_push_ns(soap, "", value, 0);
07096     }
07097     */
07098     if (!strncmp(name, "xmlns:", 6))
07099       soap_push_ns(soap, name + 6, value, 0);
07100     else if (soap_set_attr(soap, name, value))
07101       return soap->error;
07102   }
07103   else
07104 #endif
07105   { if (soap_send(soap, " ") || soap_send(soap, name))
07106       return soap->error;
07107     if (value)
07108       if (soap_send_raw(soap, "=\"", 2)
07109        || soap_string_out(soap, value, 1)
07110        || soap_send_raw(soap, "\"", 1))
07111         return soap->error;
07112   }
07113   return SOAP_OK;
07114 }
07115 #endif
07116 
07117 /******************************************************************************/
07118 #ifndef PALM_2
07119 SOAP_FMAC1
07120 int
07121 SOAP_FMAC2
07122 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
07123 { if (!soap_peek_element(soap))
07124   { if (soap->other)
07125       return soap->error = SOAP_TAG_MISMATCH;
07126     if (tag && *tag == '-')
07127       return SOAP_OK;
07128     if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
07129     { soap->peeked = 0;
07130       if (soap->body)
07131         soap->level++;
07132       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" ));
07133       if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
07134         return soap->error = SOAP_NULL;
07135       if (type && *soap->type && soap_match_tag(soap, soap->type, type))
07136         return soap->error = SOAP_TYPE;
07137     }
07138   }
07139   else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
07140     soap->error = SOAP_OK;
07141   return soap->error;
07142 }
07143 #endif
07144 
07145 /******************************************************************************/
07146 #ifndef PALM_2
07147 SOAP_FMAC1
07148 int
07149 SOAP_FMAC2
07150 soap_element_end_in(struct soap *soap, const char *tag)  
07151 { register soap_wchar c;
07152   register char *s;
07153   register const char *t;
07154   register int n = 0;
07155   if (tag && *tag == '-')
07156     return SOAP_OK;
07157   soap->level--;
07158   soap_pop_namespace(soap);
07159 #ifdef WITH_DOM
07160   /* this whitespace or mixed content is not insignificant for DOM */
07161   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
07162   { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
07163       return soap->error;
07164     if (soap->dom->prnt)
07165       soap->dom = soap->dom->prnt;
07166   }
07167 #endif
07168   if (soap->peeked)
07169   { if (soap->error == SOAP_NO_TAG)
07170       soap->error = SOAP_OK;
07171     if (*soap->tag)
07172       n++;
07173     soap->peeked = 0;
07174   }
07175   do
07176   { while (((c = soap_get(soap)) != SOAP_TT))
07177     { if ((int)c == EOF)
07178         return soap->error = SOAP_EOF;
07179       if (c == SOAP_LT)
07180         n++;
07181       else if (c == '/')
07182       { c = soap_get(soap);
07183         if (c == SOAP_GT)
07184           n--;
07185         else
07186           soap_unget(soap, c);
07187       }
07188     }
07189   } while (n--);
07190   s = soap->tag;
07191   while (soap_notblank(c = soap_get(soap)))
07192     *s++ = (char)c;
07193   *s = '\0';
07194   if ((int)c == EOF)
07195     return soap->error = SOAP_EOF;
07196   while (soap_blank(c))
07197     c = soap_get(soap);
07198   if (c != SOAP_GT)
07199     return soap->error = SOAP_SYNTAX_ERROR;
07200   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:""));
07201   if (!tag || !*tag)
07202     return SOAP_OK;
07203   if ((s = strchr(soap->tag, ':')))
07204     s++;
07205   else
07206     s = soap->tag;
07207   if ((t = strchr(tag, ':')))
07208     t++;
07209   else
07210     t = tag;
07211   if (!SOAP_STRCMP(s, t))
07212     return SOAP_OK;
07213   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n"));
07214   return soap->error = SOAP_SYNTAX_ERROR;
07215 }
07216 #endif
07217 
07218 /******************************************************************************/
07219 #ifndef PALM_2
07220 SOAP_FMAC1
07221 const char *
07222 SOAP_FMAC2
07223 soap_attr_value(struct soap *soap, const char *name, int flag)
07224 { register struct soap_attribute *tp;
07225   for (tp = soap->attributes; tp; tp = tp->next)
07226   { if (tp->visible && !soap_match_tag(soap, tp->name, name))
07227       break;
07228   }
07229   if (tp)
07230   { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
07231       soap->error = SOAP_PROHIBITED;
07232     else
07233       return tp->value;
07234   }
07235   else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
07236     soap->error = SOAP_REQUIRED;
07237   return NULL;
07238 }
07239 #endif
07240 
07241 /******************************************************************************/
07242 #ifndef PALM_2
07243 SOAP_FMAC1
07244 int
07245 SOAP_FMAC2
07246 soap_set_attr(struct soap *soap, const char *name, const char *value)
07247 { register struct soap_attribute *tp;
07248   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:""));
07249   for (tp = soap->attributes; tp; tp = tp->next)
07250   { if (!strcmp(tp->name, name))
07251       break;
07252   }
07253   if (!tp)
07254   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
07255     if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
07256       return soap->error = SOAP_EOM;
07257     tp->ns = NULL;
07258 #ifndef WITH_LEAN
07259     if (soap->mode & SOAP_XML_CANONICAL)
07260     { struct soap_attribute **tpp = &soap->attributes;
07261       const char *s = strchr(name, ':');
07262       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
07263       if (!strncmp(name, "xmlns", 5))
07264       { for (; *tpp; tpp = &(*tpp)->next)
07265           if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
07266             break;
07267       }
07268       else if (!s)
07269       { for (; *tpp; tpp = &(*tpp)->next)
07270           if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
07271             break;
07272       }
07273       else
07274       { int k;
07275         for (; *tpp; tpp = &(*tpp)->next)
07276         { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name])
07277           { if (!tp->ns)
07278             { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns));
07279               tp->ns = (*tpp)->ns;
07280             }
07281           }
07282           else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
07283             break;
07284         }
07285       }
07286       tp->next = *tpp;
07287       *tpp = tp;
07288     }
07289     else
07290 #endif
07291     { tp->next = soap->attributes;
07292       soap->attributes = tp;
07293     }
07294     strcpy(tp->name, name);
07295     tp->value = NULL;
07296   }
07297   else if (tp->visible)
07298   { return SOAP_OK;
07299   }
07300   else if (value && tp->value && tp->size <= strlen(value))
07301   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
07302     SOAP_FREE(soap, tp->value);
07303     tp->value = NULL;
07304     tp->ns = NULL;
07305   }
07306   if (value)
07307   { if (!tp->value)
07308     { tp->size = strlen(value) + 1;
07309       if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
07310         return soap->error = SOAP_EOM;
07311       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value));
07312     }
07313     strcpy(tp->value, value);
07314     if (!strncmp(tp->name, "xmlns:", 6))
07315       tp->ns = tp->value;
07316     tp->visible = 2;
07317 #ifndef WITH_LEAN
07318     if (!strcmp(name, "wsu:Id"))
07319     { soap->part = SOAP_BEGIN_SECURITY;
07320       strncpy(soap->id, value, sizeof(soap->id));
07321       soap->id[sizeof(soap->id)-1] = '\0';
07322     }
07323 #endif
07324   }
07325   else
07326     tp->visible = 1;
07327   return SOAP_OK;
07328 }
07329 #endif
07330 
07331 /******************************************************************************/
07332 #ifndef PALM_2
07333 SOAP_FMAC1
07334 void
07335 SOAP_FMAC2
07336 soap_clr_attr(struct soap *soap)
07337 { register struct soap_attribute *tp;
07338 #ifndef WITH_LEAN
07339   if ((soap->mode & SOAP_XML_CANONICAL))
07340   { while (soap->attributes)
07341     { tp = soap->attributes->next;
07342       SOAP_FREE(soap, soap->attributes->value);
07343       SOAP_FREE(soap, soap->attributes);
07344       soap->attributes = tp;
07345     }
07346   }
07347   else
07348 #endif
07349   { for (tp = soap->attributes; tp; tp = tp->next)
07350       tp->visible = 0;
07351   }
07352 }
07353 #endif
07354 
07355 /******************************************************************************/
07356 #ifndef PALM_2
07357 static int
07358 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
07359 { register size_t i;
07360   for (i = 0; i < n; i++)
07361   { register soap_wchar c = soap_get(soap);
07362     switch (c)
07363     {
07364     case SOAP_TT:
07365       *s++ = '<';
07366       soap_unget(soap, '/');
07367       break;
07368     case SOAP_LT:
07369       *s++ = '<';
07370       break;
07371     case SOAP_GT:
07372       if (d == ' ')
07373       { soap_unget(soap, c);
07374         *s = '\0';
07375         return SOAP_OK;
07376       }
07377       *s++ = '>';
07378       break;
07379     case SOAP_QT:
07380       if (c == d)
07381       { *s = '\0';
07382         return SOAP_OK;
07383       }
07384       *s++ = '"';
07385       break;
07386     case SOAP_AP:
07387       if (c == d)
07388       { *s = '\0';
07389         return SOAP_OK;
07390       }
07391       *s++ = '\'';
07392       break;
07393     case '\t':
07394     case '\n':
07395     case '\r':
07396     case ' ':
07397     case '/':
07398       if (d == ' ')
07399       { soap_unget(soap, c);
07400         *s = '\0';
07401         return SOAP_OK;
07402       }
07403     default:
07404       if ((int)c == EOF)
07405         return soap->error = SOAP_EOF;
07406       *s++ = (char)c;
07407     }
07408   }
07409   return soap->error = SOAP_EOM;
07410 }
07411 #endif
07412 
07413 /******************************************************************************/
07414 #ifdef WITH_FAST
07415 #ifndef PALM_2
07416 SOAP_FMAC1
07417 int
07418 SOAP_FMAC2
07419 soap_store_lab(struct soap *soap, const char *s, size_t n)
07420 { soap->labidx = 0;
07421   return soap_append_lab(soap, s, n);
07422 }
07423 #endif
07424 #endif
07425 
07426 /******************************************************************************/
07427 #ifdef WITH_FAST
07428 #ifndef PALM_2
07429 SOAP_FMAC1
07430 int
07431 SOAP_FMAC2
07432 soap_append_lab(struct soap *soap, const char *s, size_t n)
07433 { if (soap->labidx + n >= soap->lablen)
07434   { register char *t = soap->labbuf;
07435     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
07436     if (soap->lablen == 0)
07437       soap->lablen = SOAP_LABLEN;
07438     while (soap->labidx + n >= soap->lablen)
07439       soap->lablen <<= 1;
07440     DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
07441     soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
07442     if (!soap->labbuf)
07443     { if (t)
07444         SOAP_FREE(soap, t);
07445       return soap->error = SOAP_EOM;
07446     }
07447     if (t)
07448     { memcpy(soap->labbuf, t, soap->labidx);
07449       SOAP_FREE(soap, t);
07450     }
07451   }
07452   if (s)
07453   { memcpy(soap->labbuf + soap->labidx, s, n);
07454     soap->labidx += n;
07455   }
07456   return SOAP_OK;
07457 }
07458 #endif
07459 #endif
07460 
07461 /******************************************************************************/
07462 #ifndef PALM_2
07463 SOAP_FMAC1
07464 int
07465 SOAP_FMAC2
07466 soap_peek_element(struct soap *soap)
07467 {
07468 #ifdef WITH_DOM
07469   register struct soap_dom_attribute **att = NULL;
07470   register char *lead = NULL;
07471 #endif
07472   register struct soap_attribute *tp;
07473   const char *t;
07474   register char *s;
07475   register soap_wchar c;
07476   register int i;
07477   if (soap->peeked)
07478   { if (!*soap->tag)
07479       return soap->error = SOAP_NO_TAG;
07480     return SOAP_OK;
07481   }
07482   soap->peeked = 1;
07483   c = soap_getutf8(soap);
07484 #ifdef WITH_DOM
07485   /* whitespace leading to start tag is not insignificant for DOM */
07486   if (soap_blank(c))
07487   { soap->labidx = 0;
07488     do
07489     { if (soap_append_lab(soap, NULL, 0))
07490         return SOAP_EOM;
07491       s = soap->labbuf + soap->labidx;
07492       i = soap->lablen - soap->labidx;
07493       soap->labidx = soap->lablen;
07494       while (soap_blank(c) && i--)
07495       { *s++ = c;
07496         c = soap_getutf8(soap);
07497       }
07498     }
07499     while (soap_blank(c));
07500     *s = '\0';
07501     lead = soap_strdup(soap, soap->labbuf);
07502   }
07503 #else
07504   while (soap_blank(c))
07505     c = soap_getutf8(soap);
07506 #endif
07507   if (c != SOAP_LT)
07508   { *soap->tag = '\0';
07509     if ((int)c == EOF)
07510       return soap->error = SOAP_EOF;
07511     soap_unget(soap, c);
07512 #ifdef WITH_DOM
07513     /* whitespace leading to end tag is not insignificant for DOM */
07514     if ((soap->mode & SOAP_XML_DOM) && soap->dom)
07515       soap->dom->tail = soap_strdup(soap, lead);
07516 #endif
07517     return soap->error = SOAP_NO_TAG;
07518   }
07519   s = soap->tag;
07520   do c = soap_get1(soap);
07521   while (soap_blank(c));
07522   i = sizeof(soap->tag);
07523   while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
07524   { if (--i > 0)
07525       *s++ = (char)c;
07526     c = soap_get1(soap);
07527   }
07528   while (soap_blank(c))
07529     c = soap_get1(soap);
07530   *s = '\0';
07531   soap->id[0] = '\0';
07532   soap->href[0] = '\0';
07533   soap->type[0] = '\0';
07534   soap->arrayType[0] = '\0';
07535   soap->arraySize[0] = '\0';
07536   soap->arrayOffset[0] = '\0';
07537   soap->other = 0;
07538   soap->root = -1;
07539   soap->position = 0;
07540   soap->null = 0;
07541   soap->mustUnderstand = 0;
07542 #ifdef WITH_DOM
07543   if (soap->mode & SOAP_XML_DOM)
07544   { register struct soap_dom_element *elt;
07545     elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
07546     if (!elt)
07547       return soap->error = SOAP_EOM;
07548     elt->next = NULL;
07549     elt->nstr = NULL;
07550     elt->name = soap_strdup(soap, soap->tag);
07551     elt->prnt = soap->dom;
07552     elt->elts = NULL;
07553     elt->atts = NULL;
07554     elt->data = NULL;
07555     elt->wide = NULL;
07556     elt->type = 0;
07557     elt->node = NULL;
07558     elt->head = lead;
07559     elt->tail = NULL;
07560     elt->soap = soap;
07561     if (soap->dom)
07562     { struct soap_dom_element *p = soap->dom->elts;
07563       if (p)
07564       { while (p->next)
07565           p = p->next;
07566         p->next = elt;
07567       }
07568       else
07569         soap->dom->elts = elt;
07570     }
07571     soap->dom = elt;
07572     att = &elt->atts;
07573   }
07574 #endif
07575   for (tp = soap->attributes; tp; tp = tp->next)
07576     tp->visible = 0;
07577   while ((int)c != EOF && c != '>' && c != '/')
07578   { s = soap->tmpbuf;
07579     i = sizeof(soap->tmpbuf);
07580     while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
07581     { if (--i > 0)
07582         *s++ = (char)c;
07583       c = soap_get1(soap);
07584     }
07585     *s = '\0';
07586     if (i == sizeof(soap->tmpbuf))
07587       return soap->error = SOAP_SYNTAX_ERROR;
07588 #ifdef WITH_DOM
07589     /* add attribute name to dom */
07590     if (att)
07591     { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
07592        if (!*att)
07593          return soap->error = SOAP_EOM;
07594        (*att)->next = NULL;
07595        (*att)->nstr = NULL;
07596        (*att)->name = soap_strdup(soap, soap->tmpbuf);
07597        (*att)->data = NULL;
07598        (*att)->wide = NULL;
07599        (*att)->soap = soap;
07600     }
07601 #endif
07602     if (!strncmp(soap->tmpbuf, "xmlns", 5))
07603     { if (soap->tmpbuf[5] == ':')
07604       { soap->tmpbuf[5] = '\0';
07605         t = soap->tmpbuf + 6;
07606       }
07607       else if (soap->tmpbuf[5])
07608         t = NULL;
07609       else
07610         t = SOAP_STR_EOS;
07611     }
07612     else
07613       t = NULL;
07614     for (tp = soap->attributes; tp; tp = tp->next)
07615     { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
07616         break;
07617     }
07618     if (!tp)
07619     { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
07620       if (!tp)
07621         return soap->error = SOAP_EOM;
07622       strcpy(tp->name, soap->tmpbuf);
07623       tp->value = NULL;
07624       tp->size = 0;
07625       tp->next = soap->attributes;
07626       soap->attributes = tp;
07627     }
07628     while (soap_blank(c))
07629       c = soap_get1(soap);
07630     if (c == '=')
07631     { do c = soap_getutf8(soap);
07632       while (soap_blank(c));
07633       if (c != SOAP_QT && c != SOAP_AP)
07634       { soap_unget(soap, c);
07635         c = ' '; /* blank delimiter */
07636       }
07637       if (soap_getattrval(soap, tp->value, tp->size, c))
07638       {
07639 #ifdef WITH_FAST
07640         if (soap->error != SOAP_EOM)
07641           return soap->error;
07642         soap->error = SOAP_OK;
07643         if (soap_store_lab(soap, tp->value, tp->size))
07644           return soap->error;
07645         if (tp->value)
07646           SOAP_FREE(soap, tp->value);
07647         for (;;)
07648         { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
07649           { if (soap->error != SOAP_EOM)
07650               return soap->error;
07651             soap->error = SOAP_OK;
07652             soap->labidx = soap->lablen;
07653             if (soap_append_lab(soap, NULL, 0))
07654               return soap->error;
07655           }
07656           else
07657             break;
07658         }
07659         if (soap->labidx)
07660           tp->size = soap->lablen;
07661         else
07662         { tp->size = strlen(soap->labbuf) + 1;
07663           if (tp->size < SOAP_LABLEN)
07664             tp->size = SOAP_LABLEN;
07665         }
07666         if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
07667           return soap->error = SOAP_EOM;
07668         strcpy(tp->value, soap->labbuf);
07669 #else
07670         size_t n;
07671         if (soap->error != SOAP_EOM)
07672           return soap->error;
07673         soap->error = SOAP_OK;
07674         if (soap_new_block(soap))
07675           return soap->error;
07676         for (;;)
07677         { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN)))
07678             return soap->error;
07679           if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
07680           { if (soap->error != SOAP_EOM)
07681               return soap->error;
07682             soap->error = SOAP_OK;
07683           }
07684           else
07685             break;
07686         }
07687         n = tp->size + soap->blist->size;
07688         if (!(s = (char*)SOAP_MALLOC(soap, n)))
07689           return soap->error = SOAP_EOM;
07690         if (tp->value)
07691         { memcpy(s, tp->value, tp->size);
07692           SOAP_FREE(soap, tp->value);
07693         }
07694         soap_save_block(soap, s + tp->size, 0);
07695         tp->value = s;
07696         tp->size = n;
07697 #endif
07698       }
07699       do c = soap_get1(soap);
07700       while (soap_blank(c));
07701       tp->visible = 2; /* seen this attribute w/ value */
07702 #ifdef WITH_DOM
07703       if (att)
07704         (*att)->data = soap_strdup(soap, tp->value);
07705 #endif
07706     }
07707     else
07708       tp->visible = 1; /* seen this attribute w/o value */
07709 #ifdef WITH_DOM
07710     if (att)
07711       att = &(*att)->next;
07712 #endif
07713     if (t && tp->value)
07714     { if (soap_push_namespace(soap, t, tp->value))
07715         return soap->error;
07716       tp->visible = 0;
07717     }
07718   }
07719 #ifdef WITH_DOM
07720   if (att)
07721   { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
07722     for (att = &soap->dom->atts; *att; att = &(*att)->next)
07723       (*att)->nstr = soap_current_namespace(soap, (*att)->name);
07724   }
07725 #endif
07726   if ((int)c == EOF)
07727     return soap->error = SOAP_EOF;
07728   if (!(soap->body = (c != '/')))
07729     do c = soap_get1(soap);
07730     while (soap_blank(c));
07731 #ifdef WITH_DOM
07732   if (soap->mode & SOAP_XML_DOM)
07733   { if (!soap->body && soap->dom->prnt)
07734       soap->dom = soap->dom->prnt;
07735   }
07736 #endif
07737   for (tp = soap->attributes; tp; tp = tp->next)
07738   { if (tp->visible && tp->value)
07739     { if (!strcmp(tp->name, "id"))
07740       { *soap->id = '#';
07741         strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
07742         soap->id[sizeof(soap->id)-1] = '\0';
07743       }
07744       else if (!strcmp(tp->name, "href"))
07745       { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
07746         soap->href[sizeof(soap->href)-1] = '\0';
07747       }
07748       else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref"))
07749       { *soap->href = '#';
07750         strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
07751         soap->href[sizeof(soap->href)-1] = '\0';
07752       }
07753       else if (!soap_match_tag(soap, tp->name, "xsi:type"))
07754       { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
07755         soap->type[sizeof(soap->type)-1] = '\0';
07756       }
07757       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
07758       { s = soap_strrchr(tp->value, '[');
07759         if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
07760         { strncpy(soap->arrayType, tp->value, s - tp->value);
07761           soap->arrayType[s - tp->value] = '\0';
07762           strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
07763         }
07764         else
07765           strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
07766         soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
07767         soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
07768       }
07769       else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
07770         strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
07771       else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
07772         strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
07773       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
07774         strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
07775       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
07776         soap->position = soap_getposition(tp->value, soap->positions);
07777       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
07778         soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
07779       else if ((soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
07780             || (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENV:role")))
07781       { if ((!soap->actor || strcmp(soap->actor, tp->value))
07782          && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")
07783          && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
07784           soap->other = 1;
07785       }
07786       else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
07787             && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
07788         soap->mustUnderstand = 1;
07789       else if ((!soap_match_tag(soap, tp->name, "xsi:null")
07790              || !soap_match_tag(soap, tp->name, "xsi:nil"))
07791             && (!strcmp(tp->value, "1")
07792              || !strcmp(tp->value, "true")))
07793         soap->null = 1;
07794     }
07795   }
07796   return soap->error = SOAP_OK;
07797 }
07798 #endif
07799 
07800 /******************************************************************************/
07801 #ifndef PALM_2
07802 SOAP_FMAC1
07803 void
07804 SOAP_FMAC2
07805 soap_retry(struct soap *soap)
07806 { soap->error = SOAP_OK;
07807   soap_revert(soap);
07808 }
07809 #endif
07810 
07811 /******************************************************************************/
07812 #ifndef PALM_2
07813 SOAP_FMAC1
07814 void
07815 SOAP_FMAC2
07816 soap_revert(struct soap *soap)
07817 { if (!soap->peeked)
07818   { soap->peeked = 1;
07819     if (soap->body)
07820       soap->level--;
07821   }
07822   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
07823 }
07824 #endif
07825 
07826 /******************************************************************************/
07827 #ifndef PALM_2
07828 SOAP_FMAC1
07829 int
07830 SOAP_FMAC2
07831 soap_string_out(struct soap *soap, const char *s, int flag)
07832 { register const char *t;
07833   register soap_wchar c;
07834   register soap_wchar mask = 0xFFFFFF80UL;
07835 #ifdef WITH_DOM
07836   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
07837   { soap->dom->data = soap_strdup(soap, s);
07838     return SOAP_OK;
07839   }
07840 #endif
07841   if (soap->mode & SOAP_C_UTFSTRING)
07842     mask = 0;
07843   t = s;
07844   while ((c = *t++))
07845   { switch (c)
07846     { 
07847     case 9:
07848       if (flag)
07849       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
07850           return soap->error;
07851         s = t;
07852       }
07853       break;
07854     case 10:
07855       if (flag || !(soap->mode & SOAP_XML_CANONICAL))
07856       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
07857           return soap->error;
07858         s = t;
07859       }
07860       break;
07861     case 13:
07862       if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xD;", 5))
07863         return soap->error;
07864       s = t;
07865       break;
07866     case '&':
07867       if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
07868         return soap->error;
07869       s = t;
07870       break;
07871     case '<':
07872       if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
07873         return soap->error;
07874       s = t;
07875       break;
07876     case '>':
07877       if (!flag)
07878       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
07879           return soap->error;
07880         s = t;
07881       }
07882       break;
07883     case '"':
07884       if (flag)
07885       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
07886           return soap->error;
07887         s = t;
07888       }
07889       break;
07890     default:
07891 #ifndef WITH_LEANER
07892 #ifdef HAVE_MBTOWC
07893       if (soap->mode & SOAP_C_MBSTRING)
07894       { wchar_t wc;
07895         register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
07896         if (m > 0 && wc != c)
07897         { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
07898             return soap->error;
07899           s = t += m - 1;
07900           continue;
07901         }
07902       }
07903 #endif
07904 #endif
07905       if (c & mask)
07906       { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
07907           return soap->error;
07908         s = t;
07909       }
07910     }
07911   }
07912   return soap_send_raw(soap, s, t - s - 1);
07913 }
07914 #endif
07915 
07916 /******************************************************************************/
07917 #ifndef PALM_2
07918 SOAP_FMAC1
07919 char *
07920 SOAP_FMAC2
07921 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
07922 { register char *s;
07923   char *t = NULL;
07924   register size_t i;
07925   register long l = 0;
07926   register int n = 0;
07927   register int m = 0;
07928   register soap_wchar c;
07929 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
07930   char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
07931 #else
07932   char buf[8];
07933 #endif
07934   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n"));
07935   if (soap->peeked)
07936   { if (!soap->body)
07937       return NULL;
07938     if (*soap->tag)
07939     { n = 1;
07940       soap->peeked = 0;
07941 #ifndef WITH_LEAN
07942       t = soap->tmpbuf;
07943       t[0] = '<';
07944       strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1);
07945       strncat(t, ">", sizeof(soap->tmpbuf));
07946       m = strlen(soap->tag) + 2;
07947 #endif
07948     }
07949   }
07950 #ifdef WITH_CDATA
07951   if (!flag)
07952   { register int state = 0;
07953 #ifdef WITH_FAST
07954     soap->labidx = 0;                   /* use look-aside buffer */
07955 #else
07956     if (soap_new_block(soap))
07957       return NULL;
07958 #endif
07959     for (;;)
07960     { 
07961 #ifdef WITH_FAST
07962       register size_t k;
07963       if (soap_append_lab(soap, NULL, 0))       /* allocate more space in look-aside buffer if necessary */
07964         return NULL;
07965       s = soap->labbuf + soap->labidx;  /* space to populate */
07966       k = soap->lablen - soap->labidx;  /* number of bytes available */
07967       soap->labidx = soap->lablen;      /* claim this space */
07968 #else
07969       register size_t k = SOAP_BLKLEN;
07970       if (!(s = (char*)soap_push_block(soap, k)))
07971         return NULL;
07972 #endif
07973       for (i = 0; i < k; i++)
07974       { if (m > 0)
07975         { *s++ = *t++;  /* copy multibyte characters */
07976           m--;
07977           continue;
07978         }
07979         c = soap_getchar(soap);
07980         if ((int)c == EOF)
07981           goto end;
07982         if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN))
07983         { soap_unget(soap, c);
07984           c = soap_getutf8(soap);
07985           if (soap->mode & SOAP_C_UTFSTRING)
07986           { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
07987             { c &= 0x7FFFFFFF;
07988               t = buf;
07989               if (c < 0x0800)
07990                 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
07991               else
07992               { if (c < 0x010000)
07993                   *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
07994                 else
07995                 { if (c < 0x200000)
07996                     *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
07997                   else
07998                   { if (c < 0x04000000)
07999                       *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
08000                     else
08001                     { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
08002                       *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
08003                     }
08004                     *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
08005                   }     
08006                   *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
08007                 }
08008                 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
08009               }
08010               *t++ = (char)(0x80 | (c & 0x3F));
08011               m = (int)(t - buf) - 1;
08012               t = buf;
08013               *s++ = *t++;
08014               continue;
08015             }
08016           }
08017         }
08018         switch (state)
08019         { case 1:
08020             if (c == ']')
08021               state = 4;
08022             *s++ = c;
08023             continue;
08024           case 2:
08025             if (c == '-')
08026               state = 6;
08027             *s++ = c;
08028             continue;
08029           case 3:
08030             if (c == '?')
08031               state = 8;
08032             *s++ = c;
08033             continue;
08034           /* CDATA */
08035           case 4:
08036             if (c == ']')
08037               state = 5;
08038             else
08039               state = 1;
08040             *s++ = c;
08041             continue;
08042           case 5:
08043             if (c == '>')
08044               state = 0;
08045             else
08046               state = 1;
08047             *s++ = c;
08048             continue;
08049           /* comment */
08050           case 6:
08051             if (c == '-')
08052               state = 7;
08053             else
08054               state = 2;
08055             *s++ = c;
08056             continue;
08057           case 7:
08058             if (c == '>')
08059               state = 0;
08060             else
08061               state = 2;
08062             *s++ = c;
08063             continue;
08064           /* PI */
08065           case 8:
08066             if (c == '>')
08067               state = 0;
08068             else
08069               state = 3;
08070             *s++ = c;
08071             continue;
08072         }
08073         switch (c)
08074         {
08075         case '/':
08076           if (n > 0)
08077           { c = soap_getchar(soap);
08078             if (c == '>')
08079               n--;
08080             soap_unget(soap, c);
08081           }
08082           *s++ = '/';
08083           break;
08084         case '<':
08085           c = soap_getchar(soap);
08086           if (c == '/')
08087           { if (n == 0)
08088             { c = SOAP_TT;
08089               goto end;
08090             }
08091             n--;
08092           }
08093           else if (c == '!')
08094           { c = soap_getchar(soap);
08095             if (c == '[')
08096             { do c = soap_getchar(soap);
08097               while ((int)c != EOF && c != '[');
08098               if ((int)c == EOF)
08099                  goto end;
08100               t = (char*)"![CDATA[";
08101               m = 8;
08102               state = 1;
08103             }
08104             else if (c == '-')
08105             { if ((c = soap_getchar(soap)) == '-')
08106                 state = 2;
08107               t = (char*)"!-";
08108               m = 2;
08109               soap_unget(soap, c);
08110             }
08111             else
08112             { t = (char*)"!";
08113               m = 1;
08114               soap_unget(soap, c);
08115             }
08116             *s++ = '<';
08117             break;
08118           }
08119           else if (c == '?')
08120             state = 3;
08121           else
08122             n++;
08123           soap_unget(soap, c);
08124           *s++ = '<';
08125           break;
08126         case '>':
08127           *s++ = '>';
08128           break;
08129         case '"':
08130           *s++ = '"';
08131           break;
08132         default:
08133 #ifndef WITH_LEANER
08134 #ifdef HAVE_WCTOMB
08135           if (soap->mode & SOAP_C_MBSTRING)
08136           { m = wctomb(buf, c & 0x7FFFFFFF);
08137             if (m >= 1 && m <= (int)MB_CUR_MAX)
08138             { t = buf;
08139               *s++ = *t++;
08140               m--;
08141             }
08142             else
08143             { *s++ = SOAP_UNKNOWN_CHAR;
08144               m = 0;
08145             }
08146           }
08147           else
08148 #endif
08149 #endif
08150             *s++ = (char)(c & 0xFF);
08151         }
08152         l++;
08153         if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
08154         { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
08155           soap->error = SOAP_LENGTH;
08156           return NULL;
08157         }
08158       }
08159     }
08160   }
08161 #endif
08162 #ifdef WITH_FAST
08163   soap->labidx = 0;                     /* use look-aside buffer */
08164 #else
08165   if (soap_new_block(soap))
08166     return NULL;
08167 #endif
08168   for (;;)
08169   { 
08170 #ifdef WITH_FAST
08171     register size_t k;
08172     if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
08173       return NULL;
08174     s = soap->labbuf + soap->labidx;    /* space to populate */
08175     k = soap->lablen - soap->labidx;    /* number of bytes available */
08176     soap->labidx = soap->lablen;        /* claim this space */
08177 #else
08178     register size_t k = SOAP_BLKLEN;
08179     if (!(s = (char*)soap_push_block(soap, k)))
08180       return NULL;
08181 #endif
08182     for (i = 0; i < k; i++)
08183     { if (m > 0)
08184       { *s++ = *t++;    /* copy multibyte characters */
08185         m--;
08186         continue;
08187       }
08188       if (soap->mode & SOAP_C_UTFSTRING)
08189       { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
08190         { c &= 0x7FFFFFFF;
08191           t = buf;
08192           if (c < 0x0800)
08193             *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
08194           else
08195           { if (c < 0x010000)
08196               *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
08197             else
08198             { if (c < 0x200000)
08199                 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
08200               else
08201               { if (c < 0x04000000)
08202                   *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
08203                 else
08204                 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
08205                   *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
08206                 }
08207                 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
08208               }     
08209               *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
08210             }
08211             *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
08212           }
08213           *t++ = (char)(0x80 | (c & 0x3F));
08214           m = (int)(t - buf) - 1;
08215           t = buf;
08216           *s++ = *t++;
08217           continue;
08218         }
08219       }
08220       else
08221         c = soap_getutf8(soap);
08222       switch (c)
08223       {
08224       case SOAP_TT:
08225         if (n == 0)
08226           goto end;
08227         n--;
08228         *s++ = '<';
08229         t = (char*)"/";
08230         m = 1;
08231         break;
08232       case SOAP_LT:
08233         n++;
08234         *s++ = '<';
08235         break;
08236       case SOAP_GT:
08237         *s++ = '>';
08238         break;
08239       case SOAP_QT:
08240         *s++ = '"';
08241         break;
08242       case SOAP_AP:
08243         *s++ = '\'';
08244         break;
08245       case '/':
08246         if (n > 0)
08247         { c = soap_get(soap);
08248           if (c == SOAP_GT)
08249             n--;
08250           soap_unget(soap, c);
08251         }
08252         *s++ = '/';
08253         break;
08254       case '<' | 0x80000000:
08255         if (flag)
08256           *s++ = '<';
08257         else
08258         { *s++ = '&';
08259           t = (char*)"lt;";
08260           m = 3;
08261         }
08262         break;
08263       case '>' | 0x80000000:
08264         if (flag)
08265           *s++ = '>';
08266         else
08267         { *s++ = '&';
08268           t = (char*)"gt;";
08269           m = 3;
08270         }
08271         break;
08272       case '&' | 0x80000000:
08273         if (flag)
08274           *s++ = '&';
08275         else
08276         { *s++ = '&';
08277           t = (char*)"amp;";
08278           m = 4;
08279         }
08280         break;
08281       case '"' | 0x80000000:
08282         if (flag)
08283           *s++ = '"';
08284         else
08285         { *s++ = '&';
08286           t = (char*)"quot;";
08287           m = 5;
08288         }
08289         break;
08290       case '\'' | 0x80000000:
08291         if (flag)
08292           *s++ = '\'';
08293         else
08294         { *s++ = '&';
08295           t = (char*)"apos;";
08296           m = 5;
08297         }
08298         break;
08299       default:
08300         if ((int)c == EOF)
08301           goto end;
08302 #ifndef WITH_LEANER
08303 #ifdef HAVE_WCTOMB
08304         if (soap->mode & SOAP_C_MBSTRING)
08305         { m = wctomb(buf, c & 0x7FFFFFFF);
08306           if (m >= 1 && m <= (int)MB_CUR_MAX)
08307           { t = buf;
08308             *s++ = *t++;
08309             m--;
08310           }
08311           else
08312           { *s++ = SOAP_UNKNOWN_CHAR;
08313             m = 0;
08314           }
08315         }
08316         else
08317 #endif
08318 #endif
08319           *s++ = (char)(c & 0xFF);
08320       }
08321       l++;
08322       if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
08323       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
08324         soap->error = SOAP_LENGTH;
08325         return NULL;
08326       }
08327     }
08328   }
08329 end:
08330   soap_unget(soap, c);
08331   *s = '\0';
08332 #ifdef WITH_FAST
08333   t = soap_strdup(soap, soap->labbuf);
08334 #else
08335   soap_size_block(soap, i+1);
08336   t = soap_save_block(soap, NULL, 0);
08337 #endif
08338   if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
08339   { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
08340     soap->error = SOAP_LENGTH;
08341     return NULL;
08342   }
08343 #ifdef WITH_DOM
08344   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
08345   { if (flag == 3)
08346       soap->dom->tail = t;
08347     else
08348       soap->dom->data = t;
08349   }
08350 #endif
08351   if (flag == 2)
08352     if (soap_s2QName(soap, t, &t))
08353       return NULL;
08354   return t;
08355 }
08356 #endif
08357 
08358 /******************************************************************************/
08359 #ifndef WITH_LEANER
08360 #ifndef PALM_2
08361 SOAP_FMAC1
08362 int
08363 SOAP_FMAC2
08364 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
08365 { const char *t;
08366   char tmp;
08367   register soap_wchar c;
08368 #ifdef WITH_DOM
08369   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
08370   { wchar_t *r = (wchar_t*)s;
08371     int n = 1;
08372     while (*r++)
08373       n++;
08374     soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
08375     while (n--)
08376       *r++ = *s++;
08377     return SOAP_OK;
08378   }
08379 #endif
08380   while ((c = *s++))
08381   { switch (c)
08382     { 
08383     case 9:
08384       if (flag)
08385         t = "&#x9;";
08386       else
08387         t = "\t";
08388       break;
08389     case 10:
08390       if (flag || !(soap->mode & SOAP_XML_CANONICAL))
08391         t = "&#xA;";
08392       else
08393         t = "\n";
08394       break;
08395     case 13:
08396       t = "&#xD;";
08397       break;
08398     case '&':
08399       t = "&amp;";
08400       break;
08401     case '<':
08402       t = "&lt;";
08403       break;
08404     case '>':
08405       if (flag)
08406         t = ">";
08407       else
08408         t = "&gt;";
08409       break;
08410     case '"':
08411       if (flag)
08412         t = "&quot;";
08413       else
08414         t = "\"";
08415       break;
08416     default:
08417       if (c > 0 && c < 0x80)
08418       { tmp = (char)c;
08419         if (soap_send_raw(soap, &tmp, 1))
08420           return soap->error;
08421       }
08422       else if (soap_pututf8(soap, (unsigned long)c))
08423         return soap->error;
08424       continue;
08425     }
08426     if (soap_send(soap, t))
08427       return soap->error;
08428   }
08429   return SOAP_OK;
08430 }
08431 #endif
08432 #endif
08433 
08434 /******************************************************************************/
08435 #ifndef WITH_LEANER
08436 #ifndef PALM_2
08437 SOAP_FMAC1
08438 wchar_t *
08439 SOAP_FMAC2
08440 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
08441 { wchar_t *s;
08442   register int i, n = 0;
08443   register long l = 0;
08444   register soap_wchar c;
08445   const char *t = NULL;
08446   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
08447   if (soap->peeked)
08448   { if (!soap->body)
08449       return NULL;
08450     if (*soap->tag)
08451     { n = 1;
08452       soap->peeked = 0;
08453     }
08454   }
08455   if (soap_new_block(soap))
08456     return NULL;
08457   for (;;)
08458   { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN)))
08459       return NULL;
08460     for (i = 0; i < SOAP_BLKLEN; i++)
08461     { if (t)
08462       { *s++ = (wchar_t)*t++;
08463         if (!*t)
08464           t = NULL;
08465         continue;
08466       }
08467       c = soap_getutf8(soap);
08468       switch (c)
08469       {
08470       case SOAP_TT:
08471         if (n == 0)
08472           goto end;
08473         n--;
08474         *s++ = '<';
08475         soap_unget(soap, '/');
08476         break;
08477       case SOAP_LT:
08478         n++;
08479         *s++ = '<';
08480         break;
08481       case SOAP_GT:
08482         *s++ = '>';
08483         break;
08484       case SOAP_QT:
08485         *s++ = '"';
08486         break;
08487       case SOAP_AP:
08488         *s++ = '\'';
08489         break;
08490       case '/':
08491         if (n > 0)
08492         { c = soap_getutf8(soap);
08493           if (c == SOAP_GT)
08494             n--;
08495           soap_unget(soap, c);
08496         }
08497         *s++ = '/';
08498         break;
08499       case '<':
08500         if (flag)
08501           *s++ = (soap_wchar)'<';
08502         else
08503         { *s++ = (soap_wchar)'&';
08504           t = "lt;";
08505         }
08506         break;
08507       case '>':
08508         if (flag)
08509           *s++ = (soap_wchar)'>';
08510         else
08511         { *s++ = (soap_wchar)'&';
08512           t = "gt;";
08513         }
08514         break;
08515       case '"':
08516         if (flag)
08517           *s++ = (soap_wchar)'"';
08518         else
08519         { *s++ = (soap_wchar)'&';
08520           t = "quot;";
08521         }
08522         break;
08523       default:
08524         if ((int)c == EOF)
08525           goto end;
08526         *s++ = (wchar_t)c & 0x7FFFFFFF;
08527       }
08528       l++;
08529       if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
08530       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
08531         soap->error = SOAP_LENGTH;
08532         return NULL;
08533       }
08534     }
08535   }
08536 end:
08537   soap_unget(soap, c);
08538   *s = '\0';
08539   soap_size_block(soap, sizeof(wchar_t) * (i + 1));
08540   if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
08541   { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
08542     soap->error = SOAP_LENGTH;
08543     return NULL;
08544   }
08545   s = (wchar_t*)soap_save_block(soap, NULL, 0);
08546 #ifdef WITH_DOM
08547   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
08548     soap->dom->wide = s;
08549 #endif
08550   return s;
08551 }
08552 #endif
08553 #endif
08554 
08555 /******************************************************************************/
08556 #ifndef PALM_2
08557 SOAP_FMAC1
08558 const char*
08559 SOAP_FMAC2
08560 soap_int2s(struct soap *soap, int n)
08561 { return soap_long2s(soap, (long)n);
08562 }
08563 #endif
08564 
08565 /******************************************************************************/
08566 #ifndef PALM_2
08567 SOAP_FMAC1
08568 int
08569 SOAP_FMAC2
08570 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
08571 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
08572    || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
08573     return soap->error;
08574   return soap_element_end_out(soap, tag);
08575 }
08576 #endif
08577 
08578 /******************************************************************************/
08579 #ifndef PALM_2
08580 SOAP_FMAC1
08581 int
08582 SOAP_FMAC2
08583 soap_s2int(struct soap *soap, const char *s, int *p)
08584 { if (s)
08585   { char *r;
08586 #ifndef WITH_NOIO
08587 #ifndef WITH_LEAN
08588     soap_reset_errno;
08589 #endif
08590 #endif
08591     *p = (int)soap_strtol(s, &r, 10);
08592     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
08593 #ifndef WITH_NOIO
08594 #ifndef WITH_LEAN
08595      || soap_errno == SOAP_ERANGE
08596 #endif
08597 #endif
08598     )
08599       soap->error = SOAP_TYPE;
08600   }
08601   return soap->error;
08602 }
08603 #endif
08604 
08605 /******************************************************************************/
08606 #ifndef PALM_2
08607 SOAP_FMAC1
08608 int *
08609 SOAP_FMAC2
08610 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
08611 { if (soap_element_begin_in(soap, tag, 0, NULL))
08612     return NULL;
08613 #ifndef WITH_LEAN
08614   if (*soap->type
08615    && soap_match_tag(soap, soap->type, type)
08616    && soap_match_tag(soap, soap->type, ":int")
08617    && soap_match_tag(soap, soap->type, ":short")
08618    && soap_match_tag(soap, soap->type, ":byte"))
08619   { soap->error = SOAP_TYPE;
08620     soap_revert(soap);
08621     return NULL;
08622   }
08623 #endif
08624   p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
08625   if (*soap->href)
08626     p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
08627   else if (p)
08628   { if (soap_s2int(soap, soap_value(soap), p))
08629       return NULL;
08630   }
08631   if (soap->body && soap_element_end_in(soap, tag))
08632     return NULL;
08633   return p;
08634 }
08635 #endif
08636 
08637 /******************************************************************************/
08638 #ifndef PALM_2
08639 SOAP_FMAC1
08640 const char*
08641 SOAP_FMAC2
08642 soap_long2s(struct soap *soap, long n)
08643 { sprintf(soap->tmpbuf, "%ld", n);
08644   return soap->tmpbuf;
08645 }
08646 #endif
08647 
08648 /******************************************************************************/
08649 #ifndef PALM_2
08650 SOAP_FMAC1
08651 int
08652 SOAP_FMAC2
08653 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
08654 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
08655    || soap_string_out(soap, soap_long2s(soap, *p), 0))
08656     return soap->error;
08657   return soap_element_end_out(soap, tag);
08658 }
08659 #endif
08660 
08661 /******************************************************************************/
08662 #ifndef PALM_2
08663 SOAP_FMAC1
08664 int
08665 SOAP_FMAC2
08666 soap_s2long(struct soap *soap, const char *s, long *p)
08667 { if (s)
08668   { char *r;
08669 #ifndef WITH_NOIO
08670 #ifndef WITH_LEAN
08671     soap_reset_errno;
08672 #endif
08673 #endif
08674     *p = soap_strtol(s, &r, 10);
08675     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
08676 #ifndef WITH_NOIO
08677 #ifndef WITH_LEAN
08678      || soap_errno == SOAP_ERANGE
08679 #endif
08680 #endif
08681     )
08682       soap->error = SOAP_TYPE;
08683   }
08684   return soap->error;
08685 }
08686 #endif
08687 
08688 /******************************************************************************/
08689 #ifndef PALM_2
08690 SOAP_FMAC1
08691 long *
08692 SOAP_FMAC2
08693 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
08694 { if (soap_element_begin_in(soap, tag, 0, NULL))
08695     return NULL;
08696 #ifndef WITH_LEAN
08697   if (*soap->type
08698    && soap_match_tag(soap, soap->type, type)
08699    && soap_match_tag(soap, soap->type, ":int")
08700    && soap_match_tag(soap, soap->type, ":short")
08701    && soap_match_tag(soap, soap->type, ":byte"))
08702   { soap->error = SOAP_TYPE;
08703     soap_revert(soap);
08704     return NULL;
08705   }
08706 #endif
08707   p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
08708   if (*soap->href)
08709     p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
08710   else if (p)
08711   { if (soap_s2long(soap, soap_value(soap), p))
08712       return NULL;
08713   }
08714   if (soap->body && soap_element_end_in(soap, tag))
08715     return NULL;
08716   return p;
08717 }
08718 #endif
08719 
08720 /******************************************************************************/
08721 #ifndef WITH_LEAN
08722 SOAP_FMAC1
08723 const char*
08724 SOAP_FMAC2
08725 soap_LONG642s(struct soap *soap, LONG64 n)
08726 { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
08727   return soap->tmpbuf;
08728 }
08729 #endif
08730 
08731 /******************************************************************************/
08732 #ifndef WITH_LEAN
08733 SOAP_FMAC1
08734 int
08735 SOAP_FMAC2
08736 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
08737 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
08738    || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
08739     return soap->error;
08740   return soap_element_end_out(soap, tag);
08741 }
08742 #endif
08743 
08744 /******************************************************************************/
08745 #ifndef WITH_LEAN
08746 SOAP_FMAC1
08747 int
08748 SOAP_FMAC2
08749 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
08750 { if (s)
08751   {
08752 #ifdef HAVE_STRTOLL
08753     char *r;
08754 #ifndef WITH_NOIO
08755 #ifndef WITH_LEAN
08756     soap_reset_errno;
08757 #endif
08758 #endif
08759     *p = strtoll(s, &r, 10);
08760     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
08761 #ifndef WITH_NOIO
08762 #ifndef WITH_LEAN
08763        || soap_errno == SOAP_ERANGE
08764 #endif
08765 #endif
08766       )
08767 #else
08768 # ifdef HAVE_SSCANF
08769     if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
08770 # endif
08771 #endif
08772       soap->error = SOAP_TYPE;
08773   }
08774   return soap->error;
08775 }
08776 #endif
08777 
08778 /******************************************************************************/
08779 #ifndef WITH_LEAN
08780 SOAP_FMAC1
08781 LONG64 *
08782 SOAP_FMAC2
08783 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
08784 { if (soap_element_begin_in(soap, tag, 0, NULL))
08785     return NULL;
08786 #ifndef WITH_LEAN
08787   if (*soap->type
08788    && soap_match_tag(soap, soap->type, type)
08789    && soap_match_tag(soap, soap->type, ":integer")
08790    && soap_match_tag(soap, soap->type, ":positiveInteger")
08791    && soap_match_tag(soap, soap->type, ":negativeInteger")
08792    && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
08793    && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
08794    && soap_match_tag(soap, soap->type, ":long")
08795    && soap_match_tag(soap, soap->type, ":int")
08796    && soap_match_tag(soap, soap->type, ":short")
08797    && soap_match_tag(soap, soap->type, ":byte"))
08798   { soap->error = SOAP_TYPE;
08799     soap_revert(soap);
08800     return NULL;
08801   }
08802 #endif
08803   p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
08804   if (*soap->href)
08805     p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
08806   else if (p)
08807   { if (soap_s2LONG64(soap, soap_value(soap), p))
08808       return NULL;
08809   }
08810   if (soap->body && soap_element_end_in(soap, tag))
08811     return NULL;
08812   return p;
08813 }
08814 #endif
08815 
08816 /******************************************************************************/
08817 #ifndef PALM_2
08818 SOAP_FMAC1
08819 const char*
08820 SOAP_FMAC2
08821 soap_byte2s(struct soap *soap, char n)
08822 { return soap_long2s(soap, (long)n);
08823 }
08824 #endif
08825 
08826 /******************************************************************************/
08827 #ifndef PALM_2
08828 SOAP_FMAC1
08829 int
08830 SOAP_FMAC2
08831 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
08832 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
08833    || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
08834     return soap->error;
08835   return soap_element_end_out(soap, tag);
08836 }
08837 #endif
08838 
08839 /******************************************************************************/
08840 #ifndef PALM_2
08841 SOAP_FMAC1
08842 int
08843 SOAP_FMAC2
08844 soap_s2byte(struct soap *soap, const char *s, char *p)
08845 { if (s)
08846   { long n;
08847     char *r;
08848     n = soap_strtol(s, &r, 10);
08849     if (s == r || *r || n < -128 || n > 127)
08850       soap->error = SOAP_TYPE;
08851     *p = (char)n;
08852   }
08853   return soap->error;
08854 }
08855 #endif
08856 
08857 /******************************************************************************/
08858 #ifndef PALM_2
08859 SOAP_FMAC1
08860 char *
08861 SOAP_FMAC2
08862 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
08863 { if (soap_element_begin_in(soap, tag, 0, NULL))
08864