move pcucontrol package into pcucontrol module.
[pcucontrol.git] / pcucontrol / models / intelamt / stdsoap2.cpp
1 /*
2
3 stdsoap2.c[pp] 2.7.8c
4
5 gSOAP runtime
6
7 gSOAP XML Web services tools
8 Copyright (C) 2000-2006, Robert van Engelen, Genivia Inc., All Rights Reserved.
9 This part of the software is released under one of the following licenses:
10 GPL, the gSOAP public license, or Genivia's license for commercial use.
11 --------------------------------------------------------------------------------
12 Contributors:
13
14 Wind River Systems Inc., for the following additions under gSOAP public license:
15   - vxWorks compatible  (#define VXWORKS)
16 --------------------------------------------------------------------------------
17 gSOAP public license.
18
19 The contents of this file are subject to the gSOAP Public License Version 1.3
20 (the "License"); you may not use this file except in compliance with the
21 License. You may obtain a copy of the License at
22 http://www.cs.fsu.edu/~engelen/soaplicense.html
23 Software distributed under the License is distributed on an "AS IS" basis,
24 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
25 for the specific language governing rights and limitations under the License.
26
27 The Initial Developer of the Original Code is Robert A. van Engelen.
28 Copyright (C) 2000-2006, Robert van Engelen, Genivia Inc., All Rights Reserved.
29 --------------------------------------------------------------------------------
30 GPL license.
31
32 This program is free software; you can redistribute it and/or modify it under
33 the terms of the GNU General Public License as published by the Free Software
34 Foundation; either version 2 of the License, or (at your option) any later
35 version.
36
37 This program is distributed in the hope that it will be useful, but WITHOUT ANY
38 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
39 PARTICULAR PURPOSE. See the GNU General Public License for more details.
40
41 You should have received a copy of the GNU General Public License along with
42 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
43 Place, Suite 330, Boston, MA 02111-1307 USA
44
45 Author contact information:
46 engelen@genivia.com / engelen@acm.org
47 --------------------------------------------------------------------------------
48 A commercial use license is available from Genivia, Inc., contact@genivia.com
49 --------------------------------------------------------------------------------
50
51 Installation note:
52
53 Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
54 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
55 tab (the project file needs to be selected in the file view) and add
56 "wsock32.lib" to the "Object/library modules" entry
57
58 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
59 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
60 when locally allocated data exceeds 64K.
61
62 */
63
64 #ifdef AS400
65 # pragma convert(819)   /* EBCDIC to ASCII */
66 #endif
67
68 #include "stdsoap2.h"
69
70 #ifdef __cplusplus
71 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.8c 2006-06-24 12:00:00 GMT")
72 extern "C" {
73 #else
74 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.8c 2006-06-24 12:00:00 GMT")
75 #endif
76
77 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
78 #ifndef SOAP_UNKNOWN_CHAR
79 #define SOAP_UNKNOWN_CHAR (127)
80 #endif
81
82 /*      EOF=-1 */
83 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
84 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
85 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
86 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
87 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
88
89 #define soap_blank(c)           ((c) >= 0 && (c) <= 32)
90 #define soap_notblank(c)        ((c) > 32)
91 #define soap_hash_ptr(p)        (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1))
92
93 #ifdef SOAP_DEBUG
94 static void soap_init_logs(struct soap*);
95 static void soap_close_logfile(struct soap*, int);
96 static void soap_set_logfile(struct soap*, int, const char*);
97 static void soap_free_mht(struct soap*);
98 static void soap_track_unlink(struct soap*, const void*);
99 #endif
100
101 #ifndef PALM_2
102 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
103 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
104 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
105 #endif
106
107 #ifndef PALM_1
108 static soap_wchar soap_char(struct soap*);
109 static soap_wchar soap_get_pi(struct soap*);
110 static int soap_isxdigit(int);
111 static void *fplugin(struct soap*, const char*);
112 #ifndef WITH_NOIDREF
113 static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
114 static int soap_has_copies(struct soap*, const char*, const char*);
115 static void soap_init_iht(struct soap*);
116 static void soap_free_iht(struct soap*);
117 static void soap_init_pht(struct soap*);
118 static void soap_free_pht(struct soap*);
119 #endif
120 #endif
121
122 #ifndef WITH_LEAN
123 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
124 static int soap_isnumeric(struct soap*, const char*);
125 static time_t soap_timegm(struct tm*);
126 static struct soap_nlist *soap_lookup_ns(struct soap *soap, const char *tag, size_t n);
127 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
128 static void soap_pop_ns(struct soap *soap);
129 static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
130 #endif
131
132 #ifndef WITH_LEANER
133 #ifndef PALM_1
134 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
135 static int soap_putdimefield(struct soap*, const char*, size_t);
136 static char *soap_getdimefield(struct soap*, size_t);
137 static void soap_select_mime_boundary(struct soap*);
138 static int soap_valid_mime_boundary(struct soap*);
139 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
140 #endif
141 #endif
142
143 #ifdef WITH_GZIP
144 static int soap_getgziphdr(struct soap*);
145 #endif
146
147 #ifdef WITH_OPENSSL
148 static int ssl_init_done = 0;
149 static int ssl_auth_init(struct soap*);
150 static int ssl_verify_callback(int, X509_STORE_CTX*);
151 static int ssl_password(char*, int, int, void *);
152 /* This callback is included for future references. It should not be deleted
153 static DH *ssl_tmp_dh(SSL*, int, int);
154 */
155 #endif
156
157 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
158 #ifndef PALM_1
159 static const char *soap_decode(char*, size_t, const char*, const char*);
160 #endif
161 #endif
162
163 #ifndef WITH_NOHTTP
164 #ifndef PALM_1
165 static soap_wchar soap_getchunkchar(struct soap*);
166 static const char *http_error(struct soap*, int);
167 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
168 static int http_get(struct soap*);
169 static int http_send_header(struct soap*, const char*);
170 static int http_post_header(struct soap*, const char*, const char*);
171 static int http_response(struct soap*, int, size_t);
172 static int http_parse(struct soap*);
173 static int http_parse_header(struct soap*, const char*, const char*);
174 #endif
175 #endif
176
177 #ifndef WITH_NOIO
178 #ifndef PALM_1
179 static int fsend(struct soap*, const char*, size_t);
180 static size_t frecv(struct soap*, char*, size_t);
181 static int tcp_init(struct soap*);
182 static const char *tcp_error(struct soap*);
183 #ifndef WITH_IPV6
184 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
185 #endif
186 static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
187 static int tcp_accept(struct soap*, int, struct sockaddr*, int*);
188 static int tcp_disconnect(struct soap*);
189 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
190 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
191 static const char *soap_strerror(struct soap*);
192 #endif
193 #endif
194
195 #if defined(PALM) && !defined(PALM_2)
196 unsigned short errno;
197 #endif
198
199 #ifndef PALM_1
200 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
201 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
202 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
203 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
204 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
205 #endif
206
207 #ifndef PALM_1
208 const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
209 static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
210 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";
211 #endif
212
213 #ifndef WITH_LEAN
214 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
215 /* Alternative indentation form for SOAP_XML_INDENT:
216 static const char soap_indent[21] = "\n                   ";
217 */
218 #endif
219
220 #ifndef SOAP_CANARY
221 # define SOAP_CANARY (0xC0DE)
222 #endif
223
224 static const char soap_padding[4] = "\0\0\0";
225 #define SOAP_STR_PADDING (soap_padding)
226 #define SOAP_STR_EOS (soap_padding)
227 #define SOAP_NON_NULL (soap_padding)
228
229 #ifndef WITH_LEAN
230 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
231 { { 160, "nbsp" },
232   { 161, "iexcl" },
233   { 162, "cent" },
234   { 163, "pound" },
235   { 164, "curren" },
236   { 165, "yen" },
237   { 166, "brvbar" },
238   { 167, "sect" },
239   { 168, "uml" },
240   { 169, "copy" },
241   { 170, "ordf" },
242   { 171, "laquo" },
243   { 172, "not" },
244   { 173, "shy" },
245   { 174, "reg" },
246   { 175, "macr" },
247   { 176, "deg" },
248   { 177, "plusmn" },
249   { 178, "sup2" },
250   { 179, "sup3" },
251   { 180, "acute" },
252   { 181, "micro" },
253   { 182, "para" },
254   { 183, "middot" },
255   { 184, "cedil" },
256   { 185, "sup1" },
257   { 186, "ordm" },
258   { 187, "raquo" },
259   { 188, "frac14" },
260   { 189, "frac12" },
261   { 190, "frac34" },
262   { 191, "iquest" },
263   { 192, "Agrave" },
264   { 193, "Aacute" },
265   { 194, "Acirc" },
266   { 195, "Atilde" },
267   { 196, "Auml" },
268   { 197, "Aring" },
269   { 198, "AElig" },
270   { 199, "Ccedil" },
271   { 200, "Egrave" },
272   { 201, "Eacute" },
273   { 202, "Ecirc" },
274   { 203, "Euml" },
275   { 204, "Igrave" },
276   { 205, "Iacute" },
277   { 206, "Icirc" },
278   { 207, "Iuml" },
279   { 208, "ETH" },
280   { 209, "Ntilde" },
281   { 210, "Ograve" },
282   { 211, "Oacute" },
283   { 212, "Ocirc" },
284   { 213, "Otilde" },
285   { 214, "Ouml" },
286   { 215, "times" },
287   { 216, "Oslash" },
288   { 217, "Ugrave" },
289   { 218, "Uacute" },
290   { 219, "Ucirc" },
291   { 220, "Uuml" },
292   { 221, "Yacute" },
293   { 222, "THORN" },
294   { 223, "szlig" },
295   { 224, "agrave" },
296   { 225, "aacute" },
297   { 226, "acirc" },
298   { 227, "atilde" },
299   { 228, "auml" },
300   { 229, "aring" },
301   { 230, "aelig" },
302   { 231, "ccedil" },
303   { 232, "egrave" },
304   { 233, "eacute" },
305   { 234, "ecirc" },
306   { 235, "euml" },
307   { 236, "igrave" },
308   { 237, "iacute" },
309   { 238, "icirc" },
310   { 239, "iuml" },
311   { 240, "eth" },
312   { 241, "ntilde" },
313   { 242, "ograve" },
314   { 243, "oacute" },
315   { 244, "ocirc" },
316   { 245, "otilde" },
317   { 246, "ouml" },
318   { 247, "divide" },
319   { 248, "oslash" },
320   { 249, "ugrave" },
321   { 250, "uacute" },
322   { 251, "ucirc" },
323   { 252, "uuml" },
324   { 253, "yacute" },
325   { 254, "thorn" },
326   { 255, "yuml" },
327   {   0, NULL }
328 };
329 #endif
330
331 #ifndef WITH_NOIO
332 #ifndef WITH_LEAN
333 static const struct soap_code_map h_error_codes[] =
334 {
335 #ifdef HOST_NOT_FOUND   
336   { HOST_NOT_FOUND, "Host not found" },
337 #endif
338 #ifdef TRY_AGAIN
339   { TRY_AGAIN, "Try Again" },
340 #endif
341 #ifdef NO_RECOVERY  
342   { NO_RECOVERY, "No Recovery" },
343 #endif
344 #ifdef NO_DATA
345   { NO_DATA, "No Data" },
346 #endif
347 #ifdef NO_ADDRESS
348   { NO_ADDRESS, "No Address" },
349 #endif
350   { 0, NULL }
351 };
352 #endif
353 #endif
354
355 #ifndef WITH_NOHTTP
356 #ifndef WITH_LEAN
357 static const struct soap_code_map h_http_error_codes[] =
358 { { 200, "OK" },
359   { 201, "Created" },
360   { 202, "Accepted" },
361   { 203, "Non-Authoritative Information" },
362   { 204, "No Content" },
363   { 205, "Reset Content" },
364   { 206, "Partial Content" },
365   { 300, "Multiple Choices" },
366   { 301, "Moved Permanently" },
367   { 302, "Found" },
368   { 303, "See Other" },
369   { 304, "Not Modified" },
370   { 305, "Use Proxy" },
371   { 307, "Temporary Redirect" },
372   { 400, "Bad Request" },
373   { 401, "Unauthorized" },
374   { 402, "Payment Required" },
375   { 403, "Forbidden" },
376   { 404, "Not Found" },
377   { 405, "Method Not Allowed" },
378   { 406, "Not Acceptable" },
379   { 407, "Proxy Authentication Required" },
380   { 408, "Request Time-out" },
381   { 409, "Conflict" },
382   { 410, "Gone" },
383   { 411, "Length Required" },
384   { 412, "Precondition Failed" },
385   { 413, "Request Entity Too Large" },
386   { 414, "Request-URI Too Large" },
387   { 415, "Unsupported Media Type" },
388   { 416, "Requested range not satisfiable" },
389   { 417, "Expectation Failed" },
390   { 500, "Internal Server Error" },
391   { 501, "Not Implemented" },
392   { 502, "Bad Gateway" },
393   { 503, "Service Unavailable" },
394   { 504, "Gateway Time-out" },
395   { 505, "HTTP Version not supported" },
396   {   0, NULL }
397 };
398 #endif
399 #endif
400
401 #ifdef WITH_OPENSSL
402 static const struct soap_code_map h_ssl_error_codes[] =
403 {
404 #define _SSL_ERROR(e) { e, #e }
405   _SSL_ERROR(SSL_ERROR_SSL),
406   _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
407   _SSL_ERROR(SSL_ERROR_WANT_READ),
408   _SSL_ERROR(SSL_ERROR_WANT_WRITE),
409   _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
410   _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
411   _SSL_ERROR(SSL_ERROR_SYSCALL),
412   { 0, NULL }
413 };
414 #endif
415
416 #ifndef WITH_LEANER
417 static const struct soap_code_map mime_codes[] =
418 { { SOAP_MIME_7BIT,             "7bit" },
419   { SOAP_MIME_8BIT,             "8bit" },
420   { SOAP_MIME_BINARY,           "binary" },
421   { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
422   { SOAP_MIME_BASE64,           "base64" },
423   { SOAP_MIME_IETF_TOKEN,       "ietf-token" },
424   { SOAP_MIME_X_TOKEN,          "x-token" },
425   { 0,                          NULL }
426 };
427 #endif
428
429 #ifdef WIN32
430 static int tcp_done = 0;
431 #endif
432
433 /******************************************************************************/
434 #ifndef WITH_NOIO
435 #ifndef PALM_1
436 static int
437 fsend(struct soap *soap, const char *s, size_t n)
438 { register int nwritten;
439 #if defined(__cplusplus) && !defined(WITH_LEAN)
440   if (soap->os)
441   { soap->os->write(s, n);
442     if (soap->os->good())
443       return SOAP_OK;
444     return SOAP_EOF;
445   }
446 #endif
447   while (n)
448   { if (soap_valid_socket(soap->socket))
449     { 
450 #ifndef WITH_LEAN
451       if (soap->send_timeout)
452       { struct timeval timeout;
453         fd_set fd;
454         if (soap->send_timeout > 0)
455         { timeout.tv_sec = soap->send_timeout;
456           timeout.tv_usec = 0;
457         }
458         else
459         { timeout.tv_sec = -soap->send_timeout/1000000;
460           timeout.tv_usec = -soap->send_timeout%1000000;
461         }
462 #ifndef WIN32
463         if ((int)soap->socket > FD_SETSIZE)
464           return SOAP_FD_EXCEEDED;      /* Hint: MUST increase FD_SETSIZE */
465 #endif
466         FD_ZERO(&fd);
467         FD_SET((SOAP_SOCKET)soap->socket, &fd);
468         for (;;)
469         { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout);
470           if (r > 0)
471             break;
472           if (!r)
473           { soap->errnum = 0;
474             return SOAP_EOF;
475           }
476           if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
477           { soap->errnum = soap_socket_errno;
478             return SOAP_EOF;
479           }
480         }
481       }
482 #endif
483 #ifdef WITH_OPENSSL
484       if (soap->ssl)
485         nwritten = SSL_write(soap->ssl, s, n);
486       else if (soap->bio)
487         nwritten = BIO_write(soap->bio, s, n);
488       else
489 #endif
490 #ifdef WITH_UDP
491       if ((soap->omode & SOAP_IO_UDP))
492       { if (soap->peerlen)
493           nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
494         else
495           nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
496         /* retry and back-off algorithm */
497         /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
498         if (nwritten < 0)
499         { struct timeval timeout;
500           fd_set fd;
501           int udp_repeat;
502           int udp_delay;
503 #ifndef WIN32
504           if ((int)soap->socket > FD_SETSIZE)
505             return SOAP_FD_EXCEEDED;    /* Hint: MUST increase FD_SETSIZE */
506 #endif
507           if ((soap->connect_flags & SO_BROADCAST))
508             udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
509           else
510             udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
511           udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
512           do
513           { timeout.tv_sec = 0;
514             timeout.tv_usec = 1000 * udp_delay; /* ms */
515             FD_ZERO(&fd);
516             FD_SET((SOAP_SOCKET)soap->socket, &fd);
517             select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout);
518             if (soap->peerlen)
519               nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
520             else
521               nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
522             udp_delay <<= 1;
523             if (udp_delay > 500) /* UDP_UPPER_DELAY */
524               udp_delay = 500;
525           }
526           while (nwritten < 0 && --udp_repeat > 0);
527         }
528       }
529       else
530 #endif
531 #if !defined(PALM) && !defined(AS400)
532         nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
533 #else
534         nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags);
535 #endif
536       if (nwritten <= 0)
537       {
538 #ifdef WITH_OPENSSL
539         int err;
540         if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
541           return SOAP_EOF;
542 #endif
543         if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN)
544         { soap->errnum = soap_socket_errno;
545           return SOAP_EOF;
546         }
547         nwritten = 0; /* and call write() again */
548       }
549     }
550     else
551     {
552 #ifdef WITH_FASTCGI
553       nwritten = fwrite((void*)s, 1, n, stdout);
554       fflush(stdout);
555 #else
556 #ifdef UNDER_CE
557       nwritten = fwrite(s, 1, n, soap->sendfd);
558 #else
559 #ifdef VXWORKS
560 #ifdef WMW_RPM_IO
561       if (soap->rpmreqid)
562         nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; 
563       else
564 #endif
565         nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
566 #else
567       nwritten = write((SOAP_SOCKET)soap->sendfd, s, n);
568 #endif
569 #endif
570 #endif
571       if (nwritten <= 0)
572       { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN)
573         { soap->errnum = soap_errno;
574           return SOAP_EOF;
575         }
576         nwritten = 0; /* and call write() again */
577       }
578     }
579     n -= nwritten;
580     s += nwritten;
581   }
582   return SOAP_OK;
583 }
584 #endif
585 #endif
586
587 /******************************************************************************/
588 #ifndef PALM_1
589 SOAP_FMAC1
590 int
591 SOAP_FMAC2
592 soap_send_raw(struct soap *soap, const char *s, size_t n)
593 { if (!n)
594     return SOAP_OK;
595   if (soap->mode & SOAP_IO_LENGTH)
596   { soap->count += n;
597 #ifndef WITH_LEANER
598     if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
599       return soap->error = soap->fpreparesend(soap, s, n);
600 #endif
601     return SOAP_OK;
602   }
603   if (soap->mode & SOAP_IO)
604   { register size_t i = SOAP_BUFLEN - soap->bufidx;
605     while (n >= i)
606     { memcpy(soap->buf + soap->bufidx, s, i);
607       soap->bufidx = SOAP_BUFLEN;
608       if (soap_flush(soap))
609         return soap->error;
610       s += i;
611       n -= i;
612       i = SOAP_BUFLEN;
613     }
614     memcpy(soap->buf + soap->bufidx, s, n);
615     soap->bufidx += n;
616     return SOAP_OK;
617   }
618   return soap_flush_raw(soap, s, n);
619 }
620 #endif
621
622 /******************************************************************************/
623 #ifndef PALM_1
624 SOAP_FMAC1
625 int
626 SOAP_FMAC2
627 soap_flush(struct soap *soap)
628 { register int n = soap->bufidx;
629   if (n)
630   { soap->bufidx = 0;
631 #ifdef WITH_ZLIB
632     if (soap->mode & SOAP_ENC_ZLIB)
633     { soap->d_stream.next_in = (Byte*)soap->buf;
634       soap->d_stream.avail_in = (unsigned int)n;
635 #ifdef WITH_GZIP
636       soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
637 #endif
638       do
639       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in));
640         if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK)
641         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
642           return soap->error = SOAP_ZLIB_ERROR;
643         }
644         if (!soap->d_stream.avail_out)
645         { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
646             return soap->error;
647           soap->d_stream.next_out = (Byte*)soap->z_buf;
648           soap->d_stream.avail_out = SOAP_BUFLEN;
649         }
650       } while (soap->d_stream.avail_in);
651     }
652     else
653 #endif
654       return soap_flush_raw(soap, soap->buf, n);
655   }
656   return SOAP_OK;
657 }
658 #endif
659
660 /******************************************************************************/
661 #ifndef PALM_1
662 SOAP_FMAC1
663 int
664 SOAP_FMAC2
665 soap_flush_raw(struct soap *soap, const char *s, size_t n)
666 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
667   { register char *t;
668     if (!(t = (char*)soap_push_block(soap, n)))
669       return soap->error = SOAP_EOM;
670     memcpy(t, s, n);
671 #ifndef WITH_LEANER
672     if (soap->fpreparesend)
673       return soap->error = soap->fpreparesend(soap, s, n);
674 #endif
675     return SOAP_OK;
676   }
677 #ifndef WITH_LEANER
678   if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
679   { char t[16];
680     sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
681     DBGMSG(SENT, t, strlen(t));
682     if ((soap->error = soap->fsend(soap, t, strlen(t))))
683       return soap->error;
684     soap->chunksize += n;
685   }
686   DBGMSG(SENT, s, n);
687 #endif
688   return soap->error = soap->fsend(soap, s, n);
689 }
690 #endif
691
692 /******************************************************************************/
693 #ifndef PALM_1
694 SOAP_FMAC1
695 int
696 SOAP_FMAC2
697 soap_send(struct soap *soap, const char *s)
698 { if (s)
699     return soap_send_raw(soap, s, strlen(s));
700   return SOAP_OK;
701 }
702 #endif
703
704 /******************************************************************************/
705 #ifndef WITH_LEANER
706 #ifndef PALM_1
707 SOAP_FMAC1
708 int
709 SOAP_FMAC2
710 soap_send2(struct soap *soap, const char *s1, const char *s2)
711 { if (soap_send(soap, s1))
712     return soap->error;
713   return soap_send(soap, s2);
714 }
715 #endif
716 #endif
717
718 /******************************************************************************/
719 #ifndef WITH_LEANER
720 #ifndef PALM_1
721 SOAP_FMAC1
722 int
723 SOAP_FMAC2
724 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
725 { if (soap_send(soap, s1)
726    || soap_send(soap, s2))
727     return soap->error;
728   return soap_send(soap, s3);
729 }
730 #endif
731 #endif
732
733 /******************************************************************************/
734 #ifndef WITH_NOIO
735 #ifndef PALM_1
736 static size_t
737 frecv(struct soap *soap, char *s, size_t n)
738 { register int r;
739 #ifdef PALM
740   register int timeouts = 0;  
741 #endif
742   soap->errnum = 0;
743 #if defined(__cplusplus) && !defined(WITH_LEAN)
744   if (soap->is)
745   { if (soap->is->good())
746       return soap->is->read(s, n).gcount();
747     return 0;
748   }
749 #endif
750   if (soap_valid_socket(soap->socket))
751   { for (;;)
752     { 
753 #ifndef WITH_LEAN
754       if (soap->recv_timeout)
755       { struct timeval timeout;
756         fd_set fd;
757         if (soap->recv_timeout > 0)
758         { timeout.tv_sec = soap->recv_timeout;
759           timeout.tv_usec = 0;
760         }
761         else
762         { timeout.tv_sec = -soap->recv_timeout/1000000;
763           timeout.tv_usec = -soap->recv_timeout%1000000;
764         }
765 #ifndef WIN32
766         if ((int)soap->socket > FD_SETSIZE)
767         { soap->error = SOAP_FD_EXCEEDED;
768           return 0;     /* Hint: MUST increase FD_SETSIZE */
769         }
770 #endif
771         FD_ZERO(&fd);
772         FD_SET((SOAP_SOCKET)soap->socket, &fd);
773         for (;;)
774         { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
775           if (r > 0)
776             break;
777           if (!r)
778           { soap->errnum = 0;
779             return 0;
780           }
781           if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
782           { soap->errnum = soap_socket_errno;
783             return 0;
784           }
785         }
786       }
787 #endif
788 #ifdef WITH_OPENSSL
789       if (soap->ssl)
790       { int err;
791         r = SSL_read(soap->ssl, s, n);
792         if (r > 0)
793           return (size_t)r;
794         err = SSL_get_error(soap->ssl, r);
795         if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
796           return 0;
797       }
798       else if (soap->bio)
799       { r = BIO_read(soap->bio, s, n);
800         if (r > 0)
801           return (size_t)r;
802         return 0;
803       }
804       else
805 #endif
806       { 
807 #ifdef WITH_UDP
808         if ((soap->omode & SOAP_IO_UDP))
809         { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
810           memset((void*)&soap->peer, 0, sizeof(soap->peer));
811           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 */
812           soap->peerlen = (size_t)k;
813 #ifndef WITH_IPV6
814           soap->ip = ntohl(soap->peer.sin_addr.s_addr);
815 #endif
816         }
817         else
818 #endif
819           r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
820 #ifdef PALM
821         /* CycleSyncDisplay(curStatusMsg); */
822 #endif
823         if (r >= 0)
824           return (size_t)r;
825         if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN && soap_socket_errno != SOAP_EWOULDBLOCK)
826         { soap->errnum = soap_socket_errno;
827           return 0;
828         }
829       }
830 #ifndef WITH_LEAN
831       { struct timeval timeout;
832         fd_set fd;
833         timeout.tv_sec = 0;
834         timeout.tv_usec = 10000;
835 #ifndef WIN32
836         if ((int)soap->socket > FD_SETSIZE)
837         { soap->error = SOAP_FD_EXCEEDED;
838           return 0;     /* Hint: MUST increase FD_SETSIZE */
839         }
840 #endif
841         FD_ZERO(&fd);
842         FD_SET((SOAP_SOCKET)soap->socket, &fd);
843 #ifdef WITH_OPENSSL
844         if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE)
845           r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout);
846         else
847           r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
848 #else
849         r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
850 #endif
851         if (r < 0 && soap_socket_errno != SOAP_EINTR)
852         { soap->errnum = soap_socket_errno;
853           return 0;
854         }
855       }
856 #endif
857 #ifdef PALM
858       if (r < 0 && soap_socket_errno == SOAP_EINTR)
859       { timeouts++;
860         if (timeouts > 10)
861         { soap->errnum = soap_socket_errno;
862           return 0;
863         }
864       }
865 #endif
866     }
867   }
868 #ifdef WITH_FASTCGI
869   return fread(s, 1, n, stdin);
870 #else
871 #ifdef UNDER_CE
872   return fread(s, 1, n, soap->recvfd);
873 #else
874 #ifdef WMW_RPM_IO
875   if (soap->rpmreqid)
876     r = httpBlockRead(soap->rpmreqid, s, n);
877   else
878 #endif
879   r = read((SOAP_SOCKET)soap->recvfd, s, n);
880   if (r >= 0)
881     return (size_t)r;
882   soap->errnum = soap_errno;
883   return 0;
884 #endif
885 #endif
886 }
887 #endif
888 #endif
889
890 /******************************************************************************/
891 #ifndef WITH_NOHTTP
892 #ifndef PALM_1
893 static soap_wchar
894 soap_getchunkchar(struct soap *soap)
895 { if (soap->bufidx < soap->buflen)
896     return soap->buf[soap->bufidx++];
897   soap->bufidx = 0;
898   soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
899   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket));
900   DBGMSG(RECV, soap->buf, soap->buflen);
901   if (soap->buflen)
902     return soap->buf[soap->bufidx++];
903   return EOF;
904 }
905 #endif
906 #endif
907
908 /******************************************************************************/
909 #ifndef PALM_1
910 static int
911 soap_isxdigit(int c)
912 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
913 }
914 #endif
915
916 /******************************************************************************/
917 #ifndef PALM_1
918 SOAP_FMAC1
919 int
920 SOAP_FMAC2
921 soap_recv_raw(struct soap *soap)
922 { register size_t ret;
923 #ifdef WITH_ZLIB
924   if (soap->mode & SOAP_ENC_ZLIB)
925   { if (soap->d_stream.next_out == Z_NULL)
926       return EOF;
927     if (soap->d_stream.avail_in || !soap->d_stream.avail_out)
928     { register int r;
929       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
930       soap->d_stream.next_out = (Byte*)soap->buf;
931       soap->d_stream.avail_out = SOAP_BUFLEN;
932       r = inflate(&soap->d_stream, Z_NO_FLUSH);
933       if (r == Z_OK || r == Z_STREAM_END)
934       { soap->bufidx = 0;
935         soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out;
936         if (soap->zlib_in == SOAP_ZLIB_GZIP)
937           soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
938         if (r == Z_STREAM_END)
939         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
940           soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
941           soap->d_stream.next_out = Z_NULL;
942         }
943         if (soap->buflen)
944         { soap->count += soap->buflen;
945           return SOAP_OK;
946         }
947       }
948       else if (r != Z_BUF_ERROR)
949       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
950         soap->d_stream.next_out = Z_NULL;
951         soap->error = SOAP_ZLIB_ERROR;
952         return EOF;
953       }
954     }
955 zlib_again:
956     if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
957     { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
958       soap->buflen = soap->z_buflen;
959     }
960   }
961 #endif
962 #ifndef WITH_NOHTTP
963   if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
964   { 
965 chunk_again:
966     if (soap->chunksize)
967     { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
968       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
969       DBGMSG(RECV, soap->buf, ret);
970       soap->bufidx = 0;
971       soap->chunksize -= ret;
972     }
973     else
974     { register soap_wchar c;
975       char *t, tmp[8];
976       t = tmp;
977       if (!soap->chunkbuflen)
978       { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
979         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
980         DBGMSG(RECV, soap->buf, ret);
981         soap->bufidx = 0;
982         if (!ret)
983           return soap->ahead = EOF;
984       }
985       else
986         soap->bufidx = soap->buflen;
987       soap->buflen = soap->chunkbuflen;
988       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
989       while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
990         if ((int)c == EOF)
991           return soap->ahead = EOF;
992       do
993         *t++ = (char)c;
994       while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
995       while ((int)c != EOF && c != '\n')
996         c = soap_getchunkchar(soap);
997       if ((int)c == EOF)
998         return soap->ahead = EOF;
999       *t = '\0';
1000       soap->chunksize = soap_strtoul(tmp, &t, 16);
1001       if (!soap->chunksize)
1002       { soap->chunkbuflen = 0;
1003         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
1004         while ((int)c != EOF && c != '\n')
1005           c = soap_getchunkchar(soap);
1006         return soap->ahead = EOF;
1007       }
1008       soap->buflen = soap->bufidx + soap->chunksize;
1009       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
1010       if (soap->buflen > soap->chunkbuflen)
1011       { soap->buflen = soap->chunkbuflen;
1012         soap->chunksize -= soap->buflen - soap->bufidx;
1013         soap->chunkbuflen = 0;
1014         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
1015       }
1016       else if (soap->chunkbuflen)
1017         soap->chunksize = 0;
1018       ret = soap->buflen - soap->bufidx;
1019       if (!ret)
1020         goto chunk_again;
1021     }
1022   }
1023   else
1024 #endif
1025   { soap->bufidx = 0;
1026     soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1027     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket));
1028     DBGMSG(RECV, soap->buf, ret);
1029   }
1030 #ifndef WITH_LEANER
1031   if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret)))
1032     return soap->error;
1033 #endif
1034 #ifdef WITH_ZLIB
1035   if (soap->mode & SOAP_ENC_ZLIB)
1036   { register int r;
1037     memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
1038     soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
1039     soap->d_stream.avail_in = (unsigned int)ret;
1040     soap->d_stream.next_out = (Byte*)soap->buf;
1041     soap->d_stream.avail_out = SOAP_BUFLEN;
1042     r = inflate(&soap->d_stream, Z_NO_FLUSH);
1043     if (r == Z_OK || r == Z_STREAM_END)
1044     { soap->bufidx = 0;
1045       soap->z_buflen = soap->buflen;
1046       soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out;
1047       if (soap->zlib_in == SOAP_ZLIB_GZIP)
1048         soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
1049       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret));
1050       if (!ret)
1051         goto zlib_again;
1052       if (r == Z_STREAM_END)
1053       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
1054         soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
1055         soap->d_stream.next_out = Z_NULL;
1056       }
1057     }
1058     else
1059     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:""));
1060       soap->d_stream.next_out = Z_NULL;
1061       soap->error = SOAP_ZLIB_ERROR;
1062       return EOF;
1063     }
1064   }
1065 #endif
1066   soap->count += ret;
1067   return !ret;
1068 }
1069 #endif
1070
1071 /******************************************************************************/
1072 #ifndef PALM_1
1073 SOAP_FMAC1
1074 int
1075 SOAP_FMAC2
1076 soap_recv(struct soap *soap)
1077
1078 #ifndef WITH_LEANER
1079   if (soap->mode & SOAP_ENC_DIME)
1080   { if (soap->dime.buflen)
1081     { char *s;
1082       int i;
1083       unsigned char tmp[12];
1084       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
1085       soap->count += soap->dime.buflen - soap->buflen;
1086       soap->buflen = soap->dime.buflen;
1087       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
1088       for (i = -(long)soap->dime.size&3; i > 0; i--)
1089       { soap->bufidx++;
1090         if (soap->bufidx >= soap->buflen)
1091           if (soap_recv_raw(soap))
1092             return EOF;
1093       }
1094       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
1095       s = (char*)tmp;
1096       for (i = 12; i > 0; i--)
1097       { *s++ = soap->buf[soap->bufidx++];
1098         if (soap->bufidx >= soap->buflen)
1099           if (soap_recv_raw(soap))
1100             return EOF;
1101       }
1102       soap->dime.flags = tmp[0] & 0x7;
1103       soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
1104       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
1105       if (soap->dime.flags & SOAP_DIME_CF)
1106       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
1107         soap->dime.chunksize = soap->dime.size;
1108         if (soap->buflen - soap->bufidx >= soap->dime.size)
1109         { soap->dime.buflen = soap->buflen;
1110           soap->buflen = soap->bufidx + soap->dime.chunksize;
1111         }
1112         else
1113           soap->dime.chunksize -= soap->buflen - soap->bufidx;
1114       }
1115       else
1116       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
1117         soap->dime.buflen = 0;
1118         soap->dime.chunksize = 0;
1119       }
1120       soap->count = soap->buflen - soap->bufidx;
1121       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
1122       return SOAP_OK;
1123     }
1124     if (soap->dime.chunksize)
1125     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
1126       if (soap_recv_raw(soap))
1127         return EOF;
1128       if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
1129       { soap->dime.buflen = soap->buflen;
1130         soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
1131         soap->buflen = soap->bufidx + soap->dime.chunksize;
1132       }
1133       else
1134         soap->dime.chunksize -= soap->buflen - soap->bufidx;
1135       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count));
1136       return SOAP_OK;
1137     }
1138   }
1139 #endif
1140   return soap_recv_raw(soap);
1141 }
1142 #endif
1143
1144 /******************************************************************************/
1145 #ifndef PALM_1
1146 SOAP_FMAC1
1147 soap_wchar
1148 SOAP_FMAC2
1149 soap_getchar(struct soap *soap)
1150 { register soap_wchar c;
1151   c = soap->ahead;
1152   if (c)
1153   { if (c != EOF)
1154       soap->ahead = 0;
1155     return c;
1156   }
1157   return soap_get1(soap);
1158 }
1159 #endif
1160
1161 /******************************************************************************/
1162 #ifndef PALM_1
1163 SOAP_FMAC1
1164 const struct soap_code_map*
1165 SOAP_FMAC2
1166 soap_code(const struct soap_code_map *map, const char *str)
1167 { if (map && str)
1168   { while (map->string)
1169     { if (!strcmp(str, map->string)) /* case sensitive */
1170         return map;
1171       map++;
1172     }
1173   }
1174   return NULL;
1175 }
1176 #endif
1177
1178 /******************************************************************************/
1179 #ifndef PALM_1
1180 SOAP_FMAC1
1181 long
1182 SOAP_FMAC2
1183 soap_code_int(const struct soap_code_map *map, const char *str, long other)
1184 { if (map)
1185   { while (map->string)
1186     { if (!soap_tag_cmp(str, map->string)) /* case insensitive */
1187         return map->code;
1188       map++;
1189     }
1190   }
1191   return other;
1192 }
1193 #endif
1194
1195 /******************************************************************************/
1196 #ifndef PALM_1
1197 SOAP_FMAC1
1198 const char*
1199 SOAP_FMAC2
1200 soap_code_str(const struct soap_code_map *map, long code)
1201 { if (!map)
1202     return NULL;
1203   while (map->code != code && map->string)
1204     map++;
1205   return map->string;
1206 }
1207 #endif
1208
1209 /******************************************************************************/
1210 #ifndef PALM_1
1211 SOAP_FMAC1
1212 long
1213 SOAP_FMAC2
1214 soap_code_bits(const struct soap_code_map *map, const char *str)
1215 { register long bits = 0;
1216   if (map)
1217   { while (str && *str)
1218     { const struct soap_code_map *p;
1219       for (p = map; p->string; p++)
1220       { register size_t n = strlen(p->string);
1221         if (!strncmp(p->string, str, n) && soap_blank(str[n]))
1222         { bits |= p->code;
1223           str += n;
1224           while (*str > 0 && *str <= 32)
1225             str++;
1226           break;
1227         }
1228       }
1229       if (!p->string)
1230         return 0;
1231     }
1232   }
1233   return bits;
1234 }
1235 #endif
1236
1237 /******************************************************************************/
1238 #ifndef PALM_1
1239 SOAP_FMAC1
1240 const char*
1241 SOAP_FMAC2
1242 soap_code_list(struct soap *soap, const struct soap_code_map *map, long code)
1243 { register char *t = soap->tmpbuf;
1244   if (map)
1245   { while (map->string)
1246     { if (map->code & code)
1247       { register const char *s = map->string;
1248         if (t != soap->tmpbuf)
1249           *t++ = ' ';
1250         while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1251           *t++ = *s++;
1252         if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1253           break;
1254       }
1255       map++;
1256     }
1257   }
1258   *t = '\0';
1259   return soap->tmpbuf;
1260 }
1261 #endif
1262
1263 /******************************************************************************/
1264 #ifndef PALM_1
1265 static soap_wchar
1266 soap_char(struct soap *soap)
1267 { char tmp[8];
1268   register int i;
1269   register soap_wchar c;
1270   register char *s = tmp;
1271   for (i = 0; i < 7; i++)
1272   { c = soap_get1(soap);
1273     if (c == ';' || (int)c == EOF)
1274       break;
1275     *s++ = (char)c;
1276   }
1277   *s = '\0';
1278   if (*tmp == '#')
1279   { if (tmp[1] == 'x' || tmp[1] == 'X')
1280       return soap_strtol(tmp + 2, NULL, 16);
1281     return atol(tmp + 1);
1282   }
1283   if (!strcmp(tmp, "lt"))
1284     return '<';
1285   if (!strcmp(tmp, "gt"))
1286     return '>';
1287   if (!strcmp(tmp, "amp"))
1288     return '&';
1289   if (!strcmp(tmp, "quot"))
1290     return '"';
1291   if (!strcmp(tmp, "apos"))
1292     return '\'';
1293 #ifndef WITH_LEAN
1294   return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
1295 #else
1296   return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
1297 #endif
1298 }
1299 #endif
1300
1301 /******************************************************************************/
1302 #ifdef WITH_LEAN
1303 #ifndef PALM_1
1304 soap_wchar
1305 soap_get0(struct soap *soap)
1306 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1307     return EOF;
1308   return (unsigned char)soap->buf[soap->bufidx];
1309 }
1310 #endif
1311 #endif
1312
1313 /******************************************************************************/
1314 #ifdef WITH_LEAN
1315 #ifndef PALM_1
1316 soap_wchar
1317 soap_get1(struct soap *soap)
1318 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1319     return EOF;
1320   return (unsigned char)soap->buf[soap->bufidx++];
1321 }
1322 #endif
1323 #endif
1324
1325 /******************************************************************************/
1326 #ifndef PALM_1
1327 SOAP_FMAC1
1328 soap_wchar
1329 SOAP_FMAC2
1330 soap_get(struct soap *soap)
1331 { register soap_wchar c;
1332   c = soap->ahead;
1333   if (c)
1334   { if ((int)c != EOF)
1335       soap->ahead = 0;
1336   }
1337   else
1338     c = soap_get1(soap);
1339   while ((int)c != EOF)
1340   { if (soap->cdata)
1341     { if (c == ']')
1342       { c = soap_get1(soap);
1343         if (c == ']')
1344         { c = soap_get0(soap);
1345           if (c == '>')
1346           { soap->cdata = 0;
1347             soap_get1(soap);
1348             c = soap_get1(soap);
1349           }
1350           else
1351           { soap_unget(soap, ']');
1352             return ']';
1353           }
1354         }
1355         else
1356         { soap_revget1(soap);
1357           return ']';
1358         }
1359       }
1360       else
1361         return c;
1362     }
1363     switch (c)
1364     { case '<':
1365         do c = soap_get1(soap);
1366         while (soap_blank(c));
1367         if (c == '!' || c == '?' || c == '%')
1368         { register int k = 1;
1369           if (c == '!')
1370           { c = soap_get1(soap);
1371             if (c == '[')
1372             { do c = soap_get1(soap);
1373               while ((int)c != EOF && c != '[');
1374               if ((int)c == EOF)
1375                 break;
1376               soap->cdata = 1;
1377               c = soap_get1(soap);
1378               continue;
1379             }
1380             if (c == '-' && (c = soap_get1(soap)) == '-')
1381             { do
1382               { c = soap_get1(soap);
1383                 if (c == '-' && (c = soap_get1(soap)) == '-')
1384                   break;
1385               } while ((int)c != EOF);
1386             }
1387           }
1388           else if (c == '?')
1389             c = soap_get_pi(soap);
1390           while ((int)c != EOF)
1391           { if (c == '<')
1392               k++;
1393             else if (c == '>')
1394             { if (--k <= 0)
1395                 break;
1396             }
1397             c = soap_get1(soap);
1398           }
1399           if ((int)c == EOF)
1400             break;
1401           c = soap_get1(soap);
1402           continue;
1403         }
1404         if (c == '/')
1405           return SOAP_TT;
1406         soap_revget1(soap);
1407         return SOAP_LT;
1408       case '>':
1409         return SOAP_GT;
1410       case '"':
1411         return SOAP_QT;
1412       case '\'':
1413         return SOAP_AP;
1414       case '&':
1415         return soap_char(soap) | 0x80000000;
1416     }
1417     break;
1418   }
1419   return c;
1420 }
1421 #endif
1422
1423 /******************************************************************************/
1424 #ifndef PALM_1
1425 static soap_wchar
1426 soap_get_pi(struct soap *soap)
1427 { char buf[64];
1428   register char *s = buf;
1429   register int i = sizeof(buf);
1430   register soap_wchar c = soap_getchar(soap);
1431   /* This is a quick way to parse XML PI and we could use a callback instead to
1432    * enable applications to intercept processing instructions */
1433   while ((int)c != EOF && c != '?')
1434   { if (--i > 0)
1435     { if (soap_blank(c))
1436         c = ' ';
1437       *s++ = (char)c;
1438     }
1439     c = soap_getchar(soap);
1440   }
1441   *s = '\0';
1442   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
1443   if (!strncmp(buf, "xml ", 4))
1444   { s = strstr(buf, " encoding=");
1445     if (s && s[10])
1446     { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
1447        || !soap_tag_cmp(s + 11, "latin1*"))
1448       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
1449         soap->mode |= SOAP_ENC_LATIN;
1450       }
1451       else if (!soap_tag_cmp(s + 11, "utf-8*"))
1452       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
1453         soap->mode &= ~SOAP_ENC_LATIN;
1454       }
1455     }
1456   }
1457   if ((int)c != EOF)
1458     c = soap_getchar(soap);
1459   return c;
1460 }
1461 #endif
1462
1463 /******************************************************************************/
1464 #ifndef WITH_LEANER
1465 #ifndef PALM_1
1466 SOAP_FMAC1
1467 int
1468 SOAP_FMAC2
1469 soap_move(struct soap *soap, long n)
1470 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
1471   for (; n > 0; n--)
1472     if ((int)soap_getchar(soap) == EOF)
1473       return SOAP_EOF;
1474   return SOAP_OK;
1475 }
1476 #endif
1477 #endif
1478
1479 /******************************************************************************/
1480 #ifndef WITH_LEANER
1481 #ifndef PALM_1
1482 SOAP_FMAC1
1483 size_t
1484 SOAP_FMAC2
1485 soap_tell(struct soap *soap)
1486 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
1487 }
1488 #endif
1489 #endif
1490
1491 /******************************************************************************/
1492 #ifndef PALM_1
1493 SOAP_FMAC1
1494 int
1495 SOAP_FMAC2
1496 soap_pututf8(struct soap *soap, register unsigned long c)
1497 { char tmp[16];
1498   if (c > 0 && c < 0x80)
1499   { *tmp = (char)c;
1500     return soap_send_raw(soap, tmp, 1);
1501   }
1502 #ifndef WITH_LEAN
1503   if (soap->mode & SOAP_XML_CANONICAL)
1504   { register char *t = tmp;
1505     if (c < 0x0800)
1506       *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
1507     else
1508     { if (c < 0x010000)
1509         *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
1510       else
1511       { if (c < 0x200000)
1512           *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
1513         else
1514         { if (c < 0x04000000)
1515             *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
1516           else
1517           { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
1518             *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
1519           }
1520           *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
1521         }     
1522         *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
1523       }
1524       *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
1525     }
1526     *t++ = (char)(0x80 | (c & 0x3F));
1527     *t = '\0';
1528   }
1529   else
1530 #endif
1531     sprintf(tmp, "&#%lu;", c);
1532   return soap_send(soap, tmp);
1533 }
1534 #endif
1535
1536 /******************************************************************************/
1537 #ifndef PALM_1
1538 SOAP_FMAC1
1539 soap_wchar
1540 SOAP_FMAC2
1541 soap_getutf8(struct soap *soap)
1542 { register soap_wchar c, c1, c2, c3, c4;
1543   c = soap->ahead;
1544   if (c > 0xFF)
1545   { soap->ahead = 0;
1546     return c;
1547   }
1548 again:
1549   c = soap_get(soap);
1550   if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
1551     return c;
1552   c1 = soap_get1(soap);
1553   if (c1 < 0x80)
1554   { soap_revget1(soap); /* doesn't look like this is UTF8 */
1555     return c;
1556   }
1557   c1 &= 0x3F;
1558   if (c < 0xE0)
1559     return ((soap_wchar)(c & 0x1F) << 6) | c1;
1560   c2 = (soap_wchar)soap_get1(soap) & 0x3F;
1561   if (c == 0xEF && c1 == 0x3B && c2 == 0x3F)    /* ignore UTF-8 BOM */
1562     goto again;
1563   if (c < 0xF0)
1564     return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
1565   c3 = (soap_wchar)soap_get1(soap) & 0x3F;
1566   if (c < 0xF8)
1567     return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
1568   c4 = (soap_wchar)soap_get1(soap) & 0x3F;
1569   if (c < 0xFC)
1570     return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
1571   return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
1572 }
1573 #endif
1574
1575 /******************************************************************************/
1576 #ifndef PALM_1
1577 SOAP_FMAC1
1578 int
1579 SOAP_FMAC2
1580 soap_puthex(struct soap *soap, const unsigned char *s, int n)
1581 { char d[2];
1582   register int i;
1583 #ifdef WITH_DOM
1584   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1585   { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
1586       return soap->error;
1587     return SOAP_OK;
1588   }
1589 #endif
1590   for (i = 0; i < n; i++)
1591   { register int m = *s++;
1592     d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
1593     m &= 0x0F;
1594     d[1] = (char)(m + (m > 9 ? '7' : '0'));
1595     if (soap_send_raw(soap, d, 2))
1596       return soap->error;
1597   }
1598   return SOAP_OK;
1599 }
1600 #endif
1601
1602 /******************************************************************************/
1603 #ifndef PALM_1
1604 SOAP_FMAC1
1605 unsigned char*
1606 SOAP_FMAC2
1607 soap_gethex(struct soap *soap, int *n)
1608 {
1609 #ifdef WITH_DOM
1610   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1611   { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1612     return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
1613   }
1614 #endif
1615 #ifdef WITH_FAST
1616   soap->labidx = 0;
1617   for (;;)
1618   { register char *s;
1619     register int i, k;
1620     if (soap_append_lab(soap, NULL, 0))
1621       return NULL;
1622     s = soap->labbuf + soap->labidx;
1623     k = soap->lablen - soap->labidx;
1624     soap->labidx = soap->lablen;
1625     for (i = 0; i < k; i++)
1626     { register char d1, d2;
1627       register soap_wchar c;
1628       c = soap_get(soap);
1629       if (soap_isxdigit(c))
1630       { d1 = (char)c;
1631         c = soap_get(soap); 
1632         if (soap_isxdigit(c))
1633           d2 = (char)c;
1634         else 
1635         { soap->error = SOAP_TYPE;
1636           return NULL;
1637         }
1638       }
1639       else
1640       { unsigned char *p;
1641         soap_unget(soap, c);
1642         if (n)
1643           *n = (int)(soap->lablen - k + i);
1644         p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
1645         if (p)
1646           memcpy(p, soap->labbuf, soap->lablen - k + i);
1647         return p;
1648       }
1649       *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1650     }
1651   }
1652 #else
1653   if (soap_new_block(soap))
1654     return NULL;
1655   for (;;)
1656   { register int i;
1657     register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN);
1658     if (!s)
1659     { soap_end_block(soap);
1660       return NULL;
1661     }
1662     for (i = 0; i < SOAP_BLKLEN; i++)
1663     { register char d1, d2;
1664       register soap_wchar c = soap_get(soap);
1665       if (soap_isxdigit(c))
1666       { d1 = (char)c;
1667         c = soap_get(soap); 
1668         if (soap_isxdigit(c))
1669           d2 = (char)c;
1670         else 
1671         { soap_end_block(soap);
1672           soap->error = SOAP_TYPE;
1673           return NULL;
1674         }
1675       }
1676       else
1677       { unsigned char *p;
1678         soap_unget(soap, c);
1679         if (n)
1680           *n = soap_size_block(soap, i);
1681         p = (unsigned char*)soap_save_block(soap, NULL, 0);
1682         return p;
1683       }
1684       *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1685     }
1686   }
1687 #endif
1688 }
1689 #endif
1690
1691 /******************************************************************************/
1692 #ifndef PALM_1
1693 SOAP_FMAC1
1694 int
1695 SOAP_FMAC2
1696 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
1697 { register int i;
1698   register unsigned long m;
1699   char d[4];
1700   if (!s)
1701     return SOAP_OK;
1702 #ifdef WITH_DOM
1703   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1704   { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
1705       return soap->error;
1706     return SOAP_OK;
1707   }
1708 #endif
1709   for (; n > 2; n -= 3, s += 3)
1710   { m = s[0];
1711     m = (m << 8) | s[1];
1712     m = (m << 8) | s[2];
1713     for (i = 4; i > 0; m >>= 6)
1714       d[--i] = soap_base64o[m & 0x3F];
1715     if (soap_send_raw(soap, d, 4))
1716       return soap->error;
1717   }
1718   if (n > 0)
1719   { m = 0;
1720     for (i = 0; i < n; i++)
1721       m = (m << 8) | *s++;
1722     for (; i < 3; i++)
1723       m <<= 8;
1724     for (i++; i > 0; m >>= 6)
1725       d[--i] = soap_base64o[m & 0x3F];
1726     for (i = 3; i > n; i--)
1727       d[i] = '=';
1728     if (soap_send_raw(soap, d, 4))
1729       return soap->error;
1730   }
1731   return SOAP_OK;
1732 }
1733 #endif
1734
1735 /******************************************************************************/
1736 #ifndef PALM_1
1737 SOAP_FMAC1
1738 unsigned char*
1739 SOAP_FMAC2
1740 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
1741
1742 #ifdef WITH_DOM
1743   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1744   { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1745     return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
1746   }
1747 #endif
1748 #ifdef WITH_FAST
1749   soap->labidx = 0;
1750   for (;;)
1751   { register int i, k;
1752     register char *s;
1753     if (soap_append_lab(soap, NULL, 2))
1754       return NULL;
1755     s = soap->labbuf + soap->labidx;
1756     k = soap->lablen - soap->labidx;
1757     soap->labidx = 3 * (soap->lablen / 3);
1758     if (!s)
1759       return NULL;
1760     for (i = 0; i < k - 2; i += 3)
1761     { register unsigned long m = 0;
1762       register int j = 0;
1763       do
1764       { register soap_wchar c = soap_get(soap);
1765         if (c == '=' || c < 0)
1766         { unsigned char *p;
1767           switch (j)
1768           { case 2:
1769               *s++ = (char)((m >> 4) & 0xFF);
1770               i++;
1771               break;
1772             case 3:
1773               *s++ = (char)((m >> 10) & 0xFF);
1774               *s++ = (char)((m >> 2) & 0xFF);
1775               i += 2;
1776           }
1777           if (n)
1778             *n = (int)(soap->lablen - k + i);
1779           p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
1780           if (p)
1781             memcpy(p, soap->labbuf, soap->lablen - k + i);
1782           if (c >= 0)
1783           { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1784               ;
1785           }
1786           soap_unget(soap, c);
1787           return p;
1788         }
1789         c -= '+';
1790         if (c >= 0 && c <= 79)
1791         { m = (m << 6) + soap_base64i[c];
1792           j++;
1793         }
1794       } while (j < 4);
1795       *s++ = (char)((m >> 16) & 0xFF);
1796       *s++ = (char)((m >> 8) & 0xFF);
1797       *s++ = (char)(m & 0xFF);
1798     }
1799   }
1800 #else
1801   if (soap_new_block(soap))
1802     return NULL;
1803   for (;;)
1804   { register int i;
1805     register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
1806     if (!s)
1807     { soap_end_block(soap);
1808       return NULL;
1809     }
1810     for (i = 0; i < SOAP_BLKLEN; i++)
1811     { register unsigned long m = 0;
1812       register int j = 0;
1813       do
1814       { register soap_wchar c = soap_get(soap);
1815         if (c == '=' || c < 0)
1816         { unsigned char *p;
1817           i *= 3;
1818           switch (j)
1819           { case 2:
1820               *s++ = (char)((m >> 4) & 0xFF);
1821               i++;
1822               break;
1823             case 3:
1824               *s++ = (char)((m >> 10) & 0xFF);
1825               *s++ = (char)((m >> 2) & 0xFF);
1826               i += 2;
1827           }
1828           if (n)
1829             *n = (int)soap_size_block(soap, i);
1830           p = (unsigned char*)soap_save_block(soap, NULL, 0);
1831           if (c >= 0)
1832           { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1833               ;
1834           }
1835           soap_unget(soap, c);
1836           return p;
1837         }
1838         c -= '+';
1839         if (c >= 0 && c <= 79)
1840         { m = (m << 6) + soap_base64i[c];
1841           j++;
1842         }
1843       } while (j < 4);
1844       *s++ = (char)((m >> 16) & 0xFF);
1845       *s++ = (char)((m >> 8) & 0xFF);
1846       *s++ = (char)(m & 0xFF);
1847     }
1848   }
1849 #endif
1850 }
1851 #endif
1852
1853 /******************************************************************************/
1854 #ifndef WITH_LEANER
1855 #ifndef PALM_1
1856 SOAP_FMAC1
1857 int
1858 SOAP_FMAC2
1859 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
1860 { /* Check MTOM xop:Include element (within hex/base64Binary) */
1861   /* TODO: this code to be obsoleted with new import/xop.h conventions */
1862   int body = soap->body; /* should save type too? */
1863   if (!soap_peek_element(soap))
1864   { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href)
1865     { if (soap_dime_forward(soap, ptr, size, id, type, options))
1866         return soap->error;
1867     }
1868     if (soap->body && soap_element_end_in(soap, NULL))
1869       return soap->error;
1870   }
1871   soap->body = body;
1872   return SOAP_OK;
1873 }
1874 #endif
1875 #endif
1876
1877 /******************************************************************************/
1878 #ifndef WITH_LEANER
1879 #ifndef PALM_1
1880 SOAP_FMAC1
1881 int
1882 SOAP_FMAC2
1883 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
1884 { struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
1885   *ptr = NULL;
1886   *size = 0;
1887   *id = soap_strdup(soap, soap->href);
1888   *type = NULL;
1889   *options = NULL;
1890   if (!xp)
1891     return soap->error = SOAP_EOM;
1892   xp->next = soap->xlist;
1893   xp->ptr = ptr;
1894   xp->size = size;
1895   xp->id = *id;
1896   xp->type = type;
1897   xp->options = options;
1898   soap->xlist = xp;
1899   return SOAP_OK;
1900 }
1901 #endif
1902 #endif
1903
1904 /******************************************************************************/
1905 #ifndef PALM_1
1906 SOAP_FMAC1
1907 char *
1908 SOAP_FMAC2
1909 soap_strdup(struct soap *soap, const char *s)
1910 { char *t = NULL;
1911   if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
1912     strcpy(t, s);
1913   return t;
1914 }
1915 #endif
1916
1917 /******************************************************************************/
1918 #ifndef PALM_1
1919 SOAP_FMAC1
1920 int
1921 SOAP_FMAC2
1922 soap_new_block(struct soap *soap)
1923 { struct soap_blist *p;
1924   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
1925   if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
1926     return SOAP_EOM;   
1927   p->next = soap->blist; 
1928   p->ptr = NULL;
1929   p->size = 0;
1930   soap->blist = p;
1931   return SOAP_OK;
1932 }
1933 #endif
1934
1935 /******************************************************************************/
1936 #ifndef PALM_1
1937 SOAP_FMAC1
1938 void*
1939 SOAP_FMAC2
1940 soap_push_block(struct soap *soap, size_t n)
1941 { char *p;
1942   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));
1943   if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
1944   { soap->error = SOAP_EOM;
1945     return NULL;
1946   }
1947   *(char**)p = soap->blist->ptr;
1948   *(size_t*)(p + sizeof(char*)) = n;
1949   soap->blist->ptr = p;
1950   soap->blist->size += n;
1951   return p + sizeof(char*) + sizeof(size_t);
1952 }
1953 #endif
1954
1955 /******************************************************************************/
1956 #ifndef PALM_1
1957 SOAP_FMAC1
1958 void
1959 SOAP_FMAC2
1960 soap_pop_block(struct soap *soap)
1961 { char *p;
1962   if (!soap->blist->ptr)
1963     return;
1964   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
1965   p = soap->blist->ptr;
1966   soap->blist->size -= *(size_t*)(p + sizeof(char*));
1967   soap->blist->ptr = *(char**)p;
1968   SOAP_FREE(soap, p);
1969 }
1970 #endif
1971
1972 /******************************************************************************/
1973 #ifndef WITH_NOIDREF
1974 #ifndef PALM_1
1975 static void
1976 soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
1977 { int i;
1978   register struct soap_ilist *ip;
1979   register struct soap_flist *fp;
1980 #ifndef WITH_LEANER
1981   register struct soap_xlist *xp;
1982 #endif
1983   register void *p, **q;
1984   for (i = 0; i < SOAP_IDHASH; i++)
1985   { for (ip = soap->iht[i]; ip; ip = ip->next)
1986     { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
1987       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
1988         ip->ptr = (char*)ip->ptr + (p1-p2);
1989       }
1990       for (q = &ip->link; q; q = (void**)p)
1991       { p = *q;
1992         if (p && (char*)p >= start && (char*)p < end)
1993         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
1994           *q = (char*)p + (p1-p2);
1995         }
1996       }
1997       for (q = &ip->copy; q; q = (void**)p)
1998       { p = *q;
1999         if (p && (char*)p >= start && (char*)p < end)
2000         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
2001           *q = (char*)p + (p1-p2);
2002         }
2003       }
2004       for (fp = ip->flist; fp; fp = fp->next)
2005       { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
2006         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
2007           fp->ptr = (char*)fp->ptr + (p1-p2);
2008         }
2009       }
2010     }
2011   }
2012 #ifndef WITH_LEANER
2013   for (xp = soap->xlist; xp; xp = xp->next)
2014   { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
2015     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2)));
2016       xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
2017       xp->size = (int*)((char*)xp->size + (p1-p2));
2018       xp->type = (char**)((char*)xp->type + (p1-p2));
2019       xp->options = (char**)((char*)xp->options + (p1-p2));
2020     }
2021   }
2022 #endif
2023 }
2024 #endif
2025 #endif
2026
2027 /******************************************************************************/
2028 #ifndef WITH_NOIDREF
2029 #ifndef PALM_1
2030 static int
2031 soap_has_copies(struct soap *soap, register const char *start, register const char *end)
2032 { register int i;
2033   register struct soap_ilist *ip;
2034   register struct soap_flist *fp;
2035   register const char *p;
2036   for (i = 0; i < SOAP_IDHASH; i++)
2037   { for (ip = soap->iht[i]; ip; ip = ip->next)
2038     { for (p = (const char*)ip->copy; p; p = *(const char**)p)
2039         if (p >= start && p < end)
2040           return SOAP_ERR;
2041       for (fp = ip->flist; fp; fp = fp->next)
2042         if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
2043           return SOAP_ERR;
2044     }
2045   }
2046   return SOAP_OK;
2047 }
2048 #endif
2049 #endif
2050
2051 /******************************************************************************/
2052 #ifndef WITH_NOIDREF
2053 #ifndef PALM_1
2054 SOAP_FMAC1
2055 int
2056 SOAP_FMAC2
2057 soap_resolve(struct soap *soap)
2058 { register int i;
2059   register struct soap_ilist *ip;
2060   register struct soap_flist *fp;
2061   short flag;
2062   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
2063   for (i = 0; i < SOAP_IDHASH; i++)
2064   { for (ip = soap->iht[i]; ip; ip = ip->next)
2065     { if (ip->ptr)
2066       { register void *p, **q, *r;
2067         q = (void**)ip->link;
2068         ip->link = NULL;
2069         r = ip->ptr;
2070         DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
2071         while (q)
2072         { p = *q;
2073           *q = r;
2074           DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
2075           q = (void**)p;
2076         }
2077       }
2078       else if (*ip->id == '#')
2079       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
2080         strcpy(soap->id, ip->id + 1);
2081         return soap->error = SOAP_MISSING_ID;
2082       }
2083     }
2084   }
2085   do
2086   { flag = 0;
2087     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
2088     for (i = 0; i < SOAP_IDHASH; i++)
2089     { for (ip = soap->iht[i]; ip; ip = ip->next)
2090       { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
2091         { if (ip->copy)
2092           { register void *p, **q = (void**)ip->copy;
2093             DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
2094             ip->copy = NULL;
2095             do
2096             { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
2097               p = *q;
2098               memcpy(q, ip->ptr, ip->size);
2099               q = (void**)p;
2100             } while (q);
2101             flag = 1;
2102           }
2103           for (fp = ip->flist; fp; fp = ip->flist)
2104           { register unsigned int k = fp->level;
2105             register void *p = ip->ptr;
2106             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));
2107             while (ip->level < k)
2108             { register void **q = (void**)soap_malloc(soap, sizeof(void*));  
2109               if (!q)
2110                 return soap->error;
2111               *q = p;
2112               DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
2113               p = (void*)q;
2114               k--;
2115             }
2116             if (fp->fcopy)
2117               fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2118             else
2119               soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2120             ip->flist = fp->next;
2121             SOAP_FREE(soap, fp);
2122             flag = 1;
2123           }
2124         }
2125       }
2126     }
2127   } while (flag);
2128 #ifdef SOAP_DEBUG
2129   for (i = 0; i < SOAP_IDHASH; i++)
2130   { for (ip = soap->iht[i]; ip; ip = ip->next)
2131     { if (ip->copy || ip->flist)
2132       { 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));
2133       }
2134     }
2135   }
2136 #endif
2137   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
2138   return SOAP_OK;
2139 }
2140 #endif
2141 #endif
2142
2143 /******************************************************************************/
2144 #ifndef PALM_1
2145 SOAP_FMAC1
2146 size_t
2147 SOAP_FMAC2
2148 soap_size_block(struct soap *soap, size_t n)
2149 { if (soap->blist->ptr)
2150   { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n;
2151     *(size_t*)(soap->blist->ptr + sizeof(char*)) = n;
2152   }
2153   return soap->blist->size;
2154 }
2155 #endif
2156
2157 /******************************************************************************/
2158 #ifndef PALM_1
2159 SOAP_FMAC1
2160 char*
2161 SOAP_FMAC2
2162 soap_first_block(struct soap *soap)
2163 { char *p, *q, *r;
2164   p = soap->blist->ptr;
2165   if (!p)
2166     return NULL;
2167   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
2168   r = NULL;
2169   do
2170   { q = *(char**)p;
2171     *(char**)p = r;
2172     r = p;
2173     p = q;
2174   } while (p);
2175   soap->blist->ptr = r;
2176   return r + sizeof(char*) + sizeof(size_t);
2177 }
2178 #endif
2179
2180 /******************************************************************************/
2181 #ifndef PALM_1
2182 SOAP_FMAC1
2183 char*
2184 SOAP_FMAC2
2185 soap_next_block(struct soap *soap)
2186 { char *p;
2187   p = soap->blist->ptr;
2188   if (p)
2189   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
2190     soap->blist->ptr = *(char**)p;
2191     SOAP_FREE(soap, p);
2192     if (soap->blist->ptr)
2193       return soap->blist->ptr + sizeof(char*) + sizeof(size_t);
2194   }
2195   return NULL;
2196 }
2197 #endif
2198
2199 /******************************************************************************/
2200 #ifndef PALM_1
2201 SOAP_FMAC1
2202 size_t
2203 SOAP_FMAC2
2204 soap_block_size(struct soap *soap)
2205 { return *(size_t*)(soap->blist->ptr + sizeof(char*));
2206 }
2207 #endif
2208
2209 /******************************************************************************/
2210 #ifndef PALM_1
2211 SOAP_FMAC1
2212 void
2213 SOAP_FMAC2
2214 soap_end_block(struct soap *soap)
2215 { struct soap_blist *bp;
2216   char *p, *q;
2217   bp = soap->blist;
2218   if (bp)
2219   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
2220     for (p = bp->ptr; p; p = q)
2221     { q = *(char**)p;
2222       SOAP_FREE(soap, p);
2223     }
2224     soap->blist = bp->next;
2225     SOAP_FREE(soap, bp);
2226   }
2227   DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
2228 }
2229 #endif
2230
2231 /******************************************************************************/
2232 #ifndef PALM_1
2233 SOAP_FMAC1
2234 char*
2235 SOAP_FMAC2
2236 soap_save_block(struct soap *soap, char *p, int flag)
2237 { register size_t n;
2238   register char *q, *s;
2239   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));
2240   if (soap->blist->size)
2241   { if (!p)
2242       p = (char*)soap_malloc(soap, soap->blist->size);
2243     if (p)
2244     { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap))
2245       { n = soap_block_size(soap);
2246 #ifndef WITH_NOIDREF
2247         if (flag)
2248           soap_update_ptrs(soap, q, q + n, s, q);
2249 #endif
2250         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
2251         memcpy(s, q, n);
2252         s += n;
2253       }
2254     }
2255     else
2256       soap->error = SOAP_EOM;
2257   }
2258   soap_end_block(soap);
2259   return p;
2260 }
2261 #endif
2262
2263 /******************************************************************************/
2264 #ifndef PALM_2
2265 SOAP_FMAC1
2266 char *
2267 SOAP_FMAC2
2268 soap_putsize(struct soap *soap, const char *type, int size)
2269 { return soap_putsizes(soap, type, &size, 1);
2270 }
2271 #endif
2272
2273 /******************************************************************************/
2274 #ifndef PALM_2
2275 SOAP_FMAC1
2276 char *
2277 SOAP_FMAC2
2278 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
2279 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
2280 }
2281 #endif
2282
2283 /******************************************************************************/
2284 #ifndef PALM_2
2285 SOAP_FMAC1
2286 char *
2287 SOAP_FMAC2
2288 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
2289 { int i;
2290   if (!type)
2291     return NULL;
2292   if (soap->version == 2)
2293   { sprintf(soap->type, "%s[%d", type, size[0]);
2294     for (i = 1; i < dim; i++)
2295       sprintf(soap->type + strlen(soap->type), " %d", size[i]);
2296   }
2297   else
2298   { if (offset)
2299     { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
2300       for (i = 1; i < dim; i++)
2301         sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
2302     }
2303     else
2304     { sprintf(soap->type, "%s[%d", type, size[0]);
2305       for (i = 1; i < dim; i++)
2306         sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
2307     }
2308     strcat(soap->type, "]");
2309   }
2310   return soap->type;
2311 }
2312 #endif
2313
2314 /******************************************************************************/
2315 #ifndef PALM_2
2316 SOAP_FMAC1
2317 char *
2318 SOAP_FMAC2
2319 soap_putoffset(struct soap *soap, int offset)
2320 { return soap_putoffsets(soap, &offset, 1);
2321 }
2322 #endif
2323
2324 /******************************************************************************/
2325 #ifndef PALM_2
2326 SOAP_FMAC1
2327 char *
2328 SOAP_FMAC2
2329 soap_putoffsets(struct soap *soap, const int *offset, int dim)
2330 { register int i;
2331   sprintf(soap->arrayOffset, "[%d", offset[0]);
2332   for (i = 1; i < dim; i++)
2333     sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
2334   strcat(soap->arrayOffset, "]");
2335   return soap->arrayOffset;
2336 }
2337 #endif
2338
2339 /******************************************************************************/
2340 #ifndef PALM_2
2341 SOAP_FMAC1
2342 int
2343 SOAP_FMAC2
2344 soap_size(const int *size, int dim)
2345 { register int i, n = size[0];
2346   for (i = 1; i < dim; i++)
2347     n *= size[i];
2348   return n;
2349 }
2350 #endif
2351
2352 /******************************************************************************/
2353 #ifndef PALM_2
2354 SOAP_FMAC1
2355 int
2356 SOAP_FMAC2
2357 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
2358 { register int i, j = 0;
2359   if (offset)
2360     for (i = 0; i < dim && attr && *attr; i++)
2361     { attr++;
2362       j *= size[i];
2363       j += offset[i] = (int)atol(attr);
2364       attr = strchr(attr, ',');
2365     }
2366   else
2367     for (i = 0; i < dim && attr && *attr; i++)
2368     { attr++;
2369       j *= size[i];
2370       j += (int)atol(attr);
2371       attr = strchr(attr, ',');
2372     }
2373   return j;
2374 }
2375 #endif
2376
2377 /******************************************************************************/
2378 #ifndef PALM_2
2379 SOAP_FMAC1
2380 int
2381 SOAP_FMAC2
2382 soap_getsize(const char *attr1, const char *attr2, int *j)
2383 { register int n, k;
2384   char *s;
2385   *j = 0;
2386   if (!*attr1)
2387     return -1;
2388   if (*attr1 == '[')
2389     attr1++;
2390   n = 1;
2391   for (;;)
2392   { k = (int)soap_strtol(attr1, &s, 10);
2393     n *= k;
2394     if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
2395       return -1;
2396     attr1 = strchr(s, ',');
2397     if (!attr1)
2398       attr1 = strchr(s, ' ');
2399     if (attr2 && *attr2)
2400     { attr2++;
2401       *j *= k;
2402       k = (int)soap_strtol(attr2, &s, 10);
2403       *j += k;
2404       if (k < 0)
2405         return -1;
2406       attr2 = s;
2407     }
2408     if (!attr1)
2409       break;
2410     attr1++;
2411   }
2412   return n - *j;
2413 }
2414 #endif
2415
2416 /******************************************************************************/
2417 #ifndef PALM_2
2418 SOAP_FMAC1
2419 int
2420 SOAP_FMAC2
2421 soap_getsizes(const char *attr, int *size, int dim)
2422 { register int i, k, n;
2423   if (!*attr)
2424     return -1;
2425   i = strlen(attr);
2426   n = 1;
2427   do
2428   { for (i = i-1; i >= 0; i--)
2429       if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
2430         break;
2431     k = (int)atol(attr + i + 1);
2432     n *= size[--dim] = k;
2433     if (k < 0 || n > SOAP_MAXARRAYSIZE)
2434       return -1;
2435   } while (i >= 0 && attr[i] != '[');
2436   return n;
2437 }
2438 #endif
2439
2440 /******************************************************************************/
2441 #ifndef PALM_2
2442 SOAP_FMAC1
2443 int
2444 SOAP_FMAC2
2445 soap_getposition(const char *attr, int *pos)
2446 { register int i, n;
2447   if (!*attr)
2448     return -1;
2449   n = 0;
2450   i = 1;
2451   do
2452   { pos[n++] = (int)atol(attr + i);
2453     while (attr[i] && attr[i] != ',' && attr[i] != ']')
2454       i++;
2455     if (attr[i] == ',')
2456       i++;
2457   } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
2458   return n;
2459 }
2460 #endif
2461
2462 /******************************************************************************/
2463 #ifndef PALM_2
2464 SOAP_FMAC1
2465 int
2466 SOAP_FMAC2
2467 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
2468 { register struct soap_nlist *np;
2469   register struct Namespace *p;
2470   register short i = -1;
2471   register size_t n, k;
2472   n = strlen(id);
2473   k = strlen(ns) + 1;
2474   p = soap->local_namespaces;
2475   if (p)
2476   { for (i = 0; p->id; p++, i++)
2477     { if (p->ns && !strcmp(ns, p->ns))
2478       { if (p->out)
2479         { SOAP_FREE(soap, p->out);
2480           p->out = NULL;
2481         }
2482         break;
2483       }
2484       if (p->out)
2485       { if (!strcmp(ns, p->out))
2486           break;
2487       }
2488       else if (p->in)
2489       { if (!soap_tag_cmp(ns, p->in))
2490         { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
2491             strcpy(p->out, ns);
2492           break;
2493         }
2494       }
2495     }
2496     if (!p || !p->id)
2497       i = -1;
2498   }
2499   if (i >= 0)
2500     k = 0;
2501   np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
2502   if (!np)
2503     return soap->error = SOAP_EOM;
2504   np->next = soap->nlist;
2505   soap->nlist = np;
2506   np->level = soap->level;
2507   np->index = i;
2508   strcpy(np->id, id);
2509   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
2510   if (i < 0)
2511   { np->ns = np->id + n + 1;
2512     strcpy(np->ns, ns);
2513     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
2514   }
2515   else
2516   { np->ns = NULL;
2517     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
2518   }
2519   return SOAP_OK;
2520 }
2521 #endif
2522
2523 /******************************************************************************/
2524 #ifndef PALM_2
2525 SOAP_FMAC1
2526 void
2527 SOAP_FMAC2
2528 soap_pop_namespace(struct soap *soap)
2529 { register struct soap_nlist *np;
2530   while (soap->nlist && soap->nlist->level >= soap->level)
2531   { np = soap->nlist->next;
2532     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id));
2533     SOAP_FREE(soap, soap->nlist);
2534     soap->nlist = np;
2535   }
2536 }
2537 #endif
2538
2539 /******************************************************************************/
2540 #ifndef PALM_2
2541 SOAP_FMAC1
2542 int
2543 SOAP_FMAC2
2544 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) 
2545 { register struct soap_nlist *np = soap->nlist;
2546   while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
2547     np = np->next;
2548   if (np)
2549   { if (np->index < 0
2550      || (soap->local_namespaces[np->index].id
2551       && (strncmp(soap->local_namespaces[np->index].id, id2, n2)
2552        || soap->local_namespaces[np->index].id[n2])))
2553       return SOAP_NAMESPACE;
2554     return SOAP_OK;
2555   }
2556   if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2))
2557     return SOAP_OK;
2558   return SOAP_SYNTAX_ERROR; 
2559 }
2560 #endif
2561
2562 /******************************************************************************/
2563 #ifndef PALM_2
2564 SOAP_FMAC1
2565 const char*
2566 SOAP_FMAC2
2567 soap_current_namespace(struct soap *soap, const char *tag)
2568 { register struct soap_nlist *np;
2569   register const char *s;
2570   np = soap->nlist;
2571   if (!(s = strchr(tag, ':')))
2572   { while (np && *np->id) /* find default namespace, if present */
2573       np = np->next;
2574   }
2575   else
2576   { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
2577       np = np->next;
2578     if (!np)
2579       soap->error = SOAP_NAMESPACE;
2580   }
2581   if (np)
2582   { if (np->index >= 0)
2583       return soap->namespaces[np->index].ns;
2584     if (np->ns)
2585       return soap_strdup(soap, np->ns);
2586   }
2587   return NULL;
2588 }
2589 #endif
2590
2591 /******************************************************************************/
2592 #ifndef PALM_2
2593 SOAP_FMAC1
2594 int
2595 SOAP_FMAC2
2596 soap_tag_cmp(const char *s, const char *t)
2597 { for (;;)
2598   { register int c1 = *s;
2599     register int c2 = *t;
2600     if (!c1 || c1 == '"')
2601       break;
2602     if (c2 != '-')
2603     { if (c1 != c2)
2604       { if (c1 >= 'A' && c1 <= 'Z')
2605           c1 += 'a' - 'A';
2606         if (c2 >= 'A' && c2 <= 'Z')
2607           c2 += 'a' - 'A';
2608       }
2609       if (c1 != c2)
2610       { if (c2 != '*')
2611           return 1;
2612         c2 = *++t;
2613         if (!c2)
2614           return 0;
2615         if (c2 >= 'A' && c2 <= 'Z')
2616           c2 += 'a' - 'A';
2617         for (;;)
2618         { c1 = *s;
2619           if (!c1 || c1 == '"')
2620             break;
2621           if (c1 >= 'A' && c1 <= 'Z')
2622             c1 += 'a' - 'A';
2623           if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
2624             return 0;
2625           s++;
2626         }
2627         break;
2628       }
2629     }
2630     s++;
2631     t++;
2632   }
2633   if (*t == '*' && !t[1])
2634     return 0;
2635   return *t;
2636 }
2637 #endif
2638
2639 /******************************************************************************/
2640 #ifndef PALM_2
2641 SOAP_FMAC1
2642 int
2643 SOAP_FMAC2
2644 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
2645 { register const char *s, *t;
2646   if (!tag1 || !tag2 || !*tag2)
2647     return SOAP_OK;
2648   s = strchr(tag1, ':');
2649   t = strchr(tag2, ':');
2650   if (t)
2651   { if (s)
2652     { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
2653         return SOAP_TAG_MISMATCH;
2654       if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))
2655       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2656         return SOAP_TAG_MISMATCH;
2657       }
2658     } 
2659     else if (SOAP_STRCMP(tag1, t + 1))
2660       return SOAP_TAG_MISMATCH;
2661     else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2))
2662     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2663       return SOAP_TAG_MISMATCH;
2664     }
2665     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
2666     return SOAP_OK;
2667   }
2668   if (s)
2669   { if (SOAP_STRCMP(s + 1, tag2))
2670       return SOAP_TAG_MISMATCH;
2671   }
2672   else if (SOAP_STRCMP(tag1, tag2))
2673     return SOAP_TAG_MISMATCH;
2674   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
2675   return SOAP_OK;
2676 }
2677 #endif
2678
2679 /******************************************************************************/
2680 #ifndef PALM_2
2681 SOAP_FMAC1
2682 int
2683 SOAP_FMAC2
2684 soap_match_array(struct soap *soap, const char *type)
2685 { if (*soap->arrayType)
2686     if (soap_match_tag(soap, soap->arrayType, type)
2687      && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
2688      && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
2689     )
2690     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
2691       return SOAP_TAG_MISMATCH;
2692     }
2693   return SOAP_OK;
2694 }
2695 #endif
2696
2697 /******************************************************************************\
2698  *
2699  *      SSL
2700  *
2701 \******************************************************************************/
2702
2703 #ifdef WITH_OPENSSL
2704 /******************************************************************************/
2705 #ifndef PALM_2
2706 SOAP_FMAC1
2707 int
2708 SOAP_FMAC2
2709 soap_rand()
2710 { unsigned char buf[4];
2711   if (!ssl_init_done)
2712     soap_ssl_init();
2713   RAND_pseudo_bytes(buf, 4);
2714   return *(int*)buf;
2715 }
2716 #endif
2717
2718 /******************************************************************************/
2719 #ifndef PALM_2
2720 SOAP_FMAC1
2721 int
2722 SOAP_FMAC2
2723 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)
2724 { int err;
2725   soap->keyfile = keyfile;
2726   soap->password = password;
2727   soap->cafile = cafile;
2728   soap->capath = capath;
2729   soap->dhfile = dhfile;
2730   soap->rsa = (dhfile == NULL);
2731   soap->randfile = randfile;
2732   soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION);
2733   if (!(err = soap->fsslauth(soap)))
2734   { if (sid)
2735       SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid));
2736   }
2737   return err; 
2738 }
2739 #endif
2740
2741 /******************************************************************************/
2742 #ifndef PALM_2
2743 SOAP_FMAC1
2744 int
2745 SOAP_FMAC2
2746 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)
2747 { soap->keyfile = keyfile;
2748   soap->password = password;
2749   soap->cafile = cafile;
2750   soap->capath = capath;
2751   soap->dhfile = NULL;
2752   soap->rsa = 0;
2753   soap->randfile = randfile;
2754   soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION);
2755   return soap->fsslauth(soap);
2756 }
2757 #endif
2758
2759 /******************************************************************************/
2760 #ifndef PALM_2
2761 SOAP_FMAC1
2762 void
2763 SOAP_FMAC2
2764 soap_ssl_init()
2765 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
2766   if (!ssl_init_done)
2767   { ssl_init_done = 1;
2768     SSL_library_init();
2769 #ifndef WITH_LEAN
2770     SSL_load_error_strings();
2771 #endif
2772     if (!RAND_load_file("/dev/urandom", 1024))
2773     { char buf[1024];
2774       RAND_seed(buf, sizeof(buf));
2775       while (!RAND_status())
2776       { int r = rand();
2777         RAND_seed(&r, sizeof(int));
2778       }
2779     }
2780   }
2781 }
2782 #endif
2783
2784 /******************************************************************************/
2785 #ifndef PALM_1
2786 SOAP_FMAC1
2787 const char *
2788 SOAP_FMAC2
2789 soap_ssl_error(struct soap *soap, int ret)
2790 { int err = SSL_get_error(soap->ssl, ret);
2791   const char *msg = soap_code_str(h_ssl_error_codes, err);
2792   if (msg)
2793     strcpy(soap->msgbuf, msg);
2794   else
2795     return ERR_error_string(err, soap->msgbuf);
2796   if (ERR_peek_error())
2797   { unsigned long r;
2798     strcat(soap->msgbuf, "\n");
2799     while ((r = ERR_get_error()))
2800       ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
2801   } 
2802   else
2803   { switch (ret)
2804     { case 0:
2805         strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
2806         break;
2807       case -1:
2808         sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));  
2809         break;
2810     }
2811   }
2812   return soap->msgbuf;
2813 }
2814 #endif
2815
2816 /******************************************************************************/
2817 #ifndef PALM_1
2818 static int
2819 ssl_password(char *buf, int num, int rwflag, void *userdata)
2820 { if (num < (int)strlen((char*)userdata) + 1)
2821     return 0;
2822   return strlen(strcpy(buf, (char*)userdata));
2823 }
2824 #endif
2825
2826 /******************************************************************************/
2827 /* This callback is included for future references. It should not be deleted
2828 #ifndef PALM_2
2829 static DH *
2830 ssl_tmp_dh(SSL *ssl, int is_export, int keylength)
2831 { static DH *dh512 = NULL;
2832   static DH *dh1024 = NULL;
2833   DH *dh;
2834   switch (keylength)
2835   { case 512:
2836       if (!dh512)
2837       { BIO *bio = BIO_new_file("dh512.pem", "r");
2838         if (bio)
2839         { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2840           BIO_free(bio);
2841           return dh512;
2842         }
2843       }
2844       else
2845         return dh512;
2846     default:
2847       if (!dh1024)
2848       { BIO *bio = BIO_new_file("dh1024.pem", "r");
2849         if (bio)
2850         { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2851           BIO_free(bio);
2852         }
2853       }
2854       dh = dh1024;
2855   }
2856   return dh;
2857 }
2858 #endif
2859 */
2860
2861 /******************************************************************************/
2862 #ifndef PALM_1
2863 static int
2864 ssl_auth_init(struct soap *soap)
2865 { if (!ssl_init_done)
2866     soap_ssl_init();
2867   if (!soap->ctx)
2868   { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
2869       return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
2870   }
2871   if (soap->randfile)
2872   { if (!RAND_load_file(soap->randfile, -1))
2873       return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
2874   }
2875   if (soap->cafile || soap->capath)
2876   { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
2877       return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR);
2878     if (soap->cafile && soap->require_client_auth)
2879       SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
2880   }
2881   if (!SSL_CTX_set_default_verify_paths(soap->ctx))
2882     return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
2883 /* See below */
2884   if (soap->keyfile)
2885   { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
2886       return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
2887     if (soap->password)
2888     { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
2889       SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
2890     }
2891     if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
2892       return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
2893   }
2894 /* Suggested alternative approach to check cafile first before the key file:
2895   if (soap->password)
2896   { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
2897     SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
2898   }
2899   if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
2900   { if (soap->keyfile)
2901     { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
2902         return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR);
2903       if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
2904         return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
2905     }
2906   }
2907 */
2908   if (soap->rsa)
2909   { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
2910     if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
2911     { if (rsa)
2912         RSA_free(rsa);
2913       return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
2914     }
2915     RSA_free(rsa);
2916   }
2917   else if (soap->dhfile)
2918   { DH *dh = 0;
2919     BIO *bio;
2920     bio = BIO_new_file(soap->dhfile, "r");
2921     if (!bio)
2922       return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
2923     dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2924     BIO_free(bio);
2925     if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
2926     { if (dh)
2927         DH_free(dh);
2928       return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
2929     }
2930     DH_free(dh);
2931   }
2932   SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
2933   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);
2934 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
2935   SSL_CTX_set_verify_depth(soap->ctx, 1); 
2936 #else
2937   SSL_CTX_set_verify_depth(soap->ctx, 9); 
2938 #endif  
2939   return SOAP_OK;
2940 }
2941 #endif
2942
2943 /******************************************************************************/
2944 #ifndef PALM_1
2945 static int
2946 ssl_verify_callback(int ok, X509_STORE_CTX *store)
2947 {
2948 #ifdef SOAP_DEBUG
2949   if (!ok) 
2950   { char data[256];
2951     X509 *cert = X509_STORE_CTX_get_current_cert(store);
2952     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)));
2953     X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
2954     fprintf(stderr, "certificate issuer %s\n", data);
2955     X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
2956     fprintf(stderr, "certificate subject %s\n", data);
2957   }
2958 #endif
2959   /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
2960   return ok;
2961 }
2962 #endif
2963
2964 /******************************************************************************/
2965 #ifndef PALM_1
2966 SOAP_FMAC1
2967 int
2968 SOAP_FMAC2
2969 soap_ssl_accept(struct soap *soap)
2970 { BIO *bio;
2971   int i, r;
2972   if (!soap_valid_socket(soap->socket))
2973     return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
2974   if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
2975     return SOAP_INVALID_SOCKET;
2976   if (!soap->ssl)
2977   { soap->ssl = SSL_new(soap->ctx);
2978     if (!soap->ssl)
2979       return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
2980   }
2981   else
2982     SSL_clear(soap->ssl);
2983   soap->imode |= SOAP_ENC_SSL;
2984   soap->omode |= SOAP_ENC_SSL;
2985 #if defined(WIN32)
2986   { u_long nonblocking = 1;
2987     ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking);
2988   }
2989 #elif defined(VXWORKS)
2990   { u_long nonblocking = 1;
2991     ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&nonblocking);
2992   }
2993 #else
2994   fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK);
2995 #endif
2996   bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE);
2997   SSL_set_bio(soap->ssl, bio, bio);
2998   i = 100; /* 100 * 0.1 ms retries */
2999   while ((r = SSL_accept(soap->ssl)) <= 0)
3000   { int err = SSL_get_error(soap->ssl, r);
3001     if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
3002     { struct timeval timeout;
3003       fd_set fd;
3004       if (i-- <= 0)
3005         break;
3006       timeout.tv_sec = 0;
3007       timeout.tv_usec = 100000;
3008 #ifndef WIN32
3009       if ((int)soap->socket > FD_SETSIZE)
3010         return SOAP_FD_EXCEEDED;        /* Hint: MUST increase FD_SETSIZE */
3011 #endif
3012       FD_ZERO(&fd);
3013       FD_SET((SOAP_SOCKET)soap->socket, &fd);
3014       r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
3015       if (r < 0 && soap_socket_errno != SOAP_EINTR)
3016       { soap->errnum = soap_socket_errno;
3017         return SOAP_EOF;
3018       }
3019     }
3020     else
3021     { soap->errnum = err;
3022       break;
3023     }
3024   }
3025 #if defined(WIN32)
3026   { u_long blocking = 0;
3027     ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
3028   }
3029 #elif defined(VXWORKS)
3030   { u_long blocking = 0;
3031     ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&blocking);
3032   }
3033 #else
3034   fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
3035 #endif
3036   if (r <= 0)
3037   { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3038     soap_closesock(soap);
3039     return SOAP_SSL_ERROR;
3040   }
3041   if (soap->require_client_auth)
3042   { X509 *peer;
3043     int err;
3044     if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3045     { soap_closesock(soap);
3046       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);
3047     }
3048     peer = SSL_get_peer_certificate(soap->ssl);
3049     if (!peer)
3050     { soap_closesock(soap);
3051       return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
3052     }
3053     X509_free(peer);
3054   }
3055   return SOAP_OK;
3056 }
3057 #endif
3058
3059 /******************************************************************************/
3060 #endif /* WITH_OPENSSL */
3061
3062 /******************************************************************************/
3063 #ifndef WITH_NOIO
3064 #ifndef PALM_1
3065 static int
3066 tcp_init(struct soap *soap)
3067 { soap->errmode = 1;
3068 #ifdef WIN32
3069   if (tcp_done)
3070     return 0;
3071   else
3072   { WSADATA w;
3073     if (WSAStartup(MAKEWORD(1, 1), &w))
3074       return -1;
3075     tcp_done = 1;
3076   }
3077 #endif
3078   return 0;
3079 }
3080 #endif
3081 #endif
3082
3083 /******************************************************************************/
3084 #ifndef PALM_1
3085 SOAP_FMAC1
3086 void
3087 SOAP_FMAC2
3088 soap_done(struct soap *soap)
3089
3090 #ifdef SOAP_DEBUG
3091   int i;
3092 #endif
3093   if (soap_check_state(soap))
3094     return;
3095   soap_free(soap);
3096   while (soap->clist)
3097   { struct soap_clist *p = soap->clist->next;
3098     SOAP_FREE(soap, soap->clist);
3099     soap->clist = p;
3100   }
3101   soap->keep_alive = 0; /* to force close the socket */
3102   soap_closesock(soap);
3103 #ifdef WITH_COOKIES
3104   soap_free_cookies(soap);
3105 #endif
3106   while (soap->plugins)
3107   { register struct soap_plugin *p = soap->plugins->next;
3108     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
3109     if (soap->plugins->fcopy || soap->state == SOAP_INIT)
3110       soap->plugins->fdelete(soap, soap->plugins);
3111     SOAP_FREE(soap, soap->plugins);
3112     soap->plugins = p;
3113   }
3114   soap->fplugin = fplugin;
3115 #ifndef WITH_NOHTTP
3116   soap->fpost = http_post;
3117   soap->fget = http_get;
3118   soap->fform = NULL;
3119   soap->fposthdr = http_post_header;
3120   soap->fresponse = http_response;
3121   soap->fparse = http_parse;
3122   soap->fparsehdr = http_parse_header;
3123 #endif
3124   soap->fheader = NULL;
3125 #ifndef WITH_NOIO
3126 #ifndef WITH_IPV6
3127   soap->fresolve = tcp_gethost;
3128 #else
3129   soap->fresolve = NULL;
3130 #endif
3131   soap->faccept = tcp_accept;
3132   soap->fopen = tcp_connect;
3133   soap->fclose = tcp_disconnect;
3134   soap->fclosesocket = tcp_closesocket;
3135   soap->fshutdownsocket = tcp_shutdownsocket;
3136   soap->fsend = fsend;
3137   soap->frecv = frecv;
3138   soap->fpoll = soap_poll;
3139 #else
3140   soap->fopen = NULL;
3141   soap->fclose = NULL;
3142   soap->fpoll = NULL;
3143 #endif
3144 #ifndef WITH_LEANER
3145   soap->fprepareinit = NULL;
3146   soap->fpreparesend = NULL;
3147   soap->fpreparerecv = NULL;
3148   soap->fpreparefinal = NULL;
3149 #endif
3150   soap->fseterror = NULL;
3151   soap->fignore = NULL;
3152   soap->fserveloop = NULL;
3153 #ifdef WITH_OPENSSL
3154   if (soap->session)
3155   { SSL_SESSION_free(soap->session);
3156     soap->session = NULL;
3157   }
3158 #endif
3159   if (soap->state == SOAP_INIT)
3160   { if (soap_valid_socket(soap->master))
3161     { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
3162       soap->master = SOAP_INVALID_SOCKET;
3163     }
3164 #ifdef WITH_OPENSSL
3165     if (soap->ctx)
3166     { SSL_CTX_free(soap->ctx);
3167       soap->ctx = NULL;
3168     }
3169 #endif
3170   }
3171 #ifdef SOAP_DEBUG
3172   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
3173   for (i = 0; i < SOAP_MAXLOGS; i++)
3174   { if (soap->logfile[i])
3175     { SOAP_FREE(soap, (void*)soap->logfile[i]);
3176       soap->logfile[i] = NULL;
3177     }
3178     soap_close_logfile(soap, i);
3179   }
3180   soap_free_mht(soap);
3181   soap->state = 0;
3182 #endif
3183 }
3184 #endif
3185
3186 /******************************************************************************/
3187 #ifndef WITH_NOIO
3188 #ifndef PALM_2
3189 SOAP_FMAC1
3190 void
3191 SOAP_FMAC2
3192 soap_cleanup(struct soap *soap)
3193 { soap_done(soap);
3194 #ifdef WIN32
3195   if (!tcp_done)
3196     return;
3197   tcp_done = 0;
3198   WSACleanup();
3199 #endif
3200 }
3201 #endif
3202 #endif
3203
3204 /******************************************************************************/
3205 #ifndef WITH_NOIO
3206 #ifndef PALM_1
3207 static const char*
3208 tcp_error(struct soap *soap)
3209 { register const char *msg = NULL;
3210   switch (soap->errmode)
3211   { case 0:
3212       msg = soap_strerror(soap);
3213       break;
3214     case 1:
3215       msg = "WSAStartup failed";
3216       break;
3217     case 2:
3218     {
3219 #ifndef WITH_LEAN
3220       msg = soap_code_str(h_error_codes, soap->errnum);
3221       if (!msg)
3222 #endif
3223       { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
3224         msg = soap->msgbuf;
3225       }
3226     }
3227   }
3228   return msg;
3229 }
3230 #endif
3231 #endif
3232
3233 /******************************************************************************/
3234 #ifndef WITH_NOHTTP
3235 #ifndef PALM_1
3236 static const char*
3237 http_error(struct soap *soap, int status)
3238 { register const char *msg = SOAP_STR_EOS;
3239 #ifndef WITH_LEAN
3240   msg = soap_code_str(h_http_error_codes, status);
3241   if (!msg)
3242     msg = SOAP_STR_EOS;
3243 #endif
3244   return msg;
3245 }
3246 #endif
3247 #endif
3248
3249 /******************************************************************************/
3250 #ifndef WITH_IPV6
3251 #ifndef WITH_NOIO
3252 #ifndef PALM_1
3253 static int
3254 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
3255 { soap_int32 iadd = -1;
3256   struct hostent hostent, *host = &hostent;
3257 #ifdef VXWORKS
3258   int hostint;
3259   /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3260   iadd = inet_addr((char*)addr);
3261 #else
3262 #if defined(_AIXVERSION_431) || defined(TRU64)
3263   struct hostent_data ht_data;
3264 #endif
3265 #ifdef AS400
3266   iadd = inet_addr((void*)addr);
3267 #else
3268   iadd = inet_addr(addr);
3269 #endif
3270 #endif
3271   if (iadd != -1)
3272   { memcpy(inaddr, &iadd, sizeof(iadd));
3273     return SOAP_OK;
3274   }
3275 #if defined(__GLIBC__)
3276   if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
3277     host = NULL;
3278 #elif defined(_AIXVERSION_431) || defined(TRU64)
3279   memset((void*)&ht_data, 0, sizeof(ht_data));
3280   if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
3281   { host = NULL;
3282     soap->errnum = h_errno;
3283   }
3284 #elif defined(HAVE_GETHOSTBYNAME_R)
3285   host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
3286 #elif defined(VXWORKS)
3287   /* If the DNS resolver library resolvLib has been configured in the vxWorks
3288    * image, a query for the host IP address is sent to the DNS server, if the
3289    * name was not found in the local host table. */
3290   hostint = hostGetByName((char*)addr);
3291   if (hostint == ERROR)
3292   { host = NULL;
3293     soap->errnum = soap_errno; 
3294   }
3295 #else
3296 #ifdef AS400
3297   if (!(host = gethostbyname((void*)addr)))
3298     soap->errnum = h_errno;
3299 #else
3300   if (!(host = gethostbyname(addr)))
3301     soap->errnum = h_errno;
3302 #endif
3303 #endif
3304   if (!host)
3305   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
3306     return SOAP_ERR;
3307   }
3308 #ifdef VXWORKS
3309   inaddr->s_addr = hostint;
3310 #else
3311   memcpy(inaddr, host->h_addr, host->h_length);
3312 #endif
3313   return SOAP_OK;
3314 }
3315 #endif
3316 #endif
3317 #endif
3318
3319 /******************************************************************************/
3320 #ifndef WITH_NOIO
3321 #ifndef PALM_1
3322 static int
3323 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
3324 {
3325 #ifdef WITH_IPV6
3326   struct addrinfo hints, *res, *ressave;
3327   int err;
3328 #endif
3329   register int fd;
3330 #ifndef WITH_LEAN
3331   int len = SOAP_BUFLEN;
3332   int set = 1;
3333 #endif
3334   if (soap_valid_socket(soap->socket))
3335     soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
3336   soap->socket = SOAP_INVALID_SOCKET;
3337   if (tcp_init(soap))
3338   { soap->errnum = 0;
3339     soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
3340     return SOAP_INVALID_SOCKET;
3341   }
3342   soap->errmode = 0;
3343 #ifdef WITH_IPV6
3344   memset((void*)&hints, 0, sizeof(hints));
3345   hints.ai_family = PF_UNSPEC;
3346 #ifdef WITH_UDP
3347   if ((soap->omode & SOAP_IO_UDP))
3348     hints.ai_socktype = SOCK_DGRAM;
3349   else
3350 #endif
3351     hints.ai_socktype = SOCK_STREAM;
3352   soap->errmode = 2;
3353   if (soap->proxy_host)
3354     err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
3355   else
3356     err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
3357   if (err)
3358   { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
3359     return SOAP_INVALID_SOCKET;
3360   }
3361   ressave = res;
3362 again:
3363   fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol);
3364   soap->errmode = 0;
3365 #else
3366 #ifdef WITH_UDP
3367   if ((soap->omode & SOAP_IO_UDP))
3368     fd = (int)socket(AF_INET, SOCK_DGRAM, 0);
3369   else
3370 #endif
3371     fd = (int)socket(AF_INET, SOCK_STREAM, 0);
3372 #endif
3373   if (fd < 0)
3374   { soap->errnum = soap_socket_errno;
3375     soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
3376     return SOAP_INVALID_SOCKET;
3377   }
3378 #ifdef SOCKET_CLOSE_ON_EXEC
3379 #ifdef WIN32
3380 #ifndef UNDER_CE
3381   SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
3382 #endif
3383 #else
3384   fcntl(fd, F_SETFD, 1);
3385 #endif
3386 #endif
3387 #ifndef WITH_LEAN
3388   if (soap->connect_flags == SO_LINGER)
3389   { struct linger linger;
3390     memset((void*)&linger, 0, sizeof(linger));
3391     linger.l_onoff = 1;
3392     linger.l_linger = 0;
3393     if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
3394     { soap->errnum = soap_socket_errno;
3395       soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
3396       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3397       return SOAP_INVALID_SOCKET;
3398     }
3399   }
3400   else if (soap->connect_flags && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
3401   { soap->errnum = soap_socket_errno;
3402     soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
3403     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3404     return SOAP_INVALID_SOCKET;
3405   }
3406   if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
3407   { soap->errnum = soap_socket_errno;
3408     soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
3409     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3410     return SOAP_INVALID_SOCKET;
3411   }
3412   if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
3413   { soap->errnum = soap_socket_errno;
3414     soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3415     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3416     return SOAP_INVALID_SOCKET;
3417   }
3418   if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
3419   { soap->errnum = soap_socket_errno;
3420     soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3421     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3422     return SOAP_INVALID_SOCKET;
3423   }
3424 #ifdef TCP_NODELAY
3425   if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
3426   { soap->errnum = soap_socket_errno;
3427     soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
3428     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3429     return SOAP_INVALID_SOCKET;
3430   }
3431 #endif
3432 #endif
3433   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
3434 #ifndef WITH_IPV6
3435   soap->peerlen = sizeof(soap->peer);
3436   memset((void*)&soap->peer, 0, sizeof(soap->peer));
3437   soap->peer.sin_family = AF_INET;
3438   soap->errmode = 2;
3439   if (soap->proxy_host)
3440   { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
3441     { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3442       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3443       return SOAP_INVALID_SOCKET;
3444     }
3445     soap->peer.sin_port = htons((short)soap->proxy_port);
3446   }
3447   else
3448   { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
3449     { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3450       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3451       return SOAP_INVALID_SOCKET;
3452     }
3453     soap->peer.sin_port = htons((short)port);
3454   }
3455   soap->errmode = 0;
3456   if ((soap->omode & SOAP_IO_UDP))
3457     return fd;
3458 #endif
3459 #ifndef WITH_LEAN
3460   if (soap->connect_timeout)
3461 #if defined(WIN32)
3462   { u_long nonblocking = 1;
3463     ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
3464   }
3465 #elif defined(VXWORKS)
3466   { u_long nonblocking = 1;
3467     ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */
3468   }
3469 #else
3470     fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
3471 #endif
3472   else
3473 #if defined(WIN32)
3474   { u_long blocking = 0;
3475     ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
3476   }
3477 #elif defined(VXWORKS)
3478   { u_long blocking = 0;
3479     ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
3480   }
3481 #else
3482     fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
3483 #endif
3484 #endif
3485   for (;;)
3486   { 
3487 #ifdef WITH_IPV6
3488     if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen))
3489 #else
3490     if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
3491 #endif
3492     { 
3493 #ifndef WITH_LEAN
3494       if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK))
3495       { struct timeval timeout;
3496         SOAP_SOCKLEN_T k;
3497         fd_set fds;
3498         if (soap->connect_timeout > 0)
3499         { timeout.tv_sec = soap->connect_timeout;
3500           timeout.tv_usec = 0;
3501         }
3502         else
3503         { timeout.tv_sec = -soap->connect_timeout/1000000;
3504           timeout.tv_usec = -soap->connect_timeout%1000000;
3505         }
3506 #ifndef WIN32
3507         if ((int)soap->socket > FD_SETSIZE)
3508         { soap->error = SOAP_FD_EXCEEDED;
3509           return SOAP_INVALID_SOCKET;   /* Hint: MUST increase FD_SETSIZE */
3510         }
3511 #endif
3512         FD_ZERO(&fds);
3513         FD_SET((SOAP_SOCKET)fd, &fds);
3514         for (;;)
3515         { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout);
3516           if (r > 0)
3517             break;
3518           if (!r)
3519           { soap->errnum = 0;
3520             DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
3521             soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3522             soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3523             return SOAP_INVALID_SOCKET;
3524           }
3525           if (soap_socket_errno != SOAP_EINTR)
3526           { soap->errnum = soap_socket_errno;
3527             DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3528             soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3529             soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3530             return SOAP_INVALID_SOCKET;
3531           }
3532         }
3533         k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
3534         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 */
3535           break;
3536         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3537         soap->errnum = soap_socket_errno;
3538         soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3539         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3540         return SOAP_INVALID_SOCKET;
3541       }
3542       else
3543 #endif
3544 #ifdef WITH_IPV6
3545       if (res->ai_next)
3546       { res = res->ai_next;
3547         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3548         goto again;
3549       }
3550       else
3551 #endif
3552       if (soap_socket_errno != SOAP_EINTR)
3553       { soap->errnum = soap_socket_errno;
3554         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3555         soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3556         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3557         return SOAP_INVALID_SOCKET;
3558       }
3559     }  
3560     else
3561       break;
3562   }
3563 #ifdef WITH_IPV6
3564   soap->peerlen = 0; /* IPv6: already connected so use send() */
3565   freeaddrinfo(ressave);
3566 #endif
3567 #ifndef WITH_LEAN
3568   if (soap->connect_timeout)
3569 #if defined(WIN32)
3570   { u_long blocking = 0;
3571     ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
3572   }
3573 #elif defined(VXWORKS)
3574   { u_long blocking = 0;
3575     ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
3576   }
3577 #else
3578     fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
3579 #endif
3580 #endif
3581   soap->socket = fd;
3582   soap->imode &= ~SOAP_ENC_SSL;
3583   soap->omode &= ~SOAP_ENC_SSL;
3584   if (!soap_tag_cmp(endpoint, "https:*"))
3585   {
3586 #ifdef WITH_OPENSSL
3587     BIO *bio;
3588     int r;
3589     if (soap->proxy_host)
3590     { unsigned int k = soap->omode; /* make sure we only parse HTTP */
3591       size_t n = soap->count; /* save the content length */
3592       char *userid, *passwd;
3593       soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
3594       soap->omode |= SOAP_IO_BUFFER;
3595       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n"));
3596       sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version);
3597       if (soap_begin_send(soap)
3598        || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
3599       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3600         return SOAP_INVALID_SOCKET;
3601       }
3602 #ifndef WITH_LEAN
3603       if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
3604       { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
3605         strcpy(soap->tmpbuf, "Basic ");
3606         soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
3607         if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
3608         { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3609           return soap->error;
3610         }
3611       }
3612 #endif
3613       if ((soap->error = soap->fposthdr(soap, NULL, NULL))
3614        || soap_flush(soap))
3615       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3616         return SOAP_INVALID_SOCKET;
3617       }
3618       soap->omode = k;
3619       k = soap->imode;
3620       soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
3621       userid = soap->userid; /* preserve */
3622       passwd = soap->passwd; /* preserve */
3623       if ((soap->error = soap->fparse(soap)))
3624       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3625         return SOAP_INVALID_SOCKET;
3626       }
3627       soap->userid = userid; /* restore */
3628       soap->passwd = passwd; /* restore */
3629       soap->imode = k; /* restore */
3630       soap->count = n; /* restore */
3631       if (soap_begin_send(soap))
3632       { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3633         return SOAP_INVALID_SOCKET;
3634       }
3635     }
3636     if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
3637     { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
3638       soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3639       return SOAP_INVALID_SOCKET;
3640     }
3641     soap->ssl = SSL_new(soap->ctx);
3642     if (!soap->ssl)
3643     { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3644       soap->error = SOAP_SSL_ERROR;
3645       return SOAP_INVALID_SOCKET;
3646     }
3647     if (soap->session)
3648     { if (!strcmp(soap->session_host, host) && soap->session_port == port)
3649         SSL_set_session(soap->ssl, soap->session);
3650       SSL_SESSION_free(soap->session);
3651       soap->session = NULL;
3652     }
3653     soap->imode |= SOAP_ENC_SSL;
3654     soap->omode |= SOAP_ENC_SSL;
3655     bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE);
3656     SSL_set_bio(soap->ssl, bio, bio);
3657 #ifndef WITH_LEAN
3658     if (soap->connect_timeout)
3659 #if defined(WIN32)
3660     { u_long nonblocking = 1;
3661       ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
3662     }
3663 #elif defined(VXWORKS)
3664     { u_long nonblocking = 1;
3665       ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking));
3666     }
3667 #else
3668       fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
3669 #endif
3670 #endif
3671     for (;;)
3672     { if ((r = SSL_connect(soap->ssl)) <= 0)
3673       { int err = SSL_get_error(soap->ssl, r);
3674         if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3675         { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR);
3676           soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3677           return SOAP_INVALID_SOCKET;
3678         }
3679         if (soap->connect_timeout)
3680         { struct timeval timeout;
3681           fd_set fds;
3682           if (soap->connect_timeout > 0)
3683           { timeout.tv_sec = soap->connect_timeout;
3684             timeout.tv_usec = 0;
3685           }
3686           else
3687           { timeout.tv_sec = -soap->connect_timeout/1000000;
3688             timeout.tv_usec = -soap->connect_timeout%1000000;
3689           }
3690 #ifndef WIN32
3691           if ((int)soap->socket > FD_SETSIZE)
3692           { soap->error = SOAP_FD_EXCEEDED;
3693             return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
3694           }
3695 #endif
3696           FD_ZERO(&fds);
3697           FD_SET((SOAP_SOCKET)fd, &fds);
3698           for (;;)
3699           { int r = select((SOAP_SOCKET)(fd + 1), &fds, NULL, &fds, &timeout);
3700             if (r > 0)
3701               break;
3702             if (!r)
3703             { soap->errnum = 0;
3704               DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
3705               soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3706               soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3707               return SOAP_INVALID_SOCKET;
3708             }
3709           }
3710           continue;
3711         }
3712       }
3713       break;
3714     }
3715 #ifndef WITH_LEAN
3716     if (soap->connect_timeout)
3717 #ifdef WIN32
3718     { u_long blocking = 0;
3719       ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
3720     }
3721 #elif defined(VXWORKS)
3722     { u_long blocking = 0;
3723       ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
3724     }
3725 #else
3726       fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
3727 #endif
3728 #endif
3729     if (soap->require_server_auth)
3730     { X509 *peer;
3731       X509_NAME *subj;
3732       int ext_count;
3733       int err;
3734       int ok = 0;
3735       if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3736       { 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);
3737         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3738         return SOAP_INVALID_SOCKET;
3739       }
3740       peer = SSL_get_peer_certificate(soap->ssl);
3741       if (!peer)
3742       { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
3743         soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3744         return SOAP_INVALID_SOCKET;
3745       }
3746       ext_count = X509_get_ext_count(peer);
3747       if (ext_count > 0)
3748       { int i;
3749         for (i = 0; i < ext_count; i++)
3750         { X509_EXTENSION *ext = X509_get_ext(peer, i);
3751           const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
3752           if (!strcmp(ext_str, "subjectAltName"))
3753           { int j;
3754             STACK_OF(CONF_VALUE) *val;
3755             X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD*>(X509V3_EXT_get(ext));
3756             if (!meth)
3757               break;
3758 #ifdef WIN32
3759             val = meth->i2v(meth, meth->d2i(NULL, (const unsigned char**)&ext->value->data, ext->value->length), NULL);
3760 #else
3761             /*val = meth->i2v(meth, meth->d2i(NULL, (unsigned char**)&ext->value->data, ext->value->length), NULL);*/
3762             val = meth->i2v(meth, meth->d2i(NULL, (const unsigned char**)&ext->value->data, ext->value->length), NULL);
3763 #endif
3764             for (j = 0; j < sk_CONF_VALUE_num(val); j++)
3765             { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
3766               if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
3767               { ok = 1;
3768                 break;
3769               }
3770             }
3771           }
3772           if (ok)
3773             break;
3774         }
3775       }
3776       if (!ok && (subj = X509_get_subject_name(peer)))
3777       { X509_NAME_get_text_by_NID(subj, NID_commonName, soap->msgbuf, sizeof(soap->msgbuf));
3778         if (soap_tag_cmp(soap->msgbuf, host))
3779         { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
3780           soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3781           X509_free(peer);
3782           return SOAP_INVALID_SOCKET;
3783         }
3784       }
3785       X509_free(peer);
3786     }
3787 #else
3788     soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3789     soap->error = SOAP_SSL_ERROR;
3790     return SOAP_INVALID_SOCKET;
3791 #endif
3792   }
3793   return fd;
3794 }
3795 #endif
3796 #endif
3797
3798 /******************************************************************************/
3799 #ifndef WITH_NOIO
3800 #ifndef PALM_1
3801 SOAP_FMAC1
3802 int
3803 SOAP_FMAC2
3804 soap_bind(struct soap *soap, const char *host, int port, int backlog)
3805 {
3806 #ifdef WITH_IPV6
3807   struct addrinfo *addrinfo = NULL;
3808   struct addrinfo hints;
3809   struct addrinfo res;
3810   int err;
3811 #endif
3812 #ifndef WITH_LEAN
3813   int len = SOAP_BUFLEN;
3814   int set = 1;
3815 #endif
3816   if (soap_valid_socket(soap->master))
3817   { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
3818     soap->master = SOAP_INVALID_SOCKET;
3819   }
3820   soap->socket = SOAP_INVALID_SOCKET;
3821   soap->errmode = 1;
3822   if (tcp_init(soap))
3823   { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
3824     return SOAP_INVALID_SOCKET;
3825   }
3826 #ifdef WITH_IPV6
3827   memset((void*)&hints, 0, sizeof(hints));
3828   hints.ai_family = PF_UNSPEC;
3829 #ifdef WITH_UDP
3830   if ((soap->omode & SOAP_IO_UDP))
3831     hints.ai_socktype = SOCK_DGRAM;
3832   else
3833 #endif
3834     hints.ai_socktype = SOCK_STREAM;
3835   hints.ai_flags = AI_PASSIVE;
3836   soap->errmode = 2;
3837   err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
3838   if (addrinfo)
3839   { res = *addrinfo;
3840     soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr);
3841     soap->peerlen = addrinfo->ai_addrlen;
3842     res.ai_addr = (struct sockaddr*)&soap->peer;
3843     res.ai_addrlen = soap->peerlen;
3844     freeaddrinfo(addrinfo);
3845   }
3846   if (err)
3847   { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
3848     return SOAP_INVALID_SOCKET;
3849   }
3850   soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol);
3851 #else
3852 #ifdef WITH_UDP
3853   if ((soap->omode & SOAP_IO_UDP))
3854     soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
3855   else
3856 #endif
3857     soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
3858 #endif
3859   soap->errmode = 0;
3860   if (!soap_valid_socket(soap->master))
3861   { soap->errnum = soap_socket_errno;
3862     soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
3863     return SOAP_INVALID_SOCKET;
3864   }
3865 #ifdef WITH_UDP
3866   if ((soap->omode & SOAP_IO_UDP))
3867     soap->socket = soap->master;
3868 #endif
3869 #ifdef SOCKET_CLOSE_ON_EXEC
3870 #ifdef WIN32
3871 #ifndef UNDER_CE
3872   SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
3873 #endif
3874 #else
3875   fcntl(soap->master, F_SETFD, 1);
3876 #endif
3877 #endif
3878 #ifndef WITH_LEAN
3879   if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
3880   { soap->errnum = soap_socket_errno;
3881     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
3882     return SOAP_INVALID_SOCKET;
3883   }
3884   if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
3885   { soap->errnum = soap_socket_errno;
3886     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
3887     return SOAP_INVALID_SOCKET;
3888   }
3889   if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
3890   { soap->errnum = soap_socket_errno;
3891     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
3892     return SOAP_INVALID_SOCKET;
3893   }
3894   if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
3895   { soap->errnum = soap_socket_errno;
3896     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
3897     return SOAP_INVALID_SOCKET;
3898   }
3899 #ifdef TCP_NODELAY
3900   if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
3901   { soap->errnum = soap_socket_errno;
3902     soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
3903     return SOAP_INVALID_SOCKET;
3904   }
3905 #endif
3906 #endif
3907 #ifdef WITH_IPV6
3908   soap->errmode = 0;
3909   if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen))
3910   { soap->errnum = soap_socket_errno;
3911     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
3912     soap_closesock(soap);
3913     soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
3914     return SOAP_INVALID_SOCKET;
3915   }  
3916 #else
3917   soap->peerlen = sizeof(soap->peer);
3918   memset((void*)&soap->peer, 0, sizeof(soap->peer));
3919   soap->peer.sin_family = AF_INET;
3920   soap->errmode = 2;
3921   if (host)
3922   { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
3923     { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
3924       return SOAP_INVALID_SOCKET;
3925     }
3926   }
3927   else
3928     soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
3929   soap->peer.sin_port = htons((short)port);
3930   soap->errmode = 0;
3931   if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen))
3932   { soap->errnum = soap_socket_errno;
3933     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
3934     soap_closesock(soap);
3935     soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
3936     return SOAP_INVALID_SOCKET;
3937   }
3938 #endif
3939   if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog))
3940   { soap->errnum = soap_socket_errno;
3941     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
3942     soap_closesock(soap);
3943     soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
3944     return SOAP_INVALID_SOCKET;
3945   }  
3946   return soap->master;
3947 }
3948 #endif
3949 #endif
3950
3951 /******************************************************************************/
3952 #ifndef WITH_NOIO
3953 #ifndef PALM_1
3954 SOAP_FMAC1
3955 int
3956 SOAP_FMAC2
3957 soap_poll(struct soap *soap)
3958
3959 #ifndef WITH_LEAN
3960   struct timeval timeout;
3961   fd_set rfd, sfd, xfd;
3962   int r;
3963   timeout.tv_sec = 0;
3964   timeout.tv_usec = 0;
3965 #ifndef WIN32
3966   if ((int)soap->socket > FD_SETSIZE)
3967     return SOAP_FD_EXCEEDED;    /* Hint: MUST increase FD_SETSIZE */
3968 #endif
3969   FD_ZERO(&rfd);
3970   FD_ZERO(&sfd);
3971   FD_ZERO(&xfd);
3972   if (soap_valid_socket(soap->socket))
3973   { FD_SET((SOAP_SOCKET)soap->socket, &rfd);
3974     FD_SET((SOAP_SOCKET)soap->socket, &sfd);
3975     FD_SET((SOAP_SOCKET)soap->socket, &xfd);
3976     r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout);
3977     if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd))
3978       r = -1;
3979   }
3980   else if (soap_valid_socket(soap->master))
3981   { FD_SET((SOAP_SOCKET)soap->master, &sfd);
3982     r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout);
3983   }
3984   else
3985     return SOAP_OK;
3986   if (r > 0)
3987   {
3988 #ifdef WITH_OPENSSL
3989     if (soap->imode & SOAP_ENC_SSL)
3990     {
3991       if (soap_valid_socket(soap->socket)
3992        && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
3993        && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
3994         || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
3995         return SOAP_OK;
3996     }
3997     else
3998 #endif
3999       if (soap_valid_socket(soap->socket)
4000        && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
4001        && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
4002         || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
4003         return SOAP_OK;
4004   }
4005   else if (r < 0)
4006   { soap->errnum = soap_socket_errno;
4007     if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR)
4008     { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
4009       return soap->error = SOAP_TCP_ERROR;
4010     }
4011   }
4012   else
4013     soap->errnum = 0;
4014   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
4015   return SOAP_EOF;
4016 #else
4017   return SOAP_OK;
4018 #endif
4019 }
4020 #endif
4021 #endif
4022
4023 /******************************************************************************/
4024 #ifndef WITH_NOIO
4025 #ifndef PALM_1
4026 static int
4027 tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n)
4028 { int fd;
4029   fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n);      /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4030 #ifdef SOCKET_CLOSE_ON_EXEC
4031 #ifdef WIN32
4032 #ifndef UNDER_CE
4033   SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
4034 #endif
4035 #else
4036   fcntl(fd, F_SETFD, FD_CLOEXEC);
4037 #endif
4038 #endif
4039   return fd;
4040 }
4041 #endif
4042 #endif
4043
4044 /******************************************************************************/
4045 #ifndef WITH_NOIO
4046 #ifndef PALM_1
4047 SOAP_FMAC1
4048 int
4049 SOAP_FMAC2
4050 soap_accept(struct soap *soap)
4051 { int n = (int)sizeof(soap->peer);
4052 #ifndef WITH_LEAN
4053   int len = SOAP_BUFLEN;
4054   int set = 1;
4055 #endif
4056   soap->error = SOAP_OK;
4057 #ifdef WITH_UDP
4058   if ((soap->omode & SOAP_IO_UDP))
4059     return soap->socket = soap->master;
4060 #endif
4061   memset((void*)&soap->peer, 0, sizeof(soap->peer));
4062   soap->socket = SOAP_INVALID_SOCKET;
4063   soap->errmode = 0;
4064   soap->keep_alive = 0;
4065   if (soap_valid_socket(soap->master))
4066   { for (;;)
4067     { 
4068 #ifndef WITH_LEAN
4069       if (soap->accept_timeout)
4070       { struct timeval timeout;
4071         fd_set fd;
4072         if (soap->accept_timeout > 0)
4073         { timeout.tv_sec = soap->accept_timeout;
4074           timeout.tv_usec = 0;
4075         }
4076         else
4077         { timeout.tv_sec = -soap->accept_timeout/1000000;
4078           timeout.tv_usec = -soap->accept_timeout%1000000;
4079         }
4080 #ifndef WIN32
4081         if ((int)soap->socket > FD_SETSIZE)
4082         { soap->error = SOAP_FD_EXCEEDED;
4083           return SOAP_INVALID_SOCKET;   /* Hint: MUST increase FD_SETSIZE */
4084         }
4085 #endif
4086         FD_ZERO(&fd);
4087         FD_SET((SOAP_SOCKET)soap->master, &fd);
4088         for (;;)
4089         { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout);
4090           if (r > 0)
4091             break;
4092           if (!r)
4093           { soap->errnum = 0;
4094             soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
4095             return SOAP_INVALID_SOCKET;
4096           }
4097           if (soap_socket_errno != SOAP_EINTR)
4098           { soap->errnum = soap_socket_errno;
4099             soap_closesock(soap);
4100             soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4101             return SOAP_INVALID_SOCKET;
4102           }
4103         }
4104 #if defined(WIN32)
4105         { u_long nonblocking = 1;
4106           ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking);
4107         }
4108 #elif defined(VXWORKS)
4109         { u_long nonblocking = 1;
4110           ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&nonblocking));
4111         }
4112 #else
4113         fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK);
4114 #endif
4115       }
4116       else
4117 #if defined(WIN32)
4118       { u_long blocking = 0;
4119         ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
4120       }
4121 #elif defined(VXWORKS)
4122       { u_long blocking = 0;
4123         ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking));
4124       }
4125 #else
4126         fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
4127 #endif
4128 #endif
4129       soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
4130       soap->peerlen = (size_t)n;
4131       if (soap_valid_socket(soap->socket))
4132       {
4133 #ifdef WITH_IPV6
4134 /* Use soap->host to store the numeric form of the remote host */
4135         getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); 
4136         DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
4137         soap->ip = 0; /* info stored in soap->peer and soap->host */
4138         soap->port = 0; /* info stored in soap->peer and soap->host */
4139 #else
4140         soap->ip = ntohl(soap->peer.sin_addr.s_addr);
4141         soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
4142         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));
4143 #endif
4144 #ifndef WITH_LEAN
4145         if (soap->accept_flags == SO_LINGER)
4146         { struct linger linger;
4147           memset((void*)&linger, 0, sizeof(linger));
4148           linger.l_onoff = 1;
4149           linger.l_linger = 0;
4150           if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
4151           { soap->errnum = soap_socket_errno;
4152             soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
4153             soap_closesock(soap);
4154             return SOAP_INVALID_SOCKET;
4155           }
4156         }
4157         else if (soap->accept_flags && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
4158         { soap->errnum = soap_socket_errno;
4159           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
4160           soap_closesock(soap);
4161           return SOAP_INVALID_SOCKET;
4162         }
4163         if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4164         { soap->errnum = soap_socket_errno;
4165           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
4166           soap_closesock(soap);
4167           return SOAP_INVALID_SOCKET;
4168         }
4169         if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4170         { soap->errnum = soap_socket_errno;
4171           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
4172           soap_closesock(soap);
4173           return SOAP_INVALID_SOCKET;
4174         }
4175         if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4176         { soap->errnum = soap_socket_errno;
4177           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
4178           soap_closesock(soap);
4179           return SOAP_INVALID_SOCKET;
4180         }
4181 #ifdef TCP_NODELAY
4182         if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4183         { soap->errnum = soap_socket_errno;
4184           soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
4185           soap_closesock(soap);
4186           return SOAP_INVALID_SOCKET;
4187         }
4188 #endif
4189 #endif
4190         if (soap->accept_timeout)
4191         {
4192 #if defined(WIN32)
4193           u_long blocking = 0;
4194           ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
4195           ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
4196 #elif defined(VXWORKS)
4197           u_long blocking = 0;
4198           ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking));
4199           ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&blocking));
4200 #elif defined(PALM)
4201           fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK);
4202           fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK);
4203 #elif defined(SYMBIAN)
4204           long blocking = 0;
4205           ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking);
4206 #else
4207           fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
4208           fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
4209 #endif
4210         }
4211         soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
4212         return soap->socket;
4213       }
4214       if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
4215       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
4216         soap->errnum = soap_socket_errno;
4217         soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4218         soap_closesock(soap);
4219         return SOAP_INVALID_SOCKET;
4220       }
4221     }
4222   }
4223   else
4224   { soap->errnum = 0;
4225     soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
4226     return SOAP_INVALID_SOCKET;
4227   }
4228 }
4229 #endif
4230 #endif
4231
4232 /******************************************************************************/
4233 #ifndef WITH_NOIO
4234 #ifndef PALM_1
4235 static int
4236 tcp_disconnect(struct soap *soap)
4237 {
4238 #ifdef WITH_OPENSSL
4239   if (soap->ssl)
4240   { int r, s = 0;
4241     if (soap->session)
4242       SSL_SESSION_free(soap->session);
4243     if (*soap->host)
4244     { soap->session = SSL_get1_session(soap->ssl);
4245       if (soap->session)
4246       { strcpy(soap->session_host, soap->host);
4247         soap->session_port = soap->port;
4248       }
4249     }
4250     r = SSL_shutdown(soap->ssl);
4251     if (r != 1)
4252     { s = ERR_get_error();
4253       if (s)
4254       { if (soap_valid_socket(soap->socket))
4255         { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1);
4256           soap->socket = SOAP_INVALID_SOCKET;
4257         }
4258         r = SSL_shutdown(soap->ssl);
4259       }
4260     }
4261     DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
4262     SSL_free(soap->ssl);
4263     soap->ssl = NULL;
4264     if (s)
4265       return SOAP_SSL_ERROR;
4266     ERR_remove_state(0);
4267   }
4268 #endif
4269   if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4270   { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2);
4271     soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
4272     soap->socket = SOAP_INVALID_SOCKET;
4273   }
4274   return SOAP_OK;
4275 }
4276 #endif
4277 #endif
4278
4279 /******************************************************************************/
4280 #ifndef WITH_NOIO
4281 #ifndef PALM_1
4282 static int
4283 tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
4284 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd));
4285   return soap_closesocket(fd);
4286 }
4287 #endif
4288 #endif
4289
4290 /******************************************************************************/
4291 #ifndef WITH_NOIO
4292 #ifndef PALM_1
4293 static int
4294 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
4295 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how));
4296   return shutdown(fd, how);
4297 }
4298 #endif
4299 #endif
4300
4301 /******************************************************************************/
4302 #ifndef PALM_1
4303 SOAP_FMAC1
4304 int
4305 SOAP_FMAC2
4306 soap_closesock(struct soap *soap)
4307 { register int status = soap->error;
4308   if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
4309   { if (soap->fclose && (soap->error = soap->fclose(soap)))
4310       return soap->error;
4311     soap->keep_alive = 0;
4312   }
4313 #ifdef WITH_ZLIB
4314   if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
4315     deflateEnd(&soap->d_stream);
4316   else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
4317     inflateEnd(&soap->d_stream);
4318   soap->zlib_state = SOAP_ZLIB_NONE;
4319 #endif
4320   return soap->error = status;
4321 }
4322 #endif
4323
4324 /******************************************************************************/
4325 #ifndef WITH_NOIDREF
4326 #ifndef PALM_2
4327 SOAP_FMAC1
4328 size_t
4329 SOAP_FMAC2
4330 soap_hash(register const char *s)
4331 { register size_t h = 0;
4332   while (*s)
4333     h = 65599*h + *s++;
4334   return h % SOAP_IDHASH;
4335 }
4336 #endif
4337 #endif
4338
4339 /******************************************************************************/
4340 #ifndef WITH_NOIDREF
4341 #ifndef PALM_1
4342 static void
4343 soap_init_pht(struct soap *soap)
4344 { register int i;
4345   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n"));
4346   soap->pblk = NULL;
4347   soap->pidx = 0;
4348   for (i = 0; i < (int)SOAP_PTRHASH; i++)
4349     soap->pht[i] = NULL;
4350 }
4351 #endif
4352 #endif
4353
4354 /******************************************************************************/
4355 #ifndef PALM_1
4356 SOAP_FMAC1
4357 struct soap*
4358 SOAP_FMAC2
4359 soap_new1(soap_mode mode)
4360 { return soap_new2(mode, mode);
4361 }
4362 #endif
4363
4364 /******************************************************************************/
4365 #ifndef PALM_1
4366 SOAP_FMAC1
4367 struct soap*
4368 SOAP_FMAC2
4369 soap_new()
4370 { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
4371 }
4372 #endif
4373
4374 /******************************************************************************/
4375 #ifndef PALM_1
4376 SOAP_FMAC1
4377 struct soap*
4378 SOAP_FMAC2
4379 soap_new2(soap_mode imode, soap_mode omode)
4380 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
4381   if (soap)
4382     soap_init2(soap, imode, omode);
4383   return soap;
4384 }
4385 #endif
4386
4387 /******************************************************************************/
4388 #ifndef PALM_1
4389 SOAP_FMAC1
4390 void
4391 SOAP_FMAC2
4392 soap_del(struct soap *soap)
4393 { free(soap);
4394 }
4395 #endif
4396
4397 /******************************************************************************/
4398 #ifndef WITH_NOIDREF
4399 #ifndef PALM_1
4400 static void
4401 soap_free_pht(struct soap *soap)
4402 { register struct soap_pblk *pb, *next;
4403   register int i;
4404   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
4405   for (pb = soap->pblk; pb; pb = next)
4406   { next = pb->next;
4407     SOAP_FREE(soap, pb);
4408   }
4409   soap->pblk = NULL;
4410   soap->pidx = 0;
4411   for (i = 0; i < (int)SOAP_PTRHASH; i++)
4412     soap->pht[i] = NULL;
4413 }
4414 #endif
4415 #endif
4416
4417 /******************************************************************************/
4418 #ifndef WITH_NOIDREF
4419 #ifndef PALM_2
4420 SOAP_FMAC1
4421 int
4422 SOAP_FMAC2
4423 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
4424 { register int i;
4425   struct soap_plist *pp;
4426   if (soap->version != 1)
4427     soap->encoding = 1;
4428   if (a)
4429     i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
4430   else
4431     i = soap_pointer_lookup(soap, p, type, &pp);
4432   if (i)
4433   { if (soap_is_embedded(soap, pp)
4434      || soap_is_single(soap, pp))
4435       return 0;
4436     soap_set_embedded(soap, pp);
4437   }
4438   return i;
4439 }
4440 #endif
4441 #endif
4442
4443 /******************************************************************************/
4444 #ifndef WITH_NOIDREF
4445 #ifndef PALM_2
4446 SOAP_FMAC1
4447 int
4448 SOAP_FMAC2
4449 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
4450 { register struct soap_plist *pp;
4451   *ppp = NULL;
4452   if (p)
4453   { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
4454     { if (pp->ptr == p && pp->type == type)
4455       { *ppp = pp;
4456         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
4457         return pp->id;
4458       }
4459     }
4460   }
4461   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
4462   return 0;
4463 }
4464 #endif
4465 #endif
4466
4467 /******************************************************************************/
4468 #ifndef WITH_NOIDREF
4469 #ifndef PALM_2
4470 SOAP_FMAC1
4471 int
4472 SOAP_FMAC2
4473 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
4474 { register int h;
4475   register struct soap_plist *pp;
4476   if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
4477   { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
4478     if (!pb)
4479     { soap->error = SOAP_EOM;
4480       return 0;
4481     }
4482     pb->next = soap->pblk;
4483     soap->pblk = pb;
4484     soap->pidx = 0;
4485   }
4486   *ppp = pp = &soap->pblk->plist[soap->pidx++];
4487   if (a)
4488     h = soap_hash_ptr(a->__ptr);
4489   else
4490     h = soap_hash_ptr(p);
4491   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));
4492   pp->next = soap->pht[h];
4493   pp->type = type;
4494   pp->mark1 = 0;
4495   pp->mark2 = 0;
4496   pp->ptr = p;
4497   pp->array = a;
4498   soap->pht[h] = pp;
4499   pp->id = ++soap->idnum;
4500   return pp->id;
4501 }
4502 #endif
4503 #endif
4504
4505 /******************************************************************************/
4506 #ifndef WITH_NOIDREF
4507 #ifndef PALM_2
4508 SOAP_FMAC1
4509 int
4510 SOAP_FMAC2
4511 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
4512 { register struct soap_plist *pp;
4513   *ppp = NULL;
4514   if (!p || !a->__ptr)
4515     return 0;
4516   for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
4517   { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
4518     { register int i;
4519       for (i = 0; i < n; i++)
4520         if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
4521           break;
4522       if (i == n)
4523       { *ppp = pp;
4524         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
4525         return pp->id;
4526       }
4527     }
4528   }
4529   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
4530   return 0;
4531 }
4532 #endif
4533 #endif
4534
4535 /******************************************************************************/
4536 #ifndef PALM_1
4537 SOAP_FMAC1
4538 int
4539 SOAP_FMAC2
4540 soap_begin_count(struct soap *soap)
4541 {
4542 #ifndef WITH_LEANER
4543   if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
4544     soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
4545   else
4546 #endif
4547   { soap->mode = soap->omode;
4548     if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
4549      || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
4550 #ifndef WITH_LEANER
4551       && !soap->fpreparesend
4552 #endif
4553       ))
4554       soap->mode &= ~SOAP_IO_LENGTH;
4555     else
4556       soap->mode |= SOAP_IO_LENGTH;
4557   }
4558 #ifdef WITH_ZLIB
4559   if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
4560   { if (!(soap->mode & SOAP_ENC_DIME))
4561       soap->mode &= ~SOAP_IO_LENGTH;
4562     if (soap->mode & SOAP_ENC_XML)
4563       soap->mode |= SOAP_IO_BUFFER;
4564     else
4565       soap->mode |= SOAP_IO_STORE;
4566   }
4567 #endif
4568   if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
4569     soap->mode |= SOAP_XML_TREE;
4570 #ifndef WITH_LEANER
4571   if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
4572     soap->mode |= SOAP_ENC_MIME;
4573   else
4574     soap->mode &= ~SOAP_ENC_MTOM;
4575   if (soap->mode & SOAP_ENC_MIME)
4576     soap_select_mime_boundary(soap);
4577   soap->dime.list = soap->dime.last;    /* keep track of last DIME attachment */
4578 #endif
4579   soap->count = 0;
4580   soap->ns = 0;
4581   soap->null = 0;
4582   soap->position = 0;
4583   soap->mustUnderstand = 0;
4584   soap->encoding = 0;
4585   soap->part = SOAP_BEGIN;
4586   soap->idnum = 0;
4587   soap_clr_attr(soap);
4588   soap_set_local_namespaces(soap);
4589   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
4590 #ifndef WITH_LEANER
4591   soap->dime.count = 0; /* count # of attachments */
4592   soap->dime.size = 0; /* accumulate total size of attachments */
4593   if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
4594     return soap->error = soap->fprepareinit(soap);   
4595 #endif
4596   return SOAP_OK;
4597 }
4598 #endif
4599
4600 /******************************************************************************/
4601 #ifndef PALM_1
4602 SOAP_FMAC1
4603 int
4604 SOAP_FMAC2
4605 soap_end_count(struct soap *soap)
4606
4607 #ifndef WITH_LEANER
4608   if (soap->fpreparefinal)
4609     return soap->error = soap->fpreparefinal(soap);
4610 #endif
4611   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
4612   return SOAP_OK;
4613 }
4614 #endif
4615
4616 /******************************************************************************/
4617 #ifndef PALM_1
4618 SOAP_FMAC1
4619 int
4620 SOAP_FMAC2
4621 soap_begin_send(struct soap *soap)
4622 { soap->error = SOAP_OK;
4623   soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
4624 #ifdef WITH_ZLIB
4625   if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
4626   { if (soap->mode & SOAP_ENC_XML)
4627       soap->mode |= SOAP_IO_BUFFER;
4628     else
4629       soap->mode |= SOAP_IO_STORE;
4630   }
4631 #endif
4632 #ifdef WITH_UDP
4633   if ((soap->mode & SOAP_IO_UDP))
4634   { soap->mode |= SOAP_ENC_XML;
4635     if (soap->count > SOAP_BUFLEN)
4636       return soap->error = SOAP_UDP_ERROR;
4637   }
4638 #endif
4639   if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
4640   { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
4641       soap->mode |= SOAP_IO_BUFFER;
4642     else
4643       soap->mode |= SOAP_IO_STORE;
4644   }
4645   soap->mode &= ~SOAP_IO_LENGTH;
4646   if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
4647     soap_new_block(soap);
4648   if (!(soap->mode & SOAP_IO_KEEPALIVE))
4649     soap->keep_alive = 0;
4650   if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
4651     soap->mode |= SOAP_XML_TREE;
4652 #ifndef WITH_LEANER
4653   if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
4654   { soap->mode |= SOAP_ENC_MIME;
4655     soap->mode &= ~SOAP_ENC_DIME;
4656   }
4657   else
4658     soap->mode &= ~SOAP_ENC_MTOM;
4659   if (soap->mode & SOAP_ENC_MIME)
4660     soap_select_mime_boundary(soap);
4661 #ifdef WIN32
4662 #ifndef UNDER_CE
4663 #ifndef WITH_FASTCGI
4664   if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
4665 #ifdef __BORLANDC__
4666     setmode((SOAP_SOCKET)soap->sendfd, O_BINARY);
4667 #else
4668     _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY);
4669 #endif
4670 #endif
4671 #endif
4672 #endif
4673 #endif
4674   if (soap->mode & SOAP_IO)
4675   { soap->bufidx = 0;
4676     soap->buflen = 0;
4677   }
4678   soap->chunksize = 0;
4679   soap->ns = 0;
4680   soap->null = 0;
4681   soap->position = 0;
4682   soap->mustUnderstand = 0;
4683   soap->encoding = 0;
4684   soap->idnum = 0;
4685   soap->level = 0;
4686   soap_clr_attr(soap);
4687   soap_set_local_namespaces(soap);
4688 #ifdef WITH_ZLIB
4689   soap->z_ratio_out = 1.0;
4690   if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
4691   {
4692 #ifdef WITH_GZIP
4693     memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
4694     soap->d_stream.next_out = (Byte*)soap->z_buf + 10;
4695     soap->d_stream.avail_out = SOAP_BUFLEN - 10;
4696     soap->z_crc = crc32(0L, NULL, 0);
4697     if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
4698 #else
4699     soap->d_stream.next_out = (Byte*)soap->z_buf;
4700     soap->d_stream.avail_out = SOAP_BUFLEN;
4701     if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK)
4702 #endif
4703       return soap->error = SOAP_ZLIB_ERROR;
4704     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
4705     soap->zlib_state = SOAP_ZLIB_DEFLATE;
4706   }
4707 #endif
4708   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
4709   soap->part = SOAP_BEGIN;
4710 #ifndef WITH_LEANER
4711   if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE)
4712     soap->fprepareinit(soap);   
4713 #endif
4714   return SOAP_OK;
4715 }
4716 #endif
4717
4718 /******************************************************************************/
4719 #ifndef WITH_NOIDREF
4720 #ifndef PALM_2
4721 SOAP_FMAC1
4722 void
4723 SOAP_FMAC2
4724 soap_embedded(struct soap *soap, const void *p, int t)
4725 { struct soap_plist *pp;
4726   if (soap_pointer_lookup(soap, p, t, &pp))
4727   { pp->mark1 = 1;
4728     pp->mark2 = 1;
4729     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
4730   }
4731 }
4732 #endif
4733 #endif
4734
4735 /******************************************************************************/
4736 #ifndef WITH_NOIDREF
4737 #ifndef PALM_2
4738 SOAP_FMAC1
4739 int
4740 SOAP_FMAC2
4741 soap_reference(struct soap *soap, const void *p, int t)
4742 { struct soap_plist *pp;
4743   if (!p || (soap->mode & SOAP_XML_TREE))
4744     return 1;
4745   if (soap_pointer_lookup(soap, p, t, &pp))
4746   { if (pp->mark1 == 0)
4747     { pp->mark1 = 2;
4748       pp->mark2 = 2;
4749     }
4750   }
4751   else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
4752   { pp->mark1 = 0;
4753     pp->mark2 = 0;
4754   }
4755   else
4756     return 1;
4757   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
4758   return pp->mark1;
4759 }
4760 #endif
4761 #endif
4762
4763 /******************************************************************************/
4764 #ifndef WITH_NOIDREF
4765 #ifndef PALM_2
4766 SOAP_FMAC1
4767 int
4768 SOAP_FMAC2
4769 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
4770 { register int i;
4771   struct soap_plist *pp;
4772   if (!p || !a->__ptr)
4773     return 1;
4774   i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
4775   if (i)
4776   { if (pp->mark1 == 0)
4777     { pp->mark1 = 2;
4778       pp->mark2 = 2;
4779     }
4780   }
4781   else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
4782     return 1;
4783   else
4784   { pp->mark1 = 0;
4785     pp->mark2 = 0;
4786   }
4787   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));
4788   return pp->mark1;
4789 }
4790 #endif
4791 #endif
4792
4793 /******************************************************************************/
4794 #ifndef WITH_NOIDREF
4795 #ifndef PALM_2
4796 SOAP_FMAC1
4797 int
4798 SOAP_FMAC2
4799 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
4800 { struct soap_plist *pp;
4801   if (soap->mode & SOAP_XML_TREE)
4802     return id;
4803   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
4804   if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
4805   { if (id < 0)
4806     { id = soap_pointer_lookup(soap, p, t, &pp);
4807       if (id)
4808       { if (soap->mode & SOAP_IO_LENGTH)
4809           pp->mark1 = 2;
4810         else
4811           pp->mark2 = 2;
4812         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));
4813       }
4814       return -1;
4815     }
4816     return id;
4817   }
4818   if (id < 0)
4819     id = soap_pointer_lookup(soap, p, t, &pp);
4820   else if (id && !soap_pointer_lookup(soap, p, t, &pp))
4821     return 0;
4822   if (id && pp)
4823   { if (soap->mode & SOAP_IO_LENGTH)
4824       pp->mark1 = 1;
4825     else
4826       pp->mark2 = 1;
4827     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));
4828   }
4829   return id;
4830 }
4831 #endif
4832 #endif
4833
4834 /******************************************************************************/
4835 #ifndef WITH_NOIDREF
4836 #ifndef PALM_2
4837 SOAP_FMAC1
4838 int
4839 SOAP_FMAC2
4840 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
4841 { if (!pp)
4842     return 0;
4843   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
4844   if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
4845   { if (soap->mode & SOAP_IO_LENGTH)
4846       return pp->mark1 != 0;
4847     return pp->mark2 != 0;
4848   }
4849   if (soap->mode & SOAP_IO_LENGTH)
4850     return pp->mark1 == 1;
4851   return pp->mark2 == 1;
4852 }
4853 #endif
4854 #endif
4855
4856 /******************************************************************************/
4857 #ifndef WITH_NOIDREF
4858 #ifndef PALM_2
4859 SOAP_FMAC1
4860 int
4861 SOAP_FMAC2
4862 soap_is_single(struct soap *soap, struct soap_plist *pp)
4863 { if (soap->part == SOAP_IN_HEADER)
4864     return 1;
4865   if (!pp)
4866     return 0;
4867   if (soap->mode & SOAP_IO_LENGTH)
4868     return pp->mark1 == 0;
4869   return pp->mark2 == 0;
4870 }
4871 #endif
4872 #endif
4873
4874 /******************************************************************************/
4875 #ifndef WITH_NOIDREF
4876 #ifndef PALM_2
4877 SOAP_FMAC1
4878 void
4879 SOAP_FMAC2
4880 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
4881 { if (!pp)
4882     return;
4883   if (soap->mode & SOAP_IO_LENGTH)
4884     pp->mark1 = 1;
4885   else
4886     pp->mark2 = 1;
4887 }
4888 #endif
4889 #endif
4890
4891 /******************************************************************************/
4892 #ifndef WITH_NOIDREF
4893 #ifndef WITH_LEANER
4894 #ifndef PALM_1
4895 SOAP_FMAC1
4896 int
4897 SOAP_FMAC2
4898 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) 
4899 { struct soap_plist *pp;
4900   int i;
4901   if (!p || !a->__ptr || (!aid && !atype))
4902     return soap_element_id(soap, tag, id, p, a, n, type, t);
4903   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:""));
4904   i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
4905   if (!i)
4906   { i = soap_pointer_enter(soap, p, a, n, t, &pp);
4907     if (!i)
4908     { soap->error = SOAP_EOM;
4909       return -1;
4910     }
4911   }
4912   if (id <= 0)
4913     id = i;
4914   if (!aid)
4915   { sprintf(soap->tmpbuf, soap->dime_id_format, id);
4916     aid = soap_strdup(soap, soap->tmpbuf);
4917   }
4918   /* Add MTOM xop:Include element when necessary */
4919   /* TODO: this code to be obsoleted with new import/xop.h conventions */
4920   if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
4921   { if (soap_element_begin_out(soap, tag, 0, type)
4922      || soap_element_href(soap, "xop:Include", 0, "href", aid)
4923      || soap_element_end_out(soap, tag))
4924       return soap->error;
4925   }
4926   else if (soap_element_href(soap, tag, 0, "href", aid))
4927     return soap->error;
4928   if (soap->mode & SOAP_IO_LENGTH)
4929   { if (pp->mark1 != 3)
4930     { struct soap_multipart *content;
4931       if (soap->mode & SOAP_ENC_MTOM)
4932         content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
4933       else
4934         content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
4935       if (!content)
4936       { soap->error = SOAP_EOM;
4937         return -1;
4938       }
4939       if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
4940       { if (soap->mode & SOAP_ENC_MTOM)
4941         { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
4942           if (s)
4943           { *s = '<';
4944             strcpy(s + 1, aid + 4);
4945             strcat(s, ">");
4946             content->id = s;
4947           }
4948         }
4949         else
4950           content->id = aid + 4;
4951       }
4952       else
4953         content->id = aid;
4954       content->type = atype;
4955       content->options = aoptions;
4956       content->encoding = SOAP_MIME_BINARY;
4957       pp->mark1 = 3;
4958     }
4959   }
4960   else
4961     pp->mark2 = 3;
4962   return -1;
4963 }
4964 #endif
4965 #endif
4966 #endif
4967
4968 /******************************************************************************/
4969 #ifndef WITH_NOIDREF
4970 #ifndef PALM_1
4971 static void
4972 soap_init_iht(struct soap *soap)
4973 { register int i;
4974   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n"));
4975   for (i = 0; i < SOAP_IDHASH; i++)
4976     soap->iht[i] = NULL;
4977 }
4978 #endif
4979 #endif
4980
4981 /******************************************************************************/
4982 #ifndef WITH_NOIDREF
4983 #ifndef PALM_1
4984 static void
4985 soap_free_iht(struct soap *soap)
4986 { register int i;
4987   register struct soap_ilist *ip, *p;
4988   register struct soap_flist *fp, *fq;
4989   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
4990   for (i = 0; i < SOAP_IDHASH; i++)
4991   { for (ip = soap->iht[i]; ip; ip = p)
4992     { for (fp = ip->flist; fp; fp = fq)
4993       { fq = fp->next;
4994         SOAP_FREE(soap, fp);
4995       }
4996       p = ip->next;
4997       SOAP_FREE(soap, ip);
4998     }
4999     soap->iht[i] = NULL;
5000   }
5001 }
5002 #endif
5003 #endif
5004
5005 /******************************************************************************/
5006 #ifndef WITH_NOIDREF
5007 #ifndef PALM_2
5008 SOAP_FMAC1
5009 struct soap_ilist *
5010 SOAP_FMAC2
5011 soap_lookup(struct soap *soap, const char *id)
5012 { register struct soap_ilist *ip;
5013   for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
5014     if (!strcmp(ip->id, id))
5015       return ip;
5016   return NULL;
5017 }
5018 #endif
5019 #endif
5020
5021 /******************************************************************************/
5022 #ifndef WITH_NOIDREF
5023 #ifndef PALM_2
5024 SOAP_FMAC1
5025 struct soap_ilist *
5026 SOAP_FMAC2
5027 soap_enter(struct soap *soap, const char *id)
5028 { register size_t h;
5029   register struct soap_ilist *ip;
5030   ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
5031   if (ip)
5032   { h = soap_hash(id);
5033     strcpy(ip->id, id);
5034     ip->next = soap->iht[h];
5035     soap->iht[h] = ip;
5036     return ip;
5037   }
5038   return NULL;
5039 }
5040 #endif
5041 #endif
5042
5043 /******************************************************************************/
5044 #ifndef PALM_2
5045 SOAP_FMAC1
5046 void*
5047 SOAP_FMAC2
5048 soap_malloc(struct soap *soap, size_t n)
5049 { register char *p;
5050   if (!n)
5051     return (void*)SOAP_NON_NULL;
5052   if (!soap)
5053     return SOAP_MALLOC(soap, n);
5054 #ifdef SOAP_DEBUG
5055   n += sizeof(short);
5056 #endif
5057   n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
5058   if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
5059   { soap->error = SOAP_EOM;
5060     return NULL;
5061   }
5062   /* keep chain of alloced cells for later destruction */
5063   soap->alloced = 1;
5064 #ifdef SOAP_DEBUG
5065   /* set the canary to detect corruption */
5066   *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY;
5067 #endif
5068   *(void**)(p + n) = soap->alist;
5069   *(size_t*)(p + n + sizeof(void*)) = n;
5070   soap->alist = p + n;
5071   return p;
5072 }
5073 #endif
5074
5075 /******************************************************************************/
5076 #ifdef SOAP_DEBUG
5077 static void
5078 soap_init_mht(struct soap *soap)
5079 { register int i;
5080   for (i = 0; i < (int)SOAP_PTRHASH; i++)
5081     soap->mht[i] = NULL;
5082 }
5083 #endif
5084
5085 /******************************************************************************/
5086 #ifdef SOAP_DEBUG
5087 static void
5088 soap_free_mht(struct soap *soap)
5089 { register int i;
5090   register struct soap_mlist *mp, *mq;
5091   for (i = 0; i < (int)SOAP_PTRHASH; i++)
5092   { for (mp = soap->mht[i]; mp; mp = mq)
5093     { mq = mp->next;
5094       if (mp->live)
5095         fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
5096       free(mp);
5097     }
5098     soap->mht[i] = NULL;
5099   }
5100 }
5101 #endif
5102
5103 /******************************************************************************/
5104 #ifdef SOAP_DEBUG
5105 SOAP_FMAC1
5106 void*
5107 SOAP_FMAC2
5108 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
5109 { register void *p = malloc(size);
5110   if (soap)
5111   { register int h = soap_hash_ptr(p);
5112     register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
5113     if (soap->fdebug[SOAP_INDEX_TEST])
5114       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
5115     mp->next = soap->mht[h];
5116     mp->ptr = p;
5117     mp->file = file;
5118     mp->line = line;
5119     mp->live = 1;
5120     soap->mht[h] = mp;
5121   }
5122   return p;
5123 }
5124 #endif
5125
5126 /******************************************************************************/
5127 #ifdef SOAP_DEBUG
5128 SOAP_FMAC1
5129 void
5130 SOAP_FMAC2
5131 soap_track_free(struct soap *soap, const char *file, int line, void *p)
5132 { register int h = soap_hash_ptr(p);
5133   register struct soap_mlist *mp;
5134   for (mp = soap->mht[h]; mp; mp = mp->next)
5135     if (mp->ptr == p)
5136       break;
5137   if (mp)
5138   { if (mp->live)
5139     { free(p);
5140       if (soap->fdebug[SOAP_INDEX_TEST])
5141         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
5142       mp->live = 0;
5143     }
5144     else
5145       fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
5146   }
5147   else
5148     fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
5149 }
5150 #endif
5151
5152 /******************************************************************************/
5153 #ifdef SOAP_DEBUG
5154 static void
5155 soap_track_unlink(struct soap *soap, const void *p)
5156 { register int h = soap_hash_ptr(p);
5157   register struct soap_mlist *mp;
5158   for (mp = soap->mht[h]; mp; mp = mp->next)
5159     if (mp->ptr == p)
5160       break;
5161   if (mp)
5162     mp->live = 0;
5163 }
5164 #endif
5165
5166 /******************************************************************************/
5167 #ifndef PALM_2
5168 SOAP_FMAC1
5169 void
5170 SOAP_FMAC2
5171 soap_dealloc(struct soap *soap, void *p)
5172 { if (!soap)
5173     return;
5174   if (p)
5175   { register char **q;
5176     for (q = (char**)&soap->alist; *q; q = *(char***)q)
5177     { 
5178 #ifdef SOAP_DEBUG
5179       if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY)
5180       { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
5181         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
5182         DBGHEX(TEST, *q - 200, 200);
5183         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
5184         return;
5185       }
5186 #endif
5187       if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
5188       { *q = **(char***)q;
5189         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
5190         SOAP_FREE(soap, p);
5191         return;
5192       }
5193     }
5194     soap_delete(soap, p);
5195   }
5196   else
5197   { register char *q;
5198     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
5199     while (soap->alist)
5200     { q = (char*)soap->alist;
5201 #ifdef SOAP_DEBUG
5202       if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY)
5203       { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
5204         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
5205         DBGHEX(TEST, q - 200, 200);
5206         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
5207         return;
5208       }
5209 #endif
5210       soap->alist = *(void**)q;
5211       q -= *(size_t*)(q + sizeof(void*));
5212       SOAP_FREE(soap, q);
5213     }
5214   }
5215   /* we must assume these were deallocated: */
5216   soap->action = NULL;
5217   soap->fault = NULL;
5218   soap->header = NULL;
5219   soap->userid = NULL;
5220   soap->passwd = NULL;
5221   soap->authrealm = NULL;
5222 #ifndef WITH_LEANER
5223   soap_clr_mime(soap);
5224 #endif
5225 }
5226 #endif
5227
5228 /******************************************************************************/
5229 #ifndef PALM_2
5230 SOAP_FMAC1
5231 void
5232 SOAP_FMAC2
5233 soap_delete(struct soap *soap, void *p)
5234 { register struct soap_clist **cp;
5235   if (soap_check_state(soap))
5236     return;
5237   cp = &soap->clist;
5238   if (p)
5239   { while (*cp)
5240     { if (p == (*cp)->ptr)
5241       { register struct soap_clist *q = *cp;
5242         *cp = q->next;
5243         q->fdelete(q);
5244         SOAP_FREE(soap, q);
5245         return;
5246       }
5247       cp = &(*cp)->next;
5248     }
5249     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
5250   }
5251   else
5252   { while (*cp)
5253     { register struct soap_clist *q = *cp;
5254       *cp = q->next;
5255       q->fdelete(q);
5256       SOAP_FREE(soap, q);
5257     }
5258   }
5259 }
5260 #endif
5261
5262 /******************************************************************************/
5263 #ifndef PALM_2
5264 SOAP_FMAC1
5265 struct soap_clist *
5266 SOAP_FMAC2
5267 soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*))
5268 { register struct soap_clist *cp;
5269   if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
5270   { cp->next = soap->clist;
5271     cp->type = t;
5272     cp->size = n; 
5273     cp->ptr = p;
5274     cp->fdelete = fdelete;
5275     soap->clist = cp;
5276   }
5277   return cp;
5278 }
5279 #endif
5280
5281 /******************************************************************************/
5282 #ifndef PALM_2
5283 SOAP_FMAC1
5284 void
5285 SOAP_FMAC2
5286 soap_unlink(struct soap *soap, const void *p)
5287 { register char **q;
5288   register struct soap_clist **cp;
5289   if (!soap || !p)
5290     return;
5291   for (q = (char**)&soap->alist; *q; q = *(char***)q)
5292   { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
5293     { *q = **(char***)q;
5294       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
5295 #ifdef SOAP_DEBUG
5296       soap_track_unlink(soap, p);
5297 #endif
5298       return;
5299     }
5300   }
5301   for (cp = &soap->clist; *cp; cp = &(*cp)->next)
5302   { if (p == (*cp)->ptr)
5303     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
5304       q = (char**)*cp;
5305       *cp = (*cp)->next;
5306       SOAP_FREE(soap, q);
5307       return;
5308     }
5309   }
5310 }
5311 #endif
5312
5313 /******************************************************************************/
5314 #ifndef WITH_NOIDREF
5315 #ifndef PALM_2
5316 SOAP_FMAC1
5317 int
5318 SOAP_FMAC2
5319 soap_lookup_type(struct soap *soap, const char *id)
5320 { register struct soap_ilist *ip;
5321   if (id && *id)
5322   { ip = soap_lookup(soap, id);
5323     if (ip)
5324     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
5325       return ip->type;
5326     }
5327   }
5328   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
5329   return 0;
5330 }
5331 #endif
5332 #endif
5333
5334 /******************************************************************************/
5335 #ifndef WITH_NOIDREF
5336 #ifndef PALM_2
5337 SOAP_FMAC1
5338 void*
5339 SOAP_FMAC2
5340 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
5341 { struct soap_ilist *ip;
5342   void **q;
5343   if (!p || !id || !*id)
5344     return p;
5345   ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
5346   if (!ip)
5347   { ip = soap_enter(soap, id); /* new hash table entry for string id */
5348     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
5349     ip->type = t;
5350     ip->size = n; 
5351     ip->link = p;
5352     ip->copy = NULL;
5353     ip->flist = NULL;
5354     ip->ptr = NULL;
5355     ip->level = k;
5356     *p = NULL;
5357   }
5358   else if (ip->ptr)
5359   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
5360     if (ip->type != t)
5361     { strcpy(soap->id, id);
5362       soap->error = SOAP_HREF;
5363       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t));
5364       return NULL;
5365     }
5366     while (ip->level < k)
5367     { q = (void**)soap_malloc(soap, sizeof(void*));  
5368       if (!q)
5369         return NULL;
5370       *p = (void*)q;
5371       p = q;
5372       k--;
5373       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5374     }
5375     *p = ip->ptr;
5376   }
5377   else if (ip->level > k)
5378   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
5379     while (ip->level > k)
5380     { void *s, **r = &ip->link;
5381       q = (void**)ip->link;
5382       while (q)
5383       { *r = (void*)soap_malloc(soap, sizeof(void*));
5384         s = *q;
5385         *q = *r;
5386         r = (void**)*r;
5387         q = (void**)s;
5388       }
5389       *r = NULL;
5390       ip->size = n; 
5391       ip->copy = NULL;
5392       ip->level = ip->level - 1;
5393       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5394     }
5395     q = (void**)ip->link;
5396     ip->link = p;
5397     *p = (void*)q;
5398   }
5399   else
5400   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
5401     while (ip->level < k)
5402     { q = (void**)soap_malloc(soap, sizeof(void*));  
5403       *p = q;
5404       p = q;
5405       k--;
5406       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5407     }
5408     q = (void**)ip->link;
5409     ip->link = p;
5410     *p = (void*)q;
5411   }
5412   return p;
5413 }
5414 #endif
5415 #endif
5416
5417 /******************************************************************************/
5418 #ifndef WITH_NOIDREF
5419 #ifndef PALM_2
5420 SOAP_FMAC1
5421 void*
5422 SOAP_FMAC2
5423 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))
5424 { struct soap_ilist *ip;
5425   if (!p || !href || !*href)
5426     return p;
5427   ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
5428   if (!ip)
5429   { ip = soap_enter(soap, href); /* new hash table entry for string id */
5430     ip->type = st;
5431     ip->size = n;
5432     ip->link = NULL;
5433     ip->copy = NULL;
5434     ip->ptr = NULL;
5435     ip->level = 0;
5436     ip->flist = NULL;
5437     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));
5438   }
5439   else if (ip->type != st || (ip->level == k && ip->size != n))
5440   { 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));
5441     strcpy(soap->id, href);
5442     soap->error = SOAP_HREF;
5443     return NULL;
5444   }
5445   if (fcopy || n < sizeof(void*) || *href != '#')
5446   { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
5447     if (!fp)
5448     { soap->error = SOAP_EOM;
5449       return NULL;
5450     }
5451     fp->next = ip->flist;
5452     fp->type = tt;
5453     fp->ptr = p;
5454     fp->level = k;
5455     fp->len = len;
5456     if (fcopy)
5457       fp->fcopy = fcopy;
5458     else
5459       fp->fcopy = soap_fcopy;
5460     ip->flist = fp;
5461     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));
5462   }
5463   else
5464   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
5465     *(void**)p = ip->copy;
5466     ip->copy = p;
5467   }
5468   return p;
5469 }
5470 #endif
5471 #endif
5472
5473 /******************************************************************************/
5474 #ifndef PALM_2
5475 SOAP_FMAC1
5476 void*
5477 SOAP_FMAC2
5478 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*))
5479 {
5480 #ifndef WITH_NOIDREF
5481   struct soap_ilist *ip;
5482 #endif
5483   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
5484   soap->alloced = 0;
5485   if (!p)
5486   { if (finstantiate)
5487       p = finstantiate(soap, t, type, arrayType, &n);
5488     else
5489       p = soap_malloc(soap, n);
5490     if (p)
5491       soap->alloced = 1;
5492   }
5493 #ifndef WITH_NOIDREF
5494   if (!id || !*id)
5495 #endif
5496     return p;
5497 #ifndef WITH_NOIDREF
5498   ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
5499   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
5500   if (!ip)
5501   { ip = soap_enter(soap, id); /* new hash table entry for string id */
5502     ip->type = t;
5503     ip->link = NULL;
5504     ip->copy = NULL;
5505     ip->flist = NULL;
5506     ip->size = n;
5507     ip->ptr = p;
5508     ip->level = k;
5509     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));
5510   }
5511   else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
5512   { 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));
5513     strcpy(soap->id, id);
5514     soap->error = SOAP_HREF;
5515     return NULL;
5516   }
5517   else if (ip->ptr)
5518   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
5519     strcpy(soap->id, id);
5520     soap->error = SOAP_DUPLICATE_ID;
5521     return NULL;
5522   }
5523   else 
5524   { ip->size = n;
5525     ip->ptr = p;
5526     ip->level = k;
5527     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));
5528   }
5529   return ip->ptr;
5530 #endif
5531 }
5532 #endif
5533
5534 /******************************************************************************/
5535 #ifndef PALM_2
5536 SOAP_FMAC1
5537 void
5538 SOAP_FMAC2
5539 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
5540 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
5541   memcpy(p, q, n);
5542 }
5543 #endif
5544
5545 /******************************************************************************/
5546 #ifndef PALM_1
5547 SOAP_FMAC1
5548 int
5549 SOAP_FMAC2
5550 soap_end_send(struct soap *soap)
5551
5552 #ifndef WITH_LEANER
5553   if (soap->dime.list)
5554   { /* SOAP body referenced attachments must appear first */
5555     soap->dime.last->next = soap->dime.first;
5556     soap->dime.first = soap->dime.list->next;
5557     soap->dime.list->next = NULL;
5558     soap->dime.last = soap->dime.list;
5559   }
5560   if (soap_putdime(soap) || soap_putmime(soap))
5561     return soap->error;
5562   soap->mime.list = NULL;
5563   soap->mime.first = NULL;
5564   soap->mime.last = NULL;
5565   soap->dime.list = NULL;
5566   soap->dime.first = NULL;
5567   soap->dime.last = NULL;
5568 #endif
5569   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n"));
5570   if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
5571   { if (soap_flush(soap))
5572 #ifdef WITH_ZLIB
5573     { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
5574       { soap->zlib_state = SOAP_ZLIB_NONE;
5575         deflateEnd(&soap->d_stream);
5576       }
5577       return soap->error;
5578     }
5579 #else
5580       return soap->error;
5581 #endif
5582 #ifdef WITH_ZLIB
5583     if (soap->mode & SOAP_ENC_ZLIB)
5584     { int r;
5585       soap->d_stream.avail_in = 0;
5586       do
5587       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
5588         r = deflate(&soap->d_stream, Z_FINISH);
5589         if (soap->d_stream.avail_out != SOAP_BUFLEN)
5590         { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out))
5591           { soap->zlib_state = SOAP_ZLIB_NONE;
5592             deflateEnd(&soap->d_stream);
5593             return soap->error;
5594           }
5595           soap->d_stream.next_out = (Byte*)soap->z_buf;
5596           soap->d_stream.avail_out = SOAP_BUFLEN;
5597         }
5598       } while (r == Z_OK);
5599       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
5600       soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in;
5601       soap->mode &= ~SOAP_ENC_ZLIB;
5602       soap->zlib_state = SOAP_ZLIB_NONE;
5603       if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END)
5604       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
5605         return soap->error = SOAP_ZLIB_ERROR;
5606       }
5607 #ifdef WITH_GZIP
5608       soap->z_buf[0] = soap->z_crc & 0xFF;
5609       soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
5610       soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
5611       soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
5612       soap->z_buf[4] = soap->d_stream.total_in & 0xFF;
5613       soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF;
5614       soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF;
5615       soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF;
5616       if (soap_flush_raw(soap, soap->z_buf, 8))
5617         return soap->error;
5618       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
5619 #endif
5620     }
5621 #endif
5622     if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
5623     { char *p;
5624 #ifndef WITH_NOHTTP
5625       if (!(soap->mode & SOAP_ENC_XML))
5626       { soap->mode--;
5627         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
5628         if (soap->status >= SOAP_POST)
5629           soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
5630         else if (soap->status != SOAP_STOP)
5631           soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
5632         if (soap->error || soap_flush(soap))
5633           return soap->error;
5634         soap->mode++;
5635       }
5636 #endif
5637       for (p = soap_first_block(soap); p; p = soap_next_block(soap))
5638       { DBGMSG(SENT, p, soap_block_size(soap));
5639         if ((soap->error = soap->fsend(soap, p, soap_block_size(soap))))
5640         { soap_end_block(soap);
5641           return soap->error;
5642         }
5643       }
5644       soap_end_block(soap);
5645     }
5646 #ifndef WITH_LEANER
5647     else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
5648     { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
5649       if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
5650         return soap->error;
5651     }
5652 #endif
5653   }
5654 #ifdef WITH_TCPFIN
5655 #ifdef WITH_OPENSSL
5656   if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
5657     soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
5658 #else
5659   if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
5660     soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
5661 #endif
5662 #endif
5663   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
5664   soap->omode &= ~SOAP_XML_SEC;
5665   soap->count = 0;
5666   soap->part = SOAP_END;
5667   return SOAP_OK;
5668 }
5669 #endif
5670
5671 /******************************************************************************/
5672 #ifndef PALM_1
5673 SOAP_FMAC1
5674 int
5675 SOAP_FMAC2
5676 soap_end_recv(struct soap *soap)
5677 { soap->part = SOAP_END;
5678 #ifndef WITH_LEANER
5679   if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
5680     return soap->error;
5681   soap->dime.list = soap->dime.first;
5682   soap->dime.first = NULL;
5683   soap->dime.last = NULL;
5684   /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */
5685   if (soap->mode & SOAP_ENC_MIME)
5686   { if (soap->mode & SOAP_MIME_POSTCHECK)
5687     { soap_resolve(soap);
5688       return SOAP_OK;
5689     }
5690     if (soap_getmime(soap))
5691       return soap->error;
5692   }
5693   soap->mime.list = soap->mime.first;
5694   soap->mime.first = NULL;
5695   soap->mime.last = NULL;
5696   soap->mime.boundary = NULL;
5697 #endif
5698   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
5699 #ifdef WITH_ZLIB
5700   if (soap->mode & SOAP_ENC_ZLIB)
5701   { soap->mode &= ~SOAP_ENC_ZLIB;
5702     memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
5703     soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf;
5704     soap->buflen = soap->z_buflen;
5705     soap->zlib_state = SOAP_ZLIB_NONE;
5706     if (inflateEnd(&soap->d_stream) != Z_OK)
5707       return soap->error = SOAP_ZLIB_ERROR;
5708 #ifdef WITH_GZIP
5709     if (soap->zlib_in == SOAP_ZLIB_GZIP)
5710     { soap_wchar c;
5711       short i;
5712       for (i = 0; i < 8; i++)
5713       { if ((int)(c = soap_getchar(soap)) == EOF)
5714           return soap->error = SOAP_EOF;
5715         soap->z_buf[i] = (char)c;
5716       }
5717       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)))
5718       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
5719         return soap->error = SOAP_ZLIB_ERROR;
5720       }
5721       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)))
5722       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n"));
5723         return soap->error = SOAP_ZLIB_ERROR;
5724       }
5725     }
5726 #endif
5727   }
5728 #endif
5729   if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
5730     while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
5731       ;
5732   if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
5733     return soap->error;
5734 #ifndef WITH_NOIDREF
5735   return soap_resolve(soap);
5736 #else
5737 #ifndef WITH_LEANER
5738   if (soap->xlist)
5739   { if (soap->mode & SOAP_ENC_MTOM)
5740       return soap->error = SOAP_MIME_HREF;
5741     return soap->error = SOAP_DIME_HREF;
5742   }
5743 #endif
5744   return SOAP_OK;
5745 #endif
5746 }
5747 #endif
5748
5749 /******************************************************************************/
5750 #ifndef PALM_1
5751 SOAP_FMAC1
5752 void
5753 SOAP_FMAC2
5754 soap_free(struct soap *soap)
5755 { register struct Namespace *ns;
5756   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
5757   while (soap->nlist)
5758   { register struct soap_nlist *np = soap->nlist->next;
5759     SOAP_FREE(soap, soap->nlist);
5760     soap->nlist = np;
5761   }
5762   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
5763   while (soap->blist)
5764     soap_end_block(soap);
5765   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
5766   while (soap->attributes)
5767   { register struct soap_attribute *tp = soap->attributes->next;
5768     if (soap->attributes->value)
5769       SOAP_FREE(soap, soap->attributes->value);
5770     SOAP_FREE(soap, soap->attributes);
5771     soap->attributes = tp;
5772   }
5773 #ifdef WITH_FAST
5774   if (soap->labbuf)
5775     SOAP_FREE(soap, soap->labbuf);
5776   soap->labbuf = NULL;
5777   soap->lablen = 0;
5778   soap->labidx = 0;
5779 #endif
5780   ns = soap->local_namespaces;
5781   if (ns)
5782   { for (; ns->id; ns++)
5783     { if (ns->out)
5784       { if (soap->encodingStyle == ns->out)
5785           soap->encodingStyle = SOAP_STR_EOS;
5786         SOAP_FREE(soap, ns->out);
5787         ns->out = NULL;
5788       }
5789       if (soap->encodingStyle == ns->ns)
5790         soap->encodingStyle = SOAP_STR_EOS;
5791     }
5792     SOAP_FREE(soap, soap->local_namespaces);
5793     soap->local_namespaces = NULL;
5794   }
5795 #ifndef WITH_LEANER
5796   while (soap->xlist)
5797   { struct soap_xlist *xp = soap->xlist->next;
5798     SOAP_FREE(soap, soap->xlist);
5799     soap->xlist = xp;
5800   }
5801 #endif
5802 #ifndef WITH_NOIDREF
5803   soap_free_pht(soap);
5804   soap_free_iht(soap);
5805 #endif
5806 }
5807 #endif
5808
5809 /******************************************************************************/
5810 #ifdef SOAP_DEBUG
5811 static void
5812 soap_init_logs(struct soap *soap)
5813 { int i;
5814   for (i = 0; i < SOAP_MAXLOGS; i++)
5815   { soap->logfile[i] = NULL;
5816     soap->fdebug[i] = NULL;
5817   }
5818 }
5819 #endif
5820
5821 /******************************************************************************/
5822 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
5823 SOAP_FMAC1
5824 void
5825 SOAP_FMAC2
5826 soap_open_logfile(struct soap *soap, int i)
5827 { if (soap->logfile[i])
5828     soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
5829 }
5830 #endif
5831
5832 /******************************************************************************/
5833 #ifdef SOAP_DEBUG
5834 static void
5835 soap_close_logfile(struct soap *soap, int i)
5836 { if (soap->fdebug[i])
5837   { fclose(soap->fdebug[i]);
5838     soap->fdebug[i] = NULL;
5839   }
5840 }
5841 #endif
5842
5843 /******************************************************************************/
5844 #ifdef SOAP_DEBUG
5845 SOAP_FMAC1
5846 void
5847 SOAP_FMAC2
5848 soap_close_logfiles(struct soap *soap)
5849 { int i;
5850   for (i = 0; i < SOAP_MAXLOGS; i++)
5851     soap_close_logfile(soap, i);
5852 }
5853 #endif
5854
5855 /******************************************************************************/
5856 #ifdef SOAP_DEBUG
5857 static void
5858 soap_set_logfile(struct soap *soap, int i, const char *logfile)
5859 { char *s = NULL;
5860   soap_close_logfile(soap, i);
5861   if (soap->logfile[i])
5862     SOAP_FREE(soap, (void*)soap->logfile[i]);
5863   if (logfile)
5864     if ((s = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
5865       strcpy(s, logfile);
5866   soap->logfile[i] = s;
5867 }
5868 #endif
5869
5870 /******************************************************************************/
5871 #ifdef SOAP_DEBUG
5872 SOAP_FMAC1
5873 void
5874 SOAP_FMAC2
5875 soap_set_recv_logfile(struct soap *soap, const char *logfile)
5876 { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
5877 }
5878 #endif
5879
5880 /******************************************************************************/
5881 #ifdef SOAP_DEBUG
5882 SOAP_FMAC1
5883 void
5884 SOAP_FMAC2
5885 soap_set_sent_logfile(struct soap *soap, const char *logfile)
5886 { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
5887 }
5888 #endif
5889
5890 /******************************************************************************/
5891 #ifdef SOAP_DEBUG
5892 SOAP_FMAC1
5893 void
5894 SOAP_FMAC2
5895 soap_set_test_logfile(struct soap *soap, const char *logfile)
5896 { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
5897 }
5898 #endif
5899
5900 /******************************************************************************/
5901 #ifndef PALM_1
5902 SOAP_FMAC1
5903 struct soap*
5904 SOAP_FMAC2
5905 soap_copy(struct soap *soap)
5906 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
5907 }
5908 #endif
5909
5910 /******************************************************************************/
5911 #ifndef PALM_1
5912 SOAP_FMAC1
5913 struct soap*
5914 SOAP_FMAC2
5915 soap_copy_context(struct soap *copy, struct soap *soap)
5916 { if (soap_check_state(soap))
5917     return NULL;
5918   if (copy)
5919   { register struct soap_plugin *p;
5920     memcpy(copy, soap, sizeof(struct soap));
5921     copy->state = SOAP_COPY;
5922     copy->error = SOAP_OK;
5923     copy->userid = NULL;
5924     copy->passwd = NULL;
5925     copy->nlist = NULL;
5926     copy->blist = NULL;
5927     copy->clist = NULL;
5928     copy->alist = NULL;
5929     copy->attributes = NULL;
5930 #ifdef WITH_FAST
5931     copy->labbuf = NULL;
5932     copy->lablen = 0;
5933     copy->labidx = 0;
5934 #endif
5935 #ifdef SOAP_DEBUG
5936     soap_init_mht(copy);
5937 #endif
5938     copy->local_namespaces = NULL;
5939 #ifndef WITH_NOIDREF
5940     soap_init_iht(copy);
5941     soap_init_pht(copy);
5942 #endif
5943     copy->header = NULL;
5944     copy->fault = NULL;
5945     copy->action = NULL;
5946 #ifndef WITH_LEAN
5947 #ifdef WITH_COOKIES
5948     copy->cookies = soap_copy_cookies(copy, soap);
5949 #else
5950     copy->cookies = NULL;
5951 #endif
5952 #endif
5953 #ifdef SOAP_DEBUG
5954     soap_init_logs(copy);
5955     soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
5956     soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
5957     soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
5958 #endif
5959     copy->plugins = NULL;
5960     for (p = soap->plugins; p; p = p->next)
5961     { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
5962       if (!q)
5963         return NULL;
5964       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
5965       *q = *p;
5966       if (p->fcopy && (soap->error = p->fcopy(copy, q, p)))
5967       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
5968         SOAP_FREE(copy, q);
5969         return NULL;
5970       }
5971       q->next = copy->plugins;
5972       copy->plugins = q;
5973     }
5974   }
5975   else
5976     soap->error = SOAP_EOM;
5977   return copy;
5978 }
5979 #endif
5980
5981 /******************************************************************************/
5982 #ifndef PALM_1
5983 SOAP_FMAC1
5984 void
5985 SOAP_FMAC2
5986 soap_copy_stream(struct soap *copy, struct soap *soap)
5987 { copy->mode = soap->mode;
5988   copy->imode = soap->imode;
5989   copy->omode = soap->omode;
5990   copy->socket = soap->socket;
5991   copy->recv_timeout = soap->recv_timeout;
5992   copy->send_timeout = soap->send_timeout;
5993 #if defined(__cplusplus) && !defined(WITH_LEAN)
5994   copy->os = soap->os;
5995   copy->is = soap->is;
5996 #endif
5997   copy->sendfd = soap->sendfd;
5998   copy->recvfd = soap->recvfd;
5999   copy->bufidx = soap->bufidx;
6000   copy->buflen = soap->buflen;
6001   copy->ahead = soap->ahead;
6002   copy->cdata = soap->cdata;
6003   copy->chunksize = soap->chunksize;
6004   copy->chunkbuflen = soap->chunkbuflen;
6005   copy->keep_alive = soap->keep_alive;
6006   copy->max_keep_alive = soap->max_keep_alive;
6007   copy->peer = soap->peer;
6008   copy->peerlen = soap->peerlen;
6009 #ifdef WITH_OPENSSL
6010   copy->bio = soap->bio;
6011   copy->ssl = soap->ssl;
6012   copy->ctx = soap->ctx;
6013 #endif
6014 #ifdef WITH_ZLIB
6015   copy->zlib_state = soap->zlib_state;
6016   copy->zlib_in = soap->zlib_in;
6017   copy->zlib_out = soap->zlib_out;
6018   copy->d_stream = soap->d_stream;
6019   copy->z_buflen = soap->z_buflen;
6020   copy->z_level = soap->z_level;
6021   copy->z_crc = soap->z_crc;
6022   copy->z_ratio_in = soap->z_ratio_in;
6023   copy->z_ratio_out = soap->z_ratio_out;
6024   memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf));
6025 #endif
6026   memcpy(copy->buf, soap->buf, sizeof(soap->buf));
6027 }
6028 #endif
6029
6030 /******************************************************************************/
6031 #ifndef PALM_1
6032 SOAP_FMAC1
6033 void
6034 SOAP_FMAC2
6035 soap_init(struct soap *soap)
6036 { soap->state = SOAP_INIT;
6037   soap->version = 0;
6038   soap_imode(soap, SOAP_IO_DEFAULT);
6039   soap_omode(soap, SOAP_IO_DEFAULT);
6040   soap->plugins = NULL;
6041   soap->user = NULL;
6042   soap->userid = NULL;
6043   soap->passwd = NULL;
6044 #ifndef WITH_NOHTTP
6045   soap->fpost = http_post;
6046   soap->fget = http_get;
6047   soap->fform = NULL;
6048   soap->fposthdr = http_post_header;
6049   soap->fresponse = http_response;
6050   soap->fparse = http_parse;
6051   soap->fparsehdr = http_parse_header;
6052 #endif
6053   soap->fheader = NULL;
6054   soap->fconnect = NULL;
6055   soap->fdisconnect = NULL;
6056 #ifndef WITH_NOIO
6057 #ifndef WITH_IPV6
6058   soap->fresolve = tcp_gethost;
6059 #else
6060   soap->fresolve = NULL;
6061 #endif
6062   soap->faccept = tcp_accept;
6063   soap->fopen = tcp_connect;
6064   soap->fclose = tcp_disconnect;
6065   soap->fclosesocket = tcp_closesocket;
6066   soap->fshutdownsocket = tcp_shutdownsocket;
6067   soap->fsend = fsend;
6068   soap->frecv = frecv;
6069   soap->fpoll = soap_poll;
6070 #else
6071   soap->fopen = NULL;
6072   soap->fclose = NULL;
6073   soap->fpoll = NULL;
6074 #endif
6075   soap->fseterror = NULL;
6076   soap->fignore = NULL;
6077   soap->fserveloop = NULL;
6078   soap->fplugin = fplugin;
6079 #ifndef WITH_LEANER
6080   soap->fprepareinit = NULL;
6081   soap->fpreparesend = NULL;
6082   soap->fpreparerecv = NULL;
6083   soap->fpreparefinal = NULL;
6084   soap->fdimereadopen = NULL;
6085   soap->fdimewriteopen = NULL;
6086   soap->fdimereadclose = NULL;
6087   soap->fdimewriteclose = NULL;
6088   soap->fdimeread = NULL;
6089   soap->fdimewrite = NULL;
6090   soap->fmimereadopen = NULL;
6091   soap->fmimewriteopen = NULL;
6092   soap->fmimereadclose = NULL;
6093   soap->fmimewriteclose = NULL;
6094   soap->fmimeread = NULL;
6095   soap->fmimewrite = NULL;
6096 #endif
6097   soap->float_format = "%G";
6098   soap->double_format = "%lG";
6099   soap->dime_id_format = "cid:id%d"; /* default DIME id format */
6100   soap->http_version = "1.1";
6101   soap->http_content = NULL;
6102   soap->actor = NULL;
6103   soap->max_keep_alive = SOAP_MAXKEEPALIVE;
6104   soap->keep_alive = 0;
6105   soap->recv_timeout = 0;
6106   soap->send_timeout = 0;
6107   soap->connect_timeout = 0;
6108   soap->accept_timeout = 0;
6109   soap->socket_flags = 0;
6110   soap->connect_flags = 0;
6111   soap->bind_flags = 0;
6112   soap->accept_flags = 0;
6113   soap->ip = 0;
6114 #ifdef WITH_FAST
6115   soap->labbuf = NULL;
6116   soap->lablen = 0;
6117   soap->labidx = 0;
6118 #endif
6119   soap->encodingStyle = SOAP_STR_EOS;
6120 #ifndef WITH_NONAMESPACES
6121   soap->namespaces = namespaces;
6122 #else
6123   soap->namespaces = NULL;
6124 #endif
6125   soap->local_namespaces = NULL;
6126   soap->nlist = NULL;
6127   soap->blist = NULL;
6128   soap->clist = NULL;
6129   soap->alist = NULL;
6130   soap->attributes = NULL;
6131   soap->header = NULL;
6132   soap->fault = NULL;
6133   soap->master = SOAP_INVALID_SOCKET;
6134   soap->socket = SOAP_INVALID_SOCKET;
6135   soap->os = NULL;
6136   soap->is = NULL;
6137 #ifndef WITH_LEANER
6138   soap->dom = NULL;
6139   soap->dime.list = NULL;
6140   soap->dime.first = NULL;
6141   soap->dime.last = NULL;
6142   soap->mime.list = NULL;
6143   soap->mime.first = NULL;
6144   soap->mime.last = NULL;
6145   soap->mime.boundary = NULL;
6146   soap->mime.start = NULL;
6147   soap->xlist = NULL;
6148 #endif
6149 #ifndef UNDER_CE
6150   soap->recvfd = 0;
6151   soap->sendfd = 1;
6152 #else
6153   soap->recvfd = stdin;
6154   soap->sendfd = stdout;
6155 #endif 
6156   soap->host[0] = '\0';
6157   soap->port = 0;
6158   soap->action = NULL;
6159   soap->proxy_host = NULL;
6160   soap->proxy_port = 8080;
6161   soap->proxy_userid = NULL;
6162   soap->proxy_passwd = NULL;
6163   soap->authrealm = NULL;
6164   soap->prolog = NULL;
6165 #ifdef WITH_OPENSSL
6166   if (!ssl_init_done)
6167     soap_ssl_init();
6168   soap->fsslauth = ssl_auth_init;
6169   soap->fsslverify = ssl_verify_callback;
6170   soap->bio = NULL;
6171   soap->ssl = NULL;
6172   soap->ctx = NULL;
6173   soap->require_server_auth = 0;
6174   soap->require_client_auth = 0;
6175   soap->rsa = 0;
6176   soap->keyfile = NULL;
6177   soap->password = NULL;
6178   soap->dhfile = NULL;
6179   soap->cafile = NULL;
6180   soap->capath = NULL;
6181   soap->crlfile = NULL;
6182   soap->randfile = NULL;
6183   soap->session = NULL;
6184 #endif
6185 #ifdef WITH_ZLIB
6186   soap->zlib_state = SOAP_ZLIB_NONE;
6187   soap->zlib_in = SOAP_ZLIB_NONE;
6188   soap->zlib_out = SOAP_ZLIB_NONE;
6189   soap->d_stream.zalloc = NULL;
6190   soap->d_stream.zfree = NULL;
6191   soap->d_stream.opaque = NULL;
6192   soap->z_level = 6;
6193 #endif
6194 #ifndef WITH_LEAN
6195   soap->c14ninclude = NULL;
6196   soap->c14nexclude = NULL;
6197   soap->cookies = NULL;
6198   soap->cookie_domain = NULL;
6199   soap->cookie_path = NULL;
6200   soap->cookie_max = 32;
6201 #endif
6202 #ifdef SOAP_DEBUG
6203   soap_init_mht(soap);
6204   soap_init_logs(soap);
6205   soap_set_recv_logfile(soap, "RECV.log");
6206   soap_set_sent_logfile(soap, "SENT.log");
6207   soap_set_test_logfile(soap, NULL);
6208 #endif
6209 #ifdef WMW_RPM_IO
6210   soap->rpmreqid = NULL;
6211 #endif
6212 #ifdef PALM
6213   palmNetLibOpen();
6214 #endif
6215 #ifndef WITH_NOIDREF
6216   soap_init_iht(soap);
6217   soap_init_pht(soap);
6218 #endif
6219   soap_begin(soap);
6220 #ifdef SOAP_DEBUG
6221   soap_set_test_logfile(soap, "TEST.log");
6222 #endif
6223 }
6224 #endif
6225
6226 /******************************************************************************/
6227 #ifndef PALM_1
6228 SOAP_FMAC1
6229 void
6230 SOAP_FMAC2
6231 soap_init1(struct soap *soap, soap_mode mode)
6232 { soap_init2(soap, mode, mode);
6233 }
6234 #endif
6235
6236 /******************************************************************************/
6237 #ifndef PALM_1
6238 SOAP_FMAC1
6239 void
6240 SOAP_FMAC2
6241 soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)
6242 { soap_init(soap);
6243   soap_imode(soap, imode);
6244   soap_omode(soap, omode);
6245 }
6246 #endif
6247
6248 /******************************************************************************/
6249 #ifndef PALM_2
6250 SOAP_FMAC1
6251 void
6252 SOAP_FMAC2
6253 soap_begin(struct soap *soap)
6254 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n"));
6255   if (!soap->keep_alive)
6256   { soap->buflen = 0;
6257     soap->bufidx = 0;
6258   }
6259   soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
6260   soap->null = 0;
6261   soap->position = 0;
6262   soap->encoding = 0;
6263   soap->mustUnderstand = 0;
6264   soap->mode = 0;
6265   soap->ns = 0;
6266   soap->part = SOAP_END;
6267   soap->alloced = 0;
6268   soap->count = 0;
6269   soap->length = 0;
6270   soap->cdata = 0;
6271   soap->error = SOAP_OK;
6272   soap->peeked = 0;
6273   soap->ahead = 0;
6274   soap->idnum = 0;
6275   soap->level = 0;
6276   soap->endpoint[0] = '\0';
6277 #ifndef WITH_LEANER
6278   soap->dime.chunksize = 0;
6279   soap->dime.buflen = 0;
6280 #endif
6281   soap_free(soap);
6282 }
6283 #endif
6284
6285 /******************************************************************************/
6286 #ifndef PALM_2
6287 SOAP_FMAC1
6288 void
6289 SOAP_FMAC2
6290 soap_end(struct soap *soap)
6291 { register struct soap_clist *cp;
6292   if (soap_check_state(soap))
6293     return;
6294   soap_free(soap);
6295   soap_dealloc(soap, NULL);
6296   while (soap->clist)
6297   { cp = soap->clist->next;
6298     SOAP_FREE(soap, soap->clist);
6299     soap->clist = cp;
6300   }
6301   soap_closesock(soap);
6302 #ifdef SOAP_DEBUG
6303   soap_close_logfiles(soap);
6304 #endif
6305 #ifdef PALM
6306   palmNetLibClose();
6307 #endif
6308 }
6309 #endif
6310
6311 /******************************************************************************/
6312 #ifndef PALM_1
6313 SOAP_FMAC1
6314 int
6315 SOAP_FMAC2
6316 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
6317 { register struct Namespace *ns = soap->local_namespaces;
6318   register struct soap_nlist *np, *nq, *nr;
6319   register unsigned int level = soap->level;
6320   soap->namespaces = p;
6321   soap->local_namespaces = NULL;
6322   soap_set_local_namespaces(soap);
6323   /* reverse the namespace list */
6324   np = soap->nlist;
6325   soap->nlist = NULL;
6326   if (np)
6327   { nq = np->next;
6328     np->next = NULL;
6329     while (nq)
6330     { nr = nq->next;
6331       nq->next = np;
6332       np = nq;
6333       nq = nr;
6334     }
6335   }
6336   /* then push on new stack */
6337   while (np)
6338   { register const char *s;
6339     soap->level = np->level; /* preserve element nesting level */
6340     s = np->ns;
6341     if (!s && np->index >= 0 && ns)
6342     { s = ns[np->index].out;
6343       if (!s)
6344         s = ns[np->index].ns;
6345     }
6346     if (s && soap_push_namespace(soap, np->id, s))
6347       return soap->error;
6348     nq = np;
6349     np = np->next;
6350     SOAP_FREE(soap, nq);
6351   }
6352   if (ns)
6353   { register int i;
6354     for (i = 0; ns[i].id; i++)
6355     { if (ns[i].out)
6356       { SOAP_FREE(soap, ns[i].out);
6357         ns[i].out = NULL;
6358       }
6359     }
6360     SOAP_FREE(soap, ns);
6361   }
6362   soap->level = level; /* restore level */
6363   return SOAP_OK;
6364 }
6365 #endif
6366
6367 /******************************************************************************/
6368 #ifndef PALM_1
6369 SOAP_FMAC1
6370 void
6371 SOAP_FMAC2
6372 soap_set_local_namespaces(struct soap *soap)
6373 { if (soap->namespaces && !soap->local_namespaces)
6374   { register const struct Namespace *ns1;
6375     register struct Namespace *ns2;
6376     register size_t n = 1;
6377     for (ns1 = soap->namespaces; ns1->id; ns1++)
6378       n++;
6379     n *= sizeof(struct Namespace);
6380     ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
6381     if (ns2)
6382     { memcpy(ns2, soap->namespaces, n);
6383       if (ns2[0].ns)
6384       { if (!strcmp(ns2[0].ns, soap_env1))
6385           soap->version = 1;
6386         else
6387           soap->version = 2;
6388       }
6389       soap->local_namespaces = ns2;
6390     }
6391   }
6392 }
6393 #endif
6394
6395 /******************************************************************************/
6396 #ifndef WITH_LEAN
6397 #ifndef PALM_1
6398 SOAP_FMAC1
6399 const char *
6400 SOAP_FMAC2
6401 soap_strsearch(const char *big, const char *little)
6402 { size_t n = strlen(little);
6403   const char *s = big;
6404   while (s) 
6405   { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' '))
6406       return s;
6407     s = strchr(s, ' ');
6408     if (s)
6409       s++;
6410   }
6411   return NULL;
6412 }
6413 #endif
6414 #endif
6415
6416 /******************************************************************************/
6417 #ifndef WITH_LEAN
6418 static struct soap_nlist *
6419 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
6420 { register struct soap_nlist *np;
6421   for (np = soap->nlist; np; np = np->next)
6422   { if (!strncmp(np->id, tag, n) && !np->id[n])
6423       return np;
6424   }
6425   return NULL;
6426 }
6427 #endif
6428
6429 /******************************************************************************/
6430 #ifndef WITH_LEAN
6431 static struct soap_nlist *
6432 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
6433 { register struct soap_nlist *np;
6434   size_t n, k;
6435   if (soap_strsearch(soap->c14nexclude, id))
6436     return NULL;
6437   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns?ns:""));
6438   if (!utilized)
6439   { for (np = soap->nlist; np; np = np->next)
6440     { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
6441         break;
6442     }
6443     if (np)
6444     { if (np->index == 1)
6445         utilized = np->index;
6446       else
6447         return NULL;
6448     }
6449   }
6450   n = strlen(id);
6451   if (ns)
6452     k = strlen(ns);
6453   else
6454     k = 0;
6455   np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
6456   if (!np)
6457   { soap->error = SOAP_EOM;
6458     return NULL;
6459   }
6460   np->next = soap->nlist;
6461   soap->nlist = np;
6462   strcpy(np->id, id);
6463   if (ns)
6464   { np->ns = np->id + n + 1;
6465     strcpy(np->ns, ns);
6466   }
6467   else
6468     np->ns = NULL;
6469   np->level = soap->level;
6470   np->index = utilized;
6471   return np;
6472 }
6473 #endif
6474
6475 /******************************************************************************/
6476 #ifndef WITH_LEAN
6477 static void
6478 soap_utilize_ns(struct soap *soap, const char *tag, size_t n)
6479 { register struct soap_nlist *np = soap_lookup_ns(soap, tag, n);
6480   if (np)
6481   { if (np->index == 0)
6482       soap_push_ns(soap, np->id, np->ns, 1);
6483   }
6484   else
6485   { strncpy(soap->tmpbuf, tag, n);
6486     soap->tmpbuf[n] = '\0';
6487     soap_push_ns(soap, soap->tmpbuf, NULL, 1);
6488   }
6489 }
6490 #endif
6491
6492 /******************************************************************************/
6493 #ifndef WITH_LEAN
6494 static void
6495 soap_pop_ns(struct soap *soap)
6496 { soap_pop_namespace(soap);
6497 }
6498 #endif
6499
6500 /******************************************************************************/
6501 #ifndef PALM_2
6502 SOAP_FMAC1
6503 int
6504 SOAP_FMAC2
6505 soap_element(struct soap *soap, const char *tag, int id, const char *type)
6506 {
6507 #ifdef WITH_XMLNS
6508   register const char *s;
6509 #endif
6510   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:""));
6511 #ifdef WITH_DOM
6512   if (soap->mode & SOAP_XML_DOM)
6513   { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
6514     if (!elt)
6515       return soap->error = SOAP_EOM;
6516     elt->soap = soap;
6517     elt->next = NULL;
6518     elt->prnt = soap->dom;
6519     elt->name = soap_strdup(soap, tag);
6520     elt->elts = NULL;
6521     elt->atts = NULL;
6522     elt->nstr = NULL;
6523     elt->data = NULL;
6524     elt->wide = NULL;
6525     elt->node = NULL;
6526     elt->type = 0;
6527     elt->head = NULL;
6528     elt->tail = NULL;
6529     if (soap->dom)
6530     { struct soap_dom_element *p = soap->dom->elts;
6531       if (p)
6532       { while (p->next)
6533           p = p->next;
6534         p->next = elt;
6535       }
6536       else
6537         soap->dom->elts = elt;
6538     }
6539     soap->dom = elt;
6540   }
6541   else
6542   {
6543 #endif
6544     soap->level++;
6545 #ifndef WITH_LEAN
6546     if (!soap->ns)
6547     { if (!(soap->mode & SOAP_XML_CANONICAL)
6548        && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
6549         return soap->error;
6550     }
6551     else if (soap->mode & SOAP_XML_INDENT)
6552     { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
6553         return soap->error;
6554       soap->body = 1;
6555     }
6556 #endif
6557 #ifdef WITH_XMLNS
6558     s = strchr(tag, ':');
6559     if (s && strncmp(tag, "SOAP-ENV", s - tag))
6560     { struct Namespace *ns = soap->local_namespaces;
6561       size_t n = s - tag;
6562       if (soap_send_raw(soap, "<", 1)
6563        || soap_send(soap, s + 1))
6564         return soap->error;
6565       if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
6566         ns = NULL;
6567       for (; ns && ns->id; ns++)
6568       { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
6569         { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
6570           if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
6571             return soap->error;
6572           break;
6573         }
6574       }   
6575     }
6576     else
6577 #endif
6578     if (soap_send_raw(soap, "<", 1)
6579      || soap_send(soap, tag))
6580       return soap->error;
6581 #ifdef WITH_DOM
6582   }
6583 #endif
6584   if (!soap->ns)
6585   { struct Namespace *ns;
6586     for (ns = soap->local_namespaces; ns && ns->id; ns++)
6587     { if (*ns->id && (ns->out || ns->ns))
6588       { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
6589         if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
6590           return soap->error;
6591       }
6592     }   
6593   }
6594   soap->ns = 1; /* start with 0 or 2, but should be one to continue */
6595 #ifndef WITH_LEAN
6596   if (soap->mode & SOAP_XML_CANONICAL)
6597   { const char *t = strchr(tag, ':');
6598     if (t)
6599       soap_utilize_ns(soap, tag, t - tag);
6600   }
6601 #endif
6602   if (id > 0)
6603   { sprintf(soap->tmpbuf, "_%d", id);
6604     if (soap_attribute(soap, "id", soap->tmpbuf))
6605       return soap->error;
6606   }
6607   if (type && *type)
6608   { if (soap_attribute(soap, "xsi:type", type))
6609       return soap->error;
6610 #ifndef WITH_LEAN
6611     if (soap->mode & SOAP_XML_CANONICAL)
6612     { const char *t = strchr(type, ':');
6613       if (t)
6614         soap_utilize_ns(soap, type, t - type);
6615     }
6616 #endif
6617   }
6618   if (soap->null && soap->position > 0)
6619   { register int i;
6620     sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
6621     for (i = 1; i < soap->position; i++)
6622       sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
6623     strcat(soap->tmpbuf, "]");
6624     if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
6625       return soap->error;
6626   }
6627   if (soap->mustUnderstand)
6628   { if (soap->actor && *soap->actor)
6629     { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
6630         return soap->error;
6631     }
6632     if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
6633       return soap->error;
6634     soap->mustUnderstand = 0;
6635   }
6636   if (soap->encoding)
6637   { if (soap->encodingStyle && soap->local_namespaces)
6638     { if (!*soap->encodingStyle)
6639       { if (soap->local_namespaces[1].out)
6640           soap->encodingStyle = soap->local_namespaces[1].out;
6641         else
6642           soap->encodingStyle = soap->local_namespaces[1].ns;
6643       }
6644       if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
6645         return soap->error;
6646     }
6647     soap->encoding = 0;
6648   }
6649   soap->null = 0;
6650   soap->position = 0;
6651   return SOAP_OK;
6652 }
6653 #endif
6654
6655 /******************************************************************************/
6656 #ifndef PALM_2
6657 SOAP_FMAC1
6658 int
6659 SOAP_FMAC2
6660 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
6661 { if (*tag == '-')
6662     return SOAP_OK;
6663   if (soap_element(soap, tag, id, type))
6664     return soap->error;
6665   return soap_element_start_end_out(soap, NULL);
6666 }
6667 #endif
6668
6669 /******************************************************************************/
6670 #ifndef PALM_2
6671 #ifndef HAVE_STRRCHR
6672 SOAP_FMAC1
6673 char*
6674 SOAP_FMAC2
6675 soap_strrchr(const char *s, int t)
6676 { register char *r = NULL;
6677   while (*s)
6678     if (*s++ == t)
6679       r = (char*)s - 1;
6680   return r;
6681 }
6682 #endif
6683 #endif
6684
6685 /******************************************************************************/
6686 #ifndef PALM_2
6687 #ifndef HAVE_STRTOL
6688 SOAP_FMAC1
6689 long
6690 SOAP_FMAC2
6691 soap_strtol(const char *s, char **t, int b)
6692 { register long n = 0;
6693   register int c;
6694   while (*s > 0 && *s <= 32)
6695     s++;
6696   if (b == 10)
6697   { short neg = 0;
6698     if (*s == '-')
6699     { s++;
6700       neg = 1;
6701     }
6702     else if (*s == '+')
6703       s++;
6704     while ((c = *s) && c >= '0' && c <= '9')
6705     { if (n >= 214748364 && (n > 214748364 || c >= '8'))
6706         break;
6707       n *= 10;
6708       n += c - '0';
6709       s++;
6710     }
6711     if (neg)
6712       n = -n;
6713   }
6714   else /* b == 16 and value is always positive */
6715   { while ((c = *s))
6716     { if (c >= '0' && c <= '9')
6717         c -= '0';
6718       else if (c >= 'A' && c <= 'F')
6719         c -= 'A' - 10;
6720       else if (c >= 'a' && c <= 'f')
6721         c -= 'a' - 10;
6722       if (n > 0x07FFFFFF)
6723         break;
6724       n <<= 4;
6725       n += c;
6726       s++;
6727     }
6728   }
6729   if (t)
6730     *t = (char*)s;
6731   return n;
6732 }
6733 #endif
6734 #endif
6735
6736 /******************************************************************************/
6737 #ifndef PALM_2
6738 #ifndef HAVE_STRTOUL
6739 SOAP_FMAC1
6740 unsigned long
6741 SOAP_FMAC2
6742 soap_strtoul(const char *s, char **t, int b)
6743 { unsigned long n = 0;
6744   register int c;
6745   while (*s > 0 && *s <= 32)
6746     s++;
6747   if (b == 10)
6748   { if (*s == '+')
6749       s++;
6750     while ((c = *s) && c >= '0' && c <= '9')
6751     { if (n >= 429496729 && (n > 429496729 || c >= '6'))
6752         break;
6753       n *= 10;
6754       n += c - '0';
6755       s++;
6756     }
6757   }
6758   else /* b == 16 */
6759   { while ((c = *s))
6760     { if (c >= '0' && c <= '9')
6761         c -= '0';
6762       else if (c >= 'A' && c <= 'F')
6763         c -= 'A' - 10;
6764       else if (c >= 'a' && c <= 'f')
6765         c -= 'a' - 10;
6766       if (n > 0x0FFFFFFF)
6767         break;
6768       n <<= 4;
6769       n += c;
6770       s++;
6771     }
6772   }
6773   if (t)
6774     *t = (char*)s;
6775   return n;
6776 }
6777 #endif
6778 #endif
6779
6780 /******************************************************************************/
6781 #ifndef PALM_1
6782 SOAP_FMAC1
6783 int
6784 SOAP_FMAC2
6785 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
6786 { if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
6787     return soap->error;
6788   if (soap->version == 2)
6789   { const char *s;
6790     s = soap_strrchr(type, '[');
6791     if ((size_t)(s - type) < sizeof(soap->tmpbuf))
6792     { strncpy(soap->tmpbuf, type, s - type);
6793       soap->tmpbuf[s - type] = '\0';
6794       if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)))
6795         return soap->error;
6796       if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
6797         return soap->error;
6798     }
6799   }
6800   else
6801   { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset)))
6802       return soap->error;
6803     if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type)))
6804       return soap->error;
6805   }
6806 #ifndef WITH_LEAN
6807   if (type && *type && (soap->mode & SOAP_XML_CANONICAL))
6808   { const char *s = strchr(type, ':');
6809     if (s)
6810       soap_utilize_ns(soap, type, s - type);
6811   }
6812 #endif
6813   return soap_element_start_end_out(soap, NULL);
6814 }
6815 #endif
6816
6817 /******************************************************************************/
6818 #ifndef PALM_1
6819 SOAP_FMAC1
6820 int
6821 SOAP_FMAC2
6822 soap_element_start_end_out(struct soap *soap, const char *tag)
6823 { register struct soap_attribute *tp;
6824 #ifndef WITH_LEAN
6825   if (soap->mode & SOAP_XML_CANONICAL)
6826   { struct soap_nlist *np;
6827     for (tp = soap->attributes; tp; tp = tp->next)
6828     { if (tp->visible && tp->name)
6829       { const char *s = strchr(tp->name, ':');
6830         if (s)
6831           soap_utilize_ns(soap, tp->name, s - tp->name);
6832       }
6833     }
6834     for (np = soap->nlist; np; np = np->next)
6835     { if (np->index == 1 && np->ns)
6836       { sprintf(soap->tmpbuf, "xmlns:%s", np->id);
6837         soap_set_attr(soap, soap->tmpbuf, np->ns);
6838         np->index = 2;
6839       }
6840     }
6841   }
6842 #endif
6843 #ifdef WITH_DOM
6844   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
6845   { register struct soap_dom_attribute **att;
6846     att = &soap->dom->atts;
6847     for (tp = soap->attributes; tp; tp = tp->next)
6848     { if (tp->visible)
6849       { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
6850         if (!*att)
6851           return soap->error = SOAP_EOM;
6852         (*att)->next = NULL;
6853         (*att)->nstr = NULL;
6854         (*att)->name = soap_strdup(soap, tp->name);
6855         (*att)->data = soap_strdup(soap, tp->value);
6856         (*att)->wide = NULL;
6857         (*att)->soap = soap;
6858         att = &(*att)->next;
6859         tp->visible = 0;
6860       }
6861     }
6862     return SOAP_OK;
6863   }
6864 #endif
6865   for (tp = soap->attributes; tp; tp = tp->next)
6866   { if (tp->visible)
6867     {
6868 #ifdef WITH_XMLNS
6869       const char *s = strchr(tp->name, ':');
6870       if (s)
6871       { size_t n = s - tp->name;
6872         if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
6873           s++;
6874         else
6875           s = tp->name;
6876         if (soap_send(soap, " ") || soap_send(soap, s))
6877           return soap->error;
6878       }
6879       else
6880 #endif
6881       if (soap_send(soap, " ") || soap_send(soap, tp->name))
6882         return soap->error;
6883       if (tp->visible == 2 && tp->value)
6884         if (soap_send_raw(soap, "=\"", 2)
6885          || soap_string_out(soap, tp->value, 1)
6886          || soap_send_raw(soap, "\"", 1))
6887           return soap->error;
6888       tp->visible = 0;
6889     }
6890   }
6891   if (tag)
6892   { 
6893 #ifndef WITH_LEAN
6894     if (soap->mode & SOAP_XML_CANONICAL)
6895     { if (soap_send_raw(soap, ">", 1)
6896        || soap_element_end_out(soap, tag))
6897         return soap->error;
6898       return SOAP_OK;
6899     }
6900 #endif
6901     soap->level--;      /* decrement level just before /> */
6902     if (soap_send_raw(soap, "/>", 2))
6903       return soap->error;
6904     return SOAP_OK;
6905   }
6906   return soap_send_raw(soap, ">", 1);
6907 }
6908 #endif
6909
6910 /******************************************************************************/
6911 #ifndef PALM_1
6912 SOAP_FMAC1
6913 int
6914 SOAP_FMAC2
6915 soap_element_end_out(struct soap *soap, const char *tag)
6916 { if (*tag == '-')
6917     return SOAP_OK;
6918   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
6919 #ifdef WITH_DOM
6920   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
6921   { if (soap->dom->prnt)
6922       soap->dom = soap->dom->prnt;
6923     return SOAP_OK;
6924   }
6925 #endif
6926 #ifndef WITH_LEAN
6927   if (soap->mode & SOAP_XML_CANONICAL)
6928     soap_pop_ns(soap);
6929   if (soap->mode & SOAP_XML_INDENT)
6930   { if (!soap->body)
6931     { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
6932         return soap->error;
6933     }
6934     soap->body = 0;
6935   }
6936 #endif
6937 #ifdef WITH_XMLNS
6938   { const char *s = strchr(tag, ':');
6939     if (s && strncmp(tag, "SOAP-ENV", s - tag))
6940     { soap_pop_ns(soap);
6941       tag = s + 1;
6942     }
6943   }
6944 #endif
6945   if (soap_send_raw(soap, "</", 2)
6946    || soap_send(soap, tag))
6947     return soap->error;
6948   soap->level--;        /* decrement level just before > */
6949   return soap_send_raw(soap, ">", 1);
6950 }
6951 #endif
6952
6953 /******************************************************************************/
6954 #ifndef PALM_1
6955 SOAP_FMAC1
6956 int
6957 SOAP_FMAC2
6958 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
6959 { register int n = 0;
6960   if (soap->version == 2)
6961     n = 1;
6962   sprintf(soap->href, "#_%d", href);
6963   return soap_element_href(soap, tag, id, "href" + n, soap->href + n);
6964 }
6965 #endif
6966
6967 /******************************************************************************/
6968 #ifndef PALM_1
6969 SOAP_FMAC1
6970 int
6971 SOAP_FMAC2
6972 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
6973 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
6974   if (soap_element(soap, tag, id, NULL)
6975    || soap_attribute(soap, ref, val)
6976    || soap_element_start_end_out(soap, tag))
6977     return soap->error;
6978   return SOAP_OK;
6979 }
6980 #endif
6981
6982 /******************************************************************************/
6983 #ifndef PALM_1
6984 SOAP_FMAC1
6985 int
6986 SOAP_FMAC2
6987 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
6988 { struct soap_attribute *tp;
6989   for (tp = soap->attributes; tp; tp = tp->next)
6990     if (tp->visible)
6991       break;
6992   if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
6993   { if (soap_element(soap, tag, id, type))
6994       return soap->error;
6995     if (soap->part != SOAP_IN_HEADER && soap->encodingStyle)
6996       if (soap_attribute(soap, "xsi:nil", "true"))
6997         return soap->error;
6998     return soap_element_start_end_out(soap, tag);
6999   }
7000   soap->null = 1;
7001   soap->position = 0;
7002   soap->mustUnderstand = 0;
7003   return SOAP_OK;
7004 }
7005 #endif
7006
7007 /******************************************************************************/
7008 #ifndef PALM_1
7009 SOAP_FMAC1
7010 int
7011 SOAP_FMAC2
7012 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) 
7013 { if (!p || (a && !a->__ptr))
7014   { soap_element_null(soap, tag, id, type);
7015     return -1;
7016   }
7017 #ifndef WITH_NOIDREF
7018   if (soap->mode & SOAP_XML_TREE)
7019     return 0;
7020   if (id < 0)
7021   { struct soap_plist *pp;
7022     if (a)
7023       id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
7024     else
7025       id = soap_pointer_lookup(soap, p, t, &pp);
7026     if (id)
7027     { if (soap_is_embedded(soap, pp))
7028       { soap_element_ref(soap, tag, 0, id);
7029         return -1;
7030       }
7031       if (soap_is_single(soap, pp))
7032         return 0;
7033       soap_set_embedded(soap, pp);
7034     }
7035   }
7036   return id;
7037 #else
7038   return 0;
7039 #endif
7040 }
7041 #endif
7042
7043 /******************************************************************************/
7044 #ifndef PALM_1
7045 SOAP_FMAC1
7046 int
7047 SOAP_FMAC2
7048 soap_element_result(struct soap *soap, const char *tag)
7049 { if (soap->version == 2 && soap->encodingStyle)
7050     if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
7051      || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
7052      || soap_element_start_end_out(soap, NULL)
7053      || soap_string_out(soap, tag, 0)
7054      || soap_element_end_out(soap, "SOAP-RPC:result"))
7055       return soap->error;
7056   return SOAP_OK;
7057 }
7058 #endif
7059
7060 /******************************************************************************/
7061 #ifndef PALM_1
7062 SOAP_FMAC1
7063 void
7064 SOAP_FMAC2
7065 soap_check_result(struct soap *soap, const char *tag)
7066 { if (soap->version == 2 && soap->encodingStyle)
7067   { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
7068     /* should compare tag to element's QName value? */
7069   }
7070 }
7071 #endif
7072
7073 /******************************************************************************/
7074 #ifndef PALM_2
7075 SOAP_FMAC1
7076 int
7077 SOAP_FMAC2
7078 soap_attribute(struct soap *soap, const char *name, const char *value)
7079
7080 #ifdef WITH_DOM
7081   if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
7082   { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
7083     a->next = soap->dom->atts;
7084     a->nstr = NULL;
7085     a->name = soap_strdup(soap, name);
7086     a->data = soap_strdup(soap, value);
7087     a->wide = NULL;
7088     a->soap = soap;
7089     soap->dom->atts = a;
7090     return SOAP_OK;
7091   }
7092 #endif
7093 #ifndef WITH_LEAN
7094   if (soap->mode & SOAP_XML_CANONICAL)
7095   { /* TODO: consider using this code to handle default namespace bindings
7096     if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
7097     { if (name[5] == ':')
7098         soap_push_ns(soap, name + 6, value, 0);
7099       else
7100         soap_push_ns(soap, "", value, 0);
7101     }
7102     */
7103     if (!strncmp(name, "xmlns:", 6))
7104       soap_push_ns(soap, name + 6, value, 0);
7105     else if (soap_set_attr(soap, name, value))
7106       return soap->error;
7107   }
7108   else
7109 #endif
7110   { if (soap_send(soap, " ") || soap_send(soap, name))
7111       return soap->error;
7112     if (value)
7113       if (soap_send_raw(soap, "=\"", 2)
7114        || soap_string_out(soap, value, 1)
7115        || soap_send_raw(soap, "\"", 1))
7116         return soap->error;
7117   }
7118   return SOAP_OK;
7119 }
7120 #endif
7121
7122 /******************************************************************************/
7123 #ifndef PALM_2
7124 SOAP_FMAC1
7125 int
7126 SOAP_FMAC2
7127 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
7128 { if (!soap_peek_element(soap))
7129   { if (soap->other)
7130       return soap->error = SOAP_TAG_MISMATCH;
7131     if (tag && *tag == '-')
7132       return SOAP_OK;
7133     if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
7134     { soap->peeked = 0;
7135       if (soap->body)
7136         soap->level++;
7137       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" ));
7138       if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
7139         return soap->error = SOAP_NULL;
7140       if (type && *soap->type && soap_match_tag(soap, soap->type, type))
7141         return soap->error = SOAP_TYPE;
7142     }
7143   }
7144   else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
7145     soap->error = SOAP_OK;
7146   return soap->error;
7147 }
7148 #endif
7149
7150 /******************************************************************************/
7151 #ifndef PALM_2
7152 SOAP_FMAC1
7153 int
7154 SOAP_FMAC2
7155 soap_element_end_in(struct soap *soap, const char *tag)  
7156 { register soap_wchar c;
7157   register char *s;
7158   register const char *t;
7159   register int n = 0;
7160   if (tag && *tag == '-')
7161     return SOAP_OK;
7162   soap->level--;
7163   soap_pop_namespace(soap);
7164 #ifdef WITH_DOM
7165   /* this whitespace or mixed content is not insignificant for DOM */
7166   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7167   { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
7168       return soap->error;
7169     if (soap->dom->prnt)
7170       soap->dom = soap->dom->prnt;
7171   }
7172 #endif
7173   if (soap->peeked)
7174   { if (soap->error == SOAP_NO_TAG)
7175       soap->error = SOAP_OK;
7176     if (*soap->tag)
7177       n++;
7178     soap->peeked = 0;
7179   }
7180   do
7181   { while (((c = soap_get(soap)) != SOAP_TT))
7182     { if ((int)c == EOF)
7183         return soap->error = SOAP_EOF;
7184       if (c == SOAP_LT)
7185         n++;
7186       else if (c == '/')
7187       { c = soap_get(soap);
7188         if (c == SOAP_GT)
7189           n--;
7190         else
7191           soap_unget(soap, c);
7192       }
7193     }
7194   } while (n--);
7195   s = soap->tag;
7196   while (soap_notblank(c = soap_get(soap)))
7197     *s++ = (char)c;
7198   *s = '\0';
7199   if ((int)c == EOF)
7200     return soap->error = SOAP_EOF;
7201   while (soap_blank(c))
7202     c = soap_get(soap);
7203   if (c != SOAP_GT)
7204     return soap->error = SOAP_SYNTAX_ERROR;
7205   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:""));
7206   if (!tag || !*tag)
7207     return SOAP_OK;
7208   if ((s = strchr(soap->tag, ':')))
7209     s++;
7210   else
7211     s = soap->tag;
7212   if ((t = strchr(tag, ':')))
7213     t++;
7214   else
7215     t = tag;
7216   if (!SOAP_STRCMP(s, t))
7217     return SOAP_OK;
7218   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n"));
7219   return soap->error = SOAP_SYNTAX_ERROR;
7220 }
7221 #endif
7222
7223 /******************************************************************************/
7224 #ifndef PALM_2
7225 SOAP_FMAC1
7226 const char *
7227 SOAP_FMAC2
7228 soap_attr_value(struct soap *soap, const char *name, int flag)
7229 { register struct soap_attribute *tp;
7230   for (tp = soap->attributes; tp; tp = tp->next)
7231   { if (tp->visible && !soap_match_tag(soap, tp->name, name))
7232       break;
7233   }
7234   if (tp)
7235   { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
7236       soap->error = SOAP_PROHIBITED;
7237     else
7238       return tp->value;
7239   }
7240   else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
7241     soap->error = SOAP_REQUIRED;
7242   return NULL;
7243 }
7244 #endif
7245
7246 /******************************************************************************/
7247 #ifndef PALM_2
7248 SOAP_FMAC1
7249 int
7250 SOAP_FMAC2
7251 soap_set_attr(struct soap *soap, const char *name, const char *value)
7252 { register struct soap_attribute *tp;
7253   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:""));
7254   for (tp = soap->attributes; tp; tp = tp->next)
7255   { if (!strcmp(tp->name, name))
7256       break;
7257   }
7258   if (!tp)
7259   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
7260     if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
7261       return soap->error = SOAP_EOM;
7262     tp->ns = NULL;
7263 #ifndef WITH_LEAN
7264     if (soap->mode & SOAP_XML_CANONICAL)
7265     { struct soap_attribute **tpp = &soap->attributes;
7266       const char *s = strchr(name, ':');
7267       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
7268       if (!strncmp(name, "xmlns", 5))
7269       { for (; *tpp; tpp = &(*tpp)->next)
7270           if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
7271             break;
7272       }
7273       else if (!s)
7274       { for (; *tpp; tpp = &(*tpp)->next)
7275           if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
7276             break;
7277       }
7278       else
7279       { int k;
7280         for (; *tpp; tpp = &(*tpp)->next)
7281         { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name])
7282           { if (!tp->ns)
7283             { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns));
7284               tp->ns = (*tpp)->ns;
7285             }
7286           }
7287           else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
7288             break;
7289         }
7290       }
7291       tp->next = *tpp;
7292       *tpp = tp;
7293     }
7294     else
7295 #endif
7296     { tp->next = soap->attributes;
7297       soap->attributes = tp;
7298     }
7299     strcpy(tp->name, name);
7300     tp->value = NULL;
7301   }
7302   else if (tp->visible)
7303   { return SOAP_OK;
7304   }
7305   else if (value && tp->value && tp->size <= strlen(value))
7306   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
7307     SOAP_FREE(soap, tp->value);
7308     tp->value = NULL;
7309     tp->ns = NULL;
7310   }
7311   if (value)
7312   { if (!tp->value)
7313     { tp->size = strlen(value) + 1;
7314       if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
7315         return soap->error = SOAP_EOM;
7316       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value));
7317     }
7318     strcpy(tp->value, value);
7319     if (!strncmp(tp->name, "xmlns:", 6))
7320       tp->ns = tp->value;
7321     tp->visible = 2;
7322 #ifndef WITH_LEAN
7323     if (!strcmp(name, "wsu:Id"))
7324     { soap->part = SOAP_BEGIN_SECURITY;
7325       strncpy(soap->id, value, sizeof(soap->id));
7326       soap->id[sizeof(soap->id)-1] = '\0';
7327     }
7328 #endif
7329   }
7330   else
7331     tp->visible = 1;
7332   return SOAP_OK;
7333 }
7334 #endif
7335
7336 /******************************************************************************/
7337 #ifndef PALM_2
7338 SOAP_FMAC1
7339 void
7340 SOAP_FMAC2
7341 soap_clr_attr(struct soap *soap)
7342 { register struct soap_attribute *tp;
7343 #ifndef WITH_LEAN
7344   if ((soap->mode & SOAP_XML_CANONICAL))
7345   { while (soap->attributes)
7346     { tp = soap->attributes->next;
7347       SOAP_FREE(soap, soap->attributes->value);
7348       SOAP_FREE(soap, soap->attributes);
7349       soap->attributes = tp;
7350     }
7351   }
7352   else
7353 #endif
7354   { for (tp = soap->attributes; tp; tp = tp->next)
7355       tp->visible = 0;
7356   }
7357 }
7358 #endif
7359
7360 /******************************************************************************/
7361 #ifndef PALM_2
7362 static int
7363 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
7364 { register size_t i;
7365   for (i = 0; i < n; i++)
7366   { register soap_wchar c = soap_get(soap);
7367     switch (c)
7368     {
7369     case SOAP_TT:
7370       *s++ = '<';
7371       soap_unget(soap, '/');
7372       break;
7373     case SOAP_LT:
7374       *s++ = '<';
7375       break;
7376     case SOAP_GT:
7377       if (d == ' ')
7378       { soap_unget(soap, c);
7379         *s = '\0';
7380         return SOAP_OK;
7381       }
7382       *s++ = '>';
7383       break;
7384     case SOAP_QT:
7385       if (c == d)
7386       { *s = '\0';
7387         return SOAP_OK;
7388       }
7389       *s++ = '"';
7390       break;
7391     case SOAP_AP:
7392       if (c == d)
7393       { *s = '\0';
7394         return SOAP_OK;
7395       }
7396       *s++ = '\'';
7397       break;
7398     case '\t':
7399     case '\n':
7400     case '\r':
7401     case ' ':
7402     case '/':
7403       if (d == ' ')
7404       { soap_unget(soap, c);
7405         *s = '\0';
7406         return SOAP_OK;
7407       }
7408     default:
7409       if ((int)c == EOF)
7410         return soap->error = SOAP_EOF;
7411       *s++ = (char)c;
7412     }
7413   }
7414   return soap->error = SOAP_EOM;
7415 }
7416 #endif
7417
7418 /******************************************************************************/
7419 #ifdef WITH_FAST
7420 #ifndef PALM_2
7421 SOAP_FMAC1
7422 int
7423 SOAP_FMAC2
7424 soap_store_lab(struct soap *soap, const char *s, size_t n)
7425 { soap->labidx = 0;
7426   return soap_append_lab(soap, s, n);
7427 }
7428 #endif
7429 #endif
7430
7431 /******************************************************************************/
7432 #ifdef WITH_FAST
7433 #ifndef PALM_2
7434 SOAP_FMAC1
7435 int
7436 SOAP_FMAC2
7437 soap_append_lab(struct soap *soap, const char *s, size_t n)
7438 { if (soap->labidx + n >= soap->lablen)
7439   { register char *t = soap->labbuf;
7440     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
7441     if (soap->lablen == 0)
7442       soap->lablen = SOAP_LABLEN;
7443     while (soap->labidx + n >= soap->lablen)
7444       soap->lablen <<= 1;
7445     DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
7446     soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
7447     if (!soap->labbuf)
7448     { if (t)
7449         SOAP_FREE(soap, t);
7450       return soap->error = SOAP_EOM;
7451     }
7452     if (t)
7453     { memcpy(soap->labbuf, t, soap->labidx);
7454       SOAP_FREE(soap, t);
7455     }
7456   }
7457   if (s)
7458   { memcpy(soap->labbuf + soap->labidx, s, n);
7459     soap->labidx += n;
7460   }
7461   return SOAP_OK;
7462 }
7463 #endif
7464 #endif
7465
7466 /******************************************************************************/
7467 #ifndef PALM_2
7468 SOAP_FMAC1
7469 int
7470 SOAP_FMAC2
7471 soap_peek_element(struct soap *soap)
7472 {
7473 #ifdef WITH_DOM
7474   register struct soap_dom_attribute **att = NULL;
7475   register char *lead = NULL;
7476 #endif
7477   register struct soap_attribute *tp;
7478   const char *t;
7479   register char *s;
7480   register soap_wchar c;
7481   register int i;
7482   if (soap->peeked)
7483   { if (!*soap->tag)
7484       return soap->error = SOAP_NO_TAG;
7485     return SOAP_OK;
7486   }
7487   soap->peeked = 1;
7488   c = soap_getutf8(soap);
7489 #ifdef WITH_DOM
7490   /* whitespace leading to start tag is not insignificant for DOM */
7491   if (soap_blank(c))
7492   { soap->labidx = 0;
7493     do
7494     { if (soap_append_lab(soap, NULL, 0))
7495         return SOAP_EOM;
7496       s = soap->labbuf + soap->labidx;
7497       i = soap->lablen - soap->labidx;
7498       soap->labidx = soap->lablen;
7499       while (soap_blank(c) && i--)
7500       { *s++ = c;
7501         c = soap_getutf8(soap);
7502       }
7503     }
7504     while (soap_blank(c));
7505     *s = '\0';
7506     lead = soap_strdup(soap, soap->labbuf);
7507   }
7508 #else
7509   while (soap_blank(c))
7510     c = soap_getutf8(soap);
7511 #endif
7512   if (c != SOAP_LT)
7513   { *soap->tag = '\0';
7514     if ((int)c == EOF)
7515       return soap->error = SOAP_EOF;
7516     soap_unget(soap, c);
7517 #ifdef WITH_DOM
7518     /* whitespace leading to end tag is not insignificant for DOM */
7519     if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7520       soap->dom->tail = soap_strdup(soap, lead);
7521 #endif
7522     return soap->error = SOAP_NO_TAG;
7523   }
7524   s = soap->tag;
7525   do c = soap_get1(soap);
7526   while (soap_blank(c));
7527   i = sizeof(soap->tag);
7528   while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
7529   { if (--i > 0)
7530       *s++ = (char)c;
7531     c = soap_get1(soap);
7532   }
7533   while (soap_blank(c))
7534     c = soap_get1(soap);
7535   *s = '\0';
7536   soap->id[0] = '\0';
7537   soap->href[0] = '\0';
7538   soap->type[0] = '\0';
7539   soap->arrayType[0] = '\0';
7540   soap->arraySize[0] = '\0';
7541   soap->arrayOffset[0] = '\0';
7542   soap->other = 0;
7543   soap->root = -1;
7544   soap->position = 0;
7545   soap->null = 0;
7546   soap->mustUnderstand = 0;
7547 #ifdef WITH_DOM
7548   if (soap->mode & SOAP_XML_DOM)
7549   { register struct soap_dom_element *elt;
7550     elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
7551     if (!elt)
7552       return soap->error = SOAP_EOM;
7553     elt->next = NULL;
7554     elt->nstr = NULL;
7555     elt->name = soap_strdup(soap, soap->tag);
7556     elt->prnt = soap->dom;
7557     elt->elts = NULL;
7558     elt->atts = NULL;
7559     elt->data = NULL;
7560     elt->wide = NULL;
7561     elt->type = 0;
7562     elt->node = NULL;
7563     elt->head = lead;
7564     elt->tail = NULL;
7565     elt->soap = soap;
7566     if (soap->dom)
7567     { struct soap_dom_element *p = soap->dom->elts;
7568       if (p)
7569       { while (p->next)
7570           p = p->next;
7571         p->next = elt;
7572       }
7573       else
7574         soap->dom->elts = elt;
7575     }
7576     soap->dom = elt;
7577     att = &elt->atts;
7578   }
7579 #endif
7580   for (tp = soap->attributes; tp; tp = tp->next)
7581     tp->visible = 0;
7582   while ((int)c != EOF && c != '>' && c != '/')
7583   { s = soap->tmpbuf;
7584     i = sizeof(soap->tmpbuf);
7585     while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
7586     { if (--i > 0)
7587         *s++ = (char)c;
7588       c = soap_get1(soap);
7589     }
7590     *s = '\0';
7591     if (i == sizeof(soap->tmpbuf))
7592       return soap->error = SOAP_SYNTAX_ERROR;
7593 #ifdef WITH_DOM
7594     /* add attribute name to dom */
7595     if (att)
7596     { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
7597        if (!*att)
7598          return soap->error = SOAP_EOM;
7599        (*att)->next = NULL;
7600        (*att)->nstr = NULL;
7601        (*att)->name = soap_strdup(soap, soap->tmpbuf);
7602        (*att)->data = NULL;
7603        (*att)->wide = NULL;
7604        (*att)->soap = soap;
7605     }
7606 #endif
7607     if (!strncmp(soap->tmpbuf, "xmlns", 5))
7608     { if (soap->tmpbuf[5] == ':')
7609       { soap->tmpbuf[5] = '\0';
7610         t = soap->tmpbuf + 6;
7611       }
7612       else if (soap->tmpbuf[5])
7613         t = NULL;
7614       else
7615         t = SOAP_STR_EOS;
7616     }
7617     else
7618       t = NULL;
7619     for (tp = soap->attributes; tp; tp = tp->next)
7620     { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
7621         break;
7622     }
7623     if (!tp)
7624     { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
7625       if (!tp)
7626         return soap->error = SOAP_EOM;
7627       strcpy(tp->name, soap->tmpbuf);
7628       tp->value = NULL;
7629       tp->size = 0;
7630       tp->next = soap->attributes;
7631       soap->attributes = tp;
7632     }
7633     while (soap_blank(c))
7634       c = soap_get1(soap);
7635     if (c == '=')
7636     { do c = soap_getutf8(soap);
7637       while (soap_blank(c));
7638       if (c != SOAP_QT && c != SOAP_AP)
7639       { soap_unget(soap, c);
7640         c = ' '; /* blank delimiter */
7641       }
7642       if (soap_getattrval(soap, tp->value, tp->size, c))
7643       {
7644 #ifdef WITH_FAST
7645         if (soap->error != SOAP_EOM)
7646           return soap->error;
7647         soap->error = SOAP_OK;
7648         if (soap_store_lab(soap, tp->value, tp->size))
7649           return soap->error;
7650         if (tp->value)
7651           SOAP_FREE(soap, tp->value);
7652         for (;;)
7653         { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
7654           { if (soap->error != SOAP_EOM)
7655               return soap->error;
7656             soap->error = SOAP_OK;
7657             soap->labidx = soap->lablen;
7658             if (soap_append_lab(soap, NULL, 0))
7659               return soap->error;
7660           }
7661           else
7662             break;
7663         }
7664         if (soap->labidx)
7665           tp->size = soap->lablen;
7666         else
7667         { tp->size = strlen(soap->labbuf) + 1;
7668           if (tp->size < SOAP_LABLEN)
7669             tp->size = SOAP_LABLEN;
7670         }
7671         if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
7672           return soap->error = SOAP_EOM;
7673         strcpy(tp->value, soap->labbuf);
7674 #else
7675         size_t n;
7676         if (soap->error != SOAP_EOM)
7677           return soap->error;
7678         soap->error = SOAP_OK;
7679         if (soap_new_block(soap))
7680           return soap->error;
7681         for (;;)
7682         { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN)))
7683             return soap->error;
7684           if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
7685           { if (soap->error != SOAP_EOM)
7686               return soap->error;
7687             soap->error = SOAP_OK;
7688           }
7689           else
7690             break;
7691         }
7692         n = tp->size + soap->blist->size;
7693         if (!(s = (char*)SOAP_MALLOC(soap, n)))
7694           return soap->error = SOAP_EOM;
7695         if (tp->value)
7696         { memcpy(s, tp->value, tp->size);
7697           SOAP_FREE(soap, tp->value);
7698         }
7699         soap_save_block(soap, s + tp->size, 0);
7700         tp->value = s;
7701         tp->size = n;
7702 #endif
7703       }
7704       do c = soap_get1(soap);
7705       while (soap_blank(c));
7706       tp->visible = 2; /* seen this attribute w/ value */
7707 #ifdef WITH_DOM
7708       if (att)
7709         (*att)->data = soap_strdup(soap, tp->value);
7710 #endif
7711     }
7712     else
7713       tp->visible = 1; /* seen this attribute w/o value */
7714 #ifdef WITH_DOM
7715     if (att)
7716       att = &(*att)->next;
7717 #endif
7718     if (t && tp->value)
7719     { if (soap_push_namespace(soap, t, tp->value))
7720         return soap->error;
7721       tp->visible = 0;
7722     }
7723   }
7724 #ifdef WITH_DOM
7725   if (att)
7726   { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
7727     for (att = &soap->dom->atts; *att; att = &(*att)->next)
7728       (*att)->nstr = soap_current_namespace(soap, (*att)->name);
7729   }
7730 #endif
7731   if ((int)c == EOF)
7732     return soap->error = SOAP_EOF;
7733   if (!(soap->body = (c != '/')))
7734     do c = soap_get1(soap);
7735     while (soap_blank(c));
7736 #ifdef WITH_DOM
7737   if (soap->mode & SOAP_XML_DOM)
7738   { if (!soap->body && soap->dom->prnt)
7739       soap->dom = soap->dom->prnt;
7740   }
7741 #endif
7742   for (tp = soap->attributes; tp; tp = tp->next)
7743   { if (tp->visible && tp->value)
7744     { if (!strcmp(tp->name, "id"))
7745       { *soap->id = '#';
7746         strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
7747         soap->id[sizeof(soap->id)-1] = '\0';
7748       }
7749       else if (!strcmp(tp->name, "href"))
7750       { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
7751         soap->href[sizeof(soap->href)-1] = '\0';
7752       }
7753       else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref"))
7754       { *soap->href = '#';
7755         strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
7756         soap->href[sizeof(soap->href)-1] = '\0';
7757       }
7758       else if (!soap_match_tag(soap, tp->name, "xsi:type"))
7759       { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
7760         soap->type[sizeof(soap->type)-1] = '\0';
7761       }
7762       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
7763       { s = soap_strrchr(tp->value, '[');
7764         if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
7765         { strncpy(soap->arrayType, tp->value, s - tp->value);
7766           soap->arrayType[s - tp->value] = '\0';
7767           strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
7768         }
7769         else
7770           strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
7771         soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
7772         soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
7773       }
7774       else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
7775         strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
7776       else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
7777         strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
7778       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
7779         strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
7780       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
7781         soap->position = soap_getposition(tp->value, soap->positions);
7782       else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
7783         soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
7784       else if ((soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
7785             || (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENV:role")))
7786       { if ((!soap->actor || strcmp(soap->actor, tp->value))
7787          && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")
7788          && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
7789           soap->other = 1;
7790       }
7791       else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
7792             && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
7793         soap->mustUnderstand = 1;
7794       else if ((!soap_match_tag(soap, tp->name, "xsi:null")
7795              || !soap_match_tag(soap, tp->name, "xsi:nil"))
7796             && (!strcmp(tp->value, "1")
7797              || !strcmp(tp->value, "true")))
7798         soap->null = 1;
7799     }
7800   }
7801   return soap->error = SOAP_OK;
7802 }
7803 #endif
7804
7805 /******************************************************************************/
7806 #ifndef PALM_2
7807 SOAP_FMAC1
7808 void
7809 SOAP_FMAC2
7810 soap_retry(struct soap *soap)
7811 { soap->error = SOAP_OK;
7812   soap_revert(soap);
7813 }
7814 #endif
7815
7816 /******************************************************************************/
7817 #ifndef PALM_2
7818 SOAP_FMAC1
7819 void
7820 SOAP_FMAC2
7821 soap_revert(struct soap *soap)
7822 { if (!soap->peeked)
7823   { soap->peeked = 1;
7824     if (soap->body)
7825       soap->level--;
7826   }
7827   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
7828 }
7829 #endif
7830
7831 /******************************************************************************/
7832 #ifndef PALM_2
7833 SOAP_FMAC1
7834 int
7835 SOAP_FMAC2
7836 soap_string_out(struct soap *soap, const char *s, int flag)
7837 { register const char *t;
7838   register soap_wchar c;
7839   register soap_wchar mask = 0xFFFFFF80UL;
7840 #ifdef WITH_DOM
7841   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7842   { soap->dom->data = soap_strdup(soap, s);
7843     return SOAP_OK;
7844   }
7845 #endif
7846   if (soap->mode & SOAP_C_UTFSTRING)
7847     mask = 0;
7848   t = s;
7849   while ((c = *t++))
7850   { switch (c)
7851     { 
7852     case 9:
7853       if (flag)
7854       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
7855           return soap->error;
7856         s = t;
7857       }
7858       break;
7859     case 10:
7860       if (flag || !(soap->mode & SOAP_XML_CANONICAL))
7861       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
7862           return soap->error;
7863         s = t;
7864       }
7865       break;
7866     case 13:
7867       if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xD;", 5))
7868         return soap->error;
7869       s = t;
7870       break;
7871     case '&':
7872       if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
7873         return soap->error;
7874       s = t;
7875       break;
7876     case '<':
7877       if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
7878         return soap->error;
7879       s = t;
7880       break;
7881     case '>':
7882       if (!flag)
7883       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
7884           return soap->error;
7885         s = t;
7886       }
7887       break;
7888     case '"':
7889       if (flag)
7890       { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
7891           return soap->error;
7892         s = t;
7893       }
7894       break;
7895     default:
7896 #ifndef WITH_LEANER
7897 #ifdef HAVE_MBTOWC
7898       if (soap->mode & SOAP_C_MBSTRING)
7899       { wchar_t wc;
7900         register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
7901         if (m > 0 && wc != c)
7902         { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
7903             return soap->error;
7904           s = t += m - 1;
7905           continue;
7906         }
7907       }
7908 #endif
7909 #endif
7910       if (c & mask)
7911       { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
7912           return soap->error;
7913         s = t;
7914       }
7915     }
7916   }
7917   return soap_send_raw(soap, s, t - s - 1);
7918 }
7919 #endif
7920
7921 /******************************************************************************/
7922 #ifndef PALM_2
7923 SOAP_FMAC1
7924 char *
7925 SOAP_FMAC2
7926 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
7927 { register char *s;
7928   char *t = NULL;
7929   register size_t i;
7930   register long l = 0;
7931   register int n = 0;
7932   register int m = 0;
7933   register soap_wchar c;
7934 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
7935   char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
7936 #else
7937   char buf[8];
7938 #endif
7939   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n"));
7940   if (soap->peeked)
7941   { if (!soap->body)
7942       return NULL;
7943     if (*soap->tag)
7944     { n = 1;
7945       soap->peeked = 0;
7946 #ifndef WITH_LEAN
7947       t = soap->tmpbuf;
7948       t[0] = '<';
7949       strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1);
7950       strncat(t, ">", sizeof(soap->tmpbuf));
7951       m = strlen(soap->tag) + 2;
7952 #endif
7953     }
7954   }
7955 #ifdef WITH_CDATA
7956   if (!flag)
7957   { register int state = 0;
7958 #ifdef WITH_FAST
7959     soap->labidx = 0;                   /* use look-aside buffer */
7960 #else
7961     if (soap_new_block(soap))
7962       return NULL;
7963 #endif
7964     for (;;)
7965     { 
7966 #ifdef WITH_FAST
7967       register size_t k;
7968       if (soap_append_lab(soap, NULL, 0))       /* allocate more space in look-aside buffer if necessary */
7969         return NULL;
7970       s = soap->labbuf + soap->labidx;  /* space to populate */
7971       k = soap->lablen - soap->labidx;  /* number of bytes available */
7972       soap->labidx = soap->lablen;      /* claim this space */
7973 #else
7974       register size_t k = SOAP_BLKLEN;
7975       if (!(s = (char*)soap_push_block(soap, k)))
7976         return NULL;
7977 #endif
7978       for (i = 0; i < k; i++)
7979       { if (m > 0)
7980         { *s++ = *t++;  /* copy multibyte characters */
7981           m--;
7982           continue;
7983         }
7984         c = soap_getchar(soap);
7985         if ((int)c == EOF)
7986           goto end;
7987         if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN))
7988         { soap_unget(soap, c);
7989           c = soap_getutf8(soap);
7990           if (soap->mode & SOAP_C_UTFSTRING)
7991           { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
7992             { c &= 0x7FFFFFFF;
7993               t = buf;
7994               if (c < 0x0800)
7995                 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
7996               else
7997               { if (c < 0x010000)
7998                   *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
7999                 else
8000                 { if (c < 0x200000)
8001                     *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
8002                   else
8003                   { if (c < 0x04000000)
8004                       *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
8005                     else
8006                     { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
8007                       *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
8008                     }
8009                     *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
8010                   }     
8011                   *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
8012                 }
8013                 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
8014               }
8015               *t++ = (char)(0x80 | (c & 0x3F));
8016               m = (int)(t - buf) - 1;
8017               t = buf;
8018               *s++ = *t++;
8019               continue;
8020             }
8021           }
8022         }
8023         switch (state)
8024         { case 1:
8025             if (c == ']')
8026               state = 4;
8027             *s++ = c;
8028             continue;
8029           case 2:
8030             if (c == '-')
8031               state = 6;
8032             *s++ = c;
8033             continue;
8034           case 3:
8035             if (c == '?')
8036               state = 8;
8037             *s++ = c;
8038             continue;
8039           /* CDATA */
8040           case 4:
8041             if (c == ']')
8042               state = 5;
8043             else
8044               state = 1;
8045             *s++ = c;
8046             continue;
8047           case 5:
8048             if (c == '>')
8049               state = 0;
8050             else
8051               state = 1;
8052             *s++ = c;
8053             continue;
8054           /* comment */
8055           case 6:
8056             if (c == '-')
8057               state = 7;
8058             else
8059               state = 2;
8060             *s++ = c;
8061             continue;
8062           case 7:
8063             if (c == '>')
8064               state = 0;
8065             else
8066               state = 2;
8067             *s++ = c;
8068             continue;
8069           /* PI */
8070           case 8:
8071             if (c == '>')
8072               state = 0;
8073             else
8074               state = 3;
8075             *s++ = c;
8076             continue;
8077         }
8078         switch (c)
8079         {
8080         case '/':
8081           if (n > 0)
8082           { c = soap_getchar(soap);
8083             if (c == '>')
8084               n--;
8085             soap_unget(soap, c);
8086           }
8087           *s++ = '/';
8088           break;
8089         case '<':
8090           c = soap_getchar(soap);
8091           if (c == '/')
8092           { if (n == 0)
8093             { c = SOAP_TT;
8094               goto end;
8095             }
8096             n--;
8097           }
8098           else if (c == '!')
8099           { c = soap_getchar(soap);
8100             if (c == '[')
8101             { do c = soap_getchar(soap);
8102               while ((int)c != EOF && c != '[');
8103               if ((int)c == EOF)
8104                  goto end;
8105               t = (char*)"![CDATA[";
8106               m = 8;
8107               state = 1;
8108             }
8109             else if (c == '-')
8110             { if ((c = soap_getchar(soap)) == '-')
8111                 state = 2;
8112               t = (char*)"!-";
8113               m = 2;
8114               soap_unget(soap, c);
8115             }
8116             else
8117             { t = (char*)"!";
8118               m = 1;
8119               soap_unget(soap, c);
8120             }
8121             *s++ = '<';
8122             break;
8123           }
8124           else if (c == '?')
8125             state = 3;
8126           else
8127             n++;
8128           soap_unget(soap, c);
8129           *s++ = '<';
8130           break;
8131         case '>':
8132           *s++ = '>';
8133           break;
8134         case '"':
8135           *s++ = '"';
8136           break;
8137         default:
8138 #ifndef WITH_LEANER
8139 #ifdef HAVE_WCTOMB
8140           if (soap->mode & SOAP_C_MBSTRING)
8141           { m = wctomb(buf, c & 0x7FFFFFFF);
8142             if (m >= 1 && m <= (int)MB_CUR_MAX)
8143             { t = buf;
8144               *s++ = *t++;
8145               m--;
8146             }
8147             else
8148             { *s++ = SOAP_UNKNOWN_CHAR;
8149               m = 0;
8150             }
8151           }
8152           else
8153 #endif
8154 #endif
8155             *s++ = (char)(c & 0xFF);
8156         }
8157         l++;
8158         if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8159         { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8160           soap->error = SOAP_LENGTH;
8161           return NULL;
8162         }
8163       }
8164     }
8165   }
8166 #endif
8167 #ifdef WITH_FAST
8168   soap->labidx = 0;                     /* use look-aside buffer */
8169 #else
8170   if (soap_new_block(soap))
8171     return NULL;
8172 #endif
8173   for (;;)
8174   { 
8175 #ifdef WITH_FAST
8176     register size_t k;
8177     if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
8178       return NULL;
8179     s = soap->labbuf + soap->labidx;    /* space to populate */
8180     k = soap->lablen - soap->labidx;    /* number of bytes available */
8181     soap->labidx = soap->lablen;        /* claim this space */
8182 #else
8183     register size_t k = SOAP_BLKLEN;
8184     if (!(s = (char*)soap_push_block(soap, k)))
8185       return NULL;
8186 #endif
8187     for (i = 0; i < k; i++)
8188     { if (m > 0)
8189       { *s++ = *t++;    /* copy multibyte characters */
8190         m--;
8191         continue;
8192       }
8193       if (soap->mode & SOAP_C_UTFSTRING)
8194       { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
8195         { c &= 0x7FFFFFFF;
8196           t = buf;
8197           if (c < 0x0800)
8198             *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
8199           else
8200           { if (c < 0x010000)
8201               *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
8202             else
8203             { if (c < 0x200000)
8204                 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
8205               else
8206               { if (c < 0x04000000)
8207                   *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
8208                 else
8209                 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
8210                   *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
8211                 }
8212                 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
8213               }     
8214               *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
8215             }
8216             *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
8217           }
8218           *t++ = (char)(0x80 | (c & 0x3F));
8219           m = (int)(t - buf) - 1;
8220           t = buf;
8221           *s++ = *t++;
8222           continue;
8223         }
8224       }
8225       else
8226         c = soap_getutf8(soap);
8227       switch (c)
8228       {
8229       case SOAP_TT:
8230         if (n == 0)
8231           goto end;
8232         n--;
8233         *s++ = '<';
8234         t = (char*)"/";
8235         m = 1;
8236         break;
8237       case SOAP_LT:
8238         n++;
8239         *s++ = '<';
8240         break;
8241       case SOAP_GT:
8242         *s++ = '>';
8243         break;
8244       case SOAP_QT:
8245         *s++ = '"';
8246         break;
8247       case SOAP_AP:
8248         *s++ = '\'';
8249         break;
8250       case '/':
8251         if (n > 0)
8252         { c = soap_get(soap);
8253           if (c == SOAP_GT)
8254             n--;
8255           soap_unget(soap, c);
8256         }
8257         *s++ = '/';
8258         break;
8259       case '<' | 0x80000000:
8260         if (flag)
8261           *s++ = '<';
8262         else
8263         { *s++ = '&';
8264           t = (char*)"lt;";
8265           m = 3;
8266         }
8267         break;
8268       case '>' | 0x80000000:
8269         if (flag)
8270           *s++ = '>';
8271         else
8272         { *s++ = '&';
8273           t = (char*)"gt;";
8274           m = 3;
8275         }
8276         break;
8277       case '&' | 0x80000000:
8278         if (flag)
8279           *s++ = '&';
8280         else
8281         { *s++ = '&';
8282           t = (char*)"amp;";
8283           m = 4;
8284         }
8285         break;
8286       case '"' | 0x80000000:
8287         if (flag)
8288           *s++ = '"';
8289         else
8290         { *s++ = '&';
8291           t = (char*)"quot;";
8292           m = 5;
8293         }
8294         break;
8295       case '\'' | 0x80000000:
8296         if (flag)
8297           *s++ = '\'';
8298         else
8299         { *s++ = '&';
8300           t = (char*)"apos;";
8301           m = 5;
8302         }
8303         break;
8304       default:
8305         if ((int)c == EOF)
8306           goto end;
8307 #ifndef WITH_LEANER
8308 #ifdef HAVE_WCTOMB
8309         if (soap->mode & SOAP_C_MBSTRING)
8310         { m = wctomb(buf, c & 0x7FFFFFFF);
8311           if (m >= 1 && m <= (int)MB_CUR_MAX)
8312           { t = buf;
8313             *s++ = *t++;
8314             m--;
8315           }
8316           else
8317           { *s++ = SOAP_UNKNOWN_CHAR;
8318             m = 0;
8319           }
8320         }
8321         else
8322 #endif
8323 #endif
8324           *s++ = (char)(c & 0xFF);
8325       }
8326       l++;
8327       if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8328       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8329         soap->error = SOAP_LENGTH;
8330         return NULL;
8331       }
8332     }
8333   }
8334 end:
8335   soap_unget(soap, c);
8336   *s = '\0';
8337 #ifdef WITH_FAST
8338   t = soap_strdup(soap, soap->labbuf);
8339 #else
8340   soap_size_block(soap, i+1);
8341   t = soap_save_block(soap, NULL, 0);
8342 #endif
8343   if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
8344   { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
8345     soap->error = SOAP_LENGTH;
8346     return NULL;
8347   }
8348 #ifdef WITH_DOM
8349   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8350   { if (flag == 3)
8351       soap->dom->tail = t;
8352     else
8353       soap->dom->data = t;
8354   }
8355 #endif
8356   if (flag == 2)
8357     if (soap_s2QName(soap, t, &t))
8358       return NULL;
8359   return t;
8360 }
8361 #endif
8362
8363 /******************************************************************************/
8364 #ifndef WITH_LEANER
8365 #ifndef PALM_2
8366 SOAP_FMAC1
8367 int
8368 SOAP_FMAC2
8369 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
8370 { const char *t;
8371   char tmp;
8372   register soap_wchar c;
8373 #ifdef WITH_DOM
8374   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8375   { wchar_t *r = (wchar_t*)s;
8376     int n = 1;
8377     while (*r++)
8378       n++;
8379     soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
8380     while (n--)
8381       *r++ = *s++;
8382     return SOAP_OK;
8383   }
8384 #endif
8385   while ((c = *s++))
8386   { switch (c)
8387     { 
8388     case 9:
8389       if (flag)
8390         t = "&#x9;";
8391       else
8392         t = "\t";
8393       break;
8394     case 10:
8395       if (flag || !(soap->mode & SOAP_XML_CANONICAL))
8396         t = "&#xA;";
8397       else
8398         t = "\n";
8399       break;
8400     case 13:
8401       t = "&#xD;";
8402       break;
8403     case '&':
8404       t = "&amp;";
8405       break;
8406     case '<':
8407       t = "&lt;";
8408       break;
8409     case '>':
8410       if (flag)
8411         t = ">";
8412       else
8413         t = "&gt;";
8414       break;
8415     case '"':
8416       if (flag)
8417         t = "&quot;";
8418       else
8419         t = "\"";
8420       break;
8421     default:
8422       if (c > 0 && c < 0x80)
8423       { tmp = (char)c;
8424         if (soap_send_raw(soap, &tmp, 1))
8425           return soap->error;
8426       }
8427       else if (soap_pututf8(soap, (unsigned long)c))
8428         return soap->error;
8429       continue;
8430     }
8431     if (soap_send(soap, t))
8432       return soap->error;
8433   }
8434   return SOAP_OK;
8435 }
8436 #endif
8437 #endif
8438
8439 /******************************************************************************/
8440 #ifndef WITH_LEANER
8441 #ifndef PALM_2
8442 SOAP_FMAC1
8443 wchar_t *
8444 SOAP_FMAC2
8445 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
8446 { wchar_t *s;
8447   register int i, n = 0;
8448   register long l = 0;
8449   register soap_wchar c;
8450   const char *t = NULL;
8451   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
8452   if (soap->peeked)
8453   { if (!soap->body)
8454       return NULL;
8455     if (*soap->tag)
8456     { n = 1;
8457       soap->peeked = 0;
8458     }
8459   }
8460   if (soap_new_block(soap))
8461     return NULL;
8462   for (;;)
8463   { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN)))
8464       return NULL;
8465     for (i = 0; i < SOAP_BLKLEN; i++)
8466     { if (t)
8467       { *s++ = (wchar_t)*t++;
8468         if (!*t)
8469           t = NULL;
8470         continue;
8471       }
8472       c = soap_getutf8(soap);
8473       switch (c)
8474       {
8475       case SOAP_TT:
8476         if (n == 0)
8477           goto end;
8478         n--;
8479         *s++ = '<';
8480         soap_unget(soap, '/');
8481         break;
8482       case SOAP_LT:
8483         n++;
8484         *s++ = '<';
8485         break;
8486       case SOAP_GT:
8487         *s++ = '>';
8488         break;
8489       case SOAP_QT:
8490         *s++ = '"';
8491         break;
8492       case SOAP_AP:
8493         *s++ = '\'';
8494         break;
8495       case '/':
8496         if (n > 0)
8497         { c = soap_getutf8(soap);
8498           if (c == SOAP_GT)
8499             n--;
8500           soap_unget(soap, c);
8501         }
8502         *s++ = '/';
8503         break;
8504       case '<':
8505         if (flag)
8506           *s++ = (soap_wchar)'<';
8507         else
8508         { *s++ = (soap_wchar)'&';
8509           t = "lt;";
8510         }
8511         break;
8512       case '>':
8513         if (flag)
8514           *s++ = (soap_wchar)'>';
8515         else
8516         { *s++ = (soap_wchar)'&';
8517           t = "gt;";
8518         }
8519         break;
8520       case '"':
8521         if (flag)
8522           *s++ = (soap_wchar)'"';
8523         else
8524         { *s++ = (soap_wchar)'&';
8525           t = "quot;";
8526         }
8527         break;
8528       default:
8529         if ((int)c == EOF)
8530           goto end;
8531         *s++ = (wchar_t)c & 0x7FFFFFFF;
8532       }
8533       l++;
8534       if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8535       { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8536         soap->error = SOAP_LENGTH;
8537         return NULL;
8538       }
8539     }
8540   }
8541 end:
8542   soap_unget(soap, c);
8543   *s = '\0';
8544   soap_size_block(soap, sizeof(wchar_t) * (i + 1));
8545   if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
8546   { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
8547     soap->error = SOAP_LENGTH;
8548     return NULL;
8549   }
8550   s = (wchar_t*)soap_save_block(soap, NULL, 0);
8551 #ifdef WITH_DOM
8552   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8553     soap->dom->wide = s;
8554 #endif
8555   return s;
8556 }
8557 #endif
8558 #endif
8559
8560 /******************************************************************************/
8561 #ifndef PALM_2
8562 SOAP_FMAC1
8563 const char*
8564 SOAP_FMAC2
8565 soap_int2s(struct soap *soap, int n)
8566 { return soap_long2s(soap, (long)n);
8567 }
8568 #endif
8569
8570 /******************************************************************************/
8571 #ifndef PALM_2
8572 SOAP_FMAC1
8573 int
8574 SOAP_FMAC2
8575 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
8576 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8577    || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
8578     return soap->error;
8579   return soap_element_end_out(soap, tag);
8580 }
8581 #endif
8582
8583 /******************************************************************************/
8584 #ifndef PALM_2
8585 SOAP_FMAC1
8586 int
8587 SOAP_FMAC2
8588 soap_s2int(struct soap *soap, const char *s, int *p)
8589 { if (s)
8590   { char *r;
8591 #ifndef WITH_NOIO
8592 #ifndef WITH_LEAN
8593     soap_reset_errno;
8594 #endif
8595 #endif
8596     *p = (int)soap_strtol(s, &r, 10);
8597     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
8598 #ifndef WITH_NOIO
8599 #ifndef WITH_LEAN
8600      || soap_errno == SOAP_ERANGE
8601 #endif
8602 #endif
8603     )
8604       soap->error = SOAP_TYPE;
8605   }
8606   return soap->error;
8607 }
8608 #endif
8609
8610 /******************************************************************************/
8611 #ifndef PALM_2
8612 SOAP_FMAC1
8613 int *
8614 SOAP_FMAC2
8615 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
8616 { if (soap_element_begin_in(soap, tag, 0, NULL))
8617     return NULL;
8618 #ifndef WITH_LEAN
8619   if (*soap->type
8620    && soap_match_tag(soap, soap->type, type)
8621    && soap_match_tag(soap, soap->type, ":int")
8622    && soap_match_tag(soap, soap->type, ":short")
8623    && soap_match_tag(soap, soap->type, ":byte"))
8624   { soap->error = SOAP_TYPE;
8625     soap_revert(soap);
8626     return NULL;
8627   }
8628 #endif
8629   p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
8630   if (*soap->href)
8631     p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
8632   else if (p)
8633   { if (soap_s2int(soap, soap_value(soap), p))
8634       return NULL;
8635   }
8636   if (soap->body && soap_element_end_in(soap, tag))
8637     return NULL;
8638   return p;
8639 }
8640 #endif
8641
8642 /******************************************************************************/
8643 #ifndef PALM_2
8644 SOAP_FMAC1
8645 const char*
8646 SOAP_FMAC2
8647 soap_long2s(struct soap *soap, long n)
8648 { sprintf(soap->tmpbuf, "%ld", n);
8649   return soap->tmpbuf;
8650 }
8651 #endif
8652
8653 /******************************************************************************/
8654 #ifndef PALM_2
8655 SOAP_FMAC1
8656 int
8657 SOAP_FMAC2
8658 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
8659 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8660    || soap_string_out(soap, soap_long2s(soap, *p), 0))
8661     return soap->error;
8662   return soap_element_end_out(soap, tag);
8663 }
8664 #endif
8665
8666 /******************************************************************************/
8667 #ifndef PALM_2
8668 SOAP_FMAC1
8669 int
8670 SOAP_FMAC2
8671 soap_s2long(struct soap *soap, const char *s, long *p)
8672 { if (s)
8673   { char *r;
8674 #ifndef WITH_NOIO
8675 #ifndef WITH_LEAN
8676     soap_reset_errno;
8677 #endif
8678 #endif
8679     *p = soap_strtol(s, &r, 10);
8680     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
8681 #ifndef WITH_NOIO
8682 #ifndef WITH_LEAN
8683      || soap_errno == SOAP_ERANGE
8684 #endif
8685 #endif
8686     )
8687       soap->error = SOAP_TYPE;
8688   }
8689   return soap->error;
8690 }
8691 #endif
8692
8693 /******************************************************************************/
8694 #ifndef PALM_2
8695 SOAP_FMAC1
8696 long *
8697 SOAP_FMAC2
8698 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
8699 { if (soap_element_begin_in(soap, tag, 0, NULL))
8700     return NULL;
8701 #ifndef WITH_LEAN
8702   if (*soap->type
8703    && soap_match_tag(soap, soap->type, type)
8704    && soap_match_tag(soap, soap->type, ":int")
8705    && soap_match_tag(soap, soap->type, ":short")
8706    && soap_match_tag(soap, soap->type, ":byte"))
8707   { soap->error = SOAP_TYPE;
8708     soap_revert(soap);
8709     return NULL;
8710   }
8711 #endif
8712   p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
8713   if (*soap->href)
8714     p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
8715   else if (p)
8716   { if (soap_s2long(soap, soap_value(soap), p))
8717       return NULL;
8718   }
8719   if (soap->body && soap_element_end_in(soap, tag))
8720     return NULL;
8721   return p;
8722 }
8723 #endif
8724
8725 /******************************************************************************/
8726 #ifndef WITH_LEAN
8727 SOAP_FMAC1
8728 const char*
8729 SOAP_FMAC2
8730 soap_LONG642s(struct soap *soap, LONG64 n)
8731 { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
8732   return soap->tmpbuf;
8733 }
8734 #endif
8735
8736 /******************************************************************************/
8737 #ifndef WITH_LEAN
8738 SOAP_FMAC1
8739 int
8740 SOAP_FMAC2
8741 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
8742 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8743    || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
8744     return soap->error;
8745   return soap_element_end_out(soap, tag);
8746 }
8747 #endif
8748
8749 /******************************************************************************/
8750 #ifndef WITH_LEAN
8751 SOAP_FMAC1
8752 int
8753 SOAP_FMAC2
8754 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
8755 { if (s)
8756   {
8757 #ifdef HAVE_STRTOLL
8758     char *r;
8759 #ifndef WITH_NOIO
8760 #ifndef WITH_LEAN
8761     soap_reset_errno;
8762 #endif
8763 #endif
8764     *p = strtoll(s, &r, 10);
8765     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
8766 #ifndef WITH_NOIO
8767 #ifndef WITH_LEAN
8768        || soap_errno == SOAP_ERANGE
8769 #endif
8770 #endif
8771       )
8772 #else
8773 # ifdef HAVE_SSCANF
8774     if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
8775 # endif
8776 #endif
8777       soap->error = SOAP_TYPE;
8778   }
8779   return soap->error;
8780 }
8781 #endif
8782
8783 /******************************************************************************/
8784 #ifndef WITH_LEAN
8785 SOAP_FMAC1
8786 LONG64 *
8787 SOAP_FMAC2
8788 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
8789 { if (soap_element_begin_in(soap, tag, 0, NULL))
8790     return NULL;
8791 #ifndef WITH_LEAN
8792   if (*soap->type
8793    && soap_match_tag(soap, soap->type, type)
8794    && soap_match_tag(soap, soap->type, ":integer")
8795    && soap_match_tag(soap, soap->type, ":positiveInteger")
8796    && soap_match_tag(soap, soap->type, ":negativeInteger")
8797    && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
8798    && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
8799    && soap_match_tag(soap, soap->type, ":long")
8800    && soap_match_tag(soap, soap->type, ":int")
8801    && soap_match_tag(soap, soap->type, ":short")
8802    && soap_match_tag(soap, soap->type, ":byte"))
8803   { soap->error = SOAP_TYPE;
8804     soap_revert(soap);
8805     return NULL;
8806   }
8807 #endif
8808   p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
8809   if (*soap->href)
8810     p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
8811   else if (p)
8812   { if (soap_s2LONG64(soap, soap_value(soap), p))
8813       return NULL;
8814   }
8815   if (soap->body && soap_element_end_in(soap, tag))
8816     return NULL;
8817   return p;
8818 }
8819 #endif
8820
8821 /******************************************************************************/
8822 #ifndef PALM_2
8823 SOAP_FMAC1
8824 const char*
8825 SOAP_FMAC2
8826 soap_byte2s(struct soap *soap, char n)
8827 { return soap_long2s(soap, (long)n);
8828 }
8829 #endif
8830
8831 /******************************************************************************/
8832 #ifndef PALM_2
8833 SOAP_FMAC1
8834 int
8835 SOAP_FMAC2
8836 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
8837 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8838    || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
8839     return soap->error;
8840   return soap_element_end_out(soap, tag);
8841 }
8842 #endif
8843
8844 /******************************************************************************/
8845 #ifndef PALM_2
8846 SOAP_FMAC1
8847 int
8848 SOAP_FMAC2
8849 soap_s2byte(struct soap *soap, const char *s, char *p)
8850 { if (s)
8851   { long n;
8852     char *r;
8853     n = soap_strtol(s, &r, 10);
8854     if (s == r || *r || n < -128 || n > 127)
8855       soap->error = SOAP_TYPE;
8856     *p = (char)n;
8857   }
8858   return soap->error;
8859 }
8860 #endif
8861
8862 /******************************************************************************/
8863 #ifndef PALM_2
8864 SOAP_FMAC1
8865 char *
8866 SOAP_FMAC2
8867 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
8868 { if (soap_element_begin_in(soap, tag, 0, NULL))
8869     return NULL;
8870 #ifndef WITH_LEAN
8871   if (*soap->type
8872    && soap_match_tag(soap, soap->type, type)
8873    && soap_match_tag(soap, soap->type, ":byte"))
8874   { soap->error = SOAP_TYPE;
8875     soap_revert(soap);
8876     return NULL;
8877   }
8878 #endif
8879   p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
8880   if (*soap->href)
8881     p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
8882   else if (p)
8883   { if (soap_s2byte(soap, soap_value(soap), p))
8884       return NULL;
8885   }
8886   if (soap->body && soap_element_end_in(soap, tag))
8887     return NULL;
8888   return p;
8889 }
8890 #endif
8891
8892 /******************************************************************************/
8893 #ifndef PALM_2
8894 SOAP_FMAC1
8895 const char*
8896 SOAP_FMAC2
8897 soap_short2s(struct soap *soap, short n)
8898 { return soap_long2s(soap, (long)n);
8899 }
8900 #endif
8901
8902 /******************************************************************************/
8903 #ifndef PALM_2
8904 SOAP_FMAC1
8905 int
8906 SOAP_FMAC2
8907 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
8908 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8909    || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
8910     return soap->error;
8911   return soap_element_end_out(soap, tag);
8912 }
8913 #endif
8914
8915 /******************************************************************************/
8916 #ifndef PALM_2
8917 SOAP_FMAC1
8918 int
8919 SOAP_FMAC2
8920 soap_s2short(struct soap *soap, const char *s, short *p)
8921 { if (s)
8922   { long n;
8923     char *r;
8924     n = soap_strtol(s, &r, 10);
8925     if (s == r || *r || n < -32768 || n > 32767)
8926       soap->error = SOAP_TYPE;
8927     *p = (short)n;
8928   }
8929   return soap->error;
8930 }
8931 #endif
8932
8933 /******************************************************************************/
8934 #ifndef PALM_2
8935 SOAP_FMAC1
8936 short *
8937 SOAP_FMAC2
8938 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
8939 { if (soap_element_begin_in(soap, tag, 0, NULL))
8940     return NULL;
8941 #ifndef WITH_LEAN
8942   if (*soap->type
8943    && soap_match_tag(soap, soap->type, type)
8944    && soap_match_tag(soap, soap->type, ":short")
8945    && soap_match_tag(soap, soap->type, ":byte"))
8946   { soap->error = SOAP_TYPE;
8947     soap_revert(soap);
8948     return NULL;
8949   }
8950 #endif
8951   p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
8952   if (*soap->href)
8953     p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
8954   else if (p)
8955   { if (soap_s2short(soap, soap_value(soap), p))
8956       return NULL;
8957   }
8958   if (soap->body && soap_element_end_in(soap, tag))
8959     return NULL;
8960   return p;
8961 }
8962 #endif
8963
8964 /******************************************************************************/
8965 #ifndef PALM_2
8966 SOAP_FMAC1
8967 const char*
8968 SOAP_FMAC2
8969 soap_float2s(struct soap *soap, float n)
8970 { char *s;
8971   if (soap_isnan((double)n))
8972     s = "NaN";
8973   else if (soap_ispinff(n))
8974     s = "INF";
8975   else if (soap_isninff(n))
8976     s = "-INF";
8977   else
8978   { char *t;
8979     s = soap->tmpbuf;
8980     sprintf(soap->tmpbuf, soap->float_format, n);
8981     t = strchr(s, ','); /* convert decimal comma to DP */
8982     if (t)
8983       *t = '.';
8984   }
8985   return s;
8986 }
8987 #endif
8988
8989 /******************************************************************************/
8990 #ifndef PALM_2
8991 SOAP_FMAC1
8992 int
8993 SOAP_FMAC2
8994 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
8995 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8996    || soap_string_out(soap, soap_float2s(soap, *p), 0))
8997     return soap->error;
8998   return soap_element_end_out(soap, tag);
8999 }
9000 #endif
9001
9002 /******************************************************************************/
9003 #ifndef PALM_2
9004 SOAP_FMAC1
9005 int
9006 SOAP_FMAC2
9007 soap_s2float(struct soap *soap, const char *s, float *p)
9008 { if (s)
9009   { if (!*s)
9010       return soap->error = SOAP_TYPE;
9011     if (!soap_tag_cmp(s, "INF"))
9012       *p = FLT_PINFTY;
9013     else if (!soap_tag_cmp(s, "+INF"))
9014       *p = FLT_PINFTY;
9015     else if (!soap_tag_cmp(s, "-INF"))
9016       *p = FLT_NINFTY;
9017     else if (!soap_tag_cmp(s, "NaN"))
9018       *p = FLT_NAN;
9019     else
9020     {
9021 /* On some systems, strtof appears to be broken or doesn't link: use with caution */
9022 #if defined(HAVE_STRTOF)
9023       char *r;
9024       *p = strtof((char*)s, &r);
9025       if (*r)
9026 #elif defined(HAVE_STRTOD)
9027       char *r;
9028       *p = (float)strtod(s, &r);
9029       if (*r)
9030 #endif
9031 #ifdef HAVE_SSCANF
9032         if (sscanf(s, "%g", p) != 1)
9033           soap->error = SOAP_TYPE;
9034 #else
9035         soap->error = SOAP_TYPE;
9036 #endif
9037     }
9038   }
9039   return soap->error;
9040 }
9041 #endif
9042
9043 /******************************************************************************/
9044 #ifndef WITH_LEAN
9045 static int soap_isnumeric(struct soap *soap, const char *type)
9046 { if (soap_match_tag(soap, soap->type, type)
9047    && soap_match_tag(soap, soap->type, ":float")
9048    && soap_match_tag(soap, soap->type, ":double")
9049    && soap_match_tag(soap, soap->type, ":decimal")
9050    && soap_match_tag(soap, soap->type, ":integer")
9051    && soap_match_tag(soap, soap->type, ":positiveInteger")
9052    && soap_match_tag(soap, soap->type, ":negativeInteger")
9053    && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
9054    && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
9055    && soap_match_tag(soap, soap->type, ":long")
9056    && soap_match_tag(soap, soap->type, ":int")
9057    && soap_match_tag(soap, soap->type, ":short")
9058    && soap_match_tag(soap, soap->type, ":byte")
9059    && soap_match_tag(soap, soap->type, ":unsignedLong")
9060    && soap_match_tag(soap, soap->type, ":unsignedInt")
9061    && soap_match_tag(soap, soap->type, ":unsignedShort")
9062    && soap_match_tag(soap, soap->type, ":unsignedByte"))
9063   { soap->error = SOAP_TYPE;
9064     soap_revert(soap);
9065     return SOAP_ERR;
9066   }
9067   return SOAP_OK;
9068 }
9069 #endif
9070
9071 /******************************************************************************/
9072 #ifndef PALM_2
9073 SOAP_FMAC1
9074 float *
9075 SOAP_FMAC2
9076 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
9077 { if (soap_element_begin_in(soap, tag, 0, NULL))
9078     return NULL;
9079 #ifndef WITH_LEAN
9080   if (*soap->type != '\0' && soap_isnumeric(soap, type))
9081     return NULL;
9082 #endif
9083   p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
9084   if (*soap->href)
9085     p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
9086   else if (p)
9087   { if (soap_s2float(soap, soap_value(soap), p))
9088       return NULL;
9089   }
9090   if (soap->body && soap_element_end_in(soap, tag))
9091     return NULL;
9092   return p;
9093 }
9094 #endif
9095
9096 /******************************************************************************/
9097 #ifndef PALM_2
9098 SOAP_FMAC1
9099 const char*
9100 SOAP_FMAC2
9101 soap_double2s(struct soap *soap, double n)
9102 { char *s;
9103   if (soap_isnan(n))
9104     s = "NaN";
9105   else if (soap_ispinfd(n))
9106     s = "INF";
9107   else if (soap_isninfd(n))
9108     s = "-INF";
9109   else
9110   { char *t;
9111     s = soap->tmpbuf;
9112     sprintf(soap->tmpbuf, soap->double_format, n);
9113     t = strchr(s, ','); /* convert decimal comma to DP */
9114     if (t)
9115       *t = '.';
9116   }
9117   return s;
9118 }
9119 #endif
9120
9121 /******************************************************************************/
9122 #ifndef PALM_2
9123 SOAP_FMAC1
9124 int
9125 SOAP_FMAC2
9126 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
9127 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9128    || soap_string_out(soap, soap_double2s(soap, *p), 0))
9129     return soap->error;
9130   return soap_element_end_out(soap, tag);
9131 }
9132 #endif
9133
9134 /******************************************************************************/
9135 #ifndef PALM_2
9136 SOAP_FMAC1
9137 int
9138 SOAP_FMAC2
9139 soap_s2double(struct soap *soap, const char *s, double *p)
9140 { if (s)
9141   { if (!*s)
9142       return soap->error = SOAP_TYPE;
9143     if (!soap_tag_cmp(s, "INF"))
9144       *p = DBL_PINFTY;
9145     else if (!soap_tag_cmp(s, "+INF"))
9146       *p = DBL_PINFTY;
9147     else if (!soap_tag_cmp(s, "-INF"))
9148       *p = DBL_NINFTY;
9149     else if (!soap_tag_cmp(s, "NaN"))
9150       *p = DBL_NAN;
9151     else
9152     {
9153 #ifdef HAVE_STRTOD
9154       char *r;
9155       *p = strtod(s, &r);
9156       if (*r)
9157 #endif
9158 #ifdef HAVE_SSCANF
9159         if (sscanf(s, "%lg", p) != 1)
9160           soap->error = SOAP_TYPE;
9161 #else
9162         soap->error = SOAP_TYPE;
9163 #endif
9164     }
9165   }
9166   return soap->error;
9167 }
9168 #endif
9169
9170 /******************************************************************************/
9171 #ifndef PALM_2
9172 SOAP_FMAC1
9173 double *
9174 SOAP_FMAC2
9175 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
9176 { if (soap_element_begin_in(soap, tag, 0, NULL))
9177     return NULL;
9178 #ifndef WITH_LEAN
9179   if (*soap->type != '\0' && soap_isnumeric(soap, type))
9180     return NULL;
9181 #endif
9182   p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
9183   if (*soap->href)
9184     p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
9185   else if (p)
9186   { if (soap_s2double(soap, soap_value(soap), p))
9187       return NULL;
9188   }
9189   if (soap->body && soap_element_end_in(soap, tag))
9190     return NULL;
9191   return p;
9192 }
9193 #endif
9194
9195 /******************************************************************************/
9196 #ifndef PALM_2
9197 SOAP_FMAC1
9198 const char*
9199 SOAP_FMAC2
9200 soap_unsignedByte2s(struct soap *soap, unsigned char n)
9201 { return soap_unsignedLong2s(soap, (unsigned long)n);
9202 }
9203 #endif
9204
9205 /******************************************************************************/
9206 #ifndef PALM_2
9207 SOAP_FMAC1
9208 int
9209 SOAP_FMAC2
9210 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
9211 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9212    || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9213     return soap->error;
9214   return soap_element_end_out(soap, tag);
9215 }
9216 #endif
9217
9218 /******************************************************************************/
9219 #ifndef PALM_2
9220 SOAP_FMAC1
9221 int
9222 SOAP_FMAC2
9223 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
9224 { if (s)
9225   { unsigned long n;
9226     char *r;
9227     n = soap_strtoul(s, &r, 10);
9228     if (s == r || *r || n > 255)
9229       soap->error = SOAP_TYPE;
9230     *p = (unsigned char)n;
9231   }
9232   return soap->error;
9233 }
9234 #endif
9235
9236 /******************************************************************************/
9237 #ifndef PALM_2
9238 SOAP_FMAC1
9239 unsigned char *
9240 SOAP_FMAC2
9241 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
9242 { if (soap_element_begin_in(soap, tag, 0, NULL))
9243     return NULL;
9244 #ifndef WITH_LEAN
9245   if (*soap->type
9246    && soap_match_tag(soap, soap->type, type)
9247    && soap_match_tag(soap, soap->type, ":unsignedByte"))
9248   { soap->error = SOAP_TYPE;
9249     soap_revert(soap);
9250     return NULL;
9251   }
9252 #endif
9253   p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
9254   if (*soap->href)
9255     p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
9256   else if (p)
9257   { if (soap_s2unsignedByte(soap, soap_value(soap), p))
9258       return NULL;
9259   }
9260   if (soap->body && soap_element_end_in(soap, tag))
9261     return NULL;
9262   return p;
9263 }
9264 #endif
9265
9266 /******************************************************************************/
9267 #ifndef PALM_2
9268 SOAP_FMAC1
9269 const char*
9270 SOAP_FMAC2
9271 soap_unsignedShort2s(struct soap *soap, unsigned short n)
9272 { return soap_unsignedLong2s(soap, (unsigned long)n);
9273 }
9274 #endif
9275
9276 /******************************************************************************/
9277 #ifndef PALM_2
9278 SOAP_FMAC1
9279 int
9280 SOAP_FMAC2
9281 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
9282 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9283    || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9284     return soap->error;
9285   return soap_element_end_out(soap, tag);
9286 }
9287 #endif
9288
9289 /******************************************************************************/
9290 #ifndef PALM_2
9291 SOAP_FMAC1
9292 int
9293 SOAP_FMAC2
9294 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
9295 { if (s)
9296   { unsigned long n;
9297     char *r;
9298     n = soap_strtoul(s, &r, 10);
9299     if (s == r || *r || n > 65535)
9300       soap->error = SOAP_TYPE;
9301     *p = (unsigned short)n;
9302   }
9303   return soap->error;
9304 }
9305 #endif
9306
9307 /******************************************************************************/
9308 #ifndef PALM_2
9309 SOAP_FMAC1
9310 unsigned short *
9311 SOAP_FMAC2
9312 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
9313 { if (soap_element_begin_in(soap, tag, 0, NULL))
9314     return NULL;
9315 #ifndef WITH_LEAN
9316   if (*soap->type
9317    && soap_match_tag(soap, soap->type, type)
9318    && soap_match_tag(soap, soap->type, ":unsignedShort")
9319    && soap_match_tag(soap, soap->type, ":unsignedByte"))
9320   { soap->error = SOAP_TYPE;
9321     soap_revert(soap);
9322     return NULL;
9323   }
9324 #endif
9325   p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
9326   if (*soap->href)
9327     p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
9328   else if (p)
9329   { if (soap_s2unsignedShort(soap, soap_value(soap), p))
9330       return NULL;
9331   }
9332   if (soap->body && soap_element_end_in(soap, tag))
9333     return NULL;
9334   return p;
9335 }
9336 #endif
9337
9338 /******************************************************************************/
9339 #ifndef PALM_2
9340 SOAP_FMAC1
9341 const char*
9342 SOAP_FMAC2
9343 soap_unsignedInt2s(struct soap *soap, unsigned int n)
9344 { return soap_unsignedLong2s(soap, (unsigned long)n);
9345 }
9346 #endif
9347
9348 /******************************************************************************/
9349 #ifndef PALM_2
9350 SOAP_FMAC1
9351 int
9352 SOAP_FMAC2
9353 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
9354 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9355    || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9356     return soap->error;
9357   return soap_element_end_out(soap, tag);
9358 }
9359 #endif
9360
9361 /******************************************************************************/
9362 #ifndef PALM_2
9363 SOAP_FMAC1
9364 int
9365 SOAP_FMAC2
9366 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
9367 { if (s)
9368   { char *r;
9369 #ifndef WITH_NOIO
9370 #ifndef WITH_LEAN
9371     soap_reset_errno;
9372 #endif
9373 #endif
9374     *p = (unsigned int)soap_strtoul(s, &r, 10);
9375     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9376 #ifndef WITH_NOIO
9377 #ifndef WITH_LEAN
9378      || soap_errno == SOAP_ERANGE
9379 #endif
9380 #endif
9381     )
9382       soap->error = SOAP_TYPE;
9383   }
9384   return soap->error;
9385 }
9386 #endif
9387
9388 /******************************************************************************/
9389 #ifndef PALM_2
9390 SOAP_FMAC1
9391 unsigned int *
9392 SOAP_FMAC2
9393 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
9394 { if (soap_element_begin_in(soap, tag, 0, NULL))
9395     return NULL;
9396 #ifndef WITH_LEAN
9397   if (*soap->type
9398    && soap_match_tag(soap, soap->type, type)
9399    && soap_match_tag(soap, soap->type, ":unsignedInt")
9400    && soap_match_tag(soap, soap->type, ":unsignedShort")
9401    && soap_match_tag(soap, soap->type, ":unsignedByte"))
9402   { soap->error = SOAP_TYPE;
9403     soap_revert(soap);
9404     return NULL;
9405   }
9406 #endif
9407   p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
9408   if (*soap->href)
9409     p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
9410   else if (p)
9411   { if (soap_s2unsignedInt(soap, soap_value(soap), p))
9412       return NULL;
9413   }
9414   if (soap->body && soap_element_end_in(soap, tag))
9415     return NULL;
9416   return p;
9417 }
9418 #endif
9419
9420 /******************************************************************************/
9421 #ifndef PALM_2
9422 SOAP_FMAC1
9423 const char*
9424 SOAP_FMAC2
9425 soap_unsignedLong2s(struct soap *soap, unsigned long n)
9426 { sprintf(soap->tmpbuf, "%lu", n);
9427   return soap->tmpbuf;
9428 }
9429 #endif
9430
9431 /******************************************************************************/
9432 #ifndef PALM_2
9433 SOAP_FMAC1
9434 int
9435 SOAP_FMAC2
9436 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
9437 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9438    || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
9439     return soap->error;
9440   return soap_element_end_out(soap, tag);
9441 }
9442 #endif
9443
9444 /******************************************************************************/
9445 #ifndef PALM_2
9446 SOAP_FMAC1
9447 int
9448 SOAP_FMAC2
9449 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
9450 { if (s)
9451   { char *r;
9452 #ifndef WITH_NOIO
9453 #ifndef WITH_LEAN
9454     soap_reset_errno;
9455 #endif
9456 #endif
9457     *p = soap_strtoul(s, &r, 10);
9458     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9459 #ifndef WITH_NOIO
9460 #ifndef WITH_LEAN
9461      || soap_errno == SOAP_ERANGE
9462 #endif
9463 #endif
9464     )
9465       soap->error = SOAP_TYPE;
9466   }
9467   return soap->error;
9468 }
9469 #endif
9470
9471 /******************************************************************************/
9472 #ifndef PALM_2
9473 SOAP_FMAC1
9474 unsigned long *
9475 SOAP_FMAC2
9476 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
9477 { if (soap_element_begin_in(soap, tag, 0, NULL))
9478     return NULL;
9479 #ifndef WITH_LEAN
9480   if (*soap->type
9481    && soap_match_tag(soap, soap->type, type)
9482    && soap_match_tag(soap, soap->type, ":unsignedInt")
9483    && soap_match_tag(soap, soap->type, ":unsignedShort")
9484    && soap_match_tag(soap, soap->type, ":unsignedByte"))
9485   { soap->error = SOAP_TYPE;
9486     soap_revert(soap);
9487     return NULL;
9488   }
9489 #endif
9490   p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
9491   if (*soap->href)
9492     p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
9493   else if (p)
9494   { if (soap_s2unsignedLong(soap, soap_value(soap), p))
9495       return NULL;
9496   }
9497   if (soap->body && soap_element_end_in(soap, tag))
9498     return NULL;
9499   return p;
9500 }
9501 #endif
9502
9503 /******************************************************************************/
9504 #ifndef WITH_LEAN
9505 SOAP_FMAC1
9506 const char*
9507 SOAP_FMAC2
9508 soap_ULONG642s(struct soap *soap, ULONG64 n)
9509 { sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
9510   return soap->tmpbuf;
9511 }
9512 #endif
9513
9514 /******************************************************************************/
9515 #ifndef WITH_LEAN
9516 SOAP_FMAC1
9517 int
9518 SOAP_FMAC2
9519 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
9520 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9521    || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
9522     return soap->error;
9523   return soap_element_end_out(soap, tag);
9524 }
9525 #endif
9526
9527 /******************************************************************************/
9528 #ifndef WITH_LEAN
9529 SOAP_FMAC1
9530 int
9531 SOAP_FMAC2
9532 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
9533 { if (s)
9534   {
9535 #ifdef HAVE_STRTOULL
9536     char *r;
9537 #ifndef WITH_NOIO
9538 #ifndef WITH_LEAN
9539     soap_reset_errno;
9540 #endif
9541 #endif
9542     *p = strtoull(s, &r, 10);
9543     if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9544 #ifndef WITH_NOIO
9545 #ifndef WITH_LEAN
9546        || soap_errno == SOAP_ERANGE
9547 #endif
9548 #endif
9549       )
9550 #else
9551 # ifdef HAVE_SSCANF
9552     if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
9553 # endif
9554 #endif
9555       soap->error = SOAP_TYPE;
9556   }
9557   return soap->error;
9558 }
9559 #endif
9560
9561 /******************************************************************************/
9562 #ifndef WITH_LEAN
9563 SOAP_FMAC1
9564 ULONG64 *
9565 SOAP_FMAC2
9566 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
9567 { if (soap_element_begin_in(soap, tag, 0, NULL))
9568     return NULL;
9569   if (*soap->type
9570    && soap_match_tag(soap, soap->type, type)
9571    && soap_match_tag(soap, soap->type, ":positiveInteger")
9572    && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
9573    && soap_match_tag(soap, soap->type, ":unsignedLong")
9574    && soap_match_tag(soap, soap->type, ":unsignedInt")
9575    && soap_match_tag(soap, soap->type, ":unsignedShort")
9576    && soap_match_tag(soap, soap->type, ":unsignedByte"))
9577   { soap->error = SOAP_TYPE;
9578     soap_revert(soap);
9579     return NULL;
9580   }
9581   p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
9582   if (*soap->href)
9583     p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
9584   else if (p)
9585   { if (soap_s2ULONG64(soap, soap_value(soap), p))
9586       return NULL;
9587   }
9588   if (soap->body && soap_element_end_in(soap, tag))
9589     return NULL;
9590   return p;
9591 }
9592 #endif
9593
9594 /******************************************************************************/
9595 #ifndef PALM_2
9596 SOAP_FMAC1
9597 int
9598 SOAP_FMAC2
9599 soap_s2string(struct soap *soap, const char *s, char **t)
9600 { *t = NULL;
9601   if (s)
9602   { if (!(*t = soap_strdup(soap, s)))
9603       return soap->error = SOAP_EOM;
9604     if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
9605     { /* TODO: consider truncating UTF8 to ASCII for regular XML attribute strings? */
9606     }
9607   }
9608   return soap->error;
9609 }
9610 #endif
9611
9612 /******************************************************************************/
9613 #ifndef PALM_2
9614 SOAP_FMAC1
9615 int
9616 SOAP_FMAC2
9617 soap_s2QName(struct soap *soap, const char *s, char **t)
9618 { if (s)
9619   { struct soap_nlist *np;
9620     const char *p;
9621     if (!strncmp(s, "xml:", 4))
9622     { *t = soap_strdup(soap, s);
9623       return SOAP_OK;
9624     }
9625     np = soap->nlist;
9626     p = strchr(s, ':');
9627     if (p)
9628     { register int n = p - s;
9629       while (np && (strncmp(np->id, s, n) || np->id[n]))
9630         np = np->next;
9631       p++;
9632     }
9633     else
9634     { while (np && *np->id)
9635         np = np->next;
9636       p = s;
9637     }
9638     if (np)
9639     { if (np->index >= 0 && soap->local_namespaces)
9640       { register const char *q = soap->local_namespaces[np->index].id;
9641         if (q)
9642         { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2)))
9643             sprintf(*t, "%s:%s", q, p);
9644           return SOAP_OK;
9645         }
9646       }
9647       if (np->ns)
9648       { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4)))
9649           sprintf(*t, "\"%s\":%s", np->ns, p);
9650         return SOAP_OK;
9651       }
9652       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:""));
9653       return soap->error = SOAP_NAMESPACE; 
9654     }
9655     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s));
9656     if ((*t = (char*)soap_malloc(soap, strlen(p) + 4)))
9657       sprintf(*t, "\"\":%s", p);
9658   }
9659   else
9660     *t = NULL;
9661   return soap->error;
9662 }
9663 #endif
9664
9665 /******************************************************************************/
9666 #ifndef PALM_2
9667 SOAP_FMAC1
9668 const char*
9669 SOAP_FMAC2
9670 soap_QName2s(struct soap *soap, const char *s)
9671 { struct Namespace *p;
9672   char *t;
9673   int n;
9674   if (!s || *s != '"')
9675   {
9676 #ifndef WITH_LEAN
9677     if (s && (soap->mode & SOAP_XML_CANONICAL))
9678     { t = (char*)strchr(s, ':');
9679       if (t)
9680         soap_utilize_ns(soap, s, t - s);
9681     }
9682 #endif
9683     return s;
9684   }
9685   s++;
9686   if ((p = soap->local_namespaces))
9687   { for (; p->id; p++)
9688     { if (p->ns)
9689         if (!soap_tag_cmp(s, p->ns))
9690           break;
9691       if (p->in)
9692         if (!soap_tag_cmp(s, p->in))
9693           break;
9694     }
9695     if (p && p->id)
9696     { s = strchr(s, '"');
9697       if (s)
9698       { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s));
9699         strcpy(t, p->id);
9700         strcat(t, s + 1);
9701         return t;
9702       }
9703     }
9704   }
9705   t = (char*)strchr(s, '"');
9706   if (t)
9707     n = t - s;
9708   else
9709     n = 0;
9710   t = soap_strdup(soap, s);
9711   t[n] = '\0';
9712   sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
9713   soap_set_attr(soap, soap->tmpbuf, t);
9714   s = strchr(s, '"');
9715   if (s)
9716   { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6);
9717     strcpy(t, soap->tmpbuf + 6);
9718     strcat(t, s + 1);
9719   }
9720   return t;
9721 }
9722 #endif
9723
9724 /******************************************************************************/
9725 #ifndef WITH_LEAN
9726 SOAP_FMAC1
9727 int
9728 SOAP_FMAC2
9729 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t)
9730 { wchar_t *r;
9731   if (!s)
9732     *t = NULL;
9733   else
9734   { *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
9735     if (!r)
9736       return soap->error;
9737     if (soap->mode & SOAP_ENC_LATIN)
9738     { while (*s)
9739         *r++ = (wchar_t)*s++;
9740     }
9741     else
9742     { /* Convert UTF8 to wchar */
9743       while (*s)
9744       { register soap_wchar c, c1, c2, c3, c4;
9745         c = *s++;
9746         if (c < 0x80)
9747           *r++ = (wchar_t)c;
9748         else
9749         { c1 = (soap_wchar)*s++ & 0x3F;
9750           if (c < 0xE0)
9751             *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
9752           else
9753           { c2 = (soap_wchar)*s++ & 0x3F;
9754             if (c < 0xF0)
9755               *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
9756             else
9757             { c3 = (soap_wchar)*s++ & 0x3F;
9758               if (c < 0xF8)
9759                 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
9760               else
9761               { c4 = (soap_wchar)*s++ & 0x3F;
9762                 if (c < 0xFC)
9763                   *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
9764                 else
9765                   *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
9766               }
9767             }
9768           }
9769         }
9770       }
9771     }
9772     *r = L'\0';
9773   }
9774   return SOAP_OK;
9775 }
9776 #endif
9777
9778 /******************************************************************************/
9779 #ifndef WITH_LEAN
9780 SOAP_FMAC1
9781 const char*
9782 SOAP_FMAC2
9783 soap_wchar2s(struct soap *soap, const wchar_t *s)
9784 { register soap_wchar c;
9785   register char *r, *t;
9786   const wchar_t *q = s;
9787   size_t n = 0;
9788   while ((c = *q++))
9789   { if (c > 0 && c < 0x80)
9790       n++;
9791     else
9792       n += 6;
9793   }
9794   r = t = (char*)soap_malloc(soap, n + 1);
9795   if (r)
9796   { /* Convert wchar to UTF8 */
9797     while ((c = *s++))
9798     { if (c > 0 && c < 0x80)
9799         *t++ = (char)c;
9800       else
9801       { if (c < 0x0800)
9802           *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
9803         else
9804         { if (c < 0x010000)
9805             *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
9806           else
9807           { if (c < 0x200000)
9808               *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
9809             else
9810             { if (c < 0x04000000)
9811                 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
9812               else
9813               { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
9814                 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
9815               }
9816               *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
9817             }     
9818             *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
9819           }
9820           *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
9821         }
9822         *t++ = (char)(0x80 | (c & 0x3F));
9823       }
9824     }
9825     *t = '\0';
9826   }
9827   return r;
9828 }
9829 #endif
9830
9831 /******************************************************************************/
9832 #ifndef PALM_2
9833 SOAP_FMAC1
9834 int
9835 SOAP_FMAC2
9836 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) 
9837 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
9838   if (id < 0)
9839     return soap->error;
9840   if (!**p && (soap->mode & SOAP_C_NILSTRING))
9841     return soap_element_null(soap, tag, id, type);
9842   if (soap_element_begin_out(soap, tag, id, type)
9843    || soap_string_out(soap, *p, 0)
9844    || soap_element_end_out(soap, tag))
9845     return soap->error;
9846   return SOAP_OK;
9847 }
9848 #endif
9849
9850 /******************************************************************************/
9851 #ifndef PALM_2
9852 SOAP_FMAC1
9853 char **
9854 SOAP_FMAC2
9855 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
9856 { if (soap_element_begin_in(soap, tag, 1, NULL))
9857   { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
9858       return NULL;
9859     soap->error = SOAP_OK;
9860   }
9861   if (!p)
9862     if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
9863       return NULL;
9864   if (soap->body)
9865   { *p = soap_string_in(soap, flag, minlen, maxlen);
9866     if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
9867       return NULL;
9868   }
9869   else if (soap->null)
9870     *p = NULL;
9871   else
9872     *p = (char*)SOAP_STR_EOS;
9873   if (*soap->href)
9874     p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
9875   if (soap->body && soap_element_end_in(soap, tag))
9876     return NULL;
9877   return p;
9878 }
9879 #endif
9880
9881 /******************************************************************************/
9882 #ifndef WITH_LEANER
9883 #ifndef PALM_2
9884 SOAP_FMAC1
9885 int
9886 SOAP_FMAC2
9887 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) 
9888 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
9889   if (id < 0)
9890     return soap->error;
9891   if (!**p && (soap->mode & SOAP_C_NILSTRING))
9892     return soap_element_null(soap, tag, id, type);
9893   if (soap_element_begin_out(soap, tag, id, type)
9894    || soap_wstring_out(soap, *p, 0)
9895    || soap_element_end_out(soap, tag))
9896     return soap->error;
9897   return SOAP_OK;
9898 }
9899 #endif
9900 #endif
9901
9902 /******************************************************************************/
9903 #ifndef WITH_LEANER
9904 #ifndef PALM_2
9905 SOAP_FMAC1
9906 wchar_t **
9907 SOAP_FMAC2
9908 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
9909 { if (soap_element_begin_in(soap, tag, 1, NULL))
9910   { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
9911       return NULL;
9912     soap->error = SOAP_OK;
9913   }
9914   if (!p)
9915     if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
9916       return NULL;
9917   if (soap->body)
9918   { *p = soap_wstring_in(soap, 1, minlen, maxlen);
9919     if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
9920       return NULL;
9921   }
9922   else if (soap->null)
9923     *p = NULL;
9924   else
9925     *p = (wchar_t*)SOAP_STR_EOS;
9926   if (*soap->href)
9927     p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
9928   if (soap->body && soap_element_end_in(soap, tag))
9929     return NULL;
9930   return p;
9931 }
9932 #endif
9933 #endif
9934
9935 /******************************************************************************/
9936 #ifndef WITH_LEAN
9937 static time_t
9938 soap_timegm(struct tm *T)
9939 {
9940 #if defined(HAVE_TIMEGM)
9941   return timegm(T);
9942 #else
9943   time_t t, g, z;
9944 #ifdef HAVE_GMTIME_R
9945   struct tm tm, *tmp = &tm;
9946 #else
9947   struct tm *tmp;
9948 #endif
9949   t = mktime(T);
9950   if (t == -1)
9951     return -1;
9952 #ifdef HAVE_GMTIME_R
9953   gmtime_r(&t, tmp);
9954 #else
9955   tmp = gmtime(&t);
9956 #endif
9957   tmp->tm_isdst = 0;
9958   g = mktime(tmp);
9959   if (g == -1)
9960     return -1;
9961   z = g - t;
9962   return t - z;
9963 #endif
9964 }
9965 #endif
9966
9967 /******************************************************************************/
9968 #ifndef WITH_LEAN
9969 SOAP_FMAC1
9970 const char*
9971 SOAP_FMAC2
9972 soap_dateTime2s(struct soap *soap, time_t n)
9973 { struct tm T, *pT = &T;
9974 #if defined(HAVE_GMTIME_R)
9975   if (gmtime_r(&n, pT))
9976     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9977   /* The following defines were added for VxWorks*/
9978 #elif defined(HAVE_PGMTIME_R)
9979   if (gmtime_r(&n, pT))
9980     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9981 #elif defined(HAVE_PGMTIME)
9982   if (gmtime(&n, pT))
9983     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9984 #elif defined(HAVE_GMTIME)
9985   if ((pT = gmtime(&n)))
9986     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9987 #elif defined(HAVE_GETTIMEOFDAY)
9988   struct timezone tz;
9989   memset((void*)&tz, 0, sizeof(tz));
9990 # if defined(HAVE_LOCALTIME_R)
9991   if (localtime_r(&n, pT))
9992   { struct timeval tv;
9993     gettimeofday(&tv, &tz);
9994     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
9995     sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
9996   }
9997 # else
9998   if ((pT = localtime(&n)))
9999   { struct timeval tv;
10000     gettimeofday(&tv, &tz);
10001     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10002     sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
10003   }
10004 #endif
10005 #elif defined(HAVE_FTIME)
10006   struct timeb t;
10007   memset((void*)&t, 0, sizeof(t));
10008 # if defined(HAVE_LOCALTIME_R)
10009   if (localtime_r(&n, pT))
10010   { ftime(&t);
10011     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10012     sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
10013   }
10014   /* The following defines were added for VxWorks*/
10015 # elif defined(HAVE_PLOCALTIME_R)
10016   if (localtime_r(&n, pT))
10017   { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10018     sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60);
10019   }
10020 # else
10021   if ((pT = localtime(&n)))
10022   { ftime(&t);
10023     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10024     sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
10025   }
10026 # endif
10027 #elif defined(HAVE_LOCALTIME_R)
10028   if (localtime_r(&n, pT))
10029     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10030   /* The following defines were added for VxWorks*/
10031 #elif defined(HAVE_PLOCALTIME_R)
10032   if (localtime_r(&n, pT))
10033     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10034 #else
10035   if ((pT = localtime(&n)))
10036     strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10037 #endif
10038   else
10039     strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
10040   return soap->tmpbuf;
10041 }
10042 #endif
10043
10044 /******************************************************************************/
10045 #ifndef WITH_LEAN
10046 SOAP_FMAC1
10047 int
10048 SOAP_FMAC2
10049 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
10050 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
10051    || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
10052     return soap->error;
10053   return soap_element_end_out(soap, tag);
10054 }
10055 #endif
10056
10057 /******************************************************************************/
10058 #ifndef WITH_LEAN
10059 SOAP_FMAC1
10060 int
10061 SOAP_FMAC2
10062 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
10063 { if (s)
10064   { struct tm T;
10065     char zone[32];
10066     const char *t;
10067     memset((void*)&T, 0, sizeof(T));
10068     zone[sizeof(zone)-1] = '\0';
10069     if (strchr(s, '-'))
10070       t = "%d-%d-%dT%d:%d:%d%31s";
10071     else if (strchr(s, ':'))
10072       t = "%4d%2d%2dT%d:%d:%d%31s";
10073     else /* parse non-XSD-standard alternative ISO 8601 format */
10074       t = "%4d%2d%2dT%2d%2d%2d%31s";
10075     sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone);
10076     if (T.tm_year == 1)
10077       T.tm_year = 70;
10078     else
10079       T.tm_year -= 1900;
10080     T.tm_mon--;
10081     if (*zone)
10082     { if (*zone == '.')
10083       { for (s = zone + 1; *s; s++)
10084           if (*s < '0' || *s > '9')
10085             break;
10086       }
10087       else
10088         s = zone;
10089       if (*s == '+' || *s == '-')
10090       { int h = 0, m = 0;
10091         if (s[3] == ':')
10092         { sscanf(s, "%d:%d", &h, &m);
10093           if (h < 0)
10094             m = -m;
10095         }
10096         else
10097         { m = (int)atol(s);
10098           h = m / 100;
10099           m = m % 100;
10100         }
10101         T.tm_hour -= h;
10102         T.tm_min -= m;
10103       }
10104       T.tm_isdst = 0;
10105       *p = soap_timegm(&T);
10106     }
10107     else
10108     { T.tm_isdst = -1;
10109       *p = mktime(&T); /* no time zone: suppose it is localtime? */
10110     }
10111   }
10112   return soap->error;
10113 }
10114 #endif
10115
10116 /******************************************************************************/
10117 #ifndef WITH_LEAN
10118 SOAP_FMAC1
10119 time_t *
10120 SOAP_FMAC2
10121 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
10122 { if (soap_element_begin_in(soap, tag, 0, NULL))
10123     return NULL;
10124   if (*soap->type
10125    && soap_match_tag(soap, soap->type, type)
10126    && soap_match_tag(soap, soap->type, ":dateTime"))
10127   { soap->error = SOAP_TYPE;
10128     soap_revert(soap);
10129     return NULL;
10130   }
10131   p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
10132   if (*soap->href)
10133     p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
10134   else if (p)
10135   { if (soap_s2dateTime(soap, soap_value(soap), p))
10136       return NULL;
10137   }
10138   if (soap->body && soap_element_end_in(soap, tag))
10139     return NULL;
10140   return p;
10141 }
10142 #endif
10143
10144 /******************************************************************************/
10145 #ifndef PALM_2
10146 SOAP_FMAC1
10147 int
10148 SOAP_FMAC2
10149 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
10150 { int i;
10151   const char *t = NULL;
10152   if (tag && *tag != '-')
10153   { if (soap->local_namespaces && (t = strchr(tag, ':')))
10154     { strncpy(soap->tmpbuf, tag, t-tag);
10155       soap->tmpbuf[t-tag] = '\0';
10156       for (i = 0; soap->local_namespaces[i].id; i++)
10157         if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
10158           break;
10159       t++;
10160       if (soap_element(soap, t, 0, type)
10161        || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
10162        || soap_element_start_end_out(soap, NULL))
10163         return soap->error;
10164     }
10165     else
10166     { t = tag;
10167       if (soap_element_begin_out(soap, t, 0, type))
10168         return soap->error;
10169     }
10170   }
10171   if (p && *p)
10172   { if (soap_send(soap, *p))
10173       return soap->error;
10174   }
10175   if (t)
10176     return soap_element_end_out(soap, t);
10177   return SOAP_OK;
10178 }
10179 #endif
10180
10181 /******************************************************************************/
10182 #ifndef PALM_2
10183 SOAP_FMAC1
10184 char **
10185 SOAP_FMAC2
10186 soap_inliteral(struct soap *soap, const char *tag, char **p)
10187 { if (soap_element_begin_in(soap, tag, 1, NULL))
10188   { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
10189       return NULL;
10190     soap->error = SOAP_OK;
10191   }
10192   if (!p)
10193     if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
10194       return NULL;
10195   if (soap->body)
10196     *p = soap_string_in(soap, 0, -1, -1);
10197   else if (soap->null)
10198     *p = NULL;
10199   else
10200     *p = (char*)SOAP_STR_EOS;
10201   if (soap->body && soap_element_end_in(soap, tag))
10202     return NULL;
10203   return p;
10204 }
10205 #endif
10206
10207 /******************************************************************************/
10208 #ifndef WITH_LEANER
10209 #ifndef PALM_2
10210 SOAP_FMAC1
10211 int
10212 SOAP_FMAC2
10213 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
10214 { int i;
10215   const char *t = NULL;
10216   if (tag && *tag != '-')
10217   { if (soap->local_namespaces && (t = strchr(tag, ':')))
10218     { strncpy(soap->tmpbuf, tag, t-tag);
10219       soap->tmpbuf[t-tag] = '\0';
10220       for (i = 0; soap->local_namespaces[i].id; i++)
10221         if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
10222           break;
10223       t++;
10224       if (soap_element(soap, t, 0, type)
10225        || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
10226        || soap_element_start_end_out(soap, NULL))
10227         return soap->error;
10228     }
10229     else
10230     { t = tag;
10231       if (soap_element_begin_out(soap, t, 0, type))
10232         return soap->error;
10233     }
10234     if (soap_send(soap, soap->tmpbuf))
10235       return soap->error;
10236   }
10237   if (p)
10238   { wchar_t c;
10239     const wchar_t *s = *p;
10240     while ((c = *s++))
10241     { if (soap_pututf8(soap, (unsigned long)c))
10242         return soap->error;
10243     }
10244   }
10245   if (t)
10246     return soap_element_end_out(soap, t);
10247   return SOAP_OK;
10248 }
10249 #endif
10250 #endif
10251
10252 /******************************************************************************/
10253 #ifndef WITH_LEANER
10254 #ifndef PALM_2
10255 SOAP_FMAC1
10256 wchar_t **
10257 SOAP_FMAC2
10258 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
10259 { if (soap_element_begin_in(soap, tag, 1, NULL))
10260   { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
10261       return NULL;
10262     soap->error = SOAP_OK;
10263   }
10264   if (!p)
10265     if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
10266       return NULL;
10267   if (soap->body)
10268     *p = soap_wstring_in(soap, 0, -1, -1);
10269   else if (soap->null)
10270     *p = NULL;
10271   else
10272     *p = (wchar_t*)SOAP_STR_EOS;
10273   if (soap->body && soap_element_end_in(soap, tag))
10274     return NULL;
10275   return p;
10276 }
10277 #endif
10278 #endif
10279
10280 /******************************************************************************/
10281 #ifndef PALM_2
10282 SOAP_FMAC1
10283 const char *
10284 SOAP_FMAC2
10285 soap_value(struct soap *soap)
10286 { register size_t i;
10287   register soap_wchar c = 0;
10288   register char *s = soap->tmpbuf;
10289   if (!soap->body)
10290     return SOAP_STR_EOS;
10291   do c = soap_get(soap);
10292   while (soap_blank(c));
10293   for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
10294   { if (c == SOAP_TT || (int)c == EOF)
10295       break;
10296     *s++ = (char)c;
10297     c = soap_get(soap);
10298   }
10299   for (s--; i > 0; i--, s--)
10300   { if (!soap_blank(*s))
10301       break;
10302   }
10303   s[1] = '\0';
10304   if ((int)c == EOF || c == SOAP_TT)
10305     soap_unget(soap, c);
10306   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
10307 #ifdef WITH_DOM
10308   if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10309     soap->dom->data = soap_strdup(soap, soap->tmpbuf);
10310 #endif
10311   return soap->tmpbuf; /* return non-null pointer */
10312 }
10313 #endif
10314
10315 /******************************************************************************/
10316 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
10317 #ifndef PALM_2
10318 SOAP_FMAC1
10319 int
10320 SOAP_FMAC2
10321 soap_getline(struct soap *soap, char *s, int len)
10322 { int i = len;
10323   soap_wchar c = 0;
10324   for (;;)
10325   { while (--i > 0)
10326     { c = soap_getchar(soap);
10327       if (c == '\r' || c == '\n')
10328         break;
10329       if ((int)c == EOF)
10330         return soap->error = SOAP_EOF;
10331       *s++ = (char)c;
10332     }
10333     if (c != '\n')
10334       c = soap_getchar(soap); /* got \r, now get \n */
10335     if (c == '\n')
10336     { *s = '\0';
10337       if (i+1 == len) /* empty line: end of HTTP/MIME header */
10338         break;
10339       c = soap_unget(soap, soap_getchar(soap));
10340       if (c != ' ' && c != '\t') /* HTTP line continuation? */
10341         break;
10342     }
10343     else if ((int)c == EOF)
10344       return soap->error = SOAP_EOF;
10345   }
10346   return SOAP_OK;
10347 }
10348 #endif
10349 #endif
10350
10351 /******************************************************************************/
10352 #ifndef PALM_1
10353 static size_t
10354 soap_count_attachments(struct soap *soap)
10355
10356 #ifndef WITH_LEANER
10357   register struct soap_multipart *content;
10358   register size_t count = soap->count;
10359   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
10360   if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
10361   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
10362     for (content = soap->dime.first; content; content = content->next)
10363     { count += 12 + ((content->size+3)&(~3));
10364       if (content->id)
10365         count += ((strlen(content->id)+3)&(~3));
10366       if (content->type)
10367         count += ((strlen(content->type)+3)&(~3));
10368       if (content->options)
10369         count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
10370       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
10371     }
10372   }
10373   if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
10374   { register size_t n = strlen(soap->mime.boundary);
10375     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
10376     for (content = soap->mime.first; content; content = content->next)
10377     { register const char *s;
10378       /* count \r\n--boundary\r\n */
10379       count += 6 + n;
10380       /* count Content-Type: ...\r\n */
10381       if (content->type)
10382         count += 16 + strlen(content->type);
10383       /* count Content-Transfer-Encoding: ...\r\n */
10384       s = soap_code_str(mime_codes, content->encoding);
10385       if (s)
10386         count += 29 + strlen(s);
10387       /* count Content-ID: ...\r\n */
10388       if (content->id)
10389         count += 14 + strlen(content->id);
10390       /* count Content-Location: ...\r\n */
10391       if (content->location)
10392         count += 20 + strlen(content->location);
10393       /* count Content-Description: ...\r\n */
10394       if (content->description)
10395         count += 23 + strlen(content->description);
10396       /* count \r\n...content */
10397       count += 2 + content->size;
10398       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
10399     }
10400     /* count \r\n--boundary-- */
10401     count += 6 + n;
10402   }
10403   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count));
10404   return count;
10405 #else
10406   return soap->count;
10407 #endif
10408 }
10409 #endif
10410
10411 /******************************************************************************/
10412 #ifndef WITH_LEANER
10413 #ifndef PALM_1
10414 static int
10415 soap_putdimefield(struct soap *soap, const char *s, size_t n)
10416 { if (soap_send_raw(soap, s, n))
10417     return soap->error;
10418   return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
10419 }
10420 #endif
10421 #endif
10422
10423 /******************************************************************************/
10424 #ifndef WITH_LEANER
10425 #ifndef PALM_1
10426 SOAP_FMAC1
10427 char *
10428 SOAP_FMAC2
10429 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
10430 { size_t n;
10431   char *s = NULL;
10432   if (option)
10433   { n = strlen(option);
10434     s = (char*)soap_malloc(soap, n + 5);
10435     if (s)
10436     { s[0] = optype >> 8;
10437       s[1] = optype & 0xFF;
10438       s[2] = n >> 8;
10439       s[3] = n & 0xFF;
10440       strcpy(s + 4, option);
10441     }
10442   }
10443   return s;
10444 }
10445 #endif
10446 #endif
10447
10448 /******************************************************************************/
10449 #ifndef WITH_LEANER
10450 #ifndef PALM_1
10451 SOAP_FMAC1
10452 int
10453 SOAP_FMAC2
10454 soap_putdimehdr(struct soap *soap)
10455 { unsigned char tmp[12];
10456   size_t optlen = 0, idlen = 0, typelen = 0;
10457   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:""));
10458   if (soap->dime.options)
10459     optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
10460   if (soap->dime.id)
10461     idlen = strlen(soap->dime.id);
10462   if (soap->dime.type)
10463     typelen = strlen(soap->dime.type);
10464   tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
10465   tmp[1] = soap->dime.flags & 0xF0;
10466   tmp[2] = optlen >> 8;
10467   tmp[3] = optlen & 0xFF;
10468   tmp[4] = idlen >> 8;
10469   tmp[5] = idlen & 0xFF;
10470   tmp[6] = typelen >> 8;
10471   tmp[7] = typelen & 0xFF;
10472   tmp[8] = soap->dime.size >> 24;
10473   tmp[9] = (soap->dime.size >> 16) & 0xFF;
10474   tmp[10] = (soap->dime.size >> 8) & 0xFF;
10475   tmp[11] = soap->dime.size & 0xFF;
10476   if (soap_send_raw(soap, (char*)tmp, 12)
10477    || soap_putdimefield(soap, soap->dime.options, optlen)
10478    || soap_putdimefield(soap, soap->dime.id, idlen)
10479    || soap_putdimefield(soap, soap->dime.type, typelen))
10480     return soap->error;
10481   return SOAP_OK;
10482 }
10483 #endif
10484 #endif
10485
10486 /******************************************************************************/
10487 #ifndef WITH_LEANER
10488 #ifndef PALM_1
10489 SOAP_FMAC1
10490 int
10491 SOAP_FMAC2
10492 soap_putdime(struct soap *soap)
10493 { struct soap_multipart *content;
10494   if (!(soap->mode & SOAP_ENC_DIME))
10495     return SOAP_OK;
10496   for (content = soap->dime.first; content; content = content->next)
10497   { void *handle;
10498     soap->dime.size = content->size;
10499     soap->dime.id = content->id;
10500     soap->dime.type = content->type;
10501     soap->dime.options = content->options;
10502     soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
10503     if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
10504     { size_t size = content->size;
10505       if (!handle)
10506       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
10507         return soap->error;
10508       }
10509       if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
10510       { size_t chunksize = sizeof(soap->tmpbuf);
10511         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
10512         do 
10513         { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
10514           DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
10515           if (size < chunksize)
10516           { soap->dime.flags &= ~SOAP_DIME_CF;
10517             if (!content->next)
10518               soap->dime.flags |= SOAP_DIME_ME;
10519           }
10520           else
10521             soap->dime.flags |= SOAP_DIME_CF;
10522           soap->dime.size = size;
10523           if (soap_putdimehdr(soap)
10524            || soap_putdimefield(soap, soap->tmpbuf, size))
10525             break;
10526           if (soap->dime.id)
10527           { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
10528             soap->dime.id = NULL;
10529             soap->dime.type = NULL;
10530             soap->dime.options = NULL;
10531           }  
10532         } while (size >= chunksize);
10533       }
10534       else
10535       { if (!content->next)
10536           soap->dime.flags |= SOAP_DIME_ME;
10537         if (soap_putdimehdr(soap))
10538           return soap->error;
10539         do
10540         { size_t bufsize;
10541           if (size < sizeof(soap->tmpbuf))
10542             bufsize = size;
10543           else
10544             bufsize = sizeof(soap->tmpbuf);
10545           if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
10546           { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
10547             soap->error = SOAP_EOF;
10548             break;
10549           }
10550           if (soap_send_raw(soap, soap->tmpbuf, bufsize))
10551             break;
10552           size -= bufsize;
10553         } while (size);
10554         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
10555         soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
10556       }
10557       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
10558       if (soap->fdimereadclose)
10559         soap->fdimereadclose(soap, handle);
10560     }
10561     else
10562     { if (!content->next)
10563         soap->dime.flags |= SOAP_DIME_ME;
10564       if (soap_putdimehdr(soap)
10565        || soap_putdimefield(soap, (char*)content->ptr, content->size))
10566         return soap->error;
10567     }
10568   }
10569   return SOAP_OK;
10570 }
10571 #endif
10572 #endif
10573
10574 /******************************************************************************/
10575 #ifndef WITH_LEANER
10576 #ifndef PALM_1
10577 static char *
10578 soap_getdimefield(struct soap *soap, size_t n)
10579 { register soap_wchar c;
10580   register int i;
10581   register char *s;
10582   char *p = NULL;
10583   if (n)
10584   { p = (char*)soap_malloc(soap, n + 1);
10585     if (p)
10586     { s = p;
10587       for (i = n; i > 0; i--)
10588       { if ((int)(c = soap_get1(soap)) == EOF)
10589         { soap->error = SOAP_EOF;
10590           return NULL;
10591         }
10592         *s++ = (char)c;
10593       }
10594       *s = '\0';
10595       if ((soap->error = soap_move(soap, -(long)n&3)))
10596         return NULL;
10597     }
10598     else
10599       soap->error = SOAP_EOM;
10600   }
10601   return p;
10602 }
10603 #endif
10604 #endif
10605
10606 /******************************************************************************/
10607 #ifndef WITH_LEANER
10608 #ifndef PALM_1
10609 SOAP_FMAC1
10610 int
10611 SOAP_FMAC2
10612 soap_getdimehdr(struct soap *soap)
10613 { register soap_wchar c;
10614   register char *s;
10615   register int i;
10616   unsigned char tmp[12];
10617   size_t optlen, idlen, typelen;
10618   if (!(soap->mode & SOAP_ENC_DIME))
10619     return soap->error = SOAP_DIME_END;
10620   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
10621   if (soap->dime.buflen || soap->dime.chunksize)
10622   { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
10623       return soap->error = SOAP_EOF;
10624     soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
10625     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
10626     return SOAP_OK;
10627   }
10628   s = (char*)tmp;
10629   for (i = 12; i > 0; i--)
10630   { if ((int)(c = soap_getchar(soap)) == EOF)
10631       return soap->error = SOAP_EOF;
10632     *s++ = (char)c;
10633   }
10634   if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
10635     return soap->error = SOAP_DIME_MISMATCH;
10636   soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
10637   optlen = (tmp[2] << 8) | tmp[3];
10638   idlen = (tmp[4] << 8) | tmp[5];
10639   typelen = (tmp[6] << 8) | tmp[7];
10640   soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
10641   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
10642   if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
10643     return soap->error;
10644   if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
10645     return soap->error;
10646   if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
10647     return soap->error;
10648   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:""));
10649   if (soap->dime.flags & SOAP_DIME_ME)
10650     soap->mode &= ~SOAP_ENC_DIME;
10651   return SOAP_OK;
10652 }
10653 #endif
10654 #endif
10655
10656 /******************************************************************************/
10657 #ifndef WITH_LEANER
10658 #ifndef PALM_1
10659 SOAP_FMAC1
10660 int
10661 SOAP_FMAC2
10662 soap_getdime(struct soap *soap)
10663 { while (soap->dime.flags & SOAP_DIME_CF)
10664   { if (soap_getdimehdr(soap))
10665       return soap->error;
10666     if (soap_move(soap, soap->dime.size))
10667       return soap->error = SOAP_EOF;
10668   }
10669   if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap)))
10670     return soap->error = SOAP_EOF;
10671   for (;;)
10672   { register struct soap_multipart *content;
10673     if (soap_getdimehdr(soap))
10674       break;
10675     if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
10676     { const char *id, *type, *options;
10677       size_t size, n;
10678       if (!soap->dime.ptr)
10679         return soap->error;
10680       id = soap->dime.id;
10681       type = soap->dime.type;
10682       options = soap->dime.options;
10683       for (;;)
10684       { size = soap->dime.size;
10685         for (;;)
10686         { n = soap->buflen - soap->bufidx;
10687           if (size < n)
10688             n = size;
10689           if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
10690             break;
10691           size -= n;
10692           if (!size)
10693           { soap->bufidx += n;
10694             break;
10695           }
10696           if (soap_recv(soap))
10697           { soap->error = SOAP_EOF;
10698             goto end;
10699           }
10700         }
10701         if (soap_move(soap, -(long)soap->dime.size&3))
10702         { soap->error = SOAP_EOF;
10703           break;
10704         }
10705         if (!(soap->dime.flags & SOAP_DIME_CF))
10706           break;
10707         if (soap_getdimehdr(soap))
10708           break;
10709       }
10710 end:
10711       if (soap->fdimewriteclose)
10712         soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
10713       soap->dime.size = 0;
10714       soap->dime.id = id;
10715       soap->dime.type = type;
10716       soap->dime.options = options;
10717     }
10718     else if (soap->dime.flags & SOAP_DIME_CF)
10719     { const char *id, *type, *options;
10720       register soap_wchar c;
10721       register char *s;
10722       register int i;
10723       id = soap->dime.id;
10724       type = soap->dime.type;
10725       options = soap->dime.options;
10726       if (soap_new_block(soap))
10727         return SOAP_EOM;
10728       for (;;)
10729       { s = (char*)soap_push_block(soap, soap->dime.size);
10730         if (!s)
10731           return soap->error = SOAP_EOM;
10732         for (i = soap->dime.size; i > 0; i--)
10733         { if ((int)(c = soap_get1(soap)) == EOF)
10734             return soap->error = SOAP_EOF;
10735           *s++ = (char)c;
10736         }
10737         if (soap_move(soap, -(long)soap->dime.size&3))
10738           return soap->error = SOAP_EOF;
10739         if (!(soap->dime.flags & SOAP_DIME_CF))
10740           break;
10741         if (soap_getdimehdr(soap))
10742           return soap->error;
10743       }
10744       soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */
10745       if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0)))
10746         return soap->error;
10747       soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */
10748       soap->dime.id = id;
10749       soap->dime.type = type;
10750       soap->dime.options = options;
10751     }
10752     else
10753       soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
10754     content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
10755     if (!content)
10756       return soap->error = SOAP_EOM;
10757     content->id = soap->dime.id;
10758     content->type = soap->dime.type;
10759     content->options = soap->dime.options;
10760     if (soap->error)
10761       return soap->error;
10762     soap_resolve_attachment(soap, content);
10763   }
10764   if (soap->error != SOAP_DIME_END)
10765     return soap->error;
10766   return soap->error = SOAP_OK;
10767 }
10768 #endif
10769 #endif
10770
10771 /******************************************************************************/
10772 #ifndef WITH_LEANER
10773 #ifndef PALM_1
10774 SOAP_FMAC1
10775 int
10776 SOAP_FMAC2
10777 soap_getmimehdr(struct soap *soap)
10778 { struct soap_multipart *content;
10779   do
10780   { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
10781       return soap->error;
10782   }
10783   while (!*soap->msgbuf);
10784   if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
10785   { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
10786     /* remove white space */
10787     while (soap_blank(*s))
10788       s--;
10789     s[1] = '\0';
10790     if (soap->mime.boundary)
10791     { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
10792         return soap->error = SOAP_MIME_ERROR;
10793     }
10794     else
10795       soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
10796     if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
10797       return soap->error;
10798   }
10799   if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
10800     return soap->error = SOAP_EOM;
10801   content = soap->mime.last;
10802   for (;;)
10803   { register char *key = soap->msgbuf;
10804     register char *val;
10805     if (!*key)
10806       break;
10807     DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
10808     val = strchr(soap->msgbuf, ':');
10809     if (val)
10810     { *val = '\0';
10811       do val++;
10812       while (*val && *val <= 32);
10813       if (!soap_tag_cmp(key, "Content-ID"))
10814         content->id = soap_strdup(soap, val);
10815       else if (!soap_tag_cmp(key, "Content-Location"))
10816         content->location = soap_strdup(soap, val);
10817       else if (!soap_tag_cmp(key, "Content-Disposition"))
10818         content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
10819       else if (!soap_tag_cmp(key, "Content-Type"))
10820         content->type = soap_strdup(soap, val);
10821       else if (!soap_tag_cmp(key, "Content-Description"))
10822         content->description = soap_strdup(soap, val);
10823       else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
10824         content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
10825     }
10826     if (soap_getline(soap, key, sizeof(soap->msgbuf)))
10827       return soap->error;
10828   }
10829   return SOAP_OK;
10830 }
10831 #endif
10832 #endif
10833
10834 /******************************************************************************/
10835 #ifndef WITH_LEANER
10836 #ifndef PALM_1
10837 SOAP_FMAC1
10838 int
10839 SOAP_FMAC2
10840 soap_getmime(struct soap *soap)
10841 { while (soap_get_mime_attachment(soap, NULL))
10842     ;
10843   return soap->error;
10844 }
10845 #endif
10846 #endif
10847
10848 /******************************************************************************/
10849 #ifndef WITH_LEANER
10850 #ifndef PALM_1
10851 SOAP_FMAC1
10852 void
10853 SOAP_FMAC2
10854 soap_post_check_mime_attachments(struct soap *soap)
10855 { soap->imode |= SOAP_MIME_POSTCHECK;
10856 }
10857 #endif
10858 #endif
10859
10860 /******************************************************************************/
10861 #ifndef WITH_LEANER
10862 #ifndef PALM_1
10863 SOAP_FMAC1
10864 int
10865 SOAP_FMAC2
10866 soap_check_mime_attachments(struct soap *soap)
10867 { if (soap->mode & SOAP_MIME_POSTCHECK)
10868     return soap_get_mime_attachment(soap, NULL) != NULL;
10869   return 0;
10870 }
10871 #endif
10872 #endif
10873
10874 /******************************************************************************/
10875 #ifndef WITH_LEANER
10876 #ifndef PALM_1
10877 SOAP_FMAC1
10878 struct soap_multipart *
10879 SOAP_FMAC2
10880 soap_get_mime_attachment(struct soap *soap, void *handle)
10881 { register soap_wchar c = 0;
10882   register size_t i, m = 0;
10883   register char *s, *t = NULL;
10884   register struct soap_multipart *content;
10885   register short flag = 0;
10886   if (!(soap->mode & SOAP_ENC_MIME))
10887     return NULL;
10888   content = soap->mime.last;
10889   if (!content)
10890   { if (soap_getmimehdr(soap))
10891       return NULL;
10892     content = soap->mime.last;
10893   }
10894   else if (content != soap->mime.first)
10895   { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
10896     { if (!content->ptr)
10897         return NULL;
10898     }
10899   }
10900   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:""));
10901   if (!content->ptr && soap_new_block(soap))
10902   { soap->error = SOAP_EOM;
10903     return NULL;
10904   }
10905   for (;;)
10906   { if (content->ptr)
10907       s = soap->tmpbuf;
10908     else if (!(s = (char*)soap_push_block(soap, sizeof(soap->tmpbuf))))
10909     { soap->error = SOAP_EOM;
10910       return NULL;
10911     }
10912     for (i = 0; i < sizeof(soap->tmpbuf); i++)
10913     { if (m > 0)
10914       { *s++ = *t++;
10915         m--;
10916       }
10917       else
10918       { if (!flag)
10919         { c = soap_get1(soap);
10920           if ((int)c == EOF)
10921           { soap->error = SOAP_EOF;
10922             return NULL;
10923           }
10924         }
10925         if (flag || c == '\r')
10926         { t = soap->msgbuf;
10927           memset(t, 0, sizeof(soap->msgbuf));
10928           strcpy(t, "\n--");
10929           if (soap->mime.boundary)
10930             strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
10931           do c = soap_getchar(soap);
10932           while (c == *t++);
10933           if ((int)c == EOF)
10934           { soap->error = SOAP_EOF;
10935             return NULL;
10936           }
10937           if (!*--t)
10938             goto end;
10939           *t = (char)c;
10940           flag = (c == '\r');
10941           m = t - soap->msgbuf + 1 - flag;
10942           t = soap->msgbuf;
10943           c = '\r';
10944         }
10945         *s++ = (char)c;
10946       }
10947     }
10948     if (content->ptr && soap->fmimewrite)
10949     { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
10950         break;
10951     }
10952   }
10953 end:
10954   *s = '\0'; /* force 0-terminated */
10955   if (content->ptr)
10956   { if (!soap->error && soap->fmimewrite)
10957       soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
10958     if (soap->fmimewriteclose)
10959       soap->fmimewriteclose(soap, (void*)content->ptr);
10960     if (soap->error)
10961       return NULL;
10962   }
10963   else
10964   { content->size = soap_size_block(soap, i+1)-1;
10965     content->ptr = soap_save_block(soap, NULL, 0);
10966   }
10967   soap_resolve_attachment(soap, content);
10968   if (c == '-' && soap_getchar(soap) == '-')
10969   { soap->mode &= ~SOAP_ENC_MIME;
10970     if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
10971       return NULL;
10972   }
10973   else
10974   { while (c != '\r' && (int)c != EOF && soap_blank(c))
10975       c = soap_getchar(soap);
10976     if (c != '\r' || soap_getchar(soap) != '\n')
10977     { soap->error = SOAP_MIME_ERROR;
10978       return NULL;
10979     }
10980     if (soap_getmimehdr(soap))
10981       return NULL;
10982   }
10983   return content;
10984 }
10985 #endif
10986 #endif
10987
10988 /******************************************************************************/
10989 #ifndef WITH_LEANER
10990 #ifndef PALM_1
10991 SOAP_FMAC1
10992 int
10993 SOAP_FMAC2
10994 soap_match_cid(struct soap *soap, const char *s, const char *t)
10995 { register size_t n;
10996   if (!s)
10997     return 1;
10998   if (!strcmp(s, t))
10999     return 0;
11000   if (!strncmp(s, "cid:", 4))
11001     s += 4;
11002   n = strlen(t);
11003   if (*t == '<')
11004   { t++;
11005     n -= 2;
11006   }
11007   if (!strncmp(s, t, n) && !s[n])
11008     return 0;
11009   soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
11010   if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
11011     return 0;
11012   return 1;
11013 }
11014 #endif
11015 #endif
11016
11017 /******************************************************************************/
11018 #ifndef WITH_LEANER
11019 #ifndef PALM_1
11020 static void
11021 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
11022 { if (content->id)
11023   { register struct soap_xlist **xp = &soap->xlist;
11024     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id));
11025     while (*xp)
11026     { register struct soap_xlist *xq = *xp;
11027       if (!soap_match_cid(soap, xq->id, content->id))
11028       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id));
11029         *xp = xq->next;
11030         *xq->ptr = (unsigned char*)content->ptr;
11031         *xq->size = (int)content->size;
11032         *xq->type = (char*)content->type;
11033         if (content->options)
11034           *xq->options = (char*)content->options;
11035         else
11036           *xq->options = (char*)content->description;
11037         SOAP_FREE(soap, xq);
11038       }
11039       else
11040         xp = &(*xp)->next;
11041     }
11042   }
11043 }
11044 #endif
11045 #endif
11046
11047 /******************************************************************************/
11048 #ifndef WITH_LEANER
11049 #ifndef PALM_1
11050 SOAP_FMAC1
11051 int
11052 SOAP_FMAC2
11053 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
11054 { const char *s;
11055   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:""));
11056   if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
11057     return soap->error;
11058   if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
11059     return soap->error;
11060   s = soap_code_str(mime_codes, content->encoding);
11061   if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
11062     return soap->error;
11063   if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
11064     return soap->error;
11065   if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
11066     return soap->error;
11067   if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
11068     return soap->error;
11069   return soap_send_raw(soap, "\r\n", 2);
11070 }
11071 #endif
11072 #endif
11073
11074 /******************************************************************************/
11075 #ifndef WITH_LEANER
11076 #ifndef PALM_1
11077 SOAP_FMAC1
11078 int
11079 SOAP_FMAC2
11080 soap_putmime(struct soap *soap)
11081 { struct soap_multipart *content;
11082   if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
11083     return SOAP_OK;
11084   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
11085   for (content = soap->mime.first; content; content = content->next)
11086   { void *handle;
11087     if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
11088     { size_t size = content->size;
11089       if (!handle)
11090       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
11091         return soap->error;
11092       }
11093       if (soap_putmimehdr(soap, content))
11094         return soap->error;
11095       if (!size)
11096       { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
11097         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
11098           do 
11099           { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
11100             DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
11101             if (soap_send_raw(soap, soap->tmpbuf, size))
11102               break;
11103           } while (size); 
11104         }
11105         else
11106         { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
11107         }
11108       }
11109       else
11110       { do
11111         { size_t bufsize;
11112           if (size < sizeof(soap->tmpbuf))
11113             bufsize = size;
11114           else
11115             bufsize = sizeof(soap->tmpbuf);
11116           if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
11117           { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
11118             soap->error = SOAP_EOF;
11119             break;
11120           }
11121           if (soap_send_raw(soap, soap->tmpbuf, bufsize))
11122             break;
11123           size -= bufsize;
11124         } while (size);
11125       }
11126       if (soap->fmimereadclose)
11127         soap->fmimereadclose(soap, handle);
11128     }
11129     else
11130     { if (soap_putmimehdr(soap, content)
11131        || soap_send_raw(soap, content->ptr, content->size))
11132         return soap->error;
11133     }
11134   }
11135   return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
11136 }
11137 #endif
11138 #endif
11139
11140 /******************************************************************************/
11141 #ifndef WITH_LEANER
11142 #ifndef PALM_1
11143 SOAP_FMAC1
11144 void
11145 SOAP_FMAC2
11146 soap_set_dime(struct soap *soap)
11147 { soap->omode |= SOAP_ENC_DIME;
11148   soap->dime.first = NULL;
11149   soap->dime.last = NULL;
11150 }
11151 #endif
11152 #endif
11153
11154 /******************************************************************************/
11155 #ifndef WITH_LEANER
11156 #ifndef PALM_1
11157 SOAP_FMAC1
11158 void
11159 SOAP_FMAC2
11160 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
11161 { soap->omode |= SOAP_ENC_MIME;
11162   soap->mime.first = NULL;
11163   soap->mime.last = NULL;
11164   soap->mime.boundary = soap_strdup(soap, boundary);
11165   soap->mime.start = soap_strdup(soap, start);
11166 }
11167 #endif
11168 #endif
11169
11170 /******************************************************************************/
11171 #ifndef WITH_LEANER
11172 #ifndef PALM_1
11173 SOAP_FMAC1
11174 void
11175 SOAP_FMAC2
11176 soap_clr_dime(struct soap *soap)
11177 { soap->omode &= ~SOAP_ENC_DIME;
11178   soap->dime.first = NULL;
11179   soap->dime.last = NULL;
11180 }
11181 #endif
11182 #endif
11183
11184 /******************************************************************************/
11185 #ifndef WITH_LEANER
11186 #ifndef PALM_1
11187 SOAP_FMAC1
11188 void
11189 SOAP_FMAC2
11190 soap_clr_mime(struct soap *soap)
11191 { soap->omode &= ~SOAP_ENC_MIME;
11192   soap->mime.first = NULL;
11193   soap->mime.last = NULL;
11194   soap->mime.boundary = NULL;
11195   soap->mime.start = NULL;
11196 }
11197 #endif
11198 #endif
11199
11200 /******************************************************************************/
11201 #ifndef WITH_LEANER
11202 #ifndef PALM_1
11203 static struct soap_multipart*
11204 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
11205 { struct soap_multipart *content;
11206   content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
11207   if (content)
11208   { content->next = NULL;
11209     content->ptr = ptr;
11210     content->size = size;
11211     content->id = NULL;
11212     content->type = NULL;
11213     content->options = NULL;
11214     content->encoding = SOAP_MIME_NONE;
11215     content->location = NULL;
11216     content->description = NULL;
11217     if (!*first)
11218       *first = content;
11219     if (*last)
11220       (*last)->next = content;
11221     *last = content;
11222   }
11223   return content;
11224 }
11225 #endif
11226 #endif
11227
11228 /******************************************************************************/
11229 #ifndef WITH_LEANER
11230 #ifndef PALM_1
11231 SOAP_FMAC1
11232 int
11233 SOAP_FMAC2
11234 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
11235 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
11236   if (!content)
11237     return SOAP_EOM;
11238   content->id = soap_strdup(soap, id);
11239   content->type = soap_strdup(soap, type);
11240   content->options = soap_dime_option(soap, optype, option);
11241   return SOAP_OK;
11242 }
11243 #endif
11244 #endif
11245
11246 /******************************************************************************/
11247 #ifndef WITH_LEANER
11248 #ifndef PALM_1
11249 SOAP_FMAC1
11250 int
11251 SOAP_FMAC2
11252 soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
11253 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
11254   if (!content)
11255     return SOAP_EOM;
11256   content->id = soap_strdup(soap, id);
11257   content->type = soap_strdup(soap, type);
11258   content->encoding = encoding;
11259   content->location = soap_strdup(soap, location);
11260   content->description = soap_strdup(soap, description);
11261   return SOAP_OK;
11262 }
11263 #endif
11264 #endif
11265
11266 /******************************************************************************/
11267 #ifndef WITH_LEANER
11268 #ifndef PALM_1
11269 SOAP_FMAC1
11270 struct soap_multipart*
11271 SOAP_FMAC2
11272 soap_next_multipart(struct soap_multipart *content)
11273 { if (content)
11274     return content->next;
11275   return NULL;
11276 }
11277 #endif
11278 #endif
11279
11280 /******************************************************************************/
11281 #ifndef WITH_LEANER
11282 #ifndef PALM_1
11283 static void
11284 soap_select_mime_boundary(struct soap *soap)
11285 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
11286   { register char *s = soap->mime.boundary;
11287     register size_t n = 0;
11288     if (s)
11289       n = strlen(s);
11290     if (n < 16)
11291     { n = 64;
11292       s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
11293       if (!s)
11294         return;
11295     }
11296     strcpy(s, "==");
11297     s += 2;
11298     n -= 4;
11299     while (n)
11300     { *s++ = soap_base64o[soap_random & 0x3F];
11301       n--;
11302     }
11303     strcpy(s, "==");
11304   }
11305   if (!soap->mime.start)
11306     soap->mime.start = "<SOAP-ENV:Envelope>";
11307 }
11308 #endif
11309 #endif
11310
11311 /******************************************************************************/
11312 #ifndef WITH_LEANER
11313 #ifndef PALM_1
11314 static int
11315 soap_valid_mime_boundary(struct soap *soap)
11316 { register struct soap_multipart *content;
11317   register size_t k;
11318   if (soap->fmimeread)
11319     return SOAP_OK;
11320   k = strlen(soap->mime.boundary);
11321   for (content = soap->mime.first; content; content = content->next)
11322   { if (content->ptr && content->size >= k)
11323     { register const char *p = (const char*)content->ptr; 
11324       register size_t i;
11325       for (i = 0; i < content->size - k; i++, p++)
11326       { if (!strncmp(p, soap->mime.boundary, k))
11327           return SOAP_ERR;
11328       }
11329     }
11330   }
11331   return SOAP_OK;
11332 }
11333 #endif
11334 #endif
11335
11336 /******************************************************************************\
11337  *
11338  *      HTTP cookie handling
11339  *
11340 \******************************************************************************/
11341
11342 #ifdef WITH_COOKIES
11343 /******************************************************************************/
11344 SOAP_FMAC1
11345 size_t
11346 SOAP_FMAC2
11347 soap_encode_cookie(const char *s, char *t, size_t len)
11348 { register int c;
11349   register size_t n = len;
11350   while ((c = *s++) && --n > 0)
11351   { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c))
11352       *t++ = c;
11353     else if (n > 2)
11354     { *t++ = '%';
11355       *t++ = (c >> 4) + (c > 159 ? '7' : '0');
11356       c &= 0xF;
11357       *t++ = c + (c > 9 ? '7' : '0');
11358       n -= 2;
11359     }
11360     else
11361       break;
11362   }
11363   *t = '\0';
11364   return len - n;
11365 }
11366
11367 /******************************************************************************/
11368 SOAP_FMAC1
11369 struct soap_cookie*
11370 SOAP_FMAC2
11371 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
11372 { struct soap_cookie *p;
11373   size_t n;
11374   if (!domain)
11375     domain = soap->cookie_domain;
11376   if (!path)
11377     path = soap->cookie_path;
11378   if (*path == '/')
11379     path++;
11380   n = strlen(path);
11381   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)"));
11382   for (p = soap->cookies; p; p = p->next)
11383   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s=%s domain=%s path=%s env=%hd\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->env));
11384     if (!strcmp(p->name, name)
11385      && p->domain
11386      && p->path
11387      && !strcmp(p->domain, domain)
11388      && !strncmp(p->path, path, n))
11389       break;
11390   }
11391   return p;
11392 }
11393
11394 /******************************************************************************/
11395 SOAP_FMAC1
11396 struct soap_cookie*
11397 SOAP_FMAC2
11398 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
11399 { struct soap_cookie **p, *q;
11400   int n;
11401   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)"));
11402   if (!domain)
11403     domain = soap->cookie_domain;
11404   if (!path)
11405     path = soap->cookie_path;
11406   if (!path)
11407   { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR);
11408     return NULL;
11409   }
11410   if (*path == '/')
11411     path++;
11412   q = soap_cookie(soap, name, domain, path);
11413   if (!q)
11414   { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
11415     { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
11416         strcpy(q->name, name);
11417       q->value = NULL;
11418       q->domain = NULL;
11419       q->path = NULL;
11420       q->expire = -1;
11421       q->maxage = -1;
11422       q->version = 0;
11423       q->secure = 0;
11424       q->modified = 0;
11425       for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
11426         if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0)
11427           break;
11428       if (n)
11429       { q->next = *p;
11430         *p = q;
11431       }
11432       else
11433       { SOAP_FREE(soap, q->name);
11434         SOAP_FREE(soap, q);
11435         q = NULL;
11436       }
11437     }
11438   }
11439   else
11440     q->modified = 1;
11441   if (q)
11442   { if (q->value)
11443     { SOAP_FREE(soap, q->value);
11444       q->value = NULL;
11445     }
11446     if (q->domain)
11447     { SOAP_FREE(soap, q->domain);
11448       q->domain = NULL;
11449     }
11450     if (q->path)
11451     { SOAP_FREE(soap, q->path);
11452       q->path = NULL;
11453     }
11454     if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
11455       strcpy(q->value, value);
11456     if (domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
11457       strcpy(q->domain, domain);
11458     if (path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
11459       strcpy(q->path, path);
11460     q->session = 1;
11461     q->env = 0;
11462   }
11463   return q;
11464 }
11465
11466 /******************************************************************************/
11467 SOAP_FMAC1
11468 void
11469 SOAP_FMAC2
11470 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
11471 { struct soap_cookie **p, *q;
11472   if (!domain)
11473     domain = soap->cookie_domain;
11474   if (!domain)
11475   { soap_set_receiver_error(soap, "Cookie domain not set", NULL, SOAP_HTTP_ERROR);
11476     return;
11477   }
11478   if (!path)
11479     path = soap->cookie_path;
11480   if (!path)
11481   { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR);
11482     return;
11483   }
11484   if (*path == '/')
11485     path++;
11486   for (p = &soap->cookies, q = *p; q; q = *p)
11487     if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
11488     { if (q->value)
11489         SOAP_FREE(soap, q->value);
11490       if (q->domain)
11491         SOAP_FREE(soap, q->domain);
11492       if (q->path)
11493         SOAP_FREE(soap, q->path);
11494       *p = q->next;
11495       SOAP_FREE(soap, q);
11496     }
11497     else
11498       p = &q->next;
11499 }
11500
11501 /******************************************************************************/
11502 SOAP_FMAC1
11503 char *
11504 SOAP_FMAC2
11505 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
11506 { struct soap_cookie *p;
11507   if ((p = soap_cookie(soap, name, domain, path)))
11508     return p->value;
11509   return NULL;
11510 }
11511
11512 /******************************************************************************/
11513 SOAP_FMAC1
11514 char *
11515 SOAP_FMAC2
11516 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
11517 { struct soap_cookie *p;
11518   if ((p = soap_cookie(soap, name, domain, path)) && p->env)
11519     return p->value;
11520   return NULL;
11521 }
11522
11523 /******************************************************************************/
11524 SOAP_FMAC1
11525 time_t
11526 SOAP_FMAC2
11527 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
11528 { struct soap_cookie *p;
11529   if ((p = soap_cookie(soap, name, domain, path)))
11530     return p->expire;
11531   return -1;
11532 }
11533
11534 /******************************************************************************/
11535 SOAP_FMAC1
11536 int
11537 SOAP_FMAC2
11538 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
11539 { struct soap_cookie *p;
11540   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)"));
11541   if ((p = soap_cookie(soap, name, domain, path)))
11542   { p->maxage = expire;
11543     p->modified = 1;
11544     return SOAP_OK;
11545   }
11546   return SOAP_ERR;
11547 }
11548
11549 /******************************************************************************/
11550 SOAP_FMAC1
11551 int
11552 SOAP_FMAC2
11553 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
11554 { struct soap_cookie *p;
11555   if ((p = soap_cookie(soap, name, domain, path)))
11556   { p->session = 1;
11557     p->modified = 1;
11558     return SOAP_OK;
11559   }
11560   return SOAP_ERR;
11561 }
11562
11563 /******************************************************************************/
11564 SOAP_FMAC1
11565 int
11566 SOAP_FMAC2
11567 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
11568 { struct soap_cookie *p;
11569   if ((p = soap_cookie(soap, name, domain, path)))
11570   { p->session = 0;
11571     p->modified = 1;
11572     return SOAP_OK;
11573   }
11574   return SOAP_ERR;
11575 }
11576
11577 /******************************************************************************/
11578 SOAP_FMAC1
11579 int
11580 SOAP_FMAC2
11581 soap_putsetcookies(struct soap *soap)
11582 { struct soap_cookie *p;
11583   char *s, tmp[4096];
11584   const char *t;
11585   for (p = soap->cookies; p; p = p->next)
11586   { if (p->modified || !p->env)
11587     { s = tmp;
11588       if (p->name)
11589         s += soap_encode_cookie(p->name, s, tmp-s+4064);
11590       if (p->value && *p->value)
11591       { *s++ = '=';
11592         s += soap_encode_cookie(p->value, s, tmp-s+4064);
11593       }
11594       if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
11595         sprintf(s, ";Domain=\"%s\"", p->domain);
11596       else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
11597         sprintf(s, ";Domain=\"%s\"", soap->cookie_domain);
11598       strcat(s, ";Path=/");
11599       if (p->path)
11600         t = p->path;
11601       else
11602         t = soap->cookie_path;
11603       if (t)
11604       { if (*t == '/')
11605           t++;
11606         if ((int)strlen(t) < tmp-s+4064)
11607           strcat(s, t);
11608       }
11609       s += strlen(s);
11610       if (p->version > 0 && s-tmp < 4060)
11611       { sprintf(s, ";Version=%u", p->version);
11612         s += strlen(s);
11613       }
11614       if (p->maxage >= 0 && s-tmp < 4060)
11615       { sprintf(s, ";Max-Age=%ld", p->maxage);
11616         s += strlen(s);
11617       }
11618       if (p->secure && s-tmp < 4073)
11619         strcpy(s, ";Secure");
11620       DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
11621       if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
11622         return soap->error;
11623     }
11624   }
11625   return SOAP_OK;
11626 }
11627
11628 /******************************************************************************/
11629 SOAP_FMAC1
11630 int
11631 SOAP_FMAC2
11632 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
11633 { struct soap_cookie **p, *q;
11634   unsigned int version = 0;
11635   time_t now = time(NULL);
11636   char *s, tmp[4096];
11637   p = &soap->cookies;
11638   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path));
11639   if (*path == '/')
11640     path++;
11641   while ((q = *p))
11642   { if (q->expire && now > q->expire)
11643     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
11644       SOAP_FREE(soap, q->name);
11645       if (q->value)
11646         SOAP_FREE(soap, q->value);
11647       if (q->domain)
11648         SOAP_FREE(soap, q->domain);
11649       if (q->path)
11650         SOAP_FREE(soap, q->path);
11651       *p = q->next;
11652       SOAP_FREE(soap, q);
11653     }
11654     else
11655     { size_t domlen = 0;
11656       if (q->domain)
11657       { const char *s = strchr(q->domain, ':');
11658         if (s)
11659           domlen = s - q->domain;
11660         else
11661           domlen = strlen(q->domain);
11662       }
11663       if ((!q->domain || !strncmp(q->domain, domain, domlen))
11664           && (!q->path || !strncmp(q->path, path, strlen(q->path)))
11665           && (!q->secure || secure))
11666       { s = tmp;
11667         if (q->version != version)
11668         { sprintf(s, "$Version=%u;", q->version);
11669           version = q->version;
11670         }
11671         if (q->name)
11672           s += soap_encode_cookie(q->name, s, tmp-s+4080);
11673         if (q->value && *q->value)
11674         { *s++ = '=';
11675           s += soap_encode_cookie(q->value, s, tmp-s+4080);
11676         }
11677         if (q->path && (int)strlen(q->path) < tmp-s+4080)
11678         { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
11679           s += strlen(s);
11680         }
11681         if (q->domain && (int)strlen(q->domain) < tmp-s+4080)
11682           sprintf(s, ";$Domain=\"%s\"", q->domain);
11683         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
11684         if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
11685           return soap->error;
11686       }
11687       p = &q->next;
11688     }
11689   }
11690   return SOAP_OK;
11691 }
11692
11693 /******************************************************************************/
11694 SOAP_FMAC1
11695 void
11696 SOAP_FMAC2
11697 soap_getcookies(struct soap *soap, const char *val)
11698 { struct soap_cookie *p = NULL, *q;
11699   const char *s;
11700   char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
11701   char *domain = NULL;
11702   char *path = NULL;
11703   unsigned int version = 0;
11704   time_t now = time(NULL);
11705   if (!val)
11706     return;
11707   s = val;
11708   while (*s)
11709   { s = soap_decode_key(tmp, sizeof(tmp), s);
11710     if (!soap_tag_cmp(tmp, "$Version"))
11711     { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
11712       { if (p)
11713           p->version = (int)atol(tmp);
11714         else
11715           version = (int)atol(tmp);
11716       }
11717     }
11718     else if (!soap_tag_cmp(tmp, "$Path"))
11719     { s = soap_decode_val(tmp, sizeof(tmp), s);
11720       if (*tmp)
11721       { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11722           strcpy(t, tmp);
11723       }
11724       else
11725         t = NULL;
11726       if (p)
11727       { if (p->path)
11728           SOAP_FREE(soap, p->path);
11729         p->path = t;
11730       }
11731       else
11732       { if (path)
11733           SOAP_FREE(soap, path);
11734         path = t;
11735       }
11736     }
11737     else if (!soap_tag_cmp(tmp, "$Domain"))
11738     { s = soap_decode_val(tmp, sizeof(tmp), s);
11739       if (*tmp)
11740       { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11741           strcpy(t, tmp);
11742       }
11743       else
11744         t = NULL;
11745       if (p)
11746       { if (p->domain)
11747           SOAP_FREE(soap, p->domain);
11748         p->domain = t;
11749       }
11750       else
11751       { if (domain)
11752           SOAP_FREE(soap, domain);
11753         domain = t;
11754       }
11755     }
11756     else if (p && !soap_tag_cmp(tmp, "Path"))
11757     { if (p->path)
11758         SOAP_FREE(soap, p->path);
11759       s = soap_decode_val(tmp, sizeof(tmp), s);
11760       if (*tmp)
11761       { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11762           strcpy(p->path, tmp);
11763       }
11764       else
11765         p->path = NULL;
11766     }
11767     else if (p && !soap_tag_cmp(tmp, "Domain"))
11768     { if (p->domain)
11769         SOAP_FREE(soap, p->domain);
11770       s = soap_decode_val(tmp, sizeof(tmp), s);
11771       if (*tmp)
11772       { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11773           strcpy(p->domain, tmp);
11774       }
11775       else
11776         p->domain = NULL;
11777     }
11778     else if (p && !soap_tag_cmp(tmp, "Version"))
11779     { s = soap_decode_val(tmp, sizeof(tmp), s);
11780       p->version = (unsigned int)atol(tmp);
11781     }
11782     else if (p && !soap_tag_cmp(tmp, "Max-Age"))
11783     { s = soap_decode_val(tmp, sizeof(tmp), s);
11784       p->expire = now + atol(tmp);
11785     }
11786     else if (p && !soap_tag_cmp(tmp, "Expires"))
11787     { struct tm T;
11788       char a[3]; 
11789       static const char mns[] = "anebarprayunulugepctovec";
11790       s = soap_decode_val(tmp, sizeof(tmp), s);
11791       if (strlen(tmp) > 20)
11792       { memset((void*)&T, 0, sizeof(T));
11793         a[0] = tmp[4];
11794         a[1] = tmp[5];
11795         a[2] = '\0';
11796         T.tm_mday = (int)atol(a);
11797         a[0] = tmp[8];
11798         a[1] = tmp[9];
11799         T.tm_mon = (strstr(mns, a) - mns) / 2;
11800         a[0] = tmp[11];
11801         a[1] = tmp[12];
11802         T.tm_year = 100 + (int)atol(a);
11803         a[0] = tmp[13];
11804         a[1] = tmp[14];
11805         T.tm_hour = (int)atol(a);
11806         a[0] = tmp[16];
11807         a[1] = tmp[17];
11808         T.tm_min = (int)atol(a);
11809         a[0] = tmp[19];
11810         a[1] = tmp[20];
11811         T.tm_sec = (int)atol(a);
11812         p->expire = soap_timegm(&T);
11813       }
11814     }
11815     else if (p && !soap_tag_cmp(tmp, "Secure"))
11816       p->secure = 1;
11817     else
11818     { if (p)
11819       { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
11820         if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
11821         { q->version = p->version;
11822           q->expire = p->expire;
11823           q->secure = p->secure;
11824           q->env = 1;
11825         }
11826         if (p->name)
11827           SOAP_FREE(soap, p->name);
11828         if (p->value)
11829           SOAP_FREE(soap, p->value);
11830         if (p->domain)
11831           SOAP_FREE(soap, p->domain);
11832         if (p->path)
11833           SOAP_FREE(soap, p->path);
11834         SOAP_FREE(soap, p);
11835       }
11836       if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
11837       { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
11838         strcpy(p->name, tmp);
11839         s = soap_decode_val(tmp, sizeof(tmp), s);
11840         if (*tmp)
11841         { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
11842           strcpy(p->value, tmp);
11843         }
11844         else
11845           p->value = NULL;
11846         p->domain = domain;
11847         p->path = path;
11848         p->expire = 0;
11849         p->secure = 0;
11850         p->version = version;
11851       }
11852     }
11853   }
11854   if (p)
11855   { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
11856     if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
11857     { q->version = p->version;
11858       q->expire = p->expire;
11859       q->secure = p->secure;
11860       q->env = 1;
11861     }
11862     if (p->name)
11863       SOAP_FREE(soap, p->name);
11864     if (p->value)
11865       SOAP_FREE(soap, p->value);
11866     if (p->domain)
11867       SOAP_FREE(soap, p->domain);
11868     if (p->path)
11869       SOAP_FREE(soap, p->path);
11870     SOAP_FREE(soap, p);
11871   }
11872   if (domain)
11873     SOAP_FREE(soap, domain);
11874   if (path)
11875     SOAP_FREE(soap, path);
11876 }
11877
11878 /******************************************************************************/
11879 SOAP_FMAC1
11880 int
11881 SOAP_FMAC2
11882 soap_getenv_cookies(struct soap *soap)
11883 { struct soap_cookie *p;
11884   const char *s;
11885   char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
11886   if (!(s = getenv("HTTP_COOKIE")))
11887     return SOAP_ERR;
11888   do
11889   { s = soap_decode_key(key, sizeof(key), s);
11890     s = soap_decode_val(val, sizeof(val), s);
11891     p = soap_set_cookie(soap, key, val, NULL, NULL);
11892     if (p)
11893       p->env = 1;
11894   } while (*s);
11895   return SOAP_OK;
11896 }
11897
11898 /******************************************************************************/
11899 SOAP_FMAC1
11900 struct soap_cookie*
11901 SOAP_FMAC2
11902 soap_copy_cookies(struct soap *copy, struct soap *soap)
11903 { struct soap_cookie *p, **q, *r;
11904   q = &r;
11905   for (p = soap->cookies; p; p = p->next)
11906   { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
11907       return r;
11908     **q = *p;
11909     if (p->name)
11910     { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
11911         strcpy((*q)->name, p->name);
11912     }
11913     if (p->value)
11914     { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
11915         strcpy((*q)->value, p->value);
11916     }
11917     if (p->domain)
11918     { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
11919         strcpy((*q)->domain, p->domain);
11920     }
11921     if (p->path)
11922     { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
11923         strcpy((*q)->path, p->path);
11924     }
11925     q = &(*q)->next;
11926   }
11927   *q = NULL;
11928   return r;
11929 }
11930
11931 /******************************************************************************/
11932 SOAP_FMAC1
11933 void
11934 SOAP_FMAC2
11935 soap_free_cookies(struct soap *soap)
11936 { struct soap_cookie *p;
11937   for (p = soap->cookies; p; p = soap->cookies)
11938   { soap->cookies = p->next;
11939     SOAP_FREE(soap, p->name);
11940     if (p->value)
11941       SOAP_FREE(soap, p->value);
11942     if (p->domain)
11943       SOAP_FREE(soap, p->domain);
11944     if (p->path)
11945       SOAP_FREE(soap, p->path);
11946     SOAP_FREE(soap, p);
11947   }
11948 }
11949
11950 /******************************************************************************/
11951 #endif /* WITH_COOKIES */
11952
11953 /******************************************************************************/
11954 #ifdef WITH_GZIP
11955 #ifndef PALM_1
11956 static int
11957 soap_getgziphdr(struct soap *soap)
11958 { int i;
11959   soap_wchar c, f = 0;
11960   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
11961   for (i = 0; i < 9; i++)
11962   { if ((int)(c = soap_get1(soap) == EOF))
11963       return soap->error = SOAP_EOF;
11964     if (i == 2)
11965       f = c;
11966   }
11967   if (f & 0x04) /* FEXTRA */
11968   { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
11969     { if ((int)soap_get1(soap) == EOF)
11970         return soap->error = SOAP_EOF;
11971     }
11972   }
11973   if (f & 0x08) /* FNAME */
11974   { do
11975       c = soap_get1(soap);
11976     while (c && (int)c != EOF);
11977   }
11978   if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */
11979   { do
11980       c = soap_get1(soap);
11981     while (c && (int)c != EOF);
11982   }
11983   if ((int)c != EOF && (f & 0x01)) /* FHCRC */
11984   { if ((int)(c = soap_get1(soap)) != EOF)
11985       c = soap_get1(soap);
11986   }
11987   if ((int)c == EOF)
11988     return soap->error = SOAP_EOF;
11989   return SOAP_OK;
11990 }
11991 #endif
11992 #endif
11993
11994 /******************************************************************************/
11995 #ifndef PALM_1
11996 SOAP_FMAC1
11997 int
11998 SOAP_FMAC2
11999 soap_begin_recv(struct soap *soap)
12000 { soap_wchar c;
12001   soap->error = SOAP_OK;
12002   soap_free(soap);
12003   soap_set_local_namespaces(soap);
12004   soap->version = 0;    /* don't assume we're parsing SOAP content by default */
12005 #ifndef WITH_NOIDREF
12006   soap_free_iht(soap);
12007 #endif
12008   if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
12009     soap->omode |= SOAP_IO_CHUNK;
12010   soap->imode &= ~SOAP_IO;
12011   soap->mode = soap->imode;
12012   if (!soap->keep_alive)
12013   { soap->buflen = 0;
12014     soap->bufidx = 0;
12015   }
12016   if (!(soap->mode & SOAP_IO_KEEPALIVE))
12017     soap->keep_alive = 0;
12018   soap->ahead = 0;
12019   soap->peeked = 0;
12020   soap->level = 0;
12021   soap->part = SOAP_BEGIN;
12022   soap->alloced = 0;
12023   soap->count = 0;
12024   soap->length = 0;
12025   soap->cdata = 0;
12026   *soap->endpoint = '\0';
12027   soap->action = NULL;
12028 #ifndef WITH_LEANER
12029   soap->dom = NULL;
12030   soap->dime.chunksize = 0;
12031   soap->dime.buflen = 0;
12032   soap->dime.list = NULL;
12033   soap->dime.first = NULL;
12034   soap->dime.last = NULL;
12035   soap->mime.list = NULL;
12036   soap->mime.first = NULL;
12037   soap->mime.last = NULL;
12038   soap->mime.boundary = NULL;
12039   soap->mime.start = NULL;
12040   soap->xlist = NULL;
12041 #endif
12042 #ifdef WIN32
12043 #ifndef UNDER_CE
12044 #ifndef WITH_FASTCGI
12045   if (!soap_valid_socket(soap->socket))
12046 #ifdef __BORLANDC__
12047     setmode((SOAP_SOCKET)soap->recvfd, O_BINARY);
12048 #else
12049     _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY);
12050 #endif
12051 #endif
12052 #endif
12053 #endif
12054 #ifdef WITH_ZLIB
12055   soap->mode &= ~SOAP_ENC_ZLIB;
12056   soap->zlib_in = SOAP_ZLIB_NONE;
12057   soap->zlib_out = SOAP_ZLIB_NONE;
12058   soap->d_stream.next_in = Z_NULL;
12059   soap->d_stream.avail_in = 0;
12060   soap->d_stream.next_out = (Byte*)soap->buf;
12061   soap->d_stream.avail_out = SOAP_BUFLEN;
12062   soap->z_ratio_in = 1.0;
12063 #endif
12064 #ifndef WITH_LEANER
12065   if (soap->fprepareinit)
12066     soap->fprepareinit(soap);
12067 #endif
12068   c = soap_getchar(soap);
12069 #ifdef WITH_GZIP
12070   if (c == 0x1F)
12071   { if (soap_getgziphdr(soap))
12072       return soap->error;
12073     if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
12074       return soap->error = SOAP_ZLIB_ERROR;
12075     soap->zlib_state = SOAP_ZLIB_INFLATE;
12076     soap->mode |= SOAP_ENC_ZLIB;
12077     soap->zlib_in = SOAP_ZLIB_GZIP;
12078     soap->z_crc = crc32(0L, NULL, 0);
12079     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
12080     memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
12081     /* should not chunk over plain transport, so why bother to check? */
12082     /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
12083     /*   soap->z_buflen = soap->bufidx; */
12084     /* else */
12085     soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
12086     soap->d_stream.avail_in = soap->buflen - soap->bufidx;
12087     soap->z_buflen = soap->buflen;
12088     soap->buflen = soap->bufidx;
12089     c = soap_getchar(soap);
12090   }  
12091 #endif
12092 #ifndef WITH_LEANER
12093   if (c == '-' && soap_get0(soap) == '-')
12094     soap->mode |= SOAP_ENC_MIME;
12095   else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
12096     soap->mode |= SOAP_ENC_DIME;
12097   else
12098 #endif
12099   { while (soap_blank(c))
12100       c = soap_getchar(soap);
12101   }
12102   if ((int)c == EOF)
12103     return soap->error = SOAP_EOF;
12104   soap_unget(soap, c);
12105 #ifndef WITH_NOHTTP
12106   /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */
12107   if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
12108   { soap->mode &= ~SOAP_IO;
12109     soap->error = soap->fparse(soap);
12110     if (soap->error && soap->error < SOAP_STOP)
12111     { soap->keep_alive = 0; /* force close later */
12112       return soap->error;
12113     }
12114     if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
12115     { soap->chunkbuflen = soap->buflen;
12116       soap->buflen = soap->bufidx;
12117       soap->chunksize = 0;
12118     }
12119 #ifndef WITH_LEANER
12120     else if (soap->fpreparerecv && soap->buflen != soap->bufidx)
12121       soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx);
12122 #endif
12123 #ifdef WITH_ZLIB
12124     if (soap->zlib_in != SOAP_ZLIB_NONE)
12125     { /* fparse should not use soap_unget to push back last char */
12126 #ifdef WITH_GZIP
12127       c = soap_get1(soap);
12128       if (c == 0x1F)
12129       { if (soap_getgziphdr(soap))
12130           return soap->error;
12131         if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
12132           return soap->error = SOAP_ZLIB_ERROR;
12133         soap->zlib_state = SOAP_ZLIB_INFLATE;
12134         soap->z_crc = crc32(0L, NULL, 0);
12135         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
12136       }
12137       else
12138       { soap_revget1(soap);
12139 #else
12140       {
12141 #endif
12142         if (inflateInit(&soap->d_stream) != Z_OK)
12143           return soap->error = SOAP_ZLIB_ERROR;
12144         soap->zlib_state = SOAP_ZLIB_INFLATE;
12145         DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
12146       }
12147       soap->mode |= SOAP_ENC_ZLIB;
12148       memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
12149       soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
12150       soap->d_stream.avail_in = soap->buflen - soap->bufidx;
12151       soap->z_buflen = soap->buflen;
12152       soap->buflen = soap->bufidx;
12153     }
12154 #endif
12155     if (soap->error)
12156     { if (soap->error == SOAP_FORM && soap->fform)
12157       { soap->error = soap->fform(soap);
12158         if (soap->error == SOAP_OK)
12159           soap->error = SOAP_STOP; /* prevents further processing */
12160       }
12161       return soap->error;
12162     }
12163   }
12164 #endif
12165 #ifndef WITH_LEANER
12166   if (soap->mode & SOAP_ENC_MIME)
12167   { if (soap_getmimehdr(soap))
12168       return soap->error;
12169     if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
12170       soap->mode |= SOAP_ENC_DIME;
12171   }
12172   if (soap->mode & SOAP_ENC_DIME)
12173   { if (soap_getdimehdr(soap))
12174       return soap->error;
12175     if (soap->dime.flags & SOAP_DIME_CF)
12176     { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
12177       soap->dime.chunksize = soap->dime.size;
12178       if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
12179       { soap->dime.buflen = soap->buflen;
12180         soap->buflen = soap->bufidx + soap->dime.chunksize;
12181       }
12182       else
12183         soap->dime.chunksize -= soap->buflen - soap->bufidx;
12184     }
12185     soap->count = soap->buflen - soap->bufidx;
12186   }
12187 #endif
12188   return SOAP_OK;
12189 }
12190 #endif
12191
12192 /******************************************************************************/
12193 #ifndef WITH_NOHTTP
12194 #ifndef PALM_1
12195 static int
12196 http_parse(struct soap *soap)
12197 { char header[SOAP_HDRLEN], *s;
12198   unsigned short get = 0, status = 0, k = 0;
12199   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
12200   *soap->endpoint = '\0';
12201   soap->length = 0;
12202   soap->userid = NULL;
12203   soap->passwd = NULL;
12204   soap->action = NULL;
12205   soap->authrealm = NULL;
12206   do
12207   { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
12208       return soap->error;
12209     DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
12210     for (;;)
12211     { if (soap_getline(soap, header, SOAP_HDRLEN))
12212       { if (soap->error == SOAP_EOF)
12213         { soap->error = SOAP_OK;
12214           DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
12215           break;
12216         }
12217         return soap->error;
12218       }
12219       if (!*header)
12220         break;
12221       DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
12222       s = strchr(header, ':');
12223       if (s)
12224       { *s = '\0';
12225         do s++;
12226         while (*s && *s <= 32);
12227         if ((soap->error = soap->fparsehdr(soap, header, s)))
12228         { if (soap->error < SOAP_STOP)
12229             return soap->error;
12230           status = soap->error;
12231           soap->error = SOAP_OK;
12232         }
12233       }
12234     }
12235     if ((s = strchr(soap->msgbuf, ' ')))
12236     { k = (unsigned short)soap_strtoul(s, &s, 10);
12237       if (!soap_blank(*s))
12238         k = 0;
12239     }
12240     else
12241       k = 0;
12242   } while (k == 100);
12243   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n"));
12244   s = strstr(soap->msgbuf, "HTTP/");
12245   if (s && s[7] != '1')
12246   { if (soap->keep_alive == 1)
12247       soap->keep_alive = 0;
12248     if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */
12249     { soap->imode |= SOAP_IO_CHUNK;
12250       soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
12251     }
12252   }
12253   if (soap->keep_alive < 0)
12254     soap->keep_alive = 1;
12255   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
12256   if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5)))
12257   { size_t m = strlen(soap->endpoint);
12258     size_t n = m + (s - soap->msgbuf) - 5 - (!get);
12259     if (n >= sizeof(soap->endpoint))
12260       n = sizeof(soap->endpoint) - 1;
12261     strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m);
12262     soap->path[n - m] = '\0';
12263     strcat(soap->endpoint, soap->path);
12264     DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
12265     if (get)
12266     { soap->error = soap->fget(soap);
12267       if (soap->error == SOAP_OK)
12268         soap->error = SOAP_STOP; /* prevents further processing */
12269       return soap->error;
12270     }
12271     if (status)
12272       return soap->error = status;
12273     return SOAP_OK;
12274   }
12275   if (k == 0 || k == 200 || k == 400 || k == 500 || (k >= 201 && k <= 299 && ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || soap->length)))
12276     return SOAP_OK;
12277   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k));
12278   return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k);
12279 }
12280 #endif
12281 #endif
12282
12283 /******************************************************************************/
12284 #ifndef WITH_NOHTTP
12285 #ifndef PALM_1
12286 static int
12287 http_parse_header(struct soap *soap, const char *key, const char *val)
12288 { if (!soap_tag_cmp(key, "Host"))
12289   { 
12290 #ifdef WITH_OPENSSL
12291     if (soap->imode & SOAP_ENC_SSL)
12292       strcpy(soap->endpoint, "https://");
12293     else
12294 #endif
12295       strcpy(soap->endpoint, "http://");
12296     strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
12297     soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
12298   }
12299 #ifndef WITH_LEANER
12300   else if (!soap_tag_cmp(key, "Content-Type"))
12301   { soap->http_content = soap_strdup(soap, val);
12302     if (soap_get_header_attribute(soap, val, "application/dime"))
12303       soap->mode |= SOAP_ENC_DIME;
12304     else if (soap_get_header_attribute(soap, val, "multipart/related")
12305           || soap_get_header_attribute(soap, val, "multipart/form-data"))
12306     { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
12307       soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
12308       soap->mode |= SOAP_ENC_MIME;
12309     }
12310   }
12311 #endif
12312   else if (!soap_tag_cmp(key, "Content-Length"))
12313     soap->length = soap_strtoul(val, NULL, 10);
12314   else if (!soap_tag_cmp(key, "Content-Encoding"))
12315   { if (!soap_tag_cmp(val, "deflate"))
12316 #ifdef WITH_ZLIB
12317       soap->zlib_in = SOAP_ZLIB_DEFLATE;
12318 #else
12319       return SOAP_ZLIB_ERROR;
12320 #endif
12321     else if (!soap_tag_cmp(val, "gzip"))
12322 #ifdef WITH_GZIP
12323       soap->zlib_in = SOAP_ZLIB_GZIP;
12324 #else
12325       return SOAP_ZLIB_ERROR;
12326 #endif
12327   }
12328 #ifdef WITH_ZLIB
12329   else if (!soap_tag_cmp(key, "Accept-Encoding"))
12330   {
12331 #ifdef WITH_GZIP
12332     if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
12333       soap->zlib_out = SOAP_ZLIB_GZIP;
12334     else
12335 #endif
12336     if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
12337       soap->zlib_out = SOAP_ZLIB_DEFLATE;
12338     else
12339       soap->zlib_out = SOAP_ZLIB_NONE;
12340   }
12341 #endif
12342   else if (!soap_tag_cmp(key, "Transfer-Encoding"))
12343   { soap->mode &= ~SOAP_IO;
12344     if (!soap_tag_cmp(val, "chunked"))
12345       soap->mode |= SOAP_IO_CHUNK;
12346   }
12347   else if (!soap_tag_cmp(key, "Connection"))
12348   { if (!soap_tag_cmp(val, "keep-alive"))
12349       soap->keep_alive = -soap->keep_alive;
12350     else if (!soap_tag_cmp(val, "close"))
12351       soap->keep_alive = 0;
12352   }
12353 #ifndef WITH_LEAN
12354   else if (!soap_tag_cmp(key, "Authorization"))
12355   { if (!soap_tag_cmp(val, "Basic *"))
12356     { int n;
12357       char *s;
12358       soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
12359       soap->tmpbuf[n] = '\0';
12360       if ((s = strchr(soap->tmpbuf, ':')))
12361       { *s = '\0';
12362         soap->userid = soap_strdup(soap, soap->tmpbuf);
12363         soap->passwd = soap_strdup(soap, s + 1);
12364       }
12365     }
12366   }
12367   else if (!soap_tag_cmp(key, "WWW-Authenticate"))
12368     soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
12369   else if (!soap_tag_cmp(key, "Expect"))
12370   { if (!soap_tag_cmp(val, "100-continue"))
12371     { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
12372        || (soap->error = soap->fposthdr(soap, NULL, NULL)))
12373         return soap->error;
12374     }
12375   }
12376 #endif
12377   else if (!soap_tag_cmp(key, "SOAPAction"))
12378   { if (*val == '"')
12379     { soap->action = soap_strdup(soap, val + 1);
12380       soap->action[strlen(soap->action) - 1] = '\0';
12381     }
12382   }
12383   else if (!soap_tag_cmp(key, "Location"))
12384   { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
12385     soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
12386   }
12387 #ifdef WITH_COOKIES
12388   else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie"))
12389     soap_getcookies(soap, val);
12390 #endif
12391   return SOAP_OK;
12392 }
12393 #endif
12394 #endif
12395
12396 /******************************************************************************/
12397 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12398 #ifndef PALM_1
12399 SOAP_FMAC1
12400 const char*
12401 SOAP_FMAC2
12402 soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
12403 { register const char *s = line;
12404   if (s)
12405   { while (*s)
12406     { register short flag;
12407       s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
12408       flag = soap_tag_cmp(soap->tmpbuf, key);
12409       s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
12410       if (!flag)
12411         return soap->tmpbuf;
12412     }
12413   }
12414   return NULL;
12415 }
12416 #endif
12417 #endif
12418
12419 /******************************************************************************/
12420 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12421 #ifndef PALM_1
12422 SOAP_FMAC1
12423 const char*
12424 SOAP_FMAC2
12425 soap_decode_key(char *buf, size_t len, const char *val)
12426 { return soap_decode(buf, len, val, "=,;");
12427 }
12428 #endif
12429 #endif
12430
12431 /******************************************************************************/
12432 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12433 #ifndef PALM_1
12434 SOAP_FMAC1
12435 const char*
12436 SOAP_FMAC2
12437 soap_decode_val(char *buf, size_t len, const char *val)
12438 { if (*val != '=')
12439   { *buf = '\0';
12440     return val;
12441   }
12442   return soap_decode(buf, len, val + 1, ",;");
12443 }
12444 #endif
12445 #endif
12446
12447 /******************************************************************************/
12448 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12449 #ifndef PALM_1
12450 static const char*
12451 soap_decode(char *buf, size_t len, const char *val, const char *sep)
12452 { const char *s;
12453   char *t = buf;
12454   for (s = val; *s; s++)
12455     if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
12456       break;
12457   if (*s == '"')
12458   { s++;
12459     while (*s && *s != '"' && --len)
12460       *t++ = *s++;
12461   }
12462   else
12463   { while (soap_notblank(*s) && !strchr(sep, *s) && --len)
12464     { if (*s == '%')
12465       { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
12466               + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
12467         s += 3;
12468       }
12469       else
12470         *t++ = *s++;
12471     }
12472   }
12473   *t = '\0';
12474   while (*s && !strchr(sep, *s))
12475     s++;
12476   return s;
12477 }
12478 #endif
12479 #endif
12480
12481 /******************************************************************************/
12482 #ifndef PALM_2
12483 SOAP_FMAC1
12484 int
12485 SOAP_FMAC2
12486 soap_envelope_begin_out(struct soap *soap)
12487 {
12488 #ifndef WITH_LEANER
12489   size_t n = 0;
12490   if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start)
12491   { const char *s;
12492     if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
12493       s = "application/dime";
12494     else if (soap->version == 2)
12495     { if (soap->mode & SOAP_ENC_MTOM)
12496         s = "application/xop+xml; charset=utf-8; type=application/soap+xml";
12497       else
12498         s = "application/soap+xml; charset=utf-8";
12499     }
12500     else
12501       s = "text/xml; charset=utf-8";
12502     sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
12503     n = strlen(soap->tmpbuf);
12504     if (soap_send_raw(soap, soap->tmpbuf, n))
12505       return soap->error;
12506   }
12507   if (soap->mode & SOAP_IO_LENGTH)
12508     soap->dime.size = soap->count;      /* DIME in MIME correction */
12509   if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
12510   { if (soap_putdimehdr(soap))
12511       return soap->error;
12512   }
12513 #endif
12514   soap->part = SOAP_IN_ENVELOPE;
12515   return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
12516 }
12517 #endif
12518
12519 /******************************************************************************/
12520 #ifndef PALM_2
12521 SOAP_FMAC1
12522 int
12523 SOAP_FMAC2
12524 soap_envelope_end_out(struct soap *soap)
12525 { if (soap_element_end_out(soap, "SOAP-ENV:Envelope"))
12526     return soap->error;
12527 #ifndef WITH_LEANER
12528   if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
12529   { soap->dime.size = soap->count - soap->dime.size;    /* DIME in MIME correction */
12530     sprintf(soap->id, soap->dime_id_format, 0);
12531     soap->dime.id = soap->id;
12532     if (soap->local_namespaces)
12533     { if (soap->local_namespaces[0].out)
12534         soap->dime.type = (char*)soap->local_namespaces[0].out;
12535       else
12536         soap->dime.type = (char*)soap->local_namespaces[0].ns;
12537     }
12538     soap->dime.options = NULL;
12539     soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
12540     if (!soap->dime.first)
12541       soap->dime.flags |= SOAP_DIME_ME;
12542     soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
12543   }
12544   if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
12545     return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
12546 #endif
12547   soap->part = SOAP_END_ENVELOPE;
12548   return SOAP_OK;
12549
12550 #endif
12551
12552 /******************************************************************************/
12553 #ifndef PALM_1
12554 SOAP_FMAC1
12555 int
12556 SOAP_FMAC2
12557 soap_envelope_begin_in(struct soap *soap)
12558 { register struct Namespace *p;
12559   soap->part = SOAP_IN_ENVELOPE;
12560   if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
12561     return soap->error = SOAP_VERSIONMISMATCH;
12562   p = soap->local_namespaces;
12563   if (p)
12564   { const char *ns = p[0].out;
12565     if (!ns)
12566       ns = p[0].ns;
12567     if (!strcmp(ns, soap_env1))
12568     { soap->version = 1; /* make sure we use SOAP 1.1 */
12569       if (p[1].out)
12570         SOAP_FREE(soap, p[1].out);
12571       if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
12572         strcpy(p[1].out, soap_enc1);
12573     }
12574     else if (!strcmp(ns, soap_env2))
12575     { soap->version = 2; /* make sure we use SOAP 1.2 */
12576       if (p[1].out)
12577         SOAP_FREE(soap, p[1].out);
12578       if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
12579         strcpy(p[1].out, soap_enc2);
12580     }
12581   }
12582   return SOAP_OK;
12583 }
12584 #endif
12585
12586 /******************************************************************************/
12587 #ifndef PALM_1
12588 SOAP_FMAC1
12589 int
12590 SOAP_FMAC2
12591 soap_envelope_end_in(struct soap *soap)
12592 { soap->part = SOAP_END_ENVELOPE;
12593   return soap_element_end_in(soap, "SOAP-ENV:Envelope");
12594 }
12595 #endif
12596
12597 /******************************************************************************/
12598 #ifndef PALM_2
12599 SOAP_FMAC1
12600 int
12601 SOAP_FMAC2
12602 soap_body_begin_out(struct soap *soap)
12603 { soap->part = SOAP_IN_BODY;
12604   if (soap->version == 1)
12605     soap->encoding = 1;
12606 #ifndef WITH_LEAN
12607   if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body"))
12608     return soap->error;
12609 #endif
12610   if (soap_element(soap, "SOAP-ENV:Body", 0, NULL))
12611     return soap->error;
12612   return soap_element_start_end_out(soap, NULL);
12613 }
12614 #endif
12615
12616 /******************************************************************************/
12617 #ifndef PALM_2
12618 SOAP_FMAC1
12619 int
12620 SOAP_FMAC2
12621 soap_body_end_out(struct soap *soap)
12622 { if (soap_element_end_out(soap, "SOAP-ENV:Body"))
12623     return soap->error;
12624   soap->part = SOAP_END_BODY;
12625   return SOAP_OK;
12626 }
12627 #endif
12628
12629 /******************************************************************************/
12630 #ifndef PALM_2
12631 SOAP_FMAC1
12632 int
12633 SOAP_FMAC2
12634 soap_body_begin_in(struct soap *soap)
12635 { soap->part = SOAP_IN_BODY;
12636   if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
12637     return soap->error;
12638   if (!soap->body)
12639     soap->part = SOAP_NO_BODY;
12640   return SOAP_OK;
12641 }
12642 #endif
12643
12644 /******************************************************************************/
12645 #ifndef PALM_2
12646 SOAP_FMAC1
12647 int
12648 SOAP_FMAC2
12649 soap_body_end_in(struct soap *soap)
12650 { if (soap->part == SOAP_NO_BODY)
12651     return SOAP_OK;
12652   soap->part = SOAP_END_BODY;
12653   return soap_element_end_in(soap, "SOAP-ENV:Body");
12654 }
12655 #endif
12656
12657 /******************************************************************************/
12658 #ifndef PALM_2
12659 SOAP_FMAC1
12660 int
12661 SOAP_FMAC2
12662 soap_recv_header(struct soap *soap)
12663 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
12664     soap->error = SOAP_OK;
12665   else if (soap->error == SOAP_OK && soap->fheader)
12666     soap->error = soap->fheader(soap);
12667   return soap->error;
12668 }
12669 #endif
12670
12671 /******************************************************************************/
12672 #ifndef PALM_1
12673 SOAP_FMAC1
12674 void
12675 SOAP_FMAC2
12676 soap_set_endpoint(struct soap *soap, const char *endpoint)
12677 { register const char *s;
12678   register size_t i, n;
12679   soap->endpoint[0] = '\0';
12680   soap->host[0] = '\0';
12681   soap->path[0] = '/';
12682   soap->path[1] = '\0';
12683   soap->port = 80;
12684   if (!endpoint || !*endpoint)
12685     return;
12686 #ifdef WITH_OPENSSL
12687   if (!soap_tag_cmp(endpoint, "https:*"))
12688     soap->port = 443;
12689 #endif
12690   strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
12691   s = strchr(endpoint, ':');
12692   if (s && s[1] == '/' && s[2] == '/')
12693     s += 3;
12694   else
12695     s = endpoint;
12696   n = strlen(s);
12697   if (n >= sizeof(soap->host))
12698     n = sizeof(soap->host) - 1;
12699 #ifdef WITH_IPV6
12700   if (s[0] == '[')
12701   { s++;
12702     for (i = 0; i < n; i++)
12703     { soap->host[i] = s[i];
12704       if (s[i] == ']')
12705       { s++;
12706         break; 
12707       }
12708     }
12709   }
12710   else
12711   { for (i = 0; i < n; i++)
12712     { soap->host[i] = s[i];
12713       if (s[i] == '/' || s[i] == ':')
12714         break; 
12715     }
12716   }
12717 #else
12718   for (i = 0; i < n; i++)
12719   { soap->host[i] = s[i];
12720     if (s[i] == '/' || s[i] == ':')
12721       break; 
12722   }
12723 #endif
12724   soap->host[i] = '\0';
12725   if (s[i] == ':')
12726   { soap->port = (int)atol(s + i + 1);
12727     for (i++; i < n; i++)
12728       if (s[i] == '/')
12729         break;
12730   }
12731   if (s[i])
12732   { strncpy(soap->path, s + i, sizeof(soap->path));
12733     soap->path[sizeof(soap->path) - 1] = '\0';
12734   }
12735 }
12736 #endif
12737
12738 /******************************************************************************/
12739 #ifndef PALM_1
12740 SOAP_FMAC1
12741 int
12742 SOAP_FMAC2
12743 soap_connect(struct soap *soap, const char *endpoint, const char *action)
12744 { return soap_connect_command(soap, SOAP_POST, endpoint, action);
12745 }
12746 #endif
12747
12748 /******************************************************************************/
12749 #ifndef PALM_1
12750 SOAP_FMAC1
12751 int
12752 SOAP_FMAC2
12753 soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
12754 { char host[sizeof(soap->host)];
12755   int port;
12756   size_t count;
12757   soap->error = SOAP_OK;
12758   strcpy(host, soap->host); /* save to compare */
12759   port = soap->port; /* save to compare */
12760   soap_set_endpoint(soap, endpoint);
12761 #ifndef WITH_LEANER
12762   if (soap->fconnect)
12763   { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
12764       return soap->error;
12765   }
12766   else
12767 #endif
12768   if (soap->fopen && *soap->host)
12769   { soap->status = http_command;
12770     if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
12771     { soap->keep_alive = 0; /* to force close */
12772       soap->omode &= ~SOAP_IO_UDP; /* to force close */
12773       soap_closesock(soap);
12774       DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
12775 #ifdef WITH_UDP
12776       if (!strncmp(endpoint, "soap.udp:", 9))
12777         soap->omode |= SOAP_IO_UDP;
12778 #endif
12779       soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
12780       if (soap->error)
12781         return soap->error;
12782       soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
12783     }
12784   }
12785   count = soap_count_attachments(soap);
12786   if (soap_begin_send(soap))
12787     return soap->error;
12788 #ifndef WITH_NOHTTP
12789   soap->action = soap_strdup(soap, action);
12790   if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
12791   { unsigned int k = soap->mode;
12792     soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
12793     if ((k & SOAP_IO) != SOAP_IO_FLUSH)
12794       soap->mode |= SOAP_IO_BUFFER;
12795     if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
12796       return soap->error;
12797 #ifndef WITH_LEANER
12798     if ((k & SOAP_IO) == SOAP_IO_CHUNK)
12799     { if (soap_flush(soap))
12800         return soap->error;
12801     }
12802 #endif
12803     soap->mode = k;
12804   }
12805   if (http_command != SOAP_POST)
12806     return soap_end_send(soap);
12807 #endif
12808   return SOAP_OK;
12809 }
12810 #endif
12811
12812 /******************************************************************************/
12813 #ifndef WITH_LEAN
12814 SOAP_FMAC1
12815 char*
12816 SOAP_FMAC2
12817 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
12818 { register int i;
12819   register unsigned long m;
12820   register char *p;
12821   if (!t)
12822     t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
12823   if (!t)
12824   { soap->error = SOAP_EOM;
12825     return NULL;
12826   }
12827   p = t;
12828   t[0] = '\0';
12829   if (!s)
12830     return p;
12831   for (; n > 2; n -= 3, s += 3)
12832   { m = s[0];
12833     m = (m << 8) | s[1];
12834     m = (m << 8) | s[2];
12835     for (i = 4; i > 0; m >>= 6)
12836       t[--i] = soap_base64o[m & 0x3F];
12837     t += 4;
12838   }
12839   t[0] = '\0';
12840   if (n > 0)
12841   { m = 0;
12842     for (i = 0; i < n; i++)
12843       m = (m << 8) | *s++;
12844     for (; i < 3; i++)
12845       m <<= 8;
12846     for (i++; i > 0; m >>= 6)
12847       t[--i] = soap_base64o[m & 0x3F];
12848     for (i = 3; i > n; i--)
12849       t[i] = '=';
12850     t[4] = '\0';
12851   }
12852   return p;
12853 }
12854 #endif
12855
12856 /******************************************************************************/
12857 #ifndef WITH_LEAN
12858 SOAP_FMAC1
12859 const char*
12860 SOAP_FMAC2
12861 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
12862 { register int i, j, c;
12863   register unsigned long m;
12864   register const char *p;
12865   if (!s || !*s)
12866   { if (n)
12867       *n = 0;
12868     if (soap->error)
12869       return NULL;
12870     return SOAP_NON_NULL;
12871   }
12872   if (!t)
12873   { l = (strlen(s) + 3) / 4 * 3;
12874     t = (char*)soap_malloc(soap, l);
12875   }
12876   if (!t)
12877   { soap->error = SOAP_EOM;
12878     return NULL;
12879   }
12880   p = t;
12881   if (n)
12882     *n = 0;
12883   for (;;)
12884   { for (i = 0; i < SOAP_BLKLEN; i++)
12885     { m = 0;
12886       j = 0;
12887       while (j < 4)
12888       { c = *s++;
12889         if (c == '=' || !c)
12890         { i *= 3;
12891           switch (j)
12892           { case 2:
12893               *t++ = (char)((m >> 4) & 0xFF);
12894               i++;
12895               break;
12896             case 3:
12897               *t++ = (char)((m >> 10) & 0xFF);
12898               *t++ = (char)((m >> 2) & 0xFF);
12899               i += 2;
12900           }
12901           if (n)
12902             *n += i;
12903           return p;
12904         }
12905         c -= '+';
12906         if (c >= 0 && c <= 79)
12907         { m = (m << 6) + soap_base64i[c];
12908           j++;
12909         }
12910       }
12911       *t++ = (char)((m >> 16) & 0xFF);
12912       *t++ = (char)((m >> 8) & 0xFF);
12913       *t++ = (char)(m & 0xFF);
12914       if (l < 3)
12915       { if (n)
12916           *n += i;
12917         return p;
12918       }
12919       l -= 3;
12920     }
12921     if (n)
12922       *n += 3 * SOAP_BLKLEN;
12923   }
12924 }
12925 #endif
12926
12927 /******************************************************************************/
12928 #ifndef WITH_LEAN
12929 SOAP_FMAC1
12930 char*
12931 SOAP_FMAC2
12932 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
12933 { register char *p;
12934   if (!t)
12935     t = (char*)soap_malloc(soap, 2 * n + 1);
12936   if (!t)
12937   { soap->error = SOAP_EOM;
12938     return NULL;
12939   }
12940   p = t;
12941   t[0] = '\0';
12942   if (s)
12943   { for (; n > 0; n--)
12944     { register int m = *s++;
12945       *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
12946       m &= 0x0F;
12947       *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
12948     }
12949   }
12950   *t++ = '\0';
12951   return p;
12952 }
12953 #endif
12954
12955 /******************************************************************************/
12956 #ifndef WITH_LEAN
12957 SOAP_FMAC1
12958 const char*
12959 SOAP_FMAC2
12960 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
12961 { register const char *p;
12962   if (!s || !*s)
12963   { if (n)
12964       *n = 0;
12965     if (soap->error)
12966       return NULL;
12967     return SOAP_NON_NULL;
12968   }
12969   if (!t)
12970   { l = strlen(s) / 2;
12971     t = (char*)soap_malloc(soap, l);
12972   }
12973   if (!t)
12974   { soap->error = SOAP_EOM;
12975     return NULL;
12976   }
12977   p = t;
12978   while (l)
12979   { register int d1, d2;
12980     d1 = *s++;
12981     if (!d1)
12982       break;
12983     d2 = *s++;
12984     if (!d2)
12985       break;
12986     *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
12987     l--;
12988   }
12989   if (n)
12990     *n = t - p;
12991   return p;
12992 }
12993 #endif
12994
12995 /******************************************************************************/
12996 #ifndef WITH_NOHTTP
12997 #ifndef PALM_1
12998 SOAP_FMAC1
12999 int
13000 SOAP_FMAC2
13001 soap_puthttphdr(struct soap *soap, int status, size_t count)
13002 { register const char *s = NULL;
13003   register int err = SOAP_OK;
13004 #ifndef WITH_LEANER
13005   register const char *r = NULL;
13006 #endif
13007   if (status == SOAP_FILE && soap->http_content)
13008     s = soap->http_content;
13009   else if (status == SOAP_HTML)
13010     s = "text/html; charset=utf-8";
13011   else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
13012   { if (soap->version == 2)
13013       s = "application/soap+xml; charset=utf-8";
13014     else
13015       s = "text/xml; charset=utf-8";
13016   }
13017 #ifndef WITH_LEANER
13018   if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
13019   { if (soap->mode & SOAP_ENC_MTOM)
13020     { r = s;
13021       s = "application/xop+xml; charset=utf-8";
13022     }
13023     else
13024       s = "application/dime";
13025   }
13026   if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->status != SOAP_GET)
13027   { register const char *t = strchr(s, ';');
13028     sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary);
13029     if (t)
13030       strncat(soap->tmpbuf, s, t - s);
13031     else
13032       strcat(soap->tmpbuf, s);
13033     if (soap->mime.start)
13034     { strcat(soap->tmpbuf, "\"; start=\"");
13035       strcat(soap->tmpbuf, soap->mime.start);
13036     }
13037     strcat(soap->tmpbuf, "\"");
13038     if (r)
13039     { strcat(soap->tmpbuf, "; start-info=\"");
13040       strcat(soap->tmpbuf, r);
13041       strcat(soap->tmpbuf, "\"");
13042     }
13043     s = soap->tmpbuf;
13044   }
13045 #endif
13046   if (s && (err = soap->fposthdr(soap, "Content-Type", s)))
13047     return err;
13048 #ifdef WITH_ZLIB
13049   if (soap->omode & SOAP_ENC_ZLIB)
13050   {
13051 #ifdef WITH_GZIP
13052     err = soap->fposthdr(soap, "Content-Encoding", "gzip");
13053 #else
13054     err = soap->fposthdr(soap, "Content-Encoding", "deflate");
13055 #endif
13056     if (err)
13057       return err;
13058   }
13059 #endif
13060 #ifndef WITH_LEANER
13061   if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
13062     err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
13063   else
13064 #endif
13065   if (s && soap->status != SOAP_GET)
13066   { sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
13067     err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
13068   }
13069   if (err)
13070     return err;
13071   return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
13072 }
13073 #endif
13074 #endif
13075
13076 /******************************************************************************/
13077 #ifndef WITH_NOHTTP
13078 #ifndef PALM_1
13079 static int
13080 http_get(struct soap *soap)
13081 { return SOAP_GET_METHOD;
13082 }
13083 #endif
13084 #endif
13085
13086 /******************************************************************************/
13087 #ifndef WITH_NOHTTP
13088 #ifndef PALM_1
13089 static int
13090 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
13091 { register const char *s;
13092   register int err;
13093   if (soap->status == SOAP_GET)
13094     s = "GET";
13095   else
13096     s = "POST";
13097 #ifdef PALM
13098   if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8))
13099 #else
13100   if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
13101 #endif
13102     return SOAP_OK;
13103   if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*"))
13104     sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
13105   else
13106     sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
13107   if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13108     return err;
13109   if (port != 80)
13110     sprintf(soap->tmpbuf, "%s:%d", host, port);
13111   else
13112     strcpy(soap->tmpbuf, host); 
13113   if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))
13114    || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7"))
13115    || (err = soap_puthttphdr(soap, SOAP_OK, count)))
13116     return err;
13117 #ifdef WITH_ZLIB
13118 #ifdef WITH_GZIP
13119   if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
13120 #else
13121   if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
13122 #endif
13123     return err;
13124 #endif
13125 #ifndef WITH_LEAN
13126   if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
13127   { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
13128     strcpy(soap->tmpbuf, "Basic ");
13129     soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
13130     if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
13131       return err;
13132   }
13133   if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
13134   { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
13135     strcpy(soap->tmpbuf, "Basic ");
13136     soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
13137     if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
13138       return err;
13139   }
13140 #endif
13141 #ifdef WITH_COOKIES
13142 #ifdef WITH_OPENSSL
13143   if (soap_putcookies(soap, host, path, soap->ssl != NULL))
13144     return soap->error;
13145 #else
13146   if (soap_putcookies(soap, host, path, 0))
13147     return soap->error;
13148 #endif
13149 #endif
13150   if (soap->version == 1 || (action && *action))
13151   { sprintf(soap->tmpbuf, "\"%s\"", action?action:"");
13152     if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
13153       return err;
13154   }
13155   return soap->fposthdr(soap, NULL, NULL);
13156 }
13157 #endif
13158 #endif
13159
13160 /******************************************************************************/
13161 #ifndef WITH_NOHTTP
13162 #ifndef PALM_1
13163 static int
13164 http_send_header(struct soap *soap, const char *s)
13165 { register const char *t;
13166   do
13167   { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
13168     if (!t)
13169       t = s + strlen(s);
13170     if (soap_send_raw(soap, s, t - s))
13171       return soap->error;
13172     s = t + 1;
13173   } while (*t);
13174   return SOAP_OK;
13175 }
13176 #endif
13177 #endif
13178
13179 /******************************************************************************/
13180 #ifndef WITH_NOHTTP
13181 #ifndef PALM_1
13182 static int
13183 http_post_header(struct soap *soap, const char *key, const char *val)
13184 { if (key)
13185   { if (http_send_header(soap, key))
13186       return soap->error;
13187     if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
13188       return soap->error;
13189   }
13190   return soap_send_raw(soap, "\r\n", 2);
13191 }
13192 #endif
13193 #endif
13194
13195 /******************************************************************************/
13196 #ifndef WITH_NOHTTP
13197 #ifndef PALM_1
13198 static int
13199 http_response(struct soap *soap, int status, size_t count)
13200 { register int err;
13201 #ifdef WMW_RPM_IO
13202   if (soap->rpmreqid)
13203     httpOutputEnable(soap->rpmreqid);
13204 #endif
13205   if (!status || status == SOAP_HTML || status == SOAP_FILE)
13206   { const char *s;
13207     if (count || ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK))
13208       s = "200 OK";
13209     else
13210       s = "202 ACCEPTED";
13211     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s));
13212 #ifdef WMW_RPM_IO
13213     if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
13214 #else
13215     if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
13216 #endif
13217     { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
13218       if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13219         return err;
13220     }
13221     else if ((err = soap->fposthdr(soap, "Status", s)))
13222       return err;
13223   }
13224   else if (status >= 200 && status < 600)
13225   { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
13226     if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13227       return err;
13228 #ifndef WITH_LEAN 
13229     if (status == 401)
13230     { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service");
13231       if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
13232         return err;
13233     }
13234     else if ((status >= 301 && status <= 303) || status == 307)
13235     { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
13236         return err;
13237     }
13238 #endif
13239   }
13240   else
13241   { const char *s = *soap_faultcode(soap);
13242     if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender"))
13243       s = "400 Bad Request";
13244     else
13245       s = "500 Internal Server Error";
13246     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
13247 #ifdef WMW_RPM_IO
13248     if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
13249 #else
13250     if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
13251 #endif
13252     { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
13253       if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13254         return err;
13255     }
13256     else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */
13257       return err;
13258   }
13259   if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7"))
13260    || (err = soap_puthttphdr(soap, status, count)))
13261     return err;
13262 #ifdef WITH_COOKIES
13263   if (soap_putsetcookies(soap))
13264     return soap->error;
13265 #endif
13266   return soap->fposthdr(soap, NULL, NULL);
13267 }
13268 #endif
13269 #endif
13270
13271 /******************************************************************************/
13272 #ifndef PALM_1
13273 SOAP_FMAC1
13274 int
13275 SOAP_FMAC2
13276 soap_response(struct soap *soap, int status)
13277 { register size_t count;
13278   if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
13279    && (status == SOAP_HTML || status == SOAP_FILE))
13280   { soap->omode &= ~SOAP_IO;
13281     soap->omode |= SOAP_IO_STORE;
13282   }
13283   soap->status = status;
13284   count = soap_count_attachments(soap);
13285   if (soap_begin_send(soap))
13286     return soap->error;
13287 #ifndef WITH_NOHTTP
13288   if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
13289   { register int n = soap->mode;
13290     soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
13291     if ((n & SOAP_IO) != SOAP_IO_FLUSH)
13292       soap->mode |= SOAP_IO_BUFFER;
13293     if ((soap->error = soap->fresponse(soap, status, count)))
13294       return soap->error;
13295 #ifndef WITH_LEANER
13296     if ((n & SOAP_IO) == SOAP_IO_CHUNK)
13297     { if (soap_flush(soap))
13298         return soap->error;
13299     }
13300 #endif
13301     soap->mode = n;
13302   }
13303 #endif
13304   return SOAP_OK;
13305 }
13306 #endif
13307
13308 /******************************************************************************/
13309 #ifndef WITH_LEAN
13310 static const char*
13311 soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
13312 { if (*soap->tag)
13313     sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag);
13314   else
13315     sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS);
13316   return soap->msgbuf;
13317 }
13318 #endif
13319
13320 /******************************************************************************/
13321 #ifndef PALM_1
13322 SOAP_FMAC1
13323 void
13324 SOAP_FMAC2
13325 soap_set_fault(struct soap *soap)
13326 { const char **c = soap_faultcode(soap);
13327   const char **s = soap_faultstring(soap);
13328   if (soap->fseterror)
13329     soap->fseterror(soap, c, s);
13330   if (!*c)
13331   { if (soap->version == 2)
13332       *c = "SOAP-ENV:Sender";
13333     else
13334       *c = "SOAP-ENV:Client";
13335   }
13336   if (*s)
13337     return;
13338   switch (soap->error)
13339   {
13340 #ifndef WITH_LEAN
13341     case SOAP_CLI_FAULT:
13342       *s = "Client fault";
13343       break;
13344     case SOAP_SVR_FAULT:
13345       *s = "Server fault";
13346       break;
13347     case SOAP_TAG_MISMATCH:
13348       *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
13349       break;
13350     case SOAP_TYPE:
13351       *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
13352       break;
13353     case SOAP_SYNTAX_ERROR:
13354       *s = "Well-formedness violation";
13355       break;
13356     case SOAP_NO_TAG:
13357       *s = "No XML element tag";
13358       break;
13359     case SOAP_MUSTUNDERSTAND:
13360       *c = "SOAP-ENV:MustUnderstand";
13361       sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
13362       *s = soap->msgbuf;
13363       break;
13364     case SOAP_VERSIONMISMATCH:
13365       *c = "SOAP-ENV:VersionMismatch";
13366       *s = "SOAP version mismatch or invalid SOAP message";
13367       break;
13368     case SOAP_DATAENCODINGUNKNOWN:
13369       *c = "SOAP-ENV:DataEncodingUnknown";
13370       *s = "Unsupported SOAP data encoding";
13371       break;
13372     case SOAP_NAMESPACE:
13373       *s = soap_set_validation_fault(soap, "namespace mismatch", NULL);
13374       break;
13375     case SOAP_USER_ERROR:
13376       *s = "User error";
13377       break;
13378     case SOAP_FATAL_ERROR:
13379       *s = "Fatal error";
13380       break;
13381     case SOAP_NO_METHOD:
13382       sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
13383       *s = soap->msgbuf;
13384       break;
13385     case SOAP_GET_METHOD:
13386       *s = "HTTP GET method not implemented";
13387       break;
13388     case SOAP_EOM:
13389       *s = "Out of memory";
13390       break;
13391     case SOAP_IOB:
13392       *s = "Array index out of bounds";
13393       break;
13394     case SOAP_NULL:
13395       *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
13396       break;
13397     case SOAP_DUPLICATE_ID:
13398       *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id);
13399       if (soap->version == 2)
13400         *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
13401       break;
13402     case SOAP_MISSING_ID:
13403       *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
13404       if (soap->version == 2)
13405         *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
13406       break;
13407     case SOAP_HREF:
13408       *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id);
13409       break;
13410     case SOAP_FAULT:
13411       break;
13412 #ifndef WITH_NOIO
13413     case SOAP_UDP_ERROR:
13414       *s = "Message too large for UDP packet";
13415       break;
13416     case SOAP_TCP_ERROR:
13417       *s = tcp_error(soap);
13418       break;
13419 #endif
13420     case SOAP_HTTP_ERROR:
13421       *s = "HTTP error";
13422       break;
13423     case SOAP_SSL_ERROR:
13424 #ifdef WITH_OPENSSL
13425       *s = "SSL error";
13426 #else
13427       *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
13428 #endif
13429       break;
13430     case SOAP_PLUGIN_ERROR:
13431       *s = "Plugin registry error";
13432       break;
13433     case SOAP_DIME_ERROR:
13434       *s = "DIME format error";
13435       break;
13436     case SOAP_DIME_HREF:
13437       *s = "DIME href to missing attachment";
13438       break;
13439     case SOAP_DIME_MISMATCH:
13440       *s = "DIME version/transmission error";
13441       break;
13442     case SOAP_DIME_END:
13443       *s = "End of DIME error";
13444       break;
13445     case SOAP_MIME_ERROR:
13446       *s = "MIME format error";
13447       break;
13448     case SOAP_MIME_HREF:
13449       *s = "MIME href to missing attachment";
13450       break;
13451     case SOAP_MIME_END:
13452       *s = "End of MIME error";
13453       break;
13454     case SOAP_ZLIB_ERROR:
13455 #ifdef WITH_ZLIB
13456       sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:"");
13457       *s = soap->msgbuf;
13458 #else
13459       *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
13460 #endif
13461       break;
13462     case SOAP_REQUIRED:
13463       *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
13464       break;
13465     case SOAP_PROHIBITED:
13466       *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
13467       break;
13468     case SOAP_OCCURS:
13469       *s = soap_set_validation_fault(soap, "min/maxOccurs violation", NULL);
13470       break;
13471     case SOAP_LENGTH:
13472       *s = soap_set_validation_fault(soap, "content length violation", NULL);
13473       break;
13474     case SOAP_FD_EXCEEDED:
13475       *s = "Maximum number of open connections was reached";
13476       break;
13477     case SOAP_STOP:
13478       *s = "Stopped: no response sent";
13479       break;
13480 #endif
13481     case SOAP_EOF:
13482 #ifndef WITH_NOIO
13483       sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap));
13484       *s = soap->msgbuf;
13485       break;
13486 #else
13487       *s = "End of file or no input";
13488       break;
13489 #endif
13490     default:
13491 #ifndef WITH_NOHTTP
13492 #ifndef WITH_LEAN
13493       if (soap->error > 200 && soap->error < 600)
13494       { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
13495         *s = soap->msgbuf;
13496       }
13497       else
13498 #endif
13499 #endif
13500       { sprintf(soap->msgbuf, "Error %d", soap->error);
13501         *s = soap->msgbuf;
13502       }
13503     }
13504 }
13505 #endif
13506
13507 /******************************************************************************/
13508 #ifndef PALM_1
13509 SOAP_FMAC1
13510 int
13511 SOAP_FMAC2
13512 soap_send_fault(struct soap *soap)
13513 { register int status = soap->error;
13514   int r = 1;
13515   if (status == SOAP_STOP)
13516     return status;
13517   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
13518   soap->keep_alive = 0; /* to terminate connection */
13519   soap_set_fault(soap);
13520 #ifndef WITH_NOIO
13521 #ifndef WITH_LEAN
13522   if (soap_valid_socket(soap->socket))
13523   { struct timeval timeout;
13524     fd_set rfd, sfd;
13525     timeout.tv_sec = 0;
13526     timeout.tv_usec = 0;
13527     FD_ZERO(&rfd);
13528     FD_ZERO(&sfd);
13529     FD_SET((SOAP_SOCKET)soap->socket, &rfd);
13530     FD_SET((SOAP_SOCKET)soap->socket, &sfd);
13531     r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, NULL, &timeout);
13532     if (r > 0)
13533     { if (!FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
13534        || (FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
13535         && recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0))
13536         r = 0;
13537     }
13538   }
13539 #endif
13540 #endif
13541   if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0)
13542   { soap->error = SOAP_OK;
13543     soap_serializeheader(soap);
13544     soap_serializefault(soap);
13545     soap_begin_count(soap);
13546     if (soap->mode & SOAP_IO_LENGTH)
13547     { soap_envelope_begin_out(soap);
13548       soap_putheader(soap);
13549       soap_body_begin_out(soap);
13550       soap_putfault(soap);
13551       soap_body_end_out(soap);
13552       soap_envelope_end_out(soap);
13553     }
13554     soap_end_count(soap);
13555     if (soap_response(soap, status)
13556      || soap_envelope_begin_out(soap)
13557      || soap_putheader(soap)
13558      || soap_body_begin_out(soap)
13559      || soap_putfault(soap)
13560      || soap_body_end_out(soap)
13561      || soap_envelope_end_out(soap))
13562       return soap_closesock(soap);
13563     soap_end_send(soap);
13564   }
13565   soap->error = status;
13566   return soap_closesock(soap);
13567 }
13568 #endif
13569
13570 /******************************************************************************/
13571 #ifndef PALM_1
13572 SOAP_FMAC1
13573 int
13574 SOAP_FMAC2
13575 soap_recv_fault(struct soap *soap)
13576 { register int status = soap->error;
13577   DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n"));
13578   soap->error = SOAP_OK;
13579   if (soap_getfault(soap))
13580   { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
13581     *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
13582     soap->error = status;
13583     soap_set_fault(soap);
13584   }
13585   else
13586   { register const char *s = *soap_faultcode(soap);
13587     if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
13588       status = SOAP_SVR_FAULT; 
13589     else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
13590       status = SOAP_CLI_FAULT;
13591     else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
13592       status = SOAP_MUSTUNDERSTAND;
13593     else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
13594       status = SOAP_VERSIONMISMATCH;
13595     else
13596     { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s));
13597       status = SOAP_FAULT;
13598     }
13599     if (soap_body_end_in(soap)
13600      || soap_envelope_end_in(soap)
13601      || soap_end_recv(soap))
13602       return soap_closesock(soap);
13603     soap->error = status;
13604   }
13605   return soap_closesock(soap);
13606 }
13607 #endif
13608
13609 /******************************************************************************/
13610 #ifndef WITH_NOHTTP
13611 #ifndef PALM_1
13612 SOAP_FMAC1
13613 int
13614 SOAP_FMAC2
13615 soap_send_empty_response(struct soap *soap, int status)
13616 { register soap_mode m = soap->omode;
13617   soap->count = 0;
13618   if ((m & SOAP_IO) == SOAP_IO_CHUNK)
13619   { soap->omode &= ~SOAP_IO_CHUNK;
13620     soap->omode |= SOAP_IO_BUFFER;
13621   }
13622   if (soap_response(soap, status) || soap_end_send(soap))
13623   { soap->omode = m;
13624     return soap_closesock(soap);
13625   }
13626   soap->omode = m;
13627   return SOAP_OK;
13628 }
13629 #endif
13630 #endif
13631
13632 /******************************************************************************/
13633 #ifndef WITH_NOHTTP
13634 #ifndef PALM_1
13635 SOAP_FMAC1
13636 int
13637 SOAP_FMAC2
13638 soap_recv_empty_response(struct soap *soap)
13639 { if (soap_begin_recv(soap) || soap_end_recv(soap))
13640   { if (soap->error != 202)
13641       return soap_closesock(soap);
13642     soap->error = SOAP_OK;
13643   }
13644   return SOAP_OK;
13645 }
13646 #endif
13647 #endif
13648
13649 /******************************************************************************/
13650 #ifndef WITH_NOIO
13651 #ifndef PALM_1
13652 static const char*
13653 soap_strerror(struct soap *soap)
13654 { register int err = soap->errnum;
13655   if (err)
13656   {
13657 #ifndef WIN32
13658     return strerror(err);
13659 #else
13660     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->errorstr, sizeof(soap->errorstr)/sizeof(soap->errorstr[0]), NULL);
13661     return soap->errorstr;
13662 #endif
13663   }
13664   return "Operation interrupted or timed out";
13665 }
13666 #endif
13667 #endif 
13668
13669 /******************************************************************************/
13670 #ifndef PALM_2
13671 static int
13672 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror)
13673 { *soap_faultcode(soap) = faultcode;
13674   if (faultsubcode)
13675     *soap_faultsubcode(soap) = faultsubcode;
13676   *soap_faultstring(soap) = faultstring;
13677   if (faultdetail && *faultdetail)
13678   { register const char **s = soap_faultdetail(soap);
13679     if (s)
13680       *s = faultdetail;
13681   }
13682   return soap->error = soaperror;
13683 }
13684 #endif
13685
13686 /******************************************************************************/
13687 #ifndef PALM_2
13688 SOAP_FMAC1
13689 int
13690 SOAP_FMAC2
13691 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
13692 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror);
13693 }
13694 #endif
13695
13696 /******************************************************************************/
13697 #ifndef PALM_2
13698 SOAP_FMAC1
13699 int
13700 SOAP_FMAC2
13701 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
13702 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror);
13703 }
13704 #endif
13705
13706 /******************************************************************************/
13707 #ifndef PALM_2
13708 static int
13709 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail)
13710 { char *r = NULL, *s = NULL, *t = NULL;
13711   if (faultsubcode)
13712     r = soap_strdup(soap, faultsubcode);
13713   if (faultstring)
13714     s = soap_strdup(soap, faultstring);
13715   if (faultdetail)
13716     t = soap_strdup(soap, faultdetail);
13717   return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
13718 }
13719 #endif
13720
13721 /******************************************************************************/
13722 #ifndef PALM_2
13723 SOAP_FMAC1
13724 int
13725 SOAP_FMAC2
13726 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
13727 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail);
13728 }
13729 #endif
13730
13731 /******************************************************************************/
13732 #ifndef PALM_2
13733 SOAP_FMAC1
13734 int
13735 SOAP_FMAC2
13736 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
13737 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail);
13738 }
13739 #endif
13740
13741 /******************************************************************************/
13742 #ifndef PALM_2
13743 SOAP_FMAC1
13744 int
13745 SOAP_FMAC2
13746 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
13747 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail);
13748 }
13749 #endif
13750
13751 /******************************************************************************/
13752 #ifndef PALM_2
13753 SOAP_FMAC1
13754 int
13755 SOAP_FMAC2
13756 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
13757 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail);
13758 }
13759 #endif
13760
13761 /******************************************************************************/
13762 #ifndef PALM_2
13763 #ifndef WITH_NOSTDLIB
13764 SOAP_FMAC1
13765 void
13766 SOAP_FMAC2
13767 soap_print_fault(struct soap *soap, FILE *fd)
13768 { if (soap_check_state(soap))
13769     fprintf(fd, "Error: soap struct not initialized\n");
13770   else if (soap->error)
13771   { const char *c, *v = NULL, *s, **d;
13772     d = soap_faultcode(soap);
13773     if (!*d)
13774       soap_set_fault(soap);
13775     c = *d;
13776     if (soap->version == 2)
13777       v = *soap_faultsubcode(soap);
13778     s = *soap_faultstring(soap);
13779     d = soap_faultdetail(soap);
13780     fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
13781   }
13782 }
13783 #endif
13784 #endif
13785  
13786 /******************************************************************************/
13787 #ifndef PALM_1
13788 #ifndef WITH_NOSTDLIB
13789 SOAP_FMAC1
13790 void
13791 SOAP_FMAC2
13792 soap_print_fault_location(struct soap *soap, FILE *fd)
13793
13794 #ifndef WITH_LEAN
13795   int i, j, c1, c2;
13796   if (soap->error && soap->buflen > 0)
13797   { i = (int)soap->bufidx - 1;
13798     if (i <= 0)
13799       i = 0;
13800     c1 = soap->buf[i];
13801     soap->buf[i] = '\0';
13802     if ((int)soap->buflen >= i + 1024)
13803       j = i + 1023;
13804     else
13805       j = (int)soap->buflen - 1;
13806     c2 = soap->buf[j];
13807     soap->buf[j] = '\0';
13808     fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
13809     if (soap->bufidx < soap->buflen)
13810       fprintf(fd, "%s\n", soap->buf + soap->bufidx);
13811     soap->buf[i] = c1;
13812     soap->buf[j] = c2;
13813   }
13814 #endif
13815 }
13816 #endif
13817 #endif
13818  
13819 /******************************************************************************/
13820 #ifndef PALM_1
13821 SOAP_FMAC1
13822 int
13823 SOAP_FMAC2
13824 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
13825 { register struct soap_plugin *p;
13826   register int r;
13827   if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
13828     return soap->error = SOAP_EOM;
13829   p->id = NULL;
13830   p->data = NULL;
13831   p->fcopy = NULL;
13832   p->fdelete = NULL;
13833   r = fcreate(soap, p, arg);
13834   if (!r && p->fdelete)
13835   { p->next = soap->plugins;
13836     soap->plugins = p;
13837     DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
13838     return SOAP_OK;
13839   }
13840   DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r));
13841   SOAP_FREE(soap, p);
13842   return r;
13843 }
13844 #endif
13845
13846 /******************************************************************************/
13847 #ifndef PALM_1
13848 static void *
13849 fplugin(struct soap *soap, const char *id)
13850 { register struct soap_plugin *p;
13851   for (p = soap->plugins; p; p = p->next)
13852     if (p->id == id || !strcmp(p->id, id))
13853       return p->data;
13854   return NULL;
13855 }
13856 #endif
13857
13858 /******************************************************************************/
13859 #ifndef PALM_2
13860 SOAP_FMAC1
13861 void *
13862 SOAP_FMAC2
13863 soap_lookup_plugin(struct soap *soap, const char *id)
13864 { return soap->fplugin(soap, id);
13865 }
13866 #endif
13867
13868 /******************************************************************************/
13869 #ifdef __cplusplus
13870 }
13871 #endif
13872
13873 /******************************************************************************\
13874  *
13875  *      C++ soap struct methods
13876  *
13877 \******************************************************************************/
13878
13879 #ifdef __cplusplus
13880 #ifndef WITH_LEAN
13881 soap::soap()
13882 { soap_init(this);
13883 }
13884 #endif
13885 #endif
13886
13887 /******************************************************************************/
13888 #ifdef __cplusplus
13889 #ifndef WITH_LEAN
13890 soap::soap(soap_mode m)
13891 { soap_init1(this, m);
13892 }
13893 #endif
13894 #endif
13895
13896 /******************************************************************************/
13897 #ifdef __cplusplus
13898 #ifndef WITH_LEAN
13899 soap::soap(soap_mode im, soap_mode om)
13900 { soap_init2(this, im, om);
13901 }
13902 #endif
13903 #endif
13904
13905 /******************************************************************************/
13906 #ifdef __cplusplus
13907 #ifndef WITH_LEAN
13908 soap::soap(struct soap& soap)
13909 { soap_copy_context(this, &soap);
13910 }
13911 #endif
13912 #endif
13913
13914 /******************************************************************************/
13915 #ifdef __cplusplus
13916 #ifndef WITH_LEAN
13917 soap::~soap()
13918 { soap_destroy(this);
13919   soap_end(this);
13920   soap_done(this);
13921 }
13922 #endif
13923 #endif
13924
13925 /******************************************************************************/