7 gSOAP XML Web services tools
8 Copyright (C) 2000-2006, Robert van Engelen, Genivia Inc., All Rights Reserved.
9 This part of the software is released under one of the following licenses:
10 GPL, the gSOAP public license, or Genivia's license for commercial use.
11 --------------------------------------------------------------------------------
14 Wind River Systems Inc., for the following additions under gSOAP public license:
15 - vxWorks compatible (#define VXWORKS)
16 --------------------------------------------------------------------------------
19 The contents of this file are subject to the gSOAP Public License Version 1.3
20 (the "License"); you may not use this file except in compliance with the
21 License. You may obtain a copy of the License at
22 http://www.cs.fsu.edu/~engelen/soaplicense.html
23 Software distributed under the License is distributed on an "AS IS" basis,
24 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
25 for the specific language governing rights and limitations under the License.
27 The Initial Developer of the Original Code is Robert A. van Engelen.
28 Copyright (C) 2000-2006, Robert van Engelen, Genivia Inc., All Rights Reserved.
29 --------------------------------------------------------------------------------
32 This program is free software; you can redistribute it and/or modify it under
33 the terms of the GNU General Public License as published by the Free Software
34 Foundation; either version 2 of the License, or (at your option) any later
37 This program is distributed in the hope that it will be useful, but WITHOUT ANY
38 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
39 PARTICULAR PURPOSE. See the GNU General Public License for more details.
41 You should have received a copy of the GNU General Public License along with
42 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
43 Place, Suite 330, Boston, MA 02111-1307 USA
45 Author contact information:
46 engelen@genivia.com / engelen@acm.org
47 --------------------------------------------------------------------------------
48 A commercial use license is available from Genivia, Inc., contact@genivia.com
49 --------------------------------------------------------------------------------
53 Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
54 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
55 tab (the project file needs to be selected in the file view) and add
56 "wsock32.lib" to the "Object/library modules" entry
58 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
59 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
60 when locally allocated data exceeds 64K.
65 # pragma convert(819) /* EBCDIC to ASCII */
71 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.8c 2006-06-24 12:00:00 GMT")
74 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.8c 2006-06-24 12:00:00 GMT")
77 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
78 #ifndef SOAP_UNKNOWN_CHAR
79 #define SOAP_UNKNOWN_CHAR (127)
83 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
84 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
85 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
86 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
87 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
89 #define soap_blank(c) ((c) >= 0 && (c) <= 32)
90 #define soap_notblank(c) ((c) > 32)
91 #define soap_hash_ptr(p) (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1))
94 static void soap_init_logs(struct soap*);
95 static void soap_close_logfile(struct soap*, int);
96 static void soap_set_logfile(struct soap*, int, const char*);
97 static void soap_free_mht(struct soap*);
98 static void soap_track_unlink(struct soap*, const void*);
102 static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
103 static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
104 static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
108 static soap_wchar soap_char(struct soap*);
109 static soap_wchar soap_get_pi(struct soap*);
110 static int soap_isxdigit(int);
111 static void *fplugin(struct soap*, const char*);
113 static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
114 static int soap_has_copies(struct soap*, const char*, const char*);
115 static void soap_init_iht(struct soap*);
116 static void soap_free_iht(struct soap*);
117 static void soap_init_pht(struct soap*);
118 static void soap_free_pht(struct soap*);
123 static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
124 static int soap_isnumeric(struct soap*, const char*);
125 static time_t soap_timegm(struct tm*);
126 static struct soap_nlist *soap_lookup_ns(struct soap *soap, const char *tag, size_t n);
127 static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
128 static void soap_pop_ns(struct soap *soap);
129 static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
134 static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
135 static int soap_putdimefield(struct soap*, const char*, size_t);
136 static char *soap_getdimefield(struct soap*, size_t);
137 static void soap_select_mime_boundary(struct soap*);
138 static int soap_valid_mime_boundary(struct soap*);
139 static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
144 static int soap_getgziphdr(struct soap*);
148 static int ssl_init_done = 0;
149 static int ssl_auth_init(struct soap*);
150 static int ssl_verify_callback(int, X509_STORE_CTX*);
151 static int ssl_password(char*, int, int, void *);
152 /* This callback is included for future references. It should not be deleted
153 static DH *ssl_tmp_dh(SSL*, int, int);
157 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
159 static const char *soap_decode(char*, size_t, const char*, const char*);
165 static soap_wchar soap_getchunkchar(struct soap*);
166 static const char *http_error(struct soap*, int);
167 static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
168 static int http_get(struct soap*);
169 static int http_send_header(struct soap*, const char*);
170 static int http_post_header(struct soap*, const char*, const char*);
171 static int http_response(struct soap*, int, size_t);
172 static int http_parse(struct soap*);
173 static int http_parse_header(struct soap*, const char*, const char*);
179 static int fsend(struct soap*, const char*, size_t);
180 static size_t frecv(struct soap*, char*, size_t);
181 static int tcp_init(struct soap*);
182 static const char *tcp_error(struct soap*);
184 static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
186 static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
187 static int tcp_accept(struct soap*, int, struct sockaddr*, int*);
188 static int tcp_disconnect(struct soap*);
189 static int tcp_closesocket(struct soap*, SOAP_SOCKET);
190 static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
191 static const char *soap_strerror(struct soap*);
195 #if defined(PALM) && !defined(PALM_2)
196 unsigned short errno;
200 static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
201 static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
202 static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
203 static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
204 static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
208 const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
209 static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
210 static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
214 static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
215 /* Alternative indentation form for SOAP_XML_INDENT:
216 static const char soap_indent[21] = "\n ";
221 # define SOAP_CANARY (0xC0DE)
224 static const char soap_padding[4] = "\0\0\0";
225 #define SOAP_STR_PADDING (soap_padding)
226 #define SOAP_STR_EOS (soap_padding)
227 #define SOAP_NON_NULL (soap_padding)
230 static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
333 static const struct soap_code_map h_error_codes[] =
335 #ifdef HOST_NOT_FOUND
336 { HOST_NOT_FOUND, "Host not found" },
339 { TRY_AGAIN, "Try Again" },
342 { NO_RECOVERY, "No Recovery" },
345 { NO_DATA, "No Data" },
348 { NO_ADDRESS, "No Address" },
357 static const struct soap_code_map h_http_error_codes[] =
361 { 203, "Non-Authoritative Information" },
362 { 204, "No Content" },
363 { 205, "Reset Content" },
364 { 206, "Partial Content" },
365 { 300, "Multiple Choices" },
366 { 301, "Moved Permanently" },
368 { 303, "See Other" },
369 { 304, "Not Modified" },
370 { 305, "Use Proxy" },
371 { 307, "Temporary Redirect" },
372 { 400, "Bad Request" },
373 { 401, "Unauthorized" },
374 { 402, "Payment Required" },
375 { 403, "Forbidden" },
376 { 404, "Not Found" },
377 { 405, "Method Not Allowed" },
378 { 406, "Not Acceptable" },
379 { 407, "Proxy Authentication Required" },
380 { 408, "Request Time-out" },
383 { 411, "Length Required" },
384 { 412, "Precondition Failed" },
385 { 413, "Request Entity Too Large" },
386 { 414, "Request-URI Too Large" },
387 { 415, "Unsupported Media Type" },
388 { 416, "Requested range not satisfiable" },
389 { 417, "Expectation Failed" },
390 { 500, "Internal Server Error" },
391 { 501, "Not Implemented" },
392 { 502, "Bad Gateway" },
393 { 503, "Service Unavailable" },
394 { 504, "Gateway Time-out" },
395 { 505, "HTTP Version not supported" },
402 static const struct soap_code_map h_ssl_error_codes[] =
404 #define _SSL_ERROR(e) { e, #e }
405 _SSL_ERROR(SSL_ERROR_SSL),
406 _SSL_ERROR(SSL_ERROR_ZERO_RETURN),
407 _SSL_ERROR(SSL_ERROR_WANT_READ),
408 _SSL_ERROR(SSL_ERROR_WANT_WRITE),
409 _SSL_ERROR(SSL_ERROR_WANT_CONNECT),
410 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
411 _SSL_ERROR(SSL_ERROR_SYSCALL),
417 static const struct soap_code_map mime_codes[] =
418 { { SOAP_MIME_7BIT, "7bit" },
419 { SOAP_MIME_8BIT, "8bit" },
420 { SOAP_MIME_BINARY, "binary" },
421 { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
422 { SOAP_MIME_BASE64, "base64" },
423 { SOAP_MIME_IETF_TOKEN, "ietf-token" },
424 { SOAP_MIME_X_TOKEN, "x-token" },
430 static int tcp_done = 0;
433 /******************************************************************************/
437 fsend(struct soap *soap, const char *s, size_t n)
438 { register int nwritten;
439 #if defined(__cplusplus) && !defined(WITH_LEAN)
441 { soap->os->write(s, n);
442 if (soap->os->good())
448 { if (soap_valid_socket(soap->socket))
451 if (soap->send_timeout)
452 { struct timeval timeout;
454 if (soap->send_timeout > 0)
455 { timeout.tv_sec = soap->send_timeout;
459 { timeout.tv_sec = -soap->send_timeout/1000000;
460 timeout.tv_usec = -soap->send_timeout%1000000;
463 if ((int)soap->socket > FD_SETSIZE)
464 return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
467 FD_SET((SOAP_SOCKET)soap->socket, &fd);
469 { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout);
476 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
477 { soap->errnum = soap_socket_errno;
485 nwritten = SSL_write(soap->ssl, s, n);
487 nwritten = BIO_write(soap->bio, s, n);
491 if ((soap->omode & SOAP_IO_UDP))
493 nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
495 nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
496 /* retry and back-off algorithm */
497 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
499 { struct timeval timeout;
504 if ((int)soap->socket > FD_SETSIZE)
505 return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
507 if ((soap->connect_flags & SO_BROADCAST))
508 udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
510 udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
511 udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
513 { timeout.tv_sec = 0;
514 timeout.tv_usec = 1000 * udp_delay; /* ms */
516 FD_SET((SOAP_SOCKET)soap->socket, &fd);
517 select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout);
519 nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
521 nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
523 if (udp_delay > 500) /* UDP_UPPER_DELAY */
526 while (nwritten < 0 && --udp_repeat > 0);
531 #if !defined(PALM) && !defined(AS400)
532 nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
534 nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags);
540 if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
543 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN)
544 { soap->errnum = soap_socket_errno;
547 nwritten = 0; /* and call write() again */
553 nwritten = fwrite((void*)s, 1, n, stdout);
557 nwritten = fwrite(s, 1, n, soap->sendfd);
562 nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1;
565 nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
567 nwritten = write((SOAP_SOCKET)soap->sendfd, s, n);
572 { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN)
573 { soap->errnum = soap_errno;
576 nwritten = 0; /* and call write() again */
587 /******************************************************************************/
592 soap_send_raw(struct soap *soap, const char *s, size_t n)
595 if (soap->mode & SOAP_IO_LENGTH)
598 if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
599 return soap->error = soap->fpreparesend(soap, s, n);
603 if (soap->mode & SOAP_IO)
604 { register size_t i = SOAP_BUFLEN - soap->bufidx;
606 { memcpy(soap->buf + soap->bufidx, s, i);
607 soap->bufidx = SOAP_BUFLEN;
608 if (soap_flush(soap))
614 memcpy(soap->buf + soap->bufidx, s, n);
618 return soap_flush_raw(soap, s, n);
622 /******************************************************************************/
627 soap_flush(struct soap *soap)
628 { register int n = soap->bufidx;
632 if (soap->mode & SOAP_ENC_ZLIB)
633 { soap->d_stream.next_in = (Byte*)soap->buf;
634 soap->d_stream.avail_in = (unsigned int)n;
636 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
639 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in));
640 if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK)
641 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
642 return soap->error = SOAP_ZLIB_ERROR;
644 if (!soap->d_stream.avail_out)
645 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
647 soap->d_stream.next_out = (Byte*)soap->z_buf;
648 soap->d_stream.avail_out = SOAP_BUFLEN;
650 } while (soap->d_stream.avail_in);
654 return soap_flush_raw(soap, soap->buf, n);
660 /******************************************************************************/
665 soap_flush_raw(struct soap *soap, const char *s, size_t n)
666 { if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
668 if (!(t = (char*)soap_push_block(soap, n)))
669 return soap->error = SOAP_EOM;
672 if (soap->fpreparesend)
673 return soap->error = soap->fpreparesend(soap, s, n);
678 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
680 sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
681 DBGMSG(SENT, t, strlen(t));
682 if ((soap->error = soap->fsend(soap, t, strlen(t))))
684 soap->chunksize += n;
688 return soap->error = soap->fsend(soap, s, n);
692 /******************************************************************************/
697 soap_send(struct soap *soap, const char *s)
699 return soap_send_raw(soap, s, strlen(s));
704 /******************************************************************************/
710 soap_send2(struct soap *soap, const char *s1, const char *s2)
711 { if (soap_send(soap, s1))
713 return soap_send(soap, s2);
718 /******************************************************************************/
724 soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
725 { if (soap_send(soap, s1)
726 || soap_send(soap, s2))
728 return soap_send(soap, s3);
733 /******************************************************************************/
737 frecv(struct soap *soap, char *s, size_t n)
740 register int timeouts = 0;
743 #if defined(__cplusplus) && !defined(WITH_LEAN)
745 { if (soap->is->good())
746 return soap->is->read(s, n).gcount();
750 if (soap_valid_socket(soap->socket))
754 if (soap->recv_timeout)
755 { struct timeval timeout;
757 if (soap->recv_timeout > 0)
758 { timeout.tv_sec = soap->recv_timeout;
762 { timeout.tv_sec = -soap->recv_timeout/1000000;
763 timeout.tv_usec = -soap->recv_timeout%1000000;
766 if ((int)soap->socket > FD_SETSIZE)
767 { soap->error = SOAP_FD_EXCEEDED;
768 return 0; /* Hint: MUST increase FD_SETSIZE */
772 FD_SET((SOAP_SOCKET)soap->socket, &fd);
774 { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
781 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
782 { soap->errnum = soap_socket_errno;
791 r = SSL_read(soap->ssl, s, n);
794 err = SSL_get_error(soap->ssl, r);
795 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
799 { r = BIO_read(soap->bio, s, n);
808 if ((soap->omode & SOAP_IO_UDP))
809 { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
810 memset((void*)&soap->peer, 0, sizeof(soap->peer));
811 r = recvfrom((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
812 soap->peerlen = (size_t)k;
814 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
819 r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags);
821 /* CycleSyncDisplay(curStatusMsg); */
825 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN && soap_socket_errno != SOAP_EWOULDBLOCK)
826 { soap->errnum = soap_socket_errno;
831 { struct timeval timeout;
834 timeout.tv_usec = 10000;
836 if ((int)soap->socket > FD_SETSIZE)
837 { soap->error = SOAP_FD_EXCEEDED;
838 return 0; /* Hint: MUST increase FD_SETSIZE */
842 FD_SET((SOAP_SOCKET)soap->socket, &fd);
844 if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE)
845 r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout);
847 r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
849 r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
851 if (r < 0 && soap_socket_errno != SOAP_EINTR)
852 { soap->errnum = soap_socket_errno;
858 if (r < 0 && soap_socket_errno == SOAP_EINTR)
861 { soap->errnum = soap_socket_errno;
869 return fread(s, 1, n, stdin);
872 return fread(s, 1, n, soap->recvfd);
876 r = httpBlockRead(soap->rpmreqid, s, n);
879 r = read((SOAP_SOCKET)soap->recvfd, s, n);
882 soap->errnum = soap_errno;
890 /******************************************************************************/
894 soap_getchunkchar(struct soap *soap)
895 { if (soap->bufidx < soap->buflen)
896 return soap->buf[soap->bufidx++];
898 soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
899 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket));
900 DBGMSG(RECV, soap->buf, soap->buflen);
902 return soap->buf[soap->bufidx++];
908 /******************************************************************************/
912 { return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
916 /******************************************************************************/
921 soap_recv_raw(struct soap *soap)
922 { register size_t ret;
924 if (soap->mode & SOAP_ENC_ZLIB)
925 { if (soap->d_stream.next_out == Z_NULL)
927 if (soap->d_stream.avail_in || !soap->d_stream.avail_out)
929 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
930 soap->d_stream.next_out = (Byte*)soap->buf;
931 soap->d_stream.avail_out = SOAP_BUFLEN;
932 r = inflate(&soap->d_stream, Z_NO_FLUSH);
933 if (r == Z_OK || r == Z_STREAM_END)
935 soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out;
936 if (soap->zlib_in == SOAP_ZLIB_GZIP)
937 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
938 if (r == Z_STREAM_END)
939 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
940 soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
941 soap->d_stream.next_out = Z_NULL;
944 { soap->count += soap->buflen;
948 else if (r != Z_BUF_ERROR)
949 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
950 soap->d_stream.next_out = Z_NULL;
951 soap->error = SOAP_ZLIB_ERROR;
956 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
957 { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
958 soap->buflen = soap->z_buflen;
963 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
967 { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
968 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
969 DBGMSG(RECV, soap->buf, ret);
971 soap->chunksize -= ret;
974 { register soap_wchar c;
977 if (!soap->chunkbuflen)
978 { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
979 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
980 DBGMSG(RECV, soap->buf, ret);
983 return soap->ahead = EOF;
986 soap->bufidx = soap->buflen;
987 soap->buflen = soap->chunkbuflen;
988 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
989 while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
991 return soap->ahead = EOF;
994 while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
995 while ((int)c != EOF && c != '\n')
996 c = soap_getchunkchar(soap);
998 return soap->ahead = EOF;
1000 soap->chunksize = soap_strtoul(tmp, &t, 16);
1001 if (!soap->chunksize)
1002 { soap->chunkbuflen = 0;
1003 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
1004 while ((int)c != EOF && c != '\n')
1005 c = soap_getchunkchar(soap);
1006 return soap->ahead = EOF;
1008 soap->buflen = soap->bufidx + soap->chunksize;
1009 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
1010 if (soap->buflen > soap->chunkbuflen)
1011 { soap->buflen = soap->chunkbuflen;
1012 soap->chunksize -= soap->buflen - soap->bufidx;
1013 soap->chunkbuflen = 0;
1014 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
1016 else if (soap->chunkbuflen)
1017 soap->chunksize = 0;
1018 ret = soap->buflen - soap->bufidx;
1026 soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1027 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket));
1028 DBGMSG(RECV, soap->buf, ret);
1031 if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret)))
1035 if (soap->mode & SOAP_ENC_ZLIB)
1037 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
1038 soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
1039 soap->d_stream.avail_in = (unsigned int)ret;
1040 soap->d_stream.next_out = (Byte*)soap->buf;
1041 soap->d_stream.avail_out = SOAP_BUFLEN;
1042 r = inflate(&soap->d_stream, Z_NO_FLUSH);
1043 if (r == Z_OK || r == Z_STREAM_END)
1045 soap->z_buflen = soap->buflen;
1046 soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out;
1047 if (soap->zlib_in == SOAP_ZLIB_GZIP)
1048 soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
1049 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret));
1052 if (r == Z_STREAM_END)
1053 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
1054 soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
1055 soap->d_stream.next_out = Z_NULL;
1059 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:""));
1060 soap->d_stream.next_out = Z_NULL;
1061 soap->error = SOAP_ZLIB_ERROR;
1071 /******************************************************************************/
1076 soap_recv(struct soap *soap)
1079 if (soap->mode & SOAP_ENC_DIME)
1080 { if (soap->dime.buflen)
1083 unsigned char tmp[12];
1084 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
1085 soap->count += soap->dime.buflen - soap->buflen;
1086 soap->buflen = soap->dime.buflen;
1087 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
1088 for (i = -(long)soap->dime.size&3; i > 0; i--)
1090 if (soap->bufidx >= soap->buflen)
1091 if (soap_recv_raw(soap))
1094 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
1096 for (i = 12; i > 0; i--)
1097 { *s++ = soap->buf[soap->bufidx++];
1098 if (soap->bufidx >= soap->buflen)
1099 if (soap_recv_raw(soap))
1102 soap->dime.flags = tmp[0] & 0x7;
1103 soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
1104 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
1105 if (soap->dime.flags & SOAP_DIME_CF)
1106 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
1107 soap->dime.chunksize = soap->dime.size;
1108 if (soap->buflen - soap->bufidx >= soap->dime.size)
1109 { soap->dime.buflen = soap->buflen;
1110 soap->buflen = soap->bufidx + soap->dime.chunksize;
1113 soap->dime.chunksize -= soap->buflen - soap->bufidx;
1116 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
1117 soap->dime.buflen = 0;
1118 soap->dime.chunksize = 0;
1120 soap->count = soap->buflen - soap->bufidx;
1121 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
1124 if (soap->dime.chunksize)
1125 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
1126 if (soap_recv_raw(soap))
1128 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
1129 { soap->dime.buflen = soap->buflen;
1130 soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
1131 soap->buflen = soap->bufidx + soap->dime.chunksize;
1134 soap->dime.chunksize -= soap->buflen - soap->bufidx;
1135 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count));
1140 return soap_recv_raw(soap);
1144 /******************************************************************************/
1149 soap_getchar(struct soap *soap)
1150 { register soap_wchar c;
1157 return soap_get1(soap);
1161 /******************************************************************************/
1164 const struct soap_code_map*
1166 soap_code(const struct soap_code_map *map, const char *str)
1168 { while (map->string)
1169 { if (!strcmp(str, map->string)) /* case sensitive */
1178 /******************************************************************************/
1183 soap_code_int(const struct soap_code_map *map, const char *str, long other)
1185 { while (map->string)
1186 { if (!soap_tag_cmp(str, map->string)) /* case insensitive */
1195 /******************************************************************************/
1200 soap_code_str(const struct soap_code_map *map, long code)
1203 while (map->code != code && map->string)
1209 /******************************************************************************/
1214 soap_code_bits(const struct soap_code_map *map, const char *str)
1215 { register long bits = 0;
1217 { while (str && *str)
1218 { const struct soap_code_map *p;
1219 for (p = map; p->string; p++)
1220 { register size_t n = strlen(p->string);
1221 if (!strncmp(p->string, str, n) && soap_blank(str[n]))
1224 while (*str > 0 && *str <= 32)
1237 /******************************************************************************/
1242 soap_code_list(struct soap *soap, const struct soap_code_map *map, long code)
1243 { register char *t = soap->tmpbuf;
1245 { while (map->string)
1246 { if (map->code & code)
1247 { register const char *s = map->string;
1248 if (t != soap->tmpbuf)
1250 while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1252 if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1259 return soap->tmpbuf;
1263 /******************************************************************************/
1266 soap_char(struct soap *soap)
1269 register soap_wchar c;
1270 register char *s = tmp;
1271 for (i = 0; i < 7; i++)
1272 { c = soap_get1(soap);
1273 if (c == ';' || (int)c == EOF)
1279 { if (tmp[1] == 'x' || tmp[1] == 'X')
1280 return soap_strtol(tmp + 2, NULL, 16);
1281 return atol(tmp + 1);
1283 if (!strcmp(tmp, "lt"))
1285 if (!strcmp(tmp, "gt"))
1287 if (!strcmp(tmp, "amp"))
1289 if (!strcmp(tmp, "quot"))
1291 if (!strcmp(tmp, "apos"))
1294 return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
1296 return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
1301 /******************************************************************************/
1305 soap_get0(struct soap *soap)
1306 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1308 return (unsigned char)soap->buf[soap->bufidx];
1313 /******************************************************************************/
1317 soap_get1(struct soap *soap)
1318 { if (soap->bufidx >= soap->buflen && soap_recv(soap))
1320 return (unsigned char)soap->buf[soap->bufidx++];
1325 /******************************************************************************/
1330 soap_get(struct soap *soap)
1331 { register soap_wchar c;
1334 { if ((int)c != EOF)
1338 c = soap_get1(soap);
1339 while ((int)c != EOF)
1342 { c = soap_get1(soap);
1344 { c = soap_get0(soap);
1348 c = soap_get1(soap);
1351 { soap_unget(soap, ']');
1356 { soap_revget1(soap);
1365 do c = soap_get1(soap);
1366 while (soap_blank(c));
1367 if (c == '!' || c == '?' || c == '%')
1368 { register int k = 1;
1370 { c = soap_get1(soap);
1372 { do c = soap_get1(soap);
1373 while ((int)c != EOF && c != '[');
1377 c = soap_get1(soap);
1380 if (c == '-' && (c = soap_get1(soap)) == '-')
1382 { c = soap_get1(soap);
1383 if (c == '-' && (c = soap_get1(soap)) == '-')
1385 } while ((int)c != EOF);
1389 c = soap_get_pi(soap);
1390 while ((int)c != EOF)
1397 c = soap_get1(soap);
1401 c = soap_get1(soap);
1415 return soap_char(soap) | 0x80000000;
1423 /******************************************************************************/
1426 soap_get_pi(struct soap *soap)
1428 register char *s = buf;
1429 register int i = sizeof(buf);
1430 register soap_wchar c = soap_getchar(soap);
1431 /* This is a quick way to parse XML PI and we could use a callback instead to
1432 * enable applications to intercept processing instructions */
1433 while ((int)c != EOF && c != '?')
1435 { if (soap_blank(c))
1439 c = soap_getchar(soap);
1442 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
1443 if (!strncmp(buf, "xml ", 4))
1444 { s = strstr(buf, " encoding=");
1446 { if (!soap_tag_cmp(s + 11, "iso-8859-1*")
1447 || !soap_tag_cmp(s + 11, "latin1*"))
1448 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
1449 soap->mode |= SOAP_ENC_LATIN;
1451 else if (!soap_tag_cmp(s + 11, "utf-8*"))
1452 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
1453 soap->mode &= ~SOAP_ENC_LATIN;
1458 c = soap_getchar(soap);
1463 /******************************************************************************/
1469 soap_move(struct soap *soap, long n)
1470 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
1472 if ((int)soap_getchar(soap) == EOF)
1479 /******************************************************************************/
1485 soap_tell(struct soap *soap)
1486 { return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
1491 /******************************************************************************/
1496 soap_pututf8(struct soap *soap, register unsigned long c)
1498 if (c > 0 && c < 0x80)
1500 return soap_send_raw(soap, tmp, 1);
1503 if (soap->mode & SOAP_XML_CANONICAL)
1504 { register char *t = tmp;
1506 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
1509 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
1512 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
1514 { if (c < 0x04000000)
1515 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
1517 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
1518 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
1520 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
1522 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
1524 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
1526 *t++ = (char)(0x80 | (c & 0x3F));
1531 sprintf(tmp, "&#%lu;", c);
1532 return soap_send(soap, tmp);
1536 /******************************************************************************/
1541 soap_getutf8(struct soap *soap)
1542 { register soap_wchar c, c1, c2, c3, c4;
1550 if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
1552 c1 = soap_get1(soap);
1554 { soap_revget1(soap); /* doesn't look like this is UTF8 */
1559 return ((soap_wchar)(c & 0x1F) << 6) | c1;
1560 c2 = (soap_wchar)soap_get1(soap) & 0x3F;
1561 if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */
1564 return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
1565 c3 = (soap_wchar)soap_get1(soap) & 0x3F;
1567 return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
1568 c4 = (soap_wchar)soap_get1(soap) & 0x3F;
1570 return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
1571 return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
1575 /******************************************************************************/
1580 soap_puthex(struct soap *soap, const unsigned char *s, int n)
1584 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1585 { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
1590 for (i = 0; i < n; i++)
1591 { register int m = *s++;
1592 d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
1594 d[1] = (char)(m + (m > 9 ? '7' : '0'));
1595 if (soap_send_raw(soap, d, 2))
1602 /******************************************************************************/
1607 soap_gethex(struct soap *soap, int *n)
1610 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1611 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1612 return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
1620 if (soap_append_lab(soap, NULL, 0))
1622 s = soap->labbuf + soap->labidx;
1623 k = soap->lablen - soap->labidx;
1624 soap->labidx = soap->lablen;
1625 for (i = 0; i < k; i++)
1626 { register char d1, d2;
1627 register soap_wchar c;
1629 if (soap_isxdigit(c))
1632 if (soap_isxdigit(c))
1635 { soap->error = SOAP_TYPE;
1641 soap_unget(soap, c);
1643 *n = (int)(soap->lablen - k + i);
1644 p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
1646 memcpy(p, soap->labbuf, soap->lablen - k + i);
1649 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1653 if (soap_new_block(soap))
1657 register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN);
1659 { soap_end_block(soap);
1662 for (i = 0; i < SOAP_BLKLEN; i++)
1663 { register char d1, d2;
1664 register soap_wchar c = soap_get(soap);
1665 if (soap_isxdigit(c))
1668 if (soap_isxdigit(c))
1671 { soap_end_block(soap);
1672 soap->error = SOAP_TYPE;
1678 soap_unget(soap, c);
1680 *n = soap_size_block(soap, i);
1681 p = (unsigned char*)soap_save_block(soap, NULL, 0);
1684 *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1691 /******************************************************************************/
1696 soap_putbase64(struct soap *soap, const unsigned char *s, int n)
1698 register unsigned long m;
1703 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1704 { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
1709 for (; n > 2; n -= 3, s += 3)
1711 m = (m << 8) | s[1];
1712 m = (m << 8) | s[2];
1713 for (i = 4; i > 0; m >>= 6)
1714 d[--i] = soap_base64o[m & 0x3F];
1715 if (soap_send_raw(soap, d, 4))
1720 for (i = 0; i < n; i++)
1721 m = (m << 8) | *s++;
1724 for (i++; i > 0; m >>= 6)
1725 d[--i] = soap_base64o[m & 0x3F];
1726 for (i = 3; i > n; i--)
1728 if (soap_send_raw(soap, d, 4))
1735 /******************************************************************************/
1740 soap_getbase64(struct soap *soap, int *n, int malloc_flag)
1743 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1744 { soap->dom->data = soap_string_in(soap, 0, -1, -1);
1745 return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
1751 { register int i, k;
1753 if (soap_append_lab(soap, NULL, 2))
1755 s = soap->labbuf + soap->labidx;
1756 k = soap->lablen - soap->labidx;
1757 soap->labidx = 3 * (soap->lablen / 3);
1760 for (i = 0; i < k - 2; i += 3)
1761 { register unsigned long m = 0;
1764 { register soap_wchar c = soap_get(soap);
1765 if (c == '=' || c < 0)
1769 *s++ = (char)((m >> 4) & 0xFF);
1773 *s++ = (char)((m >> 10) & 0xFF);
1774 *s++ = (char)((m >> 2) & 0xFF);
1778 *n = (int)(soap->lablen - k + i);
1779 p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i);
1781 memcpy(p, soap->labbuf, soap->lablen - k + i);
1783 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1786 soap_unget(soap, c);
1790 if (c >= 0 && c <= 79)
1791 { m = (m << 6) + soap_base64i[c];
1795 *s++ = (char)((m >> 16) & 0xFF);
1796 *s++ = (char)((m >> 8) & 0xFF);
1797 *s++ = (char)(m & 0xFF);
1801 if (soap_new_block(soap))
1805 register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
1807 { soap_end_block(soap);
1810 for (i = 0; i < SOAP_BLKLEN; i++)
1811 { register unsigned long m = 0;
1814 { register soap_wchar c = soap_get(soap);
1815 if (c == '=' || c < 0)
1820 *s++ = (char)((m >> 4) & 0xFF);
1824 *s++ = (char)((m >> 10) & 0xFF);
1825 *s++ = (char)((m >> 2) & 0xFF);
1829 *n = (int)soap_size_block(soap, i);
1830 p = (unsigned char*)soap_save_block(soap, NULL, 0);
1832 { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1835 soap_unget(soap, c);
1839 if (c >= 0 && c <= 79)
1840 { m = (m << 6) + soap_base64i[c];
1844 *s++ = (char)((m >> 16) & 0xFF);
1845 *s++ = (char)((m >> 8) & 0xFF);
1846 *s++ = (char)(m & 0xFF);
1853 /******************************************************************************/
1859 soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
1860 { /* Check MTOM xop:Include element (within hex/base64Binary) */
1861 /* TODO: this code to be obsoleted with new import/xop.h conventions */
1862 int body = soap->body; /* should save type too? */
1863 if (!soap_peek_element(soap))
1864 { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href)
1865 { if (soap_dime_forward(soap, ptr, size, id, type, options))
1868 if (soap->body && soap_element_end_in(soap, NULL))
1877 /******************************************************************************/
1883 soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
1884 { struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
1887 *id = soap_strdup(soap, soap->href);
1891 return soap->error = SOAP_EOM;
1892 xp->next = soap->xlist;
1897 xp->options = options;
1904 /******************************************************************************/
1909 soap_strdup(struct soap *soap, const char *s)
1911 if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
1917 /******************************************************************************/
1922 soap_new_block(struct soap *soap)
1923 { struct soap_blist *p;
1924 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
1925 if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
1927 p->next = soap->blist;
1935 /******************************************************************************/
1940 soap_push_block(struct soap *soap, size_t n)
1942 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n));
1943 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
1944 { soap->error = SOAP_EOM;
1947 *(char**)p = soap->blist->ptr;
1948 *(size_t*)(p + sizeof(char*)) = n;
1949 soap->blist->ptr = p;
1950 soap->blist->size += n;
1951 return p + sizeof(char*) + sizeof(size_t);
1955 /******************************************************************************/
1960 soap_pop_block(struct soap *soap)
1962 if (!soap->blist->ptr)
1964 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
1965 p = soap->blist->ptr;
1966 soap->blist->size -= *(size_t*)(p + sizeof(char*));
1967 soap->blist->ptr = *(char**)p;
1972 /******************************************************************************/
1973 #ifndef WITH_NOIDREF
1976 soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
1978 register struct soap_ilist *ip;
1979 register struct soap_flist *fp;
1981 register struct soap_xlist *xp;
1983 register void *p, **q;
1984 for (i = 0; i < SOAP_IDHASH; i++)
1985 { for (ip = soap->iht[i]; ip; ip = ip->next)
1986 { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
1987 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
1988 ip->ptr = (char*)ip->ptr + (p1-p2);
1990 for (q = &ip->link; q; q = (void**)p)
1992 if (p && (char*)p >= start && (char*)p < end)
1993 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
1994 *q = (char*)p + (p1-p2);
1997 for (q = &ip->copy; q; q = (void**)p)
1999 if (p && (char*)p >= start && (char*)p < end)
2000 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
2001 *q = (char*)p + (p1-p2);
2004 for (fp = ip->flist; fp; fp = fp->next)
2005 { if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
2006 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
2007 fp->ptr = (char*)fp->ptr + (p1-p2);
2013 for (xp = soap->xlist; xp; xp = xp->next)
2014 { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
2015 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2)));
2016 xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
2017 xp->size = (int*)((char*)xp->size + (p1-p2));
2018 xp->type = (char**)((char*)xp->type + (p1-p2));
2019 xp->options = (char**)((char*)xp->options + (p1-p2));
2027 /******************************************************************************/
2028 #ifndef WITH_NOIDREF
2031 soap_has_copies(struct soap *soap, register const char *start, register const char *end)
2033 register struct soap_ilist *ip;
2034 register struct soap_flist *fp;
2035 register const char *p;
2036 for (i = 0; i < SOAP_IDHASH; i++)
2037 { for (ip = soap->iht[i]; ip; ip = ip->next)
2038 { for (p = (const char*)ip->copy; p; p = *(const char**)p)
2039 if (p >= start && p < end)
2041 for (fp = ip->flist; fp; fp = fp->next)
2042 if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
2051 /******************************************************************************/
2052 #ifndef WITH_NOIDREF
2057 soap_resolve(struct soap *soap)
2059 register struct soap_ilist *ip;
2060 register struct soap_flist *fp;
2062 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
2063 for (i = 0; i < SOAP_IDHASH; i++)
2064 { for (ip = soap->iht[i]; ip; ip = ip->next)
2066 { register void *p, **q, *r;
2067 q = (void**)ip->link;
2070 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
2074 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
2078 else if (*ip->id == '#')
2079 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
2080 strcpy(soap->id, ip->id + 1);
2081 return soap->error = SOAP_MISSING_ID;
2087 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
2088 for (i = 0; i < SOAP_IDHASH; i++)
2089 { for (ip = soap->iht[i]; ip; ip = ip->next)
2090 { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
2092 { register void *p, **q = (void**)ip->copy;
2093 DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
2096 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
2098 memcpy(q, ip->ptr, ip->size);
2103 for (fp = ip->flist; fp; fp = ip->flist)
2104 { register unsigned int k = fp->level;
2105 register void *p = ip->ptr;
2106 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id));
2107 while (ip->level < k)
2108 { register void **q = (void**)soap_malloc(soap, sizeof(void*));
2112 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
2117 fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2119 soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2120 ip->flist = fp->next;
2121 SOAP_FREE(soap, fp);
2129 for (i = 0; i < SOAP_IDHASH; i++)
2130 { for (ip = soap->iht[i]; ip; ip = ip->next)
2131 { if (ip->copy || ip->flist)
2132 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id));
2137 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
2143 /******************************************************************************/
2148 soap_size_block(struct soap *soap, size_t n)
2149 { if (soap->blist->ptr)
2150 { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n;
2151 *(size_t*)(soap->blist->ptr + sizeof(char*)) = n;
2153 return soap->blist->size;
2157 /******************************************************************************/
2162 soap_first_block(struct soap *soap)
2164 p = soap->blist->ptr;
2167 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
2175 soap->blist->ptr = r;
2176 return r + sizeof(char*) + sizeof(size_t);
2180 /******************************************************************************/
2185 soap_next_block(struct soap *soap)
2187 p = soap->blist->ptr;
2189 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
2190 soap->blist->ptr = *(char**)p;
2192 if (soap->blist->ptr)
2193 return soap->blist->ptr + sizeof(char*) + sizeof(size_t);
2199 /******************************************************************************/
2204 soap_block_size(struct soap *soap)
2205 { return *(size_t*)(soap->blist->ptr + sizeof(char*));
2209 /******************************************************************************/
2214 soap_end_block(struct soap *soap)
2215 { struct soap_blist *bp;
2219 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
2220 for (p = bp->ptr; p; p = q)
2224 soap->blist = bp->next;
2225 SOAP_FREE(soap, bp);
2227 DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
2231 /******************************************************************************/
2236 soap_save_block(struct soap *soap, char *p, int flag)
2237 { register size_t n;
2238 register char *q, *s;
2239 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p));
2240 if (soap->blist->size)
2242 p = (char*)soap_malloc(soap, soap->blist->size);
2244 { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap))
2245 { n = soap_block_size(soap);
2246 #ifndef WITH_NOIDREF
2248 soap_update_ptrs(soap, q, q + n, s, q);
2250 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
2256 soap->error = SOAP_EOM;
2258 soap_end_block(soap);
2263 /******************************************************************************/
2268 soap_putsize(struct soap *soap, const char *type, int size)
2269 { return soap_putsizes(soap, type, &size, 1);
2273 /******************************************************************************/
2278 soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
2279 { return soap_putsizesoffsets(soap, type, size, NULL, dim);
2283 /******************************************************************************/
2288 soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
2292 if (soap->version == 2)
2293 { sprintf(soap->type, "%s[%d", type, size[0]);
2294 for (i = 1; i < dim; i++)
2295 sprintf(soap->type + strlen(soap->type), " %d", size[i]);
2299 { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
2300 for (i = 1; i < dim; i++)
2301 sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
2304 { sprintf(soap->type, "%s[%d", type, size[0]);
2305 for (i = 1; i < dim; i++)
2306 sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
2308 strcat(soap->type, "]");
2314 /******************************************************************************/
2319 soap_putoffset(struct soap *soap, int offset)
2320 { return soap_putoffsets(soap, &offset, 1);
2324 /******************************************************************************/
2329 soap_putoffsets(struct soap *soap, const int *offset, int dim)
2331 sprintf(soap->arrayOffset, "[%d", offset[0]);
2332 for (i = 1; i < dim; i++)
2333 sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
2334 strcat(soap->arrayOffset, "]");
2335 return soap->arrayOffset;
2339 /******************************************************************************/
2344 soap_size(const int *size, int dim)
2345 { register int i, n = size[0];
2346 for (i = 1; i < dim; i++)
2352 /******************************************************************************/
2357 soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
2358 { register int i, j = 0;
2360 for (i = 0; i < dim && attr && *attr; i++)
2363 j += offset[i] = (int)atol(attr);
2364 attr = strchr(attr, ',');
2367 for (i = 0; i < dim && attr && *attr; i++)
2370 j += (int)atol(attr);
2371 attr = strchr(attr, ',');
2377 /******************************************************************************/
2382 soap_getsize(const char *attr1, const char *attr2, int *j)
2383 { register int n, k;
2392 { k = (int)soap_strtol(attr1, &s, 10);
2394 if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
2396 attr1 = strchr(s, ',');
2398 attr1 = strchr(s, ' ');
2399 if (attr2 && *attr2)
2402 k = (int)soap_strtol(attr2, &s, 10);
2416 /******************************************************************************/
2421 soap_getsizes(const char *attr, int *size, int dim)
2422 { register int i, k, n;
2428 { for (i = i-1; i >= 0; i--)
2429 if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
2431 k = (int)atol(attr + i + 1);
2432 n *= size[--dim] = k;
2433 if (k < 0 || n > SOAP_MAXARRAYSIZE)
2435 } while (i >= 0 && attr[i] != '[');
2440 /******************************************************************************/
2445 soap_getposition(const char *attr, int *pos)
2446 { register int i, n;
2452 { pos[n++] = (int)atol(attr + i);
2453 while (attr[i] && attr[i] != ',' && attr[i] != ']')
2457 } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
2462 /******************************************************************************/
2467 soap_push_namespace(struct soap *soap, const char *id, const char *ns)
2468 { register struct soap_nlist *np;
2469 register struct Namespace *p;
2470 register short i = -1;
2471 register size_t n, k;
2474 p = soap->local_namespaces;
2476 { for (i = 0; p->id; p++, i++)
2477 { if (p->ns && !strcmp(ns, p->ns))
2479 { SOAP_FREE(soap, p->out);
2485 { if (!strcmp(ns, p->out))
2489 { if (!soap_tag_cmp(ns, p->in))
2490 { if ((p->out = (char*)SOAP_MALLOC(soap, k)))
2501 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
2503 return soap->error = SOAP_EOM;
2504 np->next = soap->nlist;
2506 np->level = soap->level;
2509 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
2511 { np->ns = np->id + n + 1;
2513 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
2517 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
2523 /******************************************************************************/
2528 soap_pop_namespace(struct soap *soap)
2529 { register struct soap_nlist *np;
2530 while (soap->nlist && soap->nlist->level >= soap->level)
2531 { np = soap->nlist->next;
2532 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id));
2533 SOAP_FREE(soap, soap->nlist);
2539 /******************************************************************************/
2544 soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2)
2545 { register struct soap_nlist *np = soap->nlist;
2546 while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
2550 || (soap->local_namespaces[np->index].id
2551 && (strncmp(soap->local_namespaces[np->index].id, id2, n2)
2552 || soap->local_namespaces[np->index].id[n2])))
2553 return SOAP_NAMESPACE;
2556 if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2))
2558 return SOAP_SYNTAX_ERROR;
2562 /******************************************************************************/
2567 soap_current_namespace(struct soap *soap, const char *tag)
2568 { register struct soap_nlist *np;
2569 register const char *s;
2571 if (!(s = strchr(tag, ':')))
2572 { while (np && *np->id) /* find default namespace, if present */
2576 { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
2579 soap->error = SOAP_NAMESPACE;
2582 { if (np->index >= 0)
2583 return soap->namespaces[np->index].ns;
2585 return soap_strdup(soap, np->ns);
2591 /******************************************************************************/
2596 soap_tag_cmp(const char *s, const char *t)
2598 { register int c1 = *s;
2599 register int c2 = *t;
2600 if (!c1 || c1 == '"')
2604 { if (c1 >= 'A' && c1 <= 'Z')
2606 if (c2 >= 'A' && c2 <= 'Z')
2615 if (c2 >= 'A' && c2 <= 'Z')
2619 if (!c1 || c1 == '"')
2621 if (c1 >= 'A' && c1 <= 'Z')
2623 if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
2633 if (*t == '*' && !t[1])
2639 /******************************************************************************/
2644 soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
2645 { register const char *s, *t;
2646 if (!tag1 || !tag2 || !*tag2)
2648 s = strchr(tag1, ':');
2649 t = strchr(tag2, ':');
2652 { if (t[1] && SOAP_STRCMP(s + 1, t + 1))
2653 return SOAP_TAG_MISMATCH;
2654 if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))
2655 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2656 return SOAP_TAG_MISMATCH;
2659 else if (SOAP_STRCMP(tag1, t + 1))
2660 return SOAP_TAG_MISMATCH;
2661 else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2))
2662 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2663 return SOAP_TAG_MISMATCH;
2665 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
2669 { if (SOAP_STRCMP(s + 1, tag2))
2670 return SOAP_TAG_MISMATCH;
2672 else if (SOAP_STRCMP(tag1, tag2))
2673 return SOAP_TAG_MISMATCH;
2674 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
2679 /******************************************************************************/
2684 soap_match_array(struct soap *soap, const char *type)
2685 { if (*soap->arrayType)
2686 if (soap_match_tag(soap, soap->arrayType, type)
2687 && soap_match_tag(soap, soap->arrayType, "xsd:anyType")
2688 && soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
2690 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
2691 return SOAP_TAG_MISMATCH;
2697 /******************************************************************************\
2701 \******************************************************************************/
2704 /******************************************************************************/
2710 { unsigned char buf[4];
2713 RAND_pseudo_bytes(buf, 4);
2718 /******************************************************************************/
2723 soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
2725 soap->keyfile = keyfile;
2726 soap->password = password;
2727 soap->cafile = cafile;
2728 soap->capath = capath;
2729 soap->dhfile = dhfile;
2730 soap->rsa = (dhfile == NULL);
2731 soap->randfile = randfile;
2732 soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION);
2733 if (!(err = soap->fsslauth(soap)))
2735 SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid));
2741 /******************************************************************************/
2746 soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile)
2747 { soap->keyfile = keyfile;
2748 soap->password = password;
2749 soap->cafile = cafile;
2750 soap->capath = capath;
2751 soap->dhfile = NULL;
2753 soap->randfile = randfile;
2754 soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION);
2755 return soap->fsslauth(soap);
2759 /******************************************************************************/
2765 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
2767 { ssl_init_done = 1;
2770 SSL_load_error_strings();
2772 if (!RAND_load_file("/dev/urandom", 1024))
2774 RAND_seed(buf, sizeof(buf));
2775 while (!RAND_status())
2777 RAND_seed(&r, sizeof(int));
2784 /******************************************************************************/
2789 soap_ssl_error(struct soap *soap, int ret)
2790 { int err = SSL_get_error(soap->ssl, ret);
2791 const char *msg = soap_code_str(h_ssl_error_codes, err);
2793 strcpy(soap->msgbuf, msg);
2795 return ERR_error_string(err, soap->msgbuf);
2796 if (ERR_peek_error())
2798 strcat(soap->msgbuf, "\n");
2799 while ((r = ERR_get_error()))
2800 ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
2805 strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
2808 sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
2812 return soap->msgbuf;
2816 /******************************************************************************/
2819 ssl_password(char *buf, int num, int rwflag, void *userdata)
2820 { if (num < (int)strlen((char*)userdata) + 1)
2822 return strlen(strcpy(buf, (char*)userdata));
2826 /******************************************************************************/
2827 /* This callback is included for future references. It should not be deleted
2830 ssl_tmp_dh(SSL *ssl, int is_export, int keylength)
2831 { static DH *dh512 = NULL;
2832 static DH *dh1024 = NULL;
2837 { BIO *bio = BIO_new_file("dh512.pem", "r");
2839 { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2848 { BIO *bio = BIO_new_file("dh1024.pem", "r");
2850 { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2861 /******************************************************************************/
2864 ssl_auth_init(struct soap *soap)
2865 { if (!ssl_init_done)
2868 { if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
2869 return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
2872 { if (!RAND_load_file(soap->randfile, -1))
2873 return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
2875 if (soap->cafile || soap->capath)
2876 { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
2877 return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR);
2878 if (soap->cafile && soap->require_client_auth)
2879 SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
2881 if (!SSL_CTX_set_default_verify_paths(soap->ctx))
2882 return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
2885 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
2886 return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
2888 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
2889 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
2891 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
2892 return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
2894 /* Suggested alternative approach to check cafile first before the key file:
2896 { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
2897 SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
2899 if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
2900 { if (soap->keyfile)
2901 { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
2902 return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR);
2903 if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
2904 return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
2909 { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
2910 if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
2913 return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
2917 else if (soap->dhfile)
2920 bio = BIO_new_file(soap->dhfile, "r");
2922 return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
2923 dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2925 if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
2928 return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
2932 SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);
2933 SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify);
2934 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
2935 SSL_CTX_set_verify_depth(soap->ctx, 1);
2937 SSL_CTX_set_verify_depth(soap->ctx, 9);
2943 /******************************************************************************/
2946 ssl_verify_callback(int ok, X509_STORE_CTX *store)
2951 X509 *cert = X509_STORE_CTX_get_current_cert(store);
2952 fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store)));
2953 X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
2954 fprintf(stderr, "certificate issuer %s\n", data);
2955 X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
2956 fprintf(stderr, "certificate subject %s\n", data);
2959 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
2964 /******************************************************************************/
2969 soap_ssl_accept(struct soap *soap)
2972 if (!soap_valid_socket(soap->socket))
2973 return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
2974 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
2975 return SOAP_INVALID_SOCKET;
2977 { soap->ssl = SSL_new(soap->ctx);
2979 return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
2982 SSL_clear(soap->ssl);
2983 soap->imode |= SOAP_ENC_SSL;
2984 soap->omode |= SOAP_ENC_SSL;
2986 { u_long nonblocking = 1;
2987 ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking);
2989 #elif defined(VXWORKS)
2990 { u_long nonblocking = 1;
2991 ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&nonblocking);
2994 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK);
2996 bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE);
2997 SSL_set_bio(soap->ssl, bio, bio);
2998 i = 100; /* 100 * 0.1 ms retries */
2999 while ((r = SSL_accept(soap->ssl)) <= 0)
3000 { int err = SSL_get_error(soap->ssl, r);
3001 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
3002 { struct timeval timeout;
3007 timeout.tv_usec = 100000;
3009 if ((int)soap->socket > FD_SETSIZE)
3010 return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
3013 FD_SET((SOAP_SOCKET)soap->socket, &fd);
3014 r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout);
3015 if (r < 0 && soap_socket_errno != SOAP_EINTR)
3016 { soap->errnum = soap_socket_errno;
3021 { soap->errnum = err;
3026 { u_long blocking = 0;
3027 ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
3029 #elif defined(VXWORKS)
3030 { u_long blocking = 0;
3031 ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&blocking);
3034 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
3037 { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3038 soap_closesock(soap);
3039 return SOAP_SSL_ERROR;
3041 if (soap->require_client_auth)
3044 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3045 { soap_closesock(soap);
3046 return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR);
3048 peer = SSL_get_peer_certificate(soap->ssl);
3050 { soap_closesock(soap);
3051 return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
3059 /******************************************************************************/
3060 #endif /* WITH_OPENSSL */
3062 /******************************************************************************/
3066 tcp_init(struct soap *soap)
3067 { soap->errmode = 1;
3073 if (WSAStartup(MAKEWORD(1, 1), &w))
3083 /******************************************************************************/
3088 soap_done(struct soap *soap)
3093 if (soap_check_state(soap))
3097 { struct soap_clist *p = soap->clist->next;
3098 SOAP_FREE(soap, soap->clist);
3101 soap->keep_alive = 0; /* to force close the socket */
3102 soap_closesock(soap);
3104 soap_free_cookies(soap);
3106 while (soap->plugins)
3107 { register struct soap_plugin *p = soap->plugins->next;
3108 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
3109 if (soap->plugins->fcopy || soap->state == SOAP_INIT)
3110 soap->plugins->fdelete(soap, soap->plugins);
3111 SOAP_FREE(soap, soap->plugins);
3114 soap->fplugin = fplugin;
3116 soap->fpost = http_post;
3117 soap->fget = http_get;
3119 soap->fposthdr = http_post_header;
3120 soap->fresponse = http_response;
3121 soap->fparse = http_parse;
3122 soap->fparsehdr = http_parse_header;
3124 soap->fheader = NULL;
3127 soap->fresolve = tcp_gethost;
3129 soap->fresolve = NULL;
3131 soap->faccept = tcp_accept;
3132 soap->fopen = tcp_connect;
3133 soap->fclose = tcp_disconnect;
3134 soap->fclosesocket = tcp_closesocket;
3135 soap->fshutdownsocket = tcp_shutdownsocket;
3136 soap->fsend = fsend;
3137 soap->frecv = frecv;
3138 soap->fpoll = soap_poll;
3141 soap->fclose = NULL;
3145 soap->fprepareinit = NULL;
3146 soap->fpreparesend = NULL;
3147 soap->fpreparerecv = NULL;
3148 soap->fpreparefinal = NULL;
3150 soap->fseterror = NULL;
3151 soap->fignore = NULL;
3152 soap->fserveloop = NULL;
3155 { SSL_SESSION_free(soap->session);
3156 soap->session = NULL;
3159 if (soap->state == SOAP_INIT)
3160 { if (soap_valid_socket(soap->master))
3161 { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
3162 soap->master = SOAP_INVALID_SOCKET;
3166 { SSL_CTX_free(soap->ctx);
3172 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
3173 for (i = 0; i < SOAP_MAXLOGS; i++)
3174 { if (soap->logfile[i])
3175 { SOAP_FREE(soap, (void*)soap->logfile[i]);
3176 soap->logfile[i] = NULL;
3178 soap_close_logfile(soap, i);
3180 soap_free_mht(soap);
3186 /******************************************************************************/
3192 soap_cleanup(struct soap *soap)
3204 /******************************************************************************/
3208 tcp_error(struct soap *soap)
3209 { register const char *msg = NULL;
3210 switch (soap->errmode)
3212 msg = soap_strerror(soap);
3215 msg = "WSAStartup failed";
3220 msg = soap_code_str(h_error_codes, soap->errnum);
3223 { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
3233 /******************************************************************************/
3237 http_error(struct soap *soap, int status)
3238 { register const char *msg = SOAP_STR_EOS;
3240 msg = soap_code_str(h_http_error_codes, status);
3249 /******************************************************************************/
3254 tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
3255 { soap_int32 iadd = -1;
3256 struct hostent hostent, *host = &hostent;
3259 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3260 iadd = inet_addr((char*)addr);
3262 #if defined(_AIXVERSION_431) || defined(TRU64)
3263 struct hostent_data ht_data;
3266 iadd = inet_addr((void*)addr);
3268 iadd = inet_addr(addr);
3272 { memcpy(inaddr, &iadd, sizeof(iadd));
3275 #if defined(__GLIBC__)
3276 if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
3278 #elif defined(_AIXVERSION_431) || defined(TRU64)
3279 memset((void*)&ht_data, 0, sizeof(ht_data));
3280 if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
3282 soap->errnum = h_errno;
3284 #elif defined(HAVE_GETHOSTBYNAME_R)
3285 host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
3286 #elif defined(VXWORKS)
3287 /* If the DNS resolver library resolvLib has been configured in the vxWorks
3288 * image, a query for the host IP address is sent to the DNS server, if the
3289 * name was not found in the local host table. */
3290 hostint = hostGetByName((char*)addr);
3291 if (hostint == ERROR)
3293 soap->errnum = soap_errno;
3297 if (!(host = gethostbyname((void*)addr)))
3298 soap->errnum = h_errno;
3300 if (!(host = gethostbyname(addr)))
3301 soap->errnum = h_errno;
3305 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
3309 inaddr->s_addr = hostint;
3311 memcpy(inaddr, host->h_addr, host->h_length);
3319 /******************************************************************************/
3323 tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
3326 struct addrinfo hints, *res, *ressave;
3331 int len = SOAP_BUFLEN;
3334 if (soap_valid_socket(soap->socket))
3335 soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
3336 soap->socket = SOAP_INVALID_SOCKET;
3339 soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
3340 return SOAP_INVALID_SOCKET;
3344 memset((void*)&hints, 0, sizeof(hints));
3345 hints.ai_family = PF_UNSPEC;
3347 if ((soap->omode & SOAP_IO_UDP))
3348 hints.ai_socktype = SOCK_DGRAM;
3351 hints.ai_socktype = SOCK_STREAM;
3353 if (soap->proxy_host)
3354 err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
3356 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
3358 { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
3359 return SOAP_INVALID_SOCKET;
3363 fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol);
3367 if ((soap->omode & SOAP_IO_UDP))
3368 fd = (int)socket(AF_INET, SOCK_DGRAM, 0);
3371 fd = (int)socket(AF_INET, SOCK_STREAM, 0);
3374 { soap->errnum = soap_socket_errno;
3375 soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
3376 return SOAP_INVALID_SOCKET;
3378 #ifdef SOCKET_CLOSE_ON_EXEC
3381 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
3384 fcntl(fd, F_SETFD, 1);
3388 if (soap->connect_flags == SO_LINGER)
3389 { struct linger linger;
3390 memset((void*)&linger, 0, sizeof(linger));
3392 linger.l_linger = 0;
3393 if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
3394 { soap->errnum = soap_socket_errno;
3395 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
3396 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3397 return SOAP_INVALID_SOCKET;
3400 else if (soap->connect_flags && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
3401 { soap->errnum = soap_socket_errno;
3402 soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
3403 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3404 return SOAP_INVALID_SOCKET;
3406 if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
3407 { soap->errnum = soap_socket_errno;
3408 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
3409 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3410 return SOAP_INVALID_SOCKET;
3412 if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
3413 { soap->errnum = soap_socket_errno;
3414 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3415 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3416 return SOAP_INVALID_SOCKET;
3418 if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
3419 { soap->errnum = soap_socket_errno;
3420 soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3421 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3422 return SOAP_INVALID_SOCKET;
3425 if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
3426 { soap->errnum = soap_socket_errno;
3427 soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
3428 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3429 return SOAP_INVALID_SOCKET;
3433 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
3435 soap->peerlen = sizeof(soap->peer);
3436 memset((void*)&soap->peer, 0, sizeof(soap->peer));
3437 soap->peer.sin_family = AF_INET;
3439 if (soap->proxy_host)
3440 { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
3441 { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3442 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3443 return SOAP_INVALID_SOCKET;
3445 soap->peer.sin_port = htons((short)soap->proxy_port);
3448 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
3449 { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3450 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3451 return SOAP_INVALID_SOCKET;
3453 soap->peer.sin_port = htons((short)port);
3456 if ((soap->omode & SOAP_IO_UDP))
3460 if (soap->connect_timeout)
3462 { u_long nonblocking = 1;
3463 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
3465 #elif defined(VXWORKS)
3466 { u_long nonblocking = 1;
3467 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */
3470 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
3474 { u_long blocking = 0;
3475 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
3477 #elif defined(VXWORKS)
3478 { u_long blocking = 0;
3479 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
3482 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
3488 if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen))
3490 if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
3494 if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK))
3495 { struct timeval timeout;
3498 if (soap->connect_timeout > 0)
3499 { timeout.tv_sec = soap->connect_timeout;
3500 timeout.tv_usec = 0;
3503 { timeout.tv_sec = -soap->connect_timeout/1000000;
3504 timeout.tv_usec = -soap->connect_timeout%1000000;
3507 if ((int)soap->socket > FD_SETSIZE)
3508 { soap->error = SOAP_FD_EXCEEDED;
3509 return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
3513 FD_SET((SOAP_SOCKET)fd, &fds);
3515 { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout);
3520 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
3521 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3522 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3523 return SOAP_INVALID_SOCKET;
3525 if (soap_socket_errno != SOAP_EINTR)
3526 { soap->errnum = soap_socket_errno;
3527 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3528 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3529 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3530 return SOAP_INVALID_SOCKET;
3533 k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
3534 if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
3536 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3537 soap->errnum = soap_socket_errno;
3538 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3539 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3540 return SOAP_INVALID_SOCKET;
3546 { res = res->ai_next;
3547 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3552 if (soap_socket_errno != SOAP_EINTR)
3553 { soap->errnum = soap_socket_errno;
3554 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3555 soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3556 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3557 return SOAP_INVALID_SOCKET;
3564 soap->peerlen = 0; /* IPv6: already connected so use send() */
3565 freeaddrinfo(ressave);
3568 if (soap->connect_timeout)
3570 { u_long blocking = 0;
3571 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
3573 #elif defined(VXWORKS)
3574 { u_long blocking = 0;
3575 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
3578 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
3582 soap->imode &= ~SOAP_ENC_SSL;
3583 soap->omode &= ~SOAP_ENC_SSL;
3584 if (!soap_tag_cmp(endpoint, "https:*"))
3589 if (soap->proxy_host)
3590 { unsigned int k = soap->omode; /* make sure we only parse HTTP */
3591 size_t n = soap->count; /* save the content length */
3592 char *userid, *passwd;
3593 soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
3594 soap->omode |= SOAP_IO_BUFFER;
3595 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n"));
3596 sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version);
3597 if (soap_begin_send(soap)
3598 || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
3599 { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3600 return SOAP_INVALID_SOCKET;
3603 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
3604 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
3605 strcpy(soap->tmpbuf, "Basic ");
3606 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
3607 if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
3608 { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3613 if ((soap->error = soap->fposthdr(soap, NULL, NULL))
3614 || soap_flush(soap))
3615 { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3616 return SOAP_INVALID_SOCKET;
3620 soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
3621 userid = soap->userid; /* preserve */
3622 passwd = soap->passwd; /* preserve */
3623 if ((soap->error = soap->fparse(soap)))
3624 { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3625 return SOAP_INVALID_SOCKET;
3627 soap->userid = userid; /* restore */
3628 soap->passwd = passwd; /* restore */
3629 soap->imode = k; /* restore */
3630 soap->count = n; /* restore */
3631 if (soap_begin_send(soap))
3632 { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3633 return SOAP_INVALID_SOCKET;
3636 if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
3637 { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
3638 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3639 return SOAP_INVALID_SOCKET;
3641 soap->ssl = SSL_new(soap->ctx);
3643 { soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3644 soap->error = SOAP_SSL_ERROR;
3645 return SOAP_INVALID_SOCKET;
3648 { if (!strcmp(soap->session_host, host) && soap->session_port == port)
3649 SSL_set_session(soap->ssl, soap->session);
3650 SSL_SESSION_free(soap->session);
3651 soap->session = NULL;
3653 soap->imode |= SOAP_ENC_SSL;
3654 soap->omode |= SOAP_ENC_SSL;
3655 bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE);
3656 SSL_set_bio(soap->ssl, bio, bio);
3658 if (soap->connect_timeout)
3660 { u_long nonblocking = 1;
3661 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking);
3663 #elif defined(VXWORKS)
3664 { u_long nonblocking = 1;
3665 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking));
3668 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK);
3672 { if ((r = SSL_connect(soap->ssl)) <= 0)
3673 { int err = SSL_get_error(soap->ssl, r);
3674 if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3675 { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR);
3676 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3677 return SOAP_INVALID_SOCKET;
3679 if (soap->connect_timeout)
3680 { struct timeval timeout;
3682 if (soap->connect_timeout > 0)
3683 { timeout.tv_sec = soap->connect_timeout;
3684 timeout.tv_usec = 0;
3687 { timeout.tv_sec = -soap->connect_timeout/1000000;
3688 timeout.tv_usec = -soap->connect_timeout%1000000;
3691 if ((int)soap->socket > FD_SETSIZE)
3692 { soap->error = SOAP_FD_EXCEEDED;
3693 return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
3697 FD_SET((SOAP_SOCKET)fd, &fds);
3699 { int r = select((SOAP_SOCKET)(fd + 1), &fds, NULL, &fds, &timeout);
3704 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
3705 soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3706 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3707 return SOAP_INVALID_SOCKET;
3716 if (soap->connect_timeout)
3718 { u_long blocking = 0;
3719 ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking);
3721 #elif defined(VXWORKS)
3722 { u_long blocking = 0;
3723 ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking));
3726 fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK);
3729 if (soap->require_server_auth)
3735 if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3736 { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR);
3737 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3738 return SOAP_INVALID_SOCKET;
3740 peer = SSL_get_peer_certificate(soap->ssl);
3742 { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
3743 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3744 return SOAP_INVALID_SOCKET;
3746 ext_count = X509_get_ext_count(peer);
3749 for (i = 0; i < ext_count; i++)
3750 { X509_EXTENSION *ext = X509_get_ext(peer, i);
3751 const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
3752 if (!strcmp(ext_str, "subjectAltName"))
3754 STACK_OF(CONF_VALUE) *val;
3755 X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext);
3759 val = meth->i2v(meth, meth->d2i(NULL, (const unsigned char**)&ext->value->data, ext->value->length), NULL);
3761 /*val = meth->i2v(meth, meth->d2i(NULL, (unsigned char**)&ext->value->data, ext->value->length), NULL);*/
3762 val = meth->i2v(meth, meth->d2i(NULL, (const unsigned char**)&ext->value->data, ext->value->length), NULL);
3764 for (j = 0; j < sk_CONF_VALUE_num(val); j++)
3765 { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
3766 if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
3776 if (!ok && (subj = X509_get_subject_name(peer)))
3777 { X509_NAME_get_text_by_NID(subj, NID_commonName, soap->msgbuf, sizeof(soap->msgbuf));
3778 if (soap_tag_cmp(soap->msgbuf, host))
3779 { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
3780 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3782 return SOAP_INVALID_SOCKET;
3788 soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3789 soap->error = SOAP_SSL_ERROR;
3790 return SOAP_INVALID_SOCKET;
3798 /******************************************************************************/
3804 soap_bind(struct soap *soap, const char *host, int port, int backlog)
3807 struct addrinfo *addrinfo = NULL;
3808 struct addrinfo hints;
3809 struct addrinfo res;
3813 int len = SOAP_BUFLEN;
3816 if (soap_valid_socket(soap->master))
3817 { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master);
3818 soap->master = SOAP_INVALID_SOCKET;
3820 soap->socket = SOAP_INVALID_SOCKET;
3823 { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
3824 return SOAP_INVALID_SOCKET;
3827 memset((void*)&hints, 0, sizeof(hints));
3828 hints.ai_family = PF_UNSPEC;
3830 if ((soap->omode & SOAP_IO_UDP))
3831 hints.ai_socktype = SOCK_DGRAM;
3834 hints.ai_socktype = SOCK_STREAM;
3835 hints.ai_flags = AI_PASSIVE;
3837 err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
3840 soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr);
3841 soap->peerlen = addrinfo->ai_addrlen;
3842 res.ai_addr = (struct sockaddr*)&soap->peer;
3843 res.ai_addrlen = soap->peerlen;
3844 freeaddrinfo(addrinfo);
3847 { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
3848 return SOAP_INVALID_SOCKET;
3850 soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol);
3853 if ((soap->omode & SOAP_IO_UDP))
3854 soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
3857 soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
3860 if (!soap_valid_socket(soap->master))
3861 { soap->errnum = soap_socket_errno;
3862 soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
3863 return SOAP_INVALID_SOCKET;
3866 if ((soap->omode & SOAP_IO_UDP))
3867 soap->socket = soap->master;
3869 #ifdef SOCKET_CLOSE_ON_EXEC
3872 SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
3875 fcntl(soap->master, F_SETFD, 1);
3879 if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
3880 { soap->errnum = soap_socket_errno;
3881 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
3882 return SOAP_INVALID_SOCKET;
3884 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
3885 { soap->errnum = soap_socket_errno;
3886 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
3887 return SOAP_INVALID_SOCKET;
3889 if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
3890 { soap->errnum = soap_socket_errno;
3891 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
3892 return SOAP_INVALID_SOCKET;
3894 if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
3895 { soap->errnum = soap_socket_errno;
3896 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
3897 return SOAP_INVALID_SOCKET;
3900 if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
3901 { soap->errnum = soap_socket_errno;
3902 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
3903 return SOAP_INVALID_SOCKET;
3909 if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen))
3910 { soap->errnum = soap_socket_errno;
3911 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
3912 soap_closesock(soap);
3913 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
3914 return SOAP_INVALID_SOCKET;
3917 soap->peerlen = sizeof(soap->peer);
3918 memset((void*)&soap->peer, 0, sizeof(soap->peer));
3919 soap->peer.sin_family = AF_INET;
3922 { if (soap->fresolve(soap, host, &soap->peer.sin_addr))
3923 { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
3924 return SOAP_INVALID_SOCKET;
3928 soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
3929 soap->peer.sin_port = htons((short)port);
3931 if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen))
3932 { soap->errnum = soap_socket_errno;
3933 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
3934 soap_closesock(soap);
3935 soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
3936 return SOAP_INVALID_SOCKET;
3939 if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog))
3940 { soap->errnum = soap_socket_errno;
3941 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
3942 soap_closesock(soap);
3943 soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
3944 return SOAP_INVALID_SOCKET;
3946 return soap->master;
3951 /******************************************************************************/
3957 soap_poll(struct soap *soap)
3960 struct timeval timeout;
3961 fd_set rfd, sfd, xfd;
3964 timeout.tv_usec = 0;
3966 if ((int)soap->socket > FD_SETSIZE)
3967 return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
3972 if (soap_valid_socket(soap->socket))
3973 { FD_SET((SOAP_SOCKET)soap->socket, &rfd);
3974 FD_SET((SOAP_SOCKET)soap->socket, &sfd);
3975 FD_SET((SOAP_SOCKET)soap->socket, &xfd);
3976 r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout);
3977 if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd))
3980 else if (soap_valid_socket(soap->master))
3981 { FD_SET((SOAP_SOCKET)soap->master, &sfd);
3982 r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout);
3989 if (soap->imode & SOAP_ENC_SSL)
3991 if (soap_valid_socket(soap->socket)
3992 && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
3993 && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
3994 || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
3999 if (soap_valid_socket(soap->socket)
4000 && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
4001 && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
4002 || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
4006 { soap->errnum = soap_socket_errno;
4007 if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR)
4008 { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
4009 return soap->error = SOAP_TCP_ERROR;
4014 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
4023 /******************************************************************************/
4027 tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n)
4029 fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4030 #ifdef SOCKET_CLOSE_ON_EXEC
4033 SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
4036 fcntl(fd, F_SETFD, FD_CLOEXEC);
4044 /******************************************************************************/
4050 soap_accept(struct soap *soap)
4051 { int n = (int)sizeof(soap->peer);
4053 int len = SOAP_BUFLEN;
4056 soap->error = SOAP_OK;
4058 if ((soap->omode & SOAP_IO_UDP))
4059 return soap->socket = soap->master;
4061 memset((void*)&soap->peer, 0, sizeof(soap->peer));
4062 soap->socket = SOAP_INVALID_SOCKET;
4064 soap->keep_alive = 0;
4065 if (soap_valid_socket(soap->master))
4069 if (soap->accept_timeout)
4070 { struct timeval timeout;
4072 if (soap->accept_timeout > 0)
4073 { timeout.tv_sec = soap->accept_timeout;
4074 timeout.tv_usec = 0;
4077 { timeout.tv_sec = -soap->accept_timeout/1000000;
4078 timeout.tv_usec = -soap->accept_timeout%1000000;
4081 if ((int)soap->socket > FD_SETSIZE)
4082 { soap->error = SOAP_FD_EXCEEDED;
4083 return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
4087 FD_SET((SOAP_SOCKET)soap->master, &fd);
4089 { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout);
4094 soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
4095 return SOAP_INVALID_SOCKET;
4097 if (soap_socket_errno != SOAP_EINTR)
4098 { soap->errnum = soap_socket_errno;
4099 soap_closesock(soap);
4100 soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4101 return SOAP_INVALID_SOCKET;
4105 { u_long nonblocking = 1;
4106 ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking);
4108 #elif defined(VXWORKS)
4109 { u_long nonblocking = 1;
4110 ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&nonblocking));
4113 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK);
4118 { u_long blocking = 0;
4119 ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
4121 #elif defined(VXWORKS)
4122 { u_long blocking = 0;
4123 ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking));
4126 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
4129 soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
4130 soap->peerlen = (size_t)n;
4131 if (soap_valid_socket(soap->socket))
4134 /* Use soap->host to store the numeric form of the remote host */
4135 getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
4136 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
4137 soap->ip = 0; /* info stored in soap->peer and soap->host */
4138 soap->port = 0; /* info stored in soap->peer and soap->host */
4140 soap->ip = ntohl(soap->peer.sin_addr.s_addr);
4141 soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
4142 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF));
4145 if (soap->accept_flags == SO_LINGER)
4146 { struct linger linger;
4147 memset((void*)&linger, 0, sizeof(linger));
4149 linger.l_linger = 0;
4150 if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
4151 { soap->errnum = soap_socket_errno;
4152 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
4153 soap_closesock(soap);
4154 return SOAP_INVALID_SOCKET;
4157 else if (soap->accept_flags && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
4158 { soap->errnum = soap_socket_errno;
4159 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
4160 soap_closesock(soap);
4161 return SOAP_INVALID_SOCKET;
4163 if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4164 { soap->errnum = soap_socket_errno;
4165 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
4166 soap_closesock(soap);
4167 return SOAP_INVALID_SOCKET;
4169 if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4170 { soap->errnum = soap_socket_errno;
4171 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
4172 soap_closesock(soap);
4173 return SOAP_INVALID_SOCKET;
4175 if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4176 { soap->errnum = soap_socket_errno;
4177 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
4178 soap_closesock(soap);
4179 return SOAP_INVALID_SOCKET;
4182 if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4183 { soap->errnum = soap_socket_errno;
4184 soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
4185 soap_closesock(soap);
4186 return SOAP_INVALID_SOCKET;
4190 if (soap->accept_timeout)
4193 u_long blocking = 0;
4194 ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking);
4195 ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking);
4196 #elif defined(VXWORKS)
4197 u_long blocking = 0;
4198 ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking));
4199 ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&blocking));
4201 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK);
4202 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK);
4203 #elif defined(SYMBIAN)
4205 ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking);
4207 fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK);
4208 fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK);
4211 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
4212 return soap->socket;
4214 if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN)
4215 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
4216 soap->errnum = soap_socket_errno;
4217 soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4218 soap_closesock(soap);
4219 return SOAP_INVALID_SOCKET;
4225 soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
4226 return SOAP_INVALID_SOCKET;
4232 /******************************************************************************/
4236 tcp_disconnect(struct soap *soap)
4242 SSL_SESSION_free(soap->session);
4244 { soap->session = SSL_get1_session(soap->ssl);
4246 { strcpy(soap->session_host, soap->host);
4247 soap->session_port = soap->port;
4250 r = SSL_shutdown(soap->ssl);
4252 { s = ERR_get_error();
4254 { if (soap_valid_socket(soap->socket))
4255 { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1);
4256 soap->socket = SOAP_INVALID_SOCKET;
4258 r = SSL_shutdown(soap->ssl);
4261 DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
4262 SSL_free(soap->ssl);
4265 return SOAP_SSL_ERROR;
4266 ERR_remove_state(0);
4269 if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4270 { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2);
4271 soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket);
4272 soap->socket = SOAP_INVALID_SOCKET;
4279 /******************************************************************************/
4283 tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
4284 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd));
4285 return soap_closesocket(fd);
4290 /******************************************************************************/
4294 tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
4295 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how));
4296 return shutdown(fd, how);
4301 /******************************************************************************/
4306 soap_closesock(struct soap *soap)
4307 { register int status = soap->error;
4308 if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
4309 { if (soap->fclose && (soap->error = soap->fclose(soap)))
4311 soap->keep_alive = 0;
4314 if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
4315 deflateEnd(&soap->d_stream);
4316 else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
4317 inflateEnd(&soap->d_stream);
4318 soap->zlib_state = SOAP_ZLIB_NONE;
4320 return soap->error = status;
4324 /******************************************************************************/
4325 #ifndef WITH_NOIDREF
4330 soap_hash(register const char *s)
4331 { register size_t h = 0;
4334 return h % SOAP_IDHASH;
4339 /******************************************************************************/
4340 #ifndef WITH_NOIDREF
4343 soap_init_pht(struct soap *soap)
4345 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n"));
4348 for (i = 0; i < (int)SOAP_PTRHASH; i++)
4349 soap->pht[i] = NULL;
4354 /******************************************************************************/
4359 soap_new1(soap_mode mode)
4360 { return soap_new2(mode, mode);
4364 /******************************************************************************/
4370 { return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
4374 /******************************************************************************/
4379 soap_new2(soap_mode imode, soap_mode omode)
4380 { struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
4382 soap_init2(soap, imode, omode);
4387 /******************************************************************************/
4392 soap_del(struct soap *soap)
4397 /******************************************************************************/
4398 #ifndef WITH_NOIDREF
4401 soap_free_pht(struct soap *soap)
4402 { register struct soap_pblk *pb, *next;
4404 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
4405 for (pb = soap->pblk; pb; pb = next)
4407 SOAP_FREE(soap, pb);
4411 for (i = 0; i < (int)SOAP_PTRHASH; i++)
4412 soap->pht[i] = NULL;
4417 /******************************************************************************/
4418 #ifndef WITH_NOIDREF
4423 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
4425 struct soap_plist *pp;
4426 if (soap->version != 1)
4429 i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
4431 i = soap_pointer_lookup(soap, p, type, &pp);
4433 { if (soap_is_embedded(soap, pp)
4434 || soap_is_single(soap, pp))
4436 soap_set_embedded(soap, pp);
4443 /******************************************************************************/
4444 #ifndef WITH_NOIDREF
4449 soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
4450 { register struct soap_plist *pp;
4453 { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
4454 { if (pp->ptr == p && pp->type == type)
4456 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
4461 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
4467 /******************************************************************************/
4468 #ifndef WITH_NOIDREF
4473 soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
4475 register struct soap_plist *pp;
4476 if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
4477 { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
4479 { soap->error = SOAP_EOM;
4482 pb->next = soap->pblk;
4486 *ppp = pp = &soap->pblk->plist[soap->pidx++];
4488 h = soap_hash_ptr(a->__ptr);
4490 h = soap_hash_ptr(p);
4491 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1));
4492 pp->next = soap->pht[h];
4499 pp->id = ++soap->idnum;
4505 /******************************************************************************/
4506 #ifndef WITH_NOIDREF
4511 soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
4512 { register struct soap_plist *pp;
4514 if (!p || !a->__ptr)
4516 for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
4517 { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
4519 for (i = 0; i < n; i++)
4520 if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
4524 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
4529 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
4535 /******************************************************************************/
4540 soap_begin_count(struct soap *soap)
4543 if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
4544 soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
4547 { soap->mode = soap->omode;
4548 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
4549 || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
4551 && !soap->fpreparesend
4554 soap->mode &= ~SOAP_IO_LENGTH;
4556 soap->mode |= SOAP_IO_LENGTH;
4559 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
4560 { if (!(soap->mode & SOAP_ENC_DIME))
4561 soap->mode &= ~SOAP_IO_LENGTH;
4562 if (soap->mode & SOAP_ENC_XML)
4563 soap->mode |= SOAP_IO_BUFFER;
4565 soap->mode |= SOAP_IO_STORE;
4568 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
4569 soap->mode |= SOAP_XML_TREE;
4571 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
4572 soap->mode |= SOAP_ENC_MIME;
4574 soap->mode &= ~SOAP_ENC_MTOM;
4575 if (soap->mode & SOAP_ENC_MIME)
4576 soap_select_mime_boundary(soap);
4577 soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
4583 soap->mustUnderstand = 0;
4585 soap->part = SOAP_BEGIN;
4587 soap_clr_attr(soap);
4588 soap_set_local_namespaces(soap);
4589 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
4591 soap->dime.count = 0; /* count # of attachments */
4592 soap->dime.size = 0; /* accumulate total size of attachments */
4593 if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
4594 return soap->error = soap->fprepareinit(soap);
4600 /******************************************************************************/
4605 soap_end_count(struct soap *soap)
4608 if (soap->fpreparefinal)
4609 return soap->error = soap->fpreparefinal(soap);
4611 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
4616 /******************************************************************************/
4621 soap_begin_send(struct soap *soap)
4622 { soap->error = SOAP_OK;
4623 soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
4625 if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
4626 { if (soap->mode & SOAP_ENC_XML)
4627 soap->mode |= SOAP_IO_BUFFER;
4629 soap->mode |= SOAP_IO_STORE;
4633 if ((soap->mode & SOAP_IO_UDP))
4634 { soap->mode |= SOAP_ENC_XML;
4635 if (soap->count > SOAP_BUFLEN)
4636 return soap->error = SOAP_UDP_ERROR;
4639 if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
4640 { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
4641 soap->mode |= SOAP_IO_BUFFER;
4643 soap->mode |= SOAP_IO_STORE;
4645 soap->mode &= ~SOAP_IO_LENGTH;
4646 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
4647 soap_new_block(soap);
4648 if (!(soap->mode & SOAP_IO_KEEPALIVE))
4649 soap->keep_alive = 0;
4650 if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
4651 soap->mode |= SOAP_XML_TREE;
4653 if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
4654 { soap->mode |= SOAP_ENC_MIME;
4655 soap->mode &= ~SOAP_ENC_DIME;
4658 soap->mode &= ~SOAP_ENC_MTOM;
4659 if (soap->mode & SOAP_ENC_MIME)
4660 soap_select_mime_boundary(soap);
4663 #ifndef WITH_FASTCGI
4664 if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
4666 setmode((SOAP_SOCKET)soap->sendfd, O_BINARY);
4668 _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY);
4674 if (soap->mode & SOAP_IO)
4678 soap->chunksize = 0;
4682 soap->mustUnderstand = 0;
4686 soap_clr_attr(soap);
4687 soap_set_local_namespaces(soap);
4689 soap->z_ratio_out = 1.0;
4690 if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
4693 memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
4694 soap->d_stream.next_out = (Byte*)soap->z_buf + 10;
4695 soap->d_stream.avail_out = SOAP_BUFLEN - 10;
4696 soap->z_crc = crc32(0L, NULL, 0);
4697 if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
4699 soap->d_stream.next_out = (Byte*)soap->z_buf;
4700 soap->d_stream.avail_out = SOAP_BUFLEN;
4701 if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK)
4703 return soap->error = SOAP_ZLIB_ERROR;
4704 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
4705 soap->zlib_state = SOAP_ZLIB_DEFLATE;
4708 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
4709 soap->part = SOAP_BEGIN;
4711 if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE)
4712 soap->fprepareinit(soap);
4718 /******************************************************************************/
4719 #ifndef WITH_NOIDREF
4724 soap_embedded(struct soap *soap, const void *p, int t)
4725 { struct soap_plist *pp;
4726 if (soap_pointer_lookup(soap, p, t, &pp))
4729 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
4735 /******************************************************************************/
4736 #ifndef WITH_NOIDREF
4741 soap_reference(struct soap *soap, const void *p, int t)
4742 { struct soap_plist *pp;
4743 if (!p || (soap->mode & SOAP_XML_TREE))
4745 if (soap_pointer_lookup(soap, p, t, &pp))
4746 { if (pp->mark1 == 0)
4751 else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
4757 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
4763 /******************************************************************************/
4764 #ifndef WITH_NOIDREF
4769 soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
4771 struct soap_plist *pp;
4772 if (!p || !a->__ptr)
4774 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
4776 { if (pp->mark1 == 0)
4781 else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
4787 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2));
4793 /******************************************************************************/
4794 #ifndef WITH_NOIDREF
4799 soap_embedded_id(struct soap *soap, int id, const void *p, int t)
4800 { struct soap_plist *pp;
4801 if (soap->mode & SOAP_XML_TREE)
4803 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
4804 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
4806 { id = soap_pointer_lookup(soap, p, t, &pp);
4808 { if (soap->mode & SOAP_IO_LENGTH)
4812 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
4819 id = soap_pointer_lookup(soap, p, t, &pp);
4820 else if (id && !soap_pointer_lookup(soap, p, t, &pp))
4823 { if (soap->mode & SOAP_IO_LENGTH)
4827 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2));
4834 /******************************************************************************/
4835 #ifndef WITH_NOIDREF
4840 soap_is_embedded(struct soap *soap, struct soap_plist *pp)
4843 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
4844 if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
4845 { if (soap->mode & SOAP_IO_LENGTH)
4846 return pp->mark1 != 0;
4847 return pp->mark2 != 0;
4849 if (soap->mode & SOAP_IO_LENGTH)
4850 return pp->mark1 == 1;
4851 return pp->mark2 == 1;
4856 /******************************************************************************/
4857 #ifndef WITH_NOIDREF
4862 soap_is_single(struct soap *soap, struct soap_plist *pp)
4863 { if (soap->part == SOAP_IN_HEADER)
4867 if (soap->mode & SOAP_IO_LENGTH)
4868 return pp->mark1 == 0;
4869 return pp->mark2 == 0;
4874 /******************************************************************************/
4875 #ifndef WITH_NOIDREF
4880 soap_set_embedded(struct soap *soap, struct soap_plist *pp)
4883 if (soap->mode & SOAP_IO_LENGTH)
4891 /******************************************************************************/
4892 #ifndef WITH_NOIDREF
4898 soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t)
4899 { struct soap_plist *pp;
4901 if (!p || !a->__ptr || (!aid && !atype))
4902 return soap_element_id(soap, tag, id, p, a, n, type, t);
4903 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:""));
4904 i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
4906 { i = soap_pointer_enter(soap, p, a, n, t, &pp);
4908 { soap->error = SOAP_EOM;
4915 { sprintf(soap->tmpbuf, soap->dime_id_format, id);
4916 aid = soap_strdup(soap, soap->tmpbuf);
4918 /* Add MTOM xop:Include element when necessary */
4919 /* TODO: this code to be obsoleted with new import/xop.h conventions */
4920 if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
4921 { if (soap_element_begin_out(soap, tag, 0, type)
4922 || soap_element_href(soap, "xop:Include", 0, "href", aid)
4923 || soap_element_end_out(soap, tag))
4926 else if (soap_element_href(soap, tag, 0, "href", aid))
4928 if (soap->mode & SOAP_IO_LENGTH)
4929 { if (pp->mark1 != 3)
4930 { struct soap_multipart *content;
4931 if (soap->mode & SOAP_ENC_MTOM)
4932 content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
4934 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
4936 { soap->error = SOAP_EOM;
4939 if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
4940 { if (soap->mode & SOAP_ENC_MTOM)
4941 { char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
4944 strcpy(s + 1, aid + 4);
4950 content->id = aid + 4;
4954 content->type = atype;
4955 content->options = aoptions;
4956 content->encoding = SOAP_MIME_BINARY;
4968 /******************************************************************************/
4969 #ifndef WITH_NOIDREF
4972 soap_init_iht(struct soap *soap)
4974 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n"));
4975 for (i = 0; i < SOAP_IDHASH; i++)
4976 soap->iht[i] = NULL;
4981 /******************************************************************************/
4982 #ifndef WITH_NOIDREF
4985 soap_free_iht(struct soap *soap)
4987 register struct soap_ilist *ip, *p;
4988 register struct soap_flist *fp, *fq;
4989 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
4990 for (i = 0; i < SOAP_IDHASH; i++)
4991 { for (ip = soap->iht[i]; ip; ip = p)
4992 { for (fp = ip->flist; fp; fp = fq)
4994 SOAP_FREE(soap, fp);
4997 SOAP_FREE(soap, ip);
4999 soap->iht[i] = NULL;
5005 /******************************************************************************/
5006 #ifndef WITH_NOIDREF
5011 soap_lookup(struct soap *soap, const char *id)
5012 { register struct soap_ilist *ip;
5013 for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
5014 if (!strcmp(ip->id, id))
5021 /******************************************************************************/
5022 #ifndef WITH_NOIDREF
5027 soap_enter(struct soap *soap, const char *id)
5028 { register size_t h;
5029 register struct soap_ilist *ip;
5030 ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
5032 { h = soap_hash(id);
5034 ip->next = soap->iht[h];
5043 /******************************************************************************/
5048 soap_malloc(struct soap *soap, size_t n)
5051 return (void*)SOAP_NON_NULL;
5053 return SOAP_MALLOC(soap, n);
5057 n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
5058 if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
5059 { soap->error = SOAP_EOM;
5062 /* keep chain of alloced cells for later destruction */
5065 /* set the canary to detect corruption */
5066 *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY;
5068 *(void**)(p + n) = soap->alist;
5069 *(size_t*)(p + n + sizeof(void*)) = n;
5070 soap->alist = p + n;
5075 /******************************************************************************/
5078 soap_init_mht(struct soap *soap)
5080 for (i = 0; i < (int)SOAP_PTRHASH; i++)
5081 soap->mht[i] = NULL;
5085 /******************************************************************************/
5088 soap_free_mht(struct soap *soap)
5090 register struct soap_mlist *mp, *mq;
5091 for (i = 0; i < (int)SOAP_PTRHASH; i++)
5092 { for (mp = soap->mht[i]; mp; mp = mq)
5095 fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
5098 soap->mht[i] = NULL;
5103 /******************************************************************************/
5108 soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
5109 { register void *p = malloc(size);
5111 { register int h = soap_hash_ptr(p);
5112 register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
5113 if (soap->fdebug[SOAP_INDEX_TEST])
5114 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
5115 mp->next = soap->mht[h];
5126 /******************************************************************************/
5131 soap_track_free(struct soap *soap, const char *file, int line, void *p)
5132 { register int h = soap_hash_ptr(p);
5133 register struct soap_mlist *mp;
5134 for (mp = soap->mht[h]; mp; mp = mp->next)
5140 if (soap->fdebug[SOAP_INDEX_TEST])
5141 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
5145 fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
5148 fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
5152 /******************************************************************************/
5155 soap_track_unlink(struct soap *soap, const void *p)
5156 { register int h = soap_hash_ptr(p);
5157 register struct soap_mlist *mp;
5158 for (mp = soap->mht[h]; mp; mp = mp->next)
5166 /******************************************************************************/
5171 soap_dealloc(struct soap *soap, void *p)
5175 { register char **q;
5176 for (q = (char**)&soap->alist; *q; q = *(char***)q)
5179 if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY)
5180 { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
5181 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
5182 DBGHEX(TEST, *q - 200, 200);
5183 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
5187 if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
5188 { *q = **(char***)q;
5189 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
5194 soap_delete(soap, p);
5198 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
5200 { q = (char*)soap->alist;
5202 if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY)
5203 { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
5204 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
5205 DBGHEX(TEST, q - 200, 200);
5206 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
5210 soap->alist = *(void**)q;
5211 q -= *(size_t*)(q + sizeof(void*));
5215 /* we must assume these were deallocated: */
5216 soap->action = NULL;
5218 soap->header = NULL;
5219 soap->userid = NULL;
5220 soap->passwd = NULL;
5221 soap->authrealm = NULL;
5223 soap_clr_mime(soap);
5228 /******************************************************************************/
5233 soap_delete(struct soap *soap, void *p)
5234 { register struct soap_clist **cp;
5235 if (soap_check_state(soap))
5240 { if (p == (*cp)->ptr)
5241 { register struct soap_clist *q = *cp;
5249 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
5253 { register struct soap_clist *q = *cp;
5262 /******************************************************************************/
5267 soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*))
5268 { register struct soap_clist *cp;
5269 if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
5270 { cp->next = soap->clist;
5274 cp->fdelete = fdelete;
5281 /******************************************************************************/
5286 soap_unlink(struct soap *soap, const void *p)
5287 { register char **q;
5288 register struct soap_clist **cp;
5291 for (q = (char**)&soap->alist; *q; q = *(char***)q)
5292 { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
5293 { *q = **(char***)q;
5294 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
5296 soap_track_unlink(soap, p);
5301 for (cp = &soap->clist; *cp; cp = &(*cp)->next)
5302 { if (p == (*cp)->ptr)
5303 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
5313 /******************************************************************************/
5314 #ifndef WITH_NOIDREF
5319 soap_lookup_type(struct soap *soap, const char *id)
5320 { register struct soap_ilist *ip;
5322 { ip = soap_lookup(soap, id);
5324 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
5328 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
5334 /******************************************************************************/
5335 #ifndef WITH_NOIDREF
5340 soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
5341 { struct soap_ilist *ip;
5343 if (!p || !id || !*id)
5345 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
5347 { ip = soap_enter(soap, id); /* new hash table entry for string id */
5348 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
5359 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
5361 { strcpy(soap->id, id);
5362 soap->error = SOAP_HREF;
5363 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t));
5366 while (ip->level < k)
5367 { q = (void**)soap_malloc(soap, sizeof(void*));
5373 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5377 else if (ip->level > k)
5378 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
5379 while (ip->level > k)
5380 { void *s, **r = &ip->link;
5381 q = (void**)ip->link;
5383 { *r = (void*)soap_malloc(soap, sizeof(void*));
5392 ip->level = ip->level - 1;
5393 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5395 q = (void**)ip->link;
5400 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
5401 while (ip->level < k)
5402 { q = (void**)soap_malloc(soap, sizeof(void*));
5406 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5408 q = (void**)ip->link;
5417 /******************************************************************************/
5418 #ifndef WITH_NOIDREF
5423 soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t))
5424 { struct soap_ilist *ip;
5425 if (!p || !href || !*href)
5427 ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
5429 { ip = soap_enter(soap, href); /* new hash table entry for string id */
5437 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p));
5439 else if (ip->type != st || (ip->level == k && ip->size != n))
5440 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n));
5441 strcpy(soap->id, href);
5442 soap->error = SOAP_HREF;
5445 if (fcopy || n < sizeof(void*) || *href != '#')
5446 { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
5448 { soap->error = SOAP_EOM;
5451 fp->next = ip->flist;
5459 fp->fcopy = soap_fcopy;
5461 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href));
5464 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
5465 *(void**)p = ip->copy;
5473 /******************************************************************************/
5478 soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*))
5480 #ifndef WITH_NOIDREF
5481 struct soap_ilist *ip;
5483 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
5487 p = finstantiate(soap, t, type, arrayType, &n);
5489 p = soap_malloc(soap, n);
5493 #ifndef WITH_NOIDREF
5497 #ifndef WITH_NOIDREF
5498 ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
5499 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
5501 { ip = soap_enter(soap, id); /* new hash table entry for string id */
5509 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p));
5511 else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
5512 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n));
5513 strcpy(soap->id, id);
5514 soap->error = SOAP_HREF;
5518 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
5519 strcpy(soap->id, id);
5520 soap->error = SOAP_DUPLICATE_ID;
5527 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
5534 /******************************************************************************/
5539 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
5540 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
5545 /******************************************************************************/
5550 soap_end_send(struct soap *soap)
5553 if (soap->dime.list)
5554 { /* SOAP body referenced attachments must appear first */
5555 soap->dime.last->next = soap->dime.first;
5556 soap->dime.first = soap->dime.list->next;
5557 soap->dime.list->next = NULL;
5558 soap->dime.last = soap->dime.list;
5560 if (soap_putdime(soap) || soap_putmime(soap))
5562 soap->mime.list = NULL;
5563 soap->mime.first = NULL;
5564 soap->mime.last = NULL;
5565 soap->dime.list = NULL;
5566 soap->dime.first = NULL;
5567 soap->dime.last = NULL;
5569 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n"));
5570 if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
5571 { if (soap_flush(soap))
5573 { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
5574 { soap->zlib_state = SOAP_ZLIB_NONE;
5575 deflateEnd(&soap->d_stream);
5583 if (soap->mode & SOAP_ENC_ZLIB)
5585 soap->d_stream.avail_in = 0;
5587 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
5588 r = deflate(&soap->d_stream, Z_FINISH);
5589 if (soap->d_stream.avail_out != SOAP_BUFLEN)
5590 { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out))
5591 { soap->zlib_state = SOAP_ZLIB_NONE;
5592 deflateEnd(&soap->d_stream);
5595 soap->d_stream.next_out = (Byte*)soap->z_buf;
5596 soap->d_stream.avail_out = SOAP_BUFLEN;
5598 } while (r == Z_OK);
5599 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
5600 soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in;
5601 soap->mode &= ~SOAP_ENC_ZLIB;
5602 soap->zlib_state = SOAP_ZLIB_NONE;
5603 if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END)
5604 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
5605 return soap->error = SOAP_ZLIB_ERROR;
5608 soap->z_buf[0] = soap->z_crc & 0xFF;
5609 soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
5610 soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
5611 soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
5612 soap->z_buf[4] = soap->d_stream.total_in & 0xFF;
5613 soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF;
5614 soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF;
5615 soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF;
5616 if (soap_flush_raw(soap, soap->z_buf, 8))
5618 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
5622 if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
5625 if (!(soap->mode & SOAP_ENC_XML))
5627 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
5628 if (soap->status >= SOAP_POST)
5629 soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
5630 else if (soap->status != SOAP_STOP)
5631 soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
5632 if (soap->error || soap_flush(soap))
5637 for (p = soap_first_block(soap); p; p = soap_next_block(soap))
5638 { DBGMSG(SENT, p, soap_block_size(soap));
5639 if ((soap->error = soap->fsend(soap, p, soap_block_size(soap))))
5640 { soap_end_block(soap);
5644 soap_end_block(soap);
5647 else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
5648 { DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
5649 if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
5656 if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
5657 soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
5659 if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
5660 soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */
5663 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
5664 soap->omode &= ~SOAP_XML_SEC;
5666 soap->part = SOAP_END;
5671 /******************************************************************************/
5676 soap_end_recv(struct soap *soap)
5677 { soap->part = SOAP_END;
5679 if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
5681 soap->dime.list = soap->dime.first;
5682 soap->dime.first = NULL;
5683 soap->dime.last = NULL;
5684 /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */
5685 if (soap->mode & SOAP_ENC_MIME)
5686 { if (soap->mode & SOAP_MIME_POSTCHECK)
5687 { soap_resolve(soap);
5690 if (soap_getmime(soap))
5693 soap->mime.list = soap->mime.first;
5694 soap->mime.first = NULL;
5695 soap->mime.last = NULL;
5696 soap->mime.boundary = NULL;
5698 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
5700 if (soap->mode & SOAP_ENC_ZLIB)
5701 { soap->mode &= ~SOAP_ENC_ZLIB;
5702 memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
5703 soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf;
5704 soap->buflen = soap->z_buflen;
5705 soap->zlib_state = SOAP_ZLIB_NONE;
5706 if (inflateEnd(&soap->d_stream) != Z_OK)
5707 return soap->error = SOAP_ZLIB_ERROR;
5709 if (soap->zlib_in == SOAP_ZLIB_GZIP)
5712 for (i = 0; i < 8; i++)
5713 { if ((int)(c = soap_getchar(soap)) == EOF)
5714 return soap->error = SOAP_EOF;
5715 soap->z_buf[i] = (char)c;
5717 if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24)))
5718 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
5719 return soap->error = SOAP_ZLIB_ERROR;
5721 if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24)))
5722 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n"));
5723 return soap->error = SOAP_ZLIB_ERROR;
5729 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
5730 while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
5732 if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
5734 #ifndef WITH_NOIDREF
5735 return soap_resolve(soap);
5739 { if (soap->mode & SOAP_ENC_MTOM)
5740 return soap->error = SOAP_MIME_HREF;
5741 return soap->error = SOAP_DIME_HREF;
5749 /******************************************************************************/
5754 soap_free(struct soap *soap)
5755 { register struct Namespace *ns;
5756 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
5758 { register struct soap_nlist *np = soap->nlist->next;
5759 SOAP_FREE(soap, soap->nlist);
5762 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
5764 soap_end_block(soap);
5765 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
5766 while (soap->attributes)
5767 { register struct soap_attribute *tp = soap->attributes->next;
5768 if (soap->attributes->value)
5769 SOAP_FREE(soap, soap->attributes->value);
5770 SOAP_FREE(soap, soap->attributes);
5771 soap->attributes = tp;
5775 SOAP_FREE(soap, soap->labbuf);
5776 soap->labbuf = NULL;
5780 ns = soap->local_namespaces;
5782 { for (; ns->id; ns++)
5784 { if (soap->encodingStyle == ns->out)
5785 soap->encodingStyle = SOAP_STR_EOS;
5786 SOAP_FREE(soap, ns->out);
5789 if (soap->encodingStyle == ns->ns)
5790 soap->encodingStyle = SOAP_STR_EOS;
5792 SOAP_FREE(soap, soap->local_namespaces);
5793 soap->local_namespaces = NULL;
5797 { struct soap_xlist *xp = soap->xlist->next;
5798 SOAP_FREE(soap, soap->xlist);
5802 #ifndef WITH_NOIDREF
5803 soap_free_pht(soap);
5804 soap_free_iht(soap);
5809 /******************************************************************************/
5812 soap_init_logs(struct soap *soap)
5814 for (i = 0; i < SOAP_MAXLOGS; i++)
5815 { soap->logfile[i] = NULL;
5816 soap->fdebug[i] = NULL;
5821 /******************************************************************************/
5822 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
5826 soap_open_logfile(struct soap *soap, int i)
5827 { if (soap->logfile[i])
5828 soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
5832 /******************************************************************************/
5835 soap_close_logfile(struct soap *soap, int i)
5836 { if (soap->fdebug[i])
5837 { fclose(soap->fdebug[i]);
5838 soap->fdebug[i] = NULL;
5843 /******************************************************************************/
5848 soap_close_logfiles(struct soap *soap)
5850 for (i = 0; i < SOAP_MAXLOGS; i++)
5851 soap_close_logfile(soap, i);
5855 /******************************************************************************/
5858 soap_set_logfile(struct soap *soap, int i, const char *logfile)
5860 soap_close_logfile(soap, i);
5861 if (soap->logfile[i])
5862 SOAP_FREE(soap, (void*)soap->logfile[i]);
5864 if ((s = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
5866 soap->logfile[i] = s;
5870 /******************************************************************************/
5875 soap_set_recv_logfile(struct soap *soap, const char *logfile)
5876 { soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
5880 /******************************************************************************/
5885 soap_set_sent_logfile(struct soap *soap, const char *logfile)
5886 { soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
5890 /******************************************************************************/
5895 soap_set_test_logfile(struct soap *soap, const char *logfile)
5896 { soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
5900 /******************************************************************************/
5905 soap_copy(struct soap *soap)
5906 { return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
5910 /******************************************************************************/
5915 soap_copy_context(struct soap *copy, struct soap *soap)
5916 { if (soap_check_state(soap))
5919 { register struct soap_plugin *p;
5920 memcpy(copy, soap, sizeof(struct soap));
5921 copy->state = SOAP_COPY;
5922 copy->error = SOAP_OK;
5923 copy->userid = NULL;
5924 copy->passwd = NULL;
5929 copy->attributes = NULL;
5931 copy->labbuf = NULL;
5936 soap_init_mht(copy);
5938 copy->local_namespaces = NULL;
5939 #ifndef WITH_NOIDREF
5940 soap_init_iht(copy);
5941 soap_init_pht(copy);
5943 copy->header = NULL;
5945 copy->action = NULL;
5948 copy->cookies = soap_copy_cookies(copy, soap);
5950 copy->cookies = NULL;
5954 soap_init_logs(copy);
5955 soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
5956 soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
5957 soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
5959 copy->plugins = NULL;
5960 for (p = soap->plugins; p; p = p->next)
5961 { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
5964 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
5966 if (p->fcopy && (soap->error = p->fcopy(copy, q, p)))
5967 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
5971 q->next = copy->plugins;
5976 soap->error = SOAP_EOM;
5981 /******************************************************************************/
5986 soap_copy_stream(struct soap *copy, struct soap *soap)
5987 { copy->mode = soap->mode;
5988 copy->imode = soap->imode;
5989 copy->omode = soap->omode;
5990 copy->socket = soap->socket;
5991 copy->recv_timeout = soap->recv_timeout;
5992 copy->send_timeout = soap->send_timeout;
5993 #if defined(__cplusplus) && !defined(WITH_LEAN)
5994 copy->os = soap->os;
5995 copy->is = soap->is;
5997 copy->sendfd = soap->sendfd;
5998 copy->recvfd = soap->recvfd;
5999 copy->bufidx = soap->bufidx;
6000 copy->buflen = soap->buflen;
6001 copy->ahead = soap->ahead;
6002 copy->cdata = soap->cdata;
6003 copy->chunksize = soap->chunksize;
6004 copy->chunkbuflen = soap->chunkbuflen;
6005 copy->keep_alive = soap->keep_alive;
6006 copy->max_keep_alive = soap->max_keep_alive;
6007 copy->peer = soap->peer;
6008 copy->peerlen = soap->peerlen;
6010 copy->bio = soap->bio;
6011 copy->ssl = soap->ssl;
6012 copy->ctx = soap->ctx;
6015 copy->zlib_state = soap->zlib_state;
6016 copy->zlib_in = soap->zlib_in;
6017 copy->zlib_out = soap->zlib_out;
6018 copy->d_stream = soap->d_stream;
6019 copy->z_buflen = soap->z_buflen;
6020 copy->z_level = soap->z_level;
6021 copy->z_crc = soap->z_crc;
6022 copy->z_ratio_in = soap->z_ratio_in;
6023 copy->z_ratio_out = soap->z_ratio_out;
6024 memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf));
6026 memcpy(copy->buf, soap->buf, sizeof(soap->buf));
6030 /******************************************************************************/
6035 soap_init(struct soap *soap)
6036 { soap->state = SOAP_INIT;
6038 soap_imode(soap, SOAP_IO_DEFAULT);
6039 soap_omode(soap, SOAP_IO_DEFAULT);
6040 soap->plugins = NULL;
6042 soap->userid = NULL;
6043 soap->passwd = NULL;
6045 soap->fpost = http_post;
6046 soap->fget = http_get;
6048 soap->fposthdr = http_post_header;
6049 soap->fresponse = http_response;
6050 soap->fparse = http_parse;
6051 soap->fparsehdr = http_parse_header;
6053 soap->fheader = NULL;
6054 soap->fconnect = NULL;
6055 soap->fdisconnect = NULL;
6058 soap->fresolve = tcp_gethost;
6060 soap->fresolve = NULL;
6062 soap->faccept = tcp_accept;
6063 soap->fopen = tcp_connect;
6064 soap->fclose = tcp_disconnect;
6065 soap->fclosesocket = tcp_closesocket;
6066 soap->fshutdownsocket = tcp_shutdownsocket;
6067 soap->fsend = fsend;
6068 soap->frecv = frecv;
6069 soap->fpoll = soap_poll;
6072 soap->fclose = NULL;
6075 soap->fseterror = NULL;
6076 soap->fignore = NULL;
6077 soap->fserveloop = NULL;
6078 soap->fplugin = fplugin;
6080 soap->fprepareinit = NULL;
6081 soap->fpreparesend = NULL;
6082 soap->fpreparerecv = NULL;
6083 soap->fpreparefinal = NULL;
6084 soap->fdimereadopen = NULL;
6085 soap->fdimewriteopen = NULL;
6086 soap->fdimereadclose = NULL;
6087 soap->fdimewriteclose = NULL;
6088 soap->fdimeread = NULL;
6089 soap->fdimewrite = NULL;
6090 soap->fmimereadopen = NULL;
6091 soap->fmimewriteopen = NULL;
6092 soap->fmimereadclose = NULL;
6093 soap->fmimewriteclose = NULL;
6094 soap->fmimeread = NULL;
6095 soap->fmimewrite = NULL;
6097 soap->float_format = "%G";
6098 soap->double_format = "%lG";
6099 soap->dime_id_format = "cid:id%d"; /* default DIME id format */
6100 soap->http_version = "1.1";
6101 soap->http_content = NULL;
6103 soap->max_keep_alive = SOAP_MAXKEEPALIVE;
6104 soap->keep_alive = 0;
6105 soap->recv_timeout = 0;
6106 soap->send_timeout = 0;
6107 soap->connect_timeout = 0;
6108 soap->accept_timeout = 0;
6109 soap->socket_flags = 0;
6110 soap->connect_flags = 0;
6111 soap->bind_flags = 0;
6112 soap->accept_flags = 0;
6115 soap->labbuf = NULL;
6119 soap->encodingStyle = SOAP_STR_EOS;
6120 #ifndef WITH_NONAMESPACES
6121 soap->namespaces = namespaces;
6123 soap->namespaces = NULL;
6125 soap->local_namespaces = NULL;
6130 soap->attributes = NULL;
6131 soap->header = NULL;
6133 soap->master = SOAP_INVALID_SOCKET;
6134 soap->socket = SOAP_INVALID_SOCKET;
6139 soap->dime.list = NULL;
6140 soap->dime.first = NULL;
6141 soap->dime.last = NULL;
6142 soap->mime.list = NULL;
6143 soap->mime.first = NULL;
6144 soap->mime.last = NULL;
6145 soap->mime.boundary = NULL;
6146 soap->mime.start = NULL;
6153 soap->recvfd = stdin;
6154 soap->sendfd = stdout;
6156 soap->host[0] = '\0';
6158 soap->action = NULL;
6159 soap->proxy_host = NULL;
6160 soap->proxy_port = 8080;
6161 soap->proxy_userid = NULL;
6162 soap->proxy_passwd = NULL;
6163 soap->authrealm = NULL;
6164 soap->prolog = NULL;
6168 soap->fsslauth = ssl_auth_init;
6169 soap->fsslverify = ssl_verify_callback;
6173 soap->require_server_auth = 0;
6174 soap->require_client_auth = 0;
6176 soap->keyfile = NULL;
6177 soap->password = NULL;
6178 soap->dhfile = NULL;
6179 soap->cafile = NULL;
6180 soap->capath = NULL;
6181 soap->crlfile = NULL;
6182 soap->randfile = NULL;
6183 soap->session = NULL;
6186 soap->zlib_state = SOAP_ZLIB_NONE;
6187 soap->zlib_in = SOAP_ZLIB_NONE;
6188 soap->zlib_out = SOAP_ZLIB_NONE;
6189 soap->d_stream.zalloc = NULL;
6190 soap->d_stream.zfree = NULL;
6191 soap->d_stream.opaque = NULL;
6195 soap->c14ninclude = NULL;
6196 soap->c14nexclude = NULL;
6197 soap->cookies = NULL;
6198 soap->cookie_domain = NULL;
6199 soap->cookie_path = NULL;
6200 soap->cookie_max = 32;
6203 soap_init_mht(soap);
6204 soap_init_logs(soap);
6205 soap_set_recv_logfile(soap, "RECV.log");
6206 soap_set_sent_logfile(soap, "SENT.log");
6207 soap_set_test_logfile(soap, NULL);
6210 soap->rpmreqid = NULL;
6215 #ifndef WITH_NOIDREF
6216 soap_init_iht(soap);
6217 soap_init_pht(soap);
6221 soap_set_test_logfile(soap, "TEST.log");
6226 /******************************************************************************/
6231 soap_init1(struct soap *soap, soap_mode mode)
6232 { soap_init2(soap, mode, mode);
6236 /******************************************************************************/
6241 soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)
6243 soap_imode(soap, imode);
6244 soap_omode(soap, omode);
6248 /******************************************************************************/
6253 soap_begin(struct soap *soap)
6254 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n"));
6255 if (!soap->keep_alive)
6259 soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
6263 soap->mustUnderstand = 0;
6266 soap->part = SOAP_END;
6271 soap->error = SOAP_OK;
6276 soap->endpoint[0] = '\0';
6278 soap->dime.chunksize = 0;
6279 soap->dime.buflen = 0;
6285 /******************************************************************************/
6290 soap_end(struct soap *soap)
6291 { register struct soap_clist *cp;
6292 if (soap_check_state(soap))
6295 soap_dealloc(soap, NULL);
6297 { cp = soap->clist->next;
6298 SOAP_FREE(soap, soap->clist);
6301 soap_closesock(soap);
6303 soap_close_logfiles(soap);
6311 /******************************************************************************/
6316 soap_set_namespaces(struct soap *soap, const struct Namespace *p)
6317 { register struct Namespace *ns = soap->local_namespaces;
6318 register struct soap_nlist *np, *nq, *nr;
6319 register unsigned int level = soap->level;
6320 soap->namespaces = p;
6321 soap->local_namespaces = NULL;
6322 soap_set_local_namespaces(soap);
6323 /* reverse the namespace list */
6336 /* then push on new stack */
6338 { register const char *s;
6339 soap->level = np->level; /* preserve element nesting level */
6341 if (!s && np->index >= 0 && ns)
6342 { s = ns[np->index].out;
6344 s = ns[np->index].ns;
6346 if (s && soap_push_namespace(soap, np->id, s))
6350 SOAP_FREE(soap, nq);
6354 for (i = 0; ns[i].id; i++)
6356 { SOAP_FREE(soap, ns[i].out);
6360 SOAP_FREE(soap, ns);
6362 soap->level = level; /* restore level */
6367 /******************************************************************************/
6372 soap_set_local_namespaces(struct soap *soap)
6373 { if (soap->namespaces && !soap->local_namespaces)
6374 { register const struct Namespace *ns1;
6375 register struct Namespace *ns2;
6376 register size_t n = 1;
6377 for (ns1 = soap->namespaces; ns1->id; ns1++)
6379 n *= sizeof(struct Namespace);
6380 ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
6382 { memcpy(ns2, soap->namespaces, n);
6384 { if (!strcmp(ns2[0].ns, soap_env1))
6389 soap->local_namespaces = ns2;
6395 /******************************************************************************/
6401 soap_strsearch(const char *big, const char *little)
6402 { size_t n = strlen(little);
6403 const char *s = big;
6405 { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' '))
6416 /******************************************************************************/
6418 static struct soap_nlist *
6419 soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
6420 { register struct soap_nlist *np;
6421 for (np = soap->nlist; np; np = np->next)
6422 { if (!strncmp(np->id, tag, n) && !np->id[n])
6429 /******************************************************************************/
6431 static struct soap_nlist *
6432 soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
6433 { register struct soap_nlist *np;
6435 if (soap_strsearch(soap->c14nexclude, id))
6437 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns?ns:""));
6439 { for (np = soap->nlist; np; np = np->next)
6440 { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
6444 { if (np->index == 1)
6445 utilized = np->index;
6455 np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
6457 { soap->error = SOAP_EOM;
6460 np->next = soap->nlist;
6464 { np->ns = np->id + n + 1;
6469 np->level = soap->level;
6470 np->index = utilized;
6475 /******************************************************************************/
6478 soap_utilize_ns(struct soap *soap, const char *tag, size_t n)
6479 { register struct soap_nlist *np = soap_lookup_ns(soap, tag, n);
6481 { if (np->index == 0)
6482 soap_push_ns(soap, np->id, np->ns, 1);
6485 { strncpy(soap->tmpbuf, tag, n);
6486 soap->tmpbuf[n] = '\0';
6487 soap_push_ns(soap, soap->tmpbuf, NULL, 1);
6492 /******************************************************************************/
6495 soap_pop_ns(struct soap *soap)
6496 { soap_pop_namespace(soap);
6500 /******************************************************************************/
6505 soap_element(struct soap *soap, const char *tag, int id, const char *type)
6508 register const char *s;
6510 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:""));
6512 if (soap->mode & SOAP_XML_DOM)
6513 { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
6515 return soap->error = SOAP_EOM;
6518 elt->prnt = soap->dom;
6519 elt->name = soap_strdup(soap, tag);
6530 { struct soap_dom_element *p = soap->dom->elts;
6537 soap->dom->elts = elt;
6547 { if (!(soap->mode & SOAP_XML_CANONICAL)
6548 && soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
6551 else if (soap->mode & SOAP_XML_INDENT)
6552 { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
6558 s = strchr(tag, ':');
6559 if (s && strncmp(tag, "SOAP-ENV", s - tag))
6560 { struct Namespace *ns = soap->local_namespaces;
6562 if (soap_send_raw(soap, "<", 1)
6563 || soap_send(soap, s + 1))
6565 if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
6567 for (; ns && ns->id; ns++)
6568 { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
6569 { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
6570 if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
6578 if (soap_send_raw(soap, "<", 1)
6579 || soap_send(soap, tag))
6585 { struct Namespace *ns;
6586 for (ns = soap->local_namespaces; ns && ns->id; ns++)
6587 { if (*ns->id && (ns->out || ns->ns))
6588 { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
6589 if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
6594 soap->ns = 1; /* start with 0 or 2, but should be one to continue */
6596 if (soap->mode & SOAP_XML_CANONICAL)
6597 { const char *t = strchr(tag, ':');
6599 soap_utilize_ns(soap, tag, t - tag);
6603 { sprintf(soap->tmpbuf, "_%d", id);
6604 if (soap_attribute(soap, "id", soap->tmpbuf))
6608 { if (soap_attribute(soap, "xsi:type", type))
6611 if (soap->mode & SOAP_XML_CANONICAL)
6612 { const char *t = strchr(type, ':');
6614 soap_utilize_ns(soap, type, t - type);
6618 if (soap->null && soap->position > 0)
6620 sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
6621 for (i = 1; i < soap->position; i++)
6622 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
6623 strcat(soap->tmpbuf, "]");
6624 if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
6627 if (soap->mustUnderstand)
6628 { if (soap->actor && *soap->actor)
6629 { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
6632 if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
6634 soap->mustUnderstand = 0;
6637 { if (soap->encodingStyle && soap->local_namespaces)
6638 { if (!*soap->encodingStyle)
6639 { if (soap->local_namespaces[1].out)
6640 soap->encodingStyle = soap->local_namespaces[1].out;
6642 soap->encodingStyle = soap->local_namespaces[1].ns;
6644 if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
6655 /******************************************************************************/
6660 soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
6663 if (soap_element(soap, tag, id, type))
6665 return soap_element_start_end_out(soap, NULL);
6669 /******************************************************************************/
6671 #ifndef HAVE_STRRCHR
6675 soap_strrchr(const char *s, int t)
6676 { register char *r = NULL;
6685 /******************************************************************************/
6691 soap_strtol(const char *s, char **t, int b)
6692 { register long n = 0;
6694 while (*s > 0 && *s <= 32)
6704 while ((c = *s) && c >= '0' && c <= '9')
6705 { if (n >= 214748364 && (n > 214748364 || c >= '8'))
6714 else /* b == 16 and value is always positive */
6716 { if (c >= '0' && c <= '9')
6718 else if (c >= 'A' && c <= 'F')
6720 else if (c >= 'a' && c <= 'f')
6736 /******************************************************************************/
6738 #ifndef HAVE_STRTOUL
6742 soap_strtoul(const char *s, char **t, int b)
6743 { unsigned long n = 0;
6745 while (*s > 0 && *s <= 32)
6750 while ((c = *s) && c >= '0' && c <= '9')
6751 { if (n >= 429496729 && (n > 429496729 || c >= '6'))
6760 { if (c >= '0' && c <= '9')
6762 else if (c >= 'A' && c <= 'F')
6764 else if (c >= 'a' && c <= 'f')
6780 /******************************************************************************/
6785 soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
6786 { if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
6788 if (soap->version == 2)
6790 s = soap_strrchr(type, '[');
6791 if ((size_t)(s - type) < sizeof(soap->tmpbuf))
6792 { strncpy(soap->tmpbuf, type, s - type);
6793 soap->tmpbuf[s - type] = '\0';
6794 if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)))
6796 if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
6801 { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset)))
6803 if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type)))
6807 if (type && *type && (soap->mode & SOAP_XML_CANONICAL))
6808 { const char *s = strchr(type, ':');
6810 soap_utilize_ns(soap, type, s - type);
6813 return soap_element_start_end_out(soap, NULL);
6817 /******************************************************************************/
6822 soap_element_start_end_out(struct soap *soap, const char *tag)
6823 { register struct soap_attribute *tp;
6825 if (soap->mode & SOAP_XML_CANONICAL)
6826 { struct soap_nlist *np;
6827 for (tp = soap->attributes; tp; tp = tp->next)
6828 { if (tp->visible && tp->name)
6829 { const char *s = strchr(tp->name, ':');
6831 soap_utilize_ns(soap, tp->name, s - tp->name);
6834 for (np = soap->nlist; np; np = np->next)
6835 { if (np->index == 1 && np->ns)
6836 { sprintf(soap->tmpbuf, "xmlns:%s", np->id);
6837 soap_set_attr(soap, soap->tmpbuf, np->ns);
6844 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
6845 { register struct soap_dom_attribute **att;
6846 att = &soap->dom->atts;
6847 for (tp = soap->attributes; tp; tp = tp->next)
6849 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
6851 return soap->error = SOAP_EOM;
6852 (*att)->next = NULL;
6853 (*att)->nstr = NULL;
6854 (*att)->name = soap_strdup(soap, tp->name);
6855 (*att)->data = soap_strdup(soap, tp->value);
6856 (*att)->wide = NULL;
6857 (*att)->soap = soap;
6858 att = &(*att)->next;
6865 for (tp = soap->attributes; tp; tp = tp->next)
6869 const char *s = strchr(tp->name, ':');
6871 { size_t n = s - tp->name;
6872 if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
6876 if (soap_send(soap, " ") || soap_send(soap, s))
6881 if (soap_send(soap, " ") || soap_send(soap, tp->name))
6883 if (tp->visible == 2 && tp->value)
6884 if (soap_send_raw(soap, "=\"", 2)
6885 || soap_string_out(soap, tp->value, 1)
6886 || soap_send_raw(soap, "\"", 1))
6894 if (soap->mode & SOAP_XML_CANONICAL)
6895 { if (soap_send_raw(soap, ">", 1)
6896 || soap_element_end_out(soap, tag))
6901 soap->level--; /* decrement level just before /> */
6902 if (soap_send_raw(soap, "/>", 2))
6906 return soap_send_raw(soap, ">", 1);
6910 /******************************************************************************/
6915 soap_element_end_out(struct soap *soap, const char *tag)
6918 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
6920 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
6921 { if (soap->dom->prnt)
6922 soap->dom = soap->dom->prnt;
6927 if (soap->mode & SOAP_XML_CANONICAL)
6929 if (soap->mode & SOAP_XML_INDENT)
6931 { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
6938 { const char *s = strchr(tag, ':');
6939 if (s && strncmp(tag, "SOAP-ENV", s - tag))
6940 { soap_pop_ns(soap);
6945 if (soap_send_raw(soap, "</", 2)
6946 || soap_send(soap, tag))
6948 soap->level--; /* decrement level just before > */
6949 return soap_send_raw(soap, ">", 1);
6953 /******************************************************************************/
6958 soap_element_ref(struct soap *soap, const char *tag, int id, int href)
6959 { register int n = 0;
6960 if (soap->version == 2)
6962 sprintf(soap->href, "#_%d", href);
6963 return soap_element_href(soap, tag, id, "href" + n, soap->href + n);
6967 /******************************************************************************/
6972 soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
6973 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
6974 if (soap_element(soap, tag, id, NULL)
6975 || soap_attribute(soap, ref, val)
6976 || soap_element_start_end_out(soap, tag))
6982 /******************************************************************************/
6987 soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
6988 { struct soap_attribute *tp;
6989 for (tp = soap->attributes; tp; tp = tp->next)
6992 if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
6993 { if (soap_element(soap, tag, id, type))
6995 if (soap->part != SOAP_IN_HEADER && soap->encodingStyle)
6996 if (soap_attribute(soap, "xsi:nil", "true"))
6998 return soap_element_start_end_out(soap, tag);
7002 soap->mustUnderstand = 0;
7007 /******************************************************************************/
7012 soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t)
7013 { if (!p || (a && !a->__ptr))
7014 { soap_element_null(soap, tag, id, type);
7017 #ifndef WITH_NOIDREF
7018 if (soap->mode & SOAP_XML_TREE)
7021 { struct soap_plist *pp;
7023 id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
7025 id = soap_pointer_lookup(soap, p, t, &pp);
7027 { if (soap_is_embedded(soap, pp))
7028 { soap_element_ref(soap, tag, 0, id);
7031 if (soap_is_single(soap, pp))
7033 soap_set_embedded(soap, pp);
7043 /******************************************************************************/
7048 soap_element_result(struct soap *soap, const char *tag)
7049 { if (soap->version == 2 && soap->encodingStyle)
7050 if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
7051 || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
7052 || soap_element_start_end_out(soap, NULL)
7053 || soap_string_out(soap, tag, 0)
7054 || soap_element_end_out(soap, "SOAP-RPC:result"))
7060 /******************************************************************************/
7065 soap_check_result(struct soap *soap, const char *tag)
7066 { if (soap->version == 2 && soap->encodingStyle)
7067 { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
7068 /* should compare tag to element's QName value? */
7073 /******************************************************************************/
7078 soap_attribute(struct soap *soap, const char *name, const char *value)
7081 if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
7082 { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
7083 a->next = soap->dom->atts;
7085 a->name = soap_strdup(soap, name);
7086 a->data = soap_strdup(soap, value);
7089 soap->dom->atts = a;
7094 if (soap->mode & SOAP_XML_CANONICAL)
7095 { /* TODO: consider using this code to handle default namespace bindings
7096 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
7097 { if (name[5] == ':')
7098 soap_push_ns(soap, name + 6, value, 0);
7100 soap_push_ns(soap, "", value, 0);
7103 if (!strncmp(name, "xmlns:", 6))
7104 soap_push_ns(soap, name + 6, value, 0);
7105 else if (soap_set_attr(soap, name, value))
7110 { if (soap_send(soap, " ") || soap_send(soap, name))
7113 if (soap_send_raw(soap, "=\"", 2)
7114 || soap_string_out(soap, value, 1)
7115 || soap_send_raw(soap, "\"", 1))
7122 /******************************************************************************/
7127 soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
7128 { if (!soap_peek_element(soap))
7130 return soap->error = SOAP_TAG_MISMATCH;
7131 if (tag && *tag == '-')
7133 if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
7137 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" ));
7138 if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
7139 return soap->error = SOAP_NULL;
7140 if (type && *soap->type && soap_match_tag(soap, soap->type, type))
7141 return soap->error = SOAP_TYPE;
7144 else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
7145 soap->error = SOAP_OK;
7150 /******************************************************************************/
7155 soap_element_end_in(struct soap *soap, const char *tag)
7156 { register soap_wchar c;
7158 register const char *t;
7160 if (tag && *tag == '-')
7163 soap_pop_namespace(soap);
7165 /* this whitespace or mixed content is not insignificant for DOM */
7166 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7167 { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
7169 if (soap->dom->prnt)
7170 soap->dom = soap->dom->prnt;
7174 { if (soap->error == SOAP_NO_TAG)
7175 soap->error = SOAP_OK;
7181 { while (((c = soap_get(soap)) != SOAP_TT))
7182 { if ((int)c == EOF)
7183 return soap->error = SOAP_EOF;
7187 { c = soap_get(soap);
7191 soap_unget(soap, c);
7196 while (soap_notblank(c = soap_get(soap)))
7200 return soap->error = SOAP_EOF;
7201 while (soap_blank(c))
7204 return soap->error = SOAP_SYNTAX_ERROR;
7205 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:""));
7208 if ((s = strchr(soap->tag, ':')))
7212 if ((t = strchr(tag, ':')))
7216 if (!SOAP_STRCMP(s, t))
7218 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n"));
7219 return soap->error = SOAP_SYNTAX_ERROR;
7223 /******************************************************************************/
7228 soap_attr_value(struct soap *soap, const char *name, int flag)
7229 { register struct soap_attribute *tp;
7230 for (tp = soap->attributes; tp; tp = tp->next)
7231 { if (tp->visible && !soap_match_tag(soap, tp->name, name))
7235 { if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
7236 soap->error = SOAP_PROHIBITED;
7240 else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
7241 soap->error = SOAP_REQUIRED;
7246 /******************************************************************************/
7251 soap_set_attr(struct soap *soap, const char *name, const char *value)
7252 { register struct soap_attribute *tp;
7253 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:""));
7254 for (tp = soap->attributes; tp; tp = tp->next)
7255 { if (!strcmp(tp->name, name))
7259 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
7260 if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
7261 return soap->error = SOAP_EOM;
7264 if (soap->mode & SOAP_XML_CANONICAL)
7265 { struct soap_attribute **tpp = &soap->attributes;
7266 const char *s = strchr(name, ':');
7267 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
7268 if (!strncmp(name, "xmlns", 5))
7269 { for (; *tpp; tpp = &(*tpp)->next)
7270 if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
7274 { for (; *tpp; tpp = &(*tpp)->next)
7275 if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
7280 for (; *tpp; tpp = &(*tpp)->next)
7281 { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name])
7283 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns));
7284 tp->ns = (*tpp)->ns;
7287 else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
7296 { tp->next = soap->attributes;
7297 soap->attributes = tp;
7299 strcpy(tp->name, name);
7302 else if (tp->visible)
7305 else if (value && tp->value && tp->size <= strlen(value))
7306 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
7307 SOAP_FREE(soap, tp->value);
7313 { tp->size = strlen(value) + 1;
7314 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
7315 return soap->error = SOAP_EOM;
7316 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value));
7318 strcpy(tp->value, value);
7319 if (!strncmp(tp->name, "xmlns:", 6))
7323 if (!strcmp(name, "wsu:Id"))
7324 { soap->part = SOAP_BEGIN_SECURITY;
7325 strncpy(soap->id, value, sizeof(soap->id));
7326 soap->id[sizeof(soap->id)-1] = '\0';
7336 /******************************************************************************/
7341 soap_clr_attr(struct soap *soap)
7342 { register struct soap_attribute *tp;
7344 if ((soap->mode & SOAP_XML_CANONICAL))
7345 { while (soap->attributes)
7346 { tp = soap->attributes->next;
7347 SOAP_FREE(soap, soap->attributes->value);
7348 SOAP_FREE(soap, soap->attributes);
7349 soap->attributes = tp;
7354 { for (tp = soap->attributes; tp; tp = tp->next)
7360 /******************************************************************************/
7363 soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
7364 { register size_t i;
7365 for (i = 0; i < n; i++)
7366 { register soap_wchar c = soap_get(soap);
7371 soap_unget(soap, '/');
7378 { soap_unget(soap, c);
7404 { soap_unget(soap, c);
7410 return soap->error = SOAP_EOF;
7414 return soap->error = SOAP_EOM;
7418 /******************************************************************************/
7424 soap_store_lab(struct soap *soap, const char *s, size_t n)
7426 return soap_append_lab(soap, s, n);
7431 /******************************************************************************/
7437 soap_append_lab(struct soap *soap, const char *s, size_t n)
7438 { if (soap->labidx + n >= soap->lablen)
7439 { register char *t = soap->labbuf;
7440 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
7441 if (soap->lablen == 0)
7442 soap->lablen = SOAP_LABLEN;
7443 while (soap->labidx + n >= soap->lablen)
7445 DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
7446 soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
7450 return soap->error = SOAP_EOM;
7453 { memcpy(soap->labbuf, t, soap->labidx);
7458 { memcpy(soap->labbuf + soap->labidx, s, n);
7466 /******************************************************************************/
7471 soap_peek_element(struct soap *soap)
7474 register struct soap_dom_attribute **att = NULL;
7475 register char *lead = NULL;
7477 register struct soap_attribute *tp;
7480 register soap_wchar c;
7484 return soap->error = SOAP_NO_TAG;
7488 c = soap_getutf8(soap);
7490 /* whitespace leading to start tag is not insignificant for DOM */
7494 { if (soap_append_lab(soap, NULL, 0))
7496 s = soap->labbuf + soap->labidx;
7497 i = soap->lablen - soap->labidx;
7498 soap->labidx = soap->lablen;
7499 while (soap_blank(c) && i--)
7501 c = soap_getutf8(soap);
7504 while (soap_blank(c));
7506 lead = soap_strdup(soap, soap->labbuf);
7509 while (soap_blank(c))
7510 c = soap_getutf8(soap);
7513 { *soap->tag = '\0';
7515 return soap->error = SOAP_EOF;
7516 soap_unget(soap, c);
7518 /* whitespace leading to end tag is not insignificant for DOM */
7519 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7520 soap->dom->tail = soap_strdup(soap, lead);
7522 return soap->error = SOAP_NO_TAG;
7525 do c = soap_get1(soap);
7526 while (soap_blank(c));
7527 i = sizeof(soap->tag);
7528 while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
7531 c = soap_get1(soap);
7533 while (soap_blank(c))
7534 c = soap_get1(soap);
7537 soap->href[0] = '\0';
7538 soap->type[0] = '\0';
7539 soap->arrayType[0] = '\0';
7540 soap->arraySize[0] = '\0';
7541 soap->arrayOffset[0] = '\0';
7546 soap->mustUnderstand = 0;
7548 if (soap->mode & SOAP_XML_DOM)
7549 { register struct soap_dom_element *elt;
7550 elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
7552 return soap->error = SOAP_EOM;
7555 elt->name = soap_strdup(soap, soap->tag);
7556 elt->prnt = soap->dom;
7567 { struct soap_dom_element *p = soap->dom->elts;
7574 soap->dom->elts = elt;
7580 for (tp = soap->attributes; tp; tp = tp->next)
7582 while ((int)c != EOF && c != '>' && c != '/')
7584 i = sizeof(soap->tmpbuf);
7585 while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
7588 c = soap_get1(soap);
7591 if (i == sizeof(soap->tmpbuf))
7592 return soap->error = SOAP_SYNTAX_ERROR;
7594 /* add attribute name to dom */
7596 { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
7598 return soap->error = SOAP_EOM;
7599 (*att)->next = NULL;
7600 (*att)->nstr = NULL;
7601 (*att)->name = soap_strdup(soap, soap->tmpbuf);
7602 (*att)->data = NULL;
7603 (*att)->wide = NULL;
7604 (*att)->soap = soap;
7607 if (!strncmp(soap->tmpbuf, "xmlns", 5))
7608 { if (soap->tmpbuf[5] == ':')
7609 { soap->tmpbuf[5] = '\0';
7610 t = soap->tmpbuf + 6;
7612 else if (soap->tmpbuf[5])
7619 for (tp = soap->attributes; tp; tp = tp->next)
7620 { if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
7624 { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
7626 return soap->error = SOAP_EOM;
7627 strcpy(tp->name, soap->tmpbuf);
7630 tp->next = soap->attributes;
7631 soap->attributes = tp;
7633 while (soap_blank(c))
7634 c = soap_get1(soap);
7636 { do c = soap_getutf8(soap);
7637 while (soap_blank(c));
7638 if (c != SOAP_QT && c != SOAP_AP)
7639 { soap_unget(soap, c);
7640 c = ' '; /* blank delimiter */
7642 if (soap_getattrval(soap, tp->value, tp->size, c))
7645 if (soap->error != SOAP_EOM)
7647 soap->error = SOAP_OK;
7648 if (soap_store_lab(soap, tp->value, tp->size))
7651 SOAP_FREE(soap, tp->value);
7653 { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
7654 { if (soap->error != SOAP_EOM)
7656 soap->error = SOAP_OK;
7657 soap->labidx = soap->lablen;
7658 if (soap_append_lab(soap, NULL, 0))
7665 tp->size = soap->lablen;
7667 { tp->size = strlen(soap->labbuf) + 1;
7668 if (tp->size < SOAP_LABLEN)
7669 tp->size = SOAP_LABLEN;
7671 if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
7672 return soap->error = SOAP_EOM;
7673 strcpy(tp->value, soap->labbuf);
7676 if (soap->error != SOAP_EOM)
7678 soap->error = SOAP_OK;
7679 if (soap_new_block(soap))
7682 { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN)))
7684 if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
7685 { if (soap->error != SOAP_EOM)
7687 soap->error = SOAP_OK;
7692 n = tp->size + soap->blist->size;
7693 if (!(s = (char*)SOAP_MALLOC(soap, n)))
7694 return soap->error = SOAP_EOM;
7696 { memcpy(s, tp->value, tp->size);
7697 SOAP_FREE(soap, tp->value);
7699 soap_save_block(soap, s + tp->size, 0);
7704 do c = soap_get1(soap);
7705 while (soap_blank(c));
7706 tp->visible = 2; /* seen this attribute w/ value */
7709 (*att)->data = soap_strdup(soap, tp->value);
7713 tp->visible = 1; /* seen this attribute w/o value */
7716 att = &(*att)->next;
7719 { if (soap_push_namespace(soap, t, tp->value))
7726 { soap->dom->nstr = soap_current_namespace(soap, soap->tag);
7727 for (att = &soap->dom->atts; *att; att = &(*att)->next)
7728 (*att)->nstr = soap_current_namespace(soap, (*att)->name);
7732 return soap->error = SOAP_EOF;
7733 if (!(soap->body = (c != '/')))
7734 do c = soap_get1(soap);
7735 while (soap_blank(c));
7737 if (soap->mode & SOAP_XML_DOM)
7738 { if (!soap->body && soap->dom->prnt)
7739 soap->dom = soap->dom->prnt;
7742 for (tp = soap->attributes; tp; tp = tp->next)
7743 { if (tp->visible && tp->value)
7744 { if (!strcmp(tp->name, "id"))
7746 strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
7747 soap->id[sizeof(soap->id)-1] = '\0';
7749 else if (!strcmp(tp->name, "href"))
7750 { strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
7751 soap->href[sizeof(soap->href)-1] = '\0';
7753 else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref"))
7754 { *soap->href = '#';
7755 strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
7756 soap->href[sizeof(soap->href)-1] = '\0';
7758 else if (!soap_match_tag(soap, tp->name, "xsi:type"))
7759 { strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
7760 soap->type[sizeof(soap->type)-1] = '\0';
7762 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
7763 { s = soap_strrchr(tp->value, '[');
7764 if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
7765 { strncpy(soap->arrayType, tp->value, s - tp->value);
7766 soap->arrayType[s - tp->value] = '\0';
7767 strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
7770 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
7771 soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
7772 soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
7774 else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
7775 strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
7776 else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
7777 strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
7778 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
7779 strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
7780 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
7781 soap->position = soap_getposition(tp->value, soap->positions);
7782 else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
7783 soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
7784 else if ((soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
7785 || (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENV:role")))
7786 { if ((!soap->actor || strcmp(soap->actor, tp->value))
7787 && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")
7788 && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
7791 else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
7792 && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
7793 soap->mustUnderstand = 1;
7794 else if ((!soap_match_tag(soap, tp->name, "xsi:null")
7795 || !soap_match_tag(soap, tp->name, "xsi:nil"))
7796 && (!strcmp(tp->value, "1")
7797 || !strcmp(tp->value, "true")))
7801 return soap->error = SOAP_OK;
7805 /******************************************************************************/
7810 soap_retry(struct soap *soap)
7811 { soap->error = SOAP_OK;
7816 /******************************************************************************/
7821 soap_revert(struct soap *soap)
7822 { if (!soap->peeked)
7827 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
7831 /******************************************************************************/
7836 soap_string_out(struct soap *soap, const char *s, int flag)
7837 { register const char *t;
7838 register soap_wchar c;
7839 register soap_wchar mask = 0xFFFFFF80UL;
7841 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7842 { soap->dom->data = soap_strdup(soap, s);
7846 if (soap->mode & SOAP_C_UTFSTRING)
7854 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "	", 5))
7860 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
7861 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
7867 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
7872 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5))
7877 if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4))
7883 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4))
7890 { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6))
7898 if (soap->mode & SOAP_C_MBSTRING)
7900 register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
7901 if (m > 0 && wc != c)
7902 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
7911 { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
7917 return soap_send_raw(soap, s, t - s - 1);
7921 /******************************************************************************/
7926 soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
7930 register long l = 0;
7933 register soap_wchar c;
7934 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
7935 char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
7939 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n"));
7949 strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1);
7950 strncat(t, ">", sizeof(soap->tmpbuf));
7951 m = strlen(soap->tag) + 2;
7957 { register int state = 0;
7959 soap->labidx = 0; /* use look-aside buffer */
7961 if (soap_new_block(soap))
7968 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
7970 s = soap->labbuf + soap->labidx; /* space to populate */
7971 k = soap->lablen - soap->labidx; /* number of bytes available */
7972 soap->labidx = soap->lablen; /* claim this space */
7974 register size_t k = SOAP_BLKLEN;
7975 if (!(s = (char*)soap_push_block(soap, k)))
7978 for (i = 0; i < k; i++)
7980 { *s++ = *t++; /* copy multibyte characters */
7984 c = soap_getchar(soap);
7987 if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN))
7988 { soap_unget(soap, c);
7989 c = soap_getutf8(soap);
7990 if (soap->mode & SOAP_C_UTFSTRING)
7991 { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
7995 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
7998 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
8001 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
8003 { if (c < 0x04000000)
8004 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
8006 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
8007 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
8009 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
8011 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
8013 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
8015 *t++ = (char)(0x80 | (c & 0x3F));
8016 m = (int)(t - buf) - 1;
8082 { c = soap_getchar(soap);
8085 soap_unget(soap, c);
8090 c = soap_getchar(soap);
8099 { c = soap_getchar(soap);
8101 { do c = soap_getchar(soap);
8102 while ((int)c != EOF && c != '[');
8105 t = (char*)"![CDATA[";
8110 { if ((c = soap_getchar(soap)) == '-')
8114 soap_unget(soap, c);
8119 soap_unget(soap, c);
8128 soap_unget(soap, c);
8140 if (soap->mode & SOAP_C_MBSTRING)
8141 { m = wctomb(buf, c & 0x7FFFFFFF);
8142 if (m >= 1 && m <= (int)MB_CUR_MAX)
8148 { *s++ = SOAP_UNKNOWN_CHAR;
8155 *s++ = (char)(c & 0xFF);
8158 if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8159 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8160 soap->error = SOAP_LENGTH;
8168 soap->labidx = 0; /* use look-aside buffer */
8170 if (soap_new_block(soap))
8177 if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
8179 s = soap->labbuf + soap->labidx; /* space to populate */
8180 k = soap->lablen - soap->labidx; /* number of bytes available */
8181 soap->labidx = soap->lablen; /* claim this space */
8183 register size_t k = SOAP_BLKLEN;
8184 if (!(s = (char*)soap_push_block(soap, k)))
8187 for (i = 0; i < k; i++)
8189 { *s++ = *t++; /* copy multibyte characters */
8193 if (soap->mode & SOAP_C_UTFSTRING)
8194 { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
8198 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
8201 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
8204 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
8206 { if (c < 0x04000000)
8207 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
8209 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
8210 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
8212 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
8214 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
8216 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
8218 *t++ = (char)(0x80 | (c & 0x3F));
8219 m = (int)(t - buf) - 1;
8226 c = soap_getutf8(soap);
8252 { c = soap_get(soap);
8255 soap_unget(soap, c);
8259 case '<' | 0x80000000:
8268 case '>' | 0x80000000:
8277 case '&' | 0x80000000:
8286 case '"' | 0x80000000:
8295 case '\'' | 0x80000000:
8309 if (soap->mode & SOAP_C_MBSTRING)
8310 { m = wctomb(buf, c & 0x7FFFFFFF);
8311 if (m >= 1 && m <= (int)MB_CUR_MAX)
8317 { *s++ = SOAP_UNKNOWN_CHAR;
8324 *s++ = (char)(c & 0xFF);
8327 if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8328 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8329 soap->error = SOAP_LENGTH;
8335 soap_unget(soap, c);
8338 t = soap_strdup(soap, soap->labbuf);
8340 soap_size_block(soap, i+1);
8341 t = soap_save_block(soap, NULL, 0);
8343 if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
8344 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
8345 soap->error = SOAP_LENGTH;
8349 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8351 soap->dom->tail = t;
8353 soap->dom->data = t;
8357 if (soap_s2QName(soap, t, &t))
8363 /******************************************************************************/
8369 soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
8372 register soap_wchar c;
8374 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8375 { wchar_t *r = (wchar_t*)s;
8379 soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
8395 if (flag || !(soap->mode & SOAP_XML_CANONICAL))
8422 if (c > 0 && c < 0x80)
8424 if (soap_send_raw(soap, &tmp, 1))
8427 else if (soap_pututf8(soap, (unsigned long)c))
8431 if (soap_send(soap, t))
8439 /******************************************************************************/
8445 soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
8447 register int i, n = 0;
8448 register long l = 0;
8449 register soap_wchar c;
8450 const char *t = NULL;
8451 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
8460 if (soap_new_block(soap))
8463 { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN)))
8465 for (i = 0; i < SOAP_BLKLEN; i++)
8467 { *s++ = (wchar_t)*t++;
8472 c = soap_getutf8(soap);
8480 soap_unget(soap, '/');
8497 { c = soap_getutf8(soap);
8500 soap_unget(soap, c);
8506 *s++ = (soap_wchar)'<';
8508 { *s++ = (soap_wchar)'&';
8514 *s++ = (soap_wchar)'>';
8516 { *s++ = (soap_wchar)'&';
8522 *s++ = (soap_wchar)'"';
8524 { *s++ = (soap_wchar)'&';
8531 *s++ = (wchar_t)c & 0x7FFFFFFF;
8534 if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8535 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8536 soap->error = SOAP_LENGTH;
8542 soap_unget(soap, c);
8544 soap_size_block(soap, sizeof(wchar_t) * (i + 1));
8545 if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
8546 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
8547 soap->error = SOAP_LENGTH;
8550 s = (wchar_t*)soap_save_block(soap, NULL, 0);
8552 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8553 soap->dom->wide = s;
8560 /******************************************************************************/
8565 soap_int2s(struct soap *soap, int n)
8566 { return soap_long2s(soap, (long)n);
8570 /******************************************************************************/
8575 soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
8576 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8577 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
8579 return soap_element_end_out(soap, tag);
8583 /******************************************************************************/
8588 soap_s2int(struct soap *soap, const char *s, int *p)
8596 *p = (int)soap_strtol(s, &r, 10);
8597 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
8600 || soap_errno == SOAP_ERANGE
8604 soap->error = SOAP_TYPE;
8610 /******************************************************************************/
8615 soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
8616 { if (soap_element_begin_in(soap, tag, 0, NULL))
8620 && soap_match_tag(soap, soap->type, type)
8621 && soap_match_tag(soap, soap->type, ":int")
8622 && soap_match_tag(soap, soap->type, ":short")
8623 && soap_match_tag(soap, soap->type, ":byte"))
8624 { soap->error = SOAP_TYPE;
8629 p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
8631 p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
8633 { if (soap_s2int(soap, soap_value(soap), p))
8636 if (soap->body && soap_element_end_in(soap, tag))
8642 /******************************************************************************/
8647 soap_long2s(struct soap *soap, long n)
8648 { sprintf(soap->tmpbuf, "%ld", n);
8649 return soap->tmpbuf;
8653 /******************************************************************************/
8658 soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
8659 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8660 || soap_string_out(soap, soap_long2s(soap, *p), 0))
8662 return soap_element_end_out(soap, tag);
8666 /******************************************************************************/
8671 soap_s2long(struct soap *soap, const char *s, long *p)
8679 *p = soap_strtol(s, &r, 10);
8680 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
8683 || soap_errno == SOAP_ERANGE
8687 soap->error = SOAP_TYPE;
8693 /******************************************************************************/
8698 soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
8699 { if (soap_element_begin_in(soap, tag, 0, NULL))
8703 && soap_match_tag(soap, soap->type, type)
8704 && soap_match_tag(soap, soap->type, ":int")
8705 && soap_match_tag(soap, soap->type, ":short")
8706 && soap_match_tag(soap, soap->type, ":byte"))
8707 { soap->error = SOAP_TYPE;
8712 p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
8714 p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
8716 { if (soap_s2long(soap, soap_value(soap), p))
8719 if (soap->body && soap_element_end_in(soap, tag))
8725 /******************************************************************************/
8730 soap_LONG642s(struct soap *soap, LONG64 n)
8731 { sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
8732 return soap->tmpbuf;
8736 /******************************************************************************/
8741 soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
8742 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8743 || soap_string_out(soap, soap_LONG642s(soap, *p), 0))
8745 return soap_element_end_out(soap, tag);
8749 /******************************************************************************/
8754 soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
8764 *p = strtoll(s, &r, 10);
8765 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
8768 || soap_errno == SOAP_ERANGE
8774 if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
8777 soap->error = SOAP_TYPE;
8783 /******************************************************************************/
8788 soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
8789 { if (soap_element_begin_in(soap, tag, 0, NULL))
8793 && soap_match_tag(soap, soap->type, type)
8794 && soap_match_tag(soap, soap->type, ":integer")
8795 && soap_match_tag(soap, soap->type, ":positiveInteger")
8796 && soap_match_tag(soap, soap->type, ":negativeInteger")
8797 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
8798 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
8799 && soap_match_tag(soap, soap->type, ":long")
8800 && soap_match_tag(soap, soap->type, ":int")
8801 && soap_match_tag(soap, soap->type, ":short")
8802 && soap_match_tag(soap, soap->type, ":byte"))
8803 { soap->error = SOAP_TYPE;
8808 p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
8810 p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
8812 { if (soap_s2LONG64(soap, soap_value(soap), p))
8815 if (soap->body && soap_element_end_in(soap, tag))
8821 /******************************************************************************/
8826 soap_byte2s(struct soap *soap, char n)
8827 { return soap_long2s(soap, (long)n);
8831 /******************************************************************************/
8836 soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
8837 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8838 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
8840 return soap_element_end_out(soap, tag);
8844 /******************************************************************************/
8849 soap_s2byte(struct soap *soap, const char *s, char *p)
8853 n = soap_strtol(s, &r, 10);
8854 if (s == r || *r || n < -128 || n > 127)
8855 soap->error = SOAP_TYPE;
8862 /******************************************************************************/
8867 soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
8868 { if (soap_element_begin_in(soap, tag, 0, NULL))
8872 && soap_match_tag(soap, soap->type, type)
8873 && soap_match_tag(soap, soap->type, ":byte"))
8874 { soap->error = SOAP_TYPE;
8879 p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
8881 p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
8883 { if (soap_s2byte(soap, soap_value(soap), p))
8886 if (soap->body && soap_element_end_in(soap, tag))
8892 /******************************************************************************/
8897 soap_short2s(struct soap *soap, short n)
8898 { return soap_long2s(soap, (long)n);
8902 /******************************************************************************/
8907 soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
8908 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8909 || soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
8911 return soap_element_end_out(soap, tag);
8915 /******************************************************************************/
8920 soap_s2short(struct soap *soap, const char *s, short *p)
8924 n = soap_strtol(s, &r, 10);
8925 if (s == r || *r || n < -32768 || n > 32767)
8926 soap->error = SOAP_TYPE;
8933 /******************************************************************************/
8938 soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
8939 { if (soap_element_begin_in(soap, tag, 0, NULL))
8943 && soap_match_tag(soap, soap->type, type)
8944 && soap_match_tag(soap, soap->type, ":short")
8945 && soap_match_tag(soap, soap->type, ":byte"))
8946 { soap->error = SOAP_TYPE;
8951 p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
8953 p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
8955 { if (soap_s2short(soap, soap_value(soap), p))
8958 if (soap->body && soap_element_end_in(soap, tag))
8964 /******************************************************************************/
8969 soap_float2s(struct soap *soap, float n)
8971 if (soap_isnan((double)n))
8973 else if (soap_ispinff(n))
8975 else if (soap_isninff(n))
8980 sprintf(soap->tmpbuf, soap->float_format, n);
8981 t = strchr(s, ','); /* convert decimal comma to DP */
8989 /******************************************************************************/
8994 soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
8995 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
8996 || soap_string_out(soap, soap_float2s(soap, *p), 0))
8998 return soap_element_end_out(soap, tag);
9002 /******************************************************************************/
9007 soap_s2float(struct soap *soap, const char *s, float *p)
9010 return soap->error = SOAP_TYPE;
9011 if (!soap_tag_cmp(s, "INF"))
9013 else if (!soap_tag_cmp(s, "+INF"))
9015 else if (!soap_tag_cmp(s, "-INF"))
9017 else if (!soap_tag_cmp(s, "NaN"))
9021 /* On some systems, strtof appears to be broken or doesn't link: use with caution */
9022 #if defined(HAVE_STRTOF)
9024 *p = strtof((char*)s, &r);
9026 #elif defined(HAVE_STRTOD)
9028 *p = (float)strtod(s, &r);
9032 if (sscanf(s, "%g", p) != 1)
9033 soap->error = SOAP_TYPE;
9035 soap->error = SOAP_TYPE;
9043 /******************************************************************************/
9045 static int soap_isnumeric(struct soap *soap, const char *type)
9046 { if (soap_match_tag(soap, soap->type, type)
9047 && soap_match_tag(soap, soap->type, ":float")
9048 && soap_match_tag(soap, soap->type, ":double")
9049 && soap_match_tag(soap, soap->type, ":decimal")
9050 && soap_match_tag(soap, soap->type, ":integer")
9051 && soap_match_tag(soap, soap->type, ":positiveInteger")
9052 && soap_match_tag(soap, soap->type, ":negativeInteger")
9053 && soap_match_tag(soap, soap->type, ":nonPositiveInteger")
9054 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
9055 && soap_match_tag(soap, soap->type, ":long")
9056 && soap_match_tag(soap, soap->type, ":int")
9057 && soap_match_tag(soap, soap->type, ":short")
9058 && soap_match_tag(soap, soap->type, ":byte")
9059 && soap_match_tag(soap, soap->type, ":unsignedLong")
9060 && soap_match_tag(soap, soap->type, ":unsignedInt")
9061 && soap_match_tag(soap, soap->type, ":unsignedShort")
9062 && soap_match_tag(soap, soap->type, ":unsignedByte"))
9063 { soap->error = SOAP_TYPE;
9071 /******************************************************************************/
9076 soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
9077 { if (soap_element_begin_in(soap, tag, 0, NULL))
9080 if (*soap->type != '\0' && soap_isnumeric(soap, type))
9083 p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
9085 p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
9087 { if (soap_s2float(soap, soap_value(soap), p))
9090 if (soap->body && soap_element_end_in(soap, tag))
9096 /******************************************************************************/
9101 soap_double2s(struct soap *soap, double n)
9105 else if (soap_ispinfd(n))
9107 else if (soap_isninfd(n))
9112 sprintf(soap->tmpbuf, soap->double_format, n);
9113 t = strchr(s, ','); /* convert decimal comma to DP */
9121 /******************************************************************************/
9126 soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
9127 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9128 || soap_string_out(soap, soap_double2s(soap, *p), 0))
9130 return soap_element_end_out(soap, tag);
9134 /******************************************************************************/
9139 soap_s2double(struct soap *soap, const char *s, double *p)
9142 return soap->error = SOAP_TYPE;
9143 if (!soap_tag_cmp(s, "INF"))
9145 else if (!soap_tag_cmp(s, "+INF"))
9147 else if (!soap_tag_cmp(s, "-INF"))
9149 else if (!soap_tag_cmp(s, "NaN"))
9159 if (sscanf(s, "%lg", p) != 1)
9160 soap->error = SOAP_TYPE;
9162 soap->error = SOAP_TYPE;
9170 /******************************************************************************/
9175 soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
9176 { if (soap_element_begin_in(soap, tag, 0, NULL))
9179 if (*soap->type != '\0' && soap_isnumeric(soap, type))
9182 p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
9184 p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
9186 { if (soap_s2double(soap, soap_value(soap), p))
9189 if (soap->body && soap_element_end_in(soap, tag))
9195 /******************************************************************************/
9200 soap_unsignedByte2s(struct soap *soap, unsigned char n)
9201 { return soap_unsignedLong2s(soap, (unsigned long)n);
9205 /******************************************************************************/
9210 soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
9211 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9212 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9214 return soap_element_end_out(soap, tag);
9218 /******************************************************************************/
9223 soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
9227 n = soap_strtoul(s, &r, 10);
9228 if (s == r || *r || n > 255)
9229 soap->error = SOAP_TYPE;
9230 *p = (unsigned char)n;
9236 /******************************************************************************/
9241 soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
9242 { if (soap_element_begin_in(soap, tag, 0, NULL))
9246 && soap_match_tag(soap, soap->type, type)
9247 && soap_match_tag(soap, soap->type, ":unsignedByte"))
9248 { soap->error = SOAP_TYPE;
9253 p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
9255 p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
9257 { if (soap_s2unsignedByte(soap, soap_value(soap), p))
9260 if (soap->body && soap_element_end_in(soap, tag))
9266 /******************************************************************************/
9271 soap_unsignedShort2s(struct soap *soap, unsigned short n)
9272 { return soap_unsignedLong2s(soap, (unsigned long)n);
9276 /******************************************************************************/
9281 soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
9282 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9283 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9285 return soap_element_end_out(soap, tag);
9289 /******************************************************************************/
9294 soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
9298 n = soap_strtoul(s, &r, 10);
9299 if (s == r || *r || n > 65535)
9300 soap->error = SOAP_TYPE;
9301 *p = (unsigned short)n;
9307 /******************************************************************************/
9312 soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
9313 { if (soap_element_begin_in(soap, tag, 0, NULL))
9317 && soap_match_tag(soap, soap->type, type)
9318 && soap_match_tag(soap, soap->type, ":unsignedShort")
9319 && soap_match_tag(soap, soap->type, ":unsignedByte"))
9320 { soap->error = SOAP_TYPE;
9325 p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
9327 p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
9329 { if (soap_s2unsignedShort(soap, soap_value(soap), p))
9332 if (soap->body && soap_element_end_in(soap, tag))
9338 /******************************************************************************/
9343 soap_unsignedInt2s(struct soap *soap, unsigned int n)
9344 { return soap_unsignedLong2s(soap, (unsigned long)n);
9348 /******************************************************************************/
9353 soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
9354 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9355 || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9357 return soap_element_end_out(soap, tag);
9361 /******************************************************************************/
9366 soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
9374 *p = (unsigned int)soap_strtoul(s, &r, 10);
9375 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9378 || soap_errno == SOAP_ERANGE
9382 soap->error = SOAP_TYPE;
9388 /******************************************************************************/
9393 soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
9394 { if (soap_element_begin_in(soap, tag, 0, NULL))
9398 && soap_match_tag(soap, soap->type, type)
9399 && soap_match_tag(soap, soap->type, ":unsignedInt")
9400 && soap_match_tag(soap, soap->type, ":unsignedShort")
9401 && soap_match_tag(soap, soap->type, ":unsignedByte"))
9402 { soap->error = SOAP_TYPE;
9407 p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
9409 p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
9411 { if (soap_s2unsignedInt(soap, soap_value(soap), p))
9414 if (soap->body && soap_element_end_in(soap, tag))
9420 /******************************************************************************/
9425 soap_unsignedLong2s(struct soap *soap, unsigned long n)
9426 { sprintf(soap->tmpbuf, "%lu", n);
9427 return soap->tmpbuf;
9431 /******************************************************************************/
9436 soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
9437 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9438 || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
9440 return soap_element_end_out(soap, tag);
9444 /******************************************************************************/
9449 soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
9457 *p = soap_strtoul(s, &r, 10);
9458 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9461 || soap_errno == SOAP_ERANGE
9465 soap->error = SOAP_TYPE;
9471 /******************************************************************************/
9476 soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
9477 { if (soap_element_begin_in(soap, tag, 0, NULL))
9481 && soap_match_tag(soap, soap->type, type)
9482 && soap_match_tag(soap, soap->type, ":unsignedInt")
9483 && soap_match_tag(soap, soap->type, ":unsignedShort")
9484 && soap_match_tag(soap, soap->type, ":unsignedByte"))
9485 { soap->error = SOAP_TYPE;
9490 p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
9492 p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
9494 { if (soap_s2unsignedLong(soap, soap_value(soap), p))
9497 if (soap->body && soap_element_end_in(soap, tag))
9503 /******************************************************************************/
9508 soap_ULONG642s(struct soap *soap, ULONG64 n)
9509 { sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
9510 return soap->tmpbuf;
9514 /******************************************************************************/
9519 soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
9520 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9521 || soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
9523 return soap_element_end_out(soap, tag);
9527 /******************************************************************************/
9532 soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
9535 #ifdef HAVE_STRTOULL
9542 *p = strtoull(s, &r, 10);
9543 if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9546 || soap_errno == SOAP_ERANGE
9552 if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
9555 soap->error = SOAP_TYPE;
9561 /******************************************************************************/
9566 soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
9567 { if (soap_element_begin_in(soap, tag, 0, NULL))
9570 && soap_match_tag(soap, soap->type, type)
9571 && soap_match_tag(soap, soap->type, ":positiveInteger")
9572 && soap_match_tag(soap, soap->type, ":nonNegativeInteger")
9573 && soap_match_tag(soap, soap->type, ":unsignedLong")
9574 && soap_match_tag(soap, soap->type, ":unsignedInt")
9575 && soap_match_tag(soap, soap->type, ":unsignedShort")
9576 && soap_match_tag(soap, soap->type, ":unsignedByte"))
9577 { soap->error = SOAP_TYPE;
9581 p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
9583 p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
9585 { if (soap_s2ULONG64(soap, soap_value(soap), p))
9588 if (soap->body && soap_element_end_in(soap, tag))
9594 /******************************************************************************/
9599 soap_s2string(struct soap *soap, const char *s, char **t)
9602 { if (!(*t = soap_strdup(soap, s)))
9603 return soap->error = SOAP_EOM;
9604 if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
9605 { /* TODO: consider truncating UTF8 to ASCII for regular XML attribute strings? */
9612 /******************************************************************************/
9617 soap_s2QName(struct soap *soap, const char *s, char **t)
9619 { struct soap_nlist *np;
9621 if (!strncmp(s, "xml:", 4))
9622 { *t = soap_strdup(soap, s);
9628 { register int n = p - s;
9629 while (np && (strncmp(np->id, s, n) || np->id[n]))
9634 { while (np && *np->id)
9639 { if (np->index >= 0 && soap->local_namespaces)
9640 { register const char *q = soap->local_namespaces[np->index].id;
9642 { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2)))
9643 sprintf(*t, "%s:%s", q, p);
9648 { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4)))
9649 sprintf(*t, "\"%s\":%s", np->ns, p);
9652 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:""));
9653 return soap->error = SOAP_NAMESPACE;
9655 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s));
9656 if ((*t = (char*)soap_malloc(soap, strlen(p) + 4)))
9657 sprintf(*t, "\"\":%s", p);
9665 /******************************************************************************/
9670 soap_QName2s(struct soap *soap, const char *s)
9671 { struct Namespace *p;
9674 if (!s || *s != '"')
9677 if (s && (soap->mode & SOAP_XML_CANONICAL))
9678 { t = (char*)strchr(s, ':');
9680 soap_utilize_ns(soap, s, t - s);
9686 if ((p = soap->local_namespaces))
9687 { for (; p->id; p++)
9689 if (!soap_tag_cmp(s, p->ns))
9692 if (!soap_tag_cmp(s, p->in))
9696 { s = strchr(s, '"');
9698 { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s));
9705 t = (char*)strchr(s, '"');
9710 t = soap_strdup(soap, s);
9712 sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
9713 soap_set_attr(soap, soap->tmpbuf, t);
9716 { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6);
9717 strcpy(t, soap->tmpbuf + 6);
9724 /******************************************************************************/
9729 soap_s2wchar(struct soap *soap, const char *s, wchar_t **t)
9734 { *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
9737 if (soap->mode & SOAP_ENC_LATIN)
9739 *r++ = (wchar_t)*s++;
9742 { /* Convert UTF8 to wchar */
9744 { register soap_wchar c, c1, c2, c3, c4;
9749 { c1 = (soap_wchar)*s++ & 0x3F;
9751 *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
9753 { c2 = (soap_wchar)*s++ & 0x3F;
9755 *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
9757 { c3 = (soap_wchar)*s++ & 0x3F;
9759 *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
9761 { c4 = (soap_wchar)*s++ & 0x3F;
9763 *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
9765 *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
9778 /******************************************************************************/
9783 soap_wchar2s(struct soap *soap, const wchar_t *s)
9784 { register soap_wchar c;
9785 register char *r, *t;
9786 const wchar_t *q = s;
9789 { if (c > 0 && c < 0x80)
9794 r = t = (char*)soap_malloc(soap, n + 1);
9796 { /* Convert wchar to UTF8 */
9798 { if (c > 0 && c < 0x80)
9802 *t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
9805 *t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
9808 *t++ = (char)(0xF0 | ((c >> 18) & 0x07));
9810 { if (c < 0x04000000)
9811 *t++ = (char)(0xF8 | ((c >> 24) & 0x03));
9813 { *t++ = (char)(0xFC | ((c >> 30) & 0x01));
9814 *t++ = (char)(0x80 | ((c >> 24) & 0x3F));
9816 *t++ = (char)(0x80 | ((c >> 18) & 0x3F));
9818 *t++ = (char)(0x80 | ((c >> 12) & 0x3F));
9820 *t++ = (char)(0x80 | ((c >> 6) & 0x3F));
9822 *t++ = (char)(0x80 | (c & 0x3F));
9831 /******************************************************************************/
9836 soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
9837 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
9840 if (!**p && (soap->mode & SOAP_C_NILSTRING))
9841 return soap_element_null(soap, tag, id, type);
9842 if (soap_element_begin_out(soap, tag, id, type)
9843 || soap_string_out(soap, *p, 0)
9844 || soap_element_end_out(soap, tag))
9850 /******************************************************************************/
9855 soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
9856 { if (soap_element_begin_in(soap, tag, 1, NULL))
9857 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
9859 soap->error = SOAP_OK;
9862 if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
9865 { *p = soap_string_in(soap, flag, minlen, maxlen);
9866 if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
9869 else if (soap->null)
9872 *p = (char*)SOAP_STR_EOS;
9874 p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
9875 if (soap->body && soap_element_end_in(soap, tag))
9881 /******************************************************************************/
9887 soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
9888 { id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
9891 if (!**p && (soap->mode & SOAP_C_NILSTRING))
9892 return soap_element_null(soap, tag, id, type);
9893 if (soap_element_begin_out(soap, tag, id, type)
9894 || soap_wstring_out(soap, *p, 0)
9895 || soap_element_end_out(soap, tag))
9902 /******************************************************************************/
9908 soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
9909 { if (soap_element_begin_in(soap, tag, 1, NULL))
9910 { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
9912 soap->error = SOAP_OK;
9915 if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
9918 { *p = soap_wstring_in(soap, 1, minlen, maxlen);
9919 if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
9922 else if (soap->null)
9925 *p = (wchar_t*)SOAP_STR_EOS;
9927 p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
9928 if (soap->body && soap_element_end_in(soap, tag))
9935 /******************************************************************************/
9938 soap_timegm(struct tm *T)
9940 #if defined(HAVE_TIMEGM)
9944 #ifdef HAVE_GMTIME_R
9945 struct tm tm, *tmp = &tm;
9952 #ifdef HAVE_GMTIME_R
9967 /******************************************************************************/
9972 soap_dateTime2s(struct soap *soap, time_t n)
9973 { struct tm T, *pT = &T;
9974 #if defined(HAVE_GMTIME_R)
9975 if (gmtime_r(&n, pT))
9976 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9977 /* The following defines were added for VxWorks*/
9978 #elif defined(HAVE_PGMTIME_R)
9979 if (gmtime_r(&n, pT))
9980 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9981 #elif defined(HAVE_PGMTIME)
9983 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9984 #elif defined(HAVE_GMTIME)
9985 if ((pT = gmtime(&n)))
9986 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
9987 #elif defined(HAVE_GETTIMEOFDAY)
9989 memset((void*)&tz, 0, sizeof(tz));
9990 # if defined(HAVE_LOCALTIME_R)
9991 if (localtime_r(&n, pT))
9992 { struct timeval tv;
9993 gettimeofday(&tv, &tz);
9994 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
9995 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
9998 if ((pT = localtime(&n)))
9999 { struct timeval tv;
10000 gettimeofday(&tv, &tz);
10001 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10002 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
10005 #elif defined(HAVE_FTIME)
10007 memset((void*)&t, 0, sizeof(t));
10008 # if defined(HAVE_LOCALTIME_R)
10009 if (localtime_r(&n, pT))
10011 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10012 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
10014 /* The following defines were added for VxWorks*/
10015 # elif defined(HAVE_PLOCALTIME_R)
10016 if (localtime_r(&n, pT))
10017 { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10018 sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60);
10021 if ((pT = localtime(&n)))
10023 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10024 sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
10027 #elif defined(HAVE_LOCALTIME_R)
10028 if (localtime_r(&n, pT))
10029 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10030 /* The following defines were added for VxWorks*/
10031 #elif defined(HAVE_PLOCALTIME_R)
10032 if (localtime_r(&n, pT))
10033 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10035 if ((pT = localtime(&n)))
10036 strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10039 strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
10040 return soap->tmpbuf;
10044 /******************************************************************************/
10049 soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
10050 { if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
10051 || soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
10052 return soap->error;
10053 return soap_element_end_out(soap, tag);
10057 /******************************************************************************/
10062 soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
10067 memset((void*)&T, 0, sizeof(T));
10068 zone[sizeof(zone)-1] = '\0';
10069 if (strchr(s, '-'))
10070 t = "%d-%d-%dT%d:%d:%d%31s";
10071 else if (strchr(s, ':'))
10072 t = "%4d%2d%2dT%d:%d:%d%31s";
10073 else /* parse non-XSD-standard alternative ISO 8601 format */
10074 t = "%4d%2d%2dT%2d%2d%2d%31s";
10075 sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone);
10076 if (T.tm_year == 1)
10082 { if (*zone == '.')
10083 { for (s = zone + 1; *s; s++)
10084 if (*s < '0' || *s > '9')
10089 if (*s == '+' || *s == '-')
10090 { int h = 0, m = 0;
10092 { sscanf(s, "%d:%d", &h, &m);
10097 { m = (int)atol(s);
10105 *p = soap_timegm(&T);
10109 *p = mktime(&T); /* no time zone: suppose it is localtime? */
10112 return soap->error;
10116 /******************************************************************************/
10121 soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
10122 { if (soap_element_begin_in(soap, tag, 0, NULL))
10125 && soap_match_tag(soap, soap->type, type)
10126 && soap_match_tag(soap, soap->type, ":dateTime"))
10127 { soap->error = SOAP_TYPE;
10131 p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
10133 p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
10135 { if (soap_s2dateTime(soap, soap_value(soap), p))
10138 if (soap->body && soap_element_end_in(soap, tag))
10144 /******************************************************************************/
10149 soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
10151 const char *t = NULL;
10152 if (tag && *tag != '-')
10153 { if (soap->local_namespaces && (t = strchr(tag, ':')))
10154 { strncpy(soap->tmpbuf, tag, t-tag);
10155 soap->tmpbuf[t-tag] = '\0';
10156 for (i = 0; soap->local_namespaces[i].id; i++)
10157 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
10160 if (soap_element(soap, t, 0, type)
10161 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
10162 || soap_element_start_end_out(soap, NULL))
10163 return soap->error;
10167 if (soap_element_begin_out(soap, t, 0, type))
10168 return soap->error;
10172 { if (soap_send(soap, *p))
10173 return soap->error;
10176 return soap_element_end_out(soap, t);
10181 /******************************************************************************/
10186 soap_inliteral(struct soap *soap, const char *tag, char **p)
10187 { if (soap_element_begin_in(soap, tag, 1, NULL))
10188 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
10190 soap->error = SOAP_OK;
10193 if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
10196 *p = soap_string_in(soap, 0, -1, -1);
10197 else if (soap->null)
10200 *p = (char*)SOAP_STR_EOS;
10201 if (soap->body && soap_element_end_in(soap, tag))
10207 /******************************************************************************/
10208 #ifndef WITH_LEANER
10213 soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
10215 const char *t = NULL;
10216 if (tag && *tag != '-')
10217 { if (soap->local_namespaces && (t = strchr(tag, ':')))
10218 { strncpy(soap->tmpbuf, tag, t-tag);
10219 soap->tmpbuf[t-tag] = '\0';
10220 for (i = 0; soap->local_namespaces[i].id; i++)
10221 if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
10224 if (soap_element(soap, t, 0, type)
10225 || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
10226 || soap_element_start_end_out(soap, NULL))
10227 return soap->error;
10231 if (soap_element_begin_out(soap, t, 0, type))
10232 return soap->error;
10234 if (soap_send(soap, soap->tmpbuf))
10235 return soap->error;
10239 const wchar_t *s = *p;
10241 { if (soap_pututf8(soap, (unsigned long)c))
10242 return soap->error;
10246 return soap_element_end_out(soap, t);
10252 /******************************************************************************/
10253 #ifndef WITH_LEANER
10258 soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
10259 { if (soap_element_begin_in(soap, tag, 1, NULL))
10260 { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
10262 soap->error = SOAP_OK;
10265 if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
10268 *p = soap_wstring_in(soap, 0, -1, -1);
10269 else if (soap->null)
10272 *p = (wchar_t*)SOAP_STR_EOS;
10273 if (soap->body && soap_element_end_in(soap, tag))
10280 /******************************************************************************/
10285 soap_value(struct soap *soap)
10286 { register size_t i;
10287 register soap_wchar c = 0;
10288 register char *s = soap->tmpbuf;
10290 return SOAP_STR_EOS;
10291 do c = soap_get(soap);
10292 while (soap_blank(c));
10293 for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
10294 { if (c == SOAP_TT || (int)c == EOF)
10297 c = soap_get(soap);
10299 for (s--; i > 0; i--, s--)
10300 { if (!soap_blank(*s))
10304 if ((int)c == EOF || c == SOAP_TT)
10305 soap_unget(soap, c);
10306 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
10308 if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10309 soap->dom->data = soap_strdup(soap, soap->tmpbuf);
10311 return soap->tmpbuf; /* return non-null pointer */
10315 /******************************************************************************/
10316 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
10321 soap_getline(struct soap *soap, char *s, int len)
10326 { c = soap_getchar(soap);
10327 if (c == '\r' || c == '\n')
10330 return soap->error = SOAP_EOF;
10334 c = soap_getchar(soap); /* got \r, now get \n */
10337 if (i+1 == len) /* empty line: end of HTTP/MIME header */
10339 c = soap_unget(soap, soap_getchar(soap));
10340 if (c != ' ' && c != '\t') /* HTTP line continuation? */
10343 else if ((int)c == EOF)
10344 return soap->error = SOAP_EOF;
10351 /******************************************************************************/
10354 soap_count_attachments(struct soap *soap)
10356 #ifndef WITH_LEANER
10357 register struct soap_multipart *content;
10358 register size_t count = soap->count;
10359 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
10360 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
10361 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
10362 for (content = soap->dime.first; content; content = content->next)
10363 { count += 12 + ((content->size+3)&(~3));
10365 count += ((strlen(content->id)+3)&(~3));
10367 count += ((strlen(content->type)+3)&(~3));
10368 if (content->options)
10369 count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
10370 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
10373 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
10374 { register size_t n = strlen(soap->mime.boundary);
10375 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
10376 for (content = soap->mime.first; content; content = content->next)
10377 { register const char *s;
10378 /* count \r\n--boundary\r\n */
10380 /* count Content-Type: ...\r\n */
10382 count += 16 + strlen(content->type);
10383 /* count Content-Transfer-Encoding: ...\r\n */
10384 s = soap_code_str(mime_codes, content->encoding);
10386 count += 29 + strlen(s);
10387 /* count Content-ID: ...\r\n */
10389 count += 14 + strlen(content->id);
10390 /* count Content-Location: ...\r\n */
10391 if (content->location)
10392 count += 20 + strlen(content->location);
10393 /* count Content-Description: ...\r\n */
10394 if (content->description)
10395 count += 23 + strlen(content->description);
10396 /* count \r\n...content */
10397 count += 2 + content->size;
10398 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
10400 /* count \r\n--boundary-- */
10403 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count));
10406 return soap->count;
10411 /******************************************************************************/
10412 #ifndef WITH_LEANER
10415 soap_putdimefield(struct soap *soap, const char *s, size_t n)
10416 { if (soap_send_raw(soap, s, n))
10417 return soap->error;
10418 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
10423 /******************************************************************************/
10424 #ifndef WITH_LEANER
10429 soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
10433 { n = strlen(option);
10434 s = (char*)soap_malloc(soap, n + 5);
10436 { s[0] = optype >> 8;
10437 s[1] = optype & 0xFF;
10440 strcpy(s + 4, option);
10448 /******************************************************************************/
10449 #ifndef WITH_LEANER
10454 soap_putdimehdr(struct soap *soap)
10455 { unsigned char tmp[12];
10456 size_t optlen = 0, idlen = 0, typelen = 0;
10457 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:""));
10458 if (soap->dime.options)
10459 optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
10461 idlen = strlen(soap->dime.id);
10462 if (soap->dime.type)
10463 typelen = strlen(soap->dime.type);
10464 tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
10465 tmp[1] = soap->dime.flags & 0xF0;
10466 tmp[2] = optlen >> 8;
10467 tmp[3] = optlen & 0xFF;
10468 tmp[4] = idlen >> 8;
10469 tmp[5] = idlen & 0xFF;
10470 tmp[6] = typelen >> 8;
10471 tmp[7] = typelen & 0xFF;
10472 tmp[8] = soap->dime.size >> 24;
10473 tmp[9] = (soap->dime.size >> 16) & 0xFF;
10474 tmp[10] = (soap->dime.size >> 8) & 0xFF;
10475 tmp[11] = soap->dime.size & 0xFF;
10476 if (soap_send_raw(soap, (char*)tmp, 12)
10477 || soap_putdimefield(soap, soap->dime.options, optlen)
10478 || soap_putdimefield(soap, soap->dime.id, idlen)
10479 || soap_putdimefield(soap, soap->dime.type, typelen))
10480 return soap->error;
10486 /******************************************************************************/
10487 #ifndef WITH_LEANER
10492 soap_putdime(struct soap *soap)
10493 { struct soap_multipart *content;
10494 if (!(soap->mode & SOAP_ENC_DIME))
10496 for (content = soap->dime.first; content; content = content->next)
10498 soap->dime.size = content->size;
10499 soap->dime.id = content->id;
10500 soap->dime.type = content->type;
10501 soap->dime.options = content->options;
10502 soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
10503 if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
10504 { size_t size = content->size;
10506 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
10507 return soap->error;
10509 if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
10510 { size_t chunksize = sizeof(soap->tmpbuf);
10511 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
10513 { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
10514 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
10515 if (size < chunksize)
10516 { soap->dime.flags &= ~SOAP_DIME_CF;
10517 if (!content->next)
10518 soap->dime.flags |= SOAP_DIME_ME;
10521 soap->dime.flags |= SOAP_DIME_CF;
10522 soap->dime.size = size;
10523 if (soap_putdimehdr(soap)
10524 || soap_putdimefield(soap, soap->tmpbuf, size))
10527 { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
10528 soap->dime.id = NULL;
10529 soap->dime.type = NULL;
10530 soap->dime.options = NULL;
10532 } while (size >= chunksize);
10535 { if (!content->next)
10536 soap->dime.flags |= SOAP_DIME_ME;
10537 if (soap_putdimehdr(soap))
10538 return soap->error;
10541 if (size < sizeof(soap->tmpbuf))
10544 bufsize = sizeof(soap->tmpbuf);
10545 if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
10546 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
10547 soap->error = SOAP_EOF;
10550 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
10554 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
10555 soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
10557 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
10558 if (soap->fdimereadclose)
10559 soap->fdimereadclose(soap, handle);
10562 { if (!content->next)
10563 soap->dime.flags |= SOAP_DIME_ME;
10564 if (soap_putdimehdr(soap)
10565 || soap_putdimefield(soap, (char*)content->ptr, content->size))
10566 return soap->error;
10574 /******************************************************************************/
10575 #ifndef WITH_LEANER
10578 soap_getdimefield(struct soap *soap, size_t n)
10579 { register soap_wchar c;
10584 { p = (char*)soap_malloc(soap, n + 1);
10587 for (i = n; i > 0; i--)
10588 { if ((int)(c = soap_get1(soap)) == EOF)
10589 { soap->error = SOAP_EOF;
10595 if ((soap->error = soap_move(soap, -(long)n&3)))
10599 soap->error = SOAP_EOM;
10606 /******************************************************************************/
10607 #ifndef WITH_LEANER
10612 soap_getdimehdr(struct soap *soap)
10613 { register soap_wchar c;
10616 unsigned char tmp[12];
10617 size_t optlen, idlen, typelen;
10618 if (!(soap->mode & SOAP_ENC_DIME))
10619 return soap->error = SOAP_DIME_END;
10620 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
10621 if (soap->dime.buflen || soap->dime.chunksize)
10622 { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
10623 return soap->error = SOAP_EOF;
10624 soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
10625 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
10629 for (i = 12; i > 0; i--)
10630 { if ((int)(c = soap_getchar(soap)) == EOF)
10631 return soap->error = SOAP_EOF;
10634 if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
10635 return soap->error = SOAP_DIME_MISMATCH;
10636 soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
10637 optlen = (tmp[2] << 8) | tmp[3];
10638 idlen = (tmp[4] << 8) | tmp[5];
10639 typelen = (tmp[6] << 8) | tmp[7];
10640 soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
10641 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
10642 if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
10643 return soap->error;
10644 if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
10645 return soap->error;
10646 if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
10647 return soap->error;
10648 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:""));
10649 if (soap->dime.flags & SOAP_DIME_ME)
10650 soap->mode &= ~SOAP_ENC_DIME;
10656 /******************************************************************************/
10657 #ifndef WITH_LEANER
10662 soap_getdime(struct soap *soap)
10663 { while (soap->dime.flags & SOAP_DIME_CF)
10664 { if (soap_getdimehdr(soap))
10665 return soap->error;
10666 if (soap_move(soap, soap->dime.size))
10667 return soap->error = SOAP_EOF;
10669 if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap)))
10670 return soap->error = SOAP_EOF;
10672 { register struct soap_multipart *content;
10673 if (soap_getdimehdr(soap))
10675 if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
10676 { const char *id, *type, *options;
10678 if (!soap->dime.ptr)
10679 return soap->error;
10680 id = soap->dime.id;
10681 type = soap->dime.type;
10682 options = soap->dime.options;
10684 { size = soap->dime.size;
10686 { n = soap->buflen - soap->bufidx;
10689 if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
10693 { soap->bufidx += n;
10696 if (soap_recv(soap))
10697 { soap->error = SOAP_EOF;
10701 if (soap_move(soap, -(long)soap->dime.size&3))
10702 { soap->error = SOAP_EOF;
10705 if (!(soap->dime.flags & SOAP_DIME_CF))
10707 if (soap_getdimehdr(soap))
10711 if (soap->fdimewriteclose)
10712 soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
10713 soap->dime.size = 0;
10714 soap->dime.id = id;
10715 soap->dime.type = type;
10716 soap->dime.options = options;
10718 else if (soap->dime.flags & SOAP_DIME_CF)
10719 { const char *id, *type, *options;
10720 register soap_wchar c;
10723 id = soap->dime.id;
10724 type = soap->dime.type;
10725 options = soap->dime.options;
10726 if (soap_new_block(soap))
10729 { s = (char*)soap_push_block(soap, soap->dime.size);
10731 return soap->error = SOAP_EOM;
10732 for (i = soap->dime.size; i > 0; i--)
10733 { if ((int)(c = soap_get1(soap)) == EOF)
10734 return soap->error = SOAP_EOF;
10737 if (soap_move(soap, -(long)soap->dime.size&3))
10738 return soap->error = SOAP_EOF;
10739 if (!(soap->dime.flags & SOAP_DIME_CF))
10741 if (soap_getdimehdr(soap))
10742 return soap->error;
10744 soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */
10745 if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0)))
10746 return soap->error;
10747 soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */
10748 soap->dime.id = id;
10749 soap->dime.type = type;
10750 soap->dime.options = options;
10753 soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
10754 content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
10756 return soap->error = SOAP_EOM;
10757 content->id = soap->dime.id;
10758 content->type = soap->dime.type;
10759 content->options = soap->dime.options;
10761 return soap->error;
10762 soap_resolve_attachment(soap, content);
10764 if (soap->error != SOAP_DIME_END)
10765 return soap->error;
10766 return soap->error = SOAP_OK;
10771 /******************************************************************************/
10772 #ifndef WITH_LEANER
10777 soap_getmimehdr(struct soap *soap)
10778 { struct soap_multipart *content;
10780 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
10781 return soap->error;
10783 while (!*soap->msgbuf);
10784 if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
10785 { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
10786 /* remove white space */
10787 while (soap_blank(*s))
10790 if (soap->mime.boundary)
10791 { if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
10792 return soap->error = SOAP_MIME_ERROR;
10795 soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
10796 if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
10797 return soap->error;
10799 if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
10800 return soap->error = SOAP_EOM;
10801 content = soap->mime.last;
10803 { register char *key = soap->msgbuf;
10804 register char *val;
10807 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
10808 val = strchr(soap->msgbuf, ':');
10812 while (*val && *val <= 32);
10813 if (!soap_tag_cmp(key, "Content-ID"))
10814 content->id = soap_strdup(soap, val);
10815 else if (!soap_tag_cmp(key, "Content-Location"))
10816 content->location = soap_strdup(soap, val);
10817 else if (!soap_tag_cmp(key, "Content-Disposition"))
10818 content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
10819 else if (!soap_tag_cmp(key, "Content-Type"))
10820 content->type = soap_strdup(soap, val);
10821 else if (!soap_tag_cmp(key, "Content-Description"))
10822 content->description = soap_strdup(soap, val);
10823 else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
10824 content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
10826 if (soap_getline(soap, key, sizeof(soap->msgbuf)))
10827 return soap->error;
10834 /******************************************************************************/
10835 #ifndef WITH_LEANER
10840 soap_getmime(struct soap *soap)
10841 { while (soap_get_mime_attachment(soap, NULL))
10843 return soap->error;
10848 /******************************************************************************/
10849 #ifndef WITH_LEANER
10854 soap_post_check_mime_attachments(struct soap *soap)
10855 { soap->imode |= SOAP_MIME_POSTCHECK;
10860 /******************************************************************************/
10861 #ifndef WITH_LEANER
10866 soap_check_mime_attachments(struct soap *soap)
10867 { if (soap->mode & SOAP_MIME_POSTCHECK)
10868 return soap_get_mime_attachment(soap, NULL) != NULL;
10874 /******************************************************************************/
10875 #ifndef WITH_LEANER
10878 struct soap_multipart *
10880 soap_get_mime_attachment(struct soap *soap, void *handle)
10881 { register soap_wchar c = 0;
10882 register size_t i, m = 0;
10883 register char *s, *t = NULL;
10884 register struct soap_multipart *content;
10885 register short flag = 0;
10886 if (!(soap->mode & SOAP_ENC_MIME))
10888 content = soap->mime.last;
10890 { if (soap_getmimehdr(soap))
10892 content = soap->mime.last;
10894 else if (content != soap->mime.first)
10895 { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
10896 { if (!content->ptr)
10900 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:""));
10901 if (!content->ptr && soap_new_block(soap))
10902 { soap->error = SOAP_EOM;
10906 { if (content->ptr)
10908 else if (!(s = (char*)soap_push_block(soap, sizeof(soap->tmpbuf))))
10909 { soap->error = SOAP_EOM;
10912 for (i = 0; i < sizeof(soap->tmpbuf); i++)
10919 { c = soap_get1(soap);
10921 { soap->error = SOAP_EOF;
10925 if (flag || c == '\r')
10926 { t = soap->msgbuf;
10927 memset(t, 0, sizeof(soap->msgbuf));
10929 if (soap->mime.boundary)
10930 strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
10931 do c = soap_getchar(soap);
10934 { soap->error = SOAP_EOF;
10940 flag = (c == '\r');
10941 m = t - soap->msgbuf + 1 - flag;
10948 if (content->ptr && soap->fmimewrite)
10949 { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
10954 *s = '\0'; /* force 0-terminated */
10956 { if (!soap->error && soap->fmimewrite)
10957 soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
10958 if (soap->fmimewriteclose)
10959 soap->fmimewriteclose(soap, (void*)content->ptr);
10964 { content->size = soap_size_block(soap, i+1)-1;
10965 content->ptr = soap_save_block(soap, NULL, 0);
10967 soap_resolve_attachment(soap, content);
10968 if (c == '-' && soap_getchar(soap) == '-')
10969 { soap->mode &= ~SOAP_ENC_MIME;
10970 if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
10974 { while (c != '\r' && (int)c != EOF && soap_blank(c))
10975 c = soap_getchar(soap);
10976 if (c != '\r' || soap_getchar(soap) != '\n')
10977 { soap->error = SOAP_MIME_ERROR;
10980 if (soap_getmimehdr(soap))
10988 /******************************************************************************/
10989 #ifndef WITH_LEANER
10994 soap_match_cid(struct soap *soap, const char *s, const char *t)
10995 { register size_t n;
11000 if (!strncmp(s, "cid:", 4))
11007 if (!strncmp(s, t, n) && !s[n])
11009 soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
11010 if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
11017 /******************************************************************************/
11018 #ifndef WITH_LEANER
11021 soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
11023 { register struct soap_xlist **xp = &soap->xlist;
11024 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id));
11026 { register struct soap_xlist *xq = *xp;
11027 if (!soap_match_cid(soap, xq->id, content->id))
11028 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id));
11030 *xq->ptr = (unsigned char*)content->ptr;
11031 *xq->size = (int)content->size;
11032 *xq->type = (char*)content->type;
11033 if (content->options)
11034 *xq->options = (char*)content->options;
11036 *xq->options = (char*)content->description;
11037 SOAP_FREE(soap, xq);
11047 /******************************************************************************/
11048 #ifndef WITH_LEANER
11053 soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
11055 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:""));
11056 if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
11057 return soap->error;
11058 if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
11059 return soap->error;
11060 s = soap_code_str(mime_codes, content->encoding);
11061 if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
11062 return soap->error;
11063 if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
11064 return soap->error;
11065 if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
11066 return soap->error;
11067 if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
11068 return soap->error;
11069 return soap_send_raw(soap, "\r\n", 2);
11074 /******************************************************************************/
11075 #ifndef WITH_LEANER
11080 soap_putmime(struct soap *soap)
11081 { struct soap_multipart *content;
11082 if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
11084 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
11085 for (content = soap->mime.first; content; content = content->next)
11087 if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
11088 { size_t size = content->size;
11090 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
11091 return soap->error;
11093 if (soap_putmimehdr(soap, content))
11094 return soap->error;
11096 { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
11097 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
11099 { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
11100 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
11101 if (soap_send_raw(soap, soap->tmpbuf, size))
11106 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
11112 if (size < sizeof(soap->tmpbuf))
11115 bufsize = sizeof(soap->tmpbuf);
11116 if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
11117 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
11118 soap->error = SOAP_EOF;
11121 if (soap_send_raw(soap, soap->tmpbuf, bufsize))
11126 if (soap->fmimereadclose)
11127 soap->fmimereadclose(soap, handle);
11130 { if (soap_putmimehdr(soap, content)
11131 || soap_send_raw(soap, content->ptr, content->size))
11132 return soap->error;
11135 return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
11140 /******************************************************************************/
11141 #ifndef WITH_LEANER
11146 soap_set_dime(struct soap *soap)
11147 { soap->omode |= SOAP_ENC_DIME;
11148 soap->dime.first = NULL;
11149 soap->dime.last = NULL;
11154 /******************************************************************************/
11155 #ifndef WITH_LEANER
11160 soap_set_mime(struct soap *soap, const char *boundary, const char *start)
11161 { soap->omode |= SOAP_ENC_MIME;
11162 soap->mime.first = NULL;
11163 soap->mime.last = NULL;
11164 soap->mime.boundary = soap_strdup(soap, boundary);
11165 soap->mime.start = soap_strdup(soap, start);
11170 /******************************************************************************/
11171 #ifndef WITH_LEANER
11176 soap_clr_dime(struct soap *soap)
11177 { soap->omode &= ~SOAP_ENC_DIME;
11178 soap->dime.first = NULL;
11179 soap->dime.last = NULL;
11184 /******************************************************************************/
11185 #ifndef WITH_LEANER
11190 soap_clr_mime(struct soap *soap)
11191 { soap->omode &= ~SOAP_ENC_MIME;
11192 soap->mime.first = NULL;
11193 soap->mime.last = NULL;
11194 soap->mime.boundary = NULL;
11195 soap->mime.start = NULL;
11200 /******************************************************************************/
11201 #ifndef WITH_LEANER
11203 static struct soap_multipart*
11204 soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
11205 { struct soap_multipart *content;
11206 content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
11208 { content->next = NULL;
11209 content->ptr = ptr;
11210 content->size = size;
11211 content->id = NULL;
11212 content->type = NULL;
11213 content->options = NULL;
11214 content->encoding = SOAP_MIME_NONE;
11215 content->location = NULL;
11216 content->description = NULL;
11220 (*last)->next = content;
11228 /******************************************************************************/
11229 #ifndef WITH_LEANER
11234 soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
11235 { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
11238 content->id = soap_strdup(soap, id);
11239 content->type = soap_strdup(soap, type);
11240 content->options = soap_dime_option(soap, optype, option);
11246 /******************************************************************************/
11247 #ifndef WITH_LEANER
11252 soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description)
11253 { struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
11256 content->id = soap_strdup(soap, id);
11257 content->type = soap_strdup(soap, type);
11258 content->encoding = encoding;
11259 content->location = soap_strdup(soap, location);
11260 content->description = soap_strdup(soap, description);
11266 /******************************************************************************/
11267 #ifndef WITH_LEANER
11270 struct soap_multipart*
11272 soap_next_multipart(struct soap_multipart *content)
11274 return content->next;
11280 /******************************************************************************/
11281 #ifndef WITH_LEANER
11284 soap_select_mime_boundary(struct soap *soap)
11285 { while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
11286 { register char *s = soap->mime.boundary;
11287 register size_t n = 0;
11292 s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
11300 { *s++ = soap_base64o[soap_random & 0x3F];
11305 if (!soap->mime.start)
11306 soap->mime.start = "<SOAP-ENV:Envelope>";
11311 /******************************************************************************/
11312 #ifndef WITH_LEANER
11315 soap_valid_mime_boundary(struct soap *soap)
11316 { register struct soap_multipart *content;
11318 if (soap->fmimeread)
11320 k = strlen(soap->mime.boundary);
11321 for (content = soap->mime.first; content; content = content->next)
11322 { if (content->ptr && content->size >= k)
11323 { register const char *p = (const char*)content->ptr;
11325 for (i = 0; i < content->size - k; i++, p++)
11326 { if (!strncmp(p, soap->mime.boundary, k))
11336 /******************************************************************************\
11338 * HTTP cookie handling
11340 \******************************************************************************/
11342 #ifdef WITH_COOKIES
11343 /******************************************************************************/
11347 soap_encode_cookie(const char *s, char *t, size_t len)
11349 register size_t n = len;
11350 while ((c = *s++) && --n > 0)
11351 { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c))
11355 *t++ = (c >> 4) + (c > 159 ? '7' : '0');
11357 *t++ = c + (c > 9 ? '7' : '0');
11367 /******************************************************************************/
11369 struct soap_cookie*
11371 soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
11372 { struct soap_cookie *p;
11375 domain = soap->cookie_domain;
11377 path = soap->cookie_path;
11381 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)"));
11382 for (p = soap->cookies; p; p = p->next)
11383 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s=%s domain=%s path=%s env=%hd\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->env));
11384 if (!strcmp(p->name, name)
11387 && !strcmp(p->domain, domain)
11388 && !strncmp(p->path, path, n))
11394 /******************************************************************************/
11396 struct soap_cookie*
11398 soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
11399 { struct soap_cookie **p, *q;
11401 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)"));
11403 domain = soap->cookie_domain;
11405 path = soap->cookie_path;
11407 { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR);
11412 q = soap_cookie(soap, name, domain, path);
11414 { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
11415 { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
11416 strcpy(q->name, name);
11425 for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
11426 if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0)
11433 { SOAP_FREE(soap, q->name);
11434 SOAP_FREE(soap, q);
11443 { SOAP_FREE(soap, q->value);
11447 { SOAP_FREE(soap, q->domain);
11451 { SOAP_FREE(soap, q->path);
11454 if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
11455 strcpy(q->value, value);
11456 if (domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
11457 strcpy(q->domain, domain);
11458 if (path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
11459 strcpy(q->path, path);
11466 /******************************************************************************/
11470 soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
11471 { struct soap_cookie **p, *q;
11473 domain = soap->cookie_domain;
11475 { soap_set_receiver_error(soap, "Cookie domain not set", NULL, SOAP_HTTP_ERROR);
11479 path = soap->cookie_path;
11481 { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR);
11486 for (p = &soap->cookies, q = *p; q; q = *p)
11487 if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
11489 SOAP_FREE(soap, q->value);
11491 SOAP_FREE(soap, q->domain);
11493 SOAP_FREE(soap, q->path);
11495 SOAP_FREE(soap, q);
11501 /******************************************************************************/
11505 soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
11506 { struct soap_cookie *p;
11507 if ((p = soap_cookie(soap, name, domain, path)))
11512 /******************************************************************************/
11516 soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
11517 { struct soap_cookie *p;
11518 if ((p = soap_cookie(soap, name, domain, path)) && p->env)
11523 /******************************************************************************/
11527 soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
11528 { struct soap_cookie *p;
11529 if ((p = soap_cookie(soap, name, domain, path)))
11534 /******************************************************************************/
11538 soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
11539 { struct soap_cookie *p;
11540 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)"));
11541 if ((p = soap_cookie(soap, name, domain, path)))
11542 { p->maxage = expire;
11549 /******************************************************************************/
11553 soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
11554 { struct soap_cookie *p;
11555 if ((p = soap_cookie(soap, name, domain, path)))
11563 /******************************************************************************/
11567 soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
11568 { struct soap_cookie *p;
11569 if ((p = soap_cookie(soap, name, domain, path)))
11577 /******************************************************************************/
11581 soap_putsetcookies(struct soap *soap)
11582 { struct soap_cookie *p;
11583 char *s, tmp[4096];
11585 for (p = soap->cookies; p; p = p->next)
11586 { if (p->modified || !p->env)
11589 s += soap_encode_cookie(p->name, s, tmp-s+4064);
11590 if (p->value && *p->value)
11592 s += soap_encode_cookie(p->value, s, tmp-s+4064);
11594 if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
11595 sprintf(s, ";Domain=\"%s\"", p->domain);
11596 else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
11597 sprintf(s, ";Domain=\"%s\"", soap->cookie_domain);
11598 strcat(s, ";Path=/");
11602 t = soap->cookie_path;
11606 if ((int)strlen(t) < tmp-s+4064)
11610 if (p->version > 0 && s-tmp < 4060)
11611 { sprintf(s, ";Version=%u", p->version);
11614 if (p->maxage >= 0 && s-tmp < 4060)
11615 { sprintf(s, ";Max-Age=%ld", p->maxage);
11618 if (p->secure && s-tmp < 4073)
11619 strcpy(s, ";Secure");
11620 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
11621 if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
11622 return soap->error;
11628 /******************************************************************************/
11632 soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
11633 { struct soap_cookie **p, *q;
11634 unsigned int version = 0;
11635 time_t now = time(NULL);
11636 char *s, tmp[4096];
11637 p = &soap->cookies;
11638 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path));
11642 { if (q->expire && now > q->expire)
11643 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
11644 SOAP_FREE(soap, q->name);
11646 SOAP_FREE(soap, q->value);
11648 SOAP_FREE(soap, q->domain);
11650 SOAP_FREE(soap, q->path);
11652 SOAP_FREE(soap, q);
11655 { size_t domlen = 0;
11657 { const char *s = strchr(q->domain, ':');
11659 domlen = s - q->domain;
11661 domlen = strlen(q->domain);
11663 if ((!q->domain || !strncmp(q->domain, domain, domlen))
11664 && (!q->path || !strncmp(q->path, path, strlen(q->path)))
11665 && (!q->secure || secure))
11667 if (q->version != version)
11668 { sprintf(s, "$Version=%u;", q->version);
11669 version = q->version;
11672 s += soap_encode_cookie(q->name, s, tmp-s+4080);
11673 if (q->value && *q->value)
11675 s += soap_encode_cookie(q->value, s, tmp-s+4080);
11677 if (q->path && (int)strlen(q->path) < tmp-s+4080)
11678 { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
11681 if (q->domain && (int)strlen(q->domain) < tmp-s+4080)
11682 sprintf(s, ";$Domain=\"%s\"", q->domain);
11683 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
11684 if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
11685 return soap->error;
11693 /******************************************************************************/
11697 soap_getcookies(struct soap *soap, const char *val)
11698 { struct soap_cookie *p = NULL, *q;
11700 char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
11701 char *domain = NULL;
11703 unsigned int version = 0;
11704 time_t now = time(NULL);
11709 { s = soap_decode_key(tmp, sizeof(tmp), s);
11710 if (!soap_tag_cmp(tmp, "$Version"))
11711 { if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
11713 p->version = (int)atol(tmp);
11715 version = (int)atol(tmp);
11718 else if (!soap_tag_cmp(tmp, "$Path"))
11719 { s = soap_decode_val(tmp, sizeof(tmp), s);
11721 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11728 SOAP_FREE(soap, p->path);
11733 SOAP_FREE(soap, path);
11737 else if (!soap_tag_cmp(tmp, "$Domain"))
11738 { s = soap_decode_val(tmp, sizeof(tmp), s);
11740 { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11747 SOAP_FREE(soap, p->domain);
11752 SOAP_FREE(soap, domain);
11756 else if (p && !soap_tag_cmp(tmp, "Path"))
11758 SOAP_FREE(soap, p->path);
11759 s = soap_decode_val(tmp, sizeof(tmp), s);
11761 { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11762 strcpy(p->path, tmp);
11767 else if (p && !soap_tag_cmp(tmp, "Domain"))
11769 SOAP_FREE(soap, p->domain);
11770 s = soap_decode_val(tmp, sizeof(tmp), s);
11772 { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
11773 strcpy(p->domain, tmp);
11778 else if (p && !soap_tag_cmp(tmp, "Version"))
11779 { s = soap_decode_val(tmp, sizeof(tmp), s);
11780 p->version = (unsigned int)atol(tmp);
11782 else if (p && !soap_tag_cmp(tmp, "Max-Age"))
11783 { s = soap_decode_val(tmp, sizeof(tmp), s);
11784 p->expire = now + atol(tmp);
11786 else if (p && !soap_tag_cmp(tmp, "Expires"))
11789 static const char mns[] = "anebarprayunulugepctovec";
11790 s = soap_decode_val(tmp, sizeof(tmp), s);
11791 if (strlen(tmp) > 20)
11792 { memset((void*)&T, 0, sizeof(T));
11796 T.tm_mday = (int)atol(a);
11799 T.tm_mon = (strstr(mns, a) - mns) / 2;
11802 T.tm_year = 100 + (int)atol(a);
11805 T.tm_hour = (int)atol(a);
11808 T.tm_min = (int)atol(a);
11811 T.tm_sec = (int)atol(a);
11812 p->expire = soap_timegm(&T);
11815 else if (p && !soap_tag_cmp(tmp, "Secure"))
11819 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
11820 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
11821 { q->version = p->version;
11822 q->expire = p->expire;
11823 q->secure = p->secure;
11827 SOAP_FREE(soap, p->name);
11829 SOAP_FREE(soap, p->value);
11831 SOAP_FREE(soap, p->domain);
11833 SOAP_FREE(soap, p->path);
11834 SOAP_FREE(soap, p);
11836 if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
11837 { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
11838 strcpy(p->name, tmp);
11839 s = soap_decode_val(tmp, sizeof(tmp), s);
11841 { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
11842 strcpy(p->value, tmp);
11846 p->domain = domain;
11850 p->version = version;
11855 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure));
11856 if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
11857 { q->version = p->version;
11858 q->expire = p->expire;
11859 q->secure = p->secure;
11863 SOAP_FREE(soap, p->name);
11865 SOAP_FREE(soap, p->value);
11867 SOAP_FREE(soap, p->domain);
11869 SOAP_FREE(soap, p->path);
11870 SOAP_FREE(soap, p);
11873 SOAP_FREE(soap, domain);
11875 SOAP_FREE(soap, path);
11878 /******************************************************************************/
11882 soap_getenv_cookies(struct soap *soap)
11883 { struct soap_cookie *p;
11885 char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
11886 if (!(s = getenv("HTTP_COOKIE")))
11889 { s = soap_decode_key(key, sizeof(key), s);
11890 s = soap_decode_val(val, sizeof(val), s);
11891 p = soap_set_cookie(soap, key, val, NULL, NULL);
11898 /******************************************************************************/
11900 struct soap_cookie*
11902 soap_copy_cookies(struct soap *copy, struct soap *soap)
11903 { struct soap_cookie *p, **q, *r;
11905 for (p = soap->cookies; p; p = p->next)
11906 { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
11910 { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
11911 strcpy((*q)->name, p->name);
11914 { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
11915 strcpy((*q)->value, p->value);
11918 { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
11919 strcpy((*q)->domain, p->domain);
11922 { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
11923 strcpy((*q)->path, p->path);
11931 /******************************************************************************/
11935 soap_free_cookies(struct soap *soap)
11936 { struct soap_cookie *p;
11937 for (p = soap->cookies; p; p = soap->cookies)
11938 { soap->cookies = p->next;
11939 SOAP_FREE(soap, p->name);
11941 SOAP_FREE(soap, p->value);
11943 SOAP_FREE(soap, p->domain);
11945 SOAP_FREE(soap, p->path);
11946 SOAP_FREE(soap, p);
11950 /******************************************************************************/
11951 #endif /* WITH_COOKIES */
11953 /******************************************************************************/
11957 soap_getgziphdr(struct soap *soap)
11959 soap_wchar c, f = 0;
11960 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
11961 for (i = 0; i < 9; i++)
11962 { if ((int)(c = soap_get1(soap) == EOF))
11963 return soap->error = SOAP_EOF;
11967 if (f & 0x04) /* FEXTRA */
11968 { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
11969 { if ((int)soap_get1(soap) == EOF)
11970 return soap->error = SOAP_EOF;
11973 if (f & 0x08) /* FNAME */
11975 c = soap_get1(soap);
11976 while (c && (int)c != EOF);
11978 if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */
11980 c = soap_get1(soap);
11981 while (c && (int)c != EOF);
11983 if ((int)c != EOF && (f & 0x01)) /* FHCRC */
11984 { if ((int)(c = soap_get1(soap)) != EOF)
11985 c = soap_get1(soap);
11988 return soap->error = SOAP_EOF;
11994 /******************************************************************************/
11999 soap_begin_recv(struct soap *soap)
12001 soap->error = SOAP_OK;
12003 soap_set_local_namespaces(soap);
12004 soap->version = 0; /* don't assume we're parsing SOAP content by default */
12005 #ifndef WITH_NOIDREF
12006 soap_free_iht(soap);
12008 if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
12009 soap->omode |= SOAP_IO_CHUNK;
12010 soap->imode &= ~SOAP_IO;
12011 soap->mode = soap->imode;
12012 if (!soap->keep_alive)
12013 { soap->buflen = 0;
12016 if (!(soap->mode & SOAP_IO_KEEPALIVE))
12017 soap->keep_alive = 0;
12021 soap->part = SOAP_BEGIN;
12026 *soap->endpoint = '\0';
12027 soap->action = NULL;
12028 #ifndef WITH_LEANER
12030 soap->dime.chunksize = 0;
12031 soap->dime.buflen = 0;
12032 soap->dime.list = NULL;
12033 soap->dime.first = NULL;
12034 soap->dime.last = NULL;
12035 soap->mime.list = NULL;
12036 soap->mime.first = NULL;
12037 soap->mime.last = NULL;
12038 soap->mime.boundary = NULL;
12039 soap->mime.start = NULL;
12040 soap->xlist = NULL;
12044 #ifndef WITH_FASTCGI
12045 if (!soap_valid_socket(soap->socket))
12046 #ifdef __BORLANDC__
12047 setmode((SOAP_SOCKET)soap->recvfd, O_BINARY);
12049 _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY);
12055 soap->mode &= ~SOAP_ENC_ZLIB;
12056 soap->zlib_in = SOAP_ZLIB_NONE;
12057 soap->zlib_out = SOAP_ZLIB_NONE;
12058 soap->d_stream.next_in = Z_NULL;
12059 soap->d_stream.avail_in = 0;
12060 soap->d_stream.next_out = (Byte*)soap->buf;
12061 soap->d_stream.avail_out = SOAP_BUFLEN;
12062 soap->z_ratio_in = 1.0;
12064 #ifndef WITH_LEANER
12065 if (soap->fprepareinit)
12066 soap->fprepareinit(soap);
12068 c = soap_getchar(soap);
12071 { if (soap_getgziphdr(soap))
12072 return soap->error;
12073 if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
12074 return soap->error = SOAP_ZLIB_ERROR;
12075 soap->zlib_state = SOAP_ZLIB_INFLATE;
12076 soap->mode |= SOAP_ENC_ZLIB;
12077 soap->zlib_in = SOAP_ZLIB_GZIP;
12078 soap->z_crc = crc32(0L, NULL, 0);
12079 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
12080 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
12081 /* should not chunk over plain transport, so why bother to check? */
12082 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
12083 /* soap->z_buflen = soap->bufidx; */
12085 soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
12086 soap->d_stream.avail_in = soap->buflen - soap->bufidx;
12087 soap->z_buflen = soap->buflen;
12088 soap->buflen = soap->bufidx;
12089 c = soap_getchar(soap);
12092 #ifndef WITH_LEANER
12093 if (c == '-' && soap_get0(soap) == '-')
12094 soap->mode |= SOAP_ENC_MIME;
12095 else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
12096 soap->mode |= SOAP_ENC_DIME;
12099 { while (soap_blank(c))
12100 c = soap_getchar(soap);
12103 return soap->error = SOAP_EOF;
12104 soap_unget(soap, c);
12105 #ifndef WITH_NOHTTP
12106 /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */
12107 if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
12108 { soap->mode &= ~SOAP_IO;
12109 soap->error = soap->fparse(soap);
12110 if (soap->error && soap->error < SOAP_STOP)
12111 { soap->keep_alive = 0; /* force close later */
12112 return soap->error;
12114 if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
12115 { soap->chunkbuflen = soap->buflen;
12116 soap->buflen = soap->bufidx;
12117 soap->chunksize = 0;
12119 #ifndef WITH_LEANER
12120 else if (soap->fpreparerecv && soap->buflen != soap->bufidx)
12121 soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx);
12124 if (soap->zlib_in != SOAP_ZLIB_NONE)
12125 { /* fparse should not use soap_unget to push back last char */
12127 c = soap_get1(soap);
12129 { if (soap_getgziphdr(soap))
12130 return soap->error;
12131 if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
12132 return soap->error = SOAP_ZLIB_ERROR;
12133 soap->zlib_state = SOAP_ZLIB_INFLATE;
12134 soap->z_crc = crc32(0L, NULL, 0);
12135 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
12138 { soap_revget1(soap);
12142 if (inflateInit(&soap->d_stream) != Z_OK)
12143 return soap->error = SOAP_ZLIB_ERROR;
12144 soap->zlib_state = SOAP_ZLIB_INFLATE;
12145 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
12147 soap->mode |= SOAP_ENC_ZLIB;
12148 memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
12149 soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
12150 soap->d_stream.avail_in = soap->buflen - soap->bufidx;
12151 soap->z_buflen = soap->buflen;
12152 soap->buflen = soap->bufidx;
12156 { if (soap->error == SOAP_FORM && soap->fform)
12157 { soap->error = soap->fform(soap);
12158 if (soap->error == SOAP_OK)
12159 soap->error = SOAP_STOP; /* prevents further processing */
12161 return soap->error;
12165 #ifndef WITH_LEANER
12166 if (soap->mode & SOAP_ENC_MIME)
12167 { if (soap_getmimehdr(soap))
12168 return soap->error;
12169 if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
12170 soap->mode |= SOAP_ENC_DIME;
12172 if (soap->mode & SOAP_ENC_DIME)
12173 { if (soap_getdimehdr(soap))
12174 return soap->error;
12175 if (soap->dime.flags & SOAP_DIME_CF)
12176 { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
12177 soap->dime.chunksize = soap->dime.size;
12178 if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
12179 { soap->dime.buflen = soap->buflen;
12180 soap->buflen = soap->bufidx + soap->dime.chunksize;
12183 soap->dime.chunksize -= soap->buflen - soap->bufidx;
12185 soap->count = soap->buflen - soap->bufidx;
12192 /******************************************************************************/
12193 #ifndef WITH_NOHTTP
12196 http_parse(struct soap *soap)
12197 { char header[SOAP_HDRLEN], *s;
12198 unsigned short get = 0, status = 0, k = 0;
12199 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
12200 *soap->endpoint = '\0';
12202 soap->userid = NULL;
12203 soap->passwd = NULL;
12204 soap->action = NULL;
12205 soap->authrealm = NULL;
12207 { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
12208 return soap->error;
12209 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
12211 { if (soap_getline(soap, header, SOAP_HDRLEN))
12212 { if (soap->error == SOAP_EOF)
12213 { soap->error = SOAP_OK;
12214 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
12217 return soap->error;
12221 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
12222 s = strchr(header, ':');
12226 while (*s && *s <= 32);
12227 if ((soap->error = soap->fparsehdr(soap, header, s)))
12228 { if (soap->error < SOAP_STOP)
12229 return soap->error;
12230 status = soap->error;
12231 soap->error = SOAP_OK;
12235 if ((s = strchr(soap->msgbuf, ' ')))
12236 { k = (unsigned short)soap_strtoul(s, &s, 10);
12237 if (!soap_blank(*s))
12242 } while (k == 100);
12243 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n"));
12244 s = strstr(soap->msgbuf, "HTTP/");
12245 if (s && s[7] != '1')
12246 { if (soap->keep_alive == 1)
12247 soap->keep_alive = 0;
12248 if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */
12249 { soap->imode |= SOAP_IO_CHUNK;
12250 soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
12253 if (soap->keep_alive < 0)
12254 soap->keep_alive = 1;
12255 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
12256 if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5)))
12257 { size_t m = strlen(soap->endpoint);
12258 size_t n = m + (s - soap->msgbuf) - 5 - (!get);
12259 if (n >= sizeof(soap->endpoint))
12260 n = sizeof(soap->endpoint) - 1;
12261 strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m);
12262 soap->path[n - m] = '\0';
12263 strcat(soap->endpoint, soap->path);
12264 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
12266 { soap->error = soap->fget(soap);
12267 if (soap->error == SOAP_OK)
12268 soap->error = SOAP_STOP; /* prevents further processing */
12269 return soap->error;
12272 return soap->error = status;
12275 if (k == 0 || k == 200 || k == 400 || k == 500 || (k >= 201 && k <= 299 && ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || soap->length)))
12277 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k));
12278 return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k);
12283 /******************************************************************************/
12284 #ifndef WITH_NOHTTP
12287 http_parse_header(struct soap *soap, const char *key, const char *val)
12288 { if (!soap_tag_cmp(key, "Host"))
12290 #ifdef WITH_OPENSSL
12291 if (soap->imode & SOAP_ENC_SSL)
12292 strcpy(soap->endpoint, "https://");
12295 strcpy(soap->endpoint, "http://");
12296 strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
12297 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
12299 #ifndef WITH_LEANER
12300 else if (!soap_tag_cmp(key, "Content-Type"))
12301 { soap->http_content = soap_strdup(soap, val);
12302 if (soap_get_header_attribute(soap, val, "application/dime"))
12303 soap->mode |= SOAP_ENC_DIME;
12304 else if (soap_get_header_attribute(soap, val, "multipart/related")
12305 || soap_get_header_attribute(soap, val, "multipart/form-data"))
12306 { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
12307 soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
12308 soap->mode |= SOAP_ENC_MIME;
12312 else if (!soap_tag_cmp(key, "Content-Length"))
12313 soap->length = soap_strtoul(val, NULL, 10);
12314 else if (!soap_tag_cmp(key, "Content-Encoding"))
12315 { if (!soap_tag_cmp(val, "deflate"))
12317 soap->zlib_in = SOAP_ZLIB_DEFLATE;
12319 return SOAP_ZLIB_ERROR;
12321 else if (!soap_tag_cmp(val, "gzip"))
12323 soap->zlib_in = SOAP_ZLIB_GZIP;
12325 return SOAP_ZLIB_ERROR;
12329 else if (!soap_tag_cmp(key, "Accept-Encoding"))
12332 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
12333 soap->zlib_out = SOAP_ZLIB_GZIP;
12336 if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
12337 soap->zlib_out = SOAP_ZLIB_DEFLATE;
12339 soap->zlib_out = SOAP_ZLIB_NONE;
12342 else if (!soap_tag_cmp(key, "Transfer-Encoding"))
12343 { soap->mode &= ~SOAP_IO;
12344 if (!soap_tag_cmp(val, "chunked"))
12345 soap->mode |= SOAP_IO_CHUNK;
12347 else if (!soap_tag_cmp(key, "Connection"))
12348 { if (!soap_tag_cmp(val, "keep-alive"))
12349 soap->keep_alive = -soap->keep_alive;
12350 else if (!soap_tag_cmp(val, "close"))
12351 soap->keep_alive = 0;
12354 else if (!soap_tag_cmp(key, "Authorization"))
12355 { if (!soap_tag_cmp(val, "Basic *"))
12358 soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
12359 soap->tmpbuf[n] = '\0';
12360 if ((s = strchr(soap->tmpbuf, ':')))
12362 soap->userid = soap_strdup(soap, soap->tmpbuf);
12363 soap->passwd = soap_strdup(soap, s + 1);
12367 else if (!soap_tag_cmp(key, "WWW-Authenticate"))
12368 soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
12369 else if (!soap_tag_cmp(key, "Expect"))
12370 { if (!soap_tag_cmp(val, "100-continue"))
12371 { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
12372 || (soap->error = soap->fposthdr(soap, NULL, NULL)))
12373 return soap->error;
12377 else if (!soap_tag_cmp(key, "SOAPAction"))
12379 { soap->action = soap_strdup(soap, val + 1);
12380 soap->action[strlen(soap->action) - 1] = '\0';
12383 else if (!soap_tag_cmp(key, "Location"))
12384 { strncpy(soap->endpoint, val, sizeof(soap->endpoint));
12385 soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
12387 #ifdef WITH_COOKIES
12388 else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie"))
12389 soap_getcookies(soap, val);
12396 /******************************************************************************/
12397 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12402 soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
12403 { register const char *s = line;
12406 { register short flag;
12407 s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
12408 flag = soap_tag_cmp(soap->tmpbuf, key);
12409 s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
12411 return soap->tmpbuf;
12419 /******************************************************************************/
12420 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12425 soap_decode_key(char *buf, size_t len, const char *val)
12426 { return soap_decode(buf, len, val, "=,;");
12431 /******************************************************************************/
12432 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12437 soap_decode_val(char *buf, size_t len, const char *val)
12442 return soap_decode(buf, len, val + 1, ",;");
12447 /******************************************************************************/
12448 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
12451 soap_decode(char *buf, size_t len, const char *val, const char *sep)
12454 for (s = val; *s; s++)
12455 if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
12459 while (*s && *s != '"' && --len)
12463 { while (soap_notblank(*s) && !strchr(sep, *s) && --len)
12465 { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
12466 + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
12474 while (*s && !strchr(sep, *s))
12481 /******************************************************************************/
12486 soap_envelope_begin_out(struct soap *soap)
12488 #ifndef WITH_LEANER
12490 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start)
12492 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
12493 s = "application/dime";
12494 else if (soap->version == 2)
12495 { if (soap->mode & SOAP_ENC_MTOM)
12496 s = "application/xop+xml; charset=utf-8; type=application/soap+xml";
12498 s = "application/soap+xml; charset=utf-8";
12501 s = "text/xml; charset=utf-8";
12502 sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
12503 n = strlen(soap->tmpbuf);
12504 if (soap_send_raw(soap, soap->tmpbuf, n))
12505 return soap->error;
12507 if (soap->mode & SOAP_IO_LENGTH)
12508 soap->dime.size = soap->count; /* DIME in MIME correction */
12509 if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
12510 { if (soap_putdimehdr(soap))
12511 return soap->error;
12514 soap->part = SOAP_IN_ENVELOPE;
12515 return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
12519 /******************************************************************************/
12524 soap_envelope_end_out(struct soap *soap)
12525 { if (soap_element_end_out(soap, "SOAP-ENV:Envelope"))
12526 return soap->error;
12527 #ifndef WITH_LEANER
12528 if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
12529 { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */
12530 sprintf(soap->id, soap->dime_id_format, 0);
12531 soap->dime.id = soap->id;
12532 if (soap->local_namespaces)
12533 { if (soap->local_namespaces[0].out)
12534 soap->dime.type = (char*)soap->local_namespaces[0].out;
12536 soap->dime.type = (char*)soap->local_namespaces[0].ns;
12538 soap->dime.options = NULL;
12539 soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
12540 if (!soap->dime.first)
12541 soap->dime.flags |= SOAP_DIME_ME;
12542 soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
12544 if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
12545 return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
12547 soap->part = SOAP_END_ENVELOPE;
12552 /******************************************************************************/
12557 soap_envelope_begin_in(struct soap *soap)
12558 { register struct Namespace *p;
12559 soap->part = SOAP_IN_ENVELOPE;
12560 if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
12561 return soap->error = SOAP_VERSIONMISMATCH;
12562 p = soap->local_namespaces;
12564 { const char *ns = p[0].out;
12567 if (!strcmp(ns, soap_env1))
12568 { soap->version = 1; /* make sure we use SOAP 1.1 */
12570 SOAP_FREE(soap, p[1].out);
12571 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
12572 strcpy(p[1].out, soap_enc1);
12574 else if (!strcmp(ns, soap_env2))
12575 { soap->version = 2; /* make sure we use SOAP 1.2 */
12577 SOAP_FREE(soap, p[1].out);
12578 if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
12579 strcpy(p[1].out, soap_enc2);
12586 /******************************************************************************/
12591 soap_envelope_end_in(struct soap *soap)
12592 { soap->part = SOAP_END_ENVELOPE;
12593 return soap_element_end_in(soap, "SOAP-ENV:Envelope");
12597 /******************************************************************************/
12602 soap_body_begin_out(struct soap *soap)
12603 { soap->part = SOAP_IN_BODY;
12604 if (soap->version == 1)
12605 soap->encoding = 1;
12607 if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body"))
12608 return soap->error;
12610 if (soap_element(soap, "SOAP-ENV:Body", 0, NULL))
12611 return soap->error;
12612 return soap_element_start_end_out(soap, NULL);
12616 /******************************************************************************/
12621 soap_body_end_out(struct soap *soap)
12622 { if (soap_element_end_out(soap, "SOAP-ENV:Body"))
12623 return soap->error;
12624 soap->part = SOAP_END_BODY;
12629 /******************************************************************************/
12634 soap_body_begin_in(struct soap *soap)
12635 { soap->part = SOAP_IN_BODY;
12636 if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
12637 return soap->error;
12639 soap->part = SOAP_NO_BODY;
12644 /******************************************************************************/
12649 soap_body_end_in(struct soap *soap)
12650 { if (soap->part == SOAP_NO_BODY)
12652 soap->part = SOAP_END_BODY;
12653 return soap_element_end_in(soap, "SOAP-ENV:Body");
12657 /******************************************************************************/
12662 soap_recv_header(struct soap *soap)
12663 { if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
12664 soap->error = SOAP_OK;
12665 else if (soap->error == SOAP_OK && soap->fheader)
12666 soap->error = soap->fheader(soap);
12667 return soap->error;
12671 /******************************************************************************/
12676 soap_set_endpoint(struct soap *soap, const char *endpoint)
12677 { register const char *s;
12678 register size_t i, n;
12679 soap->endpoint[0] = '\0';
12680 soap->host[0] = '\0';
12681 soap->path[0] = '/';
12682 soap->path[1] = '\0';
12684 if (!endpoint || !*endpoint)
12686 #ifdef WITH_OPENSSL
12687 if (!soap_tag_cmp(endpoint, "https:*"))
12690 strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
12691 s = strchr(endpoint, ':');
12692 if (s && s[1] == '/' && s[2] == '/')
12697 if (n >= sizeof(soap->host))
12698 n = sizeof(soap->host) - 1;
12702 for (i = 0; i < n; i++)
12703 { soap->host[i] = s[i];
12711 { for (i = 0; i < n; i++)
12712 { soap->host[i] = s[i];
12713 if (s[i] == '/' || s[i] == ':')
12718 for (i = 0; i < n; i++)
12719 { soap->host[i] = s[i];
12720 if (s[i] == '/' || s[i] == ':')
12724 soap->host[i] = '\0';
12726 { soap->port = (int)atol(s + i + 1);
12727 for (i++; i < n; i++)
12732 { strncpy(soap->path, s + i, sizeof(soap->path));
12733 soap->path[sizeof(soap->path) - 1] = '\0';
12738 /******************************************************************************/
12743 soap_connect(struct soap *soap, const char *endpoint, const char *action)
12744 { return soap_connect_command(soap, SOAP_POST, endpoint, action);
12748 /******************************************************************************/
12753 soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
12754 { char host[sizeof(soap->host)];
12757 soap->error = SOAP_OK;
12758 strcpy(host, soap->host); /* save to compare */
12759 port = soap->port; /* save to compare */
12760 soap_set_endpoint(soap, endpoint);
12761 #ifndef WITH_LEANER
12762 if (soap->fconnect)
12763 { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
12764 return soap->error;
12768 if (soap->fopen && *soap->host)
12769 { soap->status = http_command;
12770 if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
12771 { soap->keep_alive = 0; /* to force close */
12772 soap->omode &= ~SOAP_IO_UDP; /* to force close */
12773 soap_closesock(soap);
12774 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
12776 if (!strncmp(endpoint, "soap.udp:", 9))
12777 soap->omode |= SOAP_IO_UDP;
12779 soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
12781 return soap->error;
12782 soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
12785 count = soap_count_attachments(soap);
12786 if (soap_begin_send(soap))
12787 return soap->error;
12788 #ifndef WITH_NOHTTP
12789 soap->action = soap_strdup(soap, action);
12790 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
12791 { unsigned int k = soap->mode;
12792 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
12793 if ((k & SOAP_IO) != SOAP_IO_FLUSH)
12794 soap->mode |= SOAP_IO_BUFFER;
12795 if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
12796 return soap->error;
12797 #ifndef WITH_LEANER
12798 if ((k & SOAP_IO) == SOAP_IO_CHUNK)
12799 { if (soap_flush(soap))
12800 return soap->error;
12805 if (http_command != SOAP_POST)
12806 return soap_end_send(soap);
12812 /******************************************************************************/
12817 soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
12819 register unsigned long m;
12822 t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
12824 { soap->error = SOAP_EOM;
12831 for (; n > 2; n -= 3, s += 3)
12833 m = (m << 8) | s[1];
12834 m = (m << 8) | s[2];
12835 for (i = 4; i > 0; m >>= 6)
12836 t[--i] = soap_base64o[m & 0x3F];
12842 for (i = 0; i < n; i++)
12843 m = (m << 8) | *s++;
12846 for (i++; i > 0; m >>= 6)
12847 t[--i] = soap_base64o[m & 0x3F];
12848 for (i = 3; i > n; i--)
12856 /******************************************************************************/
12861 soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
12862 { register int i, j, c;
12863 register unsigned long m;
12864 register const char *p;
12870 return SOAP_NON_NULL;
12873 { l = (strlen(s) + 3) / 4 * 3;
12874 t = (char*)soap_malloc(soap, l);
12877 { soap->error = SOAP_EOM;
12884 { for (i = 0; i < SOAP_BLKLEN; i++)
12889 if (c == '=' || !c)
12893 *t++ = (char)((m >> 4) & 0xFF);
12897 *t++ = (char)((m >> 10) & 0xFF);
12898 *t++ = (char)((m >> 2) & 0xFF);
12906 if (c >= 0 && c <= 79)
12907 { m = (m << 6) + soap_base64i[c];
12911 *t++ = (char)((m >> 16) & 0xFF);
12912 *t++ = (char)((m >> 8) & 0xFF);
12913 *t++ = (char)(m & 0xFF);
12922 *n += 3 * SOAP_BLKLEN;
12927 /******************************************************************************/
12932 soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
12933 { register char *p;
12935 t = (char*)soap_malloc(soap, 2 * n + 1);
12937 { soap->error = SOAP_EOM;
12943 { for (; n > 0; n--)
12944 { register int m = *s++;
12945 *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
12947 *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
12955 /******************************************************************************/
12960 soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
12961 { register const char *p;
12967 return SOAP_NON_NULL;
12970 { l = strlen(s) / 2;
12971 t = (char*)soap_malloc(soap, l);
12974 { soap->error = SOAP_EOM;
12979 { register int d1, d2;
12986 *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
12995 /******************************************************************************/
12996 #ifndef WITH_NOHTTP
13001 soap_puthttphdr(struct soap *soap, int status, size_t count)
13002 { register const char *s = NULL;
13003 register int err = SOAP_OK;
13004 #ifndef WITH_LEANER
13005 register const char *r = NULL;
13007 if (status == SOAP_FILE && soap->http_content)
13008 s = soap->http_content;
13009 else if (status == SOAP_HTML)
13010 s = "text/html; charset=utf-8";
13011 else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
13012 { if (soap->version == 2)
13013 s = "application/soap+xml; charset=utf-8";
13015 s = "text/xml; charset=utf-8";
13017 #ifndef WITH_LEANER
13018 if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
13019 { if (soap->mode & SOAP_ENC_MTOM)
13021 s = "application/xop+xml; charset=utf-8";
13024 s = "application/dime";
13026 if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->status != SOAP_GET)
13027 { register const char *t = strchr(s, ';');
13028 sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary);
13030 strncat(soap->tmpbuf, s, t - s);
13032 strcat(soap->tmpbuf, s);
13033 if (soap->mime.start)
13034 { strcat(soap->tmpbuf, "\"; start=\"");
13035 strcat(soap->tmpbuf, soap->mime.start);
13037 strcat(soap->tmpbuf, "\"");
13039 { strcat(soap->tmpbuf, "; start-info=\"");
13040 strcat(soap->tmpbuf, r);
13041 strcat(soap->tmpbuf, "\"");
13046 if (s && (err = soap->fposthdr(soap, "Content-Type", s)))
13049 if (soap->omode & SOAP_ENC_ZLIB)
13052 err = soap->fposthdr(soap, "Content-Encoding", "gzip");
13054 err = soap->fposthdr(soap, "Content-Encoding", "deflate");
13060 #ifndef WITH_LEANER
13061 if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
13062 err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
13065 if (s && soap->status != SOAP_GET)
13066 { sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
13067 err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
13071 return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
13076 /******************************************************************************/
13077 #ifndef WITH_NOHTTP
13080 http_get(struct soap *soap)
13081 { return SOAP_GET_METHOD;
13086 /******************************************************************************/
13087 #ifndef WITH_NOHTTP
13090 http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
13091 { register const char *s;
13093 if (soap->status == SOAP_GET)
13098 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8))
13100 if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
13103 if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*"))
13104 sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
13106 sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
13107 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13110 sprintf(soap->tmpbuf, "%s:%d", host, port);
13112 strcpy(soap->tmpbuf, host);
13113 if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))
13114 || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7"))
13115 || (err = soap_puthttphdr(soap, SOAP_OK, count)))
13119 if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
13121 if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
13126 if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
13127 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
13128 strcpy(soap->tmpbuf, "Basic ");
13129 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
13130 if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
13133 if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
13134 { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
13135 strcpy(soap->tmpbuf, "Basic ");
13136 soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262));
13137 if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
13141 #ifdef WITH_COOKIES
13142 #ifdef WITH_OPENSSL
13143 if (soap_putcookies(soap, host, path, soap->ssl != NULL))
13144 return soap->error;
13146 if (soap_putcookies(soap, host, path, 0))
13147 return soap->error;
13150 if (soap->version == 1 || (action && *action))
13151 { sprintf(soap->tmpbuf, "\"%s\"", action?action:"");
13152 if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
13155 return soap->fposthdr(soap, NULL, NULL);
13160 /******************************************************************************/
13161 #ifndef WITH_NOHTTP
13164 http_send_header(struct soap *soap, const char *s)
13165 { register const char *t;
13167 { t = strchr(s, '\n'); /* disallow \n in HTTP headers */
13170 if (soap_send_raw(soap, s, t - s))
13171 return soap->error;
13179 /******************************************************************************/
13180 #ifndef WITH_NOHTTP
13183 http_post_header(struct soap *soap, const char *key, const char *val)
13185 { if (http_send_header(soap, key))
13186 return soap->error;
13187 if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
13188 return soap->error;
13190 return soap_send_raw(soap, "\r\n", 2);
13195 /******************************************************************************/
13196 #ifndef WITH_NOHTTP
13199 http_response(struct soap *soap, int status, size_t count)
13200 { register int err;
13202 if (soap->rpmreqid)
13203 httpOutputEnable(soap->rpmreqid);
13205 if (!status || status == SOAP_HTML || status == SOAP_FILE)
13207 if (count || ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK))
13210 s = "202 ACCEPTED";
13211 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s));
13213 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
13215 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
13217 { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
13218 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13221 else if ((err = soap->fposthdr(soap, "Status", s)))
13224 else if (status >= 200 && status < 600)
13225 { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
13226 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13230 { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service");
13231 if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
13234 else if ((status >= 301 && status <= 303) || status == 307)
13235 { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
13241 { const char *s = *soap_faultcode(soap);
13242 if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender"))
13243 s = "400 Bad Request";
13245 s = "500 Internal Server Error";
13246 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
13248 if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
13250 if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
13252 { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
13253 if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13256 else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */
13259 if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7"))
13260 || (err = soap_puthttphdr(soap, status, count)))
13262 #ifdef WITH_COOKIES
13263 if (soap_putsetcookies(soap))
13264 return soap->error;
13266 return soap->fposthdr(soap, NULL, NULL);
13271 /******************************************************************************/
13276 soap_response(struct soap *soap, int status)
13277 { register size_t count;
13278 if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
13279 && (status == SOAP_HTML || status == SOAP_FILE))
13280 { soap->omode &= ~SOAP_IO;
13281 soap->omode |= SOAP_IO_STORE;
13283 soap->status = status;
13284 count = soap_count_attachments(soap);
13285 if (soap_begin_send(soap))
13286 return soap->error;
13287 #ifndef WITH_NOHTTP
13288 if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
13289 { register int n = soap->mode;
13290 soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
13291 if ((n & SOAP_IO) != SOAP_IO_FLUSH)
13292 soap->mode |= SOAP_IO_BUFFER;
13293 if ((soap->error = soap->fresponse(soap, status, count)))
13294 return soap->error;
13295 #ifndef WITH_LEANER
13296 if ((n & SOAP_IO) == SOAP_IO_CHUNK)
13297 { if (soap_flush(soap))
13298 return soap->error;
13308 /******************************************************************************/
13311 soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
13313 sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag);
13315 sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS);
13316 return soap->msgbuf;
13320 /******************************************************************************/
13325 soap_set_fault(struct soap *soap)
13326 { const char **c = soap_faultcode(soap);
13327 const char **s = soap_faultstring(soap);
13328 if (soap->fseterror)
13329 soap->fseterror(soap, c, s);
13331 { if (soap->version == 2)
13332 *c = "SOAP-ENV:Sender";
13334 *c = "SOAP-ENV:Client";
13338 switch (soap->error)
13341 case SOAP_CLI_FAULT:
13342 *s = "Client fault";
13344 case SOAP_SVR_FAULT:
13345 *s = "Server fault";
13347 case SOAP_TAG_MISMATCH:
13348 *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
13351 *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
13353 case SOAP_SYNTAX_ERROR:
13354 *s = "Well-formedness violation";
13357 *s = "No XML element tag";
13359 case SOAP_MUSTUNDERSTAND:
13360 *c = "SOAP-ENV:MustUnderstand";
13361 sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
13364 case SOAP_VERSIONMISMATCH:
13365 *c = "SOAP-ENV:VersionMismatch";
13366 *s = "SOAP version mismatch or invalid SOAP message";
13368 case SOAP_DATAENCODINGUNKNOWN:
13369 *c = "SOAP-ENV:DataEncodingUnknown";
13370 *s = "Unsupported SOAP data encoding";
13372 case SOAP_NAMESPACE:
13373 *s = soap_set_validation_fault(soap, "namespace mismatch", NULL);
13375 case SOAP_USER_ERROR:
13378 case SOAP_FATAL_ERROR:
13379 *s = "Fatal error";
13381 case SOAP_NO_METHOD:
13382 sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
13385 case SOAP_GET_METHOD:
13386 *s = "HTTP GET method not implemented";
13389 *s = "Out of memory";
13392 *s = "Array index out of bounds";
13395 *s = soap_set_validation_fault(soap, "nil not allowed", NULL);
13397 case SOAP_DUPLICATE_ID:
13398 *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id);
13399 if (soap->version == 2)
13400 *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
13402 case SOAP_MISSING_ID:
13403 *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
13404 if (soap->version == 2)
13405 *soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
13408 *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id);
13413 case SOAP_UDP_ERROR:
13414 *s = "Message too large for UDP packet";
13416 case SOAP_TCP_ERROR:
13417 *s = tcp_error(soap);
13420 case SOAP_HTTP_ERROR:
13423 case SOAP_SSL_ERROR:
13424 #ifdef WITH_OPENSSL
13427 *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
13430 case SOAP_PLUGIN_ERROR:
13431 *s = "Plugin registry error";
13433 case SOAP_DIME_ERROR:
13434 *s = "DIME format error";
13436 case SOAP_DIME_HREF:
13437 *s = "DIME href to missing attachment";
13439 case SOAP_DIME_MISMATCH:
13440 *s = "DIME version/transmission error";
13442 case SOAP_DIME_END:
13443 *s = "End of DIME error";
13445 case SOAP_MIME_ERROR:
13446 *s = "MIME format error";
13448 case SOAP_MIME_HREF:
13449 *s = "MIME href to missing attachment";
13451 case SOAP_MIME_END:
13452 *s = "End of MIME error";
13454 case SOAP_ZLIB_ERROR:
13456 sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:"");
13459 *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
13462 case SOAP_REQUIRED:
13463 *s = soap_set_validation_fault(soap, "missing required attribute", NULL);
13465 case SOAP_PROHIBITED:
13466 *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
13469 *s = soap_set_validation_fault(soap, "min/maxOccurs violation", NULL);
13472 *s = soap_set_validation_fault(soap, "content length violation", NULL);
13474 case SOAP_FD_EXCEEDED:
13475 *s = "Maximum number of open connections was reached";
13478 *s = "Stopped: no response sent";
13483 sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap));
13487 *s = "End of file or no input";
13491 #ifndef WITH_NOHTTP
13493 if (soap->error > 200 && soap->error < 600)
13494 { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
13500 { sprintf(soap->msgbuf, "Error %d", soap->error);
13507 /******************************************************************************/
13512 soap_send_fault(struct soap *soap)
13513 { register int status = soap->error;
13515 if (status == SOAP_STOP)
13517 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
13518 soap->keep_alive = 0; /* to terminate connection */
13519 soap_set_fault(soap);
13522 if (soap_valid_socket(soap->socket))
13523 { struct timeval timeout;
13525 timeout.tv_sec = 0;
13526 timeout.tv_usec = 0;
13529 FD_SET((SOAP_SOCKET)soap->socket, &rfd);
13530 FD_SET((SOAP_SOCKET)soap->socket, &sfd);
13531 r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, NULL, &timeout);
13533 { if (!FD_ISSET((SOAP_SOCKET)soap->socket, &sfd)
13534 || (FD_ISSET((SOAP_SOCKET)soap->socket, &rfd)
13535 && recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0))
13541 if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0)
13542 { soap->error = SOAP_OK;
13543 soap_serializeheader(soap);
13544 soap_serializefault(soap);
13545 soap_begin_count(soap);
13546 if (soap->mode & SOAP_IO_LENGTH)
13547 { soap_envelope_begin_out(soap);
13548 soap_putheader(soap);
13549 soap_body_begin_out(soap);
13550 soap_putfault(soap);
13551 soap_body_end_out(soap);
13552 soap_envelope_end_out(soap);
13554 soap_end_count(soap);
13555 if (soap_response(soap, status)
13556 || soap_envelope_begin_out(soap)
13557 || soap_putheader(soap)
13558 || soap_body_begin_out(soap)
13559 || soap_putfault(soap)
13560 || soap_body_end_out(soap)
13561 || soap_envelope_end_out(soap))
13562 return soap_closesock(soap);
13563 soap_end_send(soap);
13565 soap->error = status;
13566 return soap_closesock(soap);
13570 /******************************************************************************/
13575 soap_recv_fault(struct soap *soap)
13576 { register int status = soap->error;
13577 DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n"));
13578 soap->error = SOAP_OK;
13579 if (soap_getfault(soap))
13580 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
13581 *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
13582 soap->error = status;
13583 soap_set_fault(soap);
13586 { register const char *s = *soap_faultcode(soap);
13587 if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
13588 status = SOAP_SVR_FAULT;
13589 else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
13590 status = SOAP_CLI_FAULT;
13591 else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
13592 status = SOAP_MUSTUNDERSTAND;
13593 else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
13594 status = SOAP_VERSIONMISMATCH;
13596 { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s));
13597 status = SOAP_FAULT;
13599 if (soap_body_end_in(soap)
13600 || soap_envelope_end_in(soap)
13601 || soap_end_recv(soap))
13602 return soap_closesock(soap);
13603 soap->error = status;
13605 return soap_closesock(soap);
13609 /******************************************************************************/
13610 #ifndef WITH_NOHTTP
13615 soap_send_empty_response(struct soap *soap, int status)
13616 { register soap_mode m = soap->omode;
13618 if ((m & SOAP_IO) == SOAP_IO_CHUNK)
13619 { soap->omode &= ~SOAP_IO_CHUNK;
13620 soap->omode |= SOAP_IO_BUFFER;
13622 if (soap_response(soap, status) || soap_end_send(soap))
13624 return soap_closesock(soap);
13632 /******************************************************************************/
13633 #ifndef WITH_NOHTTP
13638 soap_recv_empty_response(struct soap *soap)
13639 { if (soap_begin_recv(soap) || soap_end_recv(soap))
13640 { if (soap->error != 202)
13641 return soap_closesock(soap);
13642 soap->error = SOAP_OK;
13649 /******************************************************************************/
13653 soap_strerror(struct soap *soap)
13654 { register int err = soap->errnum;
13658 return strerror(err);
13660 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->errorstr, sizeof(soap->errorstr)/sizeof(soap->errorstr[0]), NULL);
13661 return soap->errorstr;
13664 return "Operation interrupted or timed out";
13669 /******************************************************************************/
13672 soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror)
13673 { *soap_faultcode(soap) = faultcode;
13675 *soap_faultsubcode(soap) = faultsubcode;
13676 *soap_faultstring(soap) = faultstring;
13677 if (faultdetail && *faultdetail)
13678 { register const char **s = soap_faultdetail(soap);
13682 return soap->error = soaperror;
13686 /******************************************************************************/
13691 soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
13692 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror);
13696 /******************************************************************************/
13701 soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
13702 { return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror);
13706 /******************************************************************************/
13709 soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail)
13710 { char *r = NULL, *s = NULL, *t = NULL;
13712 r = soap_strdup(soap, faultsubcode);
13714 s = soap_strdup(soap, faultstring);
13716 t = soap_strdup(soap, faultdetail);
13717 return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
13721 /******************************************************************************/
13726 soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
13727 { return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail);
13731 /******************************************************************************/
13736 soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
13737 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail);
13741 /******************************************************************************/
13746 soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
13747 { return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail);
13751 /******************************************************************************/
13756 soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
13757 { return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail);
13761 /******************************************************************************/
13763 #ifndef WITH_NOSTDLIB
13767 soap_print_fault(struct soap *soap, FILE *fd)
13768 { if (soap_check_state(soap))
13769 fprintf(fd, "Error: soap struct not initialized\n");
13770 else if (soap->error)
13771 { const char *c, *v = NULL, *s, **d;
13772 d = soap_faultcode(soap);
13774 soap_set_fault(soap);
13776 if (soap->version == 2)
13777 v = *soap_faultsubcode(soap);
13778 s = *soap_faultstring(soap);
13779 d = soap_faultdetail(soap);
13780 fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]");
13786 /******************************************************************************/
13788 #ifndef WITH_NOSTDLIB
13792 soap_print_fault_location(struct soap *soap, FILE *fd)
13796 if (soap->error && soap->buflen > 0)
13797 { i = (int)soap->bufidx - 1;
13801 soap->buf[i] = '\0';
13802 if ((int)soap->buflen >= i + 1024)
13805 j = (int)soap->buflen - 1;
13807 soap->buf[j] = '\0';
13808 fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
13809 if (soap->bufidx < soap->buflen)
13810 fprintf(fd, "%s\n", soap->buf + soap->bufidx);
13819 /******************************************************************************/
13824 soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
13825 { register struct soap_plugin *p;
13827 if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
13828 return soap->error = SOAP_EOM;
13833 r = fcreate(soap, p, arg);
13834 if (!r && p->fdelete)
13835 { p->next = soap->plugins;
13837 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
13840 DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r));
13841 SOAP_FREE(soap, p);
13846 /******************************************************************************/
13849 fplugin(struct soap *soap, const char *id)
13850 { register struct soap_plugin *p;
13851 for (p = soap->plugins; p; p = p->next)
13852 if (p->id == id || !strcmp(p->id, id))
13858 /******************************************************************************/
13863 soap_lookup_plugin(struct soap *soap, const char *id)
13864 { return soap->fplugin(soap, id);
13868 /******************************************************************************/
13873 /******************************************************************************\
13875 * C++ soap struct methods
13877 \******************************************************************************/
13887 /******************************************************************************/
13890 soap::soap(soap_mode m)
13891 { soap_init1(this, m);
13896 /******************************************************************************/
13899 soap::soap(soap_mode im, soap_mode om)
13900 { soap_init2(this, im, om);
13905 /******************************************************************************/
13908 soap::soap(struct soap& soap)
13909 { soap_copy_context(this, &soap);
13914 /******************************************************************************/
13918 { soap_destroy(this);
13925 /******************************************************************************/