Sync DrDump crash handler with TortoiseSVN codebase
[TortoiseGit.git] / ext / CrashServer / CrashHandler / DumpUploaderServiceLib / stdsoap2.cpp
blob6ac905b4aeb67d90bcfc69fc8fa65c752a25183d
1 /*
2 stdsoap2.c[pp] 2.8.17r
4 gSOAP runtime engine
6 gSOAP XML Web services tools
7 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
8 This part of the software is released under ONE of the following licenses:
9 GPL, or the gSOAP public license, or Genivia's license for commercial use.
10 --------------------------------------------------------------------------------
11 Contributors:
13 Wind River Systems Inc., for the following additions under gSOAP public license:
14 - vxWorks compatible options
15 --------------------------------------------------------------------------------
16 gSOAP public license.
18 The contents of this file are subject to the gSOAP Public License Version 1.3
19 (the "License"); you may not use this file except in compliance with the
20 License. You may obtain a copy of the License at
21 http://www.cs.fsu.edu/~engelen/soaplicense.html
22 Software distributed under the License is distributed on an "AS IS" basis,
23 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
24 for the specific language governing rights and limitations under the License.
26 The Initial Developer of the Original Code is Robert A. van Engelen.
27 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
28 --------------------------------------------------------------------------------
29 GPL license.
31 This program is free software; you can redistribute it and/or modify it under
32 the terms of the GNU General Public License as published by the Free Software
33 Foundation; either version 2 of the License, or (at your option) any later
34 version.
36 This program is distributed in the hope that it will be useful, but WITHOUT ANY
37 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
38 PARTICULAR PURPOSE. See the GNU General Public License for more details.
40 You should have received a copy of the GNU General Public License along with
41 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
42 Place, Suite 330, Boston, MA 02111-1307 USA
44 Author contact information:
45 engelen@genivia.com / engelen@acm.org
47 This program is released under the GPL with the additional exemption that
48 compiling, linking, and/or using OpenSSL is allowed.
49 --------------------------------------------------------------------------------
50 A commercial use license is available from Genivia, Inc., contact@genivia.com
51 --------------------------------------------------------------------------------
54 #define GSOAP_LIB_VERSION 20817
56 #ifdef AS400
57 # pragma convert(819) /* EBCDIC to ASCII */
58 #endif
60 #include "stdsoap2.h"
61 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
62 #include <ipcom_key_db.h>
63 #endif
64 #if GSOAP_VERSION != GSOAP_LIB_VERSION
65 # error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE"
66 #endif
68 #ifdef __BORLANDC__
69 # pragma warn -8060
70 #else
71 # ifdef WIN32
72 # ifdef UNDER_CE
73 # pragma comment(lib, "ws2.lib") /* WinCE */
74 # else
75 # pragma comment(lib, "ws2_32.lib")
76 # endif
77 # pragma warning(disable : 4996) /* disable deprecation warnings */
78 # endif
79 #endif
81 #ifdef __cplusplus
82 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.17r 2013-12-18 00:00:00 GMT")
83 extern "C" {
84 #else
85 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.17r 2013-12-18 00:00:00 GMT")
86 #endif
88 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
89 #ifndef SOAP_UNKNOWN_CHAR
90 #define SOAP_UNKNOWN_CHAR (127)
91 #endif
93 /* EOF=-1 */
94 #define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */
95 #define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */
96 #define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */
97 #define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */
98 #define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */
100 #define soap_blank(c) ((c)+1 > 0 && (c) <= 32)
101 #define soap_notblank(c) ((c) > 32)
103 #if defined(WIN32) && !defined(UNDER_CE)
104 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
105 #else
106 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
107 #endif
109 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
110 static void soap_init_logs(struct soap*);
111 #endif
112 #ifdef SOAP_DEBUG
113 static void soap_close_logfile(struct soap*, int);
114 static void soap_set_logfile(struct soap*, int, const char*);
115 #endif
117 #ifdef SOAP_MEM_DEBUG
118 static void soap_init_mht(struct soap*);
119 static void soap_free_mht(struct soap*);
120 static void soap_track_unlink(struct soap*, const void*);
121 #endif
123 #ifndef PALM_2
124 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
125 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
126 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
127 #endif
129 #ifndef PALM_1
130 static void soap_free_ns(struct soap *soap);
131 static soap_wchar soap_char(struct soap*);
132 static soap_wchar soap_get_pi(struct soap*);
133 static int soap_isxdigit(int);
134 static void *fplugin(struct soap*, const char*);
135 static size_t soap_count_attachments(struct soap *soap);
136 static int soap_try_connect_command(struct soap*, int http_command, const char *endpoint, const char *action);
137 #ifdef WITH_NTLM
138 static int soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port);
139 #endif
140 #ifndef WITH_NOIDREF
141 static int soap_has_copies(struct soap*, const char*, const char*);
142 static void soap_init_iht(struct soap*);
143 static void soap_free_iht(struct soap*);
144 static void soap_init_pht(struct soap*);
145 static void soap_free_pht(struct soap*);
146 #endif
147 #endif
149 #ifndef WITH_LEAN
150 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
151 static int soap_isnumeric(struct soap*, const char*);
152 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
153 static void soap_utilize_ns(struct soap *soap, const char *tag);
154 #endif
156 #ifndef WITH_LEANER
157 #ifndef PALM_1
158 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
159 static int soap_putdimefield(struct soap*, const char*, size_t);
160 static char *soap_getdimefield(struct soap*, size_t);
161 static void soap_select_mime_boundary(struct soap*);
162 static int soap_valid_mime_boundary(struct soap*);
163 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
164 #endif
165 #endif
167 #ifdef WITH_GZIP
168 static int soap_getgziphdr(struct soap*);
169 #endif
171 #ifdef WITH_OPENSSL
172 # ifndef SOAP_SSL_RSA_BITS
173 # define SOAP_SSL_RSA_BITS 2048
174 # endif
175 static int soap_ssl_init_done = 0;
176 static int ssl_auth_init(struct soap*);
177 static int ssl_verify_callback(int, X509_STORE_CTX*);
178 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX*);
179 static int ssl_password(char*, int, int, void *);
180 #endif
182 #ifdef WITH_GNUTLS
183 # ifndef SOAP_SSL_RSA_BITS
184 # define SOAP_SSL_RSA_BITS 2048
185 # endif
186 static int soap_ssl_init_done = 0;
187 static const char *ssl_verify(struct soap *soap, const char *host);
188 # if defined(HAVE_PTHREAD_H)
189 # include <pthread.h>
190 /* make GNUTLS thread safe with pthreads */
191 GCRY_THREAD_OPTION_PTHREAD_IMPL;
192 # elif defined(HAVE_PTH_H)
193 #include <pth.h>
194 /* make GNUTLS thread safe with PTH */
195 GCRY_THREAD_OPTION_PTH_IMPL;
196 # endif
197 #endif
199 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
200 #ifndef PALM_1
201 static const char *soap_decode(char*, size_t, const char*, const char*);
202 #endif
203 #endif
205 #ifndef WITH_NOHTTP
206 #ifndef PALM_1
207 static soap_wchar soap_getchunkchar(struct soap*);
208 static const char *http_error(struct soap*, int);
209 static int http_get(struct soap*);
210 static int http_405(struct soap*);
211 static int http_200(struct soap*);
212 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
213 static int http_send_header(struct soap*, const char*);
214 static int http_post_header(struct soap*, const char*, const char*);
215 static int http_response(struct soap*, int, size_t);
216 static int http_parse(struct soap*);
217 static int http_parse_header(struct soap*, const char*, const char*);
218 #endif
219 #endif
221 #ifndef WITH_NOIO
223 #ifndef PALM_1
224 static int fsend(struct soap*, const char*, size_t);
225 static size_t frecv(struct soap*, char*, size_t);
226 static int tcp_init(struct soap*);
227 static const char *tcp_error(struct soap*);
228 #ifndef WITH_IPV6
229 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
230 #endif
231 static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
232 static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
233 static int tcp_select(struct soap*, SOAP_SOCKET, int, int);
234 static int tcp_disconnect(struct soap*);
235 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
236 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
237 static const char *soap_strerror(struct soap*);
238 #endif
240 #define SOAP_TCP_SELECT_RCV 0x1
241 #define SOAP_TCP_SELECT_SND 0x2
242 #define SOAP_TCP_SELECT_ERR 0x4
243 #define SOAP_TCP_SELECT_ALL 0x7
245 #if defined(WIN32)
246 #define SOAP_SOCKBLOCK(fd) \
247 { u_long blocking = 0; \
248 ioctlsocket(fd, FIONBIO, &blocking); \
250 #define SOAP_SOCKNONBLOCK(fd) \
251 { u_long nonblocking = 1; \
252 ioctlsocket(fd, FIONBIO, &nonblocking); \
254 #elif defined(VXWORKS)
255 #define SOAP_SOCKBLOCK(fd) \
256 { u_long blocking = 0; \
257 ioctl(fd, FIONBIO, (int)(&blocking)); \
259 #define SOAP_SOCKNONBLOCK(fd) \
260 { u_long nonblocking = 1; \
261 ioctl(fd, FIONBIO, (int)(&nonblocking)); \
263 #elif defined(__VMS)
264 #define SOAP_SOCKBLOCK(fd) \
265 { int blocking = 0; \
266 ioctl(fd, FIONBIO, &blocking); \
268 #define SOAP_SOCKNONBLOCK(fd) \
269 { int nonblocking = 1; \
270 ioctl(fd, FIONBIO, &nonblocking); \
272 #elif defined(PALM)
273 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
274 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
275 #elif defined(SYMBIAN)
276 #define SOAP_SOCKBLOCK(fd) \
277 { long blocking = 0; \
278 ioctl(fd, 0/*FIONBIO*/, &blocking); \
280 #define SOAP_SOCKNONBLOCK(fd) \
281 { long nonblocking = 1; \
282 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
284 #else
285 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
286 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
287 #endif
289 #endif
291 #if defined(PALM) && !defined(PALM_2)
292 unsigned short errno;
293 #endif
295 #ifndef PALM_1
296 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
297 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
298 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
299 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
300 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
301 #endif
303 #ifndef PALM_1
304 const union soap_double_nan soap_double_nan = {{0xFFFFFFFF, 0xFFFFFFFF}};
305 const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
306 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";
307 #endif
309 #ifndef WITH_LEAN
310 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
311 /* Alternative indentation form for SOAP_XML_INDENT:
312 static const char soap_indent[21] = "\n ";
314 #endif
316 #ifndef SOAP_CANARY
317 # define SOAP_CANARY (0xC0DE)
318 #endif
320 static const char soap_padding[4] = "\0\0\0";
321 #define SOAP_STR_PADDING (soap_padding)
322 #define SOAP_STR_EOS (soap_padding)
323 #define SOAP_NON_NULL (soap_padding)
325 #ifndef WITH_LEAN
326 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
327 { { 160, "nbsp" },
328 { 161, "iexcl" },
329 { 162, "cent" },
330 { 163, "pound" },
331 { 164, "curren" },
332 { 165, "yen" },
333 { 166, "brvbar" },
334 { 167, "sect" },
335 { 168, "uml" },
336 { 169, "copy" },
337 { 170, "ordf" },
338 { 171, "laquo" },
339 { 172, "not" },
340 { 173, "shy" },
341 { 174, "reg" },
342 { 175, "macr" },
343 { 176, "deg" },
344 { 177, "plusmn" },
345 { 178, "sup2" },
346 { 179, "sup3" },
347 { 180, "acute" },
348 { 181, "micro" },
349 { 182, "para" },
350 { 183, "middot" },
351 { 184, "cedil" },
352 { 185, "sup1" },
353 { 186, "ordm" },
354 { 187, "raquo" },
355 { 188, "frac14" },
356 { 189, "frac12" },
357 { 190, "frac34" },
358 { 191, "iquest" },
359 { 192, "Agrave" },
360 { 193, "Aacute" },
361 { 194, "Acirc" },
362 { 195, "Atilde" },
363 { 196, "Auml" },
364 { 197, "Aring" },
365 { 198, "AElig" },
366 { 199, "Ccedil" },
367 { 200, "Egrave" },
368 { 201, "Eacute" },
369 { 202, "Ecirc" },
370 { 203, "Euml" },
371 { 204, "Igrave" },
372 { 205, "Iacute" },
373 { 206, "Icirc" },
374 { 207, "Iuml" },
375 { 208, "ETH" },
376 { 209, "Ntilde" },
377 { 210, "Ograve" },
378 { 211, "Oacute" },
379 { 212, "Ocirc" },
380 { 213, "Otilde" },
381 { 214, "Ouml" },
382 { 215, "times" },
383 { 216, "Oslash" },
384 { 217, "Ugrave" },
385 { 218, "Uacute" },
386 { 219, "Ucirc" },
387 { 220, "Uuml" },
388 { 221, "Yacute" },
389 { 222, "THORN" },
390 { 223, "szlig" },
391 { 224, "agrave" },
392 { 225, "aacute" },
393 { 226, "acirc" },
394 { 227, "atilde" },
395 { 228, "auml" },
396 { 229, "aring" },
397 { 230, "aelig" },
398 { 231, "ccedil" },
399 { 232, "egrave" },
400 { 233, "eacute" },
401 { 234, "ecirc" },
402 { 235, "euml" },
403 { 236, "igrave" },
404 { 237, "iacute" },
405 { 238, "icirc" },
406 { 239, "iuml" },
407 { 240, "eth" },
408 { 241, "ntilde" },
409 { 242, "ograve" },
410 { 243, "oacute" },
411 { 244, "ocirc" },
412 { 245, "otilde" },
413 { 246, "ouml" },
414 { 247, "divide" },
415 { 248, "oslash" },
416 { 249, "ugrave" },
417 { 250, "uacute" },
418 { 251, "ucirc" },
419 { 252, "uuml" },
420 { 253, "yacute" },
421 { 254, "thorn" },
422 { 255, "yuml" },
423 { 0, NULL }
425 #endif
427 #ifndef WITH_NOIO
428 #ifndef WITH_LEAN
429 static const struct soap_code_map h_error_codes[] =
431 #ifdef HOST_NOT_FOUND
432 { HOST_NOT_FOUND, "Host not found" },
433 #endif
434 #ifdef TRY_AGAIN
435 { TRY_AGAIN, "Try Again" },
436 #endif
437 #ifdef NO_RECOVERY
438 { NO_RECOVERY, "No Recovery" },
439 #endif
440 #ifdef NO_DATA
441 { NO_DATA, "No Data" },
442 #endif
443 #ifdef NO_ADDRESS
444 { NO_ADDRESS, "No Address" },
445 #endif
446 { 0, NULL }
448 #endif
449 #endif
451 #ifndef WITH_NOHTTP
452 #ifndef WITH_LEAN
453 static const struct soap_code_map h_http_error_codes[] =
454 { { 200, "OK" },
455 { 201, "Created" },
456 { 202, "Accepted" },
457 { 203, "Non-Authoritative Information" },
458 { 204, "No Content" },
459 { 205, "Reset Content" },
460 { 206, "Partial Content" },
461 { 300, "Multiple Choices" },
462 { 301, "Moved Permanently" },
463 { 302, "Found" },
464 { 303, "See Other" },
465 { 304, "Not Modified" },
466 { 305, "Use Proxy" },
467 { 307, "Temporary Redirect" },
468 { 400, "Bad Request" },
469 { 401, "Unauthorized" },
470 { 402, "Payment Required" },
471 { 403, "Forbidden" },
472 { 404, "Not Found" },
473 { 405, "Method Not Allowed" },
474 { 406, "Not Acceptable" },
475 { 407, "Proxy Authentication Required" },
476 { 408, "Request Time-out" },
477 { 409, "Conflict" },
478 { 410, "Gone" },
479 { 411, "Length Required" },
480 { 412, "Precondition Failed" },
481 { 413, "Request Entity Too Large" },
482 { 414, "Request-URI Too Large" },
483 { 415, "Unsupported Media Type" },
484 { 416, "Requested range not satisfiable" },
485 { 417, "Expectation Failed" },
486 { 500, "Internal Server Error" },
487 { 501, "Not Implemented" },
488 { 502, "Bad Gateway" },
489 { 503, "Service Unavailable" },
490 { 504, "Gateway Time-out" },
491 { 505, "HTTP Version not supported" },
492 { 0, NULL }
494 #endif
495 #endif
497 #ifdef WITH_OPENSSL
498 static const struct soap_code_map h_ssl_error_codes[] =
500 #define _SSL_ERROR(e) { e, #e }
501 _SSL_ERROR(SSL_ERROR_SSL),
502 _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
503 _SSL_ERROR(SSL_ERROR_WANT_READ),
504 _SSL_ERROR(SSL_ERROR_WANT_WRITE),
505 _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
506 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
507 _SSL_ERROR(SSL_ERROR_SYSCALL),
508 { 0, NULL }
510 #endif
512 #ifndef WITH_LEANER
513 static const struct soap_code_map mime_codes[] =
514 { { SOAP_MIME_7BIT, "7bit" },
515 { SOAP_MIME_8BIT, "8bit" },
516 { SOAP_MIME_BINARY, "binary" },
517 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
518 { SOAP_MIME_BASE64, "base64" },
519 { SOAP_MIME_IETF_TOKEN, "ietf-token" },
520 { SOAP_MIME_X_TOKEN, "x-token" },
521 { 0, NULL }
523 #endif
525 #ifdef WIN32
526 static int tcp_done = 0;
527 #endif
529 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
530 extern int h_errno;
531 #endif
533 /******************************************************************************/
534 #ifndef WITH_NOIO
535 #ifndef PALM_1
536 static int
537 fsend(struct soap *soap, const char *s, size_t n)
538 { register int nwritten, err;
539 SOAP_SOCKET sk;
540 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
541 if (soap->os)
542 { soap->os->write(s, (std::streamsize)n);
543 if (soap->os->good())
544 return SOAP_OK;
545 soap->errnum = 0;
546 return SOAP_EOF;
548 #endif
549 sk = soap->sendsk;
550 if (!soap_valid_socket(sk))
551 sk = soap->socket;
552 while (n)
553 { if (soap_valid_socket(sk))
555 if (soap->send_timeout)
556 { for (;;)
557 { register int r;
558 #ifdef WITH_OPENSSL
559 if (soap->ssl)
560 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
561 else
562 #endif
563 #ifdef WITH_GNUTLS
564 if (soap->session)
565 r = tcp_select(soap, sk, SOAP_TCP_SELECT_ALL, soap->send_timeout);
566 else
567 #endif
568 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout);
569 if (r > 0)
570 break;
571 if (!r)
572 return SOAP_EOF;
573 err = soap->errnum;
574 if (!err)
575 return soap->error;
576 if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
577 return SOAP_EOF;
580 #ifdef WITH_OPENSSL
581 if (soap->ssl)
582 nwritten = SSL_write(soap->ssl, s, (int)n);
583 else if (soap->bio)
584 nwritten = BIO_write(soap->bio, s, (int)n);
585 else
586 #endif
587 #ifdef WITH_GNUTLS
588 if (soap->session)
589 nwritten = gnutls_record_send(soap->session, s, n);
590 else
591 #endif
592 #ifndef WITH_LEAN
593 if ((soap->omode & SOAP_IO_UDP))
594 { if (soap->peerlen)
595 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
596 else
597 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
598 /* retry and back-off algorithm */
599 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
600 if (nwritten < 0)
601 { int udp_repeat;
602 int udp_delay;
603 if ((soap->connect_flags & SO_BROADCAST))
604 udp_repeat = 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
605 else
606 udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
607 udp_delay = ((unsigned int)soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
609 { tcp_select(soap, sk, SOAP_TCP_SELECT_ERR, -1000 * udp_delay);
610 if (soap->peerlen)
611 nwritten = sendto(sk, (char*)s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen);
612 else
613 nwritten = send(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags);
614 udp_delay <<= 1;
615 if (udp_delay > 500) /* UDP_UPPER_DELAY */
616 udp_delay = 500;
618 while (nwritten < 0 && --udp_repeat > 0);
620 if (nwritten < 0)
621 { err = soap_socket_errno(sk);
622 if (err && err != SOAP_EINTR)
623 { soap->errnum = err;
624 return SOAP_EOF;
626 nwritten = 0; /* and call write() again */
629 else
630 #endif
631 #if !defined(PALM) && !defined(AS400)
632 nwritten = send(sk, s, (int)n, soap->socket_flags);
633 #else
634 nwritten = send(sk, (void*)s, n, soap->socket_flags);
635 #endif
636 if (nwritten <= 0)
638 register int r = 0;
639 err = soap_socket_errno(sk);
640 #ifdef WITH_OPENSSL
641 if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
642 { soap->errnum = err;
643 return SOAP_EOF;
645 #endif
646 #ifdef WITH_GNUTLS
647 if (soap->session)
648 { if (nwritten == GNUTLS_E_INTERRUPTED)
649 err = SOAP_EINTR;
650 else if (nwritten == GNUTLS_E_AGAIN)
651 err = SOAP_EAGAIN;
653 #endif
654 if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
656 #if defined(WITH_OPENSSL)
657 if (soap->ssl && r == SSL_ERROR_WANT_READ)
658 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
659 else
660 #elif defined(WITH_GNUTLS)
661 if (soap->session && !gnutls_record_get_direction(soap->session))
662 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
663 else
664 #endif
665 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
666 if (!r && soap->send_timeout)
667 return SOAP_EOF;
668 if (r < 0)
669 return SOAP_EOF;
671 else if (err && err != SOAP_EINTR)
672 { soap->errnum = err;
673 return SOAP_EOF;
675 nwritten = 0; /* and call write() again */
678 else
680 #ifdef WITH_FASTCGI
681 nwritten = fwrite((void*)s, 1, n, stdout);
682 fflush(stdout);
683 #else
684 #ifdef UNDER_CE
685 nwritten = fwrite(s, 1, n, soap->sendfd);
686 #else
687 #ifdef VXWORKS
688 #ifdef WMW_RPM_IO
689 if (soap->rpmreqid)
690 nwritten = (httpBlockPut(soap->rpmreqid, (char*)s, n) == 0) ? n : -1;
691 else
692 #endif
693 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
694 #else
695 #ifdef WIN32
696 nwritten = _write(soap->sendfd, s, (unsigned int)n);
697 #else
698 nwritten = write(soap->sendfd, s, (unsigned int)n);
699 #endif
700 #endif
701 #endif
702 #endif
703 if (nwritten <= 0)
705 #ifndef WITH_FASTCGI
706 err = soap_errno;
707 #else
708 err = EOF;
709 #endif
710 if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
711 { soap->errnum = err;
712 return SOAP_EOF;
714 nwritten = 0; /* and call write() again */
717 n -= nwritten;
718 s += nwritten;
720 return SOAP_OK;
722 #endif
723 #endif
725 /******************************************************************************/
726 #ifndef PALM_1
727 SOAP_FMAC1
729 SOAP_FMAC2
730 soap_send_raw(struct soap *soap, const char *s, size_t n)
731 { if (!n)
732 return SOAP_OK;
733 #ifndef WITH_LEANER
734 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->mode & SOAP_IO_LENGTH) && (soap->error = soap->fpreparesend(soap, s, n)))
735 return soap->error;
736 if (soap->ffiltersend && (soap->error = soap->ffiltersend(soap, &s, &n)))
737 return soap->error;
738 #endif
739 if (soap->mode & SOAP_IO_LENGTH)
740 soap->count += n;
741 else if (soap->mode & SOAP_IO)
742 { register size_t i = SOAP_BUFLEN - soap->bufidx;
743 while (n >= i)
744 { memcpy(soap->buf + soap->bufidx, s, i);
745 soap->bufidx = SOAP_BUFLEN;
746 if (soap_flush(soap))
747 return soap->error;
748 s += i;
749 n -= i;
750 i = SOAP_BUFLEN;
752 memcpy(soap->buf + soap->bufidx, s, n);
753 soap->bufidx += n;
755 else
756 return soap_flush_raw(soap, s, n);
757 return SOAP_OK;
759 #endif
761 /******************************************************************************/
762 #ifndef PALM_1
763 SOAP_FMAC1
765 SOAP_FMAC2
766 soap_flush(struct soap *soap)
767 { register size_t n = soap->bufidx;
768 if (n)
770 #ifndef WITH_LEANER
771 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
772 { register int r;
773 if (soap->fpreparesend && (r = soap->fpreparesend(soap, soap->buf, n)))
774 return soap->error = r;
776 #endif
777 soap->bufidx = 0;
778 #ifdef WITH_ZLIB
779 if (soap->mode & SOAP_ENC_ZLIB)
780 { soap->d_stream->next_in = (Byte*)soap->buf;
781 soap->d_stream->avail_in = (unsigned int)n;
782 #ifdef WITH_GZIP
783 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
784 #endif
786 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in));
787 if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK)
788 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
789 return soap->error = SOAP_ZLIB_ERROR;
791 if (!soap->d_stream->avail_out)
792 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
793 return soap->error;
794 soap->d_stream->next_out = (Byte*)soap->z_buf;
795 soap->d_stream->avail_out = SOAP_BUFLEN;
797 } while (soap->d_stream->avail_in);
799 else
800 #endif
801 return soap_flush_raw(soap, soap->buf, n);
803 return SOAP_OK;
805 #endif
807 /******************************************************************************/
808 #ifndef PALM_1
809 SOAP_FMAC1
811 SOAP_FMAC2
812 soap_flush_raw(struct soap *soap, const char *s, size_t n)
813 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
814 { register char *t;
815 if (!(t = (char*)soap_push_block(soap, NULL, n)))
816 return soap->error = SOAP_EOM;
817 memcpy(t, s, n);
818 return SOAP_OK;
820 #ifndef WITH_LEANER
821 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
822 { char t[16];
823 #ifdef HAVE_SNPRINTF
824 soap_snprintf(t, sizeof(t), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
825 #else
826 sprintf(t, &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
827 #endif
828 DBGMSG(SENT, t, strlen(t));
829 if ((soap->error = soap->fsend(soap, t, strlen(t))))
830 return soap->error;
831 soap->chunksize += n;
833 DBGMSG(SENT, s, n);
834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, soap->socket, soap->sendfd));
835 #endif
836 return soap->error = soap->fsend(soap, s, n);
838 #endif
840 /******************************************************************************/
841 #ifndef PALM_1
842 SOAP_FMAC1
844 SOAP_FMAC2
845 soap_send(struct soap *soap, const char *s)
846 { if (s)
847 return soap_send_raw(soap, s, strlen(s));
848 return SOAP_OK;
850 #endif
852 /******************************************************************************/
853 #ifndef WITH_LEANER
854 #ifndef PALM_1
855 SOAP_FMAC1
857 SOAP_FMAC2
858 soap_send2(struct soap *soap, const char *s1, const char *s2)
859 { if (soap_send(soap, s1))
860 return soap->error;
861 return soap_send(soap, s2);
863 #endif
864 #endif
866 /******************************************************************************/
867 #ifndef WITH_LEANER
868 #ifndef PALM_1
869 SOAP_FMAC1
871 SOAP_FMAC2
872 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
873 { if (soap_send(soap, s1)
874 || soap_send(soap, s2))
875 return soap->error;
876 return soap_send(soap, s3);
878 #endif
879 #endif
881 /******************************************************************************/
882 #ifndef WITH_NOIO
883 #ifndef PALM_1
884 static size_t
885 frecv(struct soap *soap, char *s, size_t n)
886 { register int r;
887 register int retries = 100; /* max 100 retries with non-blocking sockets */
888 SOAP_SOCKET sk;
889 soap->errnum = 0;
890 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
891 if (soap->is)
892 { if (soap->is->good())
893 return soap->is->read(s, (std::streamsize)n).gcount();
894 return 0;
896 #endif
897 sk = soap->recvsk;
898 if (!soap_valid_socket(sk))
899 sk = soap->socket;
900 if (soap_valid_socket(sk))
901 { for (;;)
903 #ifdef WITH_OPENSSL
904 register int err = 0;
905 #endif
906 #ifdef WITH_OPENSSL
907 if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
908 #else
909 if (soap->recv_timeout)
910 #endif
911 { for (;;)
912 { r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout);
913 if (r > 0)
914 break;
915 if (!r)
916 return 0;
917 r = soap->errnum;
918 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
919 return 0;
922 #ifdef WITH_OPENSSL
923 if (soap->ssl)
924 { r = SSL_read(soap->ssl, s, (int)n);
925 if (r > 0)
926 return (size_t)r;
927 err = SSL_get_error(soap->ssl, r);
928 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
929 return 0;
931 else if (soap->bio)
932 { r = BIO_read(soap->bio, s, (int)n);
933 if (r > 0)
934 return (size_t)r;
935 return 0;
937 else
938 #endif
939 #ifdef WITH_GNUTLS
940 if (soap->session)
941 { r = (int)gnutls_record_recv(soap->session, s, n);
942 if (r >= 0)
943 return (size_t)r;
945 else
946 #endif
948 #ifndef WITH_LEAN
949 if ((soap->omode & SOAP_IO_UDP))
950 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
951 memset((void*)&soap->peer, 0, sizeof(soap->peer));
952 r = recvfrom(sk, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
953 soap->peerlen = (size_t)k;
954 #ifndef WITH_IPV6
955 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
956 #endif
958 else
959 #endif
960 r = recv(sk, s, (int)n, soap->socket_flags);
961 #ifdef PALM
962 /* CycleSyncDisplay(curStatusMsg); */
963 #endif
964 if (r >= 0)
965 return (size_t)r;
966 r = soap_socket_errno(sk);
967 if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
968 { soap->errnum = r;
969 return 0;
972 #if defined(WITH_OPENSSL)
973 if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
974 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
975 else
976 #elif defined(WITH_GNUTLS)
977 if (soap->session && gnutls_record_get_direction(soap->session))
978 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
979 else
980 #endif
981 r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
982 if (!r && soap->recv_timeout)
983 return 0;
984 if (r < 0)
985 { r = soap->errnum;
986 if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
987 return 0;
989 if (retries-- <= 0)
990 return 0;
991 #ifdef PALM
992 r = soap_socket_errno(sk);
993 if (r != SOAP_EINTR && retries-- <= 0)
994 { soap->errnum = r;
995 return 0;
997 #endif
1000 #ifdef WITH_FASTCGI
1001 return fread(s, 1, n, stdin);
1002 #else
1003 #ifdef UNDER_CE
1004 return fread(s, 1, n, soap->recvfd);
1005 #else
1006 #ifdef WMW_RPM_IO
1007 if (soap->rpmreqid)
1008 r = httpBlockRead(soap->rpmreqid, s, n);
1009 else
1010 #endif
1011 #ifdef WIN32
1012 r = _read(soap->recvfd, s, (unsigned int)n);
1013 #else
1014 r = read(soap->recvfd, s, (unsigned int)n);
1015 #endif
1016 if (r >= 0)
1017 return (size_t)r;
1018 soap->errnum = soap_errno;
1019 return 0;
1020 #endif
1021 #endif
1023 #endif
1024 #endif
1026 /******************************************************************************/
1027 #ifndef WITH_NOHTTP
1028 #ifndef PALM_1
1029 static soap_wchar
1030 soap_getchunkchar(struct soap *soap)
1031 { if (soap->bufidx < soap->buflen)
1032 return soap->buf[soap->bufidx++];
1033 soap->bufidx = 0;
1034 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1035 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap->buflen, soap->socket, soap->recvfd));
1036 DBGMSG(RECV, soap->buf, soap->buflen);
1037 if (soap->buflen)
1038 return soap->buf[soap->bufidx++];
1039 return EOF;
1041 #endif
1042 #endif
1044 /******************************************************************************/
1045 #ifndef PALM_1
1046 static int
1047 soap_isxdigit(int c)
1048 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
1050 #endif
1052 /******************************************************************************/
1053 #ifndef PALM_1
1054 SOAP_FMAC1
1056 SOAP_FMAC2
1057 soap_recv_raw(struct soap *soap)
1058 { register size_t ret;
1059 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
1060 register int r;
1061 #endif
1062 #ifdef WITH_ZLIB
1063 if (soap->mode & SOAP_ENC_ZLIB)
1064 { if (soap->d_stream->next_out == Z_NULL)
1065 { soap->bufidx = soap->buflen = 0;
1066 return EOF;
1068 if (soap->d_stream->avail_in || !soap->d_stream->avail_out)
1069 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
1070 soap->d_stream->next_out = (Byte*)soap->buf;
1071 soap->d_stream->avail_out = SOAP_BUFLEN;
1072 r = inflate(soap->d_stream, Z_NO_FLUSH);
1073 if (r == Z_NEED_DICT && soap->z_dict)
1074 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
1075 if (r == Z_OK || r == Z_STREAM_END)
1076 { soap->bufidx = 0;
1077 ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
1078 if (soap->zlib_in == SOAP_ZLIB_GZIP)
1079 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
1080 if (r == Z_STREAM_END)
1081 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1082 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1083 soap->d_stream->next_out = Z_NULL;
1085 if (ret)
1086 { soap->count += ret;
1087 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1088 DBGMSG(RECV, soap->buf, ret);
1089 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
1090 #ifndef WITH_LEANER
1091 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
1092 return soap->error = r;
1093 #endif
1094 return SOAP_OK;
1097 else if (r != Z_BUF_ERROR)
1098 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
1099 soap->d_stream->next_out = Z_NULL;
1100 return soap->error = SOAP_ZLIB_ERROR;
1103 zlib_again:
1104 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
1105 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
1106 soap->buflen = soap->z_buflen;
1108 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
1110 #endif
1111 #ifndef WITH_NOHTTP
1112 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
1113 { for (;;)
1114 { register soap_wchar c;
1115 char *t, tmp[17];
1116 if (soap->chunksize)
1117 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
1118 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
1119 DBGMSG(RECV, soap->buf, ret);
1120 soap->bufidx = 0;
1121 soap->chunksize -= ret;
1122 break;
1124 t = tmp;
1125 if (!soap->chunkbuflen)
1126 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, soap->socket));
1128 DBGMSG(RECV, soap->buf, ret);
1129 soap->bufidx = 0;
1130 if (!ret)
1131 { soap->ahead = EOF;
1132 return EOF;
1135 else
1136 soap->bufidx = soap->buflen;
1137 soap->buflen = soap->chunkbuflen;
1138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
1139 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
1140 { if ((int)c == EOF)
1141 { soap->ahead = EOF;
1142 return EOF;
1146 *t++ = (char)c;
1147 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && (size_t)(t - tmp) < sizeof(tmp)-1);
1148 while ((int)c != EOF && c != '\n')
1149 c = soap_getchunkchar(soap);
1150 if ((int)c == EOF)
1151 { soap->ahead = EOF;
1152 return EOF;
1154 *t = '\0';
1155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp));
1156 soap->chunksize = (size_t)soap_strtoul(tmp, &t, 16);
1157 if (!soap->chunksize)
1158 { soap->bufidx = soap->buflen = soap->chunkbuflen = 0;
1159 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
1160 while ((int)c != EOF && c != '\n')
1161 c = soap_getchunkchar(soap);
1162 ret = 0;
1163 soap->ahead = EOF;
1164 break;
1166 soap->buflen = soap->bufidx + soap->chunksize;
1167 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
1168 if (soap->buflen > soap->chunkbuflen)
1169 { soap->buflen = soap->chunkbuflen;
1170 soap->chunksize -= soap->buflen - soap->bufidx;
1171 soap->chunkbuflen = 0;
1172 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
1174 else if (soap->chunkbuflen)
1175 soap->chunksize = 0;
1176 ret = soap->buflen - soap->bufidx;
1177 if (ret)
1178 break;
1181 else
1182 #endif
1183 { soap->bufidx = 0;
1184 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1185 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret, soap->socket, soap->recvfd));
1186 DBGMSG(RECV, soap->buf, ret);
1188 #ifdef WITH_ZLIB
1189 if (soap->mode & SOAP_ENC_ZLIB)
1190 { memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
1191 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
1192 soap->d_stream->avail_in = (unsigned int)ret;
1193 soap->d_stream->next_out = (Byte*)soap->buf;
1194 soap->d_stream->avail_out = SOAP_BUFLEN;
1195 r = inflate(soap->d_stream, Z_NO_FLUSH);
1196 if (r == Z_NEED_DICT && soap->z_dict)
1197 r = inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len);
1198 if (r == Z_OK || r == Z_STREAM_END)
1199 { soap->bufidx = 0;
1200 soap->z_buflen = soap->buflen;
1201 soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out;
1202 if (soap->zlib_in == SOAP_ZLIB_GZIP)
1203 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
1204 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen));
1205 if (ret && !soap->buflen && r != Z_STREAM_END)
1206 goto zlib_again;
1207 ret = soap->buflen;
1208 if (r == Z_STREAM_END)
1209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
1210 soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out;
1211 soap->d_stream->next_out = Z_NULL;
1213 DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1214 DBGMSG(RECV, soap->buf, ret);
1215 #ifndef WITH_LEANER
1216 if (soap->fpreparerecv && (r = soap->fpreparerecv(soap, soap->buf, ret)))
1217 return soap->error = r;
1218 #endif
1220 else
1221 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
1222 soap->d_stream->next_out = Z_NULL;
1223 return soap->error = SOAP_ZLIB_ERROR;
1226 #endif
1227 #ifndef WITH_LEANER
1228 if (soap->fpreparerecv
1229 #ifdef WITH_ZLIB
1230 && soap->zlib_in == SOAP_ZLIB_NONE
1231 #endif
1232 && (r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, ret)))
1233 return soap->error = r;
1234 #endif
1235 soap->count += ret;
1236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=%lu (+%lu)\n", (unsigned long)soap->count, (unsigned long)ret));
1237 return !ret;
1239 #endif
1241 /******************************************************************************/
1242 #ifndef PALM_1
1243 SOAP_FMAC1
1245 SOAP_FMAC2
1246 soap_recv(struct soap *soap)
1248 #ifndef WITH_LEANER
1249 if (soap->mode & SOAP_ENC_DIME)
1250 { if (soap->dime.buflen)
1251 { char *s;
1252 int i;
1253 unsigned char tmp[12];
1254 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
1255 soap->count += soap->dime.buflen - soap->buflen;
1256 soap->buflen = soap->dime.buflen;
1257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
1258 for (i = -(long)soap->dime.size&3; i > 0; i--)
1259 { soap->bufidx++;
1260 if (soap->bufidx >= soap->buflen)
1261 if (soap_recv_raw(soap))
1262 return EOF;
1264 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
1265 s = (char*)tmp;
1266 for (i = 12; i > 0; i--)
1267 { *s++ = soap->buf[soap->bufidx++];
1268 if (soap->bufidx >= soap->buflen)
1269 if (soap_recv_raw(soap))
1270 return EOF;
1272 soap->dime.flags = tmp[0] & 0x7;
1273 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
1274 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
1275 if (soap->dime.flags & SOAP_DIME_CF)
1276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
1277 soap->dime.chunksize = soap->dime.size;
1278 if (soap->buflen - soap->bufidx >= soap->dime.size)
1279 { soap->dime.buflen = soap->buflen;
1280 soap->buflen = soap->bufidx + soap->dime.chunksize;
1282 else
1283 soap->dime.chunksize -= soap->buflen - soap->bufidx;
1285 else
1286 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
1287 soap->dime.buflen = 0;
1288 soap->dime.chunksize = 0;
1290 soap->count = soap->buflen - soap->bufidx;
1291 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
1292 return SOAP_OK;
1294 if (soap->dime.chunksize)
1295 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
1296 if (soap_recv_raw(soap))
1297 return EOF;
1298 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
1299 { soap->dime.buflen = soap->buflen;
1300 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
1301 soap->buflen = soap->bufidx + soap->dime.chunksize;
1303 else
1304 soap->dime.chunksize -= soap->buflen - soap->bufidx;
1305 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%lu\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned long)soap->count));
1306 return SOAP_OK;
1309 while (soap->ffilterrecv)
1310 { int err, last = soap->filterstop;
1311 if (last)
1312 soap->bufidx = soap->buflen = 0;
1313 if ((err = soap->ffilterrecv(soap, soap->buf, &soap->buflen, sizeof(soap->buf))))
1314 return soap->error = err;
1315 if (soap->buflen)
1316 { soap->bufidx = 0;
1317 soap->filterstop = last;
1318 return SOAP_OK;
1320 if (last)
1321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Returning postponed error %d\n", last));
1322 soap->filterstop = SOAP_OK;
1323 return last;
1325 soap->filterstop = soap_recv_raw(soap); /* do not call again after EOF */
1327 #endif
1328 return soap_recv_raw(soap);
1330 #endif
1332 /******************************************************************************/
1333 #ifndef PALM_1
1334 SOAP_FMAC1
1335 soap_wchar
1336 SOAP_FMAC2
1337 soap_getchar(struct soap *soap)
1338 { register soap_wchar c;
1339 c = soap->ahead;
1340 if (c)
1341 { if (c != EOF)
1342 soap->ahead = 0;
1343 return c;
1345 return soap_get1(soap);
1347 #endif
1349 /******************************************************************************/
1350 #ifndef PALM_1
1351 SOAP_FMAC1
1352 const struct soap_code_map*
1353 SOAP_FMAC2
1354 soap_code(const struct soap_code_map *code_map, const char *str)
1355 { if (code_map && str)
1356 { while (code_map->string)
1357 { if (!strcmp(str, code_map->string)) /* case sensitive */
1358 return code_map;
1359 code_map++;
1362 return NULL;
1364 #endif
1366 /******************************************************************************/
1367 #ifndef PALM_1
1368 SOAP_FMAC1
1369 long
1370 SOAP_FMAC2
1371 soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
1372 { if (code_map)
1373 { while (code_map->string)
1374 { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
1375 return code_map->code;
1376 code_map++;
1379 return other;
1381 #endif
1383 /******************************************************************************/
1384 #ifndef PALM_1
1385 SOAP_FMAC1
1386 const char*
1387 SOAP_FMAC2
1388 soap_code_str(const struct soap_code_map *code_map, long code)
1389 { if (!code_map)
1390 return NULL;
1391 while (code_map->code != code && code_map->string)
1392 code_map++;
1393 return code_map->string;
1395 #endif
1397 /******************************************************************************/
1398 #ifndef PALM_1
1399 SOAP_FMAC1
1400 long
1401 SOAP_FMAC2
1402 soap_code_bits(const struct soap_code_map *code_map, const char *str)
1403 { register long bits = 0;
1404 if (code_map)
1405 { while (str && *str)
1406 { const struct soap_code_map *p;
1407 for (p = code_map; p->string; p++)
1408 { register size_t n = strlen(p->string);
1409 if (!strncmp(p->string, str, n) && soap_blank((soap_wchar)str[n]))
1410 { bits |= p->code;
1411 str += n;
1412 while (*str > 0 && *str <= 32)
1413 str++;
1414 break;
1417 if (!p->string)
1418 return 0;
1421 return bits;
1423 #endif
1425 /******************************************************************************/
1426 #ifndef PALM_1
1427 SOAP_FMAC1
1428 const char*
1429 SOAP_FMAC2
1430 soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
1431 { register char *t = soap->tmpbuf;
1432 if (code_map)
1433 { while (code_map->string)
1434 { if (code_map->code & code)
1435 { register const char *s = code_map->string;
1436 if (t != soap->tmpbuf)
1437 *t++ = ' ';
1438 while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1439 *t++ = *s++;
1440 if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1441 break;
1443 code_map++;
1446 *t = '\0';
1447 return soap->tmpbuf;
1449 #endif
1451 /******************************************************************************/
1452 #ifndef PALM_1
1453 static soap_wchar
1454 soap_char(struct soap *soap)
1455 { char tmp[8];
1456 register int i;
1457 register soap_wchar c;
1458 register char *s = tmp;
1459 for (i = 0; i < 7; i++)
1460 { c = soap_get1(soap);
1461 if (c == ';' || (int)c == EOF)
1462 break;
1463 *s++ = (char)c;
1465 *s = '\0';
1466 if (*tmp == '#')
1467 { if (tmp[1] == 'x' || tmp[1] == 'X')
1468 return (soap_wchar)soap_strtol(tmp + 2, NULL, 16);
1469 return (soap_wchar)soap_strtol(tmp + 1, NULL, 10);
1471 if (!strcmp(tmp, "lt"))
1472 return '<';
1473 if (!strcmp(tmp, "gt"))
1474 return '>';
1475 if (!strcmp(tmp, "amp"))
1476 return '&';
1477 if (!strcmp(tmp, "quot"))
1478 return '"';
1479 if (!strcmp(tmp, "apos"))
1480 return '\'';
1481 #ifndef WITH_LEAN
1482 return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
1483 #else
1484 return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
1485 #endif
1487 #endif
1489 /******************************************************************************/
1490 #ifdef WITH_LEAN
1491 #ifndef PALM_1
1492 soap_wchar
1493 soap_get0(struct soap *soap)
1494 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1495 return EOF;
1496 return (unsigned char)soap->buf[soap->bufidx];
1498 #endif
1499 #endif
1501 /******************************************************************************/
1502 #ifdef WITH_LEAN
1503 #ifndef PALM_1
1504 soap_wchar
1505 soap_get1(struct soap *soap)
1506 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1507 return EOF;
1508 return (unsigned char)soap->buf[soap->bufidx++];
1510 #endif
1511 #endif
1513 /******************************************************************************/
1514 #ifndef PALM_1
1515 SOAP_FMAC1
1516 soap_wchar
1517 SOAP_FMAC2
1518 soap_get(struct soap *soap)
1519 { register soap_wchar c;
1520 c = soap->ahead;
1521 if (c)
1522 { if ((int)c != EOF)
1523 soap->ahead = 0;
1525 else
1526 c = soap_get1(soap);
1527 while ((int)c != EOF)
1528 { if (soap->cdata)
1529 { if (c == ']')
1530 { c = soap_get1(soap);
1531 if (c == ']')
1532 { c = soap_get0(soap);
1533 if (c == '>')
1534 { soap->cdata = 0;
1535 c = soap_get1(soap);
1536 c = soap_get1(soap);
1538 else
1539 { soap_unget(soap, ']');
1540 return ']';
1543 else
1544 { soap_revget1(soap);
1545 return ']';
1548 else
1549 return c;
1551 switch (c)
1552 { case '<':
1553 do c = soap_get1(soap);
1554 while (soap_blank(c));
1555 if (c == '!' || c == '?' || c == '%')
1556 { register int k = 1;
1557 if (c == '!')
1558 { c = soap_get1(soap);
1559 if (c == '[')
1560 { do c = soap_get1(soap);
1561 while ((int)c != EOF && c != '[');
1562 if ((int)c == EOF)
1563 break;
1564 soap->cdata = 1;
1565 c = soap_get1(soap);
1566 continue;
1568 if (c == '-' && (c = soap_get1(soap)) == '-')
1569 { do
1570 { c = soap_get1(soap);
1571 if (c == '-' && (c = soap_get1(soap)) == '-')
1572 break;
1573 } while ((int)c != EOF);
1576 else if (c == '?')
1577 c = soap_get_pi(soap);
1578 while ((int)c != EOF)
1579 { if (c == '<')
1580 k++;
1581 else if (c == '>')
1582 { if (--k <= 0)
1583 break;
1585 c = soap_get1(soap);
1587 if ((int)c == EOF)
1588 break;
1589 c = soap_get1(soap);
1590 continue;
1592 if (c == '/')
1593 return SOAP_TT;
1594 soap_revget1(soap);
1595 return SOAP_LT;
1596 case '>':
1597 return SOAP_GT;
1598 case '"':
1599 return SOAP_QT;
1600 case '\'':
1601 return SOAP_AP;
1602 case '&':
1603 return soap_char(soap) | 0x80000000;
1605 break;
1607 return c;
1609 #endif
1611 /******************************************************************************/
1612 #ifndef PALM_1
1613 static soap_wchar
1614 soap_get_pi(struct soap *soap)
1615 { char buf[64];
1616 register char *s = buf;
1617 register int i = sizeof(buf);
1618 register soap_wchar c = soap_getchar(soap);
1619 /* This is a quick way to parse XML PI and we could use a callback instead to
1620 * enable applications to intercept processing instructions */
1621 while ((int)c != EOF && c != '?')
1622 { if (--i > 0)
1623 { if (soap_blank(c))
1624 c = ' ';
1625 *s++ = (char)c;
1627 c = soap_getchar(soap);
1629 *s = '\0';
1630 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
1631 if (!strncmp(buf, "xml ", 4))
1632 { s = strstr(buf, " encoding=");
1633 if (s && s[10])
1634 { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
1635 || !soap_tag_cmp(s + 11, "latin1*"))
1636 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
1637 soap->mode |= SOAP_ENC_LATIN;
1639 else if (!soap_tag_cmp(s + 11, "utf-8*"))
1640 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
1641 soap->mode &= ~SOAP_ENC_LATIN;
1645 if ((int)c != EOF)
1646 c = soap_getchar(soap);
1647 return c;
1649 #endif
1651 /******************************************************************************/
1652 #ifndef WITH_LEANER
1653 #ifndef PALM_1
1654 SOAP_FMAC1
1656 SOAP_FMAC2
1657 soap_move(struct soap *soap, size_t n)
1658 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %lu bytes forward\n", (unsigned long)n));
1659 for (; n; n--)
1660 if ((int)soap_getchar(soap) == EOF)
1661 return SOAP_EOF;
1662 return SOAP_OK;
1664 #endif
1665 #endif
1667 /******************************************************************************/
1668 #ifndef WITH_LEANER
1669 #ifndef PALM_1
1670 SOAP_FMAC1
1671 size_t
1672 SOAP_FMAC2
1673 soap_tell(struct soap *soap)
1674 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
1676 #endif
1677 #endif
1679 /******************************************************************************/
1680 #ifndef PALM_1
1681 SOAP_FMAC1
1683 SOAP_FMAC2
1684 soap_pututf8(struct soap *soap, register unsigned long c)
1685 { char tmp[16];
1686 if (c < 0x80 && c > 0)
1687 { *tmp = (char)c;
1688 return soap_send_raw(soap, tmp, 1);
1690 #ifndef WITH_LEAN
1691 if (c >= 0x80)
1692 { register char *t = tmp;
1693 if (c < 0x0800)
1694 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
1695 else
1696 { if (c < 0x010000)
1697 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
1698 else
1699 { if (c < 0x200000)
1700 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
1701 else
1702 { if (c < 0x04000000)
1703 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
1704 else
1705 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
1706 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
1708 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
1710 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
1712 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
1714 *t++ = (char)(0x80 | (c & 0x3F));
1715 *t = '\0';
1717 else
1718 #endif
1719 #ifdef HAVE_SNPRINTF
1720 soap_snprintf(tmp, sizeof(tmp), "&#%lu;", c);
1721 #else
1722 sprintf(tmp, "&#%lu;", c);
1723 #endif
1724 return soap_send(soap, tmp);
1726 #endif
1728 /******************************************************************************/
1729 #ifndef PALM_1
1730 SOAP_FMAC1
1731 soap_wchar
1732 SOAP_FMAC2
1733 soap_getutf8(struct soap *soap)
1734 { register soap_wchar c, c1, c2, c3, c4;
1735 c = soap->ahead;
1736 if (c >= 0x80)
1737 soap->ahead = 0;
1738 else
1739 c = soap_get(soap);
1740 if (c < 0x80 || c > 0xFF || (soap->mode & SOAP_ENC_LATIN))
1741 return c;
1742 c1 = soap_get1(soap);
1743 if (c1 < 0x80)
1744 { soap_revget1(soap); /* doesn't look like this is UTF8 */
1745 return c;
1747 c1 &= 0x3F;
1748 if (c < 0xE0)
1749 return ((soap_wchar)(c & 0x1F) << 6) | c1;
1750 c2 = (soap_wchar)soap_get1(soap) & 0x3F;
1751 if (c < 0xF0)
1752 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
1753 c3 = (soap_wchar)soap_get1(soap) & 0x3F;
1754 if (c < 0xF8)
1755 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
1756 c4 = (soap_wchar)soap_get1(soap) & 0x3F;
1757 if (c < 0xFC)
1758 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
1759 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
1761 #endif
1763 /******************************************************************************/
1764 #ifndef PALM_1
1765 SOAP_FMAC1
1767 SOAP_FMAC2
1768 soap_puthex(struct soap *soap, const unsigned char *s, int n)
1769 { char d[2];
1770 register int i;
1771 #ifdef WITH_DOM
1772 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1773 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
1774 return soap->error;
1775 return SOAP_OK;
1777 #endif
1778 for (i = 0; i < n; i++)
1779 { register int m = *s++;
1780 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
1781 m &= 0x0F;
1782 d[1] = (char)(m + (m > 9 ? '7' : '0'));
1783 if (soap_send_raw(soap, d, 2))
1784 return soap->error;
1786 return SOAP_OK;
1788 #endif
1790 /******************************************************************************/
1791 #ifndef PALM_1
1792 SOAP_FMAC1
1793 unsigned char*
1794 SOAP_FMAC2
1795 soap_gethex(struct soap *soap, int *n)
1797 #ifdef WITH_DOM
1798 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1799 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1800 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
1802 #endif
1803 #ifdef WITH_FAST
1804 soap->labidx = 0;
1805 for (;;)
1806 { register char *s;
1807 register size_t i, k;
1808 if (soap_append_lab(soap, NULL, 0))
1809 return NULL;
1810 s = soap->labbuf + soap->labidx;
1811 k = soap->lablen - soap->labidx;
1812 soap->labidx = soap->lablen;
1813 for (i = 0; i < k; i++)
1814 { register char d1, d2;
1815 register soap_wchar c;
1816 c = soap_get(soap);
1817 if (soap_isxdigit(c))
1818 { d1 = (char)c;
1819 c = soap_get(soap);
1820 if (soap_isxdigit(c))
1821 d2 = (char)c;
1822 else
1823 { soap->error = SOAP_TYPE;
1824 return NULL;
1827 else
1828 { unsigned char *p;
1829 soap_unget(soap, c);
1830 if (n)
1831 *n = (int)(soap->lablen + i - k);
1832 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
1833 if (p)
1834 memcpy(p, soap->labbuf, soap->lablen + i - k);
1835 return p;
1837 *s++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
1840 #else
1841 if (soap_new_block(soap) == NULL)
1842 return NULL;
1843 for (;;)
1844 { register int i;
1845 register char *s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN);
1846 if (!s)
1847 { soap_end_block(soap, NULL);
1848 return NULL;
1850 for (i = 0; i < SOAP_BLKLEN; i++)
1851 { register char d1, d2;
1852 register soap_wchar c = soap_get(soap);
1853 if (soap_isxdigit(c))
1854 { d1 = (char)c;
1855 c = soap_get(soap);
1856 if (soap_isxdigit(c))
1857 d2 = (char)c;
1858 else
1859 { soap_end_block(soap, NULL);
1860 soap->error = SOAP_TYPE;
1861 return NULL;
1864 else
1865 { unsigned char *p;
1866 soap_unget(soap, c);
1867 if (n)
1868 *n = (int)soap_size_block(soap, NULL, i);
1869 p = (unsigned char*)soap_save_block(soap, NULL, 0);
1870 return p;
1872 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1875 #endif
1877 #endif
1879 /******************************************************************************/
1880 #ifndef PALM_1
1881 SOAP_FMAC1
1883 SOAP_FMAC2
1884 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
1885 { register int i;
1886 register unsigned long m;
1887 char d[4];
1888 if (!s)
1889 return SOAP_OK;
1890 #ifdef WITH_DOM
1891 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1892 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
1893 return soap->error;
1894 return SOAP_OK;
1896 #endif
1897 for (; n > 2; n -= 3, s += 3)
1898 { m = s[0];
1899 m = (m << 8) | s[1];
1900 m = (m << 8) | s[2];
1901 for (i = 4; i > 0; m >>= 6)
1902 d[--i] = soap_base64o[m & 0x3F];
1903 if (soap_send_raw(soap, d, 4))
1904 return soap->error;
1906 if (n > 0)
1907 { m = 0;
1908 for (i = 0; i < n; i++)
1909 m = (m << 8) | *s++;
1910 for (; i < 3; i++)
1911 m <<= 8;
1912 for (i++; i > 0; m >>= 6)
1913 d[--i] = soap_base64o[m & 0x3F];
1914 for (i = 3; i > n; i--)
1915 d[i] = '=';
1916 if (soap_send_raw(soap, d, 4))
1917 return soap->error;
1919 return SOAP_OK;
1921 #endif
1923 /******************************************************************************/
1924 #ifndef PALM_1
1925 SOAP_FMAC1
1926 unsigned char*
1927 SOAP_FMAC2
1928 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
1929 { (void)malloc_flag;
1930 #ifdef WITH_DOM
1931 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1932 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1933 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
1935 #endif
1936 #ifdef WITH_FAST
1937 soap->labidx = 0;
1938 for (;;)
1939 { register size_t i, k;
1940 register char *s;
1941 if (soap_append_lab(soap, NULL, 2))
1942 return NULL;
1943 s = soap->labbuf + soap->labidx;
1944 k = soap->lablen - soap->labidx;
1945 soap->labidx = 3 * (soap->lablen / 3);
1946 if (!s)
1947 return NULL;
1948 if (k > 2)
1949 { for (i = 0; i < k - 2; i += 3)
1950 { register unsigned long m = 0;
1951 register int j = 0;
1953 { register soap_wchar c = soap_get(soap);
1954 if (c < SOAP_AP)
1955 c &= 0x7FFFFFFF;
1956 if (c == '=' || c < 0)
1957 { unsigned char *p;
1958 switch (j)
1959 { case 2:
1960 *s++ = (char)((m >> 4) & 0xFF);
1961 i++;
1962 break;
1963 case 3:
1964 *s++ = (char)((m >> 10) & 0xFF);
1965 *s++ = (char)((m >> 2) & 0xFF);
1966 i += 2;
1968 if (n)
1969 *n = (int)(soap->lablen + i - k);
1970 p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
1971 if (p)
1972 memcpy(p, soap->labbuf, soap->lablen + i - k);
1973 if (c >= 0)
1974 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1977 soap_unget(soap, c);
1978 return p;
1980 c -= '+';
1981 if (c >= 0 && c <= 79)
1982 { register int b = soap_base64i[c];
1983 if (b >= 64)
1984 { soap->error = SOAP_TYPE;
1985 return NULL;
1987 m = (m << 6) + b;
1988 j++;
1990 else if (!soap_blank(c + '+'))
1991 { soap->error = SOAP_TYPE;
1992 return NULL;
1994 } while (j < 4);
1995 *s++ = (char)((m >> 16) & 0xFF);
1996 *s++ = (char)((m >> 8) & 0xFF);
1997 *s++ = (char)(m & 0xFF);
2001 #else
2002 if (soap_new_block(soap) == NULL)
2003 return NULL;
2004 for (;;)
2005 { register int i;
2006 register char *s = (char*)soap_push_block(soap, NULL, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
2007 if (!s)
2008 { soap_end_block(soap, NULL);
2009 return NULL;
2011 for (i = 0; i < SOAP_BLKLEN; i++)
2012 { register unsigned long m = 0;
2013 register int j = 0;
2015 { register soap_wchar c = soap_get(soap);
2016 if (c == '=' || c < 0)
2017 { unsigned char *p;
2018 i *= 3;
2019 switch (j)
2020 { case 2:
2021 *s++ = (char)((m >> 4) & 0xFF);
2022 i++;
2023 break;
2024 case 3:
2025 *s++ = (char)((m >> 10) & 0xFF);
2026 *s++ = (char)((m >> 2) & 0xFF);
2027 i += 2;
2029 if (n)
2030 *n = (int)soap_size_block(soap, NULL, i);
2031 p = (unsigned char*)soap_save_block(soap, NULL, 0);
2032 if (c >= 0)
2033 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
2036 soap_unget(soap, c);
2037 return p;
2039 c -= '+';
2040 if (c >= 0 && c <= 79)
2041 { int b = soap_base64i[c];
2042 if (b >= 64)
2043 { soap->error = SOAP_TYPE;
2044 return NULL;
2046 m = (m << 6) + b;
2047 j++;
2049 else if (!soap_blank(c))
2050 { soap->error = SOAP_TYPE;
2051 return NULL;
2053 } while (j < 4);
2054 *s++ = (char)((m >> 16) & 0xFF);
2055 *s++ = (char)((m >> 8) & 0xFF);
2056 *s++ = (char)(m & 0xFF);
2059 #endif
2061 #endif
2063 /******************************************************************************/
2064 #ifndef WITH_LEANER
2065 #ifndef PALM_1
2066 SOAP_FMAC1
2068 SOAP_FMAC2
2069 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2070 { /* Check MTOM xop:Include element (within hex/base64Binary) */
2071 /* TODO: this code to be obsoleted with new import/xop.h conventions */
2072 short body = soap->body; /* should save type too? */
2073 if (!soap_peek_element(soap))
2074 { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL))
2075 { if (soap_dime_forward(soap, ptr, size, id, type, options)
2076 || (soap->body && soap_element_end_in(soap, "xop:Include")))
2077 return soap->error;
2080 soap->body = body;
2081 return SOAP_OK;
2083 #endif
2084 #endif
2086 /******************************************************************************/
2087 #ifndef WITH_LEANER
2088 #ifndef PALM_1
2089 SOAP_FMAC1
2091 SOAP_FMAC2
2092 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2093 { struct soap_xlist *xp;
2094 *ptr = NULL;
2095 *size = 0;
2096 *id = NULL;
2097 *type = NULL;
2098 *options = NULL;
2099 if (!*soap->href)
2100 return SOAP_OK;
2101 *id = soap_strdup(soap, soap->href);
2102 xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
2103 if (!xp)
2104 return soap->error = SOAP_EOM;
2105 xp->next = soap->xlist;
2106 xp->ptr = ptr;
2107 xp->size = size;
2108 xp->id = *id;
2109 xp->type = type;
2110 xp->options = options;
2111 soap->xlist = xp;
2112 return SOAP_OK;
2114 #endif
2115 #endif
2117 /******************************************************************************/
2118 #ifndef PALM_1
2119 SOAP_FMAC1
2120 char *
2121 SOAP_FMAC2
2122 soap_strdup(struct soap *soap, const char *s)
2123 { char *t = NULL;
2124 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
2125 strcpy(t, s);
2126 return t;
2128 #endif
2130 /******************************************************************************/
2131 #ifndef PALM_1
2132 SOAP_FMAC1
2133 wchar_t *
2134 SOAP_FMAC2
2135 soap_wstrdup(struct soap *soap, const wchar_t *s)
2136 { wchar_t *t = NULL;
2137 if (s)
2138 { size_t n = 0;
2139 while (s[n])
2140 n++;
2141 if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1))))
2142 memcpy(t, s, sizeof(wchar_t)*(n+1));
2144 return t;
2146 #endif
2148 /******************************************************************************/
2149 #ifndef PALM_1
2150 SOAP_FMAC1
2151 struct soap_blist*
2152 SOAP_FMAC2
2153 soap_new_block(struct soap *soap)
2154 { struct soap_blist *p;
2155 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
2156 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
2157 { soap->error = SOAP_EOM;
2158 return NULL;
2160 p->next = soap->blist;
2161 p->ptr = NULL;
2162 p->size = 0;
2163 soap->blist = p;
2164 return p;
2166 #endif
2168 /******************************************************************************/
2169 #ifndef PALM_1
2170 SOAP_FMAC1
2171 void*
2172 SOAP_FMAC2
2173 soap_push_block(struct soap *soap, struct soap_blist *b, size_t n)
2174 { char *p;
2175 if (!b)
2176 b = soap->blist;
2177 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)b->size + (unsigned int)n));
2178 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
2179 { soap->error = SOAP_EOM;
2180 return NULL;
2182 *(char**)p = b->ptr;
2183 *(size_t*)(p + sizeof(char*)) = n;
2184 b->ptr = p;
2185 b->size += n;
2186 return p + sizeof(char*) + sizeof(size_t);
2188 #endif
2190 /******************************************************************************/
2191 #ifndef PALM_1
2192 SOAP_FMAC1
2193 void
2194 SOAP_FMAC2
2195 soap_pop_block(struct soap *soap, struct soap_blist *b)
2196 { char *p;
2197 if (!b)
2198 b = soap->blist;
2199 if (!b->ptr)
2200 return;
2201 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
2202 p = b->ptr;
2203 b->size -= *(size_t*)(p + sizeof(char*));
2204 b->ptr = *(char**)p;
2205 SOAP_FREE(soap, p);
2207 #endif
2209 /******************************************************************************/
2210 #ifndef PALM_1
2211 SOAP_FMAC1
2212 void
2213 SOAP_FMAC2
2214 soap_update_pointers(struct soap *soap, char *start, char *end, char *p1, char *p2)
2216 #ifndef WITH_NOIDREF
2217 int i;
2218 register struct soap_ilist *ip = NULL;
2219 register struct soap_flist *fp = NULL;
2220 #ifndef WITH_LEANER
2221 register struct soap_xlist *xp = NULL;
2222 #endif
2223 register void *p, **q;
2224 for (i = 0; i < SOAP_IDHASH; i++)
2225 { for (ip = soap->iht[i]; ip; ip = ip->next)
2226 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
2227 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
2228 ip->ptr = (char*)ip->ptr + (p1-p2);
2230 for (q = &ip->link; q; q = (void**)p)
2231 { p = *q;
2232 if (p && (char*)p >= start && (char*)p < end)
2233 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
2234 *q = (char*)p + (p1-p2);
2237 for (q = &ip->copy; q; q = (void**)p)
2238 { p = *q;
2239 if (p && (char*)p >= start && (char*)p < end)
2240 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
2241 *q = (char*)p + (p1-p2);
2244 for (fp = ip->flist; fp; fp = fp->next)
2245 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
2246 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
2247 fp->ptr = (char*)fp->ptr + (p1-p2);
2252 #ifndef WITH_LEANER
2253 for (xp = soap->xlist; xp; xp = xp->next)
2254 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
2255 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id ? xp->id : SOAP_STR_EOS, xp->ptr, (char*)xp->ptr + (p1-p2)));
2256 xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
2257 xp->size = (int*)((char*)xp->size + (p1-p2));
2258 xp->type = (char**)((char*)xp->type + (p1-p2));
2259 xp->options = (char**)((char*)xp->options + (p1-p2));
2262 #endif
2263 #else
2264 (void)soap; (void)start; (void)end; (void)p1; (void)p2;
2265 #endif
2267 #endif
2269 /******************************************************************************/
2270 #ifndef WITH_NOIDREF
2271 #ifndef PALM_1
2272 static int
2273 soap_has_copies(struct soap *soap, register const char *start, register const char *end)
2274 { register int i;
2275 register struct soap_ilist *ip = NULL;
2276 register struct soap_flist *fp = NULL;
2277 register const char *p;
2278 for (i = 0; i < SOAP_IDHASH; i++)
2279 { for (ip = soap->iht[i]; ip; ip = ip->next)
2280 { for (p = (const char*)ip->copy; p; p = *(const char**)p)
2281 if (p >= start && p < end)
2282 return SOAP_ERR;
2283 for (fp = ip->flist; fp; fp = fp->next)
2284 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
2285 return SOAP_ERR;
2288 return SOAP_OK;
2290 #endif
2291 #endif
2293 /******************************************************************************/
2294 #ifndef WITH_NOIDREF
2295 #ifndef PALM_1
2296 SOAP_FMAC1
2298 SOAP_FMAC2
2299 soap_resolve(struct soap *soap)
2300 { register int i;
2301 register struct soap_ilist *ip = NULL;
2302 register struct soap_flist *fp = NULL;
2303 short flag;
2304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
2305 for (i = 0; i < SOAP_IDHASH; i++)
2306 { for (ip = soap->iht[i]; ip; ip = ip->next)
2307 { if (ip->ptr)
2308 { register void *p, **q, *r;
2309 q = (void**)ip->link;
2310 ip->link = NULL;
2311 r = ip->ptr;
2312 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
2313 while (q)
2314 { p = *q;
2315 *q = r;
2316 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
2317 q = (void**)p;
2320 else if (*ip->id == '#')
2321 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
2322 strcpy(soap->id, ip->id + 1);
2323 return soap->error = SOAP_MISSING_ID;
2328 { flag = 0;
2329 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
2330 for (i = 0; i < SOAP_IDHASH; i++)
2331 { for (ip = soap->iht[i]; ip; ip = ip->next)
2332 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
2333 { if (ip->copy)
2334 { register void *p, **q = (void**)ip->copy;
2335 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
2336 ip->copy = NULL;
2338 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
2339 p = *q;
2340 memcpy(q, ip->ptr, ip->size);
2341 q = (void**)p;
2342 } while (q);
2343 flag = 1;
2345 for (fp = ip->flist; fp; fp = ip->flist)
2346 { register unsigned int k = fp->level;
2347 register void *p = ip->ptr;
2348 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));
2349 while (ip->level < k)
2350 { register void **q = (void**)soap_malloc(soap, sizeof(void*));
2351 if (!q)
2352 return soap->error;
2353 *q = p;
2354 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
2355 p = (void*)q;
2356 k--;
2358 if (fp->fcopy)
2359 fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2360 else
2361 soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2362 ip->flist = fp->next;
2363 SOAP_FREE(soap, fp);
2364 flag = 1;
2369 } while (flag);
2370 #ifdef SOAP_DEBUG
2371 for (i = 0; i < SOAP_IDHASH; i++)
2372 { for (ip = soap->iht[i]; ip; ip = ip->next)
2373 { if (ip->copy || ip->flist)
2374 { 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));
2378 #endif
2379 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
2380 return SOAP_OK;
2382 #endif
2383 #endif
2385 /******************************************************************************/
2386 #ifndef PALM_1
2387 SOAP_FMAC1
2388 size_t
2389 SOAP_FMAC2
2390 soap_size_block(struct soap *soap, struct soap_blist *b, size_t n)
2391 { if (!b)
2392 b = soap->blist;
2393 if (b->ptr)
2394 { b->size -= *(size_t*)(b->ptr + sizeof(char*)) - n;
2395 *(size_t*)(b->ptr + sizeof(char*)) = n;
2397 return b->size;
2399 #endif
2401 /******************************************************************************/
2402 #ifndef PALM_1
2403 SOAP_FMAC1
2404 char*
2405 SOAP_FMAC2
2406 soap_first_block(struct soap *soap, struct soap_blist *b)
2407 { char *p, *q, *r;
2408 if (!b)
2409 b = soap->blist;
2410 p = b->ptr;
2411 if (!p)
2412 return NULL;
2413 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
2414 r = NULL;
2416 { q = *(char**)p;
2417 *(char**)p = r;
2418 r = p;
2419 p = q;
2420 } while (p);
2421 b->ptr = r;
2422 return r + sizeof(char*) + sizeof(size_t);
2424 #endif
2426 /******************************************************************************/
2427 #ifndef PALM_1
2428 SOAP_FMAC1
2429 char*
2430 SOAP_FMAC2
2431 soap_next_block(struct soap *soap, struct soap_blist *b)
2432 { char *p;
2433 if (!b)
2434 b = soap->blist;
2435 p = b->ptr;
2436 if (p)
2437 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
2438 b->ptr = *(char**)p;
2439 SOAP_FREE(soap, p);
2440 if (b->ptr)
2441 return b->ptr + sizeof(char*) + sizeof(size_t);
2443 return NULL;
2445 #endif
2447 /******************************************************************************/
2448 #ifndef PALM_1
2449 SOAP_FMAC1
2450 size_t
2451 SOAP_FMAC2
2452 soap_block_size(struct soap *soap, struct soap_blist *b)
2453 { if (!b)
2454 b = soap->blist;
2455 return *(size_t*)(b->ptr + sizeof(char*));
2457 #endif
2459 /******************************************************************************/
2460 #ifndef PALM_1
2461 SOAP_FMAC1
2462 void
2463 SOAP_FMAC2
2464 soap_end_block(struct soap *soap, struct soap_blist *b)
2465 { char *p, *q;
2466 if (!b)
2467 b = soap->blist;
2468 if (b)
2469 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
2470 for (p = b->ptr; p; p = q)
2471 { q = *(char**)p;
2472 SOAP_FREE(soap, p);
2474 if (soap->blist == b)
2475 soap->blist = b->next;
2476 else
2477 { struct soap_blist *bp;
2478 for (bp = soap->blist; bp; bp = bp->next)
2479 { if (bp->next == b)
2480 { bp->next = b->next;
2481 break;
2485 SOAP_FREE(soap, b);
2487 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
2489 #endif
2491 /******************************************************************************/
2492 #ifndef PALM_1
2493 SOAP_FMAC1
2494 char*
2495 SOAP_FMAC2
2496 soap_save_block(struct soap *soap, struct soap_blist *b, char *p, int flag)
2497 { register size_t n;
2498 register char *q, *s;
2499 if (!b)
2500 b = soap->blist;
2501 if (b->size)
2502 { if (!p)
2503 p = (char*)soap_malloc(soap, b->size);
2504 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)b->size, b->ptr, p));
2505 if (p)
2506 { for (s = p, q = soap_first_block(soap, b); q; q = soap_next_block(soap, b))
2507 { n = soap_block_size(soap, b);
2508 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
2509 #ifndef WITH_NOIDREF
2510 if (flag)
2511 soap_update_pointers(soap, q, q + n, s, q);
2512 #endif
2513 memcpy(s, q, n);
2514 s += n;
2517 else
2518 soap->error = SOAP_EOM;
2520 soap_end_block(soap, b);
2521 return p;
2523 #endif
2525 /******************************************************************************/
2526 #ifndef PALM_2
2527 SOAP_FMAC1
2528 char *
2529 SOAP_FMAC2
2530 soap_putsize(struct soap *soap, const char *type, int size)
2531 { return soap_putsizes(soap, type, &size, 1);
2533 #endif
2535 /******************************************************************************/
2536 #ifndef PALM_2
2537 SOAP_FMAC1
2538 char *
2539 SOAP_FMAC2
2540 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
2541 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
2543 #endif
2545 /******************************************************************************/
2546 #ifndef PALM_2
2547 SOAP_FMAC1
2548 char *
2549 SOAP_FMAC2
2550 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
2551 { register int i;
2552 register size_t l;
2553 if (!type || strlen(type) + 13 > sizeof(soap->type)) /* prevent overruns */
2554 return NULL;
2555 if (soap->version == 2)
2557 #ifdef HAVE_SNPRINTF
2558 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
2559 #else
2560 sprintf(soap->type, "%s[%d", type, size[0]);
2561 #endif
2562 for (i = 1; i < dim; i++)
2564 #ifdef HAVE_SNPRINTF
2565 l = strlen(soap->type);
2566 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, " %d", size[i]);
2567 #else
2568 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
2569 return NULL;
2570 sprintf(soap->type + l, " %d", size[i]);
2571 #endif
2574 else
2575 { if (offset)
2577 #ifdef HAVE_SNPRINTF
2578 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0] + offset[0]);
2579 #else
2580 sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
2581 #endif
2582 for (i = 1; i < dim; i++)
2584 #ifdef HAVE_SNPRINTF
2585 l = strlen(soap->type);
2586 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i] + offset[i]);
2587 #else
2588 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
2589 return NULL;
2590 sprintf(soap->type + l, ",%d", size[i] + offset[i]);
2591 #endif
2594 else
2596 #ifdef HAVE_SNPRINTF
2597 soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
2598 #else
2599 sprintf(soap->type, "%s[%d", type, size[0]);
2600 #endif
2601 for (i = 1; i < dim; i++)
2603 #ifdef HAVE_SNPRINTF
2604 l = strlen(soap->type);
2605 soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i]);
2606 #else
2607 if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
2608 return NULL;
2609 sprintf(soap->type + l, ",%d", size[i]);
2610 #endif
2614 strcat(soap->type, "]");
2615 return soap->type;
2617 #endif
2619 /******************************************************************************/
2620 #ifndef PALM_2
2621 SOAP_FMAC1
2622 char *
2623 SOAP_FMAC2
2624 soap_putoffset(struct soap *soap, int offset)
2625 { return soap_putoffsets(soap, &offset, 1);
2627 #endif
2629 /******************************************************************************/
2630 #ifndef PALM_2
2631 SOAP_FMAC1
2632 char *
2633 SOAP_FMAC2
2634 soap_putoffsets(struct soap *soap, const int *offset, int dim)
2635 { register int i;
2636 register size_t l;
2637 #ifdef HAVE_SNPRINTF
2638 soap_snprintf(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, "[%d", offset[0]);
2639 #else
2640 if (sizeof(soap->arrayOffset) < 13) /* prevent overruns */
2641 return NULL;
2642 sprintf(soap->arrayOffset, "[%d", offset[0]);
2643 #endif
2644 for (i = 1; i < dim; i++)
2646 #ifdef HAVE_SNPRINTF
2647 l = strlen(soap->arrayOffset);
2648 soap_snprintf(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, ",%d", offset[i]);
2649 #else
2650 if ((l = strlen(soap->arrayOffset)) + 13 > sizeof(soap->arrayOffset))
2651 return NULL;
2652 sprintf(soap->arrayOffset + l, ",%d", offset[i]);
2653 #endif
2655 strcat(soap->arrayOffset, "]");
2656 return soap->arrayOffset;
2658 #endif
2660 /******************************************************************************/
2661 #ifndef PALM_2
2662 SOAP_FMAC1
2664 SOAP_FMAC2
2665 soap_size(const int *size, int dim)
2666 { register int i, n = size[0];
2667 for (i = 1; i < dim; i++)
2668 n *= size[i];
2669 return n;
2671 #endif
2673 /******************************************************************************/
2674 #ifndef PALM_2
2675 SOAP_FMAC1
2677 SOAP_FMAC2
2678 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
2679 { register int i, j = 0;
2680 if (offset)
2681 for (i = 0; i < dim && attr && *attr; i++)
2682 { attr++;
2683 j *= size[i];
2684 j += offset[i] = (int)soap_strtol(attr, NULL, 10);
2685 attr = strchr(attr, ',');
2687 else
2688 for (i = 0; i < dim && attr && *attr; i++)
2689 { attr++;
2690 j *= size[i];
2691 j += (int)soap_strtol(attr, NULL, 10);
2692 attr = strchr(attr, ',');
2694 return j;
2696 #endif
2698 /******************************************************************************/
2699 #ifndef PALM_2
2700 SOAP_FMAC1
2702 SOAP_FMAC2
2703 soap_getsize(const char *attr1, const char *attr2, int *j)
2704 { register int n, k;
2705 char *s;
2706 *j = 0;
2707 if (!*attr1)
2708 return -1;
2709 if (*attr1 == '[')
2710 attr1++;
2711 n = 1;
2712 for (;;)
2713 { k = (int)soap_strtol(attr1, &s, 10);
2714 n *= k;
2715 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
2716 return -1;
2717 attr1 = strchr(s, ',');
2718 if (!attr1)
2719 attr1 = strchr(s, ' ');
2720 if (attr2 && *attr2)
2721 { attr2++;
2722 *j *= k;
2723 k = (int)soap_strtol(attr2, &s, 10);
2724 *j += k;
2725 if (k < 0)
2726 return -1;
2727 attr2 = s;
2729 if (!attr1)
2730 break;
2731 attr1++;
2733 return n - *j;
2735 #endif
2737 /******************************************************************************/
2738 #ifndef PALM_2
2739 SOAP_FMAC1
2741 SOAP_FMAC2
2742 soap_getsizes(const char *attr, int *size, int dim)
2743 { register int i, k, n;
2744 if (!*attr)
2745 return -1;
2746 i = (int)strlen(attr);
2747 n = 1;
2749 { for (i = i-1; i >= 0; i--)
2750 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
2751 break;
2752 k = (int)soap_strtol(attr + i + 1, NULL, 10);
2753 n *= size[--dim] = k;
2754 if (k < 0 || n > SOAP_MAXARRAYSIZE)
2755 return -1;
2756 } while (i >= 0 && attr[i] != '[');
2757 return n;
2759 #endif
2761 /******************************************************************************/
2762 #ifndef PALM_2
2763 SOAP_FMAC1
2765 SOAP_FMAC2
2766 soap_getposition(const char *attr, int *pos)
2767 { register int i, n;
2768 if (!*attr)
2769 return -1;
2770 n = 0;
2771 i = 1;
2773 { pos[n++] = (int)soap_strtol(attr + i, NULL, 10);
2774 while (attr[i] && attr[i] != ',' && attr[i] != ']')
2775 i++;
2776 if (attr[i] == ',')
2777 i++;
2778 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
2779 return n;
2781 #endif
2783 /******************************************************************************/
2784 #ifndef PALM_2
2785 SOAP_FMAC1
2786 struct soap_nlist *
2787 SOAP_FMAC2
2788 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
2789 { register struct soap_nlist *np;
2790 register struct Namespace *p;
2791 register short i = -1;
2792 register size_t n, k;
2793 n = strlen(id);
2794 k = strlen(ns) + 1;
2795 p = soap->local_namespaces;
2796 if (p)
2797 { for (i = 0; p->id; p++, i++)
2798 { if (p->ns && !strcmp(ns, p->ns))
2799 break;
2800 if (p->out)
2801 { if (!strcmp(ns, p->out))
2802 break;
2804 else if (p->in)
2805 { if (!soap_tag_cmp(ns, p->in))
2806 { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
2807 strcpy(p->out, ns);
2808 break;
2812 if (!p || !p->id)
2813 i = -1;
2815 if (i >= 0)
2816 k = 0;
2817 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
2818 if (!np)
2819 { soap->error = SOAP_EOM;
2820 return NULL;
2822 np->next = soap->nlist;
2823 soap->nlist = np;
2824 np->level = soap->level;
2825 np->index = i;
2826 strcpy((char*)np->id, id);
2827 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
2828 if (i < 0)
2829 { np->ns = strcpy((char*)np->id + n + 1, ns);
2830 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
2832 else
2833 { np->ns = NULL;
2834 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
2836 return np;
2838 #endif
2840 /******************************************************************************/
2841 #ifndef PALM_2
2842 SOAP_FMAC1
2843 void
2844 SOAP_FMAC2
2845 soap_pop_namespace(struct soap *soap)
2846 { register struct soap_nlist *np, *nq;
2847 for (np = soap->nlist; np && np->level >= soap->level; np = nq)
2848 { nq = np->next;
2849 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
2850 SOAP_FREE(soap, np);
2852 soap->nlist = np;
2854 #endif
2856 /******************************************************************************/
2857 #ifndef PALM_2
2858 SOAP_FMAC1
2860 SOAP_FMAC2
2861 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
2862 { register struct soap_nlist *np = soap->nlist;
2863 const char *s;
2864 while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
2865 np = np->next;
2866 if (np)
2867 { if (!(soap->mode & SOAP_XML_IGNORENS))
2868 if (np->index < 0
2869 || ((s = soap->local_namespaces[np->index].id) && (strncmp(s, id2, n2) || (s[n2] && s[n2] != '_'))))
2870 return SOAP_NAMESPACE;
2871 return SOAP_OK;
2873 if (n1 == 0)
2874 return (soap->mode & SOAP_XML_IGNORENS) ? SOAP_OK : SOAP_NAMESPACE;
2875 if ((n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3))
2876 || (soap->mode & SOAP_XML_IGNORENS))
2877 return SOAP_OK;
2878 return soap->error = SOAP_SYNTAX_ERROR;
2880 #endif
2882 /******************************************************************************/
2883 #ifndef PALM_2
2884 SOAP_FMAC1
2885 const char*
2886 SOAP_FMAC2
2887 soap_current_namespace(struct soap *soap, const char *tag)
2888 { register struct soap_nlist *np;
2889 register const char *s;
2890 if (!tag || !strncmp(tag, "xml", 3))
2891 return NULL;
2892 np = soap->nlist;
2893 if (!(s = strchr(tag, ':')))
2894 { while (np && *np->id) /* find default namespace, if present */
2895 np = np->next;
2897 else
2898 { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
2899 np = np->next;
2900 if (!np)
2901 soap->error = SOAP_NAMESPACE;
2903 if (np)
2904 { if (np->index >= 0)
2905 return soap->namespaces[np->index].ns;
2906 if (np->ns)
2907 return soap_strdup(soap, np->ns);
2909 return NULL;
2911 #endif
2913 /******************************************************************************/
2914 #ifndef PALM_2
2915 SOAP_FMAC1
2917 SOAP_FMAC2
2918 soap_tag_cmp(const char *s, const char *t)
2919 { for (;;)
2920 { register int c1 = *s;
2921 register int c2 = *t;
2922 if (!c1 || c1 == '"')
2923 break;
2924 if (c2 != '-')
2925 { if (c1 != c2)
2926 { if (c1 >= 'A' && c1 <= 'Z')
2927 c1 += 'a' - 'A';
2928 if (c2 >= 'A' && c2 <= 'Z')
2929 c2 += 'a' - 'A';
2931 if (c1 != c2)
2932 { if (c2 != '*')
2933 return 1;
2934 c2 = *++t;
2935 if (!c2)
2936 return 0;
2937 if (c2 >= 'A' && c2 <= 'Z')
2938 c2 += 'a' - 'A';
2939 for (;;)
2940 { c1 = *s;
2941 if (!c1 || c1 == '"')
2942 break;
2943 if (c1 >= 'A' && c1 <= 'Z')
2944 c1 += 'a' - 'A';
2945 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
2946 return 0;
2947 s++;
2949 break;
2952 s++;
2953 t++;
2955 if (*t == '*' && !t[1])
2956 return 0;
2957 return *t;
2959 #endif
2961 /******************************************************************************/
2962 #ifndef PALM_2
2963 SOAP_FMAC1
2965 SOAP_FMAC2
2966 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
2967 { register const char *s, *t;
2968 register int err;
2969 if (!tag1 || !tag2 || !*tag2)
2970 return SOAP_OK;
2971 s = strchr(tag1, ':');
2972 t = strchr(tag2, ':');
2973 if (t)
2974 { if (s)
2975 { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
2976 return SOAP_TAG_MISMATCH;
2977 if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
2978 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2979 if (err == SOAP_NAMESPACE)
2980 return SOAP_TAG_MISMATCH;
2981 return err;
2984 else if (!t[1])
2985 { err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);
2986 if (err == SOAP_NAMESPACE)
2987 return SOAP_TAG_MISMATCH;
2989 else if (SOAP_STRCMP(tag1, t + 1))
2990 { return SOAP_TAG_MISMATCH;
2992 else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
2993 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2994 if (err == SOAP_NAMESPACE)
2995 return SOAP_TAG_MISMATCH;
2996 return err;
2998 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
2999 return SOAP_OK;
3001 if (s)
3002 { if (SOAP_STRCMP(s + 1, tag2))
3003 return SOAP_TAG_MISMATCH;
3005 else if (SOAP_STRCMP(tag1, tag2))
3006 return SOAP_TAG_MISMATCH;
3007 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
3008 return SOAP_OK;
3010 #endif
3012 /******************************************************************************/
3013 #ifndef PALM_2
3014 SOAP_FMAC1
3016 SOAP_FMAC2
3017 soap_match_array(struct soap *soap, const char *type)
3018 { if (*soap->arrayType)
3019 if (soap_match_tag(soap, soap->arrayType, type)
3020 && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
3021 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
3023 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
3024 return SOAP_TAG_MISMATCH;
3026 return SOAP_OK;
3028 #endif
3030 /******************************************************************************\
3032 * SSL/TLS
3034 \******************************************************************************/
3036 /******************************************************************************/
3037 #ifdef WITH_OPENSSL
3038 #ifndef PALM_2
3039 SOAP_FMAC1
3041 SOAP_FMAC2
3042 soap_rand()
3043 { unsigned char buf[4];
3044 if (!soap_ssl_init_done)
3045 soap_ssl_init();
3046 RAND_pseudo_bytes(buf, 4);
3047 return *(int*)buf;
3049 #endif
3050 #endif
3052 /******************************************************************************/
3053 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3054 #ifndef PALM_2
3055 SOAP_FMAC1
3057 SOAP_FMAC2
3058 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3059 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
3060 #else
3061 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)
3062 #endif
3063 { int err;
3064 soap->keyfile = keyfile;
3065 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3066 soap->keyid = keyid;
3067 #endif
3068 soap->password = password;
3069 soap->cafile = cafile;
3070 soap->capath = capath;
3071 soap->crlfile = NULL;
3072 #ifdef WITH_OPENSSL
3073 soap->dhfile = dhfile;
3074 soap->randfile = randfile;
3075 #endif
3076 soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
3077 #ifdef WITH_GNUTLS
3078 if (dhfile)
3079 { char *s;
3080 int n = (int)soap_strtoul(dhfile, &s, 10);
3081 if (!soap->dh_params)
3082 gnutls_dh_params_init(&soap->dh_params);
3083 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3084 if (n >= 512 && s && *s == '\0')
3085 gnutls_dh_params_generate2(soap->dh_params, (unsigned int)n);
3086 else
3087 { unsigned int dparams_len;
3088 unsigned char dparams_buf[1024];
3089 FILE *fd = fopen(dhfile, "r");
3090 if (!fd)
3091 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
3092 dparams_len = (unsigned int)fread(dparams_buf, 1, sizeof(dparams_buf), fd);
3093 fclose(fd);
3094 gnutls_datum_t dparams = { dparams_buf, dparams_len };
3095 if (gnutls_dh_params_import_pkcs3(soap->dh_params, &dparams, GNUTLS_X509_FMT_PEM))
3096 return soap_set_receiver_error(soap, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR);
3099 else
3100 { if (!soap->rsa_params)
3101 gnutls_rsa_params_init(&soap->rsa_params);
3102 gnutls_rsa_params_generate2(soap->rsa_params, SOAP_SSL_RSA_BITS);
3104 if (soap->session)
3105 { gnutls_deinit(soap->session);
3106 soap->session = NULL;
3108 if (soap->xcred)
3109 { gnutls_certificate_free_credentials(soap->xcred);
3110 soap->xcred = NULL;
3112 #endif
3113 err = soap->fsslauth(soap);
3114 #ifdef WITH_OPENSSL
3115 if (!err)
3116 { if (sid)
3117 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
3118 else
3119 SSL_CTX_set_session_cache_mode(soap->ctx, SSL_SESS_CACHE_OFF);
3121 #endif
3122 return err;
3124 #endif
3125 #endif
3127 /******************************************************************************/
3128 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3129 #ifndef PALM_2
3130 SOAP_FMAC1
3132 SOAP_FMAC2
3133 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3134 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *randfile)
3135 #else
3136 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)
3137 #endif
3138 { soap->keyfile = keyfile;
3139 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3140 soap->keyid = keyid;
3141 #endif
3142 soap->password = password;
3143 soap->cafile = cafile;
3144 soap->capath = capath;
3145 soap->ssl_flags = SOAP_SSL_CLIENT | flags;
3146 #ifdef WITH_OPENSSL
3147 soap->dhfile = NULL;
3148 soap->randfile = randfile;
3149 soap->fsslverify = (flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) == 0 ? ssl_verify_callback : ssl_verify_callback_allow_expired_certificate;
3150 #endif
3151 #ifdef WITH_GNUTLS
3152 if (soap->session)
3153 { gnutls_deinit(soap->session);
3154 soap->session = NULL;
3156 if (soap->xcred)
3157 { gnutls_certificate_free_credentials(soap->xcred);
3158 soap->xcred = NULL;
3160 #endif
3161 return soap->fsslauth(soap);
3163 #endif
3164 #endif
3166 /******************************************************************************/
3167 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3168 #ifndef PALM_2
3169 SOAP_FMAC1
3170 void
3171 SOAP_FMAC2
3172 soap_ssl_init()
3173 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
3174 if (!soap_ssl_init_done)
3175 { soap_ssl_init_done = 1;
3176 #ifdef WITH_OPENSSL
3177 SSL_library_init();
3178 OpenSSL_add_all_algorithms(); /* 2.8.1 change (wsseapi.c) */
3179 OpenSSL_add_all_digests();
3180 #ifndef WITH_LEAN
3181 SSL_load_error_strings();
3182 #endif
3183 if (!RAND_load_file("/dev/urandom", 1024))
3184 { char buf[1024];
3185 RAND_seed(buf, sizeof(buf));
3186 while (!RAND_status())
3187 { int r = rand();
3188 RAND_seed(&r, sizeof(int));
3191 #endif
3192 #ifdef WITH_GNUTLS
3193 # if defined(HAVE_PTHREAD_H)
3194 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
3195 # elif defined(HAVE_PTH_H)
3196 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pth);
3197 # endif
3198 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
3199 gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
3200 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* libgcrypt init done */
3201 gnutls_global_init();
3202 #endif
3205 #endif
3206 #endif
3208 /******************************************************************************/
3209 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3210 #ifndef PALM_1
3211 SOAP_FMAC1
3212 const char *
3213 SOAP_FMAC2
3214 soap_ssl_error(struct soap *soap, int ret)
3216 #ifdef WITH_OPENSSL
3217 int err = SSL_get_error(soap->ssl, ret);
3218 const char *msg = soap_code_str(h_ssl_error_codes, err);
3219 if (msg)
3220 strcpy(soap->msgbuf, msg);
3221 else
3222 return ERR_error_string(err, soap->msgbuf);
3223 if (ERR_peek_error())
3224 { unsigned long r;
3225 strcat(soap->msgbuf, "\n");
3226 while ((r = ERR_get_error()))
3227 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
3229 else
3230 { switch (ret)
3231 { case 0:
3232 strcpy(soap->msgbuf, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information.");
3233 break;
3234 case -1:
3235 #ifdef HAVE_SNPRINTF
3236 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error observed by underlying SSL/TLS BIO: %s", strerror(errno));
3237 #else
3238 { const char *s = strerror(errno);
3239 size_t l = strlen(s);
3240 sprintf(soap->msgbuf, "Error observed by underlying SSL/TLS BIO: %s", l + 44 < sizeof(soap->msgbuf) ? s : SOAP_STR_EOS);
3242 #endif
3243 break;
3246 return soap->msgbuf;
3247 #endif
3248 #ifdef WITH_GNUTLS
3249 return gnutls_strerror(ret);
3250 #endif
3252 #endif
3253 #endif
3255 /******************************************************************************/
3256 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3257 #ifndef PALM_1
3258 static int
3259 ssl_auth_init(struct soap *soap)
3261 #ifdef WITH_OPENSSL
3262 long flags;
3263 int mode;
3264 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3265 EVP_PKEY* pkey;
3266 #endif
3267 if (!soap_ssl_init_done)
3268 soap_ssl_init();
3269 ERR_clear_error();
3270 if (!soap->ctx)
3271 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
3272 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR);
3273 /* The following alters the behavior of SSL read/write: */
3274 #if 0
3275 SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
3276 #endif
3278 if (soap->randfile)
3279 { if (!RAND_load_file(soap->randfile, -1))
3280 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR);
3282 if (soap->cafile || soap->capath)
3283 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
3284 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
3285 if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3286 SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
3288 if (!(soap->ssl_flags & SOAP_SSL_NO_DEFAULT_CA_PATH))
3289 { if (!SSL_CTX_set_default_verify_paths(soap->ctx))
3290 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
3292 /* This code assumes a typical scenario, see alternative code below */
3293 if (soap->keyfile)
3294 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
3295 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR);
3296 if (soap->password)
3297 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
3298 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
3300 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
3301 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
3302 #ifndef WM_SECURE_KEY_STORAGE
3303 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
3304 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
3305 #endif
3307 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3308 if (NULL == (pkey = ipcom_key_db_pkey_get(soap->keyid)))
3309 return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR);
3310 if (0 == SSL_CTX_use_PrivateKey(soap->ctx, pkey))
3311 return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR);
3312 #endif
3313 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
3314 #if 0
3315 if (soap->password)
3316 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
3317 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
3319 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
3320 { if (soap->keyfile)
3321 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
3322 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR);
3323 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
3324 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
3327 #endif
3328 if ((soap->ssl_flags & SOAP_SSL_RSA))
3329 { RSA *rsa = RSA_generate_key(SOAP_SSL_RSA_BITS, RSA_F4, NULL, NULL);
3330 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
3331 { if (rsa)
3332 RSA_free(rsa);
3333 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR);
3335 RSA_free(rsa);
3337 else if (soap->dhfile)
3338 { DH *dh = 0;
3339 char *s;
3340 int n = (int)soap_strtoul(soap->dhfile, &s, 10);
3341 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3342 if (n >= 512 && s && *s == '\0')
3343 #if defined(VXWORKS)
3344 DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL);
3345 #else
3346 dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
3347 #endif
3348 else
3349 { BIO *bio;
3350 bio = BIO_new_file(soap->dhfile, "r");
3351 if (!bio)
3352 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR);
3353 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3354 BIO_free(bio);
3356 if (!dh || DH_check(dh, &n) != 1 || SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
3357 { if (dh)
3358 DH_free(dh);
3359 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR);
3361 DH_free(dh);
3363 flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); /* disable SSL v2 */
3364 if ((soap->ssl_flags & SOAP_SSLv3))
3365 flags |= SSL_OP_NO_TLSv1;
3366 if ((soap->ssl_flags & SOAP_TLSv1))
3367 flags |= SSL_OP_NO_SSLv3;
3368 #ifdef SSL_OP_NO_TICKET
3369 /* TLS extension is enabled by default in OPENSSL v0.9.8k
3370 Disable it by adding SSL_OP_NO_TICKET */
3371 flags |= SSL_OP_NO_TICKET;
3372 #endif
3373 SSL_CTX_set_options(soap->ctx, flags);
3374 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3375 mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
3376 else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
3377 mode = SSL_VERIFY_PEER;
3378 else
3379 mode = SSL_VERIFY_NONE;
3380 SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
3381 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
3382 SSL_CTX_set_verify_depth(soap->ctx, 1);
3383 #else
3384 SSL_CTX_set_verify_depth(soap->ctx, 9);
3385 #endif
3386 #endif
3387 #ifdef WITH_GNUTLS
3388 int ret;
3389 if (!soap_ssl_init_done)
3390 soap_ssl_init();
3391 if (!soap->xcred)
3392 { gnutls_certificate_allocate_credentials(&soap->xcred);
3393 if (soap->cafile)
3394 { if (gnutls_certificate_set_x509_trust_file(soap->xcred, soap->cafile, GNUTLS_X509_FMT_PEM) < 0)
3395 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR);
3397 if (soap->crlfile)
3398 { if (gnutls_certificate_set_x509_crl_file(soap->xcred, soap->crlfile, GNUTLS_X509_FMT_PEM) < 0)
3399 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR);
3401 if (soap->keyfile)
3402 { if (gnutls_certificate_set_x509_key_file(soap->xcred, soap->keyfile, soap->keyfile, GNUTLS_X509_FMT_PEM) < 0) /* TODO: GNUTLS need to concat cert and key in single key file */
3403 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
3406 if ((soap->ssl_flags & SOAP_SSL_CLIENT))
3407 { gnutls_init(&soap->session, GNUTLS_CLIENT);
3408 if (soap->cafile || soap->crlfile || soap->keyfile)
3409 { ret = gnutls_priority_set_direct(soap->session, "PERFORMANCE", NULL);
3410 if (ret < 0)
3411 return soap_set_receiver_error(soap, soap_ssl_error(soap, ret), "SSL/TLS set priority error", SOAP_SSL_ERROR);
3412 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
3414 else
3415 { if (!soap->acred)
3416 gnutls_anon_allocate_client_credentials(&soap->acred);
3417 gnutls_init(&soap->session, GNUTLS_CLIENT);
3418 gnutls_priority_set_direct(soap->session, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL);
3419 gnutls_credentials_set(soap->session, GNUTLS_CRD_ANON, soap->acred);
3422 else
3423 { if (!soap->keyfile)
3424 return soap_set_receiver_error(soap, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR);
3425 if ((soap->ssl_flags & SOAP_SSL_RSA) && soap->rsa_params)
3426 gnutls_certificate_set_rsa_export_params(soap->xcred, soap->rsa_params);
3427 else if (soap->dh_params)
3428 gnutls_certificate_set_dh_params(soap->xcred, soap->dh_params);
3429 if (!soap->cache)
3430 gnutls_priority_init(&soap->cache, "NORMAL", NULL);
3431 gnutls_init(&soap->session, GNUTLS_SERVER);
3432 gnutls_priority_set(soap->session, soap->cache);
3433 gnutls_credentials_set(soap->session, GNUTLS_CRD_CERTIFICATE, soap->xcred);
3434 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3435 gnutls_certificate_server_set_request(soap->session, GNUTLS_CERT_REQUEST);
3436 gnutls_session_enable_compatibility_mode(soap->session);
3437 if ((soap->ssl_flags & SOAP_TLSv1))
3438 { int protocol_priority[] = { GNUTLS_TLS1_0, 0 };
3439 if (gnutls_protocol_set_priority(soap->session, protocol_priority) != GNUTLS_E_SUCCESS)
3440 return soap_set_receiver_error(soap, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR);
3443 #endif
3444 return SOAP_OK;
3446 #endif
3447 #endif
3449 /******************************************************************************/
3450 #ifdef WITH_OPENSSL
3451 #ifndef PALM_1
3452 static int
3453 ssl_password(char *buf, int num, int rwflag, void *userdata)
3454 { if (num < (int)strlen((char*)userdata) + 1)
3455 return 0;
3456 return (int)strlen(strcpy(buf, (char*)userdata));
3458 #endif
3459 #endif
3461 /******************************************************************************/
3462 #ifdef WITH_OPENSSL
3463 #ifndef PALM_1
3464 static int
3465 ssl_verify_callback(int ok, X509_STORE_CTX *store)
3467 #ifdef SOAP_DEBUG
3468 if (!ok)
3469 { char buf[1024];
3470 int err = X509_STORE_CTX_get_error(store);
3471 X509 *cert = X509_STORE_CTX_get_current_cert(store);
3472 fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(err));
3473 X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
3474 fprintf(stderr, "certificate issuer %s\n", buf);
3475 X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
3476 fprintf(stderr, "certificate subject %s\n", buf);
3477 /* accept self signed certificates and certificates out of date */
3478 switch (err)
3479 { case X509_V_ERR_CERT_NOT_YET_VALID:
3480 case X509_V_ERR_CERT_HAS_EXPIRED:
3481 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
3482 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
3483 X509_STORE_CTX_set_error(store, X509_V_OK);
3484 ok = 1;
3487 #endif
3488 /* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */
3489 return ok;
3491 #endif
3492 #endif
3494 /******************************************************************************/
3495 #ifdef WITH_OPENSSL
3496 #ifndef PALM_1
3497 static int
3498 ssl_verify_callback_allow_expired_certificate(int ok, X509_STORE_CTX *store)
3499 { ok = ssl_verify_callback(ok, store);
3500 if (!ok)
3501 { /* accept self signed certificates and certificates out of date */
3502 switch (X509_STORE_CTX_get_error(store))
3503 { case X509_V_ERR_CERT_NOT_YET_VALID:
3504 case X509_V_ERR_CERT_HAS_EXPIRED:
3505 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
3506 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
3507 X509_STORE_CTX_set_error(store, X509_V_OK);
3508 ok = 1;
3511 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3512 return ok;
3514 #endif
3515 #endif
3517 /******************************************************************************/
3518 #ifdef WITH_GNUTLS
3519 static const char *
3520 ssl_verify(struct soap *soap, const char *host)
3521 { unsigned int status;
3522 const char *err = NULL;
3523 int r = gnutls_certificate_verify_peers2(soap->session, &status);
3524 if (r < 0)
3525 err = "Certificate verify error";
3526 else if ((status & GNUTLS_CERT_INVALID))
3527 err = "The certificate is not trusted";
3528 else if ((status & GNUTLS_CERT_SIGNER_NOT_FOUND))
3529 err = "The certificate hasn't got a known issuer";
3530 else if ((status & GNUTLS_CERT_REVOKED))
3531 err = "The certificate has been revoked";
3532 else if (gnutls_certificate_type_get(soap->session) == GNUTLS_CRT_X509)
3533 { gnutls_x509_crt_t cert;
3534 const gnutls_datum_t *cert_list;
3535 unsigned int cert_list_size;
3536 if (gnutls_x509_crt_init(&cert) < 0)
3537 err = "Could not get X509 certificates";
3538 else if ((cert_list = gnutls_certificate_get_peers(soap->session, &cert_list_size)) == NULL)
3539 err = "Could not get X509 certificates";
3540 else if (gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER) < 0)
3541 err = "Error parsing X509 certificate";
3542 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
3543 err = "The certificate has expired";
3544 else if (!(soap->ssl_flags & SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE) && gnutls_x509_crt_get_activation_time(cert) > time(NULL))
3545 err = "The certificate is not yet activated";
3546 else if (host && !(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
3547 { if (!gnutls_x509_crt_check_hostname(cert, host))
3548 err = "Certificate host name mismatch";
3550 gnutls_x509_crt_deinit(cert);
3552 return err;
3554 #endif
3556 /******************************************************************************/
3557 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3558 #ifndef WITH_NOIO
3559 #ifndef PALM_1
3560 SOAP_FMAC1
3562 SOAP_FMAC2
3563 soap_ssl_accept(struct soap *soap)
3564 { SOAP_SOCKET sk = soap->socket;
3565 #ifdef WITH_OPENSSL
3566 BIO *bio;
3567 int retries, r, s;
3568 if (!soap_valid_socket(sk))
3569 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
3570 soap->ssl_flags &= ~SOAP_SSL_CLIENT;
3571 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
3572 return soap->error;
3573 if (!soap->ssl)
3574 { soap->ssl = SSL_new(soap->ctx);
3575 if (!soap->ssl)
3576 return soap_set_receiver_error(soap, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3578 else
3579 SSL_clear(soap->ssl);
3580 bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
3581 SSL_set_bio(soap->ssl, bio, bio);
3582 /* Set SSL sockets to non-blocking */
3583 retries = 0;
3584 if (soap->accept_timeout)
3585 { SOAP_SOCKNONBLOCK(sk)
3586 retries = 10*soap->accept_timeout;
3588 if (retries <= 0)
3589 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
3590 while ((r = SSL_accept(soap->ssl)) <= 0)
3591 { int err;
3592 if (retries-- <= 0)
3593 break;
3594 err = SSL_get_error(soap->ssl, r);
3595 if (err == SSL_ERROR_WANT_ACCEPT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
3596 { if (err == SSL_ERROR_WANT_READ)
3597 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
3598 else
3599 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
3600 if (s < 0)
3601 break;
3603 else
3604 { soap->errnum = soap_socket_errno(sk);
3605 break;
3608 if (r <= 0)
3609 { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3610 soap_closesock(soap);
3611 return SOAP_SSL_ERROR;
3613 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3614 { X509 *peer;
3615 int err;
3616 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3617 { soap_closesock(soap);
3618 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);
3620 peer = SSL_get_peer_certificate(soap->ssl);
3621 if (!peer)
3622 { soap_closesock(soap);
3623 return soap_set_sender_error(soap, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
3625 X509_free(peer);
3627 #endif
3628 #ifdef WITH_GNUTLS
3629 int retries = 0, r;
3630 if (!soap_valid_socket(sk))
3631 return soap_set_receiver_error(soap, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
3632 soap->ssl_flags &= ~SOAP_SSL_CLIENT;
3633 if (!soap->session && (soap->error = soap->fsslauth(soap)))
3634 { soap_closesock(soap);
3635 return soap->error;
3637 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
3638 /* Set SSL sockets to non-blocking */
3639 if (soap->accept_timeout)
3640 { SOAP_SOCKNONBLOCK(sk)
3641 retries = 10*soap->accept_timeout;
3643 if (retries <= 0)
3644 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
3645 while ((r = gnutls_handshake(soap->session)))
3646 { int s;
3647 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
3648 if (retries-- <= 0)
3649 break;
3650 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
3651 { if (!gnutls_record_get_direction(soap->session))
3652 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
3653 else
3654 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
3655 if (s < 0)
3656 break;
3658 else
3659 { soap->errnum = soap_socket_errno(sk);
3660 break;
3663 if (r)
3664 { soap_closesock(soap);
3665 return soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
3667 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3668 { const char *err = ssl_verify(soap, NULL);
3669 if (err)
3670 { soap_closesock(soap);
3671 return soap_set_receiver_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
3674 #endif
3675 if (soap->recv_timeout || soap->send_timeout)
3676 SOAP_SOCKNONBLOCK(sk)
3677 else
3678 SOAP_SOCKBLOCK(sk)
3679 soap->imode |= SOAP_ENC_SSL;
3680 soap->omode |= SOAP_ENC_SSL;
3681 return SOAP_OK;
3683 #endif
3684 #endif
3685 #endif
3687 /******************************************************************************\
3689 * TCP/UDP [SSL/TLS] IPv4 and IPv6
3691 \******************************************************************************/
3693 /******************************************************************************/
3694 #ifndef WITH_NOIO
3695 #ifndef PALM_1
3696 static int
3697 tcp_init(struct soap *soap)
3698 { soap->errmode = 1;
3699 #ifdef WIN32
3700 if (tcp_done)
3701 return 0;
3702 else
3703 { WSADATA w;
3704 if (WSAStartup(MAKEWORD(1, 1), &w))
3705 return -1;
3706 tcp_done = 1;
3708 #endif
3709 return 0;
3711 #endif
3712 #endif
3714 /******************************************************************************/
3715 #ifndef WITH_NOIO
3716 #ifndef PALM_1
3717 static const char*
3718 tcp_error(struct soap *soap)
3719 { register const char *msg = NULL;
3720 switch (soap->errmode)
3721 { case 0:
3722 msg = soap_strerror(soap);
3723 break;
3724 case 1:
3725 msg = "WSAStartup failed";
3726 break;
3727 case 2:
3729 #ifndef WITH_LEAN
3730 msg = soap_code_str(h_error_codes, soap->errnum);
3731 if (!msg)
3732 #endif
3734 #ifdef HAVE_SNPRINTF
3735 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "TCP/UDP IP error %d", soap->errnum);
3736 #else
3737 sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
3738 #endif
3739 msg = soap->msgbuf;
3743 return msg;
3745 #endif
3746 #endif
3748 /******************************************************************************/
3749 #ifndef WITH_IPV6
3750 #ifndef WITH_NOIO
3751 #ifndef PALM_1
3752 static int
3753 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
3754 { soap_int32 iadd = -1;
3755 struct hostent hostent, *host = &hostent;
3756 #ifdef VXWORKS
3757 int hostint;
3758 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3759 iadd = inet_addr((char*)addr);
3760 #else
3761 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3762 struct hostent_data ht_data;
3763 #endif
3764 #ifdef AS400
3765 iadd = inet_addr((void*)addr);
3766 #else
3767 iadd = inet_addr(addr);
3768 #endif
3769 #endif
3770 if (iadd != -1)
3771 { memcpy(inaddr, &iadd, sizeof(iadd));
3772 return SOAP_OK;
3774 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) || defined(__ANDROID__)
3775 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
3776 host = NULL;
3777 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3778 memset((void*)&ht_data, 0, sizeof(ht_data));
3779 if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
3780 { host = NULL;
3781 soap->errnum = h_errno;
3783 #elif defined(HAVE_GETHOSTBYNAME_R)
3784 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
3785 #elif defined(VXWORKS)
3786 /* If the DNS resolver library resolvLib has been configured in the vxWorks
3787 * image, a query for the host IP address is sent to the DNS server, if the
3788 * name was not found in the local host table. */
3789 hostint = hostGetByName((char*)addr);
3790 if (hostint == ERROR)
3791 { host = NULL;
3792 soap->errnum = soap_errno;
3794 #else
3795 #ifdef AS400
3796 if (!(host = gethostbyname((void*)addr)))
3797 soap->errnum = h_errno;
3798 #else
3799 if (!(host = gethostbyname(addr)))
3800 soap->errnum = h_errno;
3801 #endif
3802 #endif
3803 if (!host)
3804 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
3805 return SOAP_ERR;
3807 #ifdef VXWORKS
3808 inaddr->s_addr = hostint;
3809 #else
3810 memcpy(inaddr, host->h_addr, host->h_length);
3811 #endif
3812 return SOAP_OK;
3814 #endif
3815 #endif
3816 #endif
3818 /******************************************************************************/
3819 #ifndef WITH_NOIO
3820 #ifndef PALM_1
3821 static SOAP_SOCKET
3822 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
3824 #ifdef WITH_IPV6
3825 struct addrinfo hints, *res, *ressave;
3826 #endif
3827 SOAP_SOCKET sk;
3828 int err = 0;
3829 #ifndef WITH_LEAN
3830 #ifndef WIN32
3831 int len = SOAP_BUFLEN;
3832 #else
3833 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
3834 #endif
3835 int set = 1;
3836 #endif
3837 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3838 int retries;
3839 #endif
3840 if (soap_valid_socket(soap->socket))
3841 soap->fclosesocket(soap, soap->socket);
3842 soap->socket = SOAP_INVALID_SOCKET;
3843 if (tcp_init(soap))
3844 { soap->errnum = 0;
3845 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
3846 return SOAP_INVALID_SOCKET;
3848 soap->errmode = 0;
3849 #ifdef WITH_IPV6
3850 memset((void*)&hints, 0, sizeof(hints));
3851 hints.ai_family = PF_UNSPEC;
3852 #ifndef WITH_LEAN
3853 if ((soap->omode & SOAP_IO_UDP))
3854 hints.ai_socktype = SOCK_DGRAM;
3855 else
3856 #endif
3857 hints.ai_socktype = SOCK_STREAM;
3858 soap->errmode = 2;
3859 if (soap->proxy_host)
3860 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
3861 else
3862 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
3863 if (err)
3864 { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
3865 return SOAP_INVALID_SOCKET;
3867 ressave = res;
3868 again:
3869 sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
3870 soap->errmode = 0;
3871 #else
3872 #ifndef WITH_LEAN
3873 again:
3874 #endif
3875 #ifndef WITH_LEAN
3876 if ((soap->omode & SOAP_IO_UDP))
3877 sk = socket(AF_INET, SOCK_DGRAM, 0);
3878 else
3879 #endif
3880 sk = socket(AF_INET, SOCK_STREAM, 0);
3881 #endif
3882 if (!soap_valid_socket(sk))
3884 #ifdef WITH_IPV6
3885 if (res->ai_next)
3886 { res = res->ai_next;
3887 goto again;
3889 #endif
3890 soap->errnum = soap_socket_errno(sk);
3891 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
3892 #ifdef WITH_IPV6
3893 freeaddrinfo(ressave);
3894 #endif
3895 return SOAP_INVALID_SOCKET;
3897 #ifdef SOCKET_CLOSE_ON_EXEC
3898 #ifdef WIN32
3899 #ifndef UNDER_CE
3900 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
3901 #endif
3902 #else
3903 fcntl(sk, F_SETFD, 1);
3904 #endif
3905 #endif
3906 #ifndef WITH_LEAN
3907 if (soap->connect_flags == SO_LINGER)
3908 { struct linger linger;
3909 memset((void*)&linger, 0, sizeof(linger));
3910 linger.l_onoff = 1;
3911 linger.l_linger = soap->linger_time;
3912 if (setsockopt(sk, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
3913 { soap->errnum = soap_socket_errno(sk);
3914 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
3915 soap->fclosesocket(soap, sk);
3916 #ifdef WITH_IPV6
3917 freeaddrinfo(ressave);
3918 #endif
3919 return SOAP_INVALID_SOCKET;
3922 else if (soap->connect_flags && setsockopt(sk, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
3923 { soap->errnum = soap_socket_errno(sk);
3924 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
3925 soap->fclosesocket(soap, sk);
3926 #ifdef WITH_IPV6
3927 freeaddrinfo(ressave);
3928 #endif
3929 return SOAP_INVALID_SOCKET;
3931 if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(sk, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
3932 { soap->errnum = soap_socket_errno(sk);
3933 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
3934 soap->fclosesocket(soap, sk);
3935 #ifdef WITH_IPV6
3936 freeaddrinfo(ressave);
3937 #endif
3938 return SOAP_INVALID_SOCKET;
3940 if (setsockopt(sk, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
3941 { soap->errnum = soap_socket_errno(sk);
3942 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3943 soap->fclosesocket(soap, sk);
3944 #ifdef WITH_IPV6
3945 freeaddrinfo(ressave);
3946 #endif
3947 return SOAP_INVALID_SOCKET;
3949 if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
3950 { soap->errnum = soap_socket_errno(sk);
3951 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3952 soap->fclosesocket(soap, sk);
3953 #ifdef WITH_IPV6
3954 freeaddrinfo(ressave);
3955 #endif
3956 return SOAP_INVALID_SOCKET;
3958 #ifdef TCP_KEEPIDLE
3959 if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPIDLE, (char*)&(soap->tcp_keep_idle), sizeof(int)))
3960 { soap->errnum = soap_socket_errno(sk);
3961 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
3962 soap->fclosesocket(soap, (SOAP_SOCKET)sk);
3963 #ifdef WITH_IPV6
3964 freeaddrinfo(ressave);
3965 #endif
3966 return SOAP_INVALID_SOCKET;
3968 #endif
3969 #ifdef TCP_KEEPINTVL
3970 if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPINTVL, (char*)&(soap->tcp_keep_intvl), sizeof(int)))
3971 { soap->errnum = soap_socket_errno(sk);
3972 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
3973 soap->fclosesocket(soap, (SOAP_SOCKET)sk);
3974 #ifdef WITH_IPV6
3975 freeaddrinfo(ressave);
3976 #endif
3977 return SOAP_INVALID_SOCKET;
3979 #endif
3980 #ifdef TCP_KEEPCNT
3981 if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)sk, IPPROTO_TCP, TCP_KEEPCNT, (char*)&(soap->tcp_keep_cnt), sizeof(int)))
3982 { soap->errnum = soap_socket_errno(sk);
3983 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
3984 soap->fclosesocket(soap, (SOAP_SOCKET)sk);
3985 #ifdef WITH_IPV6
3986 freeaddrinfo(ressave);
3987 #endif
3988 return SOAP_INVALID_SOCKET;
3990 #endif
3991 #ifdef TCP_NODELAY
3992 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(sk, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
3993 { soap->errnum = soap_socket_errno(sk);
3994 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
3995 soap->fclosesocket(soap, sk);
3996 #ifdef WITH_IPV6
3997 freeaddrinfo(ressave);
3998 #endif
3999 return SOAP_INVALID_SOCKET;
4001 #endif
4002 #ifdef WITH_IPV6
4003 if ((soap->omode & SOAP_IO_UDP) && soap->ipv6_multicast_if)
4004 { struct sockaddr_in6 *in6addr = (struct sockaddr_in6*)res->ai_addr;
4005 in6addr->sin6_scope_id = soap->ipv6_multicast_if;
4007 #endif
4008 #ifdef IP_MULTICAST_TTL
4009 if ((soap->omode & SOAP_IO_UDP))
4010 { if (soap->ipv4_multicast_ttl)
4011 { unsigned char ttl = soap->ipv4_multicast_ttl;
4012 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&ttl, sizeof(ttl)))
4013 { soap->errnum = soap_socket_errno(sk);
4014 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR);
4015 soap->fclosesocket(soap, sk);
4016 return SOAP_INVALID_SOCKET;
4019 if ((soap->omode & SOAP_IO_UDP) && soap->ipv4_multicast_if && !soap->ipv6_multicast_if)
4020 { if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
4021 #ifndef WINDOWS
4022 { soap->errnum = soap_socket_errno(sk);
4023 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
4024 soap->fclosesocket(soap, sk);
4025 return SOAP_INVALID_SOCKET;
4027 #else
4028 #ifndef IP_MULTICAST_IF
4029 #define IP_MULTICAST_IF 2
4030 #endif
4031 if (setsockopt(sk, IPPROTO_IP, IP_MULTICAST_IF, (char*)soap->ipv4_multicast_if, sizeof(struct in_addr)))
4032 { soap->errnum = soap_socket_errno(sk);
4033 soap_set_sender_error(soap, tcp_error(soap), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR);
4034 soap->fclosesocket(soap, sk);
4035 return SOAP_INVALID_SOCKET;
4037 #endif
4040 #endif
4041 #endif
4042 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", sk, host, port));
4043 #ifndef WITH_IPV6
4044 soap->peerlen = sizeof(soap->peer);
4045 memset((void*)&soap->peer, 0, sizeof(soap->peer));
4046 soap->peer.sin_family = AF_INET;
4047 soap->errmode = 2;
4048 if (soap->proxy_host)
4049 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
4050 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
4051 soap->fclosesocket(soap, sk);
4052 return SOAP_INVALID_SOCKET;
4054 soap->peer.sin_port = htons((short)soap->proxy_port);
4056 else
4057 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
4058 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
4059 soap->fclosesocket(soap, sk);
4060 return SOAP_INVALID_SOCKET;
4062 soap->peer.sin_port = htons((short)port);
4064 soap->errmode = 0;
4065 #ifndef WITH_LEAN
4066 if ((soap->omode & SOAP_IO_UDP))
4067 return sk;
4068 #endif
4069 #else
4070 if ((soap->omode & SOAP_IO_UDP))
4071 { memcpy(&soap->peer, res->ai_addr, res->ai_addrlen);
4072 soap->peerlen = res->ai_addrlen;
4073 freeaddrinfo(ressave);
4074 return sk;
4076 #endif
4077 #ifndef WITH_LEAN
4078 if (soap->connect_timeout)
4079 SOAP_SOCKNONBLOCK(sk)
4080 else
4081 SOAP_SOCKBLOCK(sk)
4082 retries = 10;
4083 #endif
4084 for (;;)
4086 #ifdef WITH_IPV6
4087 if (connect(sk, res->ai_addr, (int)res->ai_addrlen))
4088 #else
4089 if (connect(sk, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
4090 #endif
4091 { err = soap_socket_errno(sk);
4092 #ifndef WITH_LEAN
4093 if (err == SOAP_EADDRINUSE)
4094 { soap->fclosesocket(soap, sk);
4095 if (retries-- > 0)
4096 goto again;
4098 else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK))
4100 SOAP_SOCKLEN_T k;
4101 for (;;)
4102 { register int r;
4103 r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND, soap->connect_timeout);
4104 if (r > 0)
4105 break;
4106 if (!r)
4107 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
4108 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
4109 soap->fclosesocket(soap, sk);
4110 #ifdef WITH_IPV6
4111 freeaddrinfo(ressave);
4112 #endif
4113 return SOAP_INVALID_SOCKET;
4115 r = soap->errnum = soap_socket_errno(sk);
4116 if (r != SOAP_EINTR)
4117 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
4118 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
4119 soap->fclosesocket(soap, sk);
4120 #ifdef WITH_IPV6
4121 freeaddrinfo(ressave);
4122 #endif
4123 return SOAP_INVALID_SOCKET;
4126 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
4127 if (!getsockopt(sk, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4128 break;
4129 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
4130 if (!soap->errnum)
4131 soap->errnum = soap_socket_errno(sk);
4132 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
4133 soap->fclosesocket(soap, sk);
4134 #ifdef WITH_IPV6
4135 freeaddrinfo(ressave);
4136 #endif
4137 return SOAP_INVALID_SOCKET;
4139 #endif
4140 #ifdef WITH_IPV6
4141 if (res->ai_next)
4142 { res = res->ai_next;
4143 soap->fclosesocket(soap, sk);
4144 goto again;
4146 #endif
4147 if (err && err != SOAP_EINTR)
4148 { soap->errnum = err;
4149 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
4150 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
4151 soap->fclosesocket(soap, sk);
4152 #ifdef WITH_IPV6
4153 freeaddrinfo(ressave);
4154 #endif
4155 return SOAP_INVALID_SOCKET;
4158 else
4159 break;
4161 #ifdef WITH_IPV6
4162 soap->peerlen = 0; /* IPv6: already connected so use send() */
4163 freeaddrinfo(ressave);
4164 #endif
4165 soap->socket = sk;
4166 soap->imode &= ~SOAP_ENC_SSL;
4167 soap->omode &= ~SOAP_ENC_SSL;
4168 if (!soap_tag_cmp(endpoint, "https:*"))
4170 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
4171 #ifdef WITH_OPENSSL
4172 BIO *bio;
4173 #endif
4174 int r;
4175 if (soap->proxy_host)
4176 { soap_mode m = soap->mode; /* preserve settings */
4177 soap_mode om = soap->omode; /* make sure we only parse HTTP */
4178 size_t n = soap->count; /* save the content length */
4179 const char *userid, *passwd;
4180 int status = soap->status; /* save the current status/command */
4181 short keep_alive = soap->keep_alive; /* save the KA status */
4182 soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
4183 soap->omode |= SOAP_IO_BUFFER;
4184 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint));
4185 #ifdef WITH_NTLM
4186 if (soap->ntlm_challenge)
4187 { if (soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port))
4188 return soap->error;
4190 #endif
4191 if (soap_begin_send(soap))
4192 { soap->fclosesocket(soap, sk);
4193 return SOAP_INVALID_SOCKET;
4195 soap->status = SOAP_CONNECT;
4196 soap->keep_alive = 1;
4197 if ((soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0))
4198 || soap_end_send_flush(soap))
4199 { soap->fclosesocket(soap, sk);
4200 return SOAP_INVALID_SOCKET;
4202 soap->keep_alive = keep_alive;
4203 soap->omode = om;
4204 om = soap->imode;
4205 soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
4206 userid = soap->userid; /* preserve */
4207 passwd = soap->passwd; /* preserve */
4208 if ((soap->error = soap->fparse(soap)))
4209 { soap->fclosesocket(soap, sk);
4210 return SOAP_INVALID_SOCKET;
4212 soap->status = status; /* restore */
4213 soap->userid = userid; /* restore */
4214 soap->passwd = passwd; /* restore */
4215 soap->imode = om; /* restore */
4216 soap->count = n; /* restore */
4217 if (soap_begin_send(soap))
4218 { soap->fclosesocket(soap, sk);
4219 return SOAP_INVALID_SOCKET;
4221 if (endpoint)
4222 { strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); /* restore */
4223 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
4225 soap->mode = m;
4227 #ifdef WITH_OPENSSL
4228 soap->ssl_flags |= SOAP_SSL_CLIENT;
4229 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
4230 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL required, but no ctx set\n"));
4231 soap->fclosesocket(soap, sk);
4232 soap->error = SOAP_SSL_ERROR;
4233 return SOAP_INVALID_SOCKET;
4235 if (!soap->ssl)
4236 { soap->ssl = SSL_new(soap->ctx);
4237 if (!soap->ssl)
4238 { soap->fclosesocket(soap, sk);
4239 soap->error = SOAP_SSL_ERROR;
4240 return SOAP_INVALID_SOCKET;
4243 else
4244 SSL_clear(soap->ssl);
4245 if (soap->session)
4246 { if (!strcmp(soap->session_host, host) && soap->session_port == port)
4247 SSL_set_session(soap->ssl, soap->session);
4248 SSL_SESSION_free(soap->session);
4249 soap->session = NULL;
4251 soap->imode |= SOAP_ENC_SSL;
4252 soap->omode |= SOAP_ENC_SSL;
4253 bio = BIO_new_socket((int)sk, BIO_NOCLOSE);
4254 SSL_set_bio(soap->ssl, bio, bio);
4255 /* Connect timeout: set SSL sockets to non-blocking */
4256 retries = 0;
4257 if (soap->connect_timeout)
4258 { SOAP_SOCKNONBLOCK(sk)
4259 retries = 10*soap->connect_timeout;
4261 else
4262 SOAP_SOCKBLOCK(sk)
4263 if (retries <= 0)
4264 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
4265 /* Try connecting until success or timeout (when nonblocking) */
4267 { if ((r = SSL_connect(soap->ssl)) <= 0)
4268 { int err = SSL_get_error(soap->ssl, r);
4269 if (err == SSL_ERROR_WANT_CONNECT || err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
4270 { register int s;
4271 if (err == SSL_ERROR_WANT_READ)
4272 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
4273 else
4274 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
4275 if (s < 0)
4276 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
4277 soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
4278 soap->fclosesocket(soap, sk);
4279 return SOAP_INVALID_SOCKET;
4281 if (s == 0 && retries-- <= 0)
4282 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL/TLS connect timeout\n"));
4283 soap_set_sender_error(soap, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
4284 soap->fclosesocket(soap, sk);
4285 return SOAP_INVALID_SOCKET;
4288 else
4289 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR);
4290 soap->fclosesocket(soap, sk);
4291 return SOAP_INVALID_SOCKET;
4294 } while (!SSL_is_init_finished(soap->ssl));
4295 /* Set SSL sockets to nonblocking */
4296 SOAP_SOCKNONBLOCK(sk)
4297 /* Check server credentials when required */
4298 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
4299 { int err;
4300 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
4301 { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
4302 soap->fclosesocket(soap, sk);
4303 return SOAP_INVALID_SOCKET;
4305 if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
4306 { X509_NAME *subj;
4307 STACK_OF(CONF_VALUE) *val = NULL;
4308 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
4309 GENERAL_NAMES *names = NULL;
4310 #else
4311 int ext_count;
4312 #endif
4313 int ok = 0;
4314 X509 *peer = SSL_get_peer_certificate(soap->ssl);
4315 if (!peer)
4316 { soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
4317 soap->fclosesocket(soap, sk);
4318 return SOAP_INVALID_SOCKET;
4320 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL)
4321 ext_count = X509_get_ext_count(peer);
4322 if (ext_count > 0)
4323 { int i;
4324 for (i = 0; i < ext_count; i++)
4325 { X509_EXTENSION *ext = X509_get_ext(peer, i);
4326 const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
4327 if (ext_str && !strcmp(ext_str, "subjectAltName"))
4328 { X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
4329 unsigned char *data;
4330 if (!meth)
4331 break;
4332 data = ext->value->data;
4333 if (data)
4335 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4336 void *ext_data;
4337 if (meth->it)
4338 ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
4339 else
4340 { /* OpenSSL is not portable at this point (?):
4341 Some compilers appear to prefer
4342 meth->d2i(NULL, (const unsigned char**)&data, ...
4343 and others prefer
4344 meth->d2i(NULL, &data, ext->value->length);
4346 ext_data = meth->d2i(NULL, &data, ext->value->length);
4348 if (ext_data)
4349 val = meth->i2v(meth, ext_data, NULL);
4350 else
4351 val = NULL;
4352 if (meth->it)
4353 ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
4354 else
4355 meth->ext_free(ext_data);
4356 #else
4357 void *ext_data = meth->d2i(NULL, &data, ext->value->length);
4358 if (ext_data)
4359 val = meth->i2v(meth, ext_data, NULL);
4360 meth->ext_free(ext_data);
4361 #endif
4362 if (val)
4363 { int j;
4364 for (j = 0; j < sk_CONF_VALUE_num(val); j++)
4365 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
4366 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
4367 { ok = 1;
4368 break;
4371 sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
4375 if (ok)
4376 break;
4379 #else
4380 names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
4381 if (names)
4382 { val = i2v_GENERAL_NAMES(NULL, names, val);
4383 sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
4385 if (val)
4386 { int j;
4387 for (j = 0; j < sk_CONF_VALUE_num(val); j++)
4388 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
4389 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
4390 { ok = 1;
4391 break;
4394 sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
4396 #endif
4397 if (!ok && (subj = X509_get_subject_name(peer)))
4398 { int i = -1;
4400 { ASN1_STRING *name;
4401 i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
4402 if (i == -1)
4403 break;
4404 name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
4405 if (name)
4406 { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name)))
4407 ok = 1;
4408 else
4409 { unsigned char *tmp = NULL;
4410 ASN1_STRING_to_UTF8(&tmp, name);
4411 if (tmp)
4412 { if (!soap_tag_cmp(host, (const char*)tmp))
4413 ok = 1;
4414 else if (tmp[0] == '*') /* wildcard domain */
4415 { const char *t = strchr(host, '.');
4416 if (t && !soap_tag_cmp(t, (const char*)tmp+1))
4417 ok = 1;
4419 OPENSSL_free(tmp);
4423 } while (!ok);
4425 X509_free(peer);
4426 if (!ok)
4427 { soap_set_sender_error(soap, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
4428 soap->fclosesocket(soap, sk);
4429 return SOAP_INVALID_SOCKET;
4433 #endif
4434 #ifdef WITH_GNUTLS
4435 soap->ssl_flags |= SOAP_SSL_CLIENT;
4436 if (!soap->session && (soap->error = soap->fsslauth(soap)))
4437 { soap->fclosesocket(soap, sk);
4438 return SOAP_INVALID_SOCKET;
4440 gnutls_transport_set_ptr(soap->session, (gnutls_transport_ptr_t)(long)sk);
4441 /* Set SSL sockets to non-blocking */
4442 if (soap->connect_timeout)
4443 { SOAP_SOCKNONBLOCK(sk)
4444 retries = 10*soap->connect_timeout;
4446 else
4447 SOAP_SOCKBLOCK(sk)
4448 if (retries <= 0)
4449 retries = 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
4450 while ((r = gnutls_handshake(soap->session)))
4451 { int s;
4452 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
4453 if (retries-- <= 0)
4454 break;
4455 if (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED)
4456 { if (!gnutls_record_get_direction(soap->session))
4457 s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
4458 else
4459 s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
4460 if (s < 0)
4461 break;
4463 else
4464 { soap->errnum = soap_socket_errno(sk);
4465 break;
4468 if (r)
4469 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL/TLS handshake failed", SOAP_SSL_ERROR);
4470 soap->fclosesocket(soap, sk);
4471 return SOAP_INVALID_SOCKET;
4473 if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
4474 { const char *err = ssl_verify(soap, host);
4475 if (err)
4476 { soap->fclosesocket(soap, sk);
4477 soap->error = soap_set_sender_error(soap, "SSL/TLS error", err, SOAP_SSL_ERROR);
4478 return SOAP_INVALID_SOCKET;
4481 #endif
4482 #else
4483 soap->fclosesocket(soap, sk);
4484 soap->error = SOAP_SSL_ERROR;
4485 return SOAP_INVALID_SOCKET;
4486 #endif
4488 if (soap->recv_timeout || soap->send_timeout)
4489 SOAP_SOCKNONBLOCK(sk)
4490 else
4491 SOAP_SOCKBLOCK(sk)
4492 return sk;
4494 #endif
4495 #endif
4497 /******************************************************************************/
4498 #ifndef WITH_NOIO
4499 #ifndef PALM_1
4500 static int
4501 tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
4502 { int r;
4503 struct timeval tv;
4504 fd_set fd[3], *rfd, *sfd, *efd;
4505 int retries = 0;
4506 int eintr = SOAP_MAXEINTR;
4507 soap->errnum = 0;
4508 #ifndef WIN32
4509 #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
4510 /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */
4511 if (1)
4512 #else
4513 /* if fd max set size exceeded, use poll() */
4514 if ((int)sk >= (int)FD_SETSIZE)
4515 #endif
4516 #ifdef HAVE_POLL
4517 { struct pollfd pollfd;
4518 pollfd.fd = (int)sk;
4519 pollfd.events = 0;
4520 if (flags & SOAP_TCP_SELECT_RCV)
4521 pollfd.events |= POLLIN;
4522 if (flags & SOAP_TCP_SELECT_SND)
4523 pollfd.events |= POLLOUT;
4524 if (flags & SOAP_TCP_SELECT_ERR)
4525 pollfd.events |= POLLERR;
4526 if (timeout <= 0)
4527 timeout /= -1000; /* -usec -> ms */
4528 else
4529 { retries = timeout - 1;
4530 timeout = 1000;
4533 { r = poll(&pollfd, 1, timeout);
4534 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
4535 continue;
4536 } while (r == 0 && retries--);
4537 if (r > 0)
4538 { r = 0;
4539 if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN))
4540 r |= SOAP_TCP_SELECT_RCV;
4541 if ((flags & SOAP_TCP_SELECT_SND) && (pollfd.revents & POLLOUT))
4542 r |= SOAP_TCP_SELECT_SND;
4543 if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR))
4544 r |= SOAP_TCP_SELECT_ERR;
4546 return r;
4548 #else
4549 { soap->error = SOAP_FD_EXCEEDED;
4550 return -1;
4552 #endif
4553 #endif
4554 if (timeout > 0)
4555 retries = timeout - 1;
4557 { rfd = sfd = efd = NULL;
4558 if (flags & SOAP_TCP_SELECT_RCV)
4559 { rfd = &fd[0];
4560 FD_ZERO(rfd);
4561 FD_SET(sk, rfd);
4563 if (flags & SOAP_TCP_SELECT_SND)
4564 { sfd = &fd[1];
4565 FD_ZERO(sfd);
4566 FD_SET(sk, sfd);
4568 if (flags & SOAP_TCP_SELECT_ERR)
4569 { efd = &fd[2];
4570 FD_ZERO(efd);
4571 FD_SET(sk, efd);
4573 if (timeout <= 0)
4574 { tv.tv_sec = -timeout / 1000000;
4575 tv.tv_usec = -timeout % 1000000;
4577 else
4578 { tv.tv_sec = 1;
4579 tv.tv_usec = 0;
4581 r = select((int)sk + 1, rfd, sfd, efd, &tv);
4582 if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
4583 continue;
4584 } while (r == 0 && retries--);
4585 if (r > 0)
4586 { r = 0;
4587 if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd))
4588 r |= SOAP_TCP_SELECT_RCV;
4589 if ((flags & SOAP_TCP_SELECT_SND) && FD_ISSET(sk, sfd))
4590 r |= SOAP_TCP_SELECT_SND;
4591 if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd))
4592 r |= SOAP_TCP_SELECT_ERR;
4594 return r;
4596 #endif
4597 #endif
4599 /******************************************************************************/
4600 #ifndef WITH_NOIO
4601 #ifndef PALM_1
4602 static SOAP_SOCKET
4603 tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
4604 { SOAP_SOCKET sk;
4605 (void)soap;
4606 sk = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4607 #ifdef SOCKET_CLOSE_ON_EXEC
4608 #ifdef WIN32
4609 #ifndef UNDER_CE
4610 SetHandleInformation((HANDLE)sk, HANDLE_FLAG_INHERIT, 0);
4611 #endif
4612 #else
4613 fcntl(sk, F_SETFD, FD_CLOEXEC);
4614 #endif
4615 #endif
4616 return sk;
4618 #endif
4619 #endif
4621 /******************************************************************************/
4622 #ifndef WITH_NOIO
4623 #ifndef PALM_1
4624 static int
4625 tcp_disconnect(struct soap *soap)
4627 #ifdef WITH_OPENSSL
4628 if (soap->ssl)
4629 { int r, s = 0;
4630 if (soap->session)
4631 { SSL_SESSION_free(soap->session);
4632 soap->session = NULL;
4634 if (*soap->host)
4635 { soap->session = SSL_get1_session(soap->ssl);
4636 if (soap->session)
4637 { strcpy(soap->session_host, soap->host);
4638 soap->session_port = soap->port;
4641 r = SSL_shutdown(soap->ssl);
4642 /* SSL shutdown does not work when reads are pending, non-blocking */
4643 if (r == 0)
4644 { while (SSL_want_read(soap->ssl))
4645 { if (SSL_read(soap->ssl, NULL, 0)
4646 || soap_socket_errno(soap->socket) != SOAP_EAGAIN)
4647 { r = SSL_shutdown(soap->ssl);
4648 break;
4652 if (r == 0)
4653 { if (soap_valid_socket(soap->socket))
4654 { if (!soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR))
4656 #if !defined(WITH_LEAN) && !defined(WIN32)
4658 wait up to 5 seconds for close_notify to be sent by peer (if peer not
4659 present, this avoids calling SSL_shutdown() which has a lengthy return
4660 timeout)
4662 r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5);
4663 if (r <= 0)
4664 { soap->errnum = 0;
4665 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
4666 soap->fclosesocket(soap, soap->socket);
4667 soap->socket = SOAP_INVALID_SOCKET;
4668 ERR_remove_state(0);
4669 SSL_free(soap->ssl);
4670 soap->ssl = NULL;
4671 return SOAP_OK;
4673 #else
4674 r = SSL_shutdown(soap->ssl);
4675 #endif
4679 if (r != 1)
4680 { s = ERR_get_error();
4681 if (s)
4682 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
4683 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4684 { soap->fclosesocket(soap, soap->socket);
4685 soap->socket = SOAP_INVALID_SOCKET;
4689 SSL_free(soap->ssl);
4690 soap->ssl = NULL;
4691 if (s)
4692 return SOAP_SSL_ERROR;
4693 ERR_remove_state(0);
4695 #endif
4696 #ifdef WITH_GNUTLS
4697 if (soap->session)
4698 { gnutls_bye(soap->session, GNUTLS_SHUT_RDWR);
4699 gnutls_deinit(soap->session);
4700 soap->session = NULL;
4702 #endif
4703 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4704 { soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_RDWR);
4705 soap->fclosesocket(soap, soap->socket);
4706 soap->socket = SOAP_INVALID_SOCKET;
4708 return SOAP_OK;
4710 #endif
4711 #endif
4713 /******************************************************************************/
4714 #ifndef WITH_NOIO
4715 #ifndef PALM_1
4716 static int
4717 tcp_closesocket(struct soap *soap, SOAP_SOCKET sk)
4718 { (void)soap;
4719 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk));
4720 return soap_closesocket(sk);
4722 #endif
4723 #endif
4725 /******************************************************************************/
4726 #ifndef WITH_NOIO
4727 #ifndef PALM_1
4728 static int
4729 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how)
4730 { (void)soap;
4731 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how));
4732 return shutdown(sk, how);
4734 #endif
4735 #endif
4737 /******************************************************************************/
4738 #ifndef WITH_NOIO
4739 #ifndef PALM_1
4740 SOAP_FMAC1
4741 SOAP_SOCKET
4742 SOAP_FMAC2
4743 soap_bind(struct soap *soap, const char *host, int port, int backlog)
4745 #ifdef WITH_IPV6
4746 struct addrinfo *addrinfo = NULL;
4747 struct addrinfo hints;
4748 struct addrinfo res;
4749 int err;
4750 #ifdef WITH_NO_IPV6_V6ONLY
4751 int unset = 0;
4752 #endif
4753 #endif
4754 #ifndef WITH_LEAN
4755 #ifndef WIN32
4756 int len = SOAP_BUFLEN;
4757 #else
4758 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
4759 #endif
4760 int set = 1;
4761 #endif
4762 if (soap_valid_socket(soap->master))
4763 { soap->fclosesocket(soap, soap->master);
4764 soap->master = SOAP_INVALID_SOCKET;
4766 soap->socket = SOAP_INVALID_SOCKET;
4767 soap->errmode = 1;
4768 if (tcp_init(soap))
4769 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
4770 return SOAP_INVALID_SOCKET;
4772 #ifdef WITH_IPV6
4773 memset((void*)&hints, 0, sizeof(hints));
4774 hints.ai_family = PF_UNSPEC;
4775 #ifndef WITH_LEAN
4776 if ((soap->omode & SOAP_IO_UDP))
4777 hints.ai_socktype = SOCK_DGRAM;
4778 else
4779 #endif
4780 hints.ai_socktype = SOCK_STREAM;
4781 hints.ai_flags = AI_PASSIVE;
4782 soap->errmode = 2;
4783 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
4784 if (err || !addrinfo)
4785 { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
4786 return SOAP_INVALID_SOCKET;
4788 res = *addrinfo;
4789 memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
4790 soap->peerlen = addrinfo->ai_addrlen;
4791 res.ai_addr = (struct sockaddr*)&soap->peer;
4792 res.ai_addrlen = soap->peerlen;
4793 freeaddrinfo(addrinfo);
4794 soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
4795 #else
4796 #ifndef WITH_LEAN
4797 if ((soap->omode & SOAP_IO_UDP))
4798 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
4799 else
4800 #endif
4801 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
4802 #endif
4803 soap->errmode = 0;
4804 if (!soap_valid_socket(soap->master))
4805 { soap->errnum = soap_socket_errno(soap->master);
4806 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
4807 return SOAP_INVALID_SOCKET;
4809 soap->port = port;
4810 #ifndef WITH_LEAN
4811 if ((soap->omode & SOAP_IO_UDP))
4812 soap->socket = soap->master;
4813 #endif
4814 #ifdef SOCKET_CLOSE_ON_EXEC
4815 #ifdef WIN32
4816 #ifndef UNDER_CE
4817 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
4818 #endif
4819 #else
4820 fcntl(soap->master, F_SETFD, 1);
4821 #endif
4822 #endif
4823 #ifndef WITH_LEAN
4824 if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
4825 { soap->errnum = soap_socket_errno(soap->master);
4826 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
4827 return SOAP_INVALID_SOCKET;
4829 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && (!((soap->imode | soap->omode) & SOAP_IO_UDP)) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4830 { soap->errnum = soap_socket_errno(soap->master);
4831 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
4832 return SOAP_INVALID_SOCKET;
4834 if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4835 { soap->errnum = soap_socket_errno(soap->master);
4836 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
4837 return SOAP_INVALID_SOCKET;
4839 if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4840 { soap->errnum = soap_socket_errno(soap->master);
4841 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
4842 return SOAP_INVALID_SOCKET;
4844 #ifdef TCP_NODELAY
4845 if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4846 { soap->errnum = soap_socket_errno(soap->master);
4847 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
4848 return SOAP_INVALID_SOCKET;
4850 #endif
4851 #endif
4852 #ifdef WITH_IPV6
4853 #ifdef WITH_IPV6_V6ONLY
4854 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&set, sizeof(int)))
4855 { soap->errnum = soap_socket_errno(soap->master);
4856 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt set IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
4857 return SOAP_INVALID_SOCKET;
4859 #endif
4860 #ifdef WITH_NO_IPV6_V6ONLY
4861 if (setsockopt(soap->master, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&unset, sizeof(int)))
4862 { soap->errnum = soap_socket_errno(soap->master);
4863 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt unset IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR);
4864 return SOAP_INVALID_SOCKET;
4866 #endif
4867 soap->errmode = 0;
4868 if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
4869 { soap->errnum = soap_socket_errno(soap->master);
4870 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4871 soap_closesock(soap);
4872 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
4873 return SOAP_INVALID_SOCKET;
4875 #else
4876 soap->peerlen = sizeof(soap->peer);
4877 memset((void*)&soap->peer, 0, sizeof(soap->peer));
4878 soap->peer.sin_family = AF_INET;
4879 soap->errmode = 2;
4880 if (host)
4881 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
4882 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
4883 return SOAP_INVALID_SOCKET;
4886 else
4887 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
4888 soap->peer.sin_port = htons((short)port);
4889 soap->errmode = 0;
4890 if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
4891 { soap->errnum = soap_socket_errno(soap->master);
4892 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4893 soap_closesock(soap);
4894 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
4895 return SOAP_INVALID_SOCKET;
4897 #endif
4898 if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
4899 { soap->errnum = soap_socket_errno(soap->master);
4900 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4901 soap_closesock(soap);
4902 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
4903 return SOAP_INVALID_SOCKET;
4905 return soap->master;
4907 #endif
4908 #endif
4910 /******************************************************************************/
4911 #ifndef WITH_NOIO
4912 #ifndef PALM_1
4913 SOAP_FMAC1
4915 SOAP_FMAC2
4916 soap_poll(struct soap *soap)
4918 #ifndef WITH_LEAN
4919 register int r;
4920 if (soap_valid_socket(soap->socket))
4921 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_ALL, 0);
4922 if (r > 0 && (r & SOAP_TCP_SELECT_ERR))
4923 r = -1;
4925 else if (soap_valid_socket(soap->master))
4926 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_SND, 0);
4927 else
4928 return SOAP_OK; /* OK when no socket! */
4929 if (r > 0)
4931 #ifdef WITH_OPENSSL
4932 if (soap->imode & SOAP_ENC_SSL)
4934 if (soap_valid_socket(soap->socket)
4935 && (r & SOAP_TCP_SELECT_SND)
4936 && (!(r & SOAP_TCP_SELECT_RCV)
4937 || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
4938 return SOAP_OK;
4940 else
4941 #endif
4942 { int t;
4943 if (soap_valid_socket(soap->socket)
4944 && (r & SOAP_TCP_SELECT_SND)
4945 && (!(r & SOAP_TCP_SELECT_RCV)
4946 || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0))
4947 return SOAP_OK;
4950 else if (r < 0)
4951 { if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
4952 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
4953 return soap->error = SOAP_TCP_ERROR;
4956 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
4957 return SOAP_EOF;
4958 #else
4959 return SOAP_OK;
4960 #endif
4962 #endif
4963 #endif
4965 /******************************************************************************/
4966 #ifndef WITH_NOIO
4967 #ifndef PALM_1
4968 SOAP_FMAC1
4969 SOAP_SOCKET
4970 SOAP_FMAC2
4971 soap_accept(struct soap *soap)
4972 { int n = (int)sizeof(soap->peer);
4973 register int err;
4974 #ifndef WITH_LEAN
4975 #ifndef WIN32
4976 int len = SOAP_BUFLEN;
4977 #else
4978 int len = SOAP_BUFLEN + 1; /* speeds up windows xfer */
4979 #endif
4980 int set = 1;
4981 #endif
4982 soap->error = SOAP_OK;
4983 memset((void*)&soap->peer, 0, sizeof(soap->peer));
4984 soap->socket = SOAP_INVALID_SOCKET;
4985 soap->errmode = 0;
4986 soap->keep_alive = 0;
4987 if (!soap_valid_socket(soap->master))
4988 { soap->errnum = 0;
4989 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
4990 return SOAP_INVALID_SOCKET;
4992 #ifndef WITH_LEAN
4993 if ((soap->omode & SOAP_IO_UDP))
4994 return soap->socket = soap->master;
4995 #endif
4996 for (;;)
4997 { if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout)
4998 { for (;;)
4999 { register int r;
5000 r = tcp_select(soap, soap->master, SOAP_TCP_SELECT_ALL, soap->accept_timeout ? soap->accept_timeout : 60);
5001 if (r > 0)
5002 break;
5003 if (!r && soap->accept_timeout)
5004 { soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
5005 return SOAP_INVALID_SOCKET;
5007 if (r < 0)
5008 { r = soap->errnum;
5009 if (r != SOAP_EINTR)
5010 { soap_closesock(soap);
5011 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
5012 return SOAP_INVALID_SOCKET;
5017 if (soap->accept_timeout)
5018 SOAP_SOCKNONBLOCK(soap->master)
5019 else
5020 SOAP_SOCKBLOCK(soap->master)
5021 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
5022 soap->peerlen = (size_t)n;
5023 if (soap_valid_socket(soap->socket))
5025 #ifdef WITH_IPV6
5026 unsigned int ip1, ip2, ip3, ip4;
5027 char port[16];
5028 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), port, 16, NI_NUMERICHOST | NI_NUMERICSERV);
5029 sscanf(soap->host, "%u.%u.%u.%u", &ip1, &ip2, &ip3, &ip4);
5030 soap->ip = (unsigned long)ip1 << 24 | (unsigned long)ip2 << 16 | (unsigned long)ip3 << 8 | (unsigned long)ip4;
5031 soap->port = soap_strtol(port, NULL, 10);
5032 #else
5033 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
5034 #ifdef HAVE_SNPRINTF
5035 soap_snprintf(soap->host, sizeof(soap->host), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
5036 #else
5037 sprintf(soap->host, "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
5038 #endif
5039 soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
5040 #endif
5041 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", soap->socket, soap->port, soap->host));
5042 #ifndef WITH_LEAN
5043 if (soap->accept_flags == SO_LINGER)
5044 { struct linger linger;
5045 memset((void*)&linger, 0, sizeof(linger));
5046 linger.l_onoff = 1;
5047 linger.l_linger = soap->linger_time;
5048 if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
5049 { soap->errnum = soap_socket_errno(soap->socket);
5050 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
5051 soap_closesock(soap);
5052 return SOAP_INVALID_SOCKET;
5055 else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
5056 { soap->errnum = soap_socket_errno(soap->socket);
5057 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
5058 soap_closesock(soap);
5059 return SOAP_INVALID_SOCKET;
5061 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
5062 { soap->errnum = soap_socket_errno(soap->socket);
5063 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
5064 soap_closesock(soap);
5065 return SOAP_INVALID_SOCKET;
5067 if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
5068 { soap->errnum = soap_socket_errno(soap->socket);
5069 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
5070 soap_closesock(soap);
5071 return SOAP_INVALID_SOCKET;
5073 if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
5074 { soap->errnum = soap_socket_errno(soap->socket);
5075 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
5076 soap_closesock(soap);
5077 return SOAP_INVALID_SOCKET;
5079 #ifdef TCP_NODELAY
5080 if (setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
5081 { soap->errnum = soap_socket_errno(soap->socket);
5082 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
5083 soap_closesock(soap);
5084 return SOAP_INVALID_SOCKET;
5086 #endif
5087 #endif
5088 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
5089 if (soap->send_timeout || soap->recv_timeout)
5090 SOAP_SOCKNONBLOCK(soap->socket)
5091 else
5092 SOAP_SOCKBLOCK(soap->socket)
5093 return soap->socket;
5095 err = soap_socket_errno(soap->socket);
5096 if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
5097 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
5098 soap->errnum = err;
5099 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
5100 soap_closesock(soap);
5101 return SOAP_INVALID_SOCKET;
5105 #endif
5106 #endif
5108 /******************************************************************************/
5109 #ifndef PALM_1
5110 SOAP_FMAC1
5112 SOAP_FMAC2
5113 soap_closesock(struct soap *soap)
5114 { register int status = soap->error;
5115 #ifndef WITH_LEANER
5116 if (status) /* close on error: attachment state is not to be trusted */
5117 { soap->mime.first = NULL;
5118 soap->mime.last = NULL;
5119 soap->dime.first = NULL;
5120 soap->dime.last = NULL;
5122 #endif
5123 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
5124 return soap->error;
5125 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
5126 { if (soap->fclose && (soap->error = soap->fclose(soap)))
5127 return soap->error;
5128 soap->keep_alive = 0;
5130 #ifdef WITH_ZLIB
5131 if (!(soap->mode & SOAP_MIME_POSTCHECK))
5132 { if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
5133 deflateEnd(soap->d_stream);
5134 else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
5135 inflateEnd(soap->d_stream);
5136 soap->zlib_state = SOAP_ZLIB_NONE;
5138 #endif
5139 return soap->error = status;
5141 #endif
5143 /******************************************************************************/
5144 #ifndef WITH_NOIO
5145 #ifndef PALM_1
5146 SOAP_FMAC1
5148 SOAP_FMAC2
5149 soap_force_closesock(struct soap *soap)
5150 { soap->keep_alive = 0;
5151 if (soap_valid_socket(soap->socket))
5152 return soap_closesocket(soap->socket);
5153 return SOAP_OK;
5155 #endif
5156 #endif
5158 /******************************************************************************/
5159 #ifndef WITH_NOIO
5160 #ifndef PALM_2
5161 SOAP_FMAC1
5162 void
5163 SOAP_FMAC2
5164 soap_cleanup(struct soap *soap)
5165 { soap_done(soap);
5166 #ifdef WIN32
5167 if (!tcp_done)
5168 return;
5169 tcp_done = 0;
5170 WSACleanup();
5171 #endif
5173 #endif
5174 #endif
5176 /******************************************************************************/
5177 #ifndef PALM_1
5178 SOAP_FMAC1
5179 void
5180 SOAP_FMAC2
5181 soap_done(struct soap *soap)
5183 #ifdef SOAP_DEBUG
5184 int i;
5185 #endif
5186 if (soap_check_state(soap))
5187 return;
5188 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : ""));
5189 soap_free_temp(soap);
5190 while (soap->clist)
5191 { struct soap_clist *p = soap->clist->next;
5192 SOAP_FREE(soap, soap->clist);
5193 soap->clist = p;
5195 if (soap->state == SOAP_INIT)
5196 soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
5197 soap->keep_alive = 0; /* to force close the socket */
5198 if (soap->master == soap->socket) /* do not close twice */
5199 soap->master = SOAP_INVALID_SOCKET;
5200 soap_closesock(soap);
5201 #ifdef WITH_COOKIES
5202 soap_free_cookies(soap);
5203 #endif
5204 while (soap->plugins)
5205 { register struct soap_plugin *p = soap->plugins->next;
5206 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
5207 if (soap->plugins->fcopy || soap->state == SOAP_INIT)
5208 soap->plugins->fdelete(soap, soap->plugins);
5209 SOAP_FREE(soap, soap->plugins);
5210 soap->plugins = p;
5212 soap->fplugin = fplugin;
5213 soap->fmalloc = NULL;
5214 #ifndef WITH_NOHTTP
5215 soap->fpost = http_post;
5216 soap->fget = http_get;
5217 soap->fput = http_405;
5218 soap->fdel = http_405;
5219 soap->fopt = http_200;
5220 soap->fhead = http_200;
5221 soap->fform = NULL;
5222 soap->fposthdr = http_post_header;
5223 soap->fresponse = http_response;
5224 soap->fparse = http_parse;
5225 soap->fparsehdr = http_parse_header;
5226 #endif
5227 soap->fheader = NULL;
5228 #ifndef WITH_NOIO
5229 #ifndef WITH_IPV6
5230 soap->fresolve = tcp_gethost;
5231 #else
5232 soap->fresolve = NULL;
5233 #endif
5234 soap->faccept = tcp_accept;
5235 soap->fopen = tcp_connect;
5236 soap->fclose = tcp_disconnect;
5237 soap->fclosesocket = tcp_closesocket;
5238 soap->fshutdownsocket = tcp_shutdownsocket;
5239 soap->fsend = fsend;
5240 soap->frecv = frecv;
5241 soap->fpoll = soap_poll;
5242 #else
5243 soap->fopen = NULL;
5244 soap->fclose = NULL;
5245 soap->fpoll = NULL;
5246 #endif
5247 #ifndef WITH_LEANER
5248 soap->feltbegin = NULL;
5249 soap->feltendin = NULL;
5250 soap->feltbegout = NULL;
5251 soap->feltendout = NULL;
5252 soap->fprepareinitsend = NULL;
5253 soap->fprepareinitrecv = NULL;
5254 soap->fpreparesend = NULL;
5255 soap->fpreparerecv = NULL;
5256 soap->fpreparefinalsend = NULL;
5257 soap->fpreparefinalrecv = NULL;
5258 soap->ffiltersend = NULL;
5259 soap->ffilterrecv = NULL;
5260 #endif
5261 soap->fseterror = NULL;
5262 soap->fignore = NULL;
5263 soap->fserveloop = NULL;
5264 #ifdef WITH_OPENSSL
5265 if (soap->session)
5266 { SSL_SESSION_free(soap->session);
5267 soap->session = NULL;
5269 #endif
5270 if (soap->state == SOAP_INIT)
5271 { if (soap_valid_socket(soap->master))
5272 { soap->fclosesocket(soap, soap->master);
5273 soap->master = SOAP_INVALID_SOCKET;
5276 #ifdef WITH_OPENSSL
5277 if (soap->ssl)
5278 { SSL_free(soap->ssl);
5279 soap->ssl = NULL;
5281 if (soap->state == SOAP_INIT)
5282 { if (soap->ctx)
5283 { SSL_CTX_free(soap->ctx);
5284 soap->ctx = NULL;
5287 ERR_remove_state(0);
5288 #endif
5289 #ifdef WITH_GNUTLS
5290 if (soap->state == SOAP_INIT)
5291 { if (soap->xcred)
5292 { gnutls_certificate_free_credentials(soap->xcred);
5293 soap->xcred = NULL;
5295 if (soap->acred)
5296 { gnutls_anon_free_client_credentials(soap->acred);
5297 soap->acred = NULL;
5299 if (soap->cache)
5300 { gnutls_priority_deinit(soap->cache);
5301 soap->cache = NULL;
5303 if (soap->dh_params)
5304 { gnutls_dh_params_deinit(soap->dh_params);
5305 soap->dh_params = NULL;
5307 if (soap->rsa_params)
5308 { gnutls_rsa_params_deinit(soap->rsa_params);
5309 soap->rsa_params = NULL;
5312 if (soap->session)
5313 { gnutls_deinit(soap->session);
5314 soap->session = NULL;
5316 #endif
5317 #ifdef WITH_C_LOCALE
5318 # ifdef WIN32
5319 _free_locale(soap->c_locale);
5320 # else
5321 freelocale(soap->c_locale);
5322 # endif
5323 #endif
5324 #ifdef WITH_ZLIB
5325 if (soap->d_stream)
5326 { SOAP_FREE(soap, (void*)soap->d_stream);
5327 soap->d_stream = NULL;
5329 if (soap->z_buf)
5330 { SOAP_FREE(soap, (void*)soap->z_buf);
5331 soap->z_buf = NULL;
5333 #endif
5334 #ifdef SOAP_DEBUG
5335 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
5336 for (i = 0; i < SOAP_MAXLOGS; i++)
5337 { if (soap->logfile[i])
5338 { SOAP_FREE(soap, (void*)soap->logfile[i]);
5339 soap->logfile[i] = NULL;
5341 soap_close_logfile(soap, i);
5343 soap->state = SOAP_NONE;
5344 #endif
5345 #ifdef SOAP_MEM_DEBUG
5346 soap_free_mht(soap);
5347 #endif
5349 #endif
5351 /******************************************************************************\
5353 * HTTP
5355 \******************************************************************************/
5357 /******************************************************************************/
5358 #ifndef WITH_NOHTTP
5359 #ifndef PALM_1
5360 static int
5361 http_parse(struct soap *soap)
5362 { char header[SOAP_HDRLEN], *s;
5363 unsigned short httpcmd = 0;
5364 int status = 0;
5365 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
5366 *soap->endpoint = '\0';
5367 #ifdef WITH_NTLM
5368 if (!soap->ntlm_challenge)
5369 #endif
5370 { soap->userid = NULL;
5371 soap->passwd = NULL;
5372 soap->authrealm = NULL;
5374 #ifdef WITH_NTLM
5375 soap->ntlm_challenge = NULL;
5376 #endif
5377 soap->proxy_from = NULL;
5379 { soap->length = 0;
5380 soap->http_content = NULL;
5381 soap->action = NULL;
5382 soap->status = 0;
5383 soap->body = 1;
5384 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
5385 { if (soap->error == SOAP_EOF)
5386 return SOAP_EOF;
5387 return soap->error = 414;
5389 if ((s = strchr(soap->msgbuf, ' ')))
5390 { soap->status = (unsigned short)soap_strtoul(s, &s, 10);
5391 if (!soap_blank((soap_wchar)*s))
5392 soap->status = 0;
5394 else
5395 soap->status = 0;
5396 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
5397 for (;;)
5398 { if (soap_getline(soap, header, SOAP_HDRLEN))
5399 { if (soap->error == SOAP_EOF)
5400 { soap->error = SOAP_OK;
5401 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
5402 break;
5404 return soap->error;
5406 if (!*header)
5407 break;
5408 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
5409 s = strchr(header, ':');
5410 if (s)
5411 { char *t;
5412 *s = '\0';
5413 do s++;
5414 while (*s && *s <= 32);
5415 if (*s == '"')
5416 s++;
5417 t = s + strlen(s) - 1;
5418 while (t > s && *t <= 32)
5419 t--;
5420 if (t >= s && *t == '"')
5421 t--;
5422 t[1] = '\0';
5423 if ((soap->error = soap->fparsehdr(soap, header, s)))
5424 { if (soap->error < SOAP_STOP)
5425 return soap->error;
5426 status = soap->error;
5427 soap->error = SOAP_OK;
5431 } while (soap->status == 100);
5432 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", soap->status));
5433 s = strstr(soap->msgbuf, "HTTP/");
5434 if (s && s[7] != '1')
5435 { if (soap->keep_alive == 1)
5436 soap->keep_alive = 0;
5437 if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
5438 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */
5440 if (soap->keep_alive < 0)
5441 soap->keep_alive = 1;
5442 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
5443 if (soap->status == 0)
5444 { size_t l = 0;
5445 if (s)
5446 { if (!strncmp(soap->msgbuf, "POST ", l = 5))
5447 httpcmd = 1;
5448 else if (!strncmp(soap->msgbuf, "PUT ", l = 4))
5449 httpcmd = 2;
5450 else if (!strncmp(soap->msgbuf, "GET ", l = 4))
5451 httpcmd = 3;
5452 else if (!strncmp(soap->msgbuf, "DELETE ", l = 7))
5453 httpcmd = 4;
5454 else if (!strncmp(soap->msgbuf, "OPTIONS ", l = 8))
5455 httpcmd = 5;
5456 else if (!strncmp(soap->msgbuf, "HEAD ", l = 5))
5457 httpcmd = 6;
5459 if (s && httpcmd)
5460 { size_t m = strlen(soap->endpoint);
5461 size_t n = m + (s - soap->msgbuf) - l - 1;
5462 size_t k;
5463 if (n >= sizeof(soap->endpoint))
5464 n = sizeof(soap->endpoint) - 1;
5465 if (m > n)
5466 m = n;
5467 k = n - m + 1;
5468 if (k > sizeof(soap->path))
5469 k = sizeof(soap->path);
5470 strncpy(soap->path, soap->msgbuf + l, k);
5471 soap->path[k - 1] = '\0';
5472 if (*soap->path && *soap->path != '/')
5473 *soap->endpoint = '\0';
5474 strcat(soap->endpoint, soap->path);
5475 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
5476 if (httpcmd > 1)
5477 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP %s handler\n", soap->msgbuf));
5478 switch (httpcmd)
5479 { case 2: soap->error = soap->fput(soap); break;
5480 case 3: soap->error = soap->fget(soap); break;
5481 case 4: soap->error = soap->fdel(soap); break;
5482 case 5: soap->error = soap->fopt(soap); break;
5483 case 6: soap->error = soap->fhead(soap); break;
5484 default: soap->error = 405; break;
5486 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP handler return = %d\n", soap->error));
5487 if (soap->error == SOAP_OK)
5488 soap->error = SOAP_STOP; /* prevents further processing */
5489 return soap->error;
5491 if (status)
5492 return soap->error = status;
5494 else if (status)
5495 return soap->error = status;
5496 else if (s)
5497 return soap->error = 405;
5498 return SOAP_OK;
5500 #if 0
5501 if (soap->length > 0 || (soap->http_content && (!soap->keep_alive || soap->recv_timeout)) || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
5502 #endif
5503 if (soap->body)
5504 { if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */
5505 || soap->status == 400 /* Bad Request */
5506 || soap->status == 500) /* Internal Server Error */
5507 return SOAP_OK;
5508 /* force close afterwards in soap_closesock() */
5509 soap->keep_alive = 0;
5510 #ifndef WITH_LEAN
5511 /* read HTTP body for error details */
5512 s = soap_get_http_body(soap, NULL);
5513 if (s)
5514 return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status);
5515 #endif
5517 else if (soap->status >= 200 && soap->status <= 299)
5518 return soap->error = soap->status;
5519 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status));
5520 return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status);
5522 #endif
5523 #endif
5525 /******************************************************************************/
5526 #ifndef WITH_NOHTTP
5527 #ifndef PALM_1
5528 static int
5529 http_parse_header(struct soap *soap, const char *key, const char *val)
5530 { if (!soap_tag_cmp(key, "Host"))
5532 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
5533 if (soap->imode & SOAP_ENC_SSL)
5534 strcpy(soap->endpoint, "https://");
5535 else
5536 #endif
5537 strcpy(soap->endpoint, "http://");
5538 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
5540 #ifndef WITH_LEANER
5541 else if (!soap_tag_cmp(key, "Content-Type"))
5542 { const char *action;
5543 soap->http_content = soap_strdup(soap, val);
5544 if (soap_get_header_attribute(soap, val, "application/dime"))
5545 soap->imode |= SOAP_ENC_DIME;
5546 else if (soap_get_header_attribute(soap, val, "multipart/related")
5547 || soap_get_header_attribute(soap, val, "multipart/form-data"))
5548 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
5549 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
5550 soap->imode |= SOAP_ENC_MIME;
5552 action = soap_get_header_attribute(soap, val, "action");
5553 if (action)
5554 { if (*action == '"')
5555 { soap->action = soap_strdup(soap, action + 1);
5556 if (*soap->action)
5557 soap->action[strlen(soap->action) - 1] = '\0';
5559 else
5560 soap->action = soap_strdup(soap, action);
5563 #endif
5564 else if (!soap_tag_cmp(key, "Content-Length"))
5565 { soap->length = soap_strtoul(val, NULL, 10);
5566 if (!soap->length)
5567 soap->body = 0;
5569 else if (!soap_tag_cmp(key, "Content-Encoding"))
5570 { if (!soap_tag_cmp(val, "deflate"))
5571 #ifdef WITH_ZLIB
5572 soap->zlib_in = SOAP_ZLIB_DEFLATE;
5573 #else
5574 return SOAP_ZLIB_ERROR;
5575 #endif
5576 else if (!soap_tag_cmp(val, "gzip"))
5577 #ifdef WITH_GZIP
5578 soap->zlib_in = SOAP_ZLIB_GZIP;
5579 #else
5580 return SOAP_ZLIB_ERROR;
5581 #endif
5583 #ifdef WITH_ZLIB
5584 else if (!soap_tag_cmp(key, "Accept-Encoding"))
5586 #ifdef WITH_GZIP
5587 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
5588 soap->zlib_out = SOAP_ZLIB_GZIP;
5589 else
5590 #endif
5591 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
5592 soap->zlib_out = SOAP_ZLIB_DEFLATE;
5593 else
5594 soap->zlib_out = SOAP_ZLIB_NONE;
5596 #endif
5597 else if (!soap_tag_cmp(key, "Transfer-Encoding"))
5598 { soap->imode &= ~SOAP_IO;
5599 if (!soap_tag_cmp(val, "chunked"))
5600 soap->imode |= SOAP_IO_CHUNK;
5602 else if (!soap_tag_cmp(key, "Connection"))
5603 { if (!soap_tag_cmp(val, "keep-alive"))
5604 soap->keep_alive = -soap->keep_alive;
5605 else if (!soap_tag_cmp(val, "close"))
5606 soap->keep_alive = 0;
5608 #ifndef WITH_LEAN
5609 else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization"))
5611 #ifdef WITH_NTLM
5612 if (!soap_tag_cmp(val, "NTLM*"))
5613 soap->ntlm_challenge = soap_strdup(soap, val + 4);
5614 else
5615 #endif
5616 if (!soap_tag_cmp(val, "Basic *"))
5617 { int n;
5618 char *s;
5619 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
5620 soap->tmpbuf[n] = '\0';
5621 if ((s = strchr(soap->tmpbuf, ':')))
5622 { *s = '\0';
5623 soap->userid = soap_strdup(soap, soap->tmpbuf);
5624 soap->passwd = soap_strdup(soap, s + 1);
5628 else if (!soap_tag_cmp(key, "WWW-Authenticate") || !soap_tag_cmp(key, "Proxy-Authenticate"))
5630 #ifdef WITH_NTLM
5631 if (!soap_tag_cmp(val, "NTLM*"))
5632 soap->ntlm_challenge = soap_strdup(soap, val + 4);
5633 else
5634 #endif
5635 soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
5637 else if (!soap_tag_cmp(key, "Expect"))
5638 { if (!soap_tag_cmp(val, "100-continue"))
5639 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
5640 || (soap->error = soap->fposthdr(soap, NULL, NULL)))
5641 return soap->error;
5644 #endif
5645 else if (!soap_tag_cmp(key, "SOAPAction"))
5646 { if (*val == '"')
5647 { soap->action = soap_strdup(soap, val + 1);
5648 if (*soap->action)
5649 soap->action[strlen(soap->action) - 1] = '\0';
5651 else
5652 soap->action = soap_strdup(soap, val);
5654 else if (!soap_tag_cmp(key, "Location"))
5655 { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
5656 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
5658 else if (!soap_tag_cmp(key, "X-Forwarded-For"))
5659 { soap->proxy_from = soap_strdup(soap, val);
5661 #ifdef WITH_COOKIES
5662 else if (!soap_tag_cmp(key, "Cookie")
5663 || !soap_tag_cmp(key, "Cookie2")
5664 || !soap_tag_cmp(key, "Set-Cookie")
5665 || !soap_tag_cmp(key, "Set-Cookie2"))
5666 { soap_getcookies(soap, val);
5668 #endif
5669 return SOAP_OK;
5671 #endif
5672 #endif
5674 /******************************************************************************/
5675 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5676 #ifndef PALM_1
5677 SOAP_FMAC1
5678 const char*
5679 SOAP_FMAC2
5680 soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
5681 { register const char *s = line;
5682 if (s)
5683 { while (*s)
5684 { register short flag;
5685 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
5686 flag = soap_tag_cmp(soap->tmpbuf, key);
5687 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
5688 if (!flag)
5689 return soap->tmpbuf;
5692 return NULL;
5694 #endif
5695 #endif
5697 /******************************************************************************/
5698 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5699 #ifndef PALM_1
5700 SOAP_FMAC1
5701 const char*
5702 SOAP_FMAC2
5703 soap_decode_key(char *buf, size_t len, const char *val)
5704 { return soap_decode(buf, len, val, "=,;");
5706 #endif
5707 #endif
5709 /******************************************************************************/
5710 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5711 #ifndef PALM_1
5712 SOAP_FMAC1
5713 const char*
5714 SOAP_FMAC2
5715 soap_decode_val(char *buf, size_t len, const char *val)
5716 { if (*val != '=')
5717 { *buf = '\0';
5718 return val;
5720 return soap_decode(buf, len, val + 1, ",;");
5722 #endif
5723 #endif
5725 /******************************************************************************/
5726 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5727 #ifndef PALM_1
5728 static const char*
5729 soap_decode(char *buf, size_t len, const char *val, const char *sep)
5730 { const char *s;
5731 char *t = buf;
5732 size_t i = len;
5733 for (s = val; *s; s++)
5734 if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
5735 break;
5736 if (len > 0)
5737 { if (*s == '"')
5738 { s++;
5739 while (*s && *s != '"' && --i)
5740 *t++ = *s++;
5742 else
5743 { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --i)
5744 { if (*s == '%' && s[1] && s[2])
5745 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
5746 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
5747 s += 3;
5749 else
5750 *t++ = *s++;
5753 buf[len - 1] = '\0'; /* appease */
5755 *t = '\0';
5756 while (*s && !strchr(sep, *s))
5757 s++;
5758 return s;
5760 #endif
5761 #endif
5763 /******************************************************************************/
5764 #ifndef WITH_NOHTTP
5765 #ifndef PALM_1
5766 static const char*
5767 http_error(struct soap *soap, int status)
5768 { register const char *msg = SOAP_STR_EOS;
5769 (void)soap;
5770 #ifndef WITH_LEAN
5771 msg = soap_code_str(h_http_error_codes, status);
5772 if (!msg)
5773 msg = SOAP_STR_EOS;
5774 #endif
5775 return msg;
5777 #endif
5778 #endif
5780 /******************************************************************************/
5782 #ifndef WITH_NOHTTP
5783 #ifndef PALM_1
5784 static int
5785 http_get(struct soap *soap)
5786 { (void)soap;
5787 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP GET request\n"));
5788 return SOAP_GET_METHOD;
5790 #endif
5791 #endif
5793 /******************************************************************************/
5794 #ifndef WITH_NOHTTP
5795 #ifndef PALM_1
5796 static int
5797 http_405(struct soap *soap)
5798 { (void)soap;
5799 return 405;
5801 #endif
5802 #endif
5804 /******************************************************************************/
5805 #ifndef WITH_NOHTTP
5806 #ifndef PALM_1
5807 static int
5808 http_200(struct soap *soap)
5809 { return soap_send_empty_response(soap, 200);
5811 #endif
5812 #endif
5814 /******************************************************************************/
5815 #ifndef WITH_NOHTTP
5816 #ifndef PALM_1
5817 static int
5818 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
5819 { register const char *s;
5820 register int err;
5821 switch (soap->status)
5822 { case SOAP_GET:
5823 s = "GET";
5824 break;
5825 case SOAP_PUT:
5826 s = "PUT";
5827 break;
5828 case SOAP_DEL:
5829 s = "DELETE";
5830 break;
5831 case SOAP_CONNECT:
5832 s = "CONNECT";
5833 break;
5834 default:
5835 s = "POST";
5837 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP %s to %s\n", s, endpoint ? endpoint : "(null)"));
5838 #ifdef PALM
5839 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))
5840 #else
5841 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
5842 #endif
5843 return SOAP_OK;
5844 if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80
5845 || strlen(host) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
5846 return soap->error = SOAP_EOM; /* prevent overrun (note that 'host' and 'soap->host' are substrings of 'endpoint') */
5847 if (soap->status == SOAP_CONNECT)
5849 #ifdef HAVE_SNPRINTF
5850 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
5851 #else
5852 sprintf(soap->tmpbuf, "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
5853 #endif
5855 else if (soap->proxy_host && endpoint)
5857 #ifdef HAVE_SNPRINTF
5858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s HTTP/%s", s, endpoint, soap->http_version);
5859 #else
5860 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
5861 #endif
5863 else
5865 #ifdef HAVE_SNPRINTF
5866 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
5867 #else
5868 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
5869 #endif
5871 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
5872 return err;
5873 #ifdef WITH_OPENSSL
5874 if ((soap->ssl && port != 443) || (!soap->ssl && port != 80))
5875 #else
5876 if (port != 80)
5877 #endif
5879 #ifdef WITH_IPV6
5880 if (*host != '[' && strchr(host, ':'))
5882 #ifdef HAVE_SNPRINTF
5883 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]:%d", host, port); /* RFC 2732 */
5884 #else
5885 sprintf(soap->tmpbuf, "[%s]:%d", host, port); /* RFC 2732 */
5886 #endif
5888 else
5889 #endif
5891 #ifdef HAVE_SNPRINTF
5892 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s:%d", host, port);
5893 #else
5894 sprintf(soap->tmpbuf, "%s:%d", host, port);
5895 #endif
5898 else
5900 #ifdef WITH_IPV6
5901 if (*host != '[' && strchr(host, ':'))
5903 #ifdef HAVE_SNPRINTF
5904 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]", host); /* RFC 2732 */
5905 #else
5906 sprintf(soap->tmpbuf, "[%s]", host); /* RFC 2732 */
5907 #endif
5909 else
5910 #endif
5911 strcpy(soap->tmpbuf, host);
5913 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)))
5914 return err;
5915 if ((err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8")))
5916 return err;
5917 if ((err = soap_puthttphdr(soap, SOAP_OK, count)))
5918 return err;
5919 #ifdef WITH_ZLIB
5920 #ifdef WITH_GZIP
5921 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
5922 #else
5923 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
5924 #endif
5925 return err;
5926 #endif
5927 #ifndef WITH_LEAN
5928 #ifdef WITH_NTLM
5929 if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf))
5930 { if (*soap->ntlm_challenge)
5932 #ifdef HAVE_SNPRINTF
5933 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "NTLM %s", soap->ntlm_challenge);
5934 #else
5935 sprintf(soap->tmpbuf, "NTLM %s", soap->ntlm_challenge);
5936 #endif
5937 if (soap->proxy_host)
5938 { if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
5939 return err;
5941 else if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
5942 return err;
5945 else
5947 #endif
5948 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
5949 { strcpy(soap->tmpbuf, "Basic ");
5950 #ifdef HAVE_SNPRINTF
5951 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->userid, soap->passwd);
5952 #else
5953 sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
5954 #endif
5955 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
5956 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
5957 return err;
5959 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
5960 { strcpy(soap->tmpbuf, "Basic ");
5961 #ifdef HAVE_SNPRINTF
5962 soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
5963 #else
5964 sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
5965 #endif
5966 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
5967 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
5968 return err;
5970 #ifdef WITH_NTLM
5972 #endif
5973 #endif
5974 #ifdef WITH_COOKIES
5975 #ifdef WITH_OPENSSL
5976 if (soap_putcookies(soap, host, path, soap->ssl != NULL))
5977 return soap->error;
5978 #else
5979 if (soap_putcookies(soap, host, path, 0))
5980 return soap->error;
5981 #endif
5982 #endif
5983 if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL)
5985 #ifdef HAVE_SNPRINTF
5986 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "\"%s\"", action);
5987 #else
5988 sprintf(soap->tmpbuf, "\"%s\"", strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
5989 #endif
5990 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
5991 return err;
5993 return soap->fposthdr(soap, NULL, NULL);
5995 #endif
5996 #endif
5998 /******************************************************************************/
5999 #ifndef WITH_NOHTTP
6000 #ifndef PALM_1
6001 static int
6002 http_send_header(struct soap *soap, const char *s)
6003 { register const char *t;
6005 { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
6006 if (!t)
6007 t = s + strlen(s);
6008 if (soap_send_raw(soap, s, t - s))
6009 return soap->error;
6010 s = t + 1;
6011 } while (*t);
6012 return SOAP_OK;
6014 #endif
6015 #endif
6017 /******************************************************************************/
6018 #ifndef WITH_NOHTTP
6019 #ifndef PALM_1
6020 static int
6021 http_post_header(struct soap *soap, const char *key, const char *val)
6022 { if (key)
6023 { if (http_send_header(soap, key))
6024 return soap->error;
6025 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
6026 return soap->error;
6028 return soap_send_raw(soap, "\r\n", 2);
6030 #endif
6031 #endif
6033 /******************************************************************************/
6034 #ifndef WITH_NOHTTP
6035 #ifndef PALM_1
6036 static int
6037 http_response(struct soap *soap, int status, size_t count)
6038 { register int err;
6039 char http[10];
6040 int code = status;
6041 const char *line;
6042 #ifdef WMW_RPM_IO
6043 if (soap->rpmreqid)
6044 httpOutputEnable(soap->rpmreqid);
6045 #endif
6046 if (!soap->http_version || strlen(soap->http_version) > 4)
6047 return soap->error = SOAP_EOM;
6048 #ifdef WMW_RPM_IO
6049 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
6050 #else
6051 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */
6052 #endif
6054 #ifdef HAVE_SNPRINTF
6055 soap_snprintf(http, sizeof(http), "HTTP/%s", soap->http_version);
6056 #else
6057 sprintf(http, "HTTP/%s", soap->http_version);
6058 #endif
6060 else
6061 strcpy(http, "Status:");
6062 if (!status || status == SOAP_HTML || status == SOAP_FILE)
6063 { if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
6064 code = 200;
6065 else
6066 code = 202;
6068 else if (status < 200 || status >= 600)
6069 { const char *s = *soap_faultcode(soap);
6070 if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
6071 code = 405;
6072 else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
6073 code = 400;
6074 else
6075 code = 500;
6077 line = http_error(soap, code);
6078 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line));
6079 #ifdef HAVE_SNPRINTF
6080 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %d %s", http, code, line);
6081 #else
6082 sprintf(soap->tmpbuf, "%s %d %s", http, code, line);
6083 #endif
6084 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
6085 return err;
6086 #ifndef WITH_LEAN
6087 if (status == 401)
6089 #ifdef HAVE_SNPRINTF
6090 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
6091 #else
6092 sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
6093 #endif
6094 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
6095 return err;
6097 else if ((status >= 301 && status <= 303) || status == 307)
6098 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
6099 return err;
6101 #endif
6102 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.8"))
6103 || (err = soap_puthttphdr(soap, status, count)))
6104 return err;
6105 #ifdef WITH_COOKIES
6106 if (soap_putsetcookies(soap))
6107 return soap->error;
6108 #endif
6109 return soap->fposthdr(soap, NULL, NULL);
6111 #endif
6112 #endif
6114 /******************************************************************************/
6115 #ifndef PALM_1
6116 SOAP_FMAC1
6118 SOAP_FMAC2
6119 soap_response(struct soap *soap, int status)
6120 { register size_t count;
6121 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
6122 && (status == SOAP_HTML || status == SOAP_FILE))
6123 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
6124 soap->status = status;
6125 count = soap_count_attachments(soap);
6126 if (soap_begin_send(soap))
6127 return soap->error;
6128 #ifndef WITH_NOHTTP
6129 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
6130 { register int n = soap->mode;
6131 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
6132 if ((n & SOAP_IO) != SOAP_IO_FLUSH)
6133 soap->mode |= SOAP_IO_BUFFER;
6134 if ((soap->error = soap->fresponse(soap, status, count)))
6135 return soap->error;
6136 #ifndef WITH_LEANER
6137 if ((n & SOAP_IO) == SOAP_IO_CHUNK)
6138 { if (soap_flush(soap))
6139 return soap->error;
6141 #endif
6142 soap->mode = n;
6144 #endif
6145 return SOAP_OK;
6147 #endif
6149 /******************************************************************************/
6150 #ifndef PALM_1
6151 SOAP_FMAC1
6152 const char*
6153 SOAP_FMAC2
6154 soap_url(struct soap *soap, const char *s, const char *t)
6155 { if (!t || (*t != '/' && *t != '?') || strlen(s) + strlen(t) >= sizeof(soap->msgbuf))
6156 return s;
6157 strcpy(soap->msgbuf, s);
6158 strcat(soap->msgbuf, t);
6159 return soap->msgbuf;
6161 #endif
6163 /******************************************************************************/
6164 #ifndef PALM_1
6165 SOAP_FMAC1
6166 size_t
6167 SOAP_FMAC2
6168 soap_encode_url(const char *s, char *t, size_t len)
6169 { register int c;
6170 register size_t n = len;
6171 while ((c = *s++) && --n > 0)
6172 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c))
6173 *t++ = c;
6174 else if (n > 2)
6175 { *t++ = '%';
6176 *t++ = (c >> 4) + (c > 159 ? '7' : '0');
6177 c &= 0xF;
6178 *t++ = c + (c > 9 ? '7' : '0');
6179 n -= 2;
6181 else
6182 break;
6184 *t = '\0';
6185 return len - n;
6187 #endif
6189 /******************************************************************************/
6190 #ifndef PALM_1
6191 SOAP_FMAC1
6192 const char*
6193 SOAP_FMAC2
6194 soap_encode_url_string(struct soap *soap, const char *s)
6195 { if (s)
6196 { size_t n = 3*strlen(s)+1;
6197 char *t = (char*)soap_malloc(soap, n);
6198 if (t)
6199 { soap_encode_url(s, t, n);
6200 return t;
6203 return SOAP_STR_EOS;
6205 #endif
6207 /******************************************************************************\
6209 * HTTP Cookies
6211 \******************************************************************************/
6213 #ifdef WITH_COOKIES
6214 /******************************************************************************/
6215 SOAP_FMAC1
6216 struct soap_cookie*
6217 SOAP_FMAC2
6218 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
6219 { struct soap_cookie *p;
6220 if (!domain)
6221 domain = soap->cookie_domain;
6222 if (!path)
6223 path = soap->cookie_path;
6224 if (!path)
6225 path = SOAP_STR_EOS;
6226 else if (*path == '/')
6227 path++;
6228 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)"));
6229 for (p = soap->cookies; p; p = p->next)
6230 { 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));
6231 if (!strcmp(p->name, name)
6232 && p->domain
6233 && p->path
6234 && !strcmp(p->domain, domain)
6235 && (!*p->path || !strncmp(p->path, path, strlen(p->path))))
6236 break;
6238 return p;
6241 /******************************************************************************/
6242 SOAP_FMAC1
6243 struct soap_cookie*
6244 SOAP_FMAC2
6245 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
6246 { struct soap_cookie **p, *q;
6247 int n;
6248 if (!domain)
6249 domain = soap->cookie_domain;
6250 if (!path)
6251 path = soap->cookie_path;
6252 if (!path)
6253 path = SOAP_STR_EOS;
6254 else if (*path == '/')
6255 path++;
6256 q = soap_cookie(soap, name, domain, path);
6257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s='%s' domain='%s' path='%s'\n", q ? SOAP_STR_EOS : "new ", name, value ? value : "(null)", domain ? domain : "(null)", path ? path : "(null)"));
6258 if (!q)
6259 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
6260 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
6261 strcpy(q->name, name);
6262 q->value = NULL;
6263 q->domain = NULL;
6264 q->path = NULL;
6265 q->expire = 0;
6266 q->maxage = -1;
6267 q->version = 1;
6268 q->secure = 0;
6269 q->modified = 0;
6270 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
6271 if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
6272 break;
6273 if (n)
6274 { q->next = *p;
6275 *p = q;
6277 else
6278 { SOAP_FREE(soap, q->name);
6279 SOAP_FREE(soap, q);
6280 q = NULL;
6284 else
6285 q->modified = 1;
6286 if (q)
6287 { if (q->value)
6288 { if (!value || strcmp(value, q->value))
6289 { SOAP_FREE(soap, q->value);
6290 q->value = NULL;
6293 if (value && *value && !q->value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
6294 strcpy(q->value, value);
6295 if (q->domain)
6296 { if (!domain || strcmp(domain, q->domain))
6297 { SOAP_FREE(soap, q->domain);
6298 q->domain = NULL;
6301 if (domain && !q->domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
6302 strcpy(q->domain, domain);
6303 if (q->path)
6304 { if (!path || strncmp(path, q->path, strlen(q->path)))
6305 { SOAP_FREE(soap, q->path);
6306 q->path = NULL;
6309 if (path && !q->path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
6310 strcpy(q->path, path);
6311 q->session = 1;
6312 q->env = 0;
6314 return q;
6317 /******************************************************************************/
6318 SOAP_FMAC1
6319 void
6320 SOAP_FMAC2
6321 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
6322 { struct soap_cookie **p, *q;
6323 if (!domain)
6324 domain = soap->cookie_domain;
6325 if (!domain)
6326 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)"));
6327 return;
6329 if (!path)
6330 path = soap->cookie_path;
6331 if (!path)
6332 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie path not set\n", name ? name : "(null)"));
6333 return;
6335 if (*path == '/')
6336 path++;
6337 for (p = &soap->cookies, q = *p; q; q = *p)
6338 { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
6339 { if (q->value)
6340 SOAP_FREE(soap, q->value);
6341 if (q->domain)
6342 SOAP_FREE(soap, q->domain);
6343 if (q->path)
6344 SOAP_FREE(soap, q->path);
6345 *p = q->next;
6346 SOAP_FREE(soap, q);
6348 else
6349 p = &q->next;
6353 /******************************************************************************/
6354 SOAP_FMAC1
6355 char *
6356 SOAP_FMAC2
6357 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
6358 { struct soap_cookie *p;
6359 if ((p = soap_cookie(soap, name, domain, path)))
6360 return p->value;
6361 return NULL;
6364 /******************************************************************************/
6365 SOAP_FMAC1
6366 char *
6367 SOAP_FMAC2
6368 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
6369 { struct soap_cookie *p;
6370 if ((p = soap_cookie(soap, name, domain, path)) && p->env)
6371 return p->value;
6372 return NULL;
6375 /******************************************************************************/
6376 SOAP_FMAC1
6377 time_t
6378 SOAP_FMAC2
6379 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
6380 { struct soap_cookie *p;
6381 if ((p = soap_cookie(soap, name, domain, path)))
6382 return p->expire;
6383 return -1;
6386 /******************************************************************************/
6387 SOAP_FMAC1
6389 SOAP_FMAC2
6390 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
6391 { struct soap_cookie *p;
6392 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", expire, name, domain ? domain : "(null)", path ? path : "(null)"));
6393 if ((p = soap_cookie(soap, name, domain, path)))
6394 { p->maxage = expire;
6395 p->modified = 1;
6396 return SOAP_OK;
6398 return SOAP_ERR;
6401 /******************************************************************************/
6402 SOAP_FMAC1
6404 SOAP_FMAC2
6405 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
6406 { struct soap_cookie *p;
6407 if ((p = soap_cookie(soap, name, domain, path)))
6408 { p->session = 1;
6409 p->modified = 1;
6410 return SOAP_OK;
6412 return SOAP_ERR;
6415 /******************************************************************************/
6416 SOAP_FMAC1
6418 SOAP_FMAC2
6419 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
6420 { struct soap_cookie *p;
6421 if ((p = soap_cookie(soap, name, domain, path)))
6422 { p->session = 0;
6423 p->modified = 1;
6424 return SOAP_OK;
6426 return SOAP_ERR;
6429 /******************************************************************************/
6430 SOAP_FMAC1
6432 SOAP_FMAC2
6433 soap_putsetcookies(struct soap *soap)
6434 { struct soap_cookie *p;
6435 char *s, tmp[4096];
6436 const char *t;
6437 for (p = soap->cookies; p; p = p->next)
6439 if (p->modified
6440 #ifdef WITH_OPENSSL
6441 || (!p->env && !soap->ssl == !p->secure)
6442 #endif
6444 { s = tmp;
6445 if (p->name)
6446 s += soap_encode_url(p->name, s, tmp-s+4064);
6447 if (p->value && *p->value)
6448 { *s++ = '=';
6449 s += soap_encode_url(p->value, s, tmp-s+4064);
6451 if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
6452 { strcpy(s, ";Domain=");
6453 strcat(s, p->domain);
6455 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
6456 { strcpy(s, ";Domain=");
6457 strcat(s, soap->cookie_domain);
6459 strcat(s, ";Path=/");
6460 s += strlen(s);
6461 if (p->path)
6462 t = p->path;
6463 else
6464 t = soap->cookie_path;
6465 if (t)
6466 { if (*t == '/')
6467 t++;
6468 if ((int)strlen(t) < tmp-s+4064)
6469 { if (strchr(t, '%')) /* already URL encoded? */
6470 { strcpy(s, t);
6471 s += strlen(s);
6473 else
6474 s += soap_encode_url(t, s, tmp-s+4064);
6477 if (p->version > 0 && s-tmp < 4060)
6479 #ifdef HAVE_SNPRINTF
6480 soap_snprintf(s, 4096 - (s-tmp), ";Version=%u", p->version);
6481 #else
6482 sprintf(s, ";Version=%u", p->version);
6483 #endif
6484 s += strlen(s);
6486 if (p->maxage >= 0 && s-tmp < 4060)
6488 #ifdef HAVE_SNPRINTF
6489 soap_snprintf(s, 4096 - (s-tmp), ";Max-Age=%ld", p->maxage);
6490 #else
6491 sprintf(s, ";Max-Age=%ld", p->maxage);
6492 #endif
6493 s += strlen(s);
6495 if (s-tmp < 4073
6496 && (p->secure
6497 #ifdef WITH_OPENSSL
6498 || soap->ssl
6499 #endif
6501 strcpy(s, ";Secure");
6502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
6503 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
6504 return soap->error;
6507 return SOAP_OK;
6510 /******************************************************************************/
6511 SOAP_FMAC1
6513 SOAP_FMAC2
6514 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
6515 { struct soap_cookie **p, *q;
6516 unsigned int version = 0;
6517 time_t now = time(NULL);
6518 char *s, tmp[4096];
6519 if (!domain || !path)
6520 return SOAP_OK;
6521 s = tmp;
6522 p = &soap->cookies;
6523 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path));
6524 if (*path == '/')
6525 path++;
6526 while ((q = *p))
6527 { if (q->expire && now > q->expire)
6528 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
6529 SOAP_FREE(soap, q->name);
6530 if (q->value)
6531 SOAP_FREE(soap, q->value);
6532 if (q->domain)
6533 SOAP_FREE(soap, q->domain);
6534 if (q->path)
6535 SOAP_FREE(soap, q->path);
6536 *p = q->next;
6537 SOAP_FREE(soap, q);
6539 else
6540 { int flag;
6541 char *t = q->domain;
6542 size_t n = 0;
6543 if (!t)
6544 flag = 1;
6545 else
6546 { const char *r = strchr(t, ':');
6547 if (r)
6548 n = r - t;
6549 else
6550 n = strlen(t);
6551 flag = !strncmp(t, domain, n);
6553 /* domain-level cookies, cannot compile when WITH_NOIO set */
6554 #ifndef WITH_NOIO
6555 if (!flag)
6556 { struct hostent *hostent = gethostbyname((char*)domain);
6557 if (hostent)
6558 { const char *r = strchr(hostent->h_name, '.');
6559 if (!r)
6560 r = hostent->h_name;
6561 flag = !strncmp(t, r, n);
6564 #endif
6565 if (flag
6566 && (!q->path || !strncmp(q->path, path, strlen(q->path)))
6567 && (!q->secure || secure))
6568 { size_t n = 12;
6569 if (q->name)
6570 n += 3*strlen(q->name);
6571 if (q->value && *q->value)
6572 n += 3*strlen(q->value) + 1;
6573 if (q->path && *q->path)
6574 n += strlen(q->path) + 9;
6575 if (q->domain)
6576 n += strlen(q->domain) + 11;
6577 if (tmp - s + n > sizeof(tmp))
6578 { if (s == tmp)
6579 return SOAP_OK; /* HTTP header size overflow */
6580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
6581 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
6582 return soap->error;
6583 s = tmp;
6585 else if (s != tmp)
6586 { strcat(s, " ");
6587 s++;
6589 if (q->version != version && s-tmp < 4060)
6591 #ifdef HAVE_SNPRINTF
6592 soap_snprintf(s, 4096 - (s-tmp), "$Version=%u;", q->version);
6593 #else
6594 sprintf(s, "$Version=%u;", q->version);
6595 #endif
6596 version = q->version;
6597 s += strlen(s);
6599 if (q->name)
6600 s += soap_encode_url(q->name, s, tmp+sizeof(tmp)-s-16);
6601 if (q->value && *q->value)
6602 { *s++ = '=';
6603 s += soap_encode_url(q->value, s, tmp+sizeof(tmp)-s-16);
6605 if (q->path && (s-tmp) + strlen(q->path) < 4060)
6607 #ifdef HAVE_SNPRINTF
6608 soap_snprintf(s, 4096 - (s-tmp), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
6609 #else
6610 sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
6611 #endif
6612 s += strlen(s);
6614 if (q->domain && (s-tmp) + strlen(q->domain) < 4060)
6616 #ifdef HAVE_SNPRINTF
6617 soap_snprintf(s, 4096 - (s-tmp), ";$Domain=\"%s\"", q->domain);
6618 #else
6619 sprintf(s, ";$Domain=\"%s\"", q->domain);
6620 #endif
6621 s += strlen(s);
6624 p = &q->next;
6627 if (s != tmp)
6628 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
6629 return soap->error;
6630 return SOAP_OK;
6633 /******************************************************************************/
6634 SOAP_FMAC1
6635 void
6636 SOAP_FMAC2
6637 soap_getcookies(struct soap *soap, const char *val)
6638 { struct soap_cookie *p = NULL, *q;
6639 const char *s;
6640 char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6641 char *domain = NULL;
6642 char *path = NULL;
6643 unsigned int version = 0;
6644 time_t now = time(NULL);
6645 if (!val)
6646 return;
6647 s = val;
6648 while (*s)
6649 { s = soap_decode_key(tmp, sizeof(tmp), s);
6650 if (!soap_tag_cmp(tmp, "$Version"))
6651 { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
6652 { if (p)
6653 p->version = (int)soap_strtol(tmp, NULL, 10);
6654 else
6655 version = (int)soap_strtol(tmp, NULL, 10);
6658 else if (!soap_tag_cmp(tmp, "$Path"))
6659 { s = soap_decode_val(tmp, sizeof(tmp), s);
6660 if (*tmp)
6661 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6662 strcpy(t, tmp);
6664 else
6665 t = NULL;
6666 if (p)
6667 { if (p->path)
6668 SOAP_FREE(soap, p->path);
6669 p->path = t;
6671 else
6672 { if (path)
6673 SOAP_FREE(soap, path);
6674 path = t;
6677 else if (!soap_tag_cmp(tmp, "$Domain"))
6678 { s = soap_decode_val(tmp, sizeof(tmp), s);
6679 if (*tmp)
6680 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6681 strcpy(t, tmp);
6683 else
6684 t = NULL;
6685 if (p)
6686 { if (p->domain)
6687 SOAP_FREE(soap, p->domain);
6688 p->domain = t;
6690 else
6691 { if (domain)
6692 SOAP_FREE(soap, domain);
6693 domain = t;
6696 else if (p && !soap_tag_cmp(tmp, "Path"))
6697 { if (p->path)
6698 SOAP_FREE(soap, p->path);
6699 s = soap_decode_val(tmp, sizeof(tmp), s);
6700 if (*tmp)
6701 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6702 strcpy(p->path, tmp);
6704 else
6705 p->path = NULL;
6707 else if (p && !soap_tag_cmp(tmp, "Domain"))
6708 { if (p->domain)
6709 SOAP_FREE(soap, p->domain);
6710 s = soap_decode_val(tmp, sizeof(tmp), s);
6711 if (*tmp)
6712 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
6713 strcpy(p->domain, tmp);
6715 else
6716 p->domain = NULL;
6718 else if (p && !soap_tag_cmp(tmp, "Version"))
6719 { s = soap_decode_val(tmp, sizeof(tmp), s);
6720 p->version = (unsigned int)soap_strtoul(tmp, NULL, 10);
6722 else if (p && !soap_tag_cmp(tmp, "Max-Age"))
6723 { s = soap_decode_val(tmp, sizeof(tmp), s);
6724 p->expire = now + soap_strtol(tmp, NULL, 10);
6726 else if (p && !soap_tag_cmp(tmp, "Expires"))
6727 { struct tm T;
6728 char a[3];
6729 static const char mns[] = "anebarprayunulugepctovec";
6730 s = soap_decode_val(tmp, sizeof(tmp), s);
6731 if (strlen(tmp) > 20)
6732 { memset((void*)&T, 0, sizeof(T));
6733 a[0] = tmp[4];
6734 a[1] = tmp[5];
6735 a[2] = '\0';
6736 T.tm_mday = (int)soap_strtol(a, NULL, 10);
6737 a[0] = tmp[8];
6738 a[1] = tmp[9];
6739 T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
6740 a[0] = tmp[11];
6741 a[1] = tmp[12];
6742 T.tm_year = 100 + (int)soap_strtol(a, NULL, 10);
6743 a[0] = tmp[13];
6744 a[1] = tmp[14];
6745 T.tm_hour = (int)soap_strtol(a, NULL, 10);
6746 a[0] = tmp[16];
6747 a[1] = tmp[17];
6748 T.tm_min = (int)soap_strtol(a, NULL, 10);
6749 a[0] = tmp[19];
6750 a[1] = tmp[20];
6751 T.tm_sec = (int)soap_strtol(a, NULL, 10);
6752 p->expire = soap_timegm(&T);
6755 else if (p && !soap_tag_cmp(tmp, "Secure"))
6756 p->secure = 1;
6757 else
6758 { if (p)
6759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
6760 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
6761 { q->version = p->version;
6762 q->expire = p->expire;
6763 q->secure = p->secure;
6764 q->env = 1;
6766 if (p->name)
6767 SOAP_FREE(soap, p->name);
6768 if (p->value)
6769 SOAP_FREE(soap, p->value);
6770 if (p->domain)
6771 SOAP_FREE(soap, p->domain);
6772 if (p->path)
6773 SOAP_FREE(soap, p->path);
6774 SOAP_FREE(soap, p);
6776 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
6777 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
6778 strcpy(p->name, tmp);
6779 s = soap_decode_val(tmp, sizeof(tmp), s);
6780 if (*tmp)
6781 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
6782 strcpy(p->value, tmp);
6784 else
6785 p->value = NULL;
6786 if (domain)
6787 p->domain = domain;
6788 else if (*soap->host)
6789 { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1);
6790 strcpy(p->domain, soap->host);
6792 else
6793 p->domain = NULL;
6794 if (path)
6795 p->path = path;
6796 else if (soap->path && *soap->path)
6797 { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1);
6798 strcpy(p->path, soap->path);
6800 else
6801 { p->path = (char*)SOAP_MALLOC(soap, 2);
6802 strcpy(p->path, "/");
6804 p->expire = 0;
6805 p->secure = 0;
6806 p->version = version;
6810 if (p)
6811 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
6812 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
6813 { q->version = p->version;
6814 q->expire = p->expire;
6815 q->secure = p->secure;
6816 q->env = 1;
6818 if (p->name)
6819 SOAP_FREE(soap, p->name);
6820 if (p->value)
6821 SOAP_FREE(soap, p->value);
6822 if (p->domain)
6823 SOAP_FREE(soap, p->domain);
6824 if (p->path)
6825 SOAP_FREE(soap, p->path);
6826 SOAP_FREE(soap, p);
6828 if (domain)
6829 SOAP_FREE(soap, domain);
6830 if (path)
6831 SOAP_FREE(soap, path);
6834 /******************************************************************************/
6835 SOAP_FMAC1
6837 SOAP_FMAC2
6838 soap_getenv_cookies(struct soap *soap)
6839 { struct soap_cookie *p;
6840 const char *s;
6841 char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6842 if (!(s = getenv("HTTP_COOKIE")))
6843 return SOAP_ERR;
6845 { s = soap_decode_key(key, sizeof(key), s);
6846 s = soap_decode_val(val, sizeof(val), s);
6847 p = soap_set_cookie(soap, key, val, NULL, NULL);
6848 if (p)
6849 p->env = 1;
6850 } while (*s);
6851 return SOAP_OK;
6854 /******************************************************************************/
6855 SOAP_FMAC1
6856 struct soap_cookie*
6857 SOAP_FMAC2
6858 soap_copy_cookies(struct soap *copy, const struct soap *soap)
6859 { struct soap_cookie *p, **q, *r;
6860 q = &r;
6861 for (p = soap->cookies; p; p = p->next)
6862 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
6863 return r;
6864 **q = *p;
6865 if (p->name)
6866 { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
6867 strcpy((*q)->name, p->name);
6869 if (p->value)
6870 { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
6871 strcpy((*q)->value, p->value);
6873 if (p->domain)
6874 { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
6875 strcpy((*q)->domain, p->domain);
6877 if (p->path)
6878 { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
6879 strcpy((*q)->path, p->path);
6881 q = &(*q)->next;
6883 *q = NULL;
6884 return r;
6887 /******************************************************************************/
6888 SOAP_FMAC1
6889 void
6890 SOAP_FMAC2
6891 soap_free_cookies(struct soap *soap)
6892 { struct soap_cookie *p;
6893 for (p = soap->cookies; p; p = soap->cookies)
6894 { soap->cookies = p->next;
6895 SOAP_FREE(soap, p->name);
6896 if (p->value)
6897 SOAP_FREE(soap, p->value);
6898 if (p->domain)
6899 SOAP_FREE(soap, p->domain);
6900 if (p->path)
6901 SOAP_FREE(soap, p->path);
6902 SOAP_FREE(soap, p);
6906 /******************************************************************************/
6907 #endif /* WITH_COOKIES */
6909 /******************************************************************************/
6910 #ifndef WITH_NOIDREF
6911 #ifndef PALM_2
6912 SOAP_FMAC1
6913 size_t
6914 SOAP_FMAC2
6915 soap_hash(register const char *s)
6916 { register size_t h = 0;
6917 while (*s)
6918 h = 65599*h + *s++;
6919 return h % SOAP_IDHASH;
6921 #endif
6922 #endif
6924 /******************************************************************************/
6925 #ifndef WITH_NOIDREF
6926 #ifndef PALM_1
6927 static void
6928 soap_init_pht(struct soap *soap)
6929 { register int i;
6930 soap->pblk = NULL;
6931 soap->pidx = 0;
6932 for (i = 0; i < (int)SOAP_PTRHASH; i++)
6933 soap->pht[i] = NULL;
6935 #endif
6936 #endif
6938 /******************************************************************************/
6939 #ifndef PALM_1
6940 SOAP_FMAC1
6941 struct soap*
6942 SOAP_FMAC2
6943 soap_versioning(soap_new)(soap_mode imode, soap_mode omode)
6944 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
6945 if (soap)
6946 soap_versioning(soap_init)(soap, imode, omode);
6947 return soap;
6949 #endif
6951 /******************************************************************************/
6952 #ifndef PALM_1
6953 SOAP_FMAC1
6954 void
6955 SOAP_FMAC2
6956 soap_free(struct soap *soap)
6957 { soap_done(soap);
6958 free(soap);
6960 #endif
6962 /******************************************************************************/
6963 #ifndef PALM_1
6964 SOAP_FMAC1
6965 void
6966 SOAP_FMAC2
6967 soap_del(struct soap *soap)
6968 { free(soap);
6970 #endif
6972 /******************************************************************************/
6973 #ifndef WITH_NOIDREF
6974 #ifndef PALM_1
6975 static void
6976 soap_free_pht(struct soap *soap)
6977 { register struct soap_pblk *pb, *next;
6978 register int i;
6979 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
6980 for (pb = soap->pblk; pb; pb = next)
6981 { next = pb->next;
6982 SOAP_FREE(soap, pb);
6984 soap->pblk = NULL;
6985 soap->pidx = 0;
6986 for (i = 0; i < (int)SOAP_PTRHASH; i++)
6987 soap->pht[i] = NULL;
6989 #endif
6990 #endif
6992 /******************************************************************************/
6993 #ifndef WITH_NOIDREF
6994 #ifndef PALM_2
6995 SOAP_FMAC1
6997 SOAP_FMAC2
6998 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
6999 { register int i;
7000 struct soap_plist *pp;
7001 (void)soap;
7002 if (soap->version == 2)
7003 soap->encoding = 1;
7004 if (a)
7005 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
7006 else
7007 i = soap_pointer_lookup(soap, p, type, &pp);
7008 if (i)
7009 { if (soap_is_embedded(soap, pp)
7010 || soap_is_single(soap, pp))
7011 return 0;
7012 soap_set_embedded(soap, pp);
7014 return i;
7016 #endif
7017 #endif
7019 /******************************************************************************/
7020 #ifndef WITH_NOIDREF
7021 #ifndef PALM_2
7022 SOAP_FMAC1
7024 SOAP_FMAC2
7025 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
7026 { register struct soap_plist *pp;
7027 *ppp = NULL;
7028 if (p)
7029 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
7030 { if (pp->ptr == p && pp->type == type)
7031 { *ppp = pp;
7032 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
7033 return pp->id;
7037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
7038 return 0;
7040 #endif
7041 #endif
7043 /******************************************************************************/
7044 #ifndef WITH_NOIDREF
7045 #ifndef PALM_2
7046 SOAP_FMAC1
7048 SOAP_FMAC2
7049 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
7050 { register size_t h;
7051 register struct soap_plist *pp;
7052 (void)n;
7053 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
7054 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
7055 if (!pb)
7056 { soap->error = SOAP_EOM;
7057 return 0;
7059 pb->next = soap->pblk;
7060 soap->pblk = pb;
7061 soap->pidx = 0;
7063 *ppp = pp = &soap->pblk->plist[soap->pidx++];
7064 if (a)
7065 h = soap_hash_ptr(a->__ptr);
7066 else
7067 h = soap_hash_ptr(p);
7068 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));
7069 pp->next = soap->pht[h];
7070 pp->type = type;
7071 pp->mark1 = 0;
7072 pp->mark2 = 0;
7073 pp->ptr = p;
7074 pp->array = a;
7075 soap->pht[h] = pp;
7076 pp->id = ++soap->idnum;
7077 return pp->id;
7079 #endif
7080 #endif
7082 /******************************************************************************/
7083 #ifndef WITH_NOIDREF
7084 #ifndef PALM_2
7085 SOAP_FMAC1
7087 SOAP_FMAC2
7088 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
7089 { register struct soap_plist *pp;
7090 *ppp = NULL;
7091 if (!p || !a->__ptr)
7092 return 0;
7093 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
7094 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
7095 { register int i;
7096 for (i = 0; i < n; i++)
7097 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
7098 break;
7099 if (i == n)
7100 { *ppp = pp;
7101 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
7102 return pp->id;
7106 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
7107 return 0;
7109 #endif
7110 #endif
7112 /******************************************************************************/
7113 #ifndef PALM_1
7114 SOAP_FMAC1
7116 SOAP_FMAC2
7117 soap_begin_count(struct soap *soap)
7118 { soap_free_ns(soap);
7119 #ifndef WITH_LEANER
7120 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
7121 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
7122 else
7123 #endif
7124 { soap->mode = soap->omode;
7125 if ((soap->mode & SOAP_IO_UDP))
7126 soap->mode |= SOAP_ENC_XML;
7127 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
7128 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
7129 #ifndef WITH_LEANER
7130 && !soap->fpreparesend
7131 #endif
7133 soap->mode &= ~SOAP_IO_LENGTH;
7134 else
7135 soap->mode |= SOAP_IO_LENGTH;
7137 #ifdef WITH_ZLIB
7138 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
7139 { if (!(soap->mode & SOAP_ENC_DIME))
7140 soap->mode &= ~SOAP_IO_LENGTH;
7141 if (soap->mode & SOAP_ENC_XML)
7142 soap->mode |= SOAP_IO_BUFFER;
7143 else
7144 soap->mode |= SOAP_IO_STORE;
7146 #endif
7147 #ifndef WITH_LEANER
7148 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
7149 soap->mode |= SOAP_ENC_MIME;
7150 else if (!(soap->mode & SOAP_ENC_MIME))
7151 soap->mode &= ~SOAP_ENC_MTOM;
7152 if (soap->mode & SOAP_ENC_MIME)
7153 soap_select_mime_boundary(soap);
7154 soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
7155 #endif
7156 soap->count = 0;
7157 soap->ns = 0;
7158 soap->null = 0;
7159 soap->position = 0;
7160 soap->mustUnderstand = 0;
7161 soap->encoding = 0;
7162 soap->part = SOAP_BEGIN;
7163 soap->event = 0;
7164 soap->evlev = 0;
7165 soap->idnum = 0;
7166 soap_clr_attr(soap);
7167 soap_set_local_namespaces(soap);
7168 #ifndef WITH_LEANER
7169 soap->dime.count = 0; /* count # of attachments */
7170 soap->dime.size = 0; /* accumulate total size of attachments */
7171 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
7172 return soap->error;
7173 #endif
7174 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, (unsigned int)soap->mode, (unsigned long)soap->count));
7175 return SOAP_OK;
7177 #endif
7179 /******************************************************************************/
7180 #ifndef PALM_1
7181 SOAP_FMAC1
7183 SOAP_FMAC2
7184 soap_end_count(struct soap *soap)
7185 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
7186 #ifndef WITH_LEANER
7187 if ((soap->mode & SOAP_IO_LENGTH))
7188 { if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
7189 return soap->error;
7191 #endif
7192 return SOAP_OK;
7194 #endif
7196 /******************************************************************************/
7197 #ifndef PALM_1
7198 SOAP_FMAC1
7200 SOAP_FMAC2
7201 soap_begin_send(struct soap *soap)
7202 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
7203 soap_free_ns(soap);
7204 soap->error = SOAP_OK;
7205 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
7206 #ifdef WITH_ZLIB
7207 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
7208 { if (soap->mode & SOAP_ENC_XML)
7209 soap->mode |= SOAP_IO_BUFFER;
7210 else
7211 soap->mode |= SOAP_IO_STORE;
7213 #endif
7214 #ifndef WITH_LEAN
7215 if ((soap->mode & SOAP_IO_UDP))
7216 { soap->mode |= SOAP_ENC_XML;
7217 if (soap->count > SOAP_BUFLEN)
7218 return soap->error = SOAP_UDP_ERROR;
7220 #endif
7221 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
7222 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
7223 soap->mode |= SOAP_IO_BUFFER;
7224 else
7225 soap->mode |= SOAP_IO_STORE;
7227 soap->mode &= ~SOAP_IO_LENGTH;
7228 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
7229 if (soap_new_block(soap) == NULL)
7230 return soap->error;
7231 if (!(soap->mode & SOAP_IO_KEEPALIVE))
7232 soap->keep_alive = 0;
7233 #ifndef WITH_LEANER
7234 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
7235 { soap->mode |= SOAP_ENC_MIME;
7236 soap->mode &= ~SOAP_ENC_DIME;
7238 else if (!(soap->mode & SOAP_ENC_MIME))
7239 soap->mode &= ~SOAP_ENC_MTOM;
7240 if (soap->mode & SOAP_ENC_MIME)
7241 soap_select_mime_boundary(soap);
7242 #ifdef WIN32
7243 #ifndef UNDER_CE
7244 #ifndef WITH_FASTCGI
7245 if (!soap_valid_socket(soap->socket) && !soap->os) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
7246 #ifdef __BORLANDC__
7247 setmode(soap->sendfd, _O_BINARY);
7248 #else
7249 _setmode(soap->sendfd, _O_BINARY);
7250 #endif
7251 #endif
7252 #endif
7253 #endif
7254 #endif
7255 if (soap->mode & SOAP_IO)
7256 { soap->bufidx = 0;
7257 soap->buflen = 0;
7259 soap->chunksize = 0;
7260 soap->ns = 0;
7261 soap->null = 0;
7262 soap->position = 0;
7263 soap->mustUnderstand = 0;
7264 soap->encoding = 0;
7265 soap->idnum = 0;
7266 soap->level = 0;
7267 soap_clr_attr(soap);
7268 soap_set_local_namespaces(soap);
7269 #ifdef WITH_ZLIB
7270 soap->z_ratio_out = 1.0;
7271 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
7272 { if (!soap->z_buf)
7273 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
7274 soap->d_stream->next_out = (Byte*)soap->z_buf;
7275 soap->d_stream->avail_out = SOAP_BUFLEN;
7276 #ifdef WITH_GZIP
7277 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
7278 { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
7279 soap->d_stream->next_out = (Byte*)soap->z_buf + 10;
7280 soap->d_stream->avail_out = SOAP_BUFLEN - 10;
7281 soap->z_crc = crc32(0L, NULL, 0);
7282 soap->zlib_out = SOAP_ZLIB_GZIP;
7283 if (soap->z_dict)
7284 *((Byte*)soap->z_buf + 2) = 0xff;
7285 if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
7286 return soap->error = SOAP_ZLIB_ERROR;
7288 else
7289 #endif
7290 if (deflateInit(soap->d_stream, soap->z_level) != Z_OK)
7291 return soap->error = SOAP_ZLIB_ERROR;
7292 if (soap->z_dict)
7293 { if (deflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
7294 return soap->error = SOAP_ZLIB_ERROR;
7296 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
7297 soap->zlib_state = SOAP_ZLIB_DEFLATE;
7299 #endif
7300 #ifdef WITH_OPENSSL
7301 if (soap->ssl)
7302 ERR_clear_error();
7303 #endif
7304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
7305 soap->part = SOAP_BEGIN;
7306 #ifndef WITH_LEANER
7307 if (soap->fprepareinitsend && (soap->mode & SOAP_IO) == SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
7308 return soap->error;
7309 #endif
7310 return SOAP_OK;
7312 #endif
7314 /******************************************************************************/
7315 #ifndef WITH_NOIDREF
7316 #ifndef PALM_2
7317 SOAP_FMAC1
7318 void
7319 SOAP_FMAC2
7320 soap_embedded(struct soap *soap, const void *p, int t)
7321 { struct soap_plist *pp;
7322 if (soap_pointer_lookup(soap, p, t, &pp))
7323 { pp->mark1 = 1;
7324 pp->mark2 = 1;
7325 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
7328 #endif
7329 #endif
7331 /******************************************************************************/
7332 #ifndef WITH_NOIDREF
7333 #ifndef PALM_2
7334 SOAP_FMAC1
7336 SOAP_FMAC2
7337 soap_reference(struct soap *soap, const void *p, int t)
7338 { struct soap_plist *pp;
7339 if (!p || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
7340 return 1;
7341 if (soap_pointer_lookup(soap, p, t, &pp))
7342 { if (pp->mark1 == 0)
7343 { pp->mark1 = 2;
7344 pp->mark2 = 2;
7347 else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
7348 return 1;
7349 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
7350 return pp->mark1;
7352 #endif
7353 #endif
7355 /******************************************************************************/
7356 #ifndef WITH_NOIDREF
7357 #ifndef PALM_2
7358 SOAP_FMAC1
7360 SOAP_FMAC2
7361 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
7362 { struct soap_plist *pp;
7363 if (!p || !a->__ptr || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
7364 return 1;
7365 if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
7366 { if (pp->mark1 == 0)
7367 { pp->mark1 = 2;
7368 pp->mark2 = 2;
7371 else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
7372 return 1;
7373 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));
7374 return pp->mark1;
7376 #endif
7377 #endif
7379 /******************************************************************************/
7380 #ifndef WITH_NOIDREF
7381 #ifndef PALM_2
7382 SOAP_FMAC1
7384 SOAP_FMAC2
7385 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
7386 { struct soap_plist *pp = NULL;
7387 if (!id || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
7388 return id;
7389 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
7390 if (soap->version == 1 && soap->part != SOAP_IN_HEADER)
7391 { if (id < 0)
7392 { id = soap_pointer_lookup(soap, p, t, &pp);
7393 if (id)
7394 { if (soap->mode & SOAP_IO_LENGTH)
7395 pp->mark1 = 2;
7396 else
7397 pp->mark2 = 2;
7398 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));
7400 return -1;
7402 return id;
7404 if (id < 0)
7405 id = soap_pointer_lookup(soap, p, t, &pp);
7406 else if (id && !soap_pointer_lookup(soap, p, t, &pp))
7407 return 0;
7408 if (id && pp)
7409 { if (soap->mode & SOAP_IO_LENGTH)
7410 pp->mark1 = 1;
7411 else
7412 pp->mark2 = 1;
7413 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));
7415 return id;
7417 #endif
7418 #endif
7420 /******************************************************************************/
7421 #ifndef WITH_NOIDREF
7422 #ifndef PALM_2
7423 SOAP_FMAC1
7425 SOAP_FMAC2
7426 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
7427 { if (!pp)
7428 return 0;
7429 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
7430 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
7431 { if (soap->mode & SOAP_IO_LENGTH)
7432 return pp->mark1 != 0;
7433 return pp->mark2 != 0;
7435 if (soap->mode & SOAP_IO_LENGTH)
7436 return pp->mark1 == 1;
7437 return pp->mark2 == 1;
7439 #endif
7440 #endif
7442 /******************************************************************************/
7443 #ifndef WITH_NOIDREF
7444 #ifndef PALM_2
7445 SOAP_FMAC1
7447 SOAP_FMAC2
7448 soap_is_single(struct soap *soap, struct soap_plist *pp)
7449 { if (soap->part == SOAP_IN_HEADER)
7450 return 1;
7451 if (!pp)
7452 return 0;
7453 if (soap->mode & SOAP_IO_LENGTH)
7454 return pp->mark1 == 0;
7455 return pp->mark2 == 0;
7457 #endif
7458 #endif
7460 /******************************************************************************/
7461 #ifndef WITH_NOIDREF
7462 #ifndef PALM_2
7463 SOAP_FMAC1
7464 void
7465 SOAP_FMAC2
7466 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
7467 { if (!pp)
7468 return;
7469 if (soap->mode & SOAP_IO_LENGTH)
7470 pp->mark1 = 1;
7471 else
7472 pp->mark2 = 1;
7474 #endif
7475 #endif
7477 /******************************************************************************/
7478 #ifndef WITH_LEANER
7479 #ifndef PALM_1
7480 SOAP_FMAC1
7482 SOAP_FMAC2
7483 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)
7485 #ifndef WITH_NOIDREF
7486 struct soap_plist *pp;
7487 int i;
7488 if (!p || !a->__ptr || (!aid && !atype))
7489 return soap_element_id(soap, tag, id, p, a, n, type, t);
7490 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid ? aid : SOAP_STR_EOS, id, atype ? atype : SOAP_STR_EOS));
7491 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
7492 if (!i)
7493 { i = soap_pointer_enter(soap, p, a, n, t, &pp);
7494 if (!i)
7495 { soap->error = SOAP_EOM;
7496 return -1;
7499 if (id <= 0)
7500 id = i;
7501 if (!aid)
7503 #ifdef HAVE_SNPRINTF
7504 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->dime_id_format, id);
7505 #else
7506 sprintf(soap->tmpbuf, soap->dime_id_format, id);
7507 #endif
7508 aid = soap_strdup(soap, soap->tmpbuf);
7510 /* Add MTOM xop:Include element when necessary */
7511 /* TODO: this code to be obsoleted with new import/xop.h conventions */
7512 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
7513 { if (soap_element_begin_out(soap, tag, 0, type)
7514 || soap_element_href(soap, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid)
7515 || soap_element_end_out(soap, tag))
7516 return soap->error;
7518 else if (soap_element_href(soap, tag, 0, "href", aid))
7519 return soap->error;
7520 if (soap->mode & SOAP_IO_LENGTH)
7521 { if (pp->mark1 != 3)
7522 { struct soap_multipart *content;
7523 if (soap->mode & SOAP_ENC_MTOM)
7524 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
7525 else
7526 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
7527 if (!content)
7528 { soap->error = SOAP_EOM;
7529 return -1;
7531 if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
7532 { if (soap->mode & SOAP_ENC_MTOM)
7533 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
7534 if (s)
7535 { *s = '<';
7536 strcpy(s + 1, aid + 4);
7537 strcat(s, ">");
7538 content->id = s;
7541 else
7542 content->id = aid + 4;
7544 else
7545 content->id = aid;
7546 content->type = atype;
7547 content->options = aoptions;
7548 content->encoding = SOAP_MIME_BINARY;
7549 pp->mark1 = 3;
7552 else
7553 pp->mark2 = 3;
7554 #endif
7555 return -1;
7557 #endif
7558 #endif
7560 /******************************************************************************/
7561 #ifndef WITH_NOIDREF
7562 #ifndef PALM_1
7563 static void
7564 soap_init_iht(struct soap *soap)
7565 { register int i;
7566 for (i = 0; i < SOAP_IDHASH; i++)
7567 soap->iht[i] = NULL;
7569 #endif
7570 #endif
7572 /******************************************************************************/
7573 #ifndef WITH_NOIDREF
7574 #ifndef PALM_1
7575 static void
7576 soap_free_iht(struct soap *soap)
7577 { register int i;
7578 register struct soap_ilist *ip = NULL, *p = NULL;
7579 register struct soap_flist *fp = NULL, *fq = NULL;
7580 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
7581 for (i = 0; i < SOAP_IDHASH; i++)
7582 { for (ip = soap->iht[i]; ip; ip = p)
7583 { for (fp = ip->flist; fp; fp = fq)
7584 { fq = fp->next;
7585 SOAP_FREE(soap, fp);
7587 p = ip->next;
7588 SOAP_FREE(soap, ip);
7590 soap->iht[i] = NULL;
7593 #endif
7594 #endif
7596 /******************************************************************************/
7597 #ifndef WITH_NOIDREF
7598 #ifndef PALM_2
7599 SOAP_FMAC1
7600 struct soap_ilist *
7601 SOAP_FMAC2
7602 soap_lookup(struct soap *soap, const char *id)
7603 { register struct soap_ilist *ip = NULL;
7604 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
7605 if (!strcmp(ip->id, id))
7606 return ip;
7607 return NULL;
7609 #endif
7610 #endif
7612 /******************************************************************************/
7613 #ifndef WITH_NOIDREF
7614 #ifndef PALM_2
7615 SOAP_FMAC1
7616 struct soap_ilist *
7617 SOAP_FMAC2
7618 soap_enter(struct soap *soap, const char *id)
7619 { register size_t h;
7620 register struct soap_ilist *ip;
7621 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
7622 if (ip)
7623 { strcpy((char*)ip->id, id);
7624 h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
7625 ip->next = soap->iht[h];
7626 soap->iht[h] = ip;
7628 return ip;
7630 #endif
7631 #endif
7633 /******************************************************************************/
7634 #ifndef PALM_2
7635 SOAP_FMAC1
7636 void*
7637 SOAP_FMAC2
7638 soap_malloc(struct soap *soap, size_t n)
7639 { register char *p;
7640 if (!n)
7641 return (void*)SOAP_NON_NULL;
7642 if (!soap)
7643 return SOAP_MALLOC(soap, n);
7644 if (soap->fmalloc)
7645 p = (char*)soap->fmalloc(soap, n);
7646 else
7647 { n += sizeof(short);
7648 n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
7649 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
7650 { soap->error = SOAP_EOM;
7651 return NULL;
7653 /* set the canary to detect corruption */
7654 *(unsigned short*)(p + n - sizeof(unsigned short)) = (unsigned short)SOAP_CANARY;
7655 /* keep chain of alloced cells for destruction */
7656 *(void**)(p + n) = soap->alist;
7657 *(size_t*)(p + n + sizeof(void*)) = n;
7658 soap->alist = p + n;
7660 soap->alloced = 1;
7661 return p;
7663 #endif
7665 /******************************************************************************/
7666 #ifdef SOAP_MEM_DEBUG
7667 static void
7668 soap_init_mht(struct soap *soap)
7669 { register int i;
7670 for (i = 0; i < (int)SOAP_PTRHASH; i++)
7671 soap->mht[i] = NULL;
7673 #endif
7675 /******************************************************************************/
7676 #ifdef SOAP_MEM_DEBUG
7677 static void
7678 soap_free_mht(struct soap *soap)
7679 { register int i;
7680 register struct soap_mlist *mp, *mq;
7681 for (i = 0; i < (int)SOAP_PTRHASH; i++)
7682 { for (mp = soap->mht[i]; mp; mp = mq)
7683 { mq = mp->next;
7684 if (mp->live)
7685 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
7686 free(mp);
7688 soap->mht[i] = NULL;
7691 #endif
7693 /******************************************************************************/
7694 #ifdef SOAP_MEM_DEBUG
7695 SOAP_FMAC1
7696 void*
7697 SOAP_FMAC2
7698 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
7699 { register void *p = malloc(size);
7700 if (soap)
7701 { register size_t h = soap_hash_ptr(p);
7702 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
7703 if (soap->fdebug[SOAP_INDEX_TEST])
7704 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
7706 mp->next = soap->mht[h];
7707 mp->ptr = p;
7708 mp->file = file;
7709 mp->line = line;
7710 mp->live = 1;
7711 soap->mht[h] = mp;
7713 return p;
7715 #endif
7717 /******************************************************************************/
7718 #ifdef SOAP_MEM_DEBUG
7719 SOAP_FMAC1
7720 void
7721 SOAP_FMAC2
7722 soap_track_free(struct soap *soap, const char *file, int line, void *p)
7723 { register size_t h = soap_hash_ptr(p);
7724 register struct soap_mlist *mp;
7725 for (mp = soap->mht[h]; mp; mp = mp->next)
7726 if (mp->ptr == p)
7727 break;
7728 if (mp)
7729 { if (mp->live)
7730 { free(p);
7731 if (soap->fdebug[SOAP_INDEX_TEST])
7732 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
7734 mp->live = 0;
7736 else
7737 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
7739 else
7740 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
7742 #endif
7744 /******************************************************************************/
7745 #ifdef SOAP_MEM_DEBUG
7746 static void
7747 soap_track_unlink(struct soap *soap, const void *p)
7748 { register size_t h = soap_hash_ptr(p);
7749 register struct soap_mlist *mp;
7750 for (mp = soap->mht[h]; mp; mp = mp->next)
7751 if (mp->ptr == p)
7752 break;
7753 if (mp)
7754 mp->live = 0;
7756 #endif
7758 /******************************************************************************/
7759 #ifndef PALM_2
7760 SOAP_FMAC1
7761 void
7762 SOAP_FMAC2
7763 soap_dealloc(struct soap *soap, void *p)
7764 { if (soap_check_state(soap))
7765 return;
7766 if (p)
7767 { register char **q;
7768 for (q = (char**)&soap->alist; *q; q = *(char***)q)
7770 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7772 #ifdef SOAP_MEM_DEBUG
7773 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
7774 #endif
7775 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
7776 DBGHEX(TEST, *q - 200, 200);
7777 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
7778 soap->error = SOAP_MOE;
7779 return;
7781 if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
7782 { *q = **(char***)q;
7783 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
7784 SOAP_FREE(soap, p);
7785 return;
7788 soap_delete(soap, p);
7790 else
7791 { register char *q;
7792 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
7793 while (soap->alist)
7794 { q = (char*)soap->alist;
7795 if (*(unsigned short*)(char*)(q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7797 #ifdef SOAP_MEM_DEBUG
7798 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
7799 #endif
7800 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
7801 DBGHEX(TEST, q - 200, 200);
7802 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
7803 soap->error = SOAP_MOE;
7804 return;
7806 soap->alist = *(void**)q;
7807 q -= *(size_t*)(q + sizeof(void*));
7808 SOAP_FREE(soap, q);
7810 /* we must assume these were deallocated: */
7811 soap->http_content = NULL;
7812 soap->action = NULL;
7813 soap->fault = NULL;
7814 soap->header = NULL;
7815 soap->userid = NULL;
7816 soap->passwd = NULL;
7817 soap->authrealm = NULL;
7818 #ifdef WITH_NTLM
7819 soap->ntlm_challenge = NULL;
7820 #endif
7821 #ifndef WITH_LEANER
7822 soap_clr_mime(soap);
7823 #endif
7826 #endif
7828 /******************************************************************************/
7829 #ifndef PALM_2
7830 SOAP_FMAC1
7831 void
7832 SOAP_FMAC2
7833 soap_delete(struct soap *soap, void *p)
7834 { register struct soap_clist **cp;
7835 if (soap_check_state(soap))
7836 return;
7837 cp = &soap->clist;
7838 if (p)
7839 { while (*cp)
7840 { if (p == (*cp)->ptr)
7841 { register struct soap_clist *q = *cp;
7842 *cp = q->next;
7843 if (q->fdelete(q))
7844 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
7845 #ifdef SOAP_MEM_DEBUG
7846 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
7847 #endif
7849 SOAP_FREE(soap, q);
7850 return;
7852 cp = &(*cp)->next;
7854 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
7856 else
7857 { while (*cp)
7858 { register struct soap_clist *q = *cp;
7859 *cp = q->next;
7860 if (q->fdelete(q))
7861 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
7862 #ifdef SOAP_MEM_DEBUG
7863 fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
7864 #endif
7866 SOAP_FREE(soap, q);
7869 soap->fault = NULL; /* this was possibly deallocated */
7870 soap->header = NULL; /* this was possibly deallocated */
7872 #endif
7874 /******************************************************************************/
7875 #ifndef PALM_2
7876 SOAP_FMAC1
7877 void
7878 SOAP_FMAC2
7879 soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
7880 { register struct soap_clist *cp;
7881 register char **q;
7882 #ifdef SOAP_MEM_DEBUG
7883 register void *p;
7884 register struct soap_mlist **mp, *mq;
7885 size_t h;
7886 #endif
7887 for (q = (char**)&soap->alist; *q; q = *(char***)q)
7889 if (*(unsigned short*)(char*)(*q - sizeof(unsigned short)) != (unsigned short)SOAP_CANARY)
7891 #ifdef SOAP_MEM_DEBUG
7892 fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
7893 #endif
7894 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
7895 DBGHEX(TEST, *q - 200, 200);
7896 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
7897 soap->error = SOAP_MOE;
7898 return;
7900 #ifdef SOAP_MEM_DEBUG
7901 p = (void*)(*q - *(size_t*)(*q + sizeof(void*)));
7902 h = soap_hash_ptr(p);
7903 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
7904 { if ((*mp)->ptr == p)
7905 { mq = *mp;
7906 *mp = mq->next;
7907 mq->next = soap_to->mht[h];
7908 soap_to->mht[h] = mq;
7909 break;
7912 #endif
7914 *q = (char*)soap_to->alist;
7915 soap_to->alist = soap->alist;
7916 soap->alist = NULL;
7917 #ifdef SOAP_MEM_DEBUG
7918 cp = soap->clist;
7919 while (cp)
7920 { h = soap_hash_ptr(cp);
7921 for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
7922 { if ((*mp)->ptr == cp)
7923 { mq = *mp;
7924 *mp = mq->next;
7925 mq->next = soap_to->mht[h];
7926 soap_to->mht[h] = mq;
7927 break;
7930 cp = cp->next;
7932 #endif
7933 cp = soap_to->clist;
7934 if (cp)
7935 { while (cp->next)
7936 cp = cp->next;
7937 cp->next = soap->clist;
7939 else
7940 soap_to->clist = soap->clist;
7941 soap->clist = NULL;
7943 #endif
7945 /******************************************************************************/
7946 #ifndef PALM_2
7947 SOAP_FMAC1
7948 struct soap_clist *
7949 SOAP_FMAC2
7950 soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*))
7951 { register struct soap_clist *cp;
7952 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
7953 { cp->next = soap->clist;
7954 cp->type = t;
7955 cp->size = n;
7956 cp->ptr = p;
7957 cp->fdelete = fdelete;
7958 soap->clist = cp;
7960 return cp;
7962 #endif
7964 /******************************************************************************/
7965 #ifndef PALM_2
7966 SOAP_FMAC1
7968 SOAP_FMAC2
7969 soap_unlink(struct soap *soap, const void *p)
7970 { register char **q;
7971 register struct soap_clist **cp;
7972 if (soap && p)
7973 { for (q = (char**)&soap->alist; *q; q = *(char***)q)
7974 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
7975 { *q = **(char***)q;
7976 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
7977 #ifdef SOAP_MEM_DEBUG
7978 soap_track_unlink(soap, p);
7979 #endif
7980 return SOAP_OK; /* found and removed from dealloc chain */
7983 for (cp = &soap->clist; *cp; cp = &(*cp)->next)
7984 { if (p == (*cp)->ptr)
7985 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
7986 q = (char**)*cp;
7987 *cp = (*cp)->next;
7988 SOAP_FREE(soap, q);
7989 return SOAP_OK; /* found and removed from dealloc chain */
7993 return SOAP_ERR;
7995 #endif
7997 /******************************************************************************/
7998 #ifndef WITH_NOIDREF
7999 #ifndef PALM_2
8000 SOAP_FMAC1
8002 SOAP_FMAC2
8003 soap_lookup_type(struct soap *soap, const char *id)
8004 { register struct soap_ilist *ip;
8005 if (id && *id)
8006 { ip = soap_lookup(soap, id);
8007 if (ip)
8008 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
8009 return ip->type;
8012 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
8013 return 0;
8015 #endif
8016 #endif
8018 /******************************************************************************/
8019 #ifndef WITH_NOIDREF
8020 #ifndef PALM_2
8021 SOAP_FMAC1
8022 void*
8023 SOAP_FMAC2
8024 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
8025 { struct soap_ilist *ip;
8026 void **q;
8027 if (!p || !id || !*id)
8028 return p;
8029 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
8030 if (!ip)
8031 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
8032 return NULL;
8033 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
8034 ip->type = t;
8035 ip->size = n;
8036 ip->link = p;
8037 ip->copy = NULL;
8038 ip->flist = NULL;
8039 ip->ptr = NULL;
8040 ip->level = k;
8041 *p = NULL;
8043 else if (ip->ptr)
8044 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
8045 if (ip->type != t)
8046 { strcpy(soap->id, id);
8047 soap->error = SOAP_HREF;
8048 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t));
8049 return NULL;
8051 while (ip->level < k)
8052 { q = (void**)soap_malloc(soap, sizeof(void*));
8053 if (!q)
8054 return NULL;
8055 *p = (void*)q;
8056 p = q;
8057 k--;
8058 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
8060 *p = ip->ptr;
8062 else if (ip->level > k)
8063 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
8064 while (ip->level > k)
8065 { void *s, **r = &ip->link;
8066 q = (void**)ip->link;
8067 while (q)
8068 { *r = (void*)soap_malloc(soap, sizeof(void*));
8069 if (!*r)
8070 return NULL;
8071 s = *q;
8072 *q = *r;
8073 r = (void**)*r;
8074 q = (void**)s;
8076 *r = NULL;
8077 ip->size = n;
8078 ip->copy = NULL;
8079 ip->level = ip->level - 1;
8080 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
8082 q = (void**)ip->link;
8083 ip->link = p;
8084 *p = (void*)q;
8086 else
8087 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
8088 while (ip->level < k)
8089 { q = (void**)soap_malloc(soap, sizeof(void*));
8090 if (!q)
8091 return NULL;
8092 *p = q;
8093 p = q;
8094 k--;
8095 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
8097 q = (void**)ip->link;
8098 ip->link = p;
8099 *p = (void*)q;
8101 return p;
8103 #endif
8104 #endif
8106 /******************************************************************************/
8107 #ifndef WITH_NOIDREF
8108 #ifndef PALM_2
8109 SOAP_FMAC1
8110 void*
8111 SOAP_FMAC2
8112 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))
8113 { struct soap_ilist *ip;
8114 if (!p || !href || !*href)
8115 return p;
8116 ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
8117 if (!ip)
8118 { if (!(ip = soap_enter(soap, href))) /* new hash table entry for string id */
8119 return NULL;
8120 ip->type = st;
8121 ip->size = n;
8122 ip->link = NULL;
8123 ip->copy = NULL;
8124 ip->ptr = NULL;
8125 ip->level = 0;
8126 ip->flist = NULL;
8127 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));
8129 else if (ip->type != st || (ip->level == k && ip->size != n))
8130 { 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));
8131 strcpy(soap->id, href);
8132 soap->error = SOAP_HREF;
8133 return NULL;
8135 if (fcopy || n < sizeof(void*) || *href != '#')
8136 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
8137 if (!fp)
8138 { soap->error = SOAP_EOM;
8139 return NULL;
8141 fp->next = ip->flist;
8142 fp->type = tt;
8143 fp->ptr = p;
8144 fp->level = k;
8145 fp->len = len;
8146 if (fcopy)
8147 fp->fcopy = fcopy;
8148 else
8149 fp->fcopy = soap_fcopy;
8150 ip->flist = fp;
8151 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));
8153 else
8154 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
8155 *(void**)p = ip->copy;
8156 ip->copy = p;
8158 return p;
8160 #endif
8161 #endif
8163 /******************************************************************************/
8164 #ifndef PALM_2
8165 SOAP_FMAC1
8166 void*
8167 SOAP_FMAC2
8168 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*))
8170 #ifndef WITH_NOIDREF
8171 struct soap_ilist *ip;
8172 #endif
8173 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
8174 soap->alloced = 0;
8175 if (!p)
8176 { if (finstantiate)
8177 p = finstantiate(soap, t, type, arrayType, &n);
8178 else
8179 p = soap_malloc(soap, n);
8180 if (p)
8181 soap->alloced = 1;
8183 #ifndef WITH_NOIDREF
8184 if (!id || !*id)
8185 #endif
8186 return p;
8187 #ifndef WITH_NOIDREF
8188 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
8189 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
8190 if (!ip)
8191 { if (!(ip = soap_enter(soap, id))) /* new hash table entry for string id */
8192 return NULL;
8193 ip->type = t;
8194 ip->link = NULL;
8195 ip->copy = NULL;
8196 ip->flist = NULL;
8197 ip->size = n;
8198 ip->ptr = p;
8199 ip->level = k;
8200 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));
8202 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
8203 { 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));
8204 strcpy(soap->id, id);
8205 soap->error = SOAP_HREF;
8206 return NULL;
8208 else if (ip->ptr)
8209 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
8210 strcpy(soap->id, id);
8211 soap->error = SOAP_DUPLICATE_ID;
8212 return NULL;
8214 else
8215 { ip->size = n;
8216 ip->ptr = p;
8217 ip->level = k;
8218 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));
8220 return ip->ptr;
8221 #endif
8223 #endif
8225 /******************************************************************************/
8226 #ifndef PALM_2
8227 SOAP_FMAC1
8228 void
8229 SOAP_FMAC2
8230 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
8231 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
8232 memcpy(p, q, n);
8233 (void)soap; (void)st; (void)tt; (void)len;
8235 #endif
8237 /******************************************************************************/
8238 #ifndef PALM_1
8239 SOAP_FMAC1
8241 SOAP_FMAC2
8242 soap_end_send(struct soap *soap)
8244 #ifndef WITH_LEANER
8245 int err;
8246 if (soap->dime.list)
8247 { /* SOAP body referenced attachments must appear first */
8248 soap->dime.last->next = soap->dime.first;
8249 soap->dime.first = soap->dime.list->next;
8250 soap->dime.list->next = NULL;
8251 soap->dime.last = soap->dime.list;
8253 if (!(err = soap_putdime(soap)))
8254 err = soap_putmime(soap);
8255 soap->mime.list = NULL;
8256 soap->mime.first = NULL;
8257 soap->mime.last = NULL;
8258 soap->dime.list = NULL;
8259 soap->dime.first = NULL;
8260 soap->dime.last = NULL;
8261 if (err)
8262 return err;
8263 #endif
8264 return soap_end_send_flush(soap);
8266 #endif
8268 /******************************************************************************/
8269 #ifndef PALM_1
8270 SOAP_FMAC1
8272 SOAP_FMAC2
8273 soap_end_send_flush(struct soap *soap)
8274 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
8275 if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
8276 { if (soap_flush(soap))
8277 #ifdef WITH_ZLIB
8278 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
8279 { soap->zlib_state = SOAP_ZLIB_NONE;
8280 deflateEnd(soap->d_stream);
8282 return soap->error;
8284 #else
8285 return soap->error;
8286 #endif
8287 #ifdef WITH_ZLIB
8288 if (soap->mode & SOAP_ENC_ZLIB)
8289 { int r;
8290 soap->d_stream->avail_in = 0;
8292 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
8293 r = deflate(soap->d_stream, Z_FINISH);
8294 if (soap->d_stream->avail_out != SOAP_BUFLEN)
8295 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out))
8296 { soap->zlib_state = SOAP_ZLIB_NONE;
8297 deflateEnd(soap->d_stream);
8298 return soap->error;
8300 soap->d_stream->next_out = (Byte*)soap->z_buf;
8301 soap->d_stream->avail_out = SOAP_BUFLEN;
8303 } while (r == Z_OK);
8304 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out));
8305 soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in;
8306 soap->mode &= ~SOAP_ENC_ZLIB;
8307 soap->zlib_state = SOAP_ZLIB_NONE;
8308 if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END)
8309 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS));
8310 return soap->error = SOAP_ZLIB_ERROR;
8312 #ifdef WITH_GZIP
8313 if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
8314 { soap->z_buf[0] = soap->z_crc & 0xFF;
8315 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
8316 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
8317 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
8318 soap->z_buf[4] = soap->d_stream->total_in & 0xFF;
8319 soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF;
8320 soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF;
8321 soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF;
8322 if (soap_flush_raw(soap, soap->z_buf, 8))
8323 return soap->error;
8324 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
8326 #endif
8328 #endif
8329 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
8330 { char *p;
8331 #ifndef WITH_NOHTTP
8332 if (!(soap->mode & SOAP_ENC_XML))
8333 { soap->mode--;
8334 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
8335 if (soap->status >= SOAP_POST)
8336 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
8337 else if (soap->status != SOAP_STOP)
8338 soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
8339 if (soap->error || soap_flush(soap))
8340 return soap->error;
8341 soap->mode++;
8343 #endif
8344 for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
8345 { DBGMSG(SENT, p, soap_block_size(soap, NULL));
8346 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), soap->socket, soap->sendfd));
8347 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL))))
8348 { soap_end_block(soap, NULL);
8349 return soap->error;
8352 soap_end_block(soap, NULL);
8353 if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
8354 return soap->error;
8356 #ifndef WITH_LEANER
8357 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
8358 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
8359 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
8360 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
8361 return soap->error;
8363 #endif
8365 #ifdef WITH_TCPFIN
8366 #ifdef WITH_OPENSSL
8367 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
8368 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
8369 #else
8370 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
8371 soap->fshutdownsocket(soap, soap->socket, SOAP_SHUT_WR); /* Send TCP FIN */
8372 #endif
8373 #endif
8374 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
8375 soap->omode &= ~SOAP_SEC_WSUID;
8376 soap->count = 0;
8377 soap->part = SOAP_END;
8378 return SOAP_OK;
8380 #endif
8382 /******************************************************************************/
8383 #ifndef PALM_1
8384 SOAP_FMAC1
8386 SOAP_FMAC2
8387 soap_end_recv(struct soap *soap)
8388 { soap->part = SOAP_END;
8389 #ifndef WITH_LEAN
8390 soap->wsuid = NULL; /* reset before next send */
8391 soap->c14nexclude = NULL; /* reset before next send */
8392 #endif
8393 #ifndef WITH_LEANER
8394 soap->ffilterrecv = NULL;
8395 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
8396 { soap->dime.first = NULL;
8397 soap->dime.last = NULL;
8398 return soap->error;
8400 soap->dime.list = soap->dime.first;
8401 soap->dime.first = NULL;
8402 soap->dime.last = NULL;
8403 /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
8404 if (soap->mode & SOAP_ENC_MIME)
8405 { if (soap->mode & SOAP_MIME_POSTCHECK)
8406 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Post checking MIME attachments\n"));
8407 if (!soap->keep_alive)
8408 soap->keep_alive = -1;
8409 #ifndef WITH_NOIDREF
8410 soap_resolve(soap);
8411 #endif
8412 return SOAP_OK;
8414 if (soap_getmime(soap))
8415 return soap->error;
8417 soap->mime.list = soap->mime.first;
8418 soap->mime.first = NULL;
8419 soap->mime.last = NULL;
8420 soap->mime.boundary = NULL;
8421 if (soap->xlist)
8422 { struct soap_multipart *content;
8423 for (content = soap->mime.list; content; content = content->next)
8424 soap_resolve_attachment(soap, content);
8426 #endif
8427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
8428 #ifdef WITH_ZLIB
8429 if (soap->mode & SOAP_ENC_ZLIB)
8430 { /* Make sure end of compressed content is reached */
8431 while (soap->d_stream->next_out != Z_NULL)
8432 if ((int)soap_get1(soap) == EOF)
8433 break;
8434 soap->mode &= ~SOAP_ENC_ZLIB;
8435 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
8436 soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf;
8437 soap->buflen = soap->z_buflen;
8438 soap->zlib_state = SOAP_ZLIB_NONE;
8439 if (inflateEnd(soap->d_stream) != Z_OK)
8440 return soap->error = SOAP_ZLIB_ERROR;
8441 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
8442 #ifdef WITH_GZIP
8443 if (soap->zlib_in == SOAP_ZLIB_GZIP)
8444 { soap_wchar c;
8445 short i;
8446 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
8447 for (i = 0; i < 8; i++)
8448 { if ((int)(c = soap_get1(soap)) == EOF)
8449 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: unable to read crc value\n"));
8450 return soap->error = SOAP_ZLIB_ERROR;
8452 soap->z_buf[i] = (char)c;
8454 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)))
8455 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
8456 return soap->error = SOAP_ZLIB_ERROR;
8458 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)))
8459 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip inflate error: incorrect message length\n"));
8460 return soap->error = SOAP_ZLIB_ERROR;
8463 soap->zlib_in = SOAP_ZLIB_NONE;
8464 #endif
8466 #endif
8467 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
8468 while (soap->ahead != EOF && !soap_recv_raw(soap))
8470 #ifndef WITH_NOIDREF
8471 if (soap_resolve(soap))
8472 return soap->error;
8473 #endif
8474 #ifndef WITH_LEANER
8475 if (soap->xlist)
8476 { if (soap->mode & SOAP_ENC_MTOM)
8477 return soap->error = SOAP_MIME_HREF;
8478 return soap->error = SOAP_DIME_HREF;
8480 #endif
8481 soap_free_ns(soap);
8482 #ifndef WITH_LEANER
8483 if (soap->fpreparefinalrecv)
8484 return soap->error = soap->fpreparefinalrecv(soap);
8485 #endif
8486 return SOAP_OK;
8488 #endif
8490 /******************************************************************************/
8491 #ifndef PALM_1
8492 SOAP_FMAC1
8493 void
8494 SOAP_FMAC2
8495 soap_free_temp(struct soap *soap)
8496 { register struct soap_attribute *tp, *tq;
8497 register struct Namespace *ns;
8498 soap_free_ns(soap);
8499 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
8500 while (soap->blist)
8501 soap_end_block(soap, NULL);
8502 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
8503 for (tp = soap->attributes; tp; tp = tq)
8504 { tq = tp->next;
8505 if (tp->value)
8506 SOAP_FREE(soap, tp->value);
8507 SOAP_FREE(soap, tp);
8509 soap->attributes = NULL;
8510 #ifdef WITH_FAST
8511 if (soap->labbuf)
8512 SOAP_FREE(soap, soap->labbuf);
8513 soap->labbuf = NULL;
8514 soap->lablen = 0;
8515 soap->labidx = 0;
8516 #endif
8517 ns = soap->local_namespaces;
8518 if (ns)
8519 { for (; ns->id; ns++)
8520 { if (ns->out)
8521 { SOAP_FREE(soap, ns->out);
8522 ns->out = NULL;
8525 SOAP_FREE(soap, soap->local_namespaces);
8526 soap->local_namespaces = NULL;
8528 #ifndef WITH_LEANER
8529 while (soap->xlist)
8530 { struct soap_xlist *xp = soap->xlist->next;
8531 SOAP_FREE(soap, soap->xlist);
8532 soap->xlist = xp;
8534 #endif
8535 #ifndef WITH_NOIDREF
8536 soap_free_pht(soap);
8537 soap_free_iht(soap);
8538 #endif
8540 #endif
8542 /******************************************************************************/
8543 #ifndef PALM_1
8544 static void
8545 soap_free_ns(struct soap *soap)
8546 { register struct soap_nlist *np, *nq;
8547 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
8548 for (np = soap->nlist; np; np = nq)
8549 { nq = np->next;
8550 SOAP_FREE(soap, np);
8552 soap->nlist = NULL;
8554 #endif
8556 /******************************************************************************/
8557 #ifndef PALM_1
8558 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8559 static void
8560 soap_init_logs(struct soap *soap)
8561 { int i;
8562 for (i = 0; i < SOAP_MAXLOGS; i++)
8563 { soap->logfile[i] = NULL;
8564 soap->fdebug[i] = NULL;
8567 #endif
8568 #endif
8570 /******************************************************************************/
8571 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8572 SOAP_FMAC1
8573 void
8574 SOAP_FMAC2
8575 soap_open_logfile(struct soap *soap, int i)
8576 { if (soap->logfile[i])
8577 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
8579 #endif
8581 /******************************************************************************/
8582 #ifdef SOAP_DEBUG
8583 static void
8584 soap_close_logfile(struct soap *soap, int i)
8585 { if (soap->fdebug[i])
8586 { fclose(soap->fdebug[i]);
8587 soap->fdebug[i] = NULL;
8590 #endif
8592 /******************************************************************************/
8593 #ifdef SOAP_DEBUG
8594 SOAP_FMAC1
8595 void
8596 SOAP_FMAC2
8597 soap_close_logfiles(struct soap *soap)
8598 { int i;
8599 for (i = 0; i < SOAP_MAXLOGS; i++)
8600 soap_close_logfile(soap, i);
8602 #endif
8604 /******************************************************************************/
8605 #ifdef SOAP_DEBUG
8606 static void
8607 soap_set_logfile(struct soap *soap, int i, const char *logfile)
8608 { const char *s;
8609 char *t = NULL;
8610 soap_close_logfile(soap, i);
8611 s = soap->logfile[i];
8612 soap->logfile[i] = logfile;
8613 if (s)
8614 SOAP_FREE(soap, (void*)s);
8615 if (logfile)
8616 if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
8617 strcpy(t, logfile);
8618 soap->logfile[i] = t;
8620 #endif
8622 /******************************************************************************/
8623 SOAP_FMAC1
8624 void
8625 SOAP_FMAC2
8626 soap_set_recv_logfile(struct soap *soap, const char *logfile)
8628 #ifdef SOAP_DEBUG
8629 soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
8630 #endif
8633 /******************************************************************************/
8634 SOAP_FMAC1
8635 void
8636 SOAP_FMAC2
8637 soap_set_sent_logfile(struct soap *soap, const char *logfile)
8639 #ifdef SOAP_DEBUG
8640 soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
8641 #endif
8644 /******************************************************************************/
8645 SOAP_FMAC1
8646 void
8647 SOAP_FMAC2
8648 soap_set_test_logfile(struct soap *soap, const char *logfile)
8650 #ifdef SOAP_DEBUG
8651 soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
8652 #endif
8655 /******************************************************************************/
8656 #ifndef PALM_1
8657 SOAP_FMAC1
8658 struct soap*
8659 SOAP_FMAC2
8660 soap_copy(const struct soap *soap)
8661 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
8663 #endif
8665 /******************************************************************************/
8666 #ifndef PALM_1
8667 SOAP_FMAC1
8668 struct soap*
8669 SOAP_FMAC2
8670 soap_copy_context(struct soap *copy, const struct soap *soap)
8671 { if (copy == soap)
8672 return copy;
8673 if (soap_check_state(soap))
8674 return NULL;
8675 if (copy)
8676 { register struct soap_plugin *p = NULL;
8677 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying context\n"));
8678 #ifdef __cplusplus
8679 *copy = *soap;
8680 #else
8681 memcpy(copy, soap, sizeof(struct soap));
8682 #endif
8683 copy->state = SOAP_COPY;
8684 copy->error = SOAP_OK;
8685 copy->userid = NULL;
8686 copy->passwd = NULL;
8687 #ifdef WITH_NTLM
8688 copy->ntlm_challenge = NULL;
8689 #endif
8690 copy->nlist = NULL;
8691 copy->blist = NULL;
8692 copy->clist = NULL;
8693 copy->alist = NULL;
8694 copy->attributes = NULL;
8695 copy->labbuf = NULL;
8696 copy->lablen = 0;
8697 copy->labidx = 0;
8698 #ifdef SOAP_MEM_DEBUG
8699 soap_init_mht(copy);
8700 #endif
8701 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8702 soap_init_logs(copy);
8703 #endif
8704 #ifdef SOAP_DEBUG
8705 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
8706 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
8707 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
8708 #endif
8709 copy->namespaces = soap->local_namespaces;
8710 copy->local_namespaces = NULL;
8711 soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */
8712 copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */
8713 #ifdef WITH_C_LOCALE
8714 # ifdef WIN32
8715 copy->c_locale = _create_locale(LC_ALL, "C");
8716 # else
8717 copy->c_locale = duplocale(soap->c_locale);
8718 # endif
8719 #else
8720 copy->c_locale = NULL;
8721 #endif
8722 #ifdef WITH_OPENSSL
8723 copy->bio = NULL;
8724 copy->ssl = NULL;
8725 copy->session = NULL;
8726 #endif
8727 #ifdef WITH_GNUTLS
8728 copy->session = NULL;
8729 #endif
8730 #ifdef WITH_ZLIB
8731 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
8732 copy->d_stream->zalloc = Z_NULL;
8733 copy->d_stream->zfree = Z_NULL;
8734 copy->d_stream->opaque = Z_NULL;
8735 copy->z_buf = NULL;
8736 #endif
8737 #ifndef WITH_NOIDREF
8738 soap_init_iht(copy);
8739 soap_init_pht(copy);
8740 #endif
8741 copy->header = NULL;
8742 copy->fault = NULL;
8743 copy->action = NULL;
8744 #ifndef WITH_LEAN
8745 #ifdef WITH_COOKIES
8746 copy->cookies = soap_copy_cookies(copy, soap);
8747 #else
8748 copy->cookies = NULL;
8749 #endif
8750 #endif
8751 copy->plugins = NULL;
8752 for (p = soap->plugins; p; p = p->next)
8753 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
8754 if (!q)
8755 return NULL;
8756 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
8757 *q = *p;
8758 if (p->fcopy && p->fcopy(copy, q, p))
8759 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
8760 SOAP_FREE(copy, q);
8761 return NULL;
8763 q->next = copy->plugins;
8764 copy->plugins = q;
8767 return copy;
8769 #endif
8771 /******************************************************************************/
8772 #ifndef PALM_1
8773 SOAP_FMAC1
8774 void
8775 SOAP_FMAC2
8776 soap_copy_stream(struct soap *copy, struct soap *soap)
8777 { struct soap_attribute *tp = NULL, *tq;
8778 if (copy == soap)
8779 return;
8780 copy->header = soap->header;
8781 copy->mode = soap->mode;
8782 copy->imode = soap->imode;
8783 copy->omode = soap->omode;
8784 copy->master = soap->master;
8785 copy->socket = soap->socket;
8786 copy->sendsk = soap->sendsk;
8787 copy->recvsk = soap->recvsk;
8788 copy->recv_timeout = soap->recv_timeout;
8789 copy->send_timeout = soap->send_timeout;
8790 #if defined(__cplusplus) && !defined(WITH_LEAN)
8791 copy->os = soap->os;
8792 copy->is = soap->is;
8793 #endif
8794 copy->sendfd = soap->sendfd;
8795 copy->recvfd = soap->recvfd;
8796 copy->bufidx = soap->bufidx;
8797 copy->buflen = soap->buflen;
8798 copy->ahead = soap->ahead;
8799 copy->cdata = soap->cdata;
8800 copy->chunksize = soap->chunksize;
8801 copy->chunkbuflen = soap->chunkbuflen;
8802 copy->keep_alive = soap->keep_alive;
8803 copy->tcp_keep_alive = soap->tcp_keep_alive;
8804 copy->tcp_keep_idle = soap->tcp_keep_idle;
8805 copy->tcp_keep_intvl = soap->tcp_keep_intvl;
8806 copy->tcp_keep_cnt = soap->tcp_keep_cnt;
8807 copy->max_keep_alive = soap->max_keep_alive;
8808 #ifndef WITH_NOIO
8809 copy->peer = soap->peer;
8810 copy->peerlen = soap->peerlen;
8811 copy->ip = soap->ip;
8812 copy->port = soap->port;
8813 memcpy(copy->host, soap->host, sizeof(soap->host));
8814 memcpy(copy->endpoint, soap->endpoint, sizeof(soap->endpoint));
8815 #endif
8816 #ifdef WITH_OPENSSL
8817 copy->bio = soap->bio;
8818 copy->ctx = soap->ctx;
8819 copy->ssl = soap->ssl;
8820 #endif
8821 #ifdef WITH_GNUTLS
8822 copy->session = soap->session;
8823 #endif
8824 #ifdef WITH_ZLIB
8825 copy->zlib_state = soap->zlib_state;
8826 copy->zlib_in = soap->zlib_in;
8827 copy->zlib_out = soap->zlib_out;
8828 if (!copy->d_stream)
8829 copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream));
8830 if (copy->d_stream)
8831 memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream));
8832 copy->z_crc = soap->z_crc;
8833 copy->z_ratio_in = soap->z_ratio_in;
8834 copy->z_ratio_out = soap->z_ratio_out;
8835 copy->z_buf = NULL;
8836 copy->z_buflen = soap->z_buflen;
8837 copy->z_level = soap->z_level;
8838 if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE)
8839 { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN);
8840 if (copy->z_buf)
8841 memcpy(copy->z_buf, soap->z_buf, SOAP_BUFLEN);
8843 copy->z_dict = soap->z_dict;
8844 copy->z_dict_len = soap->z_dict_len;
8845 #endif
8846 memcpy(copy->buf, soap->buf, sizeof(soap->buf));
8847 /* copy XML parser state */
8848 soap_free_ns(copy);
8849 soap_set_local_namespaces(copy);
8850 copy->version = soap->version;
8851 if (soap->nlist && soap->local_namespaces)
8852 { register struct soap_nlist *np = NULL, *nq;
8853 /* copy reversed nlist */
8854 for (nq = soap->nlist; nq; nq = nq->next)
8855 { register struct soap_nlist *nr = np;
8856 size_t n = sizeof(struct soap_nlist) + strlen(nq->id);
8857 np = (struct soap_nlist*)SOAP_MALLOC(copy, n);
8858 if (!np)
8859 break;
8860 memcpy(np, nq, n);
8861 np->next = nr;
8863 while (np)
8864 { register const char *s = np->ns;
8865 copy->level = np->level; /* preserve element nesting level */
8866 if (!s && np->index >= 0)
8867 { s = soap->local_namespaces[np->index].out;
8868 if (!s)
8869 s = soap->local_namespaces[np->index].ns;
8871 if (s && soap_push_namespace(copy, np->id, s) == NULL)
8872 break;
8873 nq = np;
8874 np = np->next;
8875 SOAP_FREE(copy, nq);
8878 memcpy(copy->tag, soap->tag, sizeof(copy->tag));
8879 memcpy(copy->id, soap->id, sizeof(copy->id));
8880 memcpy(copy->href, soap->href, sizeof(copy->href));
8881 memcpy(copy->type, soap->type, sizeof(copy->type));
8882 copy->other = soap->other;
8883 copy->root = soap->root;
8884 copy->null = soap->null;
8885 copy->body = soap->body;
8886 copy->part = soap->part;
8887 copy->mustUnderstand = soap->mustUnderstand;
8888 copy->level = soap->level;
8889 copy->peeked = soap->peeked;
8890 /* copy attributes */
8891 for (tq = soap->attributes; tq; tq = tq->next)
8892 { struct soap_attribute *tr = tp;
8893 size_t n = sizeof(struct soap_attribute) + strlen(tq->name);
8894 tp = (struct soap_attribute*)SOAP_MALLOC(copy, n);
8895 memcpy(tp, tq, n);
8896 if (tp->size)
8897 { tp->value = (char*)SOAP_MALLOC(copy, tp->size);
8898 if (tp->value)
8899 strcpy(tp->value, tq->value);
8901 tp->ns = NULL;
8902 tp->next = tr;
8904 copy->attributes = tp;
8906 #endif
8908 /******************************************************************************/
8909 #ifndef PALM_1
8910 SOAP_FMAC1
8911 void
8912 SOAP_FMAC2
8913 soap_free_stream(struct soap *soap)
8914 { soap->socket = SOAP_INVALID_SOCKET;
8915 soap->sendsk = SOAP_INVALID_SOCKET;
8916 soap->recvsk = SOAP_INVALID_SOCKET;
8917 #ifdef WITH_OPENSSL
8918 soap->bio = NULL;
8919 soap->ctx = NULL;
8920 soap->ssl = NULL;
8921 #endif
8922 #ifdef WITH_GNUTLS
8923 soap->xcred = NULL;
8924 soap->acred = NULL;
8925 soap->cache = NULL;
8926 soap->session = NULL;
8927 soap->dh_params = NULL;
8928 soap->rsa_params = NULL;
8929 #endif
8930 #ifdef WITH_ZLIB
8931 if (soap->z_buf)
8932 SOAP_FREE(soap, soap->z_buf);
8933 soap->z_buf = NULL;
8934 #endif
8936 #endif
8938 /******************************************************************************/
8939 #ifndef PALM_1
8940 SOAP_FMAC1
8941 void
8942 SOAP_FMAC2
8943 soap_initialize(struct soap *soap)
8944 { soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
8946 #endif
8948 /******************************************************************************/
8949 #ifndef PALM_1
8950 SOAP_FMAC1
8951 void
8952 SOAP_FMAC2
8953 soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
8954 { size_t i;
8955 soap->state = SOAP_INIT;
8956 #ifdef SOAP_MEM_DEBUG
8957 soap_init_mht(soap);
8958 #endif
8959 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8960 soap_init_logs(soap);
8961 #endif
8962 #ifdef SOAP_DEBUG
8963 #ifdef TANDEM_NONSTOP
8964 soap_set_test_logfile(soap, "TESTLOG");
8965 soap_set_sent_logfile(soap, "SENTLOG");
8966 soap_set_recv_logfile(soap, "RECVLOG");
8967 #else
8968 soap_set_test_logfile(soap, "TEST.log");
8969 soap_set_sent_logfile(soap, "SENT.log");
8970 soap_set_recv_logfile(soap, "RECV.log");
8971 #endif
8972 #endif
8973 soap->version = 0;
8974 soap_mode(soap, imode);
8975 soap_imode(soap, imode);
8976 soap_omode(soap, omode);
8977 soap->plugins = NULL;
8978 soap->user = NULL;
8979 for (i = 0; i < sizeof(soap->data)/sizeof(*soap->data); i++)
8980 soap->data[i] = NULL;
8981 soap->userid = NULL;
8982 soap->passwd = NULL;
8983 soap->authrealm = NULL;
8984 #ifdef WITH_NTLM
8985 soap->ntlm_challenge = NULL;
8986 #endif
8987 #ifndef WITH_NOHTTP
8988 soap->fpost = http_post;
8989 soap->fget = http_get;
8990 soap->fput = http_405;
8991 soap->fdel = http_405;
8992 soap->fopt = http_200;
8993 soap->fhead = http_200;
8994 soap->fform = NULL;
8995 soap->fposthdr = http_post_header;
8996 soap->fresponse = http_response;
8997 soap->fparse = http_parse;
8998 soap->fparsehdr = http_parse_header;
8999 #endif
9000 soap->fheader = NULL;
9001 soap->fconnect = NULL;
9002 soap->fdisconnect = NULL;
9003 #ifndef WITH_NOIO
9004 soap->ipv6_multicast_if = 0; /* in_addr_t value */
9005 soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */
9006 soap->ipv4_multicast_ttl = 0; /* 0: use default */
9007 #ifndef WITH_IPV6
9008 soap->fresolve = tcp_gethost;
9009 #else
9010 soap->fresolve = NULL;
9011 #endif
9012 soap->faccept = tcp_accept;
9013 soap->fopen = tcp_connect;
9014 soap->fclose = tcp_disconnect;
9015 soap->fclosesocket = tcp_closesocket;
9016 soap->fshutdownsocket = tcp_shutdownsocket;
9017 soap->fsend = fsend;
9018 soap->frecv = frecv;
9019 soap->fpoll = soap_poll;
9020 #else
9021 soap->fopen = NULL;
9022 soap->fclose = NULL;
9023 soap->fpoll = NULL;
9024 #endif
9025 soap->fseterror = NULL;
9026 soap->fignore = NULL;
9027 soap->fserveloop = NULL;
9028 soap->fplugin = fplugin;
9029 soap->fmalloc = NULL;
9030 #ifndef WITH_LEANER
9031 soap->feltbegin = NULL;
9032 soap->feltendin = NULL;
9033 soap->feltbegout = NULL;
9034 soap->feltendout = NULL;
9035 soap->fprepareinitsend = NULL;
9036 soap->fprepareinitrecv = NULL;
9037 soap->fpreparesend = NULL;
9038 soap->fpreparerecv = NULL;
9039 soap->fpreparefinalsend = NULL;
9040 soap->fpreparefinalrecv = NULL;
9041 soap->ffiltersend = NULL;
9042 soap->ffilterrecv = NULL;
9043 soap->fdimereadopen = NULL;
9044 soap->fdimewriteopen = NULL;
9045 soap->fdimereadclose = NULL;
9046 soap->fdimewriteclose = NULL;
9047 soap->fdimeread = NULL;
9048 soap->fdimewrite = NULL;
9049 soap->fmimereadopen = NULL;
9050 soap->fmimewriteopen = NULL;
9051 soap->fmimereadclose = NULL;
9052 soap->fmimewriteclose = NULL;
9053 soap->fmimeread = NULL;
9054 soap->fmimewrite = NULL;
9055 #endif
9056 soap->float_format = "%.9G"; /* Alternative: use "%G" */
9057 soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
9058 soap->dime_id_format = "cid:id%d"; /* default DIME id format */
9059 soap->http_version = "1.1";
9060 soap->proxy_http_version = "1.0";
9061 soap->http_content = NULL;
9062 soap->actor = NULL;
9063 soap->lang = "en";
9064 soap->keep_alive = 0;
9065 soap->tcp_keep_alive = 0;
9066 soap->tcp_keep_idle = 0;
9067 soap->tcp_keep_intvl = 0;
9068 soap->tcp_keep_cnt = 0;
9069 soap->max_keep_alive = SOAP_MAXKEEPALIVE;
9070 soap->recv_timeout = 0;
9071 soap->send_timeout = 0;
9072 soap->connect_timeout = 0;
9073 soap->accept_timeout = 0;
9074 soap->socket_flags = 0;
9075 soap->connect_flags = 0;
9076 soap->bind_flags = 0;
9077 soap->accept_flags = 0;
9078 soap->linger_time = 0;
9079 soap->ip = 0;
9080 soap->labbuf = NULL;
9081 soap->lablen = 0;
9082 soap->labidx = 0;
9083 soap->encodingStyle = NULL;
9084 #ifndef WITH_NONAMESPACES
9085 soap->namespaces = namespaces;
9086 #else
9087 soap->namespaces = NULL;
9088 #endif
9089 soap->local_namespaces = NULL;
9090 soap->nlist = NULL;
9091 soap->blist = NULL;
9092 soap->clist = NULL;
9093 soap->alist = NULL;
9094 soap->attributes = NULL;
9095 soap->header = NULL;
9096 soap->fault = NULL;
9097 soap->master = SOAP_INVALID_SOCKET;
9098 soap->socket = SOAP_INVALID_SOCKET;
9099 soap->sendsk = SOAP_INVALID_SOCKET;
9100 soap->recvsk = SOAP_INVALID_SOCKET;
9101 soap->os = NULL;
9102 soap->is = NULL;
9103 #ifndef WITH_LEANER
9104 soap->dom = NULL;
9105 soap->dime.list = NULL;
9106 soap->dime.first = NULL;
9107 soap->dime.last = NULL;
9108 soap->mime.list = NULL;
9109 soap->mime.first = NULL;
9110 soap->mime.last = NULL;
9111 soap->mime.boundary = NULL;
9112 soap->mime.start = NULL;
9113 soap->xlist = NULL;
9114 #endif
9115 #ifndef UNDER_CE
9116 soap->recvfd = 0;
9117 soap->sendfd = 1;
9118 #else
9119 soap->recvfd = stdin;
9120 soap->sendfd = stdout;
9121 #endif
9122 soap->host[0] = '\0';
9123 soap->port = 0;
9124 soap->action = NULL;
9125 soap->proxy_host = NULL;
9126 soap->proxy_port = 8080;
9127 soap->proxy_userid = NULL;
9128 soap->proxy_passwd = NULL;
9129 soap->prolog = NULL;
9130 #ifdef WITH_ZLIB
9131 soap->zlib_state = SOAP_ZLIB_NONE;
9132 soap->zlib_in = SOAP_ZLIB_NONE;
9133 soap->zlib_out = SOAP_ZLIB_NONE;
9134 soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream));
9135 soap->d_stream->zalloc = Z_NULL;
9136 soap->d_stream->zfree = Z_NULL;
9137 soap->d_stream->opaque = Z_NULL;
9138 soap->z_buf = NULL;
9139 soap->z_level = 6;
9140 soap->z_dict = NULL;
9141 soap->z_dict_len = 0;
9142 #endif
9143 #ifndef WITH_LEAN
9144 soap->wsuid = NULL;
9145 soap->c14nexclude = NULL;
9146 soap->cookies = NULL;
9147 soap->cookie_domain = NULL;
9148 soap->cookie_path = NULL;
9149 soap->cookie_max = 32;
9150 #endif
9151 #ifdef WMW_RPM_IO
9152 soap->rpmreqid = NULL;
9153 #endif
9154 #ifdef PALM
9155 palmNetLibOpen();
9156 #endif
9157 #ifndef WITH_NOIDREF
9158 soap_init_iht(soap);
9159 soap_init_pht(soap);
9160 #endif
9161 #ifdef WITH_OPENSSL
9162 if (!soap_ssl_init_done)
9163 soap_ssl_init();
9164 soap->fsslauth = ssl_auth_init;
9165 soap->fsslverify = ssl_verify_callback;
9166 soap->bio = NULL;
9167 soap->ssl = NULL;
9168 soap->ctx = NULL;
9169 soap->session = NULL;
9170 soap->ssl_flags = SOAP_SSL_DEFAULT;
9171 soap->keyfile = NULL;
9172 soap->keyid = NULL;
9173 soap->password = NULL;
9174 soap->cafile = NULL;
9175 soap->capath = NULL;
9176 soap->crlfile = NULL;
9177 soap->dhfile = NULL;
9178 soap->randfile = NULL;
9179 #endif
9180 #ifdef WITH_GNUTLS
9181 if (!soap_ssl_init_done)
9182 soap_ssl_init();
9183 soap->fsslauth = ssl_auth_init;
9184 soap->fsslverify = NULL;
9185 soap->xcred = NULL;
9186 soap->acred = NULL;
9187 soap->cache = NULL;
9188 soap->session = NULL;
9189 soap->ssl_flags = SOAP_SSL_DEFAULT;
9190 soap->keyfile = NULL;
9191 soap->keyid = NULL;
9192 soap->password = NULL;
9193 soap->cafile = NULL;
9194 soap->capath = NULL;
9195 soap->crlfile = NULL;
9196 soap->dh_params = NULL;
9197 soap->rsa_params = NULL;
9198 #endif
9199 #ifdef WITH_C_LOCALE
9200 # ifdef WIN32
9201 soap->c_locale = _create_locale(LC_ALL, "C");
9202 # else
9203 soap->c_locale = newlocale(LC_ALL_MASK, "C", NULL);
9204 # endif
9205 #else
9206 soap->c_locale = NULL;
9207 #endif
9208 soap->buflen = 0;
9209 soap->bufidx = 0;
9210 #ifndef WITH_LEANER
9211 soap->dime.chunksize = 0;
9212 soap->dime.buflen = 0;
9213 #endif
9214 soap->null = 0;
9215 soap->position = 0;
9216 soap->encoding = 0;
9217 soap->mustUnderstand = 0;
9218 soap->ns = 0;
9219 soap->part = SOAP_END;
9220 soap->event = 0;
9221 soap->evlev = 0;
9222 soap->alloced = 0;
9223 soap->count = 0;
9224 soap->length = 0;
9225 soap->cdata = 0;
9226 soap->peeked = 0;
9227 soap->ahead = 0;
9228 soap->idnum = 0;
9229 soap->level = 0;
9230 soap->endpoint[0] = '\0';
9231 soap->error = SOAP_OK;
9233 #endif
9235 /******************************************************************************/
9236 #ifndef PALM_2
9237 SOAP_FMAC1
9238 void
9239 SOAP_FMAC2
9240 soap_begin(struct soap *soap)
9241 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
9242 if (!soap->keep_alive)
9243 { soap->buflen = 0;
9244 soap->bufidx = 0;
9246 soap->null = 0;
9247 soap->position = 0;
9248 soap->encoding = 0;
9249 soap->mustUnderstand = 0;
9250 soap->mode = 0;
9251 soap->ns = 0;
9252 soap->part = SOAP_END;
9253 soap->event = 0;
9254 soap->evlev = 0;
9255 soap->alloced = 0;
9256 soap->count = 0;
9257 soap->length = 0;
9258 soap->cdata = 0;
9259 soap->error = SOAP_OK;
9260 soap->peeked = 0;
9261 soap->ahead = 0;
9262 soap->idnum = 0;
9263 soap->level = 0;
9264 soap->endpoint[0] = '\0';
9265 soap->encodingStyle = SOAP_STR_EOS;
9266 #ifndef WITH_LEANER
9267 soap->dime.chunksize = 0;
9268 soap->dime.buflen = 0;
9269 #endif
9270 soap_free_temp(soap);
9272 #endif
9274 /******************************************************************************/
9275 #ifndef PALM_2
9276 SOAP_FMAC1
9277 void
9278 SOAP_FMAC2
9279 soap_end(struct soap *soap)
9280 { if (soap_check_state(soap))
9281 return;
9282 soap_free_temp(soap);
9283 soap_dealloc(soap, NULL);
9284 while (soap->clist)
9285 { register struct soap_clist *cp = soap->clist->next;
9286 SOAP_FREE(soap, soap->clist);
9287 soap->clist = cp;
9289 soap_closesock(soap);
9290 #ifdef SOAP_DEBUG
9291 soap_close_logfiles(soap);
9292 #endif
9293 #ifdef PALM
9294 palmNetLibClose();
9295 #endif
9297 #endif
9299 /******************************************************************************/
9300 #ifndef PALM_1
9301 SOAP_FMAC1
9302 void
9303 SOAP_FMAC2
9304 soap_set_version(struct soap *soap, short version)
9305 { soap_set_local_namespaces(soap);
9306 if (soap->version != version)
9307 { if (version == 1)
9308 { soap->local_namespaces[0].ns = soap_env1;
9309 soap->local_namespaces[1].ns = soap_enc1;
9311 else if (version == 2)
9312 { soap->local_namespaces[0].ns = soap_env2;
9313 soap->local_namespaces[1].ns = soap_enc2;
9315 soap->version = version;
9318 #endif
9320 /******************************************************************************/
9321 #ifndef PALM_1
9322 SOAP_FMAC1
9324 SOAP_FMAC2
9325 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
9326 { register struct Namespace *ns = soap->local_namespaces;
9327 register struct soap_nlist *np, *nq, *nr;
9328 register unsigned int level = soap->level;
9329 soap->namespaces = p;
9330 soap->local_namespaces = NULL;
9331 soap_set_local_namespaces(soap);
9332 /* reverse the namespace list */
9333 np = soap->nlist;
9334 soap->nlist = NULL;
9335 if (np)
9336 { nq = np->next;
9337 np->next = NULL;
9338 while (nq)
9339 { nr = nq->next;
9340 nq->next = np;
9341 np = nq;
9342 nq = nr;
9345 /* then push on new stack */
9346 while (np)
9347 { register const char *s;
9348 soap->level = np->level; /* preserve element nesting level */
9349 s = np->ns;
9350 if (!s && np->index >= 0 && ns)
9351 { s = ns[np->index].out;
9352 if (!s)
9353 s = ns[np->index].ns;
9355 if (s && soap_push_namespace(soap, np->id, s) == NULL)
9356 return soap->error;
9357 nq = np;
9358 np = np->next;
9359 SOAP_FREE(soap, nq);
9361 if (ns)
9362 { register int i;
9363 for (i = 0; ns[i].id; i++)
9364 { if (ns[i].out)
9365 { SOAP_FREE(soap, ns[i].out);
9366 ns[i].out = NULL;
9369 SOAP_FREE(soap, ns);
9371 soap->level = level; /* restore level */
9372 return SOAP_OK;
9374 #endif
9376 /******************************************************************************/
9377 #ifndef PALM_1
9378 SOAP_FMAC1
9379 void
9380 SOAP_FMAC2
9381 soap_set_local_namespaces(struct soap *soap)
9382 { if (soap->namespaces && !soap->local_namespaces)
9383 { register const struct Namespace *ns1;
9384 register struct Namespace *ns2;
9385 register size_t n = 1;
9386 for (ns1 = soap->namespaces; ns1->id; ns1++)
9387 n++;
9388 n *= sizeof(struct Namespace);
9389 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
9390 if (ns2)
9391 { memcpy(ns2, soap->namespaces, n);
9392 if (ns2[0].ns)
9393 { if (!strcmp(ns2[0].ns, soap_env1))
9394 soap->version = 1;
9395 else if (!strcmp(ns2[0].ns, soap_env2))
9396 soap->version = 2;
9398 soap->local_namespaces = ns2;
9399 for (; ns2->id; ns2++)
9400 ns2->out = NULL;
9404 #endif
9406 /******************************************************************************/
9407 #ifndef WITH_LEAN
9408 #ifndef PALM_1
9409 SOAP_FMAC1
9410 const char *
9411 SOAP_FMAC2
9412 soap_tagsearch(const char *big, const char *little)
9413 { if (little)
9414 { register size_t n = strlen(little);
9415 register const char *s = big;
9416 while (s)
9417 { register const char *t = s;
9418 register size_t i;
9419 for (i = 0; i < n; i++, t++)
9420 { if (*t != little[i])
9421 break;
9423 if (*t == '\0' || *t == ' ')
9424 { if (i == n || (i && little[i-1] == ':'))
9425 return s;
9427 s = strchr(t, ' ');
9428 if (s)
9429 s++;
9432 return NULL;
9434 #endif
9435 #endif
9437 /******************************************************************************/
9438 #ifndef WITH_LEAN
9439 #ifndef PALM_1
9440 SOAP_FMAC1
9441 struct soap_nlist *
9442 SOAP_FMAC2
9443 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
9444 { register struct soap_nlist *np;
9445 for (np = soap->nlist; np; np = np->next)
9446 { if (!strncmp(np->id, tag, n) && !np->id[n])
9447 return np;
9449 return NULL;
9451 #endif
9452 #endif
9454 /******************************************************************************/
9455 #ifndef WITH_LEAN
9456 static struct soap_nlist *
9457 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
9458 { register struct soap_nlist *np;
9459 size_t n, k;
9460 if (soap_tagsearch(soap->c14nexclude, id))
9461 return NULL;
9462 if (!utilized)
9463 { for (np = soap->nlist; np; np = np->next)
9464 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
9465 break;
9467 if (np)
9468 { if ((np->level < soap->level || !np->ns) && np->index == 1)
9469 utilized = 1;
9470 else
9471 return NULL;
9474 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns ? ns : "(null)", utilized));
9475 n = strlen(id);
9476 if (ns)
9477 k = strlen(ns);
9478 else
9479 k = 0;
9480 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
9481 if (!np)
9482 { soap->error = SOAP_EOM;
9483 return NULL;
9485 np->next = soap->nlist;
9486 soap->nlist = np;
9487 strcpy((char*)np->id, id);
9488 if (ns)
9489 np->ns = strcpy((char*)np->id + n + 1, ns);
9490 else
9491 np->ns = NULL;
9492 np->level = soap->level;
9493 np->index = utilized;
9494 return np;
9496 #endif
9498 /******************************************************************************/
9499 #ifndef WITH_LEAN
9500 static void
9501 soap_utilize_ns(struct soap *soap, const char *tag)
9502 { register struct soap_nlist *np;
9503 size_t n = 0;
9504 const char *t = strchr(tag, ':');
9505 if (t)
9506 { n = t - tag;
9507 if (n >= sizeof(soap->tmpbuf))
9508 n = sizeof(soap->tmpbuf) - 1;
9510 np = soap_lookup_ns(soap, tag, n);
9511 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
9512 if (np)
9513 { if (np->index <= 0)
9514 soap_push_ns(soap, np->id, np->ns, 1);
9516 else if (strncmp(tag, "xml", 3))
9517 { strncpy(soap->tmpbuf, tag, n);
9518 soap->tmpbuf[n] = '\0';
9519 soap_push_ns(soap, soap->tmpbuf, NULL, 1);
9522 #endif
9524 /******************************************************************************/
9525 #ifndef PALM_2
9526 SOAP_FMAC1
9528 SOAP_FMAC2
9529 soap_element(struct soap *soap, const char *tag, int id, const char *type)
9531 #ifndef WITH_LEAN
9532 register const char *s;
9533 #endif
9534 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag, soap->level, id, type ? type : SOAP_STR_EOS));
9535 soap->level++;
9536 #ifdef WITH_DOM
9537 #ifndef WITH_LEAN
9538 if (soap->wsuid && soap_tagsearch(soap->wsuid, tag))
9539 { size_t i;
9540 for (s = tag, i = 0; *s && i < sizeof(soap->tag) - 1; s++, i++)
9541 soap->tag[i] = *s == ':' ? '-' : *s;
9542 soap->tag[i] = '\0';
9543 if (soap_set_attr(soap, "wsu:Id", soap->tag, 1))
9544 return soap->error;
9546 if ((soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
9547 { if (soap->evlev >= soap->level)
9548 soap->evlev = 0;
9549 if (soap->event == SOAP_SEC_BEGIN && !soap->evlev)
9550 { register struct soap_nlist *np;
9551 /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
9552 for (np = soap->nlist; np; np = np->next)
9553 { if (np->index == 2)
9554 { struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1);
9555 if (np1)
9556 np1->index = 0;
9559 soap->evlev = soap->level;
9562 #endif
9563 if (soap->mode & SOAP_XML_DOM)
9564 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
9565 if (!elt)
9566 return soap->error;
9567 elt->soap = soap;
9568 elt->next = NULL;
9569 elt->prnt = soap->dom;
9570 elt->name = soap_strdup(soap, tag);
9571 elt->elts = NULL;
9572 elt->atts = NULL;
9573 elt->nstr = NULL;
9574 elt->data = NULL;
9575 elt->wide = NULL;
9576 elt->node = NULL;
9577 elt->type = 0;
9578 elt->head = NULL;
9579 elt->tail = NULL;
9580 if (soap->dom)
9581 { struct soap_dom_element *p = soap->dom->elts;
9582 if (p)
9583 { while (p->next)
9584 p = p->next;
9585 p->next = elt;
9587 else
9588 soap->dom->elts = elt;
9590 soap->dom = elt;
9592 else
9594 #endif
9595 #ifndef WITH_LEAN
9596 if (!soap->ns)
9597 { if (!(soap->mode & SOAP_XML_CANONICAL)
9598 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
9599 return soap->error;
9601 else if (soap->mode & SOAP_XML_INDENT)
9602 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
9603 return soap->error;
9604 soap->body = 1;
9606 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
9607 { struct Namespace *ns = soap->local_namespaces;
9608 size_t n = s - tag;
9609 if (soap_send_raw(soap, "<", 1)
9610 || soap_send(soap, s + 1))
9611 return soap->error;
9612 if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
9613 ns = NULL;
9614 for (; ns && ns->id; ns++)
9615 { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
9616 { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
9617 if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
9618 return soap->error;
9619 break;
9623 else
9624 #endif
9625 if (soap_send_raw(soap, "<", 1)
9626 || soap_send(soap, tag))
9627 return soap->error;
9628 #ifdef WITH_DOM
9630 #endif
9631 if (!soap->ns)
9632 { struct Namespace *ns = soap->local_namespaces;
9633 int k = -1;
9634 if (ns)
9636 #ifndef WITH_LEAN
9637 if ((soap->mode & SOAP_XML_DEFAULTNS))
9638 { if (soap->version)
9639 k = 4; /* first four required entries */
9640 else if (!(soap->mode & SOAP_XML_NOTYPE) || (soap->mode & SOAP_XML_NIL))
9641 { ns += 2;
9642 k = 2; /* next two entries */
9644 else
9645 k = 0; /* no entries */
9647 #endif
9648 while (k-- && ns->id)
9649 { if (*ns->id && (ns->out || ns->ns))
9651 #ifdef HAVE_SNPRINTF
9652 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", ns->id);
9653 #else
9654 sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
9655 #endif
9656 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
9657 return soap->error;
9659 ns++;
9663 soap->ns = 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
9664 #ifndef WITH_LEAN
9665 if (soap->mode & SOAP_XML_CANONICAL)
9666 soap_utilize_ns(soap, tag);
9667 #endif
9668 if (id > 0)
9670 #ifdef HAVE_SNPRINTF
9671 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "_%d", id);
9672 #else
9673 sprintf(soap->tmpbuf, "_%d", id);
9674 #endif
9675 if (soap->version == 2)
9676 { if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
9677 return soap->error;
9679 else if (soap_attribute(soap, "id", soap->tmpbuf))
9680 return soap->error;
9682 if (type && *type && !(soap->mode & SOAP_XML_NOTYPE) && soap->part != SOAP_IN_HEADER)
9683 { const char *t = type;
9684 #ifndef WITH_LEAN
9685 if (soap->mode & SOAP_XML_DEFAULTNS)
9686 { t = strchr(type, ':');
9687 if (t)
9688 t++;
9689 else
9690 t = type;
9692 #endif
9693 if (soap->attributes ? soap_set_attr(soap, "xsi:type", t, 1) : soap_attribute(soap, "xsi:type", t))
9694 return soap->error;
9695 #ifndef WITH_LEAN
9696 if (soap->mode & SOAP_XML_CANONICAL)
9697 soap_utilize_ns(soap, type);
9698 #endif
9700 if (soap->null && soap->position > 0)
9701 { register int i;
9702 #ifdef HAVE_SNPRINTF
9703 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, "[%d", soap->positions[0]);
9704 #else
9705 sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
9706 #endif
9707 for (i = 1; i < soap->position; i++)
9708 { register size_t l = strlen(soap->tmpbuf);
9709 #ifdef HAVE_SNPRINTF
9710 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf)-l-1, ",%d", soap->positions[i]);
9711 #else
9712 if (l + 13 < sizeof(soap->tmpbuf))
9713 sprintf(soap->tmpbuf + l, ",%d", soap->positions[i]);
9714 #endif
9716 strcat(soap->tmpbuf, "]");
9717 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
9718 return soap->error;
9720 if (soap->mustUnderstand)
9721 { if (soap->actor && *soap->actor)
9722 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
9723 return soap->error;
9725 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
9726 return soap->error;
9727 soap->mustUnderstand = 0;
9729 if (soap->encoding)
9730 { if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id)
9731 { if (!*soap->encodingStyle)
9732 { if (soap->local_namespaces[1].out)
9733 soap->encodingStyle = soap->local_namespaces[1].out;
9734 else
9735 soap->encodingStyle = soap->local_namespaces[1].ns;
9737 if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
9738 return soap->error;
9740 else
9741 soap->encodingStyle = NULL;
9742 soap->encoding = 0;
9744 soap->null = 0;
9745 soap->position = 0;
9746 if (soap->event == SOAP_SEC_BEGIN)
9747 soap->event = 0;
9748 return SOAP_OK;
9750 #endif
9752 /******************************************************************************/
9753 #ifndef PALM_2
9754 SOAP_FMAC1
9756 SOAP_FMAC2
9757 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
9758 { if (*tag == '-')
9759 return SOAP_OK;
9760 if (soap_element(soap, tag, id, type))
9761 return soap->error;
9762 #ifdef WITH_DOM
9763 if (soap_element_start_end_out(soap, NULL))
9764 return soap->error;
9765 if (soap->feltbegout)
9766 return soap->error = soap->feltbegout(soap, tag);
9767 return SOAP_OK;
9768 #else
9769 return soap_element_start_end_out(soap, NULL);
9770 #endif
9772 #endif
9774 /******************************************************************************/
9775 #ifndef PALM_2
9776 #ifndef HAVE_STRRCHR
9777 SOAP_FMAC1
9778 char*
9779 SOAP_FMAC2
9780 soap_strrchr(const char *s, int t)
9781 { register char *r = NULL;
9782 while (*s)
9783 if (*s++ == t)
9784 r = (char*)s - 1;
9785 return r;
9787 #endif
9788 #endif
9790 /******************************************************************************/
9791 #ifndef PALM_2
9792 #ifndef HAVE_STRTOL
9793 SOAP_FMAC1
9794 long
9795 SOAP_FMAC2
9796 soap_strtol(const char *s, char **t, int b)
9797 { register long n = 0;
9798 register int c;
9799 while (*s > 0 && *s <= 32)
9800 s++;
9801 if (b == 10)
9802 { short neg = 0;
9803 if (*s == '-')
9804 { s++;
9805 neg = 1;
9807 else if (*s == '+')
9808 s++;
9809 while ((c = *s) && c >= '0' && c <= '9')
9810 { if (n >= 214748364 && (n > 214748364 || c >= '8'))
9811 break;
9812 n *= 10;
9813 n += c - '0';
9814 s++;
9816 if (neg)
9817 n = -n;
9819 else /* assume b == 16 and value is always positive */
9820 { while ((c = *s))
9821 { if (c >= '0' && c <= '9')
9822 c -= '0';
9823 else if (c >= 'A' && c <= 'F')
9824 c -= 'A' - 10;
9825 else if (c >= 'a' && c <= 'f')
9826 c -= 'a' - 10;
9827 if (n > 0x07FFFFFF)
9828 break;
9829 n <<= 4;
9830 n += c;
9831 s++;
9834 if (t)
9835 *t = (char*)s;
9836 return n;
9838 #endif
9839 #endif
9841 /******************************************************************************/
9842 #ifndef PALM_2
9843 #ifndef HAVE_STRTOUL
9844 SOAP_FMAC1
9845 unsigned long
9846 SOAP_FMAC2
9847 soap_strtoul(const char *s, char **t, int b)
9848 { unsigned long n = 0;
9849 register int c;
9850 while (*s > 0 && *s <= 32)
9851 s++;
9852 if (b == 10)
9853 { if (*s == '+')
9854 s++;
9855 while ((c = *s) && c >= '0' && c <= '9')
9856 { if (n >= 429496729 && (n > 429496729 || c >= '6'))
9857 break;
9858 n *= 10;
9859 n += c - '0';
9860 s++;
9863 else /* b == 16 */
9864 { while ((c = *s))
9865 { if (c >= '0' && c <= '9')
9866 c -= '0';
9867 else if (c >= 'A' && c <= 'F')
9868 c -= 'A' - 10;
9869 else if (c >= 'a' && c <= 'f')
9870 c -= 'a' - 10;
9871 if (n > 0x0FFFFFFF)
9872 break;
9873 n <<= 4;
9874 n += c;
9875 s++;
9878 if (t)
9879 *t = (char*)s;
9880 return n;
9882 #endif
9883 #endif
9885 /******************************************************************************/
9886 #ifndef PALM_1
9887 SOAP_FMAC1
9889 SOAP_FMAC2
9890 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
9891 { if (!type || !*type)
9892 return soap_element_begin_out(soap, tag, id, NULL);
9893 if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
9894 return soap->error;
9895 if (soap->version == 2)
9896 { const char *s;
9897 s = soap_strrchr(type, '[');
9898 if (s && (size_t)(s - type) < sizeof(soap->tmpbuf))
9899 { strncpy(soap->tmpbuf, type, s - type);
9900 soap->tmpbuf[s - type] = '\0';
9901 if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
9902 return soap->error;
9903 s++;
9904 if (*s)
9905 { strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
9906 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
9907 soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0';
9908 if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf))
9909 return soap->error;
9913 else
9914 { if (offset && soap_attribute(soap, "SOAP-ENC:offset", offset))
9915 return soap->error;
9916 if (soap_attribute(soap, "SOAP-ENC:arrayType", type))
9917 return soap->error;
9919 #ifndef WITH_LEAN
9920 if ((soap->mode & SOAP_XML_CANONICAL))
9921 soap_utilize_ns(soap, type);
9922 #endif
9923 return soap_element_start_end_out(soap, NULL);
9925 #endif
9927 /******************************************************************************/
9928 #ifndef PALM_1
9929 SOAP_FMAC1
9931 SOAP_FMAC2
9932 soap_element_start_end_out(struct soap *soap, const char *tag)
9933 { register struct soap_attribute *tp;
9934 #ifndef WITH_LEAN
9935 if (soap->mode & SOAP_XML_CANONICAL)
9936 { struct soap_nlist *np;
9937 for (tp = soap->attributes; tp; tp = tp->next)
9938 { if (tp->visible && tp->name)
9939 soap_utilize_ns(soap, tp->name);
9941 for (np = soap->nlist; np; np = np->next)
9942 { if (np->index == 1 && np->ns)
9943 { if (*(np->id))
9945 #ifdef HAVE_SNPRINTF
9946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", np->id);
9947 #else
9948 sprintf(soap->tmpbuf, "xmlns:%s", np->id);
9949 #endif
9951 else
9952 strcpy(soap->tmpbuf, "xmlns");
9953 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
9954 soap_set_attr(soap, soap->tmpbuf, np->ns, 1);
9955 np->index = 2;
9959 #endif
9960 #ifdef WITH_DOM
9961 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
9962 { register struct soap_dom_attribute **att;
9963 att = &soap->dom->atts;
9964 for (tp = soap->attributes; tp; tp = tp->next)
9965 { if (tp->visible)
9966 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
9967 if (!*att)
9968 return soap->error;
9969 (*att)->next = NULL;
9970 (*att)->nstr = NULL;
9971 (*att)->name = soap_strdup(soap, tp->name);
9972 (*att)->data = soap_strdup(soap, tp->value);
9973 (*att)->wide = NULL;
9974 (*att)->soap = soap;
9975 att = &(*att)->next;
9976 tp->visible = 0;
9979 return SOAP_OK;
9981 #endif
9982 for (tp = soap->attributes; tp; tp = tp->next)
9983 { if (tp->visible)
9985 #ifndef WITH_LEAN
9986 const char *s;
9987 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tp->name, ':')))
9988 { size_t n = s - tp->name;
9989 if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
9990 s++;
9991 else
9992 s = tp->name;
9993 if (soap_send(soap, " ") || soap_send(soap, s))
9994 return soap->error;
9996 else
9997 #endif
9998 if (soap_send(soap, " ") || soap_send(soap, tp->name))
9999 return soap->error;
10000 if (tp->visible == 2 && tp->value)
10001 if (soap_send_raw(soap, "=\"", 2)
10002 || soap_string_out(soap, tp->value, tp->flag)
10003 || soap_send_raw(soap, "\"", 1))
10004 return soap->error;
10005 tp->visible = 0;
10008 if (tag)
10010 #ifndef WITH_LEAN
10011 if (soap->mode & SOAP_XML_CANONICAL)
10012 { if (soap_send_raw(soap, ">", 1)
10013 || soap_element_end_out(soap, tag))
10014 return soap->error;
10015 return SOAP_OK;
10017 #endif
10018 soap->level--; /* decrement level just before /> */
10019 return soap_send_raw(soap, "/>", 2);
10021 return soap_send_raw(soap, ">", 1);
10023 #endif
10025 /******************************************************************************/
10026 #ifndef PALM_1
10027 SOAP_FMAC1
10029 SOAP_FMAC2
10030 soap_element_end_out(struct soap *soap, const char *tag)
10032 #ifndef WITH_LEAN
10033 const char *s;
10034 #endif
10035 if (*tag == '-')
10036 return SOAP_OK;
10037 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
10038 #ifdef WITH_DOM
10039 if (soap->feltendout && (soap->error = soap->feltendout(soap, tag)))
10040 return soap->error;
10041 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10042 { if (soap->dom->prnt)
10043 soap->dom = soap->dom->prnt;
10044 return SOAP_OK;
10046 #endif
10047 #ifndef WITH_LEAN
10048 if (soap->mode & SOAP_XML_CANONICAL)
10049 soap_pop_namespace(soap);
10050 if (soap->mode & SOAP_XML_INDENT)
10051 { if (!soap->body)
10052 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
10053 return soap->error;
10055 soap->body = 0;
10057 if ((soap->mode & SOAP_XML_DEFAULTNS) && (s = strchr(tag, ':')))
10058 { soap_pop_namespace(soap);
10059 tag = s + 1;
10061 #endif
10062 if (soap_send_raw(soap, "</", 2)
10063 || soap_send(soap, tag))
10064 return soap->error;
10065 soap->level--; /* decrement level just before > */
10066 return soap_send_raw(soap, ">", 1);
10068 #endif
10070 /******************************************************************************/
10071 #ifndef PALM_1
10072 SOAP_FMAC1
10074 SOAP_FMAC2
10075 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
10076 { register const char *s = "ref";
10077 register int n = 1;
10078 if (soap->version == 1)
10079 { s = "href";
10080 n = 0;
10082 else if (soap->version == 2)
10083 s = "SOAP-ENC:ref";
10084 #ifdef HAVE_SNPRINTF
10085 soap_snprintf(soap->href, sizeof(soap->href), "#_%d", href);
10086 #else
10087 sprintf(soap->href, "#_%d", href);
10088 #endif
10089 return soap_element_href(soap, tag, id, s, soap->href + n);
10091 #endif
10093 /******************************************************************************/
10094 #ifndef PALM_1
10095 SOAP_FMAC1
10097 SOAP_FMAC2
10098 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
10099 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
10100 if (soap_element(soap, tag, id, NULL)
10101 || soap_attribute(soap, ref, val)
10102 || soap_element_start_end_out(soap, tag))
10103 return soap->error;
10104 return SOAP_OK;
10106 #endif
10108 /******************************************************************************/
10109 #ifndef PALM_1
10110 SOAP_FMAC1
10112 SOAP_FMAC2
10113 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
10114 { struct soap_attribute *tp = NULL;
10115 for (tp = soap->attributes; tp; tp = tp->next)
10116 if (tp->visible)
10117 break;
10118 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
10119 { if (soap_element(soap, tag, id, type)
10120 || (!tp && soap_attribute(soap, "xsi:nil", "true")))
10121 return soap->error;
10122 return soap_element_start_end_out(soap, tag);
10124 soap->null = 1;
10125 soap->position = 0;
10126 soap->mustUnderstand = 0;
10127 return SOAP_OK;
10129 #endif
10131 /******************************************************************************/
10132 #ifndef PALM_1
10133 SOAP_FMAC1
10135 SOAP_FMAC2
10136 soap_element_nil(struct soap *soap, const char *tag)
10137 { if (soap_element(soap, tag, -1, NULL)
10138 || ((soap->mode & SOAP_XML_NIL) && soap_attribute(soap, "xsi:nil", "true")))
10139 return soap->error;
10140 return soap_element_start_end_out(soap, tag);
10142 #endif
10144 /******************************************************************************/
10145 #ifndef PALM_1
10146 SOAP_FMAC1
10148 SOAP_FMAC2
10149 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)
10150 { if (!p)
10151 { soap->error = soap_element_null(soap, tag, id, type);
10152 return -1;
10154 #ifndef WITH_NOIDREF
10155 if ((!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
10156 return 0;
10157 if (id < 0)
10158 { struct soap_plist *pp;
10159 if (a)
10160 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
10161 else
10162 id = soap_pointer_lookup(soap, p, t, &pp);
10163 if (id)
10164 { if (soap_is_embedded(soap, pp))
10165 { soap_element_ref(soap, tag, 0, id);
10166 return -1;
10168 if (soap_is_single(soap, pp))
10169 return 0;
10170 soap_set_embedded(soap, pp);
10173 return id;
10174 #else
10175 return 0;
10176 #endif
10178 #endif
10180 /******************************************************************************/
10181 #ifndef PALM_1
10182 SOAP_FMAC1
10184 SOAP_FMAC2
10185 soap_element_result(struct soap *soap, const char *tag)
10186 { if (soap->version == 2 && soap->encodingStyle)
10187 { if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
10188 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
10189 || soap_element_start_end_out(soap, NULL)
10190 || soap_string_out(soap, tag, 0)
10191 || soap_element_end_out(soap, "SOAP-RPC:result"))
10192 return soap->error;
10194 return SOAP_OK;
10196 #endif
10198 /******************************************************************************/
10199 #ifndef PALM_1
10200 SOAP_FMAC1
10201 void
10202 SOAP_FMAC2
10203 soap_check_result(struct soap *soap, const char *tag)
10204 { if (soap->version == 2 && soap->encodingStyle)
10205 { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
10206 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
10208 (void)tag;
10210 #endif
10212 /******************************************************************************/
10213 #ifndef PALM_2
10214 SOAP_FMAC1
10216 SOAP_FMAC2
10217 soap_attribute(struct soap *soap, const char *name, const char *value)
10219 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attribute '%s'='%s'\n", name, value));
10220 #ifdef WITH_DOM
10221 if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
10222 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
10223 if (!a)
10224 return soap->error;
10225 a->next = soap->dom->atts;
10226 a->nstr = NULL;
10227 a->name = soap_strdup(soap, name);
10228 a->data = soap_strdup(soap, value);
10229 a->wide = NULL;
10230 a->soap = soap;
10231 soap->dom->atts = a;
10232 return SOAP_OK;
10234 #endif
10235 #ifndef WITH_LEAN
10236 if (soap->mode & SOAP_XML_CANONICAL)
10237 { /* push namespace */
10238 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
10239 soap_push_ns(soap, name + 5 + (name[5] == ':'), value, 0);
10240 else if (soap_set_attr(soap, name, value, 1))
10241 return soap->error;
10243 else
10244 #endif
10245 { if (soap_send(soap, " ") || soap_send(soap, name))
10246 return soap->error;
10247 if (value)
10248 if (soap_send_raw(soap, "=\"", 2)
10249 || soap_string_out(soap, value, 1)
10250 || soap_send_raw(soap, "\"", 1))
10251 return soap->error;
10253 return SOAP_OK;
10255 #endif
10257 /******************************************************************************/
10258 #ifndef PALM_2
10259 SOAP_FMAC1
10261 SOAP_FMAC2
10262 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
10263 { if (!soap_peek_element(soap))
10264 { if (soap->other)
10265 return soap->error = SOAP_TAG_MISMATCH;
10266 if (tag && *tag == '-')
10267 return SOAP_OK;
10268 if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
10269 { soap->peeked = 0;
10270 if (type && *soap->type && soap_match_tag(soap, soap->type, type))
10271 return soap->error = SOAP_TYPE;
10272 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
10273 return soap->error = SOAP_NULL;
10274 if (soap->body)
10275 soap->level++;
10276 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS ));
10277 soap->error = SOAP_OK;
10280 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
10281 soap->error = SOAP_OK;
10282 return soap->error;
10284 #endif
10286 /******************************************************************************/
10287 #ifndef PALM_2
10288 SOAP_FMAC1
10290 SOAP_FMAC2
10291 soap_element_end_in(struct soap *soap, const char *tag)
10292 { register soap_wchar c;
10293 register char *s;
10294 register int n = 0;
10295 if (tag && *tag == '-')
10296 return SOAP_OK;
10297 if (soap->error == SOAP_NO_TAG)
10298 soap->error = SOAP_OK;
10299 #ifdef WITH_DOM
10300 /* this whitespace or mixed content is significant for DOM */
10301 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10302 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
10303 return soap->error;
10304 if (soap->dom->prnt)
10305 soap->dom = soap->dom->prnt;
10307 #endif
10308 if (soap->peeked)
10309 { if (*soap->tag)
10310 n++;
10311 soap->peeked = 0;
10314 { while (((c = soap_get(soap)) != SOAP_TT))
10315 { if ((int)c == EOF)
10316 return soap->error = SOAP_CHK_EOF;
10317 if (c == SOAP_LT)
10318 n++;
10319 else if (c == '/')
10320 { c = soap_get(soap);
10321 if (c == SOAP_GT)
10322 n--;
10323 else
10324 soap_unget(soap, c);
10327 } while (n--);
10328 s = soap->tag;
10329 n = sizeof(soap->tag);
10330 while (soap_notblank(c = soap_get(soap)))
10331 { if (--n > 0)
10332 *s++ = (char)c;
10334 *s = '\0';
10335 if ((int)c == EOF)
10336 return soap->error = SOAP_CHK_EOF;
10337 while (soap_blank(c))
10338 c = soap_get(soap);
10339 if (c != SOAP_GT)
10340 return soap->error = SOAP_SYNTAX_ERROR;
10341 #ifndef WITH_LEAN
10342 #ifdef WITH_DOM
10343 if (soap->feltendin)
10344 { soap->level--;
10345 return soap->error = soap->feltendin(soap, soap->tag, tag);
10347 #endif
10348 if (tag && (soap->mode & SOAP_XML_STRICT))
10349 { soap_pop_namespace(soap);
10350 if (soap_match_tag(soap, soap->tag, tag))
10351 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag '%s' does not match '%s'\n", soap->tag, tag ? tag : SOAP_STR_EOS));
10352 return soap->error = SOAP_SYNTAX_ERROR;
10355 #endif
10356 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag ? tag : SOAP_STR_EOS));
10357 soap->level--;
10358 return SOAP_OK;
10360 #endif
10362 /******************************************************************************/
10363 #ifndef PALM_2
10364 SOAP_FMAC1
10365 const char *
10366 SOAP_FMAC2
10367 soap_attr_value(struct soap *soap, const char *name, int flag)
10368 { register struct soap_attribute *tp;
10369 if (*name == '-')
10370 return SOAP_STR_EOS;
10371 for (tp = soap->attributes; tp; tp = tp->next)
10372 { if (tp->visible && !soap_match_tag(soap, tp->name, name))
10373 break;
10375 if (tp)
10376 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
10377 soap->error = SOAP_PROHIBITED;
10378 else
10379 return tp->value;
10381 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
10382 soap->error = SOAP_REQUIRED;
10383 else
10384 soap->error = SOAP_OK;
10385 return NULL;
10387 #endif
10389 /******************************************************************************/
10390 #ifndef PALM_2
10391 SOAP_FMAC1
10393 SOAP_FMAC2
10394 soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
10395 { register struct soap_attribute *tp;
10396 if (*name == '-')
10397 return SOAP_OK;
10398 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value ? value : SOAP_STR_EOS));
10399 for (tp = soap->attributes; tp; tp = tp->next)
10400 { if (!strcmp(tp->name, name))
10401 break;
10403 if (!tp)
10404 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
10405 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
10406 return soap->error = SOAP_EOM;
10407 tp->ns = NULL;
10408 #ifndef WITH_LEAN
10409 if ((soap->mode & SOAP_XML_CANONICAL))
10410 { struct soap_attribute **tpp = &soap->attributes;
10411 const char *s = strchr(name, ':');
10412 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name));
10413 if (!strncmp(name, "xmlns", 5))
10414 { for (; *tpp; tpp = &(*tpp)->next)
10415 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
10416 break;
10418 else if (!s)
10419 { for (; *tpp; tpp = &(*tpp)->next)
10420 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
10421 break;
10423 else
10424 { struct soap_nlist *np = soap_lookup_ns(soap, name, s - name);
10425 if (np)
10426 tp->ns = np->ns;
10427 else
10428 { struct soap_attribute *tq;
10429 for (tq = soap->attributes; tq; tq = tq->next)
10430 { if (!strncmp(tq->name, "xmlns:", 6) && !strncmp(tq->name + 6, name, s - name) && !tq->name[6 + s - name])
10431 { tp->ns = tq->ns;
10432 break;
10436 for (; *tpp; tpp = &(*tpp)->next)
10437 { int k;
10438 if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
10439 break;
10442 tp->next = *tpp;
10443 *tpp = tp;
10445 else
10446 #endif
10447 { tp->next = soap->attributes;
10448 soap->attributes = tp;
10450 strcpy((char*)tp->name, name);
10451 tp->value = NULL;
10453 else if (tp->visible)
10454 { return SOAP_OK;
10456 else if (value && tp->value && tp->size <= strlen(value))
10457 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
10458 SOAP_FREE(soap, tp->value);
10459 tp->value = NULL;
10460 tp->ns = NULL;
10462 if (value)
10463 { if (!tp->value)
10464 { tp->size = strlen(value) + 1;
10465 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
10466 return soap->error = SOAP_EOM;
10467 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value));
10469 strcpy(tp->value, value);
10470 if (!strncmp(tp->name, "xmlns:", 6))
10471 tp->ns = tp->value;
10472 tp->visible = 2;
10473 tp->flag = (short)flag;
10474 #ifndef WITH_LEAN
10475 if (!strcmp(name, "wsu:Id"))
10476 { soap->event = SOAP_SEC_BEGIN;
10477 strncpy(soap->id, value, sizeof(soap->id));
10478 soap->id[sizeof(soap->id) - 1] = '\0';
10480 #endif
10482 else
10483 tp->visible = 1;
10484 return SOAP_OK;
10486 #endif
10488 /******************************************************************************/
10489 #ifndef PALM_2
10490 SOAP_FMAC1
10491 void
10492 SOAP_FMAC2
10493 soap_clr_attr(struct soap *soap)
10494 { register struct soap_attribute *tp;
10495 #ifndef WITH_LEAN
10496 if ((soap->mode & SOAP_XML_CANONICAL))
10497 { while (soap->attributes)
10498 { tp = soap->attributes->next;
10499 if (soap->attributes->value)
10500 SOAP_FREE(soap, soap->attributes->value);
10501 SOAP_FREE(soap, soap->attributes);
10502 soap->attributes = tp;
10505 else
10506 #endif
10507 { for (tp = soap->attributes; tp; tp = tp->next)
10508 tp->visible = 0;
10511 #endif
10513 /******************************************************************************/
10514 #ifndef PALM_2
10515 static int
10516 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
10517 { register size_t i;
10518 for (i = 0; i < n; i++)
10519 { register soap_wchar c = soap_get(soap);
10520 switch (c)
10522 case SOAP_TT:
10523 *s++ = '<';
10524 soap_unget(soap, '/');
10525 break;
10526 case SOAP_LT:
10527 *s++ = '<';
10528 break;
10529 case SOAP_GT:
10530 if (d == ' ')
10531 { soap_unget(soap, c);
10532 *s = '\0';
10533 return SOAP_OK;
10535 *s++ = '>';
10536 break;
10537 case SOAP_QT:
10538 if (c == d)
10539 { *s = '\0';
10540 return SOAP_OK;
10542 *s++ = '"';
10543 break;
10544 case SOAP_AP:
10545 if (c == d)
10546 { *s = '\0';
10547 return SOAP_OK;
10549 *s++ = '\'';
10550 break;
10551 case '\t':
10552 case '\n':
10553 case '\r':
10554 case ' ':
10555 case '/':
10556 if (d == ' ')
10557 { soap_unget(soap, c);
10558 *s = '\0';
10559 return SOAP_OK;
10561 default:
10562 if ((int)c == EOF)
10563 { *s = '\0';
10564 return soap->error = SOAP_CHK_EOF;
10566 *s++ = (char)c;
10569 return soap->error = SOAP_EOM;
10571 #endif
10573 /******************************************************************************/
10574 #ifdef WITH_FAST
10575 #ifndef PALM_2
10576 SOAP_FMAC1
10578 SOAP_FMAC2
10579 soap_store_lab(struct soap *soap, const char *s, size_t n)
10580 { soap->labidx = 0;
10581 return soap_append_lab(soap, s, n);
10583 #endif
10584 #endif
10586 /******************************************************************************/
10587 #ifdef WITH_FAST
10588 #ifndef PALM_2
10589 SOAP_FMAC1
10591 SOAP_FMAC2
10592 soap_append_lab(struct soap *soap, const char *s, size_t n)
10593 { if (soap->labidx + n >= soap->lablen)
10594 { register char *t = soap->labbuf;
10595 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen));
10596 if (soap->lablen == 0)
10597 soap->lablen = SOAP_LABLEN;
10598 while (soap->labidx + n >= soap->lablen)
10599 soap->lablen <<= 1;
10600 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen));
10601 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
10602 if (!soap->labbuf)
10603 { if (t)
10604 SOAP_FREE(soap, t);
10605 return soap->error = SOAP_EOM;
10607 if (t)
10608 { memcpy(soap->labbuf, t, soap->labidx);
10609 SOAP_FREE(soap, t);
10612 if (s)
10613 { memcpy(soap->labbuf + soap->labidx, s, n);
10614 soap->labidx += n;
10616 return SOAP_OK;
10618 #endif
10619 #endif
10621 /******************************************************************************/
10622 #ifndef PALM_2
10623 SOAP_FMAC1
10625 SOAP_FMAC2
10626 soap_peek_element(struct soap *soap)
10628 #ifdef WITH_DOM
10629 register struct soap_dom_attribute **att = NULL;
10630 register char *lead = NULL;
10631 #endif
10632 register struct soap_attribute *tp, *tq = NULL;
10633 register const char *t;
10634 register char *s;
10635 register soap_wchar c;
10636 register int i;
10637 if (soap->peeked)
10638 { if (!*soap->tag)
10639 return soap->error = SOAP_NO_TAG;
10640 return SOAP_OK;
10642 soap->peeked = 1;
10643 soap->id[0] = '\0';
10644 soap->href[0] = '\0';
10645 soap->type[0] = '\0';
10646 soap->arrayType[0] = '\0';
10647 soap->arraySize[0] = '\0';
10648 soap->arrayOffset[0] = '\0';
10649 soap->other = 0;
10650 soap->root = -1;
10651 soap->position = 0;
10652 soap->null = 0;
10653 soap->mustUnderstand = 0;
10654 /* UTF-8 BOM? */
10655 c = soap_getchar(soap);
10656 if (c == 0xEF && soap_get0(soap) == 0xBB)
10657 { c = soap_get1(soap);
10658 if ((c = soap_get1(soap)) == 0xBF)
10659 soap->mode &= ~SOAP_ENC_LATIN;
10660 else
10661 soap_unget(soap, (0x0F << 12) | (0xBB << 6) | (c & 0x3F)); /* UTF-8 */
10663 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
10664 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
10665 return soap->error = SOAP_UTF_ERROR;
10666 else
10667 soap_unget(soap, c);
10668 c = soap_get(soap);
10669 #ifdef WITH_DOM
10670 /* whitespace leading to tag is not insignificant for DOM */
10671 if (soap_blank(c))
10672 { soap->labidx = 0;
10674 { if (soap_append_lab(soap, NULL, 0))
10675 return soap->error;
10676 s = soap->labbuf + soap->labidx;
10677 i = soap->lablen - soap->labidx;
10678 soap->labidx = soap->lablen;
10679 while (soap_blank(c) && i--)
10680 { *s++ = c;
10681 c = soap_get(soap);
10684 while (soap_blank(c));
10685 *s = '\0';
10686 lead = soap->labbuf;
10688 #else
10689 /* skip space */
10690 while (soap_blank(c))
10691 c = soap_get(soap);
10692 #endif
10693 if (c != SOAP_LT)
10694 { *soap->tag = '\0';
10695 if ((int)c == EOF)
10696 return soap->error = SOAP_CHK_EOF;
10697 soap_unget(soap, c);
10698 #ifdef WITH_DOM
10699 /* whitespace leading to end tag is significant for DOM */
10700 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10701 { if (lead && *lead)
10702 soap->dom->tail = soap_strdup(soap, lead);
10703 else
10704 soap->dom->tail = (char*)SOAP_STR_EOS;
10706 #endif
10707 return soap->error = SOAP_NO_TAG;
10709 do c = soap_get1(soap);
10710 while (soap_blank(c));
10711 s = soap->tag;
10712 i = sizeof(soap->tag);
10713 while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
10714 { if (--i > 0)
10715 *s++ = (char)c;
10716 c = soap_get1(soap);
10718 *s = '\0';
10719 while (soap_blank(c))
10720 c = soap_get1(soap);
10721 #ifdef WITH_DOM
10722 if (soap->mode & SOAP_XML_DOM)
10723 { register struct soap_dom_element *elt;
10724 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
10725 if (!elt)
10726 return soap->error;
10727 elt->next = NULL;
10728 elt->nstr = NULL;
10729 elt->name = soap_strdup(soap, soap->tag);
10730 elt->prnt = soap->dom;
10731 elt->elts = NULL;
10732 elt->atts = NULL;
10733 elt->data = NULL;
10734 elt->wide = NULL;
10735 elt->type = 0;
10736 elt->node = NULL;
10737 elt->head = soap_strdup(soap, lead);
10738 elt->tail = NULL;
10739 elt->soap = soap;
10740 if (soap->dom)
10741 { struct soap_dom_element *p = soap->dom->elts;
10742 if (p)
10743 { while (p->next)
10744 p = p->next;
10745 p->next = elt;
10747 else
10748 soap->dom->elts = elt;
10750 soap->dom = elt;
10751 att = &elt->atts;
10753 #endif
10754 soap_pop_namespace(soap);
10755 for (tp = soap->attributes; tp; tp = tp->next)
10756 tp->visible = 0;
10757 while ((int)c != EOF && c != '>' && c != '/')
10758 { s = soap->tmpbuf;
10759 i = sizeof(soap->tmpbuf);
10760 while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
10761 { if (--i > 0)
10762 *s++ = (char)c;
10763 c = soap_get1(soap);
10765 *s = '\0';
10766 if (i == sizeof(soap->tmpbuf))
10767 return soap->error = SOAP_SYNTAX_ERROR;
10768 #ifdef WITH_DOM
10769 /* add attribute name to dom */
10770 if (att)
10771 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
10772 if (!*att)
10773 return soap->error;
10774 (*att)->next = NULL;
10775 (*att)->nstr = NULL;
10776 (*att)->name = soap_strdup(soap, soap->tmpbuf);
10777 (*att)->data = NULL;
10778 (*att)->wide = NULL;
10779 (*att)->soap = soap;
10781 #endif
10782 if (!strncmp(soap->tmpbuf, "xmlns", 5))
10783 { if (soap->tmpbuf[5] == ':')
10784 t = soap->tmpbuf + 6;
10785 else if (soap->tmpbuf[5])
10786 t = NULL;
10787 else
10788 t = SOAP_STR_EOS;
10790 else
10791 t = NULL;
10792 tq = NULL;
10793 for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
10794 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
10795 break;
10797 if (!tp)
10798 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
10799 if (!tp)
10800 return soap->error = SOAP_EOM;
10801 strcpy((char*)tp->name, soap->tmpbuf);
10802 tp->value = NULL;
10803 tp->size = 0;
10804 tp->ns = NULL;
10805 /* if attribute name is qualified, append it to the end of the list */
10806 if (tq && strchr(soap->tmpbuf, ':'))
10807 { tq->next = tp;
10808 tp->next = NULL;
10810 else
10811 { tp->next = soap->attributes;
10812 soap->attributes = tp;
10815 while (soap_blank(c))
10816 c = soap_get1(soap);
10817 if (c == '=')
10818 { do c = soap_getutf8(soap);
10819 while (soap_blank(c));
10820 if (c != SOAP_QT && c != SOAP_AP)
10821 { soap_unget(soap, c);
10822 c = ' '; /* blank delimiter */
10824 if (soap_getattrval(soap, tp->value, tp->size, c))
10826 #ifdef WITH_FAST
10827 if (soap->error != SOAP_EOM)
10828 return soap->error;
10829 soap->error = SOAP_OK;
10830 if (soap_store_lab(soap, tp->value, tp->size))
10831 return soap->error;
10832 if (tp->value)
10833 SOAP_FREE(soap, tp->value);
10834 tp->value = NULL;
10835 for (;;)
10836 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
10837 { if (soap->error != SOAP_EOM)
10838 return soap->error;
10839 soap->error = SOAP_OK;
10840 soap->labidx = soap->lablen;
10841 if (soap_append_lab(soap, NULL, 0))
10842 return soap->error;
10844 else
10845 break;
10847 if (soap->labidx)
10848 tp->size = soap->lablen;
10849 else
10850 { tp->size = strlen(soap->labbuf) + 1;
10851 if (tp->size < SOAP_LABLEN)
10852 tp->size = SOAP_LABLEN;
10854 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
10855 return soap->error = SOAP_EOM;
10856 strcpy(tp->value, soap->labbuf);
10857 #else
10858 size_t n;
10859 if (soap->error != SOAP_EOM)
10860 return soap->error;
10861 soap->error = SOAP_OK;
10862 if (soap_new_block(soap) == NULL)
10863 return soap->error;
10864 for (;;)
10865 { if (!(s = (char*)soap_push_block(soap, NULL, SOAP_BLKLEN)))
10866 return soap->error;
10867 if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
10868 { if (soap->error != SOAP_EOM)
10869 return soap->error;
10870 soap->error = SOAP_OK;
10872 else
10873 break;
10875 n = tp->size + soap->blist->size;
10876 if (!(s = (char*)SOAP_MALLOC(soap, n)))
10877 return soap->error = SOAP_EOM;
10878 if (tp->value)
10879 { memcpy(s, tp->value, tp->size);
10880 SOAP_FREE(soap, tp->value);
10882 soap_save_block(soap, NULL, s + tp->size, 0);
10883 tp->value = s;
10884 tp->size = n;
10885 #endif
10887 do c = soap_get1(soap);
10888 while (soap_blank(c));
10889 tp->visible = 2; /* seen this attribute w/ value */
10890 #ifdef WITH_DOM
10891 if (att)
10892 (*att)->data = soap_strdup(soap, tp->value);
10893 #endif
10895 else
10896 tp->visible = 1; /* seen this attribute w/o value */
10897 #ifdef WITH_DOM
10898 if (att)
10899 att = &(*att)->next;
10900 #endif
10901 if (t && tp->value)
10902 { if (soap_push_namespace(soap, t, tp->value) == NULL)
10903 return soap->error;
10906 #ifdef WITH_DOM
10907 if (att)
10908 { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
10909 for (att = &soap->dom->atts; *att; att = &(*att)->next)
10910 (*att)->nstr = soap_current_namespace(soap, (*att)->name);
10912 #endif
10913 if ((int)c == EOF)
10914 return soap->error = SOAP_CHK_EOF;
10915 if (!(soap->body = (c != '/')))
10916 do c = soap_get1(soap);
10917 while (soap_blank(c));
10918 #ifdef WITH_DOM
10919 if (soap->mode & SOAP_XML_DOM)
10920 { if (!soap->body && soap->dom->prnt)
10921 soap->dom = soap->dom->prnt;
10923 #endif
10924 for (tp = soap->attributes; tp; tp = tp->next)
10925 { if (tp->visible && tp->value)
10927 #ifndef WITH_NOIDREF
10928 if (!strcmp(tp->name, "id"))
10929 { if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE))
10930 || (soap->mode & SOAP_XML_GRAPH))
10931 { *soap->id = '#';
10932 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
10933 soap->id[sizeof(soap->id) - 1] = '\0';
10936 else if (!strcmp(tp->name, "href"))
10937 { if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE))
10938 || (soap->mode & SOAP_XML_GRAPH)
10939 || (soap->mode & SOAP_ENC_MTOM)
10940 || (soap->mode & SOAP_ENC_DIME))
10941 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
10942 soap->href[sizeof(soap->href) - 1] = '\0';
10945 else if (!strcmp(tp->name, "ref"))
10946 { if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE))
10947 || (soap->mode & SOAP_XML_GRAPH))
10948 { *soap->href = '#';
10949 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
10950 soap->href[sizeof(soap->href) - 1] = '\0';
10953 else
10954 #endif
10955 if (!soap_match_tag(soap, tp->name, "xsi:type"))
10956 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
10957 soap->type[sizeof(soap->type) - 1] = '\0';
10959 else if ((!soap_match_tag(soap, tp->name, "xsi:null")
10960 || !soap_match_tag(soap, tp->name, "xsi:nil"))
10961 && (!strcmp(tp->value, "1")
10962 || !strcmp(tp->value, "true")))
10963 { soap->null = 1;
10965 else if (soap->version == 1)
10966 { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
10967 { s = soap_strrchr(tp->value, '[');
10968 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
10969 { strncpy(soap->arrayType, tp->value, s - tp->value);
10970 soap->arrayType[s - tp->value] = '\0';
10971 strncpy(soap->arraySize, s, sizeof(soap->arraySize));
10973 else
10974 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType));
10975 soap->arraySize[sizeof(soap->arraySize) - 1] = '\0';
10976 soap->arrayType[sizeof(soap->arrayType) - 1] = '\0';
10978 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
10979 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
10980 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
10981 soap->position = soap_getposition(tp->value, soap->positions);
10982 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
10983 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
10984 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
10985 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
10986 soap->mustUnderstand = 1;
10987 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
10988 { if ((!soap->actor || strcmp(soap->actor, tp->value))
10989 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
10990 soap->other = 1;
10993 else if (soap->version == 2)
10995 #ifndef WITH_NOIDREF
10996 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id"))
10997 { *soap->id = '#';
10998 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
10999 soap->id[sizeof(soap->id) - 1] = '\0';
11001 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
11002 { *soap->href = '#';
11003 strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
11004 soap->href[sizeof(soap->href) - 1] = '\0';
11006 else
11007 #endif
11008 if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
11009 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
11010 else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
11011 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
11012 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
11013 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
11014 soap->mustUnderstand = 1;
11015 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
11016 { if ((!soap->actor || strcmp(soap->actor, tp->value))
11017 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
11018 soap->other = 1;
11021 else
11022 { if (!soap_match_tag(soap, tp->name, "wsdl:required") && !strcmp(tp->value, "true"))
11023 soap->mustUnderstand = 1;
11027 #ifdef WITH_DOM
11028 if (soap->feltbegin)
11029 return soap->error = soap->feltbegin(soap, soap->tag);
11030 #endif
11031 return soap->error = SOAP_OK;
11033 #endif
11035 /******************************************************************************/
11036 #ifndef PALM_2
11037 SOAP_FMAC1
11038 void
11039 SOAP_FMAC2
11040 soap_retry(struct soap *soap)
11041 { soap->error = SOAP_OK;
11042 soap_revert(soap);
11044 #endif
11046 /******************************************************************************/
11047 #ifndef PALM_2
11048 SOAP_FMAC1
11049 void
11050 SOAP_FMAC2
11051 soap_revert(struct soap *soap)
11052 { if (!soap->peeked)
11053 { soap->peeked = 1;
11054 if (soap->body)
11055 soap->level--;
11057 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting to last element '%s' (level=%u)\n", soap->tag, soap->level));
11059 #endif
11061 /******************************************************************************/
11062 #ifndef PALM_2
11063 SOAP_FMAC1
11065 SOAP_FMAC2
11066 soap_string_out(struct soap *soap, const char *s, int flag)
11067 { register const char *t;
11068 register soap_wchar c;
11069 register soap_wchar mask = (soap_wchar)0xFFFFFF80UL;
11070 #ifdef WITH_DOM
11071 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
11072 { soap->dom->data = soap_strdup(soap, s);
11073 return SOAP_OK;
11075 #endif
11076 if (flag == 2 || soap->mode & SOAP_C_UTFSTRING)
11077 mask = 0;
11078 t = s;
11079 while ((c = *t++))
11080 { switch (c)
11082 case 0x09:
11083 if (flag)
11084 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#x9;", 5))
11085 return soap->error;
11086 s = t;
11088 break;
11089 case 0x0A:
11090 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
11091 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xA;", 5))
11092 return soap->error;
11093 s = t;
11095 break;
11096 case 0x0D:
11097 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&#xD;", 5))
11098 return soap->error;
11099 s = t;
11100 break;
11101 case '&':
11102 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&amp;", 5))
11103 return soap->error;
11104 s = t;
11105 break;
11106 case '<':
11107 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&lt;", 4))
11108 return soap->error;
11109 s = t;
11110 break;
11111 case '>':
11112 if (!flag)
11113 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&gt;", 4))
11114 return soap->error;
11115 s = t;
11117 break;
11118 case '"':
11119 if (flag)
11120 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&quot;", 6))
11121 return soap->error;
11122 s = t;
11124 break;
11125 default:
11126 #ifndef WITH_LEANER
11127 #ifdef HAVE_MBTOWC
11128 if (soap->mode & SOAP_C_MBSTRING)
11129 { wchar_t wc;
11130 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
11131 if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80))
11132 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc))
11133 return soap->error;
11134 s = t += m - 1;
11135 continue;
11138 #endif
11139 #endif
11140 #ifndef WITH_NOSTRINGTOUTF8
11141 if ((c & mask) || !(c & 0xFFFFFFE0UL))
11142 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
11143 return soap->error;
11144 s = t;
11146 #endif
11149 return soap_send_raw(soap, s, t - s - 1);
11151 #endif
11153 /******************************************************************************/
11154 #ifndef PALM_2
11155 SOAP_FMAC1
11156 char *
11157 SOAP_FMAC2
11158 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
11159 { register char *s;
11160 char *t = NULL;
11161 register size_t i;
11162 register long l = 0;
11163 register int n = 0, f = 0, m = 0;
11164 register soap_wchar c;
11165 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
11166 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
11167 #else
11168 char buf[8];
11169 #endif
11170 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content, flag=%d\n", flag));
11171 if (soap->peeked && *soap->tag)
11173 #ifndef WITH_LEAN
11174 struct soap_attribute *tp;
11175 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
11176 t = soap->tmpbuf;
11177 *t = '<';
11178 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
11179 t[sizeof(soap->tmpbuf) - 1] = '\0';
11180 t += strlen(t);
11181 for (tp = soap->attributes; tp; tp = tp->next)
11182 { if (tp->visible)
11183 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
11184 break;
11185 *t++ = ' ';
11186 strcpy(t, tp->name);
11187 t += strlen(t);
11188 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
11189 break; /* too many or large attribute values */
11190 if (tp->value)
11191 { *t++ = '=';
11192 *t++ = '"';
11193 strcpy(t, tp->value);
11194 t += strlen(t);
11195 *t++ = '"';
11199 if (!soap->body)
11200 *t++ = '/';
11201 *t++ = '>';
11202 *t = '\0';
11203 t = soap->tmpbuf;
11204 m = (int)strlen(soap->tmpbuf);
11205 #endif
11206 if (soap->body)
11207 n = 1;
11208 f = 1;
11209 soap->peeked = 0;
11211 #ifdef WITH_CDATA
11212 if (!flag)
11213 { register int state = 0;
11214 #ifdef WITH_FAST
11215 soap->labidx = 0; /* use look-aside buffer */
11216 #else
11217 if (soap_new_block(soap) == NULL)
11218 return NULL;
11219 #endif
11220 for (;;)
11222 #ifdef WITH_FAST
11223 register size_t k;
11224 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
11225 return NULL;
11226 s = soap->labbuf + soap->labidx; /* space to populate */
11227 k = soap->lablen - soap->labidx; /* number of bytes available */
11228 soap->labidx = soap->lablen; /* claim this space */
11229 #else
11230 register size_t k = SOAP_BLKLEN;
11231 if (!(s = (char*)soap_push_block(soap, NULL, k)))
11232 return NULL;
11233 #endif
11234 for (i = 0; i < k; i++)
11235 { if (m > 0)
11236 { *s++ = *t++; /* copy multibyte characters */
11237 m--;
11238 continue;
11240 c = soap_getchar(soap);
11241 if ((int)c == EOF)
11242 goto end;
11243 if ((c >= 0x80 || c < SOAP_AP) && state != 1 && !(soap->mode & SOAP_ENC_LATIN))
11244 { if ((c & 0x7FFFFFFF) >= 0x80)
11245 { soap_unget(soap, c);
11246 c = soap_getutf8(soap);
11248 if ((c & 0x7FFFFFFF) >= 0x80 && (!flag || (soap->mode & SOAP_C_UTFSTRING)))
11249 { c &= 0x7FFFFFFF;
11250 t = buf;
11251 if (c < 0x0800)
11252 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
11253 else
11254 { if (c < 0x010000)
11255 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
11256 else
11257 { if (c < 0x200000)
11258 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
11259 else
11260 { if (c < 0x04000000)
11261 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
11262 else
11263 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
11264 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
11266 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
11268 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
11270 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
11272 *t++ = (char)(0x80 | (c & 0x3F));
11273 m = (int)(t - buf) - 1;
11274 t = buf;
11275 *s++ = *t++;
11276 continue;
11279 switch (state)
11280 { case 1:
11281 if (c == ']')
11282 state = 4;
11283 *s++ = (char)c;
11284 continue;
11285 case 2:
11286 if (c == '-')
11287 state = 6;
11288 *s++ = (char)c;
11289 continue;
11290 case 3:
11291 if (c == '?')
11292 state = 8;
11293 *s++ = (char)c;
11294 continue;
11295 /* CDATA */
11296 case 4:
11297 if (c == ']')
11298 state = 5;
11299 else
11300 state = 1;
11301 *s++ = (char)c;
11302 continue;
11303 case 5:
11304 if (c == '>')
11305 state = 0;
11306 else if (c != ']')
11307 state = 1;
11308 *s++ = (char)c;
11309 continue;
11310 /* comment */
11311 case 6:
11312 if (c == '-')
11313 state = 7;
11314 else
11315 state = 2;
11316 *s++ = (char)c;
11317 continue;
11318 case 7:
11319 if (c == '>')
11320 state = 0;
11321 else if (c != '-')
11322 state = 2;
11323 *s++ = (char)c;
11324 continue;
11325 /* PI */
11326 case 8:
11327 if (c == '>')
11328 state = 0;
11329 else if (c != '?')
11330 state = 3;
11331 *s++ = (char)c;
11332 continue;
11334 switch (c)
11336 case SOAP_TT:
11337 if (n == 0)
11338 goto end;
11339 n--;
11340 *s++ = '<';
11341 t = (char*)"/";
11342 m = 1;
11343 break;
11344 case SOAP_LT:
11345 if (f && n == 0)
11346 goto end;
11347 n++;
11348 *s++ = '<';
11349 break;
11350 case SOAP_GT:
11351 *s++ = '>';
11352 break;
11353 case SOAP_QT:
11354 *s++ = '"';
11355 break;
11356 case SOAP_AP:
11357 *s++ = '\'';
11358 break;
11359 case '/':
11360 if (n > 0)
11361 { c = soap_getchar(soap);
11362 if (c == '>')
11363 n--;
11364 soap_unget(soap, c);
11366 *s++ = '/';
11367 break;
11368 case '<':
11369 c = soap_getchar(soap);
11370 if (c == '/')
11371 { if (n == 0)
11372 { c = SOAP_TT;
11373 goto end;
11375 n--;
11377 else if (c == '!')
11378 { c = soap_getchar(soap);
11379 if (c == '[')
11380 { do c = soap_getchar(soap);
11381 while ((int)c != EOF && c != '[');
11382 if ((int)c == EOF)
11383 goto end;
11384 t = (char*)"![CDATA[";
11385 m = 8;
11386 state = 1;
11388 else if (c == '-')
11389 { if ((c = soap_getchar(soap)) == '-')
11390 state = 2;
11391 t = (char*)"!-";
11392 m = 2;
11393 soap_unget(soap, c);
11395 else
11396 { t = (char*)"!";
11397 m = 1;
11398 soap_unget(soap, c);
11400 *s++ = '<';
11401 break;
11403 else if (c == '?')
11404 state = 3;
11405 else if (f && n == 0)
11406 { soap_revget1(soap);
11407 c = '<';
11408 goto end;
11410 else
11411 n++;
11412 soap_unget(soap, c);
11413 *s++ = '<';
11414 break;
11415 case '>':
11416 *s++ = '>';
11417 break;
11418 case '"':
11419 *s++ = '"';
11420 break;
11421 default:
11422 #ifndef WITH_LEANER
11423 #ifdef HAVE_WCTOMB
11424 if (soap->mode & SOAP_C_MBSTRING)
11425 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
11426 if (m >= 1 && m <= (int)MB_CUR_MAX)
11427 { t = buf;
11428 *s++ = *t++;
11429 m--;
11431 else
11432 { *s++ = SOAP_UNKNOWN_CHAR;
11433 m = 0;
11436 else
11437 #endif
11438 #endif
11439 *s++ = (char)(c & 0xFF);
11441 l++;
11442 if (maxlen >= 0 && l > maxlen)
11443 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
11444 soap->error = SOAP_LENGTH;
11445 return NULL;
11450 #endif
11451 #ifdef WITH_FAST
11452 soap->labidx = 0; /* use look-aside buffer */
11453 #else
11454 if (soap_new_block(soap) == NULL)
11455 return NULL;
11456 #endif
11457 for (;;)
11459 #ifdef WITH_FAST
11460 register size_t k;
11461 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
11462 return NULL;
11463 s = soap->labbuf + soap->labidx; /* space to populate */
11464 k = soap->lablen - soap->labidx; /* number of bytes available */
11465 soap->labidx = soap->lablen; /* claim this space */
11466 #else
11467 register size_t k = SOAP_BLKLEN;
11468 if (!(s = (char*)soap_push_block(soap, NULL, k)))
11469 return NULL;
11470 #endif
11471 for (i = 0; i < k; i++)
11472 { if (m > 0)
11473 { *s++ = *t++; /* copy multibyte characters */
11474 m--;
11475 continue;
11477 #ifndef WITH_CDATA
11478 if (!flag)
11479 c = soap_getchar(soap);
11480 else
11481 #endif
11482 if ((soap->mode & SOAP_C_UTFSTRING))
11483 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
11484 { c &= 0x7FFFFFFF;
11485 t = buf;
11486 if (c < 0x0800)
11487 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
11488 else
11489 { if (c < 0x010000)
11490 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
11491 else
11492 { if (c < 0x200000)
11493 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
11494 else
11495 { if (c < 0x04000000)
11496 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
11497 else
11498 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
11499 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
11501 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
11503 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
11505 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
11507 *t++ = (char)(0x80 | (c & 0x3F));
11508 m = (int)(t - buf) - 1;
11509 t = buf;
11510 *s++ = *t++;
11511 continue;
11514 else
11515 c = soap_getutf8(soap);
11516 switch (c)
11518 case SOAP_TT:
11519 if (n == 0)
11520 goto end;
11521 n--;
11522 *s++ = '<';
11523 t = (char*)"/";
11524 m = 1;
11525 break;
11526 case SOAP_LT:
11527 if (f && n == 0)
11528 goto end;
11529 n++;
11530 *s++ = '<';
11531 break;
11532 case SOAP_GT:
11533 *s++ = '>';
11534 break;
11535 case SOAP_QT:
11536 *s++ = '"';
11537 break;
11538 case SOAP_AP:
11539 *s++ = '\'';
11540 break;
11541 case '/':
11542 if (n > 0)
11543 { if (!flag)
11544 { c = soap_getchar(soap);
11545 if (c == '>')
11546 n--;
11548 else
11549 { c = soap_get(soap);
11550 if (c == SOAP_GT)
11551 n--;
11553 soap_unget(soap, c);
11555 *s++ = '/';
11556 break;
11557 case (soap_wchar)('<' | 0x80000000):
11558 if (flag)
11559 *s++ = '<';
11560 else
11561 { *s++ = '&';
11562 t = (char*)"lt;";
11563 m = 3;
11565 break;
11566 case (soap_wchar)('>' | 0x80000000):
11567 if (flag)
11568 *s++ = '>';
11569 else
11570 { *s++ = '&';
11571 t = (char*)"gt;";
11572 m = 3;
11574 break;
11575 case (soap_wchar)('&' | 0x80000000):
11576 if (flag)
11577 *s++ = '&';
11578 else
11579 { *s++ = '&';
11580 t = (char*)"amp;";
11581 m = 4;
11583 break;
11584 case (soap_wchar)('"' | 0x80000000):
11585 if (flag)
11586 *s++ = '"';
11587 else
11588 { *s++ = '&';
11589 t = (char*)"quot;";
11590 m = 5;
11592 break;
11593 case (soap_wchar)('\'' | 0x80000000):
11594 if (flag)
11595 *s++ = '\'';
11596 else
11597 { *s++ = '&';
11598 t = (char*)"apos;";
11599 m = 5;
11601 break;
11602 default:
11603 if ((int)c == EOF)
11604 goto end;
11605 #ifndef WITH_CDATA
11606 if (c == '<' && !flag)
11607 { if (f && n == 0)
11608 goto end;
11609 c = soap_getchar(soap);
11610 soap_unget(soap, c);
11611 if (c == '/')
11612 { c = SOAP_TT;
11613 if (n == 0)
11614 goto end;
11615 n--;
11617 else
11618 n++;
11619 *s++ = '<';
11620 break;
11622 else
11623 #endif
11624 #ifndef WITH_LEANER
11625 #ifdef HAVE_WCTOMB
11626 if (soap->mode & SOAP_C_MBSTRING)
11627 { m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
11628 if (m >= 1 && m <= (int)MB_CUR_MAX)
11629 { t = buf;
11630 *s++ = *t++;
11631 m--;
11633 else
11634 { *s++ = SOAP_UNKNOWN_CHAR;
11635 m = 0;
11638 else
11639 #endif
11640 #endif
11641 *s++ = (char)(c & 0xFF);
11643 l++;
11644 if (maxlen >= 0 && l > maxlen)
11645 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
11646 soap->error = SOAP_LENGTH;
11647 return NULL;
11651 end:
11652 soap_unget(soap, c);
11653 *s = '\0';
11654 #ifdef WITH_FAST
11655 t = soap_strdup(soap, soap->labbuf);
11656 #else
11657 soap_size_block(soap, NULL, i + 1);
11658 t = soap_save_block(soap, NULL, 0);
11659 #endif
11660 if (l < minlen)
11661 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
11662 soap->error = SOAP_LENGTH;
11663 return NULL;
11665 #ifdef WITH_DOM
11666 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
11667 { if (flag == 3)
11668 soap->dom->tail = t;
11669 else
11670 soap->dom->data = t;
11672 #endif
11673 if (flag == 2)
11674 if (soap_s2QName(soap, t, &t, minlen, maxlen))
11675 return NULL;
11676 return t;
11678 #endif
11680 /******************************************************************************/
11681 #ifndef WITH_LEANER
11682 #ifndef PALM_2
11683 SOAP_FMAC1
11685 SOAP_FMAC2
11686 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
11687 { const char *t;
11688 char tmp;
11689 register soap_wchar c;
11690 #ifdef WITH_DOM
11691 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
11692 { wchar_t *r = (wchar_t*)s;
11693 int n = 1;
11694 while (*r++)
11695 n++;
11696 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
11697 while (n--)
11698 *r++ = *s++;
11699 return SOAP_OK;
11701 #endif
11702 while ((c = *s++))
11703 { switch (c)
11705 case 0x09:
11706 if (flag)
11707 t = "&#x9;";
11708 else
11709 t = "\t";
11710 break;
11711 case 0x0A:
11712 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
11713 t = "&#xA;";
11714 else
11715 t = "\n";
11716 break;
11717 case 0x0D:
11718 t = "&#xD;";
11719 break;
11720 case '&':
11721 t = "&amp;";
11722 break;
11723 case '<':
11724 t = "&lt;";
11725 break;
11726 case '>':
11727 if (flag)
11728 t = ">";
11729 else
11730 t = "&gt;";
11731 break;
11732 case '"':
11733 if (flag)
11734 t = "&quot;";
11735 else
11736 t = "\"";
11737 break;
11738 default:
11739 if (c >= 0x20 && c < 0x80)
11740 { tmp = (char)c;
11741 if (soap_send_raw(soap, &tmp, 1))
11742 return soap->error;
11744 else
11745 { /* check for UTF16 encoding when wchar_t is too small to hold UCS */
11746 if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
11747 { register soap_wchar d = *s++;
11748 if ((d & 0xFC00) == 0xDC00)
11749 c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
11750 else
11751 c = 0xFFFD; /* Malformed */
11753 if (soap_pututf8(soap, (unsigned long)c))
11754 return soap->error;
11756 continue;
11758 if (soap_send(soap, t))
11759 return soap->error;
11761 return SOAP_OK;
11763 #endif
11764 #endif
11766 /******************************************************************************/
11767 #ifndef WITH_LEANER
11768 #ifndef PALM_2
11769 SOAP_FMAC1
11770 wchar_t *
11771 SOAP_FMAC2
11772 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
11773 { wchar_t *s;
11774 register int i, n = 0, f = 0;
11775 register long l = 0;
11776 register soap_wchar c;
11777 char *t = NULL;
11778 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
11779 if (soap->peeked)
11780 { if (*soap->tag)
11782 #ifndef WITH_LEAN
11783 struct soap_attribute *tp;
11784 t = soap->tmpbuf;
11785 *t = '<';
11786 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
11787 t[sizeof(soap->tmpbuf) - 1] = '\0';
11788 t += strlen(t);
11789 for (tp = soap->attributes; tp; tp = tp->next)
11790 { if (tp->visible)
11791 { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
11792 break;
11793 *t++ = ' ';
11794 strcpy(t, tp->name);
11795 t += strlen(t);
11796 if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
11797 break;
11798 if (tp->value)
11799 { *t++ = '=';
11800 *t++ = '"';
11801 strcpy(t, tp->value);
11802 t += strlen(t);
11803 *t++ = '"';
11807 if (!soap->body)
11808 *t++ = '/';
11809 *t++ = '>';
11810 *t = '\0';
11811 t = soap->tmpbuf;
11812 #endif
11813 if (soap->body)
11814 n = 1;
11815 f = 1;
11816 soap->peeked = 0;
11819 if (soap_new_block(soap) == NULL)
11820 return NULL;
11821 for (;;)
11822 { if (!(s = (wchar_t*)soap_push_block(soap, NULL, sizeof(wchar_t)*SOAP_BLKLEN)))
11823 return NULL;
11824 for (i = 0; i < SOAP_BLKLEN; i++)
11825 { if (t)
11826 { *s++ = (wchar_t)*t++;
11827 if (!*t)
11828 t = NULL;
11829 continue;
11831 c = soap_getutf8(soap);
11832 switch (c)
11834 case SOAP_TT:
11835 if (n == 0)
11836 goto end;
11837 n--;
11838 *s++ = '<';
11839 soap_unget(soap, '/');
11840 break;
11841 case SOAP_LT:
11842 if (f && n == 0)
11843 goto end;
11844 n++;
11845 *s++ = '<';
11846 break;
11847 case SOAP_GT:
11848 *s++ = '>';
11849 break;
11850 case SOAP_QT:
11851 *s++ = '"';
11852 break;
11853 case SOAP_AP:
11854 *s++ = '\'';
11855 break;
11856 case '/':
11857 if (n > 0)
11858 { c = soap_getutf8(soap);
11859 if (c == SOAP_GT)
11860 n--;
11861 soap_unget(soap, c);
11863 *s++ = '/';
11864 break;
11865 case '<':
11866 if (flag)
11867 *s++ = (soap_wchar)'<';
11868 else
11869 { *s++ = (soap_wchar)'&';
11870 t = (char*)"lt;";
11872 break;
11873 case '>':
11874 if (flag)
11875 *s++ = (soap_wchar)'>';
11876 else
11877 { *s++ = (soap_wchar)'&';
11878 t = (char*)"gt;";
11880 break;
11881 case '"':
11882 if (flag)
11883 *s++ = (soap_wchar)'"';
11884 else
11885 { *s++ = (soap_wchar)'&';
11886 t = (char*)"quot;";
11888 break;
11889 default:
11890 if ((int)c == EOF)
11891 goto end;
11892 /* use UTF16 encoding when wchar_t is too small to hold UCS */
11893 if (sizeof(wchar_t) < 4 && c > 0xFFFF)
11894 { register soap_wchar c1, c2;
11895 c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
11896 c2 = 0xDC00 + (c & 0x3FF);
11897 c = c1;
11898 soap_unget(soap, c2);
11900 *s++ = (wchar_t)c & 0x7FFFFFFF;
11902 l++;
11903 if (maxlen >= 0 && l > maxlen)
11904 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
11905 soap->error = SOAP_LENGTH;
11906 return NULL;
11910 end:
11911 soap_unget(soap, c);
11912 *s = '\0';
11913 soap_size_block(soap, NULL, sizeof(wchar_t) * (i + 1));
11914 if (l < minlen)
11915 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
11916 soap->error = SOAP_LENGTH;
11917 return NULL;
11919 s = (wchar_t*)soap_save_block(soap, NULL, NULL, 0);
11920 #ifdef WITH_DOM
11921 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
11922 soap->dom->wide = s;
11923 #endif
11924 return s;
11926 #endif
11927 #endif
11929 /******************************************************************************/
11930 #ifndef PALM_2
11931 SOAP_FMAC1
11932 const char*
11933 SOAP_FMAC2
11934 soap_int2s(struct soap *soap, int n)
11935 { return soap_long2s(soap, (long)n);
11937 #endif
11939 /******************************************************************************/
11940 #ifndef PALM_2
11941 SOAP_FMAC1
11943 SOAP_FMAC2
11944 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
11945 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
11946 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
11947 return soap->error;
11948 return soap_element_end_out(soap, tag);
11950 #endif
11952 /******************************************************************************/
11953 #ifndef PALM_2
11954 SOAP_FMAC1
11956 SOAP_FMAC2
11957 soap_s2int(struct soap *soap, const char *s, int *p)
11958 { if (s)
11959 { long n;
11960 char *r;
11961 #ifndef WITH_NOIO
11962 #ifndef WITH_LEAN
11963 soap_reset_errno;
11964 #endif
11965 #endif
11966 n = soap_strtol(s, &r, 10);
11967 if (s == r || *r
11968 #ifndef WITH_LEAN
11969 || n != (int)n
11970 #endif
11971 #ifndef WITH_NOIO
11972 #ifndef WITH_LEAN
11973 || soap_errno == SOAP_ERANGE
11974 #endif
11975 #endif
11977 soap->error = SOAP_TYPE;
11978 *p = (int)n;
11980 return soap->error;
11982 #endif
11984 /******************************************************************************/
11985 #ifndef PALM_2
11986 SOAP_FMAC1
11987 int *
11988 SOAP_FMAC2
11989 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
11990 { if (soap_element_begin_in(soap, tag, 0, NULL))
11991 return NULL;
11992 #ifndef WITH_LEAN
11993 if (*soap->type
11994 && soap_match_tag(soap, soap->type, type)
11995 && soap_match_tag(soap, soap->type, ":int")
11996 && soap_match_tag(soap, soap->type, ":short")
11997 && soap_match_tag(soap, soap->type, ":byte"))
11998 { soap->error = SOAP_TYPE;
11999 soap_revert(soap);
12000 return NULL;
12002 #endif
12003 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
12004 if (*soap->href)
12005 p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
12006 else if (p)
12007 { if (soap_s2int(soap, soap_value(soap), p))
12008 return NULL;
12010 if (soap->body && soap_element_end_in(soap, tag))
12011 return NULL;
12012 return p;
12014 #endif
12016 /******************************************************************************/
12017 #ifndef PALM_2
12018 SOAP_FMAC1
12019 const char*
12020 SOAP_FMAC2
12021 soap_long2s(struct soap *soap, long n)
12023 #ifdef HAVE_SNPRINTF
12024 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%ld", n);
12025 #else
12026 sprintf(soap->tmpbuf, "%ld", n);
12027 #endif
12028 return soap->tmpbuf;
12030 #endif
12032 /******************************************************************************/
12033 #ifndef PALM_2
12034 SOAP_FMAC1
12036 SOAP_FMAC2
12037 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
12038 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12039 || soap_string_out(soap, soap_long2s(soap, *p), 0))
12040 return soap->error;
12041 return soap_element_end_out(soap, tag);
12043 #endif
12045 /******************************************************************************/
12046 #ifndef PALM_2
12047 SOAP_FMAC1
12049 SOAP_FMAC2
12050 soap_s2long(struct soap *soap, const char *s, long *p)
12051 { if (s)
12052 { char *r;
12053 #ifndef WITH_NOIO
12054 #ifndef WITH_LEAN
12055 soap_reset_errno;
12056 #endif
12057 #endif
12058 *p = soap_strtol(s, &r, 10);
12059 if (s == r || *r
12060 #ifndef WITH_NOIO
12061 #ifndef WITH_LEAN
12062 || soap_errno == SOAP_ERANGE
12063 #endif
12064 #endif
12066 soap->error = SOAP_TYPE;
12068 return soap->error;
12070 #endif
12072 /******************************************************************************/
12073 #ifndef PALM_2
12074 SOAP_FMAC1
12075 long *
12076 SOAP_FMAC2
12077 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
12078 { if (soap_element_begin_in(soap, tag, 0, NULL))
12079 return NULL;
12080 #ifndef WITH_LEAN
12081 if (*soap->type
12082 && soap_match_tag(soap, soap->type, type)
12083 && soap_match_tag(soap, soap->type, ":int")
12084 && soap_match_tag(soap, soap->type, ":short")
12085 && soap_match_tag(soap, soap->type, ":byte"))
12086 { soap->error = SOAP_TYPE;
12087 soap_revert(soap);
12088 return NULL;
12090 #endif
12091 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
12092 if (*soap->href)
12093 p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
12094 else if (p)
12095 { if (soap_s2long(soap, soap_value(soap), p))
12096 return NULL;
12098 if (soap->body && soap_element_end_in(soap, tag))
12099 return NULL;
12100 return p;
12102 #endif
12104 /******************************************************************************/
12105 #ifndef WITH_LEAN
12106 SOAP_FMAC1
12107 const char*
12108 SOAP_FMAC2
12109 soap_LONG642s(struct soap *soap, LONG64 n)
12111 #ifdef HAVE_SNPRINTF
12112 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_LONG_FORMAT, n);
12113 #else
12114 sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
12115 #endif
12116 return soap->tmpbuf;
12118 #endif
12120 /******************************************************************************/
12121 #ifndef WITH_LEAN
12122 SOAP_FMAC1
12124 SOAP_FMAC2
12125 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
12126 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12127 || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
12128 return soap->error;
12129 return soap_element_end_out(soap, tag);
12131 #endif
12133 /******************************************************************************/
12134 #ifndef WITH_LEAN
12135 SOAP_FMAC1
12137 SOAP_FMAC2
12138 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
12139 { if (s)
12141 #ifdef HAVE_STRTOLL
12142 char *r;
12143 #ifndef WITH_NOIO
12144 #ifndef WITH_LEAN
12145 soap_reset_errno;
12146 #endif
12147 #endif
12148 *p = soap_strtoll(s, &r, 10);
12149 if (s == r || *r
12150 #ifndef WITH_NOIO
12151 #ifndef WITH_LEAN
12152 || soap_errno == SOAP_ERANGE
12153 #endif
12154 #endif
12156 #else
12157 # ifdef HAVE_SSCANF
12158 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
12159 # endif
12160 #endif
12161 soap->error = SOAP_TYPE;
12163 return soap->error;
12165 #endif
12167 /******************************************************************************/
12168 #ifndef WITH_LEAN
12169 SOAP_FMAC1
12170 LONG64 *
12171 SOAP_FMAC2
12172 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
12173 { if (soap_element_begin_in(soap, tag, 0, NULL))
12174 return NULL;
12175 #ifndef WITH_LEAN
12176 if (*soap->type
12177 && soap_match_tag(soap, soap->type, type)
12178 && soap_match_tag(soap, soap->type, ":integer")
12179 && soap_match_tag(soap, soap->type, ":positiveInteger")
12180 && soap_match_tag(soap, soap->type, ":negativeInteger")
12181 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
12182 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
12183 && soap_match_tag(soap, soap->type, ":long")
12184 && soap_match_tag(soap, soap->type, ":int")
12185 && soap_match_tag(soap, soap->type, ":short")
12186 && soap_match_tag(soap, soap->type, ":byte"))
12187 { soap->error = SOAP_TYPE;
12188 soap_revert(soap);
12189 return NULL;
12191 #endif
12192 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
12193 if (*soap->href)
12194 p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
12195 else if (p)
12196 { if (soap_s2LONG64(soap, soap_value(soap), p))
12197 return NULL;
12199 if (soap->body && soap_element_end_in(soap, tag))
12200 return NULL;
12201 return p;
12203 #endif
12205 /******************************************************************************/
12206 #ifndef PALM_2
12207 SOAP_FMAC1
12208 const char*
12209 SOAP_FMAC2
12210 soap_byte2s(struct soap *soap, char n)
12211 { return soap_long2s(soap, (long)n);
12213 #endif
12215 /******************************************************************************/
12216 #ifndef PALM_2
12217 SOAP_FMAC1
12219 SOAP_FMAC2
12220 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
12221 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12222 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
12223 return soap->error;
12224 return soap_element_end_out(soap, tag);
12226 #endif
12228 /******************************************************************************/
12229 #ifndef PALM_2
12230 SOAP_FMAC1
12232 SOAP_FMAC2
12233 soap_s2byte(struct soap *soap, const char *s, char *p)
12234 { if (s)
12235 { long n;
12236 char *r;
12237 n = soap_strtol(s, &r, 10);
12238 if (s == r || *r || n < -128 || n > 127)
12239 soap->error = SOAP_TYPE;
12240 *p = (char)n;
12242 return soap->error;
12244 #endif
12246 /******************************************************************************/
12247 #ifndef PALM_2
12248 SOAP_FMAC1
12249 char *
12250 SOAP_FMAC2
12251 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
12252 { if (soap_element_begin_in(soap, tag, 0, NULL))
12253 return NULL;
12254 #ifndef WITH_LEAN
12255 if (*soap->type
12256 && soap_match_tag(soap, soap->type, type)
12257 && soap_match_tag(soap, soap->type, ":byte"))
12258 { soap->error = SOAP_TYPE;
12259 soap_revert(soap);
12260 return NULL;
12262 #endif
12263 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
12264 if (*soap->href)
12265 p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
12266 else if (p)
12267 { if (soap_s2byte(soap, soap_value(soap), p))
12268 return NULL;
12270 if (soap->body && soap_element_end_in(soap, tag))
12271 return NULL;
12272 return p;
12274 #endif
12276 /******************************************************************************/
12277 #ifndef PALM_2
12278 SOAP_FMAC1
12279 const char*
12280 SOAP_FMAC2
12281 soap_short2s(struct soap *soap, short n)
12282 { return soap_long2s(soap, (long)n);
12284 #endif
12286 /******************************************************************************/
12287 #ifndef PALM_2
12288 SOAP_FMAC1
12290 SOAP_FMAC2
12291 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
12292 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12293 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
12294 return soap->error;
12295 return soap_element_end_out(soap, tag);
12297 #endif
12299 /******************************************************************************/
12300 #ifndef PALM_2
12301 SOAP_FMAC1
12303 SOAP_FMAC2
12304 soap_s2short(struct soap *soap, const char *s, short *p)
12305 { if (s)
12306 { long n;
12307 char *r;
12308 n = soap_strtol(s, &r, 10);
12309 if (s == r || *r || n < -32768 || n > 32767)
12310 soap->error = SOAP_TYPE;
12311 *p = (short)n;
12313 return soap->error;
12315 #endif
12317 /******************************************************************************/
12318 #ifndef PALM_2
12319 SOAP_FMAC1
12320 short *
12321 SOAP_FMAC2
12322 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
12323 { if (soap_element_begin_in(soap, tag, 0, NULL))
12324 return NULL;
12325 #ifndef WITH_LEAN
12326 if (*soap->type
12327 && soap_match_tag(soap, soap->type, type)
12328 && soap_match_tag(soap, soap->type, ":short")
12329 && soap_match_tag(soap, soap->type, ":byte"))
12330 { soap->error = SOAP_TYPE;
12331 soap_revert(soap);
12332 return NULL;
12334 #endif
12335 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
12336 if (*soap->href)
12337 p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
12338 else if (p)
12339 { if (soap_s2short(soap, soap_value(soap), p))
12340 return NULL;
12342 if (soap->body && soap_element_end_in(soap, tag))
12343 return NULL;
12344 return p;
12346 #endif
12348 /******************************************************************************/
12349 #ifndef PALM_2
12350 SOAP_FMAC1
12351 const char*
12352 SOAP_FMAC2
12353 soap_float2s(struct soap *soap, float n)
12354 { char *s;
12355 if (soap_isnan((double)n))
12356 return "NaN";
12357 if (soap_ispinff(n))
12358 return "INF";
12359 if (soap_isninff(n))
12360 return "-INF";
12361 #if defined(HAVE_SPRINTF_L)
12362 # ifdef WIN32
12363 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, soap->c_locale, n);
12364 # else
12365 sprintf_l(soap->tmpbuf, soap->c_locale, soap->float_format, n);
12366 # endif
12367 #else
12368 # ifdef HAVE_SNPRINTF
12369 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->float_format, n);
12370 # else
12371 sprintf(soap->tmpbuf, soap->float_format, n);
12372 # endif
12373 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
12374 if (s)
12375 *s = '.';
12376 #endif
12377 return soap->tmpbuf;
12379 #endif
12381 /******************************************************************************/
12382 #ifndef PALM_2
12383 SOAP_FMAC1
12385 SOAP_FMAC2
12386 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
12387 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12388 || soap_string_out(soap, soap_float2s(soap, *p), 0))
12389 return soap->error;
12390 return soap_element_end_out(soap, tag);
12392 #endif
12394 /******************************************************************************/
12395 #ifndef PALM_2
12396 SOAP_FMAC1
12398 SOAP_FMAC2
12399 soap_s2float(struct soap *soap, const char *s, float *p)
12400 { if (s)
12401 { if (!*s)
12402 return soap->error = SOAP_TYPE;
12403 if (!soap_tag_cmp(s, "INF"))
12404 *p = FLT_PINFTY;
12405 else if (!soap_tag_cmp(s, "+INF"))
12406 *p = FLT_PINFTY;
12407 else if (!soap_tag_cmp(s, "-INF"))
12408 *p = FLT_NINFTY;
12409 else if (!soap_tag_cmp(s, "NaN"))
12410 *p = FLT_NAN;
12411 else
12413 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
12414 #if defined(HAVE_STRTOD_L)
12415 char *r;
12416 # ifdef WIN32
12417 *p = (float)_strtod_l(s, &r, soap->c_locale);
12418 # else
12419 *p = (float)strtod_l(s, &r, soap->c_locale);
12420 # endif
12421 if (*r)
12422 #elif defined(HAVE_STRTOD)
12423 char *r;
12424 *p = (float)strtod(s, &r);
12425 if (*r)
12426 #elif defined(HAVE_STRTOF_L)
12427 char *r;
12428 *p = strtof_l((char*)s, &r, soap->c_locale);
12429 if (*r)
12430 #elif defined(HAVE_STRTOF)
12431 char *r;
12432 *p = strtof((char*)s, &r);
12433 if (*r)
12434 #endif
12436 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
12437 if (sscanf_l(s, soap->c_locale, "%f", p) != 1)
12438 soap->error = SOAP_TYPE;
12439 #elif defined(HAVE_SSCANF)
12440 if (sscanf(s, "%f", p) != 1)
12441 soap->error = SOAP_TYPE;
12442 #else
12443 soap->error = SOAP_TYPE;
12444 #endif
12448 return soap->error;
12450 #endif
12452 /******************************************************************************/
12453 #ifndef WITH_LEAN
12454 static int soap_isnumeric(struct soap *soap, const char *type)
12455 { if (soap_match_tag(soap, soap->type, type)
12456 && soap_match_tag(soap, soap->type, ":float")
12457 && soap_match_tag(soap, soap->type, ":double")
12458 && soap_match_tag(soap, soap->type, ":decimal")
12459 && soap_match_tag(soap, soap->type, ":integer")
12460 && soap_match_tag(soap, soap->type, ":positiveInteger")
12461 && soap_match_tag(soap, soap->type, ":negativeInteger")
12462 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
12463 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
12464 && soap_match_tag(soap, soap->type, ":long")
12465 && soap_match_tag(soap, soap->type, ":int")
12466 && soap_match_tag(soap, soap->type, ":short")
12467 && soap_match_tag(soap, soap->type, ":byte")
12468 && soap_match_tag(soap, soap->type, ":unsignedLong")
12469 && soap_match_tag(soap, soap->type, ":unsignedInt")
12470 && soap_match_tag(soap, soap->type, ":unsignedShort")
12471 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12472 { soap->error = SOAP_TYPE;
12473 soap_revert(soap);
12474 return SOAP_ERR;
12476 return SOAP_OK;
12478 #endif
12480 /******************************************************************************/
12481 #ifndef PALM_2
12482 SOAP_FMAC1
12483 float *
12484 SOAP_FMAC2
12485 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
12486 { if (soap_element_begin_in(soap, tag, 0, NULL))
12487 return NULL;
12488 #ifndef WITH_LEAN
12489 if (*soap->type != '\0' && soap_isnumeric(soap, type))
12490 return NULL;
12491 #endif
12492 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
12493 if (*soap->href)
12494 p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
12495 else if (p)
12496 { if (soap_s2float(soap, soap_value(soap), p))
12497 return NULL;
12499 if (soap->body && soap_element_end_in(soap, tag))
12500 return NULL;
12501 return p;
12503 #endif
12505 /******************************************************************************/
12506 #ifndef PALM_2
12507 SOAP_FMAC1
12508 const char*
12509 SOAP_FMAC2
12510 soap_double2s(struct soap *soap, double n)
12511 { char *s;
12512 if (soap_isnan(n))
12513 return "NaN";
12514 if (soap_ispinfd(n))
12515 return "INF";
12516 if (soap_isninfd(n))
12517 return "-INF";
12518 #if defined(HAVE_SPRINTF_L)
12519 # ifdef WIN32
12520 _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, soap->c_locale, n);
12521 # else
12522 sprintf_l(soap->tmpbuf, soap->c_locale, soap->double_format, n);
12523 # endif
12524 #else
12525 # ifdef HAVE_SNPRINTF
12526 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->double_format, n);
12527 #else
12528 sprintf(soap->tmpbuf, soap->double_format, n);
12529 #endif
12530 s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
12531 if (s)
12532 *s = '.';
12533 #endif
12534 return soap->tmpbuf;
12536 #endif
12538 /******************************************************************************/
12539 #ifndef PALM_2
12540 SOAP_FMAC1
12542 SOAP_FMAC2
12543 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
12544 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12545 || soap_string_out(soap, soap_double2s(soap, *p), 0))
12546 return soap->error;
12547 return soap_element_end_out(soap, tag);
12549 #endif
12551 /******************************************************************************/
12552 #ifndef PALM_2
12553 SOAP_FMAC1
12555 SOAP_FMAC2
12556 soap_s2double(struct soap *soap, const char *s, double *p)
12557 { if (s)
12558 { if (!*s)
12559 return soap->error = SOAP_TYPE;
12560 if (!soap_tag_cmp(s, "INF"))
12561 *p = DBL_PINFTY;
12562 else if (!soap_tag_cmp(s, "+INF"))
12563 *p = DBL_PINFTY;
12564 else if (!soap_tag_cmp(s, "-INF"))
12565 *p = DBL_NINFTY;
12566 else if (!soap_tag_cmp(s, "NaN"))
12567 *p = DBL_NAN;
12568 else
12570 #if defined(HAVE_STRTOD_L)
12571 char *r;
12572 # ifdef WIN32
12573 *p = _strtod_l(s, &r, soap->c_locale);
12574 # else
12575 *p = strtod_l(s, &r, soap->c_locale);
12576 # endif
12577 if (*r)
12578 #elif defined(HAVE_STRTOD)
12579 char *r;
12580 *p = strtod(s, &r);
12581 if (*r)
12582 #endif
12584 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
12585 if (sscanf_l(s, soap->c_locale, "%lf", p) != 1)
12586 soap->error = SOAP_TYPE;
12587 #elif defined(HAVE_SSCANF)
12588 if (sscanf(s, "%lf", p) != 1)
12589 soap->error = SOAP_TYPE;
12590 #else
12591 soap->error = SOAP_TYPE;
12592 #endif
12596 return soap->error;
12598 #endif
12600 /******************************************************************************/
12601 #ifndef PALM_2
12602 SOAP_FMAC1
12603 double *
12604 SOAP_FMAC2
12605 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
12606 { if (soap_element_begin_in(soap, tag, 0, NULL))
12607 return NULL;
12608 #ifndef WITH_LEAN
12609 if (*soap->type != '\0' && soap_isnumeric(soap, type))
12610 return NULL;
12611 #endif
12612 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
12613 if (*soap->href)
12614 p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
12615 else if (p)
12616 { if (soap_s2double(soap, soap_value(soap), p))
12617 return NULL;
12619 if (soap->body && soap_element_end_in(soap, tag))
12620 return NULL;
12621 return p;
12623 #endif
12625 /******************************************************************************/
12626 #ifndef PALM_2
12627 SOAP_FMAC1
12628 const char*
12629 SOAP_FMAC2
12630 soap_unsignedByte2s(struct soap *soap, unsigned char n)
12631 { return soap_unsignedLong2s(soap, (unsigned long)n);
12633 #endif
12635 /******************************************************************************/
12636 #ifndef PALM_2
12637 SOAP_FMAC1
12639 SOAP_FMAC2
12640 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
12641 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12642 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
12643 return soap->error;
12644 return soap_element_end_out(soap, tag);
12646 #endif
12648 /******************************************************************************/
12649 #ifndef PALM_2
12650 SOAP_FMAC1
12652 SOAP_FMAC2
12653 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
12654 { if (s)
12655 { unsigned long n;
12656 char *r;
12657 n = soap_strtoul(s, &r, 10);
12658 if (s == r || *r || n > 255)
12659 soap->error = SOAP_TYPE;
12660 *p = (unsigned char)n;
12662 return soap->error;
12664 #endif
12666 /******************************************************************************/
12667 #ifndef PALM_2
12668 SOAP_FMAC1
12669 unsigned char *
12670 SOAP_FMAC2
12671 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
12672 { if (soap_element_begin_in(soap, tag, 0, NULL))
12673 return NULL;
12674 #ifndef WITH_LEAN
12675 if (*soap->type
12676 && soap_match_tag(soap, soap->type, type)
12677 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12678 { soap->error = SOAP_TYPE;
12679 soap_revert(soap);
12680 return NULL;
12682 #endif
12683 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
12684 if (*soap->href)
12685 p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
12686 else if (p)
12687 { if (soap_s2unsignedByte(soap, soap_value(soap), p))
12688 return NULL;
12690 if (soap->body && soap_element_end_in(soap, tag))
12691 return NULL;
12692 return p;
12694 #endif
12696 /******************************************************************************/
12697 #ifndef PALM_2
12698 SOAP_FMAC1
12699 const char*
12700 SOAP_FMAC2
12701 soap_unsignedShort2s(struct soap *soap, unsigned short n)
12702 { return soap_unsignedLong2s(soap, (unsigned long)n);
12704 #endif
12706 /******************************************************************************/
12707 #ifndef PALM_2
12708 SOAP_FMAC1
12710 SOAP_FMAC2
12711 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
12712 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12713 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
12714 return soap->error;
12715 return soap_element_end_out(soap, tag);
12717 #endif
12719 /******************************************************************************/
12720 #ifndef PALM_2
12721 SOAP_FMAC1
12723 SOAP_FMAC2
12724 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
12725 { if (s)
12726 { unsigned long n;
12727 char *r;
12728 n = soap_strtoul(s, &r, 10);
12729 if (s == r || *r || n > 65535)
12730 soap->error = SOAP_TYPE;
12731 *p = (unsigned short)n;
12733 return soap->error;
12735 #endif
12737 /******************************************************************************/
12738 #ifndef PALM_2
12739 SOAP_FMAC1
12740 unsigned short *
12741 SOAP_FMAC2
12742 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
12743 { if (soap_element_begin_in(soap, tag, 0, NULL))
12744 return NULL;
12745 #ifndef WITH_LEAN
12746 if (*soap->type
12747 && soap_match_tag(soap, soap->type, type)
12748 && soap_match_tag(soap, soap->type, ":unsignedShort")
12749 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12750 { soap->error = SOAP_TYPE;
12751 soap_revert(soap);
12752 return NULL;
12754 #endif
12755 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
12756 if (*soap->href)
12757 p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
12758 else if (p)
12759 { if (soap_s2unsignedShort(soap, soap_value(soap), p))
12760 return NULL;
12762 if (soap->body && soap_element_end_in(soap, tag))
12763 return NULL;
12764 return p;
12766 #endif
12768 /******************************************************************************/
12769 #ifndef PALM_2
12770 SOAP_FMAC1
12771 const char*
12772 SOAP_FMAC2
12773 soap_unsignedInt2s(struct soap *soap, unsigned int n)
12774 { return soap_unsignedLong2s(soap, (unsigned long)n);
12776 #endif
12778 /******************************************************************************/
12779 #ifndef PALM_2
12780 SOAP_FMAC1
12782 SOAP_FMAC2
12783 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
12784 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12785 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
12786 return soap->error;
12787 return soap_element_end_out(soap, tag);
12789 #endif
12791 /******************************************************************************/
12792 #ifndef PALM_2
12793 SOAP_FMAC1
12795 SOAP_FMAC2
12796 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
12797 { if (s)
12798 { char *r;
12799 #ifndef WITH_NOIO
12800 #ifndef WITH_LEAN
12801 soap_reset_errno;
12802 #endif
12803 #endif
12804 *p = (unsigned int)soap_strtoul(s, &r, 10);
12805 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
12806 #ifndef WITH_NOIO
12807 #ifndef WITH_LEAN
12808 || soap_errno == SOAP_ERANGE
12809 #endif
12810 #endif
12812 soap->error = SOAP_TYPE;
12814 return soap->error;
12816 #endif
12818 /******************************************************************************/
12819 #ifndef PALM_2
12820 SOAP_FMAC1
12821 unsigned int *
12822 SOAP_FMAC2
12823 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
12824 { if (soap_element_begin_in(soap, tag, 0, NULL))
12825 return NULL;
12826 #ifndef WITH_LEAN
12827 if (*soap->type
12828 && soap_match_tag(soap, soap->type, type)
12829 && soap_match_tag(soap, soap->type, ":unsignedInt")
12830 && soap_match_tag(soap, soap->type, ":unsignedShort")
12831 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12832 { soap->error = SOAP_TYPE;
12833 soap_revert(soap);
12834 return NULL;
12836 #endif
12837 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
12838 if (*soap->href)
12839 p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
12840 else if (p)
12841 { if (soap_s2unsignedInt(soap, soap_value(soap), p))
12842 return NULL;
12844 if (soap->body && soap_element_end_in(soap, tag))
12845 return NULL;
12846 return p;
12848 #endif
12850 /******************************************************************************/
12851 #ifndef PALM_2
12852 SOAP_FMAC1
12853 const char*
12854 SOAP_FMAC2
12855 soap_unsignedLong2s(struct soap *soap, unsigned long n)
12857 #ifdef HAVE_SNPRINTF
12858 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", n);
12859 #else
12860 sprintf(soap->tmpbuf, "%lu", n);
12861 #endif
12862 return soap->tmpbuf;
12864 #endif
12866 /******************************************************************************/
12867 #ifndef PALM_2
12868 SOAP_FMAC1
12870 SOAP_FMAC2
12871 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
12872 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12873 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
12874 return soap->error;
12875 return soap_element_end_out(soap, tag);
12877 #endif
12879 /******************************************************************************/
12880 #ifndef PALM_2
12881 SOAP_FMAC1
12883 SOAP_FMAC2
12884 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
12885 { if (s)
12886 { char *r;
12887 #ifndef WITH_NOIO
12888 #ifndef WITH_LEAN
12889 soap_reset_errno;
12890 #endif
12891 #endif
12892 *p = soap_strtoul(s, &r, 10);
12893 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
12894 #ifndef WITH_NOIO
12895 #ifndef WITH_LEAN
12896 || soap_errno == SOAP_ERANGE
12897 #endif
12898 #endif
12900 soap->error = SOAP_TYPE;
12902 return soap->error;
12904 #endif
12906 /******************************************************************************/
12907 #ifndef PALM_2
12908 SOAP_FMAC1
12909 unsigned long *
12910 SOAP_FMAC2
12911 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
12912 { if (soap_element_begin_in(soap, tag, 0, NULL))
12913 return NULL;
12914 #ifndef WITH_LEAN
12915 if (*soap->type
12916 && soap_match_tag(soap, soap->type, type)
12917 && soap_match_tag(soap, soap->type, ":unsignedInt")
12918 && soap_match_tag(soap, soap->type, ":unsignedShort")
12919 && soap_match_tag(soap, soap->type, ":unsignedByte"))
12920 { soap->error = SOAP_TYPE;
12921 soap_revert(soap);
12922 return NULL;
12924 #endif
12925 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
12926 if (*soap->href)
12927 p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
12928 else if (p)
12929 { if (soap_s2unsignedLong(soap, soap_value(soap), p))
12930 return NULL;
12932 if (soap->body && soap_element_end_in(soap, tag))
12933 return NULL;
12934 return p;
12936 #endif
12938 /******************************************************************************/
12939 #ifndef WITH_LEAN
12940 SOAP_FMAC1
12941 const char*
12942 SOAP_FMAC2
12943 soap_ULONG642s(struct soap *soap, ULONG64 n)
12945 #ifdef HAVE_SNPRINTF
12946 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_ULONG_FORMAT, n);
12947 #else
12948 sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
12949 #endif
12950 return soap->tmpbuf;
12952 #endif
12954 /******************************************************************************/
12955 #ifndef WITH_LEAN
12956 SOAP_FMAC1
12958 SOAP_FMAC2
12959 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
12960 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
12961 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
12962 return soap->error;
12963 return soap_element_end_out(soap, tag);
12965 #endif
12967 /******************************************************************************/
12968 #ifndef WITH_LEAN
12969 SOAP_FMAC1
12971 SOAP_FMAC2
12972 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
12973 { if (s)
12975 #ifdef HAVE_STRTOULL
12976 char *r;
12977 #ifndef WITH_NOIO
12978 #ifndef WITH_LEAN
12979 soap_reset_errno;
12980 #endif
12981 #endif
12982 *p = soap_strtoull(s, &r, 10);
12983 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
12984 #ifndef WITH_NOIO
12985 #ifndef WITH_LEAN
12986 || soap_errno == SOAP_ERANGE
12987 #endif
12988 #endif
12990 #else
12991 #ifdef HAVE_SSCANF
12992 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
12993 #endif
12994 #endif
12995 soap->error = SOAP_TYPE;
12997 return soap->error;
12999 #endif
13001 /******************************************************************************/
13002 #ifndef WITH_LEAN
13003 SOAP_FMAC1
13004 ULONG64 *
13005 SOAP_FMAC2
13006 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
13007 { if (soap_element_begin_in(soap, tag, 0, NULL))
13008 return NULL;
13009 if (*soap->type
13010 && soap_match_tag(soap, soap->type, type)
13011 && soap_match_tag(soap, soap->type, ":positiveInteger")
13012 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
13013 && soap_match_tag(soap, soap->type, ":unsignedLong")
13014 && soap_match_tag(soap, soap->type, ":unsignedInt")
13015 && soap_match_tag(soap, soap->type, ":unsignedShort")
13016 && soap_match_tag(soap, soap->type, ":unsignedByte"))
13017 { soap->error = SOAP_TYPE;
13018 soap_revert(soap);
13019 return NULL;
13021 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
13022 if (*soap->href)
13023 p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
13024 else if (p)
13025 { if (soap_s2ULONG64(soap, soap_value(soap), p))
13026 return NULL;
13028 if (soap->body && soap_element_end_in(soap, tag))
13029 return NULL;
13030 return p;
13032 #endif
13034 /******************************************************************************/
13035 #ifndef PALM_2
13036 SOAP_FMAC1
13038 SOAP_FMAC2
13039 soap_s2string(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
13040 { if (s)
13041 { long l = (long)strlen(s);
13042 if ((maxlen >= 0 && l > maxlen) || l < minlen)
13043 return soap->error = SOAP_LENGTH;
13044 if (!(*t = soap_strdup(soap, s)))
13045 return soap->error = SOAP_EOM;
13046 if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
13047 { char *r = *t;
13048 /* remove non-ASCII chars */
13049 for (s = *t; *s; s++)
13050 if (!(*s & 0x80))
13051 *r++ = *s;
13052 *r = '\0';
13055 return soap->error;
13057 #endif
13059 /******************************************************************************/
13060 #ifndef PALM_2
13061 SOAP_FMAC1
13063 SOAP_FMAC2
13064 soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxlen)
13065 { if (s)
13066 { long l = (long)strlen(s);
13067 if ((maxlen >= 0 && l > maxlen) || l < minlen)
13068 return soap->error = SOAP_LENGTH;
13069 soap->labidx = 0;
13070 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s));
13071 /* convert (by prefix normalize prefix) all QNames in s */
13072 for (;;)
13073 { size_t n;
13074 struct soap_nlist *np;
13075 register const char *p;
13076 /* skip blanks */
13077 while (*s && soap_blank((soap_wchar)*s))
13078 s++;
13079 if (!*s)
13080 break;
13081 /* find next QName */
13082 n = 1;
13083 while (s[n] && !soap_blank((soap_wchar)s[n]))
13084 n++;
13085 np = soap->nlist;
13086 /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
13087 if (!np || *s == '#' || !strncmp(s, "xml:", 4))
13088 { soap_append_lab(soap, s, n);
13090 else /* we normalize the QName by replacing its prefix */
13091 { const char *q;
13092 for (p = s; *p && p < s + n; p++)
13093 if (*p == ':')
13094 break;
13095 if (*p == ':')
13096 { size_t k = p - s;
13097 while (np && (strncmp(np->id, s, k) || np->id[k]))
13098 np = np->next;
13099 p++;
13101 else
13102 { while (np && *np->id)
13103 np = np->next;
13104 p = s;
13106 /* replace prefix */
13107 if (np)
13108 { if (np->index >= 0 && soap->local_namespaces && (q = soap->local_namespaces[np->index].id))
13109 { size_t k = strlen(q);
13110 if (q[k-1] != '_')
13111 soap_append_lab(soap, q, k);
13112 else
13113 { soap_append_lab(soap, "\"", 1);
13114 soap_append_lab(soap, soap->local_namespaces[np->index].ns, strlen(soap->local_namespaces[np->index].ns));
13115 soap_append_lab(soap, "\"", 1);
13118 else if (np->ns)
13119 { soap_append_lab(soap, "\"", 1);
13120 soap_append_lab(soap, np->ns, strlen(np->ns));
13121 soap_append_lab(soap, "\"", 1);
13123 else
13124 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s, np->index, np->ns ? np->ns : SOAP_STR_EOS));
13125 return soap->error = SOAP_NAMESPACE;
13128 else if (s[n]) /* no namespace, part of string */
13129 { soap_append_lab(soap, s, n);
13131 else /* no namespace: assume "" namespace */
13132 { soap_append_lab(soap, "\"\"", 2);
13134 soap_append_lab(soap, ":", 1);
13135 soap_append_lab(soap, p, n - (p-s));
13137 /* advance to next and add spacing */
13138 s += n;
13139 if (*s)
13140 soap_append_lab(soap, " ", 1);
13142 soap_append_lab(soap, SOAP_STR_EOS, 1);
13143 *t = soap_strdup(soap, soap->labbuf);
13144 DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t));
13146 return soap->error;
13148 #endif
13150 /******************************************************************************/
13151 #ifndef PALM_2
13152 SOAP_FMAC1
13153 const char*
13154 SOAP_FMAC2
13155 soap_QName2s(struct soap *soap, const char *s)
13156 { const char *t = NULL;
13157 if (s)
13158 { soap->labidx = 0;
13159 for (;;)
13160 { size_t n;
13161 /* skip blanks */
13162 while (*s && soap_blank((soap_wchar)*s))
13163 s++;
13164 if (!*s)
13165 break;
13166 /* find next QName */
13167 n = 1;
13168 while (s[n] && !soap_blank((soap_wchar)s[n]))
13169 n++;
13170 /* normal prefix: pass string as is */
13171 if (*s != '"')
13173 #ifndef WITH_LEAN
13174 if ((soap->mode & SOAP_XML_CANONICAL))
13175 soap_utilize_ns(soap, s);
13176 if ((soap->mode & SOAP_XML_DEFAULTNS))
13177 { const char *r = strchr(s, ':');
13178 if (r && soap->nlist && !strncmp(soap->nlist->id, s, r-s) && !soap->nlist->id[r-s])
13179 { n -= r-s + 1;
13180 s = r + 1;
13183 #endif
13184 soap_append_lab(soap, s, n);
13186 else /* URL-based string prefix */
13187 { const char *q;
13188 s++;
13189 q = strchr(s, '"');
13190 if (q)
13191 { struct Namespace *p = soap->local_namespaces;
13192 if (p)
13193 { for (; p->id; p++)
13194 { if (p->ns)
13195 if (!soap_tag_cmp(s, p->ns))
13196 break;
13197 if (p->in)
13198 if (!soap_tag_cmp(s, p->in))
13199 break;
13202 /* URL is in the namespace table? */
13203 if (p && p->id)
13204 { const char *r = p->id;
13205 #ifndef WITH_LEAN
13206 if ((soap->mode & SOAP_XML_DEFAULTNS) && soap->nlist && !strcmp(soap->nlist->id, r))
13207 q++;
13208 else
13209 #endif
13210 soap_append_lab(soap, r, strlen(r));
13212 else /* not in namespace table: create xmlns binding */
13213 { char *r = soap_strdup(soap, s);
13214 r[q-s] = '\0';
13215 #ifdef HAVE_SNPRINTF
13216 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:_%d", soap->idnum++);
13217 #else
13218 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
13219 #endif
13220 soap_set_attr(soap, soap->tmpbuf, r, 1);
13221 soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6));
13223 soap_append_lab(soap, q + 1, n - (q-s) - 1);
13226 /* advance to next and add spacing */
13227 s += n;
13228 if (*s)
13229 soap_append_lab(soap, " ", 1);
13231 soap_append_lab(soap, SOAP_STR_EOS, 1);
13232 t = soap_strdup(soap, soap->labbuf);
13234 return t;
13236 #endif
13238 /******************************************************************************/
13239 #ifndef WITH_LEAN
13240 SOAP_FMAC1
13242 SOAP_FMAC2
13243 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t, long minlen, long maxlen)
13244 { if (s)
13245 { long l;
13246 wchar_t *r;
13247 *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
13248 if (!r)
13249 return soap->error = SOAP_EOM;
13250 if (soap->mode & SOAP_ENC_LATIN)
13251 { while (*s)
13252 *r++ = (wchar_t)*s++;
13254 else
13255 { /* Convert UTF8 to wchar */
13256 while (*s)
13257 { register soap_wchar c, c1, c2, c3, c4;
13258 c = (unsigned char)*s++;
13259 if (c < 0x80)
13260 *r++ = (wchar_t)c;
13261 else
13262 { c1 = (soap_wchar)*s++ & 0x3F;
13263 if (c < 0xE0)
13264 *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
13265 else
13266 { c2 = (soap_wchar)*s++ & 0x3F;
13267 if (c < 0xF0)
13268 *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
13269 else
13270 { c3 = (soap_wchar)*s++ & 0x3F;
13271 if (c < 0xF8)
13272 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
13273 else
13274 { c4 = (soap_wchar)*s++ & 0x3F;
13275 if (c < 0xFC)
13276 *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
13277 else
13278 *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
13285 *r = L'\0';
13286 l = (long)(r - *t);
13287 if ((maxlen >= 0 && l > maxlen) || l < minlen)
13288 return soap->error = SOAP_LENGTH;
13290 return soap->error;
13292 #endif
13294 /******************************************************************************/
13295 #ifndef WITH_LEAN
13296 SOAP_FMAC1
13297 const char*
13298 SOAP_FMAC2
13299 soap_wchar2s(struct soap *soap, const wchar_t *s)
13300 { register soap_wchar c;
13301 register char *r, *t;
13302 const wchar_t *q = s;
13303 size_t n = 0;
13304 while ((c = *q++))
13305 { if (c > 0 && c < 0x80)
13306 n++;
13307 else
13308 n += 6;
13310 r = t = (char*)soap_malloc(soap, n + 1);
13311 if (r)
13312 { /* Convert wchar to UTF8 */
13313 while ((c = *s++))
13314 { if (c > 0 && c < 0x80)
13315 *t++ = (char)c;
13316 else
13317 { if (c < 0x0800)
13318 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
13319 else
13320 { if (c < 0x010000)
13321 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
13322 else
13323 { if (c < 0x200000)
13324 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
13325 else
13326 { if (c < 0x04000000)
13327 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
13328 else
13329 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
13330 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
13332 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
13334 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
13336 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
13338 *t++ = (char)(0x80 | (c & 0x3F));
13341 *t = '\0';
13343 return r;
13345 #endif
13347 /******************************************************************************/
13348 #ifndef PALM_2
13349 SOAP_FMAC1
13351 SOAP_FMAC2
13352 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
13353 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
13354 if (id < 0)
13355 return soap->error;
13356 if (!**p && (soap->mode & SOAP_C_NILSTRING))
13357 return soap_element_null(soap, tag, id, type);
13358 if (soap_element_begin_out(soap, tag, id, type)
13359 || soap_string_out(soap, *p, 0)
13360 || soap_element_end_out(soap, tag))
13361 return soap->error;
13362 return SOAP_OK;
13364 #endif
13366 /******************************************************************************/
13367 #ifndef PALM_2
13368 SOAP_FMAC1
13369 char **
13370 SOAP_FMAC2
13371 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
13372 { (void)type;
13373 if (soap_element_begin_in(soap, tag, 1, NULL))
13374 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
13375 return NULL;
13376 soap->error = SOAP_OK;
13378 if (!p)
13379 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
13380 return NULL;
13382 if (soap->null)
13383 *p = NULL;
13384 else if (soap->body)
13385 { *p = soap_string_in(soap, flag, minlen, maxlen);
13386 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
13387 return NULL;
13388 if (!**p && tag && *tag == '-')
13389 { soap->error = SOAP_NO_TAG;
13390 return NULL;
13393 else if (tag && *tag == '-')
13394 { soap->error = SOAP_NO_TAG;
13395 return NULL;
13397 else if (!*soap->href && minlen > 0)
13398 { soap->error = SOAP_LENGTH;
13399 return NULL;
13401 else
13402 *p = soap_strdup(soap, SOAP_STR_EOS);
13403 if (*soap->href)
13404 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
13405 if (soap->body && soap_element_end_in(soap, tag))
13406 return NULL;
13407 return p;
13409 #endif
13411 /******************************************************************************/
13412 #ifndef WITH_LEANER
13413 #ifndef PALM_2
13414 SOAP_FMAC1
13416 SOAP_FMAC2
13417 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
13418 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
13419 if (id < 0)
13420 return soap->error;
13421 if (!**p && (soap->mode & SOAP_C_NILSTRING))
13422 return soap_element_null(soap, tag, id, type);
13423 if (soap_element_begin_out(soap, tag, id, type)
13424 || soap_wstring_out(soap, *p, 0)
13425 || soap_element_end_out(soap, tag))
13426 return soap->error;
13427 return SOAP_OK;
13429 #endif
13430 #endif
13432 /******************************************************************************/
13433 #ifndef WITH_LEANER
13434 #ifndef PALM_2
13435 SOAP_FMAC1
13436 wchar_t **
13437 SOAP_FMAC2
13438 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
13439 { (void)type;
13440 if (soap_element_begin_in(soap, tag, 1, NULL))
13441 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
13442 return NULL;
13443 soap->error = SOAP_OK;
13445 if (!p)
13446 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
13447 return NULL;
13449 if (soap->body)
13450 { *p = soap_wstring_in(soap, 1, minlen, maxlen);
13451 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
13452 return NULL;
13453 if (!**p && tag && *tag == '-')
13454 { soap->error = SOAP_NO_TAG;
13455 return NULL;
13458 else if (tag && *tag == '-')
13459 { soap->error = SOAP_NO_TAG;
13460 return NULL;
13462 else if (soap->null)
13463 *p = NULL;
13464 else
13465 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
13466 if (*soap->href)
13467 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
13468 if (soap->body && soap_element_end_in(soap, tag))
13469 return NULL;
13470 return p;
13472 #endif
13473 #endif
13475 /******************************************************************************/
13476 #ifndef WITH_LEAN
13477 SOAP_FMAC1
13478 time_t
13479 SOAP_FMAC2
13480 soap_timegm(struct tm *T)
13482 #if defined(HAVE_TIMEGM)
13483 return timegm(T);
13484 #else
13485 time_t t, g, z;
13486 struct tm tm;
13487 t = mktime(T);
13488 if (t == (time_t)-1)
13489 return (time_t)-1;
13490 #ifdef HAVE_GMTIME_R
13491 gmtime_r(&t, &tm);
13492 #else
13493 tm = *gmtime(&t);
13494 #endif
13495 tm.tm_isdst = 0;
13496 g = mktime(&tm);
13497 if (g == (time_t)-1)
13498 return (time_t)-1;
13499 z = g - t;
13500 return t - z;
13501 #endif
13503 #endif
13505 /******************************************************************************/
13506 #ifndef WITH_LEAN
13507 SOAP_FMAC1
13508 const char*
13509 SOAP_FMAC2
13510 soap_dateTime2s(struct soap *soap, time_t n)
13511 { struct tm T, *pT = &T;
13512 #if defined(HAVE_GMTIME_R)
13513 if (gmtime_r(&n, pT))
13514 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
13515 #elif defined(HAVE_GMTIME)
13516 if ((pT = gmtime(&n)))
13517 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
13518 #elif defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)
13519 #if defined(HAVE_LOCALTIME_R)
13520 if (localtime_r(&n, pT))
13521 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
13522 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
13523 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
13525 #else
13526 if ((pT = localtime(&n)))
13527 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
13528 memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
13529 soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
13531 #endif
13532 #elif defined(HAVE_GETTIMEOFDAY)
13533 struct timezone tz;
13534 memset((void*)&tz, 0, sizeof(tz));
13535 #if defined(HAVE_LOCALTIME_R)
13536 if (localtime_r(&n, pT))
13537 { struct timeval tv;
13538 gettimeofday(&tv, &tz);
13539 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
13540 #ifdef HAVE_SNPRINTF
13541 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
13542 #else
13543 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
13544 #endif
13546 #else
13547 if ((pT = localtime(&n)))
13548 { struct timeval tv;
13549 gettimeofday(&tv, &tz);
13550 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
13551 #ifdef HAVE_SNPRINTF
13552 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
13553 #else
13554 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
13555 #endif
13557 #endif
13558 #elif defined(HAVE_FTIME)
13559 struct timeb t;
13560 memset((void*)&t, 0, sizeof(t));
13561 #if defined(HAVE_LOCALTIME_R)
13562 if (localtime_r(&n, pT))
13564 #ifdef __BORLANDC__
13565 ::ftime(&t);
13566 #else
13567 ftime(&t);
13568 #endif
13569 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
13570 #ifdef HAVE_SNPRINTF
13571 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
13572 #else
13573 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
13574 #endif
13576 #else
13577 if ((pT = localtime(&n)))
13579 #ifdef __BORLANDC__
13580 ::ftime(&t);
13581 #else
13582 ftime(&t);
13583 #endif
13584 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
13585 #ifdef HAVE_SNPRINTF
13586 soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
13587 #else
13588 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
13589 #endif
13591 #endif
13592 #elif defined(HAVE_LOCALTIME_R)
13593 if (localtime_r(&n, pT))
13594 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
13595 #else
13596 if ((pT = localtime(&n)))
13597 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
13598 #endif
13599 else
13600 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
13601 return soap->tmpbuf;
13603 #endif
13605 /******************************************************************************/
13606 #ifndef WITH_LEAN
13607 SOAP_FMAC1
13609 SOAP_FMAC2
13610 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
13611 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
13612 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
13613 return soap->error;
13614 return soap_element_end_out(soap, tag);
13616 #endif
13618 /******************************************************************************/
13619 #ifndef WITH_LEAN
13620 SOAP_FMAC1
13622 SOAP_FMAC2
13623 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
13624 { if (s)
13625 { char zone[32];
13626 struct tm T;
13627 const char *t;
13628 *zone = '\0';
13629 memset((void*)&T, 0, sizeof(T));
13630 if (strchr(s, '-'))
13631 t = "%d-%d-%dT%d:%d:%d%31s";
13632 else if (strchr(s, ':'))
13633 t = "%4d%2d%2dT%d:%d:%d%31s";
13634 else /* parse non-XSD-standard alternative ISO 8601 format */
13635 t = "%4d%2d%2dT%2d%2d%2d%31s";
13636 if (sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone) < 6)
13637 return soap->error = SOAP_TYPE;
13638 if (T.tm_year == 1)
13639 T.tm_year = 70;
13640 else
13641 T.tm_year -= 1900;
13642 T.tm_mon--;
13643 if (*zone == '.')
13644 { for (s = zone + 1; *s; s++)
13645 if (*s < '0' || *s > '9')
13646 break;
13648 else
13649 s = zone;
13650 if (*s)
13652 #ifndef WITH_NOZONE
13653 if (*s == '+' || *s == '-')
13654 { int h = 0, m = 0;
13655 if (s[3] == ':')
13656 { /* +hh:mm */
13657 sscanf(s, "%d:%d", &h, &m);
13658 if (h < 0)
13659 m = -m;
13661 else /* +hhmm */
13662 { m = (int)soap_strtol(s, NULL, 10);
13663 h = m / 100;
13664 m = m % 100;
13666 T.tm_min -= m;
13667 T.tm_hour -= h;
13668 /* put hour and min in range */
13669 T.tm_hour += T.tm_min / 60;
13670 T.tm_min %= 60;
13671 if (T.tm_min < 0)
13672 { T.tm_min += 60;
13673 T.tm_hour--;
13675 T.tm_mday += T.tm_hour / 24;
13676 T.tm_hour %= 24;
13677 if (T.tm_hour < 0)
13678 { T.tm_hour += 24;
13679 T.tm_mday--;
13681 /* note: day of the month may be out of range, timegm() handles it */
13683 #endif
13684 *p = soap_timegm(&T);
13686 else /* no UTC or timezone, so assume we got a localtime */
13687 { T.tm_isdst = -1;
13688 *p = mktime(&T);
13691 return soap->error;
13693 #endif
13695 /******************************************************************************/
13696 #ifndef WITH_LEAN
13697 SOAP_FMAC1
13698 time_t *
13699 SOAP_FMAC2
13700 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
13701 { if (soap_element_begin_in(soap, tag, 0, NULL))
13702 return NULL;
13703 if (*soap->type
13704 && soap_match_tag(soap, soap->type, type)
13705 && soap_match_tag(soap, soap->type, ":dateTime"))
13706 { soap->error = SOAP_TYPE;
13707 soap_revert(soap);
13708 return NULL;
13710 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
13711 if (*soap->href)
13712 p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
13713 else if (p)
13714 { if (soap_s2dateTime(soap, soap_value(soap), p))
13715 return NULL;
13717 if (soap->body && soap_element_end_in(soap, tag))
13718 return NULL;
13719 return p;
13721 #endif
13723 /******************************************************************************/
13724 #ifndef PALM_2
13725 SOAP_FMAC1
13727 SOAP_FMAC2
13728 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
13729 { int i;
13730 const char *t = NULL;
13731 if (tag && *tag != '-')
13732 { if (soap->local_namespaces && (t = strchr(tag, ':')))
13733 { size_t n = t - tag;
13734 if (n >= sizeof(soap->tmpbuf))
13735 n = sizeof(soap->tmpbuf) - 1;
13736 strncpy(soap->tmpbuf, tag, n);
13737 soap->tmpbuf[n] = '\0';
13738 for (i = 0; soap->local_namespaces[i].id; i++)
13739 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
13740 break;
13741 t++;
13742 if (soap_element(soap, t, 0, type)
13743 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
13744 || soap_element_start_end_out(soap, NULL))
13745 return soap->error;
13747 else
13748 { t = tag;
13749 if (soap_element_begin_out(soap, t, 0, type))
13750 return soap->error;
13753 if (p && *p)
13754 { if (soap_send(soap, *p)) /* send as-is */
13755 return soap->error;
13757 if (t)
13758 return soap_element_end_out(soap, t);
13759 return SOAP_OK;
13761 #endif
13763 /******************************************************************************/
13764 #ifndef PALM_2
13765 SOAP_FMAC1
13766 char **
13767 SOAP_FMAC2
13768 soap_inliteral(struct soap *soap, const char *tag, char **p)
13769 { if (soap_element_begin_in(soap, tag, 1, NULL))
13770 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
13771 return NULL;
13772 soap->error = SOAP_OK;
13774 if (!p)
13775 { if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
13776 return NULL;
13778 if (soap->body || (tag && *tag == '-'))
13779 { *p = soap_string_in(soap, 0, -1, -1);
13780 if (!*p)
13781 return NULL;
13782 if (!**p && tag && *tag == '-')
13783 { soap->error = SOAP_NO_TAG;
13784 return NULL;
13787 else if (soap->null)
13788 *p = NULL;
13789 else
13790 *p = soap_strdup(soap, SOAP_STR_EOS);
13791 if (soap->body && soap_element_end_in(soap, tag))
13792 return NULL;
13793 return p;
13795 #endif
13797 /******************************************************************************/
13798 #ifndef WITH_LEANER
13799 #ifndef PALM_2
13800 SOAP_FMAC1
13802 SOAP_FMAC2
13803 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
13804 { int i;
13805 const char *t = NULL;
13806 if (tag && *tag != '-')
13807 { if (soap->local_namespaces && (t = strchr(tag, ':')))
13808 { size_t n = t - tag;
13809 if (n >= sizeof(soap->tmpbuf))
13810 n = sizeof(soap->tmpbuf) - 1;
13811 strncpy(soap->tmpbuf, tag, n);
13812 soap->tmpbuf[n] = '\0';
13813 for (i = 0; soap->local_namespaces[i].id; i++)
13814 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
13815 break;
13816 t++;
13817 if (soap_element(soap, t, 0, type)
13818 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
13819 || soap_element_start_end_out(soap, NULL))
13820 return soap->error;
13822 else
13823 { t = tag;
13824 if (soap_element_begin_out(soap, t, 0, type))
13825 return soap->error;
13828 if (p)
13829 { wchar_t c;
13830 const wchar_t *s = *p;
13831 while ((c = *s++))
13832 { if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */
13833 return soap->error;
13836 if (t)
13837 return soap_element_end_out(soap, t);
13838 return SOAP_OK;
13840 #endif
13841 #endif
13843 /******************************************************************************/
13844 #ifndef WITH_LEANER
13845 #ifndef PALM_2
13846 SOAP_FMAC1
13847 wchar_t **
13848 SOAP_FMAC2
13849 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
13850 { if (soap_element_begin_in(soap, tag, 1, NULL))
13851 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
13852 return NULL;
13853 soap->error = SOAP_OK;
13855 if (!p)
13856 { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
13857 return NULL;
13859 if (soap->body)
13860 { *p = soap_wstring_in(soap, 0, -1, -1);
13861 if (!*p)
13862 return NULL;
13863 if (!**p && tag && *tag == '-')
13864 { soap->error = SOAP_NO_TAG;
13865 return NULL;
13868 else if (tag && *tag == '-')
13869 { soap->error = SOAP_NO_TAG;
13870 return NULL;
13872 else if (soap->null)
13873 *p = NULL;
13874 else
13875 *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS);
13876 if (soap->body && soap_element_end_in(soap, tag))
13877 return NULL;
13878 return p;
13880 #endif
13881 #endif
13883 /******************************************************************************/
13884 #ifndef PALM_2
13885 SOAP_FMAC1
13886 const char *
13887 SOAP_FMAC2
13888 soap_value(struct soap *soap)
13889 { register size_t i;
13890 register soap_wchar c = 0;
13891 register char *s = soap->tmpbuf;
13892 if (!soap->body)
13893 return SOAP_STR_EOS;
13894 do c = soap_get(soap);
13895 while (soap_blank(c));
13896 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
13897 { if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
13898 break;
13899 *s++ = (char)c;
13900 c = soap_get(soap);
13902 for (s--; i > 0; i--, s--)
13903 { if (!soap_blank((soap_wchar)*s))
13904 break;
13906 s[1] = '\0';
13907 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */
13908 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
13909 if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
13910 soap_unget(soap, c);
13911 else if (soap->mode & SOAP_XML_STRICT)
13912 { soap->error = SOAP_LENGTH;
13913 return NULL;
13915 #ifdef WITH_DOM
13916 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
13917 soap->dom->data = soap_strdup(soap, soap->tmpbuf);
13918 #endif
13919 return soap->tmpbuf; /* return non-null pointer */
13921 #endif
13923 /******************************************************************************/
13924 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
13925 #ifndef PALM_2
13926 SOAP_FMAC1
13928 SOAP_FMAC2
13929 soap_getline(struct soap *soap, char *s, int len)
13930 { int i = len;
13931 soap_wchar c = 0;
13932 for (;;)
13933 { while (--i > 0)
13934 { c = soap_getchar(soap);
13935 if (c == '\r' || c == '\n')
13936 break;
13937 if ((int)c == EOF)
13938 return soap->error = SOAP_CHK_EOF;
13939 *s++ = (char)c;
13941 *s = '\0';
13942 if (c != '\n')
13943 c = soap_getchar(soap); /* got \r or something else, now get \n */
13944 if (c == '\n')
13945 { if (i + 1 == len) /* empty line: end of HTTP/MIME header */
13946 break;
13947 c = soap_get0(soap);
13948 if (c != ' ' && c != '\t') /* HTTP line continuation? */
13949 break;
13951 else if ((int)c == EOF)
13952 return soap->error = SOAP_CHK_EOF;
13953 if (i <= 0)
13954 return soap->error = SOAP_HDR;
13956 return SOAP_OK;
13958 #endif
13959 #endif
13961 /******************************************************************************/
13962 #ifndef PALM_1
13963 static size_t
13964 soap_count_attachments(struct soap *soap)
13966 #ifndef WITH_LEANER
13967 register struct soap_multipart *content;
13968 register size_t count = soap->count;
13969 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
13970 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
13971 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
13972 for (content = soap->dime.first; content; content = content->next)
13973 { count += 12 + ((content->size+3)&(~3));
13974 if (content->id)
13975 count += ((strlen(content->id)+3)&(~3));
13976 if (content->type)
13977 count += ((strlen(content->type)+3)&(~3));
13978 if (content->options)
13979 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
13980 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
13983 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
13984 { register size_t n = strlen(soap->mime.boundary);
13985 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
13986 for (content = soap->mime.first; content; content = content->next)
13987 { register const char *s;
13988 /* count \r\n--boundary\r\n */
13989 count += 6 + n;
13990 /* count Content-Type: ...\r\n */
13991 if (content->type)
13992 count += 16 + strlen(content->type);
13993 /* count Content-Transfer-Encoding: ...\r\n */
13994 s = soap_code_str(mime_codes, content->encoding);
13995 if (s)
13996 count += 29 + strlen(s);
13997 /* count Content-ID: ...\r\n */
13998 if (content->id)
13999 count += 14 + strlen(content->id);
14000 /* count Content-Location: ...\r\n */
14001 if (content->location)
14002 count += 20 + strlen(content->location);
14003 /* count Content-Description: ...\r\n */
14004 if (content->description)
14005 count += 23 + strlen(content->description);
14006 /* count \r\n...content */
14007 count += 2 + content->size;
14008 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
14010 /* count \r\n--boundary-- */
14011 count += 6 + n;
14013 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=%lu\n", (unsigned long)count));
14014 return count;
14015 #else
14016 return soap->count;
14017 #endif
14019 #endif
14021 /******************************************************************************/
14022 #ifndef WITH_LEANER
14023 #ifndef PALM_1
14024 static int
14025 soap_putdimefield(struct soap *soap, const char *s, size_t n)
14026 { if (soap_send_raw(soap, s, n))
14027 return soap->error;
14028 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
14030 #endif
14031 #endif
14033 /******************************************************************************/
14034 #ifndef WITH_LEANER
14035 #ifndef PALM_1
14036 SOAP_FMAC1
14037 char *
14038 SOAP_FMAC2
14039 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
14040 { size_t n;
14041 char *s = NULL;
14042 if (option)
14043 { n = strlen(option);
14044 s = (char*)soap_malloc(soap, n + 5);
14045 if (s)
14046 { s[0] = (char)(optype >> 8);
14047 s[1] = (char)(optype & 0xFF);
14048 s[2] = (char)(n >> 8);
14049 s[3] = (char)(n & 0xFF);
14050 strcpy(s + 4, option);
14053 return s;
14055 #endif
14056 #endif
14058 /******************************************************************************/
14059 #ifndef WITH_LEANER
14060 #ifndef PALM_1
14061 SOAP_FMAC1
14063 SOAP_FMAC2
14064 soap_putdimehdr(struct soap *soap)
14065 { unsigned char tmp[12];
14066 size_t optlen = 0, idlen = 0, typelen = 0;
14067 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS));
14068 if (soap->dime.options)
14069 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
14070 if (soap->dime.id)
14071 { idlen = strlen(soap->dime.id);
14072 if (idlen > 0x0000FFFF)
14073 idlen = 0x0000FFFF;
14075 if (soap->dime.type)
14076 { typelen = strlen(soap->dime.type);
14077 if (typelen > 0x0000FFFF)
14078 typelen = 0x0000FFFF;
14080 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
14081 tmp[1] = soap->dime.flags & 0xF0;
14082 tmp[2] = (char)(optlen >> 8);
14083 tmp[3] = (char)(optlen & 0xFF);
14084 tmp[4] = (char)(idlen >> 8);
14085 tmp[5] = (char)(idlen & 0xFF);
14086 tmp[6] = (char)(typelen >> 8);
14087 tmp[7] = (char)(typelen & 0xFF);
14088 tmp[8] = (char)(soap->dime.size >> 24);
14089 tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
14090 tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
14091 tmp[11] = (char)(soap->dime.size & 0xFF);
14092 if (soap_send_raw(soap, (char*)tmp, 12)
14093 || soap_putdimefield(soap, soap->dime.options, optlen)
14094 || soap_putdimefield(soap, soap->dime.id, idlen)
14095 || soap_putdimefield(soap, soap->dime.type, typelen))
14096 return soap->error;
14097 return SOAP_OK;
14099 #endif
14100 #endif
14102 /******************************************************************************/
14103 #ifndef WITH_LEANER
14104 #ifndef PALM_1
14105 SOAP_FMAC1
14107 SOAP_FMAC2
14108 soap_putdime(struct soap *soap)
14109 { struct soap_multipart *content;
14110 if (!(soap->mode & SOAP_ENC_DIME))
14111 return SOAP_OK;
14112 for (content = soap->dime.first; content; content = content->next)
14113 { void *handle;
14114 soap->dime.size = content->size;
14115 soap->dime.id = content->id;
14116 soap->dime.type = content->type;
14117 soap->dime.options = content->options;
14118 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
14119 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
14120 { size_t size = content->size;
14121 if (!handle)
14122 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
14123 return soap->error;
14125 if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
14126 { size_t chunksize = sizeof(soap->tmpbuf);
14127 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
14129 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
14130 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
14131 if (size < chunksize)
14132 { soap->dime.flags &= ~SOAP_DIME_CF;
14133 if (!content->next)
14134 soap->dime.flags |= SOAP_DIME_ME;
14136 else
14137 soap->dime.flags |= SOAP_DIME_CF;
14138 soap->dime.size = size;
14139 if (soap_putdimehdr(soap)
14140 || soap_putdimefield(soap, soap->tmpbuf, size))
14141 break;
14142 if (soap->dime.id)
14143 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
14144 soap->dime.id = NULL;
14145 soap->dime.type = NULL;
14146 soap->dime.options = NULL;
14148 } while (size >= chunksize);
14150 else
14151 { if (!content->next)
14152 soap->dime.flags |= SOAP_DIME_ME;
14153 if (soap_putdimehdr(soap))
14154 return soap->error;
14156 { size_t bufsize;
14157 if (size < sizeof(soap->tmpbuf))
14158 bufsize = size;
14159 else
14160 bufsize = sizeof(soap->tmpbuf);
14161 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
14162 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
14163 soap->error = SOAP_CHK_EOF;
14164 break;
14166 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
14167 break;
14168 size -= bufsize;
14169 } while (size);
14170 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
14171 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
14173 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
14174 if (soap->fdimereadclose)
14175 soap->fdimereadclose(soap, handle);
14177 else
14178 { if (!content->next)
14179 soap->dime.flags |= SOAP_DIME_ME;
14180 if (soap_putdimehdr(soap)
14181 || soap_putdimefield(soap, (char*)content->ptr, content->size))
14182 return soap->error;
14185 return SOAP_OK;
14187 #endif
14188 #endif
14190 /******************************************************************************/
14191 #ifndef WITH_LEANER
14192 #ifndef PALM_1
14193 static char *
14194 soap_getdimefield(struct soap *soap, size_t n)
14195 { register soap_wchar c;
14196 register size_t i;
14197 register char *s;
14198 register char *p = NULL;
14199 if (n)
14200 { p = (char*)soap_malloc(soap, n + 1);
14201 if (p)
14202 { s = p;
14203 for (i = n; i > 0; i--)
14204 { if ((int)(c = soap_get1(soap)) == EOF)
14205 { soap->error = SOAP_CHK_EOF;
14206 return NULL;
14208 *s++ = (char)c;
14210 *s = '\0';
14211 if ((soap->error = soap_move(soap, (size_t)(-(long)n&3))))
14212 return NULL;
14214 else
14215 soap->error = SOAP_EOM;
14217 return p;
14219 #endif
14220 #endif
14222 /******************************************************************************/
14223 #ifndef WITH_LEANER
14224 #ifndef PALM_1
14225 SOAP_FMAC1
14227 SOAP_FMAC2
14228 soap_getdimehdr(struct soap *soap)
14229 { register soap_wchar c;
14230 register char *s;
14231 register int i;
14232 unsigned char tmp[12];
14233 size_t optlen, idlen, typelen;
14234 if (!(soap->mode & SOAP_ENC_DIME))
14235 return soap->error = SOAP_DIME_END;
14236 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
14237 if (soap->dime.buflen || soap->dime.chunksize)
14238 { if (soap_move(soap, soap->dime.size - soap_tell(soap)))
14239 return soap->error = SOAP_CHK_EOF;
14240 soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
14241 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
14242 return SOAP_OK;
14244 s = (char*)tmp;
14245 for (i = 12; i > 0; i--)
14246 { if ((int)(c = soap_getchar(soap)) == EOF)
14247 return soap->error = SOAP_CHK_EOF;
14248 *s++ = (char)c;
14250 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
14251 return soap->error = SOAP_DIME_MISMATCH;
14252 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
14253 optlen = (tmp[2] << 8) | tmp[3];
14254 idlen = (tmp[4] << 8) | tmp[5];
14255 typelen = (tmp[6] << 8) | tmp[7];
14256 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
14257 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
14258 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
14259 return soap->error;
14260 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
14261 return soap->error;
14262 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
14263 return soap->error;
14264 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id='%s', type='%s', options='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "", soap->dime.options ? soap->dime.options+4 : SOAP_STR_EOS));
14265 if (soap->dime.flags & SOAP_DIME_ME)
14266 soap->mode &= ~SOAP_ENC_DIME;
14267 return SOAP_OK;
14269 #endif
14270 #endif
14272 /******************************************************************************/
14273 #ifndef WITH_LEANER
14274 #ifndef PALM_1
14275 SOAP_FMAC1
14277 SOAP_FMAC2
14278 soap_getdime(struct soap *soap)
14279 { while (soap->dime.flags & SOAP_DIME_CF)
14280 { if (soap_getdimehdr(soap))
14281 return soap->error;
14282 if (soap_move(soap, soap->dime.size))
14283 return soap->error = SOAP_EOF;
14285 if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap))))
14286 return soap->error = SOAP_EOF;
14287 for (;;)
14288 { register struct soap_multipart *content;
14289 if (soap_getdimehdr(soap))
14290 break;
14291 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
14292 { const char *id, *type, *options;
14293 size_t size, n;
14294 if (!soap->dime.ptr)
14295 return soap->error;
14296 id = soap->dime.id;
14297 type = soap->dime.type;
14298 options = soap->dime.options;
14299 for (;;)
14300 { size = soap->dime.size;
14301 for (;;)
14302 { n = soap->buflen - soap->bufidx;
14303 if (size < n)
14304 n = size;
14305 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
14306 break;
14307 size -= n;
14308 if (!size)
14309 { soap->bufidx += n;
14310 break;
14312 if (soap_recv(soap))
14313 { soap->error = SOAP_EOF;
14314 goto end;
14317 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
14318 { soap->error = SOAP_EOF;
14319 break;
14321 if (!(soap->dime.flags & SOAP_DIME_CF))
14322 break;
14323 if (soap_getdimehdr(soap))
14324 break;
14326 end:
14327 if (soap->fdimewriteclose)
14328 soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
14329 soap->dime.size = 0;
14330 soap->dime.id = id;
14331 soap->dime.type = type;
14332 soap->dime.options = options;
14334 else if (soap->dime.flags & SOAP_DIME_CF)
14335 { const char *id, *type, *options;
14336 id = soap->dime.id;
14337 type = soap->dime.type;
14338 options = soap->dime.options;
14339 if (soap_new_block(soap) == NULL)
14340 return SOAP_EOM;
14341 for (;;)
14342 { register soap_wchar c;
14343 register size_t i;
14344 register char *s;
14345 if (soap->dime.size > SOAP_MAXDIMESIZE)
14346 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE));
14347 return soap->error = SOAP_DIME_ERROR;
14349 s = (char*)soap_push_block(soap, NULL, soap->dime.size);
14350 if (!s)
14351 return soap->error = SOAP_EOM;
14352 for (i = soap->dime.size; i > 0; i--)
14353 { if ((int)(c = soap_get1(soap)) == EOF)
14354 return soap->error = SOAP_EOF;
14355 *s++ = (char)c;
14357 if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
14358 return soap->error = SOAP_EOF;
14359 if (!(soap->dime.flags & SOAP_DIME_CF))
14360 break;
14361 if (soap_getdimehdr(soap))
14362 return soap->error;
14364 soap->dime.size = soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */
14365 if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0)))
14366 return soap->error;
14367 soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated */
14368 soap->dime.id = id;
14369 soap->dime.type = type;
14370 soap->dime.options = options;
14372 else
14373 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
14374 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
14375 if (!content)
14376 return soap->error = SOAP_EOM;
14377 content->id = soap->dime.id;
14378 content->type = soap->dime.type;
14379 content->options = soap->dime.options;
14380 if (soap->error)
14381 return soap->error;
14382 soap_resolve_attachment(soap, content);
14384 if (soap->error != SOAP_DIME_END)
14385 return soap->error;
14386 return soap->error = SOAP_OK;
14388 #endif
14389 #endif
14391 /******************************************************************************/
14392 #ifndef WITH_LEANER
14393 #ifndef PALM_1
14394 SOAP_FMAC1
14396 SOAP_FMAC2
14397 soap_getmimehdr(struct soap *soap)
14398 { struct soap_multipart *content;
14400 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
14401 return soap->error;
14403 while (!*soap->msgbuf);
14404 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
14405 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
14406 /* remove white space */
14407 while (soap_blank((soap_wchar)*s))
14408 s--;
14409 s[1] = '\0';
14410 if (soap->mime.boundary)
14411 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
14412 return soap->error = SOAP_MIME_ERROR;
14414 else
14415 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
14416 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
14417 return soap->error;
14419 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
14420 return soap->error = SOAP_EOM;
14421 content = soap->mime.last;
14422 for (;;)
14423 { register char *key = soap->msgbuf;
14424 register char *val;
14425 if (!*key)
14426 break;
14427 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
14428 val = strchr(soap->msgbuf, ':');
14429 if (val)
14430 { *val = '\0';
14431 do val++;
14432 while (*val && *val <= 32);
14433 if (!soap_tag_cmp(key, "Content-ID"))
14434 content->id = soap_strdup(soap, val);
14435 else if (!soap_tag_cmp(key, "Content-Location"))
14436 content->location = soap_strdup(soap, val);
14437 else if (!soap_tag_cmp(key, "Content-Disposition"))
14438 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
14439 else if (!soap_tag_cmp(key, "Content-Type"))
14440 content->type = soap_strdup(soap, val);
14441 else if (!soap_tag_cmp(key, "Content-Description"))
14442 content->description = soap_strdup(soap, val);
14443 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
14444 content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
14446 if (soap_getline(soap, key, sizeof(soap->msgbuf)))
14447 return soap->error;
14449 return SOAP_OK;
14451 #endif
14452 #endif
14454 /******************************************************************************/
14455 #ifndef WITH_LEANER
14456 #ifndef PALM_1
14457 SOAP_FMAC1
14459 SOAP_FMAC2
14460 soap_getmime(struct soap *soap)
14461 { while (soap_get_mime_attachment(soap, NULL))
14463 return soap->error;
14465 #endif
14466 #endif
14468 /******************************************************************************/
14469 #ifndef WITH_LEANER
14470 #ifndef PALM_1
14471 SOAP_FMAC1
14472 void
14473 SOAP_FMAC2
14474 soap_post_check_mime_attachments(struct soap *soap)
14475 { soap->imode |= SOAP_MIME_POSTCHECK;
14477 #endif
14478 #endif
14480 /******************************************************************************/
14481 #ifndef WITH_LEANER
14482 #ifndef PALM_1
14483 SOAP_FMAC1
14485 SOAP_FMAC2
14486 soap_check_mime_attachments(struct soap *soap)
14487 { if (soap->mode & SOAP_MIME_POSTCHECK)
14488 return soap_get_mime_attachment(soap, NULL) != NULL;
14489 return SOAP_OK;
14491 #endif
14492 #endif
14494 /******************************************************************************/
14495 #ifndef WITH_LEANER
14496 #ifndef PALM_1
14497 SOAP_FMAC1
14498 struct soap_multipart *
14499 SOAP_FMAC2
14500 soap_get_mime_attachment(struct soap *soap, void *handle)
14501 { register soap_wchar c = 0;
14502 register size_t i, m = 0;
14503 register char *s, *t = NULL;
14504 register struct soap_multipart *content;
14505 register short flag = 0;
14506 if (!(soap->mode & SOAP_ENC_MIME))
14507 return NULL;
14508 content = soap->mime.last;
14509 if (!content)
14510 { if (soap_getmimehdr(soap))
14511 return NULL;
14512 content = soap->mime.last;
14514 else if (content != soap->mime.first)
14515 { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
14516 { if (!content->ptr)
14517 return NULL;
14520 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id='%s' type='%s'\n", content->id ? content->id : SOAP_STR_EOS, content->type ? content->type : SOAP_STR_EOS));
14521 if (!content->ptr && soap_new_block(soap) == NULL)
14522 { soap->error = SOAP_EOM;
14523 return NULL;
14525 for (;;)
14526 { if (content->ptr)
14527 s = soap->tmpbuf;
14528 else if (!(s = (char*)soap_push_block(soap, NULL, sizeof(soap->tmpbuf))))
14529 { soap->error = SOAP_EOM;
14530 return NULL;
14532 for (i = 0; i < sizeof(soap->tmpbuf); i++)
14533 { if (m > 0)
14534 { *s++ = *t++;
14535 m--;
14537 else
14538 { if (!flag)
14539 { c = soap_get1(soap);
14540 if ((int)c == EOF)
14541 { if (content->ptr && soap->fmimewriteclose)
14542 soap->fmimewriteclose(soap, (void*)content->ptr);
14543 soap->error = SOAP_CHK_EOF;
14544 return NULL;
14547 if (flag || c == '\r')
14548 { t = soap->msgbuf;
14549 memset(t, 0, sizeof(soap->msgbuf));
14550 strcpy(t, "\n--");
14551 if (soap->mime.boundary)
14552 strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
14553 do c = soap_getchar(soap);
14554 while (c == *t++);
14555 if ((int)c == EOF)
14556 { if (content->ptr && soap->fmimewriteclose)
14557 soap->fmimewriteclose(soap, (void*)content->ptr);
14558 soap->error = SOAP_CHK_EOF;
14559 return NULL;
14561 if (!*--t)
14562 goto end;
14563 *t = (char)c;
14564 flag = (c == '\r');
14565 m = t - soap->msgbuf + 1 - flag;
14566 t = soap->msgbuf;
14567 c = '\r';
14569 *s++ = (char)c;
14572 if (content->ptr && soap->fmimewrite)
14573 { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
14574 break;
14577 end:
14578 *s = '\0'; /* make 0-terminated */
14579 if (content->ptr)
14580 { if (!soap->error && soap->fmimewrite)
14581 soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
14582 if (soap->fmimewriteclose)
14583 soap->fmimewriteclose(soap, (void*)content->ptr);
14584 if (soap->error)
14585 return NULL;
14587 else
14588 { content->size = soap_size_block(soap, NULL, i+1) - 1; /* last block with '\0' */
14589 content->ptr = soap_save_block(soap, NULL, NULL, 0);
14591 soap_resolve_attachment(soap, content);
14592 if (c == '-' && soap_getchar(soap) == '-')
14593 { soap->mode &= ~SOAP_ENC_MIME;
14594 if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
14595 { if (soap->keep_alive < 0)
14596 soap->keep_alive = 0;
14597 soap_closesock(soap);
14598 return NULL;
14601 else
14602 { while (c != '\r' && (int)c != EOF && soap_blank(c))
14603 c = soap_getchar(soap);
14604 if (c != '\r' || soap_getchar(soap) != '\n')
14605 { soap->error = SOAP_MIME_ERROR;
14606 return NULL;
14608 if (soap_getmimehdr(soap))
14609 return NULL;
14611 return content;
14613 #endif
14614 #endif
14616 /******************************************************************************/
14617 #ifndef WITH_LEANER
14618 #ifndef PALM_1
14619 SOAP_FMAC1
14621 SOAP_FMAC2
14622 soap_match_cid(struct soap *soap, const char *s, const char *t)
14623 { register size_t n;
14624 if (!s)
14625 return 1;
14626 if (!strcmp(s, t))
14627 return 0;
14628 if (!strncmp(s, "cid:", 4))
14629 s += 4;
14630 n = strlen(t);
14631 if (*t == '<')
14632 { t++;
14633 n -= 2;
14635 if (!strncmp(s, t, n) && !s[n])
14636 return 0;
14637 soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
14638 if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
14639 return 0;
14640 return 1;
14642 #endif
14643 #endif
14645 /******************************************************************************/
14646 #ifndef WITH_LEANER
14647 #ifndef PALM_1
14648 static void
14649 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
14650 { if (content->id)
14651 { register struct soap_xlist **xp = &soap->xlist;
14652 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id));
14653 while (*xp)
14654 { register struct soap_xlist *xq = *xp;
14655 if (!soap_match_cid(soap, xq->id, content->id))
14656 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id));
14657 *xp = xq->next;
14658 *xq->ptr = (unsigned char*)content->ptr;
14659 *xq->size = (int)content->size;
14660 *xq->type = (char*)content->type;
14661 if (content->options)
14662 *xq->options = (char*)content->options;
14663 else
14664 *xq->options = (char*)content->description;
14665 SOAP_FREE(soap, xq);
14667 else
14668 xp = &(*xp)->next;
14672 #endif
14673 #endif
14675 /******************************************************************************/
14676 #ifndef WITH_LEANER
14677 #ifndef PALM_1
14678 SOAP_FMAC1
14680 SOAP_FMAC2
14681 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
14682 { const char *s;
14683 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS));
14684 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
14685 return soap->error;
14686 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
14687 return soap->error;
14688 s = soap_code_str(mime_codes, content->encoding);
14689 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
14690 return soap->error;
14691 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
14692 return soap->error;
14693 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
14694 return soap->error;
14695 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
14696 return soap->error;
14697 return soap_send_raw(soap, "\r\n", 2);
14699 #endif
14700 #endif
14702 /******************************************************************************/
14703 #ifndef WITH_LEANER
14704 #ifndef PALM_1
14705 SOAP_FMAC1
14707 SOAP_FMAC2
14708 soap_putmime(struct soap *soap)
14709 { struct soap_multipart *content;
14710 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
14711 return SOAP_OK;
14712 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
14713 for (content = soap->mime.first; content; content = content->next)
14714 { void *handle;
14715 if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
14716 { size_t size = content->size;
14717 if (!handle)
14718 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
14719 return soap->error;
14721 if (soap_putmimehdr(soap, content))
14722 return soap->error;
14723 if (!size)
14724 { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
14725 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
14727 { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
14728 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
14729 if (soap_send_raw(soap, soap->tmpbuf, size))
14730 break;
14731 } while (size);
14733 else
14734 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
14737 else
14738 { do
14739 { size_t bufsize;
14740 if (size < sizeof(soap->tmpbuf))
14741 bufsize = size;
14742 else
14743 bufsize = sizeof(soap->tmpbuf);
14744 if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
14745 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
14746 soap->error = SOAP_EOF;
14747 break;
14749 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
14750 break;
14751 size -= bufsize;
14752 } while (size);
14754 if (soap->fmimereadclose)
14755 soap->fmimereadclose(soap, handle);
14757 else
14758 { if (soap_putmimehdr(soap, content)
14759 || soap_send_raw(soap, content->ptr, content->size))
14760 return soap->error;
14763 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
14765 #endif
14766 #endif
14768 /******************************************************************************/
14769 #ifndef WITH_LEANER
14770 #ifndef PALM_1
14771 SOAP_FMAC1
14772 void
14773 SOAP_FMAC2
14774 soap_set_dime(struct soap *soap)
14775 { soap->omode |= SOAP_ENC_DIME;
14776 soap->dime.first = NULL;
14777 soap->dime.last = NULL;
14779 #endif
14780 #endif
14782 /******************************************************************************/
14783 #ifndef WITH_LEANER
14784 #ifndef PALM_1
14785 SOAP_FMAC1
14786 void
14787 SOAP_FMAC2
14788 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
14789 { soap->omode |= SOAP_ENC_MIME;
14790 soap->mime.first = NULL;
14791 soap->mime.last = NULL;
14792 soap->mime.boundary = soap_strdup(soap, boundary);
14793 soap->mime.start = soap_strdup(soap, start);
14795 #endif
14796 #endif
14798 /******************************************************************************/
14799 #ifndef WITH_LEANER
14800 #ifndef PALM_1
14801 SOAP_FMAC1
14802 void
14803 SOAP_FMAC2
14804 soap_clr_dime(struct soap *soap)
14805 { soap->omode &= ~SOAP_ENC_DIME;
14806 soap->dime.first = NULL;
14807 soap->dime.last = NULL;
14809 #endif
14810 #endif
14812 /******************************************************************************/
14813 #ifndef WITH_LEANER
14814 #ifndef PALM_1
14815 SOAP_FMAC1
14816 void
14817 SOAP_FMAC2
14818 soap_clr_mime(struct soap *soap)
14819 { soap->omode &= ~SOAP_ENC_MIME;
14820 soap->mime.first = NULL;
14821 soap->mime.last = NULL;
14822 soap->mime.boundary = NULL;
14823 soap->mime.start = NULL;
14825 #endif
14826 #endif
14828 /******************************************************************************/
14829 #ifndef WITH_LEANER
14830 #ifndef PALM_1
14831 static struct soap_multipart*
14832 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
14833 { struct soap_multipart *content;
14834 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
14835 if (content)
14836 { content->next = NULL;
14837 content->ptr = ptr;
14838 content->size = size;
14839 content->id = NULL;
14840 content->type = NULL;
14841 content->options = NULL;
14842 content->encoding = SOAP_MIME_NONE;
14843 content->location = NULL;
14844 content->description = NULL;
14845 if (!*first)
14846 *first = content;
14847 if (*last)
14848 (*last)->next = content;
14849 *last = content;
14851 return content;
14853 #endif
14854 #endif
14856 /******************************************************************************/
14857 #ifndef WITH_LEANER
14858 #ifndef PALM_1
14859 SOAP_FMAC1
14861 SOAP_FMAC2
14862 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
14863 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
14864 if (!content)
14865 return SOAP_EOM;
14866 content->id = soap_strdup(soap, id);
14867 content->type = soap_strdup(soap, type);
14868 content->options = soap_dime_option(soap, optype, option);
14869 return SOAP_OK;
14871 #endif
14872 #endif
14874 /******************************************************************************/
14875 #ifndef WITH_LEANER
14876 #ifndef PALM_1
14877 SOAP_FMAC1
14879 SOAP_FMAC2
14880 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)
14881 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
14882 if (!content)
14883 return SOAP_EOM;
14884 content->id = soap_strdup(soap, id);
14885 content->type = soap_strdup(soap, type);
14886 content->encoding = encoding;
14887 content->location = soap_strdup(soap, location);
14888 content->description = soap_strdup(soap, description);
14889 return SOAP_OK;
14891 #endif
14892 #endif
14894 /******************************************************************************/
14895 #ifndef WITH_LEANER
14896 #ifndef PALM_1
14897 SOAP_FMAC1
14898 struct soap_multipart*
14899 SOAP_FMAC2
14900 soap_next_multipart(struct soap_multipart *content)
14901 { if (content)
14902 return content->next;
14903 return NULL;
14905 #endif
14906 #endif
14908 /******************************************************************************/
14909 #ifndef WITH_LEANER
14910 #ifndef PALM_1
14911 static void
14912 soap_select_mime_boundary(struct soap *soap)
14913 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
14914 { register char *s = soap->mime.boundary;
14915 register size_t n = 0;
14916 if (s)
14917 n = strlen(s);
14918 if (n < 16)
14919 { n = 64;
14920 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
14921 if (!s)
14922 return;
14924 strcpy(s, "==");
14925 s += 2;
14926 n -= 4;
14927 while (n)
14928 { *s++ = soap_base64o[soap_random & 0x3F];
14929 n--;
14931 strcpy(s, "==");
14933 if (!soap->mime.start)
14934 soap->mime.start = "<SOAP-ENV:Envelope>";
14936 #endif
14937 #endif
14939 /******************************************************************************/
14940 #ifndef WITH_LEANER
14941 #ifndef PALM_1
14942 static int
14943 soap_valid_mime_boundary(struct soap *soap)
14944 { register struct soap_multipart *content;
14945 register size_t k;
14946 if (soap->fmimeread)
14947 return SOAP_OK;
14948 k = strlen(soap->mime.boundary);
14949 for (content = soap->mime.first; content; content = content->next)
14950 { if (content->ptr && content->size >= k)
14951 { register const char *p = (const char*)content->ptr;
14952 register size_t i;
14953 for (i = 0; i < content->size - k; i++, p++)
14954 { if (!strncmp(p, soap->mime.boundary, k))
14955 return SOAP_ERR;
14959 return SOAP_OK;
14961 #endif
14962 #endif
14964 /******************************************************************************/
14965 #ifdef WITH_GZIP
14966 #ifndef PALM_1
14967 static int
14968 soap_getgziphdr(struct soap *soap)
14969 { int i;
14970 soap_wchar c = 0, f = 0;
14971 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
14972 for (i = 0; i < 9; i++)
14973 { if ((int)(c = soap_get1(soap) == EOF))
14974 return soap->error = SOAP_ZLIB_ERROR;
14975 if (i == 1 && c == 8)
14976 soap->z_dict = 0;
14977 if (i == 2)
14978 f = c;
14980 if (f & 0x04) /* FEXTRA */
14981 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
14982 { if ((int)soap_get1(soap) == EOF)
14983 return soap->error = SOAP_ZLIB_ERROR;
14986 if (f & 0x08) /* skip FNAME */
14987 { do
14988 c = soap_get1(soap);
14989 while (c && (int)c != EOF);
14991 if ((int)c != EOF && (f & 0x10)) /* skip FCOMMENT */
14992 { do
14993 c = soap_get1(soap);
14994 while (c && (int)c != EOF);
14996 if ((int)c != EOF && (f & 0x02)) /* skip FHCRC (CRC32 is used) */
14997 { if ((int)(c = soap_get1(soap)) != EOF)
14998 c = soap_get1(soap);
15000 if ((int)c == EOF)
15001 return soap->error = SOAP_ZLIB_ERROR;
15002 return SOAP_OK;
15004 #endif
15005 #endif
15007 /******************************************************************************/
15008 #ifndef PALM_1
15009 SOAP_FMAC1
15011 SOAP_FMAC2
15012 soap_begin_serve(struct soap *soap)
15014 #ifdef WITH_FASTCGI
15015 if (FCGI_Accept() < 0)
15016 { soap->error = SOAP_EOF;
15017 return soap_send_fault(soap);
15019 #endif
15020 soap_begin(soap);
15021 if (soap_begin_recv(soap)
15022 || soap_envelope_begin_in(soap)
15023 || soap_recv_header(soap)
15024 || soap_body_begin_in(soap))
15025 { if (soap->error < SOAP_STOP)
15027 #ifdef WITH_FASTCGI
15028 soap_send_fault(soap);
15029 #else
15030 return soap_send_fault(soap);
15031 #endif
15033 return soap_closesock(soap);
15035 return SOAP_OK;
15037 #endif
15039 /******************************************************************************/
15040 #ifndef PALM_1
15041 SOAP_FMAC1
15043 SOAP_FMAC2
15044 soap_begin_recv(struct soap *soap)
15045 { register soap_wchar c;
15046 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", soap->socket, soap->recvfd));
15047 soap->error = SOAP_OK;
15048 soap->filterstop = SOAP_OK;
15049 soap_free_temp(soap);
15050 soap_set_local_namespaces(soap);
15051 soap->version = 0; /* don't assume we're parsing SOAP content by default */
15052 #ifndef WITH_NOIDREF
15053 soap_free_iht(soap);
15054 #endif
15055 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
15056 soap->omode |= SOAP_IO_CHUNK;
15057 soap->imode &= ~(SOAP_IO | SOAP_ENC_MIME);
15058 soap->mode = soap->imode;
15059 if (!soap->keep_alive)
15060 { soap->buflen = 0;
15061 soap->bufidx = 0;
15063 if (!(soap->mode & SOAP_IO_KEEPALIVE))
15064 soap->keep_alive = 0;
15065 soap->ahead = 0;
15066 soap->peeked = 0;
15067 soap->level = 0;
15068 soap->part = SOAP_BEGIN;
15069 soap->alloced = 0;
15070 soap->body = 1;
15071 soap->count = 0;
15072 soap->length = 0;
15073 soap->cdata = 0;
15074 *soap->endpoint = '\0';
15075 soap->action = NULL;
15076 soap->header = NULL;
15077 soap->fault = NULL;
15078 soap->status = 0;
15079 soap->fform = NULL;
15080 #ifndef WITH_LEANER
15081 soap->dom = NULL;
15082 soap->dime.chunksize = 0;
15083 soap->dime.buflen = 0;
15084 soap->dime.list = NULL;
15085 soap->dime.first = NULL;
15086 soap->dime.last = NULL;
15087 soap->mime.list = NULL;
15088 soap->mime.first = NULL;
15089 soap->mime.last = NULL;
15090 soap->mime.boundary = NULL;
15091 soap->mime.start = NULL;
15092 #endif
15093 #ifdef WIN32
15094 #ifndef UNDER_CE
15095 #ifndef WITH_FASTCGI
15096 if (!soap_valid_socket(soap->socket) && !soap->is) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
15097 #ifdef __BORLANDC__
15098 setmode(soap->recvfd, _O_BINARY);
15099 #else
15100 _setmode(soap->recvfd, _O_BINARY);
15101 #endif
15102 #endif
15103 #endif
15104 #endif
15105 #ifdef WITH_ZLIB
15106 soap->mode &= ~SOAP_ENC_ZLIB;
15107 soap->zlib_in = SOAP_ZLIB_NONE;
15108 soap->zlib_out = SOAP_ZLIB_NONE;
15109 soap->d_stream->next_in = Z_NULL;
15110 soap->d_stream->avail_in = 0;
15111 soap->d_stream->next_out = (Byte*)soap->buf;
15112 soap->d_stream->avail_out = SOAP_BUFLEN;
15113 soap->z_ratio_in = 1.0;
15114 #endif
15115 #ifdef WITH_OPENSSL
15116 if (soap->ssl)
15117 ERR_clear_error();
15118 #endif
15119 #ifndef WITH_LEANER
15120 if (soap->fprepareinitrecv && (soap->error = soap->fprepareinitrecv(soap)))
15121 return soap->error;
15122 #endif
15123 c = soap_getchar(soap);
15124 #ifdef WITH_GZIP
15125 if (c == 0x1F)
15126 { if (soap_getgziphdr(soap))
15127 return soap->error;
15128 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
15129 return soap->error = SOAP_ZLIB_ERROR;
15130 if (soap->z_dict)
15131 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
15132 return soap->error = SOAP_ZLIB_ERROR;
15134 soap->zlib_state = SOAP_ZLIB_INFLATE;
15135 soap->mode |= SOAP_ENC_ZLIB;
15136 soap->zlib_in = SOAP_ZLIB_GZIP;
15137 soap->z_crc = crc32(0L, NULL, 0);
15138 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
15139 if (!soap->z_buf)
15140 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
15141 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
15142 /* should not chunk over plain transport, so why bother to check? */
15143 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
15144 /* soap->z_buflen = soap->bufidx; */
15145 /* else */
15146 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
15147 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
15148 soap->z_buflen = soap->buflen;
15149 soap->buflen = soap->bufidx;
15150 c = ' ';
15152 #endif
15153 while (soap_blank(c))
15154 c = soap_getchar(soap);
15155 #ifndef WITH_LEANER
15156 if (c == '-' && soap_get0(soap) == '-')
15157 soap->mode |= SOAP_ENC_MIME;
15158 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
15159 soap->mode |= SOAP_ENC_DIME;
15160 else
15161 #endif
15162 { /* skip BOM */
15163 if (c == 0xEF && soap_get0(soap) == 0xBB)
15164 { c = soap_get1(soap);
15165 if ((c = soap_get1(soap)) == 0xBF)
15166 { soap->mode &= ~SOAP_ENC_LATIN;
15167 c = soap_getchar(soap);
15169 else
15170 c = (0x0F << 12) | (0xBB << 6) | (c & 0x3F); /* UTF-8 */
15172 else if ((c == 0xFE && soap_get0(soap) == 0xFF) /* UTF-16 BE */
15173 || (c == 0xFF && soap_get0(soap) == 0xFE)) /* UTF-16 LE */
15174 return soap->error = SOAP_UTF_ERROR;
15175 /* skip space */
15176 while (soap_blank(c))
15177 c = soap_getchar(soap);
15179 if ((int)c == EOF)
15180 return soap->error = SOAP_CHK_EOF;
15181 soap_unget(soap, c);
15182 #ifndef WITH_NOHTTP
15183 /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
15184 if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_XML)))
15185 { soap_mode m = soap->imode;
15186 soap->mode &= ~SOAP_IO;
15187 soap->error = soap->fparse(soap);
15188 if (soap->error && soap->error < SOAP_STOP)
15189 { soap->keep_alive = 0; /* force close later */
15190 return soap->error;
15192 if (soap->error == SOAP_STOP)
15193 { if (soap->fform)
15194 { soap->error = soap->fform(soap);
15195 if (soap->error == SOAP_OK)
15196 soap->error = SOAP_STOP; /* prevents further processing */
15198 return soap->error;
15200 soap->mode = soap->imode; /* if imode is changed, effectuate */
15201 soap->imode = m; /* restore imode */
15202 #ifdef WITH_ZLIB
15203 soap->mode &= ~SOAP_ENC_ZLIB;
15204 #endif
15205 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
15206 { soap->chunkbuflen = soap->buflen;
15207 soap->buflen = soap->bufidx;
15208 soap->chunksize = 0;
15210 /* Note: fparse should not use soap_unget to push back last char */
15211 #if 0
15212 if (soap->status > 200 && soap->length == 0 && !(soap->http_content && (!soap->keep_alive || soap->recv_timeout)) && (soap->imode & SOAP_IO) != SOAP_IO_CHUNK)
15213 #endif
15214 if (soap->status && !soap->body)
15215 return soap->error = soap->status;
15216 #ifdef WITH_ZLIB
15217 if (soap->zlib_in != SOAP_ZLIB_NONE)
15219 #ifdef WITH_GZIP
15220 if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
15221 { c = soap_get1(soap);
15222 if (c == (int)EOF)
15223 return soap->error = SOAP_EOF;
15224 if (c == 0x1F)
15225 { if (soap_getgziphdr(soap))
15226 return soap->error;
15227 if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK)
15228 return soap->error = SOAP_ZLIB_ERROR;
15229 soap->z_crc = crc32(0L, NULL, 0);
15230 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
15232 else
15233 { soap_revget1(soap);
15234 if (inflateInit(soap->d_stream) != Z_OK)
15235 return soap->error = SOAP_ZLIB_ERROR;
15236 soap->zlib_in = SOAP_ZLIB_DEFLATE;
15239 else
15240 #endif
15241 if (inflateInit(soap->d_stream) != Z_OK)
15242 return soap->error = SOAP_ZLIB_ERROR;
15243 if (soap->z_dict)
15244 { if (inflateSetDictionary(soap->d_stream, (const Bytef*)soap->z_dict, soap->z_dict_len) != Z_OK)
15245 return soap->error = SOAP_ZLIB_ERROR;
15247 soap->zlib_state = SOAP_ZLIB_INFLATE;
15248 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
15249 soap->mode |= SOAP_ENC_ZLIB;
15250 if (!soap->z_buf)
15251 soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN);
15252 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
15253 soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx);
15254 soap->d_stream->avail_in = (unsigned int)(soap->buflen - soap->bufidx);
15255 soap->z_buflen = soap->buflen;
15256 soap->buflen = soap->bufidx;
15258 #endif
15259 #ifndef WITH_LEANER
15260 if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
15261 { int r;
15262 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n"));
15263 if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx)))
15264 return soap->error = r;
15266 #endif
15267 if (soap_get0(soap) == (int)EOF)
15268 { if (soap->status == 0 || soap->status == 200)
15269 return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */
15270 return soap->error = soap->status;
15272 if (soap->error)
15273 { if (soap->error == SOAP_FORM && soap->fform)
15274 { soap->error = soap->fform(soap);
15275 if (soap->error == SOAP_OK)
15276 soap->error = SOAP_STOP; /* prevents further processing */
15278 return soap->error;
15281 #endif
15282 #ifndef WITH_LEANER
15283 if (soap->mode & SOAP_ENC_MIME)
15284 { do /* skip preamble */
15285 { if ((int)(c = soap_getchar(soap)) == EOF)
15286 return soap->error = SOAP_CHK_EOF;
15287 } while (c != '-' || soap_get0(soap) != '-');
15288 soap_unget(soap, c);
15289 if (soap_getmimehdr(soap))
15290 return soap->error;
15291 if (soap->mime.start)
15292 { do
15293 { if (!soap->mime.last->id)
15294 break;
15295 if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
15296 break;
15297 } while (soap_get_mime_attachment(soap, NULL));
15299 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
15300 soap->mode |= SOAP_ENC_DIME;
15302 if (soap->mode & SOAP_ENC_DIME)
15303 { if (soap_getdimehdr(soap))
15304 return soap->error;
15305 if (soap->dime.flags & SOAP_DIME_CF)
15306 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
15307 soap->dime.chunksize = soap->dime.size;
15308 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
15309 { soap->dime.buflen = soap->buflen;
15310 soap->buflen = soap->bufidx + soap->dime.chunksize;
15312 else
15313 soap->dime.chunksize -= soap->buflen - soap->bufidx;
15315 soap->count = soap->buflen - soap->bufidx;
15317 #endif
15318 return SOAP_OK;
15320 #endif
15322 /******************************************************************************/
15323 #ifndef PALM_2
15324 SOAP_FMAC1
15326 SOAP_FMAC2
15327 soap_envelope_begin_out(struct soap *soap)
15329 #ifndef WITH_LEANER
15330 size_t n = 0;
15331 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 )
15332 { const char *s;
15333 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
15334 s = "application/dime";
15335 else if (soap->version == 2)
15336 { if (soap->mode & SOAP_ENC_MTOM)
15337 s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
15338 else
15339 s = "application/soap+xml; charset=utf-8";
15341 else if (soap->mode & SOAP_ENC_MTOM)
15342 s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
15343 else
15344 s = "text/xml; charset=utf-8";
15345 #ifdef HAVE_SNPRINTF
15346 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
15347 #else
15348 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);
15349 #endif
15350 n = strlen(soap->tmpbuf);
15351 if (soap_send_raw(soap, soap->tmpbuf, n))
15352 return soap->error;
15354 if (soap->mode & SOAP_IO_LENGTH)
15355 soap->dime.size = soap->count; /* DIME in MIME correction */
15356 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
15357 { if (soap_putdimehdr(soap))
15358 return soap->error;
15360 #endif
15361 if (soap->version == 0)
15362 return SOAP_OK;
15363 soap->part = SOAP_IN_ENVELOPE;
15364 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
15366 #endif
15368 /******************************************************************************/
15369 #ifndef PALM_2
15370 SOAP_FMAC1
15372 SOAP_FMAC2
15373 soap_envelope_end_out(struct soap *soap)
15374 { if (soap->version == 0)
15375 return SOAP_OK;
15376 if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
15377 || soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */
15378 return soap->error;
15379 #ifndef WITH_LEANER
15380 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
15381 { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */
15382 #ifdef HAVE_SNPRINTF
15383 soap_snprintf(soap->id, sizeof(soap->id), soap->dime_id_format, 0);
15384 #else
15385 sprintf(soap->id, soap->dime_id_format, 0);
15386 #endif
15387 soap->dime.id = soap->id;
15388 if (soap->local_namespaces)
15389 { if (soap->local_namespaces[0].out)
15390 soap->dime.type = (char*)soap->local_namespaces[0].out;
15391 else
15392 soap->dime.type = (char*)soap->local_namespaces[0].ns;
15394 soap->dime.options = NULL;
15395 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
15396 if (!soap->dime.first)
15397 soap->dime.flags |= SOAP_DIME_ME;
15398 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
15400 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
15401 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
15402 #endif
15403 soap->part = SOAP_END_ENVELOPE;
15404 return SOAP_OK;
15406 #endif
15408 /******************************************************************************/
15409 #ifndef WITH_LEAN
15410 #ifndef PALM_1
15411 SOAP_FMAC1
15412 char*
15413 SOAP_FMAC2
15414 soap_get_http_body(struct soap *soap, size_t *len)
15415 { if (len)
15416 *len = 0;
15417 #ifndef WITH_LEAN
15418 register size_t l = 0, n = 0;
15419 register char *s;
15420 /* get HTTP body length */
15421 if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
15422 { n = soap->length;
15423 if (!n)
15424 return NULL;
15426 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Parsing HTTP body (mode=0x%x,len=%lu)\n", soap->mode, (unsigned long)n));
15427 #ifdef WITH_FAST
15428 soap->labidx = 0; /* use look-aside buffer */
15429 #else
15430 if (soap_new_block(soap) == NULL)
15431 return NULL;
15432 #endif
15433 for (;;)
15435 #ifdef WITH_FAST
15436 register size_t i, k;
15437 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
15438 return NULL;
15439 s = soap->labbuf + soap->labidx; /* space to populate */
15440 k = soap->lablen - soap->labidx; /* number of bytes available */
15441 soap->labidx = soap->lablen; /* claim this space */
15442 #else
15443 register size_t i, k = SOAP_BLKLEN;
15444 if (!(s = (char*)soap_push_block(soap, NULL, k)))
15445 return NULL;
15446 #endif
15447 for (i = 0; i < k; i++)
15448 { register soap_wchar c;
15449 l++;
15450 if (n > 0 && l > n)
15451 goto end;
15452 c = soap_get1(soap);
15453 if ((int)c == EOF)
15454 goto end;
15455 *s++ = (char)(c & 0xFF);
15458 end:
15459 *s = '\0';
15460 if (len)
15461 *len = l - 1; /* len excludes terminating \0 */
15462 #ifdef WITH_FAST
15463 if ((s = (char*)soap_malloc(soap, l)))
15464 memcpy(s, soap->labbuf, l);
15465 #else
15466 soap_size_block(soap, NULL, i+1);
15467 s = soap_save_block(soap, NULL, 0);
15468 #endif
15469 return s;
15470 #else
15471 return NULL;
15472 #endif
15474 #endif
15475 #endif
15477 /******************************************************************************/
15478 #ifndef PALM_1
15479 SOAP_FMAC1
15481 SOAP_FMAC2
15482 soap_envelope_begin_in(struct soap *soap)
15483 { register struct Namespace *p;
15484 soap->part = SOAP_IN_ENVELOPE;
15485 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
15486 { if (soap->error == SOAP_TAG_MISMATCH)
15487 { if (!soap_element_begin_in(soap, "Envelope", 0, NULL))
15488 soap->error = SOAP_VERSIONMISMATCH;
15489 else if (soap->status == 0 || (soap->status >= 200 && soap->status <= 299))
15490 return SOAP_OK; /* allow non-SOAP XML content to be captured */
15491 soap->error = soap->status;
15493 else if (soap->status)
15494 soap->error = soap->status;
15495 return soap->error;
15497 p = soap->local_namespaces;
15498 if (p)
15499 { const char *ns = p[0].out;
15500 if (!ns)
15501 ns = p[0].ns;
15502 if (!strcmp(ns, soap_env1))
15503 { soap->version = 1; /* make sure we use SOAP 1.1 */
15504 if (p[1].out)
15505 SOAP_FREE(soap, p[1].out);
15506 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
15507 strcpy(p[1].out, soap_enc1);
15509 else if (!strcmp(ns, soap_env2))
15510 { soap->version = 2; /* make sure we use SOAP 1.2 */
15511 if (p[1].out)
15512 SOAP_FREE(soap, p[1].out);
15513 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
15514 strcpy(p[1].out, soap_enc2);
15517 return SOAP_OK;
15519 #endif
15521 /******************************************************************************/
15522 #ifndef PALM_1
15523 SOAP_FMAC1
15525 SOAP_FMAC2
15526 soap_envelope_end_in(struct soap *soap)
15527 { if (soap->version == 0)
15528 return SOAP_OK;
15529 soap->part = SOAP_END_ENVELOPE;
15530 return soap_element_end_in(soap, "SOAP-ENV:Envelope");
15532 #endif
15534 /******************************************************************************/
15535 #ifndef PALM_2
15536 SOAP_FMAC1
15538 SOAP_FMAC2
15539 soap_body_begin_out(struct soap *soap)
15540 { if (soap->version == 1)
15541 soap->encoding = 1;
15542 #ifndef WITH_LEAN
15543 if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
15544 return soap->error;
15545 #endif
15546 if (soap->version == 0)
15547 return SOAP_OK;
15548 soap->part = SOAP_IN_BODY;
15549 return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
15551 #endif
15553 /******************************************************************************/
15554 #ifndef PALM_2
15555 SOAP_FMAC1
15557 SOAP_FMAC2
15558 soap_body_end_out(struct soap *soap)
15559 { if (soap->version == 0)
15560 return SOAP_OK;
15561 if (soap_element_end_out(soap, "SOAP-ENV:Body"))
15562 return soap->error;
15563 soap->part = SOAP_END_BODY;
15564 return SOAP_OK;
15566 #endif
15568 /******************************************************************************/
15569 #ifndef PALM_2
15570 SOAP_FMAC1
15572 SOAP_FMAC2
15573 soap_body_begin_in(struct soap *soap)
15574 { if (soap->version == 0)
15575 return SOAP_OK;
15576 soap->part = SOAP_IN_BODY;
15577 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
15578 return soap->error;
15579 if (!soap->body)
15580 soap->part = SOAP_NO_BODY;
15581 return SOAP_OK;
15583 #endif
15585 /******************************************************************************/
15586 #ifndef PALM_2
15587 SOAP_FMAC1
15589 SOAP_FMAC2
15590 soap_body_end_in(struct soap *soap)
15591 { if (soap->version == 0)
15592 return SOAP_OK;
15593 if (soap->part == SOAP_NO_BODY)
15594 return soap->error = SOAP_OK;
15595 soap->part = SOAP_END_BODY;
15596 return soap_element_end_in(soap, "SOAP-ENV:Body");
15598 #endif
15600 /******************************************************************************/
15601 #ifndef PALM_2
15602 SOAP_FMAC1
15604 SOAP_FMAC2
15605 soap_recv_header(struct soap *soap)
15606 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
15607 soap->error = SOAP_OK;
15608 if (soap->error == SOAP_OK && soap->fheader)
15609 soap->error = soap->fheader(soap);
15610 return soap->error;
15612 #endif
15614 /******************************************************************************/
15615 #ifndef PALM_1
15616 SOAP_FMAC1
15617 void
15618 SOAP_FMAC2
15619 soap_set_endpoint(struct soap *soap, const char *endpoint)
15620 { register const char *s;
15621 register size_t i, n;
15622 soap->endpoint[0] = '\0';
15623 soap->host[0] = '\0';
15624 soap->path[0] = '/';
15625 soap->path[1] = '\0';
15626 soap->port = 80;
15627 if (!endpoint || !*endpoint)
15628 return;
15629 #ifdef WITH_OPENSSL
15630 if (!soap_tag_cmp(endpoint, "https:*"))
15631 soap->port = 443;
15632 #endif
15633 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint));
15634 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
15635 s = strchr(endpoint, ':');
15636 if (s && s[1] == '/' && s[2] == '/')
15637 s += 3;
15638 else
15639 s = endpoint;
15640 n = strlen(s);
15641 if (n >= sizeof(soap->host))
15642 n = sizeof(soap->host) - 1;
15643 #ifdef WITH_IPV6
15644 if (s[0] == '[')
15645 { s++;
15646 for (i = 0; i < n; i++)
15647 { if (s[i] == ']')
15648 { s++;
15649 --n;
15650 break;
15652 soap->host[i] = s[i];
15655 else
15656 { for (i = 0; i < n; i++)
15657 { soap->host[i] = s[i];
15658 if (s[i] == '/' || s[i] == ':')
15659 break;
15662 #else
15663 for (i = 0; i < n; i++)
15664 { soap->host[i] = s[i];
15665 if (s[i] == '/' || s[i] == ':')
15666 break;
15668 #endif
15669 soap->host[i] = '\0';
15670 if (s[i] == ':')
15671 { soap->port = (int)soap_strtol(s + i + 1, NULL, 10);
15672 for (i++; i < n; i++)
15673 if (s[i] == '/')
15674 break;
15676 if (i < n && s[i])
15677 { strncpy(soap->path, s + i, sizeof(soap->path));
15678 soap->path[sizeof(soap->path) - 1] = '\0';
15681 #endif
15683 /******************************************************************************/
15684 #ifndef PALM_1
15685 SOAP_FMAC1
15687 SOAP_FMAC2
15688 soap_connect(struct soap *soap, const char *endpoint, const char *action)
15689 { return soap_connect_command(soap, SOAP_POST, endpoint, action);
15691 #endif
15693 /******************************************************************************/
15694 #ifndef PALM_1
15695 SOAP_FMAC1
15697 SOAP_FMAC2
15698 soap_connect_command(struct soap *soap, int http_command, const char *endpoints, const char *action)
15699 { char *endpoint;
15700 const char *s;
15701 if (endpoints && (s = strchr(endpoints, ' ')))
15702 { endpoint = (char*)SOAP_MALLOC(soap, strlen(endpoints) + 1);
15703 for (;;)
15704 { strncpy(endpoint, endpoints, s - endpoints);
15705 endpoint[s - endpoints] = '\0';
15706 if (soap_try_connect_command(soap, http_command, endpoint, action) != SOAP_TCP_ERROR)
15707 break;
15708 if (!*s)
15709 break;
15710 soap->error = SOAP_OK;
15711 while (*s == ' ')
15712 s++;
15713 endpoints = s;
15714 s = strchr(endpoints, ' ');
15715 if (!s)
15716 s = endpoints + strlen(endpoints);
15718 SOAP_FREE(soap, endpoint);
15720 else
15721 soap_try_connect_command(soap, http_command, endpoints, action);
15722 return soap->error;
15724 #endif
15726 /******************************************************************************/
15727 #ifndef PALM_1
15728 static int
15729 soap_try_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
15730 { char host[sizeof(soap->host)];
15731 int port;
15732 size_t count;
15733 soap->error = SOAP_OK;
15734 strcpy(host, soap->host); /* save previous host name: if != then reconnect */
15735 port = soap->port; /* save previous port to compare */
15736 soap->status = http_command;
15737 soap_set_endpoint(soap, endpoint);
15738 #ifndef WITH_LEANER
15739 if (soap->fconnect)
15740 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
15741 return soap->error;
15743 else
15744 #endif
15745 soap->action = soap_strdup(soap, action);
15746 if (soap->fopen && *soap->host)
15747 { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
15748 { soap->error = SOAP_OK;
15749 #ifndef WITH_LEAN
15750 if (!strncmp(endpoint, "soap.udp:", 9))
15751 soap->omode |= SOAP_IO_UDP;
15752 else
15753 #endif
15754 { soap->keep_alive = 0; /* to force close */
15755 soap->omode &= ~SOAP_IO_UDP; /* to force close */
15757 soap_closesock(soap);
15758 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint?endpoint:"(null)", soap->host, soap->path, soap->port));
15759 if (!soap->keep_alive || !soap_valid_socket(soap->socket))
15760 { soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
15761 if (soap->error)
15762 return soap->error;
15763 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
15767 #ifdef WITH_NTLM
15768 if (soap_ntlm_handshake(soap, SOAP_GET, endpoint, soap->host, soap->port))
15769 return soap->error;
15770 #endif
15771 count = soap_count_attachments(soap);
15772 if (soap_begin_send(soap))
15773 return soap->error;
15774 if (http_command == SOAP_GET)
15775 { soap->mode &= ~SOAP_IO;
15776 soap->mode |= SOAP_IO_BUFFER;
15778 #ifndef WITH_NOHTTP
15779 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
15780 { unsigned int k = soap->mode;
15781 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
15782 if ((k & SOAP_IO) != SOAP_IO_FLUSH)
15783 soap->mode |= SOAP_IO_BUFFER;
15784 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
15785 return soap->error;
15786 #ifndef WITH_LEANER
15787 if ((k & SOAP_IO) == SOAP_IO_CHUNK)
15788 { if (soap_flush(soap))
15789 return soap->error;
15791 #endif
15792 soap->mode = k;
15794 if (http_command == SOAP_GET || http_command == SOAP_DEL)
15795 return soap_end_send_flush(soap);
15796 #endif
15797 return SOAP_OK;
15799 #endif
15801 /******************************************************************************/
15802 #ifdef WITH_NTLM
15803 #ifndef PALM_1
15804 static int
15805 soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const char *host, int port)
15806 { /* requires libntlm from http://www.nongnu.org/libntlm/ */
15807 const char *userid = (soap->proxy_userid ? soap->proxy_userid : soap->userid);
15808 const char *passwd = (soap->proxy_passwd ? soap->proxy_passwd : soap->passwd);
15809 struct SOAP_ENV__Header *oldheader;
15810 if (soap->ntlm_challenge && userid && passwd && soap->authrealm)
15811 { tSmbNtlmAuthRequest req;
15812 tSmbNtlmAuthResponse res;
15813 tSmbNtlmAuthChallenge ch;
15814 short k = soap->keep_alive;
15815 size_t l = soap->length;
15816 size_t c = soap->count;
15817 soap_mode m = soap->mode, o = soap->omode;
15818 int s = soap->status;
15819 char *a = soap->action;
15820 short v = soap->version;
15821 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge));
15822 if (!*soap->ntlm_challenge)
15823 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
15824 /* S -> C 401 Unauthorized
15825 WWW-Authenticate: NTLM
15827 buildSmbNtlmAuthRequest(&req, userid, soap->authrealm);
15828 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&req, NULL, SmbLength(&req));
15829 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
15830 /* C -> S GET ...
15831 Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
15833 soap->omode = SOAP_IO_BUFFER;
15834 if (soap_begin_send(soap))
15835 return soap->error;
15836 soap->keep_alive = 1;
15837 soap->status = command;
15838 if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0)
15839 || soap_end_send_flush(soap))
15840 return soap->error;
15841 soap->mode = m;
15842 soap->keep_alive = k;
15843 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 2: waiting on server NTLM response\n"));
15844 oldheader = soap->header;
15845 if (soap_begin_recv(soap))
15846 if (soap->error == SOAP_EOF)
15847 return soap->error;
15848 soap_end_recv(soap);
15849 soap->header = oldheader;
15850 soap->length = l;
15851 if (soap->status != 401 && soap->status != 407)
15852 return soap->error = SOAP_NTLM_ERROR;
15853 soap->error = SOAP_OK;
15855 /* S -> C 401 Unauthorized
15856 WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
15858 soap_base642s(soap, soap->ntlm_challenge, (char*)&ch, sizeof(tSmbNtlmAuthChallenge), NULL);
15859 buildSmbNtlmAuthResponse(&ch, &res, userid, passwd);
15860 soap->ntlm_challenge = soap_s2base64(soap, (unsigned char*)&res, NULL, SmbLength(&res));
15861 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap->ntlm_challenge));
15862 /* C -> S GET ...
15863 Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
15865 soap->userid = NULL;
15866 soap->passwd = NULL;
15867 soap->proxy_userid = NULL;
15868 soap->proxy_passwd = NULL;
15869 soap->keep_alive = k;
15870 soap->length = l;
15871 soap->count = c;
15872 soap->mode = m;
15873 soap->omode = o;
15874 soap->status = s;
15875 soap->action = a;
15876 soap->version = v;
15878 return SOAP_OK;
15880 #endif
15881 #endif
15883 /******************************************************************************/
15884 #ifndef WITH_LEAN
15885 SOAP_FMAC1
15886 char*
15887 SOAP_FMAC2
15888 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
15889 { register int i;
15890 register unsigned long m;
15891 register char *p;
15892 if (!t)
15893 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
15894 if (!t)
15895 return NULL;
15896 p = t;
15897 t[0] = '\0';
15898 if (!s)
15899 return p;
15900 for (; n > 2; n -= 3, s += 3)
15901 { m = s[0];
15902 m = (m << 8) | s[1];
15903 m = (m << 8) | s[2];
15904 for (i = 4; i > 0; m >>= 6)
15905 t[--i] = soap_base64o[m & 0x3F];
15906 t += 4;
15908 t[0] = '\0';
15909 if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
15910 { m = 0;
15911 for (i = 0; i < n; i++)
15912 m = (m << 8) | *s++;
15913 for (; i < 3; i++)
15914 m <<= 8;
15915 for (i = 4; i > 0; m >>= 6)
15916 t[--i] = soap_base64o[m & 0x3F];
15917 for (i = 3; i > n; i--)
15918 t[i] = '=';
15919 t[4] = '\0';
15921 return p;
15923 #endif
15925 /******************************************************************************/
15926 #ifndef WITH_LEAN
15927 SOAP_FMAC1
15928 const char*
15929 SOAP_FMAC2
15930 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
15931 { register size_t i, j;
15932 register soap_wchar c;
15933 register unsigned long m;
15934 register const char *p;
15935 if (!s || !*s)
15936 { if (n)
15937 *n = 0;
15938 if (soap->error)
15939 return NULL;
15940 return SOAP_NON_NULL;
15942 if (!t)
15943 { l = (strlen(s) + 3) / 4 * 3 + 1; /* make sure enough space for \0 */
15944 t = (char*)soap_malloc(soap, l);
15946 if (!t)
15947 return NULL;
15948 p = t;
15949 if (n)
15950 *n = 0;
15951 for (i = 0; ; i += 3, l -= 3)
15952 { m = 0;
15953 j = 0;
15954 while (j < 4)
15955 { c = *s++;
15956 if (c == '=' || !c)
15957 { if (l >= j - 1)
15958 { switch (j)
15959 { case 2:
15960 *t++ = (char)((m >> 4) & 0xFF);
15961 i++;
15962 l--;
15963 break;
15964 case 3:
15965 *t++ = (char)((m >> 10) & 0xFF);
15966 *t++ = (char)((m >> 2) & 0xFF);
15967 i += 2;
15968 l -= 2;
15971 if (n)
15972 *n = (int)i;
15973 if (l)
15974 *t = '\0';
15975 return p;
15977 c -= '+';
15978 if (c >= 0 && c <= 79)
15979 { int b = soap_base64i[c];
15980 if (b >= 64)
15981 { soap->error = SOAP_TYPE;
15982 return NULL;
15984 m = (m << 6) + b;
15985 j++;
15987 else if (!soap_blank(c + '+'))
15988 { soap->error = SOAP_TYPE;
15989 return NULL;
15992 if (l < 3)
15993 { if (n)
15994 *n = (int)i;
15995 if (l)
15996 *t = '\0';
15997 return p;
15999 *t++ = (char)((m >> 16) & 0xFF);
16000 *t++ = (char)((m >> 8) & 0xFF);
16001 *t++ = (char)(m & 0xFF);
16004 #endif
16006 /******************************************************************************/
16007 #ifndef WITH_LEAN
16008 SOAP_FMAC1
16009 char*
16010 SOAP_FMAC2
16011 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
16012 { register char *p;
16013 if (!t)
16014 t = (char*)soap_malloc(soap, 2 * n + 1);
16015 if (!t)
16016 return NULL;
16017 p = t;
16018 t[0] = '\0';
16019 if (s)
16020 { for (; n > 0; n--)
16021 { register int m = *s++;
16022 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
16023 m &= 0x0F;
16024 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
16027 *t++ = '\0';
16028 return p;
16030 #endif
16032 /******************************************************************************/
16033 #ifndef WITH_LEAN
16034 SOAP_FMAC1
16035 const char*
16036 SOAP_FMAC2
16037 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
16038 { register const char *p;
16039 if (!s || !*s)
16040 { if (n)
16041 *n = 0;
16042 if (soap->error)
16043 return NULL;
16044 return SOAP_NON_NULL;
16046 if (!t)
16047 { l = strlen(s) / 2 + 1; /* make sure enough space for \0 */
16048 t = (char*)soap_malloc(soap, l);
16050 if (!t)
16051 return NULL;
16052 p = t;
16053 while (l)
16054 { register int d1, d2;
16055 d1 = *s++;
16056 if (!d1)
16057 break;
16058 d2 = *s++;
16059 if (!d2)
16060 break;
16061 *t++ = (char)(((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'));
16062 l--;
16064 if (n)
16065 *n = (int)(t - p);
16066 if (l)
16067 *t = '\0';
16068 return p;
16070 #endif
16072 /******************************************************************************/
16073 #ifndef WITH_NOHTTP
16074 #ifndef PALM_1
16075 SOAP_FMAC1
16077 SOAP_FMAC2
16078 soap_puthttphdr(struct soap *soap, int status, size_t count)
16079 { if (soap->status != SOAP_GET && soap->status != SOAP_DEL && soap->status != SOAP_CONNECT)
16080 { register const char *s = "text/xml; charset=utf-8";
16081 register int err = SOAP_OK;
16082 #ifndef WITH_LEANER
16083 register const char *r = NULL;
16084 #endif
16085 if ((status == SOAP_FILE || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE) && soap->http_content && !strchr(s, 10) && !strchr(s, 13))
16086 s = soap->http_content;
16087 else if (status == SOAP_HTML)
16088 s = "text/html; charset=utf-8";
16089 else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
16090 { if (soap->version == 2)
16091 s = "application/soap+xml; charset=utf-8";
16093 #ifndef WITH_LEANER
16094 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
16095 { if (soap->mode & SOAP_ENC_MTOM)
16096 { if (soap->version == 2)
16097 r = "application/soap+xml";
16098 else
16099 r = "text/xml";
16100 s = "application/xop+xml";
16102 else
16103 s = "application/dime";
16105 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80)
16106 { register const char *t;
16107 #ifdef HAVE_SNPRINTF
16108 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
16109 #else
16110 sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
16111 #endif
16112 t = strchr(s, ';');
16113 if (t)
16114 strncat(soap->tmpbuf, s, t - s);
16115 else
16116 strcat(soap->tmpbuf, s);
16117 if (soap->mime.start && strlen(soap->tmpbuf) + strlen(soap->mime.start) + 11 < sizeof(soap->tmpbuf))
16118 { strcat(soap->tmpbuf, "\"; start=\"");
16119 strcat(soap->tmpbuf, soap->mime.start);
16121 strcat(soap->tmpbuf, "\"");
16122 if (r && strlen(soap->tmpbuf) + strlen(r) + 15 < sizeof(soap->tmpbuf))
16123 { strcat(soap->tmpbuf, "; start-info=\"");
16124 strcat(soap->tmpbuf, r);
16125 strcat(soap->tmpbuf, "\"");
16128 else
16129 strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
16130 soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
16131 s = soap->tmpbuf;
16132 if (status == SOAP_OK && soap->version == 2 && soap->action && strlen(soap->action) + strlen(s) < sizeof(soap->tmpbuf) - 80)
16134 #ifdef HAVE_SNPRINTF
16135 size_t l = strlen(s);
16136 soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "; action=\"%s\"", soap->action);
16137 #else
16138 sprintf(soap->tmpbuf + strlen(s), "; action=\"%s\"", soap->action);
16139 #endif
16141 #endif
16142 if ((err = soap->fposthdr(soap, "Content-Type", s)))
16143 return err;
16144 #ifdef WITH_ZLIB
16145 if ((soap->omode & SOAP_ENC_ZLIB))
16147 #ifdef WITH_GZIP
16148 err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
16149 #else
16150 err = soap->fposthdr(soap, "Content-Encoding", "deflate");
16151 #endif
16152 if (err)
16153 return err;
16155 #endif
16156 #ifndef WITH_LEANER
16157 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
16158 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
16159 else
16160 #endif
16161 if (s)
16163 #ifdef HAVE_SNPRINTF
16164 soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", (unsigned long)count);
16165 #else
16166 sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
16167 #endif
16168 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
16170 if (err)
16171 return err;
16173 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
16175 #endif
16176 #endif
16178 /******************************************************************************/
16179 #ifndef WITH_LEAN
16180 static const char*
16181 soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
16182 { if (!t)
16183 t = SOAP_STR_EOS;
16184 if (*soap->tag)
16186 #ifdef HAVE_SNPRINTF
16187 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s in element '%s'", s, t ? t : SOAP_STR_EOS, soap->tag);
16188 #else
16189 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
16190 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag);
16191 else
16192 sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
16193 #endif
16195 else
16197 #ifdef HAVE_SNPRINTF
16198 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s", s, t ? t : SOAP_STR_EOS);
16199 #else
16200 if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
16201 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t);
16202 else
16203 sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
16204 #endif
16206 return soap->msgbuf;
16208 #endif
16210 /******************************************************************************/
16211 #ifndef PALM_1
16212 SOAP_FMAC1
16213 void
16214 SOAP_FMAC2
16215 soap_set_fault(struct soap *soap)
16216 { const char **c = soap_faultcode(soap);
16217 const char **s = soap_faultstring(soap);
16218 if (soap->fseterror)
16219 soap->fseterror(soap, c, s);
16220 if (!*c)
16221 { if (soap->version == 2)
16222 *c = "SOAP-ENV:Sender";
16223 else
16224 *c = "SOAP-ENV:Client";
16226 if (*s)
16227 return;
16228 switch (soap->error)
16230 #ifndef WITH_LEAN
16231 case SOAP_CLI_FAULT:
16232 *s = "Client fault";
16233 break;
16234 case SOAP_SVR_FAULT:
16235 *s = "Server fault";
16236 break;
16237 case SOAP_TAG_MISMATCH:
16238 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
16239 break;
16240 case SOAP_TYPE:
16241 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
16242 break;
16243 case SOAP_SYNTAX_ERROR:
16244 *s = "Well-formedness violation";
16245 break;
16246 case SOAP_NO_TAG:
16247 *s = "No tag: no XML root element or missing SOAP message body element";
16248 break;
16249 case SOAP_MUSTUNDERSTAND:
16250 *c = "SOAP-ENV:MustUnderstand";
16251 #ifdef HAVE_SNPRINTF
16252 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "The data in element '%s' must be understood but cannot be handled", soap->tag);
16253 #else
16254 strncpy(soap->msgbuf, soap->tag, sizeof(soap->msgbuf));
16255 soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
16256 #endif
16257 *s = soap->msgbuf;
16258 break;
16259 case SOAP_VERSIONMISMATCH:
16260 *c = "SOAP-ENV:VersionMismatch";
16261 *s = "Invalid SOAP message or SOAP version mismatch";
16262 break;
16263 case SOAP_DATAENCODINGUNKNOWN:
16264 *c = "SOAP-ENV:DataEncodingUnknown";
16265 *s = "Unsupported SOAP data encoding";
16266 break;
16267 case SOAP_NAMESPACE:
16268 *s = soap_set_validation_fault(soap, "namespace error", NULL);
16269 break;
16270 case SOAP_USER_ERROR:
16271 *s = "User data error";
16272 break;
16273 case SOAP_FATAL_ERROR:
16274 *s = "Fatal error";
16275 break;
16276 case SOAP_NO_METHOD:
16277 #ifdef HAVE_SNPRINTF
16278 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
16279 #else
16280 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
16281 #endif
16282 *s = soap->msgbuf;
16283 break;
16284 case SOAP_NO_DATA:
16285 *s = "Data required for operation";
16286 break;
16287 case SOAP_GET_METHOD:
16288 *s = "HTTP GET method not implemented";
16289 break;
16290 case SOAP_PUT_METHOD:
16291 *s = "HTTP PUT method not implemented";
16292 break;
16293 case SOAP_HTTP_METHOD:
16294 *s = "HTTP method not implemented";
16295 break;
16296 case SOAP_EOM:
16297 *s = "Out of memory";
16298 break;
16299 case SOAP_MOE:
16300 *s = "Memory overflow or memory corruption error";
16301 break;
16302 case SOAP_HDR:
16303 *s = "Header line too long";
16304 break;
16305 case SOAP_IOB:
16306 *s = "Array index out of bounds";
16307 break;
16308 case SOAP_NULL:
16309 *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
16310 break;
16311 case SOAP_DUPLICATE_ID:
16312 *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id);
16313 if (soap->version == 2)
16314 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
16315 break;
16316 case SOAP_MISSING_ID:
16317 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
16318 if (soap->version == 2)
16319 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
16320 break;
16321 case SOAP_HREF:
16322 *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id);
16323 break;
16324 case SOAP_FAULT:
16325 break;
16326 #ifndef WITH_NOIO
16327 case SOAP_UDP_ERROR:
16328 *s = "Message too large for UDP packet";
16329 break;
16330 case SOAP_TCP_ERROR:
16331 *s = tcp_error(soap);
16332 break;
16333 #endif
16334 case SOAP_HTTP_ERROR:
16335 *s = "An HTTP processing error occurred";
16336 break;
16337 case SOAP_NTLM_ERROR:
16338 *s = "An HTTP NTLM authentication error occurred";
16339 break;
16340 case SOAP_SSL_ERROR:
16341 #ifdef WITH_OPENSSL
16342 *s = "SSL/TLS error";
16343 #else
16344 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
16345 #endif
16346 break;
16347 case SOAP_PLUGIN_ERROR:
16348 *s = "Plugin registry error";
16349 break;
16350 case SOAP_DIME_ERROR:
16351 *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE";
16352 break;
16353 case SOAP_DIME_HREF:
16354 *s = "DIME href to missing attachment";
16355 break;
16356 case SOAP_DIME_MISMATCH:
16357 *s = "DIME version/transmission error";
16358 break;
16359 case SOAP_DIME_END:
16360 *s = "End of DIME error";
16361 break;
16362 case SOAP_MIME_ERROR:
16363 *s = "MIME format error";
16364 break;
16365 case SOAP_MIME_HREF:
16366 *s = "MIME href to missing attachment";
16367 break;
16368 case SOAP_MIME_END:
16369 *s = "End of MIME error";
16370 break;
16371 case SOAP_ZLIB_ERROR:
16372 #ifdef WITH_ZLIB
16373 #ifdef HAVE_SNPRINTF
16374 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
16375 #else
16376 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg ? soap->d_stream->msg : SOAP_STR_EOS);
16377 #endif
16378 *s = soap->msgbuf;
16379 #else
16380 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
16381 #endif
16382 break;
16383 case SOAP_REQUIRED:
16384 *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
16385 break;
16386 case SOAP_PROHIBITED:
16387 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
16388 break;
16389 case SOAP_OCCURS:
16390 *s = soap_set_validation_fault(soap, "occurrence violation", NULL);
16391 break;
16392 case SOAP_LENGTH:
16393 *s = soap_set_validation_fault(soap, "content range or length violation", NULL);
16394 break;
16395 case SOAP_FD_EXCEEDED:
16396 *s = "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
16397 break;
16398 case SOAP_UTF_ERROR:
16399 *s = "UTF content encoding error";
16400 break;
16401 case SOAP_STOP:
16402 *s = "Stopped: no response sent or received (informative)";
16403 break;
16404 #endif
16405 case SOAP_EOF:
16406 #ifndef WITH_NOIO
16407 *s = soap_strerror(soap); /* *s = soap->msgbuf */
16408 #ifndef WITH_LEAN
16409 if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
16410 { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
16411 memcpy(soap->msgbuf, "End of file or no input: ", 25);
16413 #endif
16414 break;
16415 #else
16416 *s = "End of file or no input";
16417 break;
16418 #endif
16419 default:
16420 #ifndef WITH_NOHTTP
16421 #ifndef WITH_LEAN
16422 if (soap->error > 200 && soap->error < 600)
16424 #ifdef HAVE_SNPRINTF
16425 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
16426 #else
16427 sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
16428 #endif
16429 *s = soap->msgbuf;
16431 else
16432 #endif
16433 #endif
16435 #ifdef HAVE_SNPRINTF
16436 soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error %d", soap->error);
16437 #else
16438 sprintf(soap->msgbuf, "Error %d", soap->error);
16439 #endif
16440 *s = soap->msgbuf;
16444 #endif
16446 /******************************************************************************/
16447 #ifndef PALM_1
16448 SOAP_FMAC1
16450 SOAP_FMAC2
16451 soap_send_fault(struct soap *soap)
16452 { register int status = soap->error;
16453 if (status == SOAP_OK || status == SOAP_STOP)
16454 return soap_closesock(soap);
16455 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
16456 soap->keep_alive = 0; /* to terminate connection */
16457 soap_set_fault(soap);
16458 if (soap->error < 200 && soap->error != SOAP_FAULT)
16459 soap->header = NULL;
16460 if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
16461 { register int r = 1;
16462 #ifndef WITH_NOIO
16463 if (soap->fpoll && soap->fpoll(soap))
16464 r = 0;
16465 #ifndef WITH_LEAN
16466 else if (soap_valid_socket(soap->socket))
16467 { r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
16468 if (r > 0)
16469 { int t;
16470 if (!(r & SOAP_TCP_SELECT_SND)
16471 || ((r & SOAP_TCP_SELECT_RCV)
16472 && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0))
16473 r = 0;
16476 #endif
16477 #endif
16478 if (r > 0)
16479 { soap->error = SOAP_OK;
16480 soap->encodingStyle = NULL; /* no encodingStyle in Faults */
16481 soap_serializeheader(soap);
16482 soap_serializefault(soap);
16483 soap_begin_count(soap);
16484 if (soap->mode & SOAP_IO_LENGTH)
16485 { soap_envelope_begin_out(soap);
16486 soap_putheader(soap);
16487 soap_body_begin_out(soap);
16488 soap_putfault(soap);
16489 soap_body_end_out(soap);
16490 soap_envelope_end_out(soap);
16492 soap_end_count(soap);
16493 if (soap_response(soap, status)
16494 || soap_envelope_begin_out(soap)
16495 || soap_putheader(soap)
16496 || soap_body_begin_out(soap)
16497 || soap_putfault(soap)
16498 || soap_body_end_out(soap)
16499 || soap_envelope_end_out(soap))
16500 return soap_closesock(soap);
16501 soap_end_send(soap);
16504 soap->error = status;
16505 return soap_closesock(soap);
16507 #endif
16509 /******************************************************************************/
16510 #ifndef PALM_1
16511 SOAP_FMAC1
16513 SOAP_FMAC2
16514 soap_recv_fault(struct soap *soap, int check)
16515 { register int status = soap->error;
16516 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Check if receiving SOAP Fault\n"));
16517 if (!check)
16518 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
16519 if (soap->error != SOAP_NO_TAG
16520 && (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
16521 return soap->error;
16523 else if (soap->version == 0) /* check == 1 but no SOAP: do not parse SOAP Fault */
16524 return SOAP_OK;
16525 soap->error = SOAP_OK;
16526 if (soap_getfault(soap))
16527 { /* check flag set: check if SOAP Fault is present, if not just return */
16528 if (check && soap->error == SOAP_TAG_MISMATCH && soap->level == 2)
16529 return soap->error = SOAP_OK;
16530 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed at level %u tag '%s'\n", soap->level, soap->tag));
16531 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
16532 soap->error = status;
16533 soap_set_fault(soap);
16535 else
16536 { register const char *s = *soap_faultcode(soap);
16537 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
16538 status = SOAP_SVR_FAULT;
16539 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
16540 status = SOAP_CLI_FAULT;
16541 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
16542 status = SOAP_MUSTUNDERSTAND;
16543 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
16544 status = SOAP_VERSIONMISMATCH;
16545 else
16546 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Received SOAP Fault code %s\n", s));
16547 status = SOAP_FAULT;
16549 if (!soap_body_end_in(soap))
16550 soap_envelope_end_in(soap);
16552 soap_end_recv(soap);
16553 soap->error = status;
16554 return soap_closesock(soap);
16556 #endif
16558 /******************************************************************************/
16559 #ifndef WITH_NOHTTP
16560 #ifndef PALM_1
16561 SOAP_FMAC1
16563 SOAP_FMAC2
16564 soap_send_empty_response(struct soap *soap, int httpstatuscode)
16565 { register soap_mode m = soap->omode;
16566 if (!(m & SOAP_IO_UDP))
16567 { soap->count = 0;
16568 if ((m & SOAP_IO) == SOAP_IO_CHUNK)
16569 soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
16570 soap_response(soap, httpstatuscode);
16571 soap_end_send(soap); /* force end of sends */
16572 soap->error = SOAP_STOP; /* stops the server (from returning a response) */
16573 soap->omode = m;
16575 return soap_closesock(soap);
16577 #endif
16578 #endif
16580 /******************************************************************************/
16581 #ifndef WITH_NOHTTP
16582 #ifndef PALM_1
16583 SOAP_FMAC1
16585 SOAP_FMAC2
16586 soap_recv_empty_response(struct soap *soap)
16587 { if (!(soap->omode & SOAP_IO_UDP))
16588 { if (!soap_begin_recv(soap))
16590 #ifndef WITH_LEAN
16591 if (soap->body)
16592 soap_get_http_body(soap, NULL); /* read (empty?) HTTP body and discard */
16593 #endif
16594 soap_end_recv(soap);
16596 else if (soap->error == SOAP_NO_DATA || soap->error == 202)
16597 soap->error = SOAP_OK;
16599 return soap_closesock(soap);
16601 #endif
16602 #endif
16604 /******************************************************************************/
16605 #ifndef WITH_NOIO
16606 #ifndef PALM_1
16607 static const char*
16608 soap_strerror(struct soap *soap)
16609 { register int err = soap->errnum;
16610 *soap->msgbuf = '\0';
16611 if (err)
16613 #ifndef WIN32
16614 # ifdef HAVE_STRERROR_R
16615 # ifdef _GNU_SOURCE
16616 return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */
16617 # else
16618 strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */
16619 # endif
16620 # else
16621 return strerror(err);
16622 # endif
16623 #else
16624 #ifndef UNDER_CE
16625 DWORD len;
16626 *soap->msgbuf = '\0';
16627 len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL);
16628 #else
16629 DWORD i, len;
16630 *soap->msgbuf = '\0';
16631 len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
16632 for (i = 0; i <= len; i++)
16633 { if (((TCHAR*)soap->msgbuf)[i] < 0x80)
16634 soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
16635 else
16636 soap->msgbuf[i] = '?';
16638 #endif
16639 #endif
16641 else
16642 { char *s = soap->msgbuf;
16643 #ifndef WITH_LEAN
16644 int rt = soap->recv_timeout, st = soap->send_timeout;
16645 int ru = ' ', su = ' ';
16646 #endif
16647 strcpy(s, "Operation interrupted or timed out");
16648 #ifndef WITH_LEAN
16649 if (rt < 0)
16650 { rt = -rt;
16651 ru = 'u';
16653 if (st < 0)
16654 { st = -st;
16655 su = 'u';
16657 if (rt)
16659 #ifdef HAVE_SNPRINTF
16660 size_t l = strlen(s);
16661 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs recv delay)", rt, ru);
16662 #else
16663 sprintf(s + strlen(s), " (%d%cs recv delay)", rt, ru);
16664 #endif
16666 if (st)
16668 #ifdef HAVE_SNPRINTF
16669 size_t l = strlen(s);
16670 soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs send delay)", st, su);
16671 #else
16672 sprintf(s + strlen(s), " (%d%cs send delay)", st, su);
16673 #endif
16675 #endif
16677 return soap->msgbuf;
16679 #endif
16680 #endif
16682 /******************************************************************************/
16683 #ifndef PALM_2
16684 static int
16685 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror)
16686 { *soap_faultcode(soap) = faultcode;
16687 if (faultsubcodeQName)
16688 *soap_faultsubcode(soap) = faultsubcodeQName;
16689 *soap_faultstring(soap) = faultstring;
16690 if (faultdetailXML && *faultdetailXML)
16691 { register const char **s = soap_faultdetail(soap);
16692 if (s)
16693 *s = faultdetailXML;
16695 return soap->error = soaperror;
16697 #endif
16699 /******************************************************************************/
16700 #ifndef PALM_2
16701 SOAP_FMAC1
16703 SOAP_FMAC2
16704 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
16705 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror);
16707 #endif
16709 /******************************************************************************/
16710 #ifndef PALM_2
16711 SOAP_FMAC1
16713 SOAP_FMAC2
16714 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror)
16715 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror);
16717 #endif
16719 /******************************************************************************/
16720 #ifndef PALM_2
16721 static int
16722 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
16723 { char *r = NULL, *s = NULL, *t = NULL;
16724 if (faultsubcodeQName)
16725 r = soap_strdup(soap, faultsubcodeQName);
16726 if (faultstring)
16727 s = soap_strdup(soap, faultstring);
16728 if (faultdetailXML)
16729 t = soap_strdup(soap, faultdetailXML);
16730 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
16732 #endif
16734 /******************************************************************************/
16735 #ifndef PALM_2
16736 SOAP_FMAC1
16738 SOAP_FMAC2
16739 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
16740 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML);
16742 #endif
16744 /******************************************************************************/
16745 #ifndef PALM_2
16746 SOAP_FMAC1
16748 SOAP_FMAC2
16749 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
16750 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML);
16752 #endif
16754 /******************************************************************************/
16755 #ifndef PALM_2
16756 SOAP_FMAC1
16758 SOAP_FMAC2
16759 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML)
16760 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML);
16762 #endif
16764 /******************************************************************************/
16765 #ifndef PALM_2
16766 SOAP_FMAC1
16768 SOAP_FMAC2
16769 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML)
16770 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML);
16772 #endif
16774 /******************************************************************************/
16775 #ifndef PALM_2
16776 #ifndef WITH_NOSTDLIB
16777 SOAP_FMAC1
16778 void
16779 SOAP_FMAC2
16780 soap_print_fault(struct soap *soap, FILE *fd)
16781 { if (soap_check_state(soap))
16782 fprintf(fd, "Error: soap struct state not initialized\n");
16783 else if (soap->error)
16784 { const char **c, *v = NULL, *s, *d;
16785 c = soap_faultcode(soap);
16786 if (!*c)
16787 soap_set_fault(soap);
16788 if (soap->version == 2)
16789 v = soap_check_faultsubcode(soap);
16790 s = *soap_faultstring(soap);
16791 d = soap_check_faultdetail(soap);
16792 fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
16795 #endif
16796 #endif
16798 /******************************************************************************/
16799 #ifdef __cplusplus
16800 #ifndef WITH_LEAN
16801 #ifndef WITH_NOSTDLIB
16802 #ifndef WITH_COMPAT
16803 SOAP_FMAC1
16804 void
16805 SOAP_FMAC2
16806 soap_stream_fault(struct soap *soap, std::ostream& os)
16807 { if (soap_check_state(soap))
16808 os << "Error: soap struct state not initialized\n";
16809 else if (soap->error)
16810 { const char **c, *v = NULL, *s, *d;
16811 c = soap_faultcode(soap);
16812 if (!*c)
16813 soap_set_fault(soap);
16814 if (soap->version == 2)
16815 v = soap_check_faultsubcode(soap);
16816 s = *soap_faultstring(soap);
16817 d = soap_check_faultdetail(soap);
16818 os << (soap->version ? "SOAP 1." : "Error ")
16819 << (soap->version ? (int)soap->version : soap->error)
16820 << " fault: " << *c
16821 << "[" << (v ? v : "no subcode") << "]"
16822 << std::endl
16823 << "\"" << (s ? s : "[no reason]") << "\""
16824 << std::endl
16825 << "Detail: " << (d ? d : "[no detail]")
16826 << std::endl;
16829 #endif
16830 #endif
16831 #endif
16832 #endif
16834 /******************************************************************************/
16835 #ifndef WITH_LEAN
16836 #ifndef WITH_NOSTDLIB
16837 SOAP_FMAC1
16838 char*
16839 SOAP_FMAC2
16840 soap_sprint_fault(struct soap *soap, char *buf, size_t len)
16841 { if (soap_check_state(soap))
16842 { strncpy(buf, "Error: soap struct not initialized", len);
16843 buf[len - 1] = '\0';
16845 else if (soap->error)
16846 { const char **c, *v = NULL, *s, *d;
16847 c = soap_faultcode(soap);
16848 if (!*c)
16849 soap_set_fault(soap);
16850 if (soap->version == 2)
16851 v = *soap_faultsubcode(soap);
16852 s = *soap_faultstring(soap);
16853 d = soap_check_faultdetail(soap);
16854 #ifdef HAVE_SNPRINTF
16855 soap_snprintf(buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
16856 #else
16857 if (len > 40 + (v ? strlen(v) : 0) + (s ? strlen(s) : 0) + (d ? strlen(d) : 0))
16858 sprintf(buf, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c, v ? v : "no subcode", s ? s : "[no reason]", d ? d : "[no detail]");
16859 else if (len > 40)
16860 sprintf(buf, "%s%d fault: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, *c);
16861 else
16862 buf[0] = '\0';
16863 #endif
16865 return buf;
16867 #endif
16868 #endif
16870 /******************************************************************************/
16871 #ifndef PALM_1
16872 #ifndef WITH_NOSTDLIB
16873 SOAP_FMAC1
16874 void
16875 SOAP_FMAC2
16876 soap_print_fault_location(struct soap *soap, FILE *fd)
16878 #ifndef WITH_LEAN
16879 int i, j, c1, c2;
16880 if (soap->error && soap->error != SOAP_STOP && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN)
16881 { i = (int)soap->bufidx - 1;
16882 if (i <= 0)
16883 i = 0;
16884 c1 = soap->buf[i];
16885 soap->buf[i] = '\0';
16886 if ((int)soap->buflen >= i + 1024)
16887 j = i + 1023;
16888 else
16889 j = (int)soap->buflen - 1;
16890 c2 = soap->buf[j];
16891 soap->buf[j] = '\0';
16892 fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
16893 if (soap->bufidx < soap->buflen)
16894 fprintf(fd, "%s\n", soap->buf + soap->bufidx);
16895 soap->buf[i] = (char)c1;
16896 soap->buf[j] = (char)c2;
16898 #endif
16900 #endif
16901 #endif
16903 /******************************************************************************/
16904 #ifndef PALM_1
16905 SOAP_FMAC1
16907 SOAP_FMAC2
16908 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
16909 { register struct soap_plugin *p;
16910 register int r;
16911 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
16912 return soap->error = SOAP_EOM;
16913 p->id = NULL;
16914 p->data = NULL;
16915 p->fcopy = NULL;
16916 p->fdelete = NULL;
16917 r = fcreate(soap, p, arg);
16918 if (!r && p->fdelete)
16919 { p->next = soap->plugins;
16920 soap->plugins = p;
16921 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
16922 return SOAP_OK;
16924 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));
16925 SOAP_FREE(soap, p);
16926 return r;
16928 #endif
16930 /******************************************************************************/
16931 #ifndef PALM_1
16932 static void *
16933 fplugin(struct soap *soap, const char *id)
16934 { register struct soap_plugin *p;
16935 for (p = soap->plugins; p; p = p->next)
16936 if (p->id == id || !strcmp(p->id, id))
16937 return p->data;
16938 return NULL;
16940 #endif
16942 /******************************************************************************/
16943 #ifndef PALM_2
16944 SOAP_FMAC1
16945 void *
16946 SOAP_FMAC2
16947 soap_lookup_plugin(struct soap *soap, const char *id)
16948 { return soap->fplugin(soap, id);
16950 #endif
16952 /******************************************************************************/
16953 #ifdef __cplusplus
16955 #endif
16957 /******************************************************************************\
16959 * C++ soap struct methods
16961 \******************************************************************************/
16963 #ifdef __cplusplus
16964 soap::soap()
16965 { soap_init(this);
16967 #endif
16969 /******************************************************************************/
16970 #ifdef __cplusplus
16971 soap::soap(soap_mode m)
16972 { soap_init1(this, m);
16974 #endif
16976 /******************************************************************************/
16977 #ifdef __cplusplus
16978 soap::soap(soap_mode im, soap_mode om)
16979 { soap_init2(this, im, om);
16981 #endif
16983 /******************************************************************************/
16984 #ifdef __cplusplus
16985 soap::soap(const struct soap& soap)
16986 { soap_copy_context(this, &soap);
16988 #endif
16990 /******************************************************************************/
16991 #ifdef __cplusplus
16992 soap::~soap()
16993 { soap_destroy(this);
16994 soap_end(this);
16995 soap_done(this);
16997 #endif
16999 /******************************************************************************/