6 gSOAP XML Web services tools
7 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
8 This part of the software is released under ONE of the following licenses:
9 GPL, or the gSOAP public license, or Genivia's license for commercial use.
10 --------------------------------------------------------------------------------
13 Wind River Systems Inc., for the following additions under gSOAP public license:
14 - vxWorks compatible options
15 --------------------------------------------------------------------------------
18 The contents of this file are subject to the gSOAP Public License Version 1.3
19 (the "License"); you may not use this file except in compliance with the
20 License. You may obtain a copy of the License at
21 http://www.cs.fsu.edu/~engelen/soaplicense.html
22 Software distributed under the License is distributed on an "AS IS" basis,
23 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
24 for the specific language governing rights and limitations under the License.
26 The Initial Developer of the Original Code is Robert A. van Engelen.
27 Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
28 --------------------------------------------------------------------------------
31 This program is free software; you can redistribute it and/or modify it under
32 the terms of the GNU General Public License as published by the Free Software
33 Foundation; either version 2 of the License, or (at your option) any later
36 This program is distributed in the hope that it will be useful, but WITHOUT ANY
37 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
38 PARTICULAR PURPOSE. See the GNU General Public License for more details.
40 You should have received a copy of the GNU General Public License along with
41 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
42 Place, Suite 330, Boston, MA 02111-1307 USA
44 Author contact information:
45 engelen@genivia.com / engelen@acm.org
47 This program is released under the GPL with the additional exemption that
48 compiling, linking, and/or using OpenSSL is allowed.
49 --------------------------------------------------------------------------------
50 A commercial use license is available from Genivia, Inc., contact@genivia.com
51 --------------------------------------------------------------------------------
54 #define GSOAP_LIB_VERSION 20817
57 # pragma convert(819) /* EBCDIC to ASCII */
61 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
62 #include <ipcom_key_db.h>
64 #if GSOAP_VERSION != GSOAP_LIB_VERSION
65 # error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE"
73 # pragma comment(lib, "ws2.lib") /* WinCE */
75 # pragma comment(lib, "ws2_32.lib")
77 # pragma warning(disable : 4996) /* disable deprecation warnings */
82 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.17r 2013-12-18 00:00:00 GMT")
85 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.17r 2013-12-18 00:00:00 GMT")
88 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
89 #ifndef SOAP_UNKNOWN_CHAR
90 #define SOAP_UNKNOWN_CHAR (127)
94 #define SOAP_LT (soap_wchar)(-2) /* XML-specific '<' */
95 #define SOAP_TT (soap_wchar)(-3) /* XML-specific '</' */
96 #define SOAP_GT (soap_wchar)(-4) /* XML-specific '>' */
97 #define SOAP_QT (soap_wchar)(-5) /* XML-specific '"' */
98 #define SOAP_AP (soap_wchar)(-6) /* XML-specific ''' */
100 #define soap_blank(c) ((c)+1 > 0 && (c) <= 32)
101 #define soap_notblank(c) ((c) > 32)
103 #if defined(WIN32) && !defined(UNDER_CE)
104 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
106 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
109 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
110 static void soap_init_logs(struct soap
*);
113 static void soap_close_logfile(struct soap
*, int);
114 static void soap_set_logfile(struct soap
*, int, const char*);
117 #ifdef SOAP_MEM_DEBUG
118 static void soap_init_mht(struct soap
*);
119 static void soap_free_mht(struct soap
*);
120 static void soap_track_unlink(struct soap
*, const void*);
124 static int soap_set_error(struct soap
*, const char*, const char*, const char*, const char*, int);
125 static int soap_copy_fault(struct soap
*, const char*, const char*, const char*, const char*);
126 static int soap_getattrval(struct soap
*, char*, size_t, soap_wchar
);
130 static void soap_free_ns(struct soap
*soap
);
131 static soap_wchar
soap_char(struct soap
*);
132 static soap_wchar
soap_get_pi(struct soap
*);
133 static int soap_isxdigit(int);
134 static void *fplugin(struct soap
*, const char*);
135 static size_t soap_count_attachments(struct soap
*soap
);
136 static int soap_try_connect_command(struct soap
*, int http_command
, const char *endpoint
, const char *action
);
138 static int soap_ntlm_handshake(struct soap
*soap
, int command
, const char *endpoint
, const char *host
, int port
);
141 static int soap_has_copies(struct soap
*, const char*, const char*);
142 static void soap_init_iht(struct soap
*);
143 static void soap_free_iht(struct soap
*);
144 static void soap_init_pht(struct soap
*);
145 static void soap_free_pht(struct soap
*);
150 static const char *soap_set_validation_fault(struct soap
*, const char*, const char*);
151 static int soap_isnumeric(struct soap
*, const char*);
152 static struct soap_nlist
*soap_push_ns(struct soap
*soap
, const char *id
, const char *ns
, short utilized
);
153 static void soap_utilize_ns(struct soap
*soap
, const char *tag
);
158 static struct soap_multipart
*soap_new_multipart(struct soap
*, struct soap_multipart
**, struct soap_multipart
**, char*, size_t);
159 static int soap_putdimefield(struct soap
*, const char*, size_t);
160 static char *soap_getdimefield(struct soap
*, size_t);
161 static void soap_select_mime_boundary(struct soap
*);
162 static int soap_valid_mime_boundary(struct soap
*);
163 static void soap_resolve_attachment(struct soap
*, struct soap_multipart
*);
168 static int soap_getgziphdr(struct soap
*);
172 # ifndef SOAP_SSL_RSA_BITS
173 # define SOAP_SSL_RSA_BITS 2048
175 static int soap_ssl_init_done
= 0;
176 static int ssl_auth_init(struct soap
*);
177 static int ssl_verify_callback(int, X509_STORE_CTX
*);
178 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX
*);
179 static int ssl_password(char*, int, int, void *);
183 # ifndef SOAP_SSL_RSA_BITS
184 # define SOAP_SSL_RSA_BITS 2048
186 static int soap_ssl_init_done
= 0;
187 static const char *ssl_verify(struct soap
*soap
, const char *host
);
188 # if defined(HAVE_PTHREAD_H)
189 # include <pthread.h>
190 /* make GNUTLS thread safe with pthreads */
191 GCRY_THREAD_OPTION_PTHREAD_IMPL
;
192 # elif defined(HAVE_PTH_H)
194 /* make GNUTLS thread safe with PTH */
195 GCRY_THREAD_OPTION_PTH_IMPL
;
199 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
201 static const char *soap_decode(char*, size_t, const char*, const char*);
207 static soap_wchar
soap_getchunkchar(struct soap
*);
208 static const char *http_error(struct soap
*, int);
209 static int http_get(struct soap
*);
210 static int http_405(struct soap
*);
211 static int http_200(struct soap
*);
212 static int http_post(struct soap
*, const char*, const char*, int, const char*, const char*, size_t);
213 static int http_send_header(struct soap
*, const char*);
214 static int http_post_header(struct soap
*, const char*, const char*);
215 static int http_response(struct soap
*, int, size_t);
216 static int http_parse(struct soap
*);
217 static int http_parse_header(struct soap
*, const char*, const char*);
224 static int fsend(struct soap
*, const char*, size_t);
225 static size_t frecv(struct soap
*, char*, size_t);
226 static int tcp_init(struct soap
*);
227 static const char *tcp_error(struct soap
*);
229 static int tcp_gethost(struct soap
*, const char *addr
, struct in_addr
*inaddr
);
231 static SOAP_SOCKET
tcp_connect(struct soap
*, const char *endpoint
, const char *host
, int port
);
232 static SOAP_SOCKET
tcp_accept(struct soap
*, SOAP_SOCKET
, struct sockaddr
*, int*);
233 static int tcp_select(struct soap
*, SOAP_SOCKET
, int, int);
234 static int tcp_disconnect(struct soap
*);
235 static int tcp_closesocket(struct soap
*, SOAP_SOCKET
);
236 static int tcp_shutdownsocket(struct soap
*, SOAP_SOCKET
, int);
237 static const char *soap_strerror(struct soap
*);
240 #define SOAP_TCP_SELECT_RCV 0x1
241 #define SOAP_TCP_SELECT_SND 0x2
242 #define SOAP_TCP_SELECT_ERR 0x4
243 #define SOAP_TCP_SELECT_ALL 0x7
246 #define SOAP_SOCKBLOCK(fd) \
247 { u_long blocking = 0; \
248 ioctlsocket(fd, FIONBIO, &blocking); \
250 #define SOAP_SOCKNONBLOCK(fd) \
251 { u_long nonblocking = 1; \
252 ioctlsocket(fd, FIONBIO, &nonblocking); \
254 #elif defined(VXWORKS)
255 #define SOAP_SOCKBLOCK(fd) \
256 { u_long blocking = 0; \
257 ioctl(fd, FIONBIO, (int)(&blocking)); \
259 #define SOAP_SOCKNONBLOCK(fd) \
260 { u_long nonblocking = 1; \
261 ioctl(fd, FIONBIO, (int)(&nonblocking)); \
264 #define SOAP_SOCKBLOCK(fd) \
265 { int blocking = 0; \
266 ioctl(fd, FIONBIO, &blocking); \
268 #define SOAP_SOCKNONBLOCK(fd) \
269 { int nonblocking = 1; \
270 ioctl(fd, FIONBIO, &nonblocking); \
273 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
274 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
275 #elif defined(SYMBIAN)
276 #define SOAP_SOCKBLOCK(fd) \
277 { long blocking = 0; \
278 ioctl(fd, 0/*FIONBIO*/, &blocking); \
280 #define SOAP_SOCKNONBLOCK(fd) \
281 { long nonblocking = 1; \
282 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
285 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
286 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
291 #if defined(PALM) && !defined(PALM_2)
292 unsigned short errno
;
296 static const char soap_env1
[42] = "http://schemas.xmlsoap.org/soap/envelope/";
297 static const char soap_enc1
[42] = "http://schemas.xmlsoap.org/soap/encoding/";
298 static const char soap_env2
[40] = "http://www.w3.org/2003/05/soap-envelope";
299 static const char soap_enc2
[40] = "http://www.w3.org/2003/05/soap-encoding";
300 static const char soap_rpc
[35] = "http://www.w3.org/2003/05/soap-rpc";
304 const union soap_double_nan soap_double_nan
= {{0xFFFFFFFF, 0xFFFFFFFF}};
305 const char soap_base64o
[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
306 const char soap_base64i
[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
310 static const char soap_indent
[11] = "\n\t\t\t\t\t\t\t\t\t";
311 /* Alternative indentation form for SOAP_XML_INDENT:
312 static const char soap_indent[21] = "\n ";
317 # define SOAP_CANARY (0xC0DE)
320 static const char soap_padding
[4] = "\0\0\0";
321 #define SOAP_STR_PADDING (soap_padding)
322 #define SOAP_STR_EOS (soap_padding)
323 #define SOAP_NON_NULL (soap_padding)
326 static const struct soap_code_map html_entity_codes
[] = /* entities for XHTML parsing */
429 static const struct soap_code_map h_error_codes
[] =
431 #ifdef HOST_NOT_FOUND
432 { HOST_NOT_FOUND
, "Host not found" },
435 { TRY_AGAIN
, "Try Again" },
438 { NO_RECOVERY
, "No Recovery" },
441 { NO_DATA
, "No Data" },
444 { NO_ADDRESS
, "No Address" },
453 static const struct soap_code_map h_http_error_codes
[] =
457 { 203, "Non-Authoritative Information" },
458 { 204, "No Content" },
459 { 205, "Reset Content" },
460 { 206, "Partial Content" },
461 { 300, "Multiple Choices" },
462 { 301, "Moved Permanently" },
464 { 303, "See Other" },
465 { 304, "Not Modified" },
466 { 305, "Use Proxy" },
467 { 307, "Temporary Redirect" },
468 { 400, "Bad Request" },
469 { 401, "Unauthorized" },
470 { 402, "Payment Required" },
471 { 403, "Forbidden" },
472 { 404, "Not Found" },
473 { 405, "Method Not Allowed" },
474 { 406, "Not Acceptable" },
475 { 407, "Proxy Authentication Required" },
476 { 408, "Request Time-out" },
479 { 411, "Length Required" },
480 { 412, "Precondition Failed" },
481 { 413, "Request Entity Too Large" },
482 { 414, "Request-URI Too Large" },
483 { 415, "Unsupported Media Type" },
484 { 416, "Requested range not satisfiable" },
485 { 417, "Expectation Failed" },
486 { 500, "Internal Server Error" },
487 { 501, "Not Implemented" },
488 { 502, "Bad Gateway" },
489 { 503, "Service Unavailable" },
490 { 504, "Gateway Time-out" },
491 { 505, "HTTP Version not supported" },
498 static const struct soap_code_map h_ssl_error_codes
[] =
500 #define _SSL_ERROR(e) { e, #e }
501 _SSL_ERROR(SSL_ERROR_SSL
),
502 _SSL_ERROR(SSL_ERROR_ZERO_RETURN
),
503 _SSL_ERROR(SSL_ERROR_WANT_READ
),
504 _SSL_ERROR(SSL_ERROR_WANT_WRITE
),
505 _SSL_ERROR(SSL_ERROR_WANT_CONNECT
),
506 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP
),
507 _SSL_ERROR(SSL_ERROR_SYSCALL
),
513 static const struct soap_code_map mime_codes
[] =
514 { { SOAP_MIME_7BIT
, "7bit" },
515 { SOAP_MIME_8BIT
, "8bit" },
516 { SOAP_MIME_BINARY
, "binary" },
517 { SOAP_MIME_QUOTED_PRINTABLE
, "quoted-printable" },
518 { SOAP_MIME_BASE64
, "base64" },
519 { SOAP_MIME_IETF_TOKEN
, "ietf-token" },
520 { SOAP_MIME_X_TOKEN
, "x-token" },
526 static int tcp_done
= 0;
529 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
533 /******************************************************************************/
537 fsend(struct soap
*soap
, const char *s
, size_t n
)
538 { register int nwritten
, err
;
540 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
542 { soap
->os
->write(s
, (std::streamsize
)n
);
543 if (soap
->os
->good())
550 if (!soap_valid_socket(sk
))
553 { if (soap_valid_socket(sk
))
555 if (soap
->send_timeout
)
560 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_ALL
, soap
->send_timeout
);
565 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_ALL
, soap
->send_timeout
);
568 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
);
576 if (err
!= SOAP_EAGAIN
&& err
!= SOAP_EWOULDBLOCK
)
582 nwritten
= SSL_write(soap
->ssl
, s
, (int)n
);
584 nwritten
= BIO_write(soap
->bio
, s
, (int)n
);
589 nwritten
= gnutls_record_send(soap
->session
, s
, n
);
593 if ((soap
->omode
& SOAP_IO_UDP
))
595 nwritten
= sendto(sk
, (char*)s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, (SOAP_WINSOCKINT
)soap
->peerlen
);
597 nwritten
= send(sk
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
);
598 /* retry and back-off algorithm */
599 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
603 if ((soap
->connect_flags
& SO_BROADCAST
))
604 udp_repeat
= 2; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
606 udp_repeat
= 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
607 udp_delay
= ((unsigned int)soap_random
% 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
609 { tcp_select(soap
, sk
, SOAP_TCP_SELECT_ERR
, -1000 * udp_delay
);
611 nwritten
= sendto(sk
, (char*)s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, (SOAP_WINSOCKINT
)soap
->peerlen
);
613 nwritten
= send(sk
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
);
615 if (udp_delay
> 500) /* UDP_UPPER_DELAY */
618 while (nwritten
< 0 && --udp_repeat
> 0);
621 { err
= soap_socket_errno(sk
);
622 if (err
&& err
!= SOAP_EINTR
)
623 { soap
->errnum
= err
;
626 nwritten
= 0; /* and call write() again */
631 #if !defined(PALM) && !defined(AS400)
632 nwritten
= send(sk
, s
, (int)n
, soap
->socket_flags
);
634 nwritten
= send(sk
, (void*)s
, n
, soap
->socket_flags
);
639 err
= soap_socket_errno(sk
);
641 if (soap
->ssl
&& (r
= SSL_get_error(soap
->ssl
, nwritten
)) != SSL_ERROR_NONE
&& r
!= SSL_ERROR_WANT_READ
&& r
!= SSL_ERROR_WANT_WRITE
)
642 { soap
->errnum
= err
;
648 { if (nwritten
== GNUTLS_E_INTERRUPTED
)
650 else if (nwritten
== GNUTLS_E_AGAIN
)
654 if (err
== SOAP_EWOULDBLOCK
|| err
== SOAP_EAGAIN
)
656 #if defined(WITH_OPENSSL)
657 if (soap
->ssl
&& r
== SSL_ERROR_WANT_READ
)
658 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
660 #elif defined(WITH_GNUTLS)
661 if (soap
->session
&& !gnutls_record_get_direction(soap
->session
))
662 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
665 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
666 if (!r
&& soap
->send_timeout
)
671 else if (err
&& err
!= SOAP_EINTR
)
672 { soap
->errnum
= err
;
675 nwritten
= 0; /* and call write() again */
681 nwritten
= fwrite((void*)s
, 1, n
, stdout
);
685 nwritten
= fwrite(s
, 1, n
, soap
->sendfd
);
690 nwritten
= (httpBlockPut(soap
->rpmreqid
, (char*)s
, n
) == 0) ? n
: -1;
693 nwritten
= fwrite(s
, sizeof(char), n
, fdopen(soap
->sendfd
, "w"));
696 nwritten
= _write(soap
->sendfd
, s
, (unsigned int)n
);
698 nwritten
= write(soap
->sendfd
, s
, (unsigned int)n
);
710 if (err
&& err
!= SOAP_EINTR
&& err
!= SOAP_EWOULDBLOCK
&& err
!= SOAP_EAGAIN
)
711 { soap
->errnum
= err
;
714 nwritten
= 0; /* and call write() again */
725 /******************************************************************************/
730 soap_send_raw(struct soap
*soap
, const char *s
, size_t n
)
734 if (soap
->fpreparesend
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& (soap
->mode
& SOAP_IO_LENGTH
) && (soap
->error
= soap
->fpreparesend(soap
, s
, n
)))
736 if (soap
->ffiltersend
&& (soap
->error
= soap
->ffiltersend(soap
, &s
, &n
)))
739 if (soap
->mode
& SOAP_IO_LENGTH
)
741 else if (soap
->mode
& SOAP_IO
)
742 { register size_t i
= SOAP_BUFLEN
- soap
->bufidx
;
744 { memcpy(soap
->buf
+ soap
->bufidx
, s
, i
);
745 soap
->bufidx
= SOAP_BUFLEN
;
746 if (soap_flush(soap
))
752 memcpy(soap
->buf
+ soap
->bufidx
, s
, n
);
756 return soap_flush_raw(soap
, s
, n
);
761 /******************************************************************************/
766 soap_flush(struct soap
*soap
)
767 { register size_t n
= soap
->bufidx
;
771 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
773 if (soap
->fpreparesend
&& (r
= soap
->fpreparesend(soap
, soap
->buf
, n
)))
774 return soap
->error
= r
;
779 if (soap
->mode
& SOAP_ENC_ZLIB
)
780 { soap
->d_stream
->next_in
= (Byte
*)soap
->buf
;
781 soap
->d_stream
->avail_in
= (unsigned int)n
;
783 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)n
);
786 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflating %u bytes\n", soap
->d_stream
->avail_in
));
787 if (deflate(soap
->d_stream
, Z_NO_FLUSH
) != Z_OK
)
788 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to deflate: %s\n", soap
->d_stream
->msg
? soap
->d_stream
->msg
: SOAP_STR_EOS
));
789 return soap
->error
= SOAP_ZLIB_ERROR
;
791 if (!soap
->d_stream
->avail_out
)
792 { if (soap_flush_raw(soap
, soap
->z_buf
, SOAP_BUFLEN
))
794 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
795 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
797 } while (soap
->d_stream
->avail_in
);
801 return soap_flush_raw(soap
, soap
->buf
, n
);
807 /******************************************************************************/
812 soap_flush_raw(struct soap
*soap
, const char *s
, size_t n
)
813 { if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
815 if (!(t
= (char*)soap_push_block(soap
, NULL
, n
)))
816 return soap
->error
= SOAP_EOM
;
821 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
824 soap_snprintf(t
, sizeof(t
), &"\r\n%lX\r\n"[soap
->chunksize
? 0 : 2], (unsigned long)n
);
826 sprintf(t
, &"\r\n%lX\r\n"[soap
->chunksize
? 0 : 2], (unsigned long)n
);
828 DBGMSG(SENT
, t
, strlen(t
));
829 if ((soap
->error
= soap
->fsend(soap
, t
, strlen(t
))))
831 soap
->chunksize
+= n
;
834 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n
, soap
->socket
, soap
->sendfd
));
836 return soap
->error
= soap
->fsend(soap
, s
, n
);
840 /******************************************************************************/
845 soap_send(struct soap
*soap
, const char *s
)
847 return soap_send_raw(soap
, s
, strlen(s
));
852 /******************************************************************************/
858 soap_send2(struct soap
*soap
, const char *s1
, const char *s2
)
859 { if (soap_send(soap
, s1
))
861 return soap_send(soap
, s2
);
866 /******************************************************************************/
872 soap_send3(struct soap
*soap
, const char *s1
, const char *s2
, const char *s3
)
873 { if (soap_send(soap
, s1
)
874 || soap_send(soap
, s2
))
876 return soap_send(soap
, s3
);
881 /******************************************************************************/
885 frecv(struct soap
*soap
, char *s
, size_t n
)
887 register int retries
= 100; /* max 100 retries with non-blocking sockets */
890 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
892 { if (soap
->is
->good())
893 return soap
->is
->read(s
, (std::streamsize
)n
).gcount();
898 if (!soap_valid_socket(sk
))
900 if (soap_valid_socket(sk
))
904 register int err
= 0;
907 if (soap
->recv_timeout
&& !soap
->ssl
) /* SSL: sockets are nonblocking */
909 if (soap
->recv_timeout
)
912 { r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
);
918 if (r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
924 { r
= SSL_read(soap
->ssl
, s
, (int)n
);
927 err
= SSL_get_error(soap
->ssl
, r
);
928 if (err
!= SSL_ERROR_NONE
&& err
!= SSL_ERROR_WANT_READ
&& err
!= SSL_ERROR_WANT_WRITE
)
932 { r
= BIO_read(soap
->bio
, s
, (int)n
);
941 { r
= (int)gnutls_record_recv(soap
->session
, s
, n
);
949 if ((soap
->omode
& SOAP_IO_UDP
))
950 { SOAP_SOCKLEN_T k
= (SOAP_SOCKLEN_T
)sizeof(soap
->peer
);
951 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
952 r
= recvfrom(sk
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, &k
); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
953 soap
->peerlen
= (size_t)k
;
955 soap
->ip
= ntohl(soap
->peer
.sin_addr
.s_addr
);
960 r
= recv(sk
, s
, (int)n
, soap
->socket_flags
);
962 /* CycleSyncDisplay(curStatusMsg); */
966 r
= soap_socket_errno(sk
);
967 if (r
!= SOAP_EINTR
&& r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
972 #if defined(WITH_OPENSSL)
973 if (soap
->ssl
&& err
== SSL_ERROR_WANT_WRITE
)
974 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
976 #elif defined(WITH_GNUTLS)
977 if (soap
->session
&& gnutls_record_get_direction(soap
->session
))
978 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
981 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
982 if (!r
&& soap
->recv_timeout
)
986 if (r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
992 r
= soap_socket_errno(sk
);
993 if (r
!= SOAP_EINTR
&& retries
-- <= 0)
1001 return fread(s
, 1, n
, stdin
);
1004 return fread(s
, 1, n
, soap
->recvfd
);
1008 r
= httpBlockRead(soap
->rpmreqid
, s
, n
);
1012 r
= _read(soap
->recvfd
, s
, (unsigned int)n
);
1014 r
= read(soap
->recvfd
, s
, (unsigned int)n
);
1018 soap
->errnum
= soap_errno
;
1026 /******************************************************************************/
1030 soap_getchunkchar(struct soap
*soap
)
1031 { if (soap
->bufidx
< soap
->buflen
)
1032 return soap
->buf
[soap
->bufidx
++];
1034 soap
->buflen
= soap
->chunkbuflen
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1035 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)soap
->buflen
, soap
->socket
, soap
->recvfd
));
1036 DBGMSG(RECV
, soap
->buf
, soap
->buflen
);
1038 return soap
->buf
[soap
->bufidx
++];
1044 /******************************************************************************/
1047 soap_isxdigit(int c
)
1048 { return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a' && c
<= 'f');
1052 /******************************************************************************/
1057 soap_recv_raw(struct soap
*soap
)
1058 { register size_t ret
;
1059 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
1063 if (soap
->mode
& SOAP_ENC_ZLIB
)
1064 { if (soap
->d_stream
->next_out
== Z_NULL
)
1065 { soap
->bufidx
= soap
->buflen
= 0;
1068 if (soap
->d_stream
->avail_in
|| !soap
->d_stream
->avail_out
)
1069 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflating\n"));
1070 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
1071 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
1072 r
= inflate(soap
->d_stream
, Z_NO_FLUSH
);
1073 if (r
== Z_NEED_DICT
&& soap
->z_dict
)
1074 r
= inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
);
1075 if (r
== Z_OK
|| r
== Z_STREAM_END
)
1077 ret
= soap
->buflen
= SOAP_BUFLEN
- soap
->d_stream
->avail_out
;
1078 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
1079 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)ret
);
1080 if (r
== Z_STREAM_END
)
1081 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
1082 soap
->z_ratio_in
= (float)soap
->d_stream
->total_in
/ (float)soap
->d_stream
->total_out
;
1083 soap
->d_stream
->next_out
= Z_NULL
;
1086 { soap
->count
+= ret
;
1087 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- decompressed ----\n"));
1088 DBGMSG(RECV
, soap
->buf
, ret
);
1089 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n----\n"));
1091 if (soap
->fpreparerecv
&& (r
= soap
->fpreparerecv(soap
, soap
->buf
, ret
)))
1092 return soap
->error
= r
;
1097 else if (r
!= Z_BUF_ERROR
)
1098 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflate error: %s\n", soap
->d_stream
->msg
? soap
->d_stream
->msg
: SOAP_STR_EOS
));
1099 soap
->d_stream
->next_out
= Z_NULL
;
1100 return soap
->error
= SOAP_ZLIB_ERROR
;
1104 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
&& !soap
->chunksize
)
1105 { memcpy(soap
->buf
, soap
->z_buf
, SOAP_BUFLEN
);
1106 soap
->buflen
= soap
->z_buflen
;
1108 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- compressed ----\n"));
1112 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
) /* read HTTP chunked transfer */
1114 { register soap_wchar c
;
1116 if (soap
->chunksize
)
1117 { soap
->buflen
= ret
= soap
->frecv(soap
, soap
->buf
, soap
->chunksize
> SOAP_BUFLEN
? SOAP_BUFLEN
: soap
->chunksize
);
1118 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Getting chunk: read %u bytes\n", (unsigned int)ret
));
1119 DBGMSG(RECV
, soap
->buf
, ret
);
1121 soap
->chunksize
-= ret
;
1125 if (!soap
->chunkbuflen
)
1126 { soap
->chunkbuflen
= ret
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1127 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret
, soap
->socket
));
1128 DBGMSG(RECV
, soap
->buf
, ret
);
1131 { soap
->ahead
= EOF
;
1136 soap
->bufidx
= soap
->buflen
;
1137 soap
->buflen
= soap
->chunkbuflen
;
1138 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap
->bufidx
, (unsigned int)soap
->buflen
));
1139 while (!soap_isxdigit((int)(c
= soap_getchunkchar(soap
))))
1140 { if ((int)c
== EOF
)
1141 { soap
->ahead
= EOF
;
1147 while (soap_isxdigit((int)(c
= soap_getchunkchar(soap
))) && (size_t)(t
- tmp
) < sizeof(tmp
)-1);
1148 while ((int)c
!= EOF
&& c
!= '\n')
1149 c
= soap_getchunkchar(soap
);
1151 { soap
->ahead
= EOF
;
1155 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunk size = %s (hex)\n", tmp
));
1156 soap
->chunksize
= (size_t)soap_strtoul(tmp
, &t
, 16);
1157 if (!soap
->chunksize
)
1158 { soap
->bufidx
= soap
->buflen
= soap
->chunkbuflen
= 0;
1159 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of chunked message\n"));
1160 while ((int)c
!= EOF
&& c
!= '\n')
1161 c
= soap_getchunkchar(soap
);
1166 soap
->buflen
= soap
->bufidx
+ soap
->chunksize
;
1167 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap
->bufidx
, (unsigned int)soap
->buflen
, tmp
));
1168 if (soap
->buflen
> soap
->chunkbuflen
)
1169 { soap
->buflen
= soap
->chunkbuflen
;
1170 soap
->chunksize
-= soap
->buflen
- soap
->bufidx
;
1171 soap
->chunkbuflen
= 0;
1172 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap
->buflen
- soap
->bufidx
)));
1174 else if (soap
->chunkbuflen
)
1175 soap
->chunksize
= 0;
1176 ret
= soap
->buflen
- soap
->bufidx
;
1184 soap
->buflen
= ret
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1185 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes from socket=%d/fd=%d\n", (unsigned int)ret
, soap
->socket
, soap
->recvfd
));
1186 DBGMSG(RECV
, soap
->buf
, ret
);
1189 if (soap
->mode
& SOAP_ENC_ZLIB
)
1190 { memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
1191 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
1192 soap
->d_stream
->avail_in
= (unsigned int)ret
;
1193 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
1194 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
1195 r
= inflate(soap
->d_stream
, Z_NO_FLUSH
);
1196 if (r
== Z_NEED_DICT
&& soap
->z_dict
)
1197 r
= inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
);
1198 if (r
== Z_OK
|| r
== Z_STREAM_END
)
1200 soap
->z_buflen
= soap
->buflen
;
1201 soap
->buflen
= SOAP_BUFLEN
- soap
->d_stream
->avail_out
;
1202 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
1203 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)soap
->buflen
);
1204 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated %u bytes\n", (unsigned int)soap
->buflen
));
1205 if (ret
&& !soap
->buflen
&& r
!= Z_STREAM_END
)
1208 if (r
== Z_STREAM_END
)
1209 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated total %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
1210 soap
->z_ratio_in
= (float)soap
->d_stream
->total_in
/ (float)soap
->d_stream
->total_out
;
1211 soap
->d_stream
->next_out
= Z_NULL
;
1213 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- decompressed ----\n"));
1214 DBGMSG(RECV
, soap
->buf
, ret
);
1216 if (soap
->fpreparerecv
&& (r
= soap
->fpreparerecv(soap
, soap
->buf
, ret
)))
1217 return soap
->error
= r
;
1221 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to inflate: (%d) %s\n", r
, soap
->d_stream
->msg
? soap
->d_stream
->msg
: SOAP_STR_EOS
));
1222 soap
->d_stream
->next_out
= Z_NULL
;
1223 return soap
->error
= SOAP_ZLIB_ERROR
;
1228 if (soap
->fpreparerecv
1230 && soap
->zlib_in
== SOAP_ZLIB_NONE
1232 && (r
= soap
->fpreparerecv(soap
, soap
->buf
+ soap
->bufidx
, ret
)))
1233 return soap
->error
= r
;
1236 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read count=%lu (+%lu)\n", (unsigned long)soap
->count
, (unsigned long)ret
));
1241 /******************************************************************************/
1246 soap_recv(struct soap
*soap
)
1249 if (soap
->mode
& SOAP_ENC_DIME
)
1250 { if (soap
->dime
.buflen
)
1253 unsigned char tmp
[12];
1254 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME hdr for chunked DIME is in buffer\n"));
1255 soap
->count
+= soap
->dime
.buflen
- soap
->buflen
;
1256 soap
->buflen
= soap
->dime
.buflen
;
1257 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Skip padding (%ld bytes)\n", -(long)soap
->dime
.size
&3));
1258 for (i
= -(long)soap
->dime
.size
&3; i
> 0; i
--)
1260 if (soap
->bufidx
>= soap
->buflen
)
1261 if (soap_recv_raw(soap
))
1264 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME hdr for next chunk\n"));
1266 for (i
= 12; i
> 0; i
--)
1267 { *s
++ = soap
->buf
[soap
->bufidx
++];
1268 if (soap
->bufidx
>= soap
->buflen
)
1269 if (soap_recv_raw(soap
))
1272 soap
->dime
.flags
= tmp
[0] & 0x7;
1273 soap
->dime
.size
= ((size_t)tmp
[8] << 24) | ((size_t)tmp
[9] << 16) | ((size_t)tmp
[10] << 8) | ((size_t)tmp
[11]);
1274 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME chunk (%u bytes)\n", (unsigned int)soap
->dime
.size
));
1275 if (soap
->dime
.flags
& SOAP_DIME_CF
)
1276 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "More chunking\n"));
1277 soap
->dime
.chunksize
= soap
->dime
.size
;
1278 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.size
)
1279 { soap
->dime
.buflen
= soap
->buflen
;
1280 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
1283 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
1286 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Last chunk\n"));
1287 soap
->dime
.buflen
= 0;
1288 soap
->dime
.chunksize
= 0;
1290 soap
->count
= soap
->buflen
- soap
->bufidx
;
1291 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%u bytes remaining\n", (unsigned int)soap
->count
));
1294 if (soap
->dime
.chunksize
)
1295 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap
->dime
.chunksize
));
1296 if (soap_recv_raw(soap
))
1298 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.chunksize
)
1299 { soap
->dime
.buflen
= soap
->buflen
;
1300 soap
->count
-= soap
->buflen
- soap
->bufidx
- soap
->dime
.chunksize
;
1301 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
1304 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
1305 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%lu bytes remaining, count=%lu\n", (unsigned long)(soap
->buflen
-soap
->bufidx
), (unsigned long)soap
->count
));
1309 while (soap
->ffilterrecv
)
1310 { int err
, last
= soap
->filterstop
;
1312 soap
->bufidx
= soap
->buflen
= 0;
1313 if ((err
= soap
->ffilterrecv(soap
, soap
->buf
, &soap
->buflen
, sizeof(soap
->buf
))))
1314 return soap
->error
= err
;
1317 soap
->filterstop
= last
;
1321 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Returning postponed error %d\n", last
));
1322 soap
->filterstop
= SOAP_OK
;
1325 soap
->filterstop
= soap_recv_raw(soap
); /* do not call again after EOF */
1328 return soap_recv_raw(soap
);
1332 /******************************************************************************/
1337 soap_getchar(struct soap
*soap
)
1338 { register soap_wchar c
;
1345 return soap_get1(soap
);
1349 /******************************************************************************/
1352 const struct soap_code_map
*
1354 soap_code(const struct soap_code_map
*code_map
, const char *str
)
1355 { if (code_map
&& str
)
1356 { while (code_map
->string
)
1357 { if (!strcmp(str
, code_map
->string
)) /* case sensitive */
1366 /******************************************************************************/
1371 soap_code_int(const struct soap_code_map
*code_map
, const char *str
, long other
)
1373 { while (code_map
->string
)
1374 { if (!soap_tag_cmp(str
, code_map
->string
)) /* case insensitive */
1375 return code_map
->code
;
1383 /******************************************************************************/
1388 soap_code_str(const struct soap_code_map
*code_map
, long code
)
1391 while (code_map
->code
!= code
&& code_map
->string
)
1393 return code_map
->string
;
1397 /******************************************************************************/
1402 soap_code_bits(const struct soap_code_map
*code_map
, const char *str
)
1403 { register long bits
= 0;
1405 { while (str
&& *str
)
1406 { const struct soap_code_map
*p
;
1407 for (p
= code_map
; p
->string
; p
++)
1408 { register size_t n
= strlen(p
->string
);
1409 if (!strncmp(p
->string
, str
, n
) && soap_blank((soap_wchar
)str
[n
]))
1412 while (*str
> 0 && *str
<= 32)
1425 /******************************************************************************/
1430 soap_code_list(struct soap
*soap
, const struct soap_code_map
*code_map
, long code
)
1431 { register char *t
= soap
->tmpbuf
;
1433 { while (code_map
->string
)
1434 { if (code_map
->code
& code
)
1435 { register const char *s
= code_map
->string
;
1436 if (t
!= soap
->tmpbuf
)
1438 while (*s
&& t
< soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 1)
1440 if (t
== soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 1)
1447 return soap
->tmpbuf
;
1451 /******************************************************************************/
1454 soap_char(struct soap
*soap
)
1457 register soap_wchar c
;
1458 register char *s
= tmp
;
1459 for (i
= 0; i
< 7; i
++)
1460 { c
= soap_get1(soap
);
1461 if (c
== ';' || (int)c
== EOF
)
1467 { if (tmp
[1] == 'x' || tmp
[1] == 'X')
1468 return (soap_wchar
)soap_strtol(tmp
+ 2, NULL
, 16);
1469 return (soap_wchar
)soap_strtol(tmp
+ 1, NULL
, 10);
1471 if (!strcmp(tmp
, "lt"))
1473 if (!strcmp(tmp
, "gt"))
1475 if (!strcmp(tmp
, "amp"))
1477 if (!strcmp(tmp
, "quot"))
1479 if (!strcmp(tmp
, "apos"))
1482 return (soap_wchar
)soap_code_int(html_entity_codes
, tmp
, SOAP_UNKNOWN_CHAR
);
1484 return SOAP_UNKNOWN_CHAR
; /* use this to represent unknown code */
1489 /******************************************************************************/
1493 soap_get0(struct soap
*soap
)
1494 { if (soap
->bufidx
>= soap
->buflen
&& soap_recv(soap
))
1496 return (unsigned char)soap
->buf
[soap
->bufidx
];
1501 /******************************************************************************/
1505 soap_get1(struct soap
*soap
)
1506 { if (soap
->bufidx
>= soap
->buflen
&& soap_recv(soap
))
1508 return (unsigned char)soap
->buf
[soap
->bufidx
++];
1513 /******************************************************************************/
1518 soap_get(struct soap
*soap
)
1519 { register soap_wchar c
;
1522 { if ((int)c
!= EOF
)
1526 c
= soap_get1(soap
);
1527 while ((int)c
!= EOF
)
1530 { c
= soap_get1(soap
);
1532 { c
= soap_get0(soap
);
1535 c
= soap_get1(soap
);
1536 c
= soap_get1(soap
);
1539 { soap_unget(soap
, ']');
1544 { soap_revget1(soap
);
1553 do c
= soap_get1(soap
);
1554 while (soap_blank(c
));
1555 if (c
== '!' || c
== '?' || c
== '%')
1556 { register int k
= 1;
1558 { c
= soap_get1(soap
);
1560 { do c
= soap_get1(soap
);
1561 while ((int)c
!= EOF
&& c
!= '[');
1565 c
= soap_get1(soap
);
1568 if (c
== '-' && (c
= soap_get1(soap
)) == '-')
1570 { c
= soap_get1(soap
);
1571 if (c
== '-' && (c
= soap_get1(soap
)) == '-')
1573 } while ((int)c
!= EOF
);
1577 c
= soap_get_pi(soap
);
1578 while ((int)c
!= EOF
)
1585 c
= soap_get1(soap
);
1589 c
= soap_get1(soap
);
1603 return soap_char(soap
) | 0x80000000;
1611 /******************************************************************************/
1614 soap_get_pi(struct soap
*soap
)
1616 register char *s
= buf
;
1617 register int i
= sizeof(buf
);
1618 register soap_wchar c
= soap_getchar(soap
);
1619 /* This is a quick way to parse XML PI and we could use a callback instead to
1620 * enable applications to intercept processing instructions */
1621 while ((int)c
!= EOF
&& c
!= '?')
1623 { if (soap_blank(c
))
1627 c
= soap_getchar(soap
);
1630 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "XML PI <?%s?>\n", buf
));
1631 if (!strncmp(buf
, "xml ", 4))
1632 { s
= strstr(buf
, " encoding=");
1634 { if (!soap_tag_cmp(s
+ 11, "iso-8859-1*")
1635 || !soap_tag_cmp(s
+ 11, "latin1*"))
1636 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Switching to latin1 encoding\n"));
1637 soap
->mode
|= SOAP_ENC_LATIN
;
1639 else if (!soap_tag_cmp(s
+ 11, "utf-8*"))
1640 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Switching to utf-8 encoding\n"));
1641 soap
->mode
&= ~SOAP_ENC_LATIN
;
1646 c
= soap_getchar(soap
);
1651 /******************************************************************************/
1657 soap_move(struct soap
*soap
, size_t n
)
1658 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Moving %lu bytes forward\n", (unsigned long)n
));
1660 if ((int)soap_getchar(soap
) == EOF
)
1667 /******************************************************************************/
1673 soap_tell(struct soap
*soap
)
1674 { return soap
->count
- soap
->buflen
+ soap
->bufidx
- (soap
->ahead
!= 0);
1679 /******************************************************************************/
1684 soap_pututf8(struct soap
*soap
, register unsigned long c
)
1686 if (c
< 0x80 && c
> 0)
1688 return soap_send_raw(soap
, tmp
, 1);
1692 { register char *t
= tmp
;
1694 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
1697 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
1700 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
1702 { if (c
< 0x04000000)
1703 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
1705 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
1706 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
1708 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
1710 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
1712 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
1714 *t
++ = (char)(0x80 | (c
& 0x3F));
1719 #ifdef HAVE_SNPRINTF
1720 soap_snprintf(tmp
, sizeof(tmp
), "&#%lu;", c
);
1722 sprintf(tmp
, "&#%lu;", c
);
1724 return soap_send(soap
, tmp
);
1728 /******************************************************************************/
1733 soap_getutf8(struct soap
*soap
)
1734 { register soap_wchar c
, c1
, c2
, c3
, c4
;
1740 if (c
< 0x80 || c
> 0xFF || (soap
->mode
& SOAP_ENC_LATIN
))
1742 c1
= soap_get1(soap
);
1744 { soap_revget1(soap
); /* doesn't look like this is UTF8 */
1749 return ((soap_wchar
)(c
& 0x1F) << 6) | c1
;
1750 c2
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1752 return ((soap_wchar
)(c
& 0x0F) << 12) | (c1
<< 6) | c2
;
1753 c3
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1755 return ((soap_wchar
)(c
& 0x07) << 18) | (c1
<< 12) | (c2
<< 6) | c3
;
1756 c4
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1758 return ((soap_wchar
)(c
& 0x03) << 24) | (c1
<< 18) | (c2
<< 12) | (c3
<< 6) | c4
;
1759 return ((soap_wchar
)(c
& 0x01) << 30) | (c1
<< 24) | (c2
<< 18) | (c3
<< 12) | (c4
<< 6) | (soap_wchar
)(soap_get1(soap
) & 0x3F);
1763 /******************************************************************************/
1768 soap_puthex(struct soap
*soap
, const unsigned char *s
, int n
)
1772 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1773 { if (!(soap
->dom
->data
= soap_s2hex(soap
, s
, NULL
, n
)))
1778 for (i
= 0; i
< n
; i
++)
1779 { register int m
= *s
++;
1780 d
[0] = (char)((m
>> 4) + (m
> 159 ? '7' : '0'));
1782 d
[1] = (char)(m
+ (m
> 9 ? '7' : '0'));
1783 if (soap_send_raw(soap
, d
, 2))
1790 /******************************************************************************/
1795 soap_gethex(struct soap
*soap
, int *n
)
1798 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1799 { soap
->dom
->data
= soap_string_in(soap
, 0, -1, -1);
1800 return (unsigned char*)soap_hex2s(soap
, soap
->dom
->data
, NULL
, 0, n
);
1807 register size_t i
, k
;
1808 if (soap_append_lab(soap
, NULL
, 0))
1810 s
= soap
->labbuf
+ soap
->labidx
;
1811 k
= soap
->lablen
- soap
->labidx
;
1812 soap
->labidx
= soap
->lablen
;
1813 for (i
= 0; i
< k
; i
++)
1814 { register char d1
, d2
;
1815 register soap_wchar c
;
1817 if (soap_isxdigit(c
))
1820 if (soap_isxdigit(c
))
1823 { soap
->error
= SOAP_TYPE
;
1829 soap_unget(soap
, c
);
1831 *n
= (int)(soap
->lablen
+ i
- k
);
1832 p
= (unsigned char*)soap_malloc(soap
, soap
->lablen
+ i
- k
);
1834 memcpy(p
, soap
->labbuf
, soap
->lablen
+ i
- k
);
1837 *s
++ = (char)(((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0'));
1841 if (soap_new_block(soap
) == NULL
)
1845 register char *s
= (char*)soap_push_block(soap
, NULL
, SOAP_BLKLEN
);
1847 { soap_end_block(soap
, NULL
);
1850 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
1851 { register char d1
, d2
;
1852 register soap_wchar c
= soap_get(soap
);
1853 if (soap_isxdigit(c
))
1856 if (soap_isxdigit(c
))
1859 { soap_end_block(soap
, NULL
);
1860 soap
->error
= SOAP_TYPE
;
1866 soap_unget(soap
, c
);
1868 *n
= (int)soap_size_block(soap
, NULL
, i
);
1869 p
= (unsigned char*)soap_save_block(soap
, NULL
, 0);
1872 *s
++ = ((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0');
1879 /******************************************************************************/
1884 soap_putbase64(struct soap
*soap
, const unsigned char *s
, int n
)
1886 register unsigned long m
;
1891 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1892 { if (!(soap
->dom
->data
= soap_s2base64(soap
, s
, NULL
, n
)))
1897 for (; n
> 2; n
-= 3, s
+= 3)
1899 m
= (m
<< 8) | s
[1];
1900 m
= (m
<< 8) | s
[2];
1901 for (i
= 4; i
> 0; m
>>= 6)
1902 d
[--i
] = soap_base64o
[m
& 0x3F];
1903 if (soap_send_raw(soap
, d
, 4))
1908 for (i
= 0; i
< n
; i
++)
1909 m
= (m
<< 8) | *s
++;
1912 for (i
++; i
> 0; m
>>= 6)
1913 d
[--i
] = soap_base64o
[m
& 0x3F];
1914 for (i
= 3; i
> n
; i
--)
1916 if (soap_send_raw(soap
, d
, 4))
1923 /******************************************************************************/
1928 soap_getbase64(struct soap
*soap
, int *n
, int malloc_flag
)
1929 { (void)malloc_flag
;
1931 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1932 { soap
->dom
->data
= soap_string_in(soap
, 0, -1, -1);
1933 return (unsigned char*)soap_base642s(soap
, soap
->dom
->data
, NULL
, 0, n
);
1939 { register size_t i
, k
;
1941 if (soap_append_lab(soap
, NULL
, 2))
1943 s
= soap
->labbuf
+ soap
->labidx
;
1944 k
= soap
->lablen
- soap
->labidx
;
1945 soap
->labidx
= 3 * (soap
->lablen
/ 3);
1949 { for (i
= 0; i
< k
- 2; i
+= 3)
1950 { register unsigned long m
= 0;
1953 { register soap_wchar c
= soap_get(soap
);
1956 if (c
== '=' || c
< 0)
1960 *s
++ = (char)((m
>> 4) & 0xFF);
1964 *s
++ = (char)((m
>> 10) & 0xFF);
1965 *s
++ = (char)((m
>> 2) & 0xFF);
1969 *n
= (int)(soap
->lablen
+ i
- k
);
1970 p
= (unsigned char*)soap_malloc(soap
, soap
->lablen
+ i
- k
);
1972 memcpy(p
, soap
->labbuf
, soap
->lablen
+ i
- k
);
1974 { while ((int)((c
= soap_get(soap
)) != EOF
) && c
!= SOAP_LT
&& c
!= SOAP_TT
)
1977 soap_unget(soap
, c
);
1981 if (c
>= 0 && c
<= 79)
1982 { register int b
= soap_base64i
[c
];
1984 { soap
->error
= SOAP_TYPE
;
1990 else if (!soap_blank(c
+ '+'))
1991 { soap
->error
= SOAP_TYPE
;
1995 *s
++ = (char)((m
>> 16) & 0xFF);
1996 *s
++ = (char)((m
>> 8) & 0xFF);
1997 *s
++ = (char)(m
& 0xFF);
2002 if (soap_new_block(soap
) == NULL
)
2006 register char *s
= (char*)soap_push_block(soap
, NULL
, 3 * SOAP_BLKLEN
); /* must be multiple of 3 */
2008 { soap_end_block(soap
, NULL
);
2011 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
2012 { register unsigned long m
= 0;
2015 { register soap_wchar c
= soap_get(soap
);
2016 if (c
== '=' || c
< 0)
2021 *s
++ = (char)((m
>> 4) & 0xFF);
2025 *s
++ = (char)((m
>> 10) & 0xFF);
2026 *s
++ = (char)((m
>> 2) & 0xFF);
2030 *n
= (int)soap_size_block(soap
, NULL
, i
);
2031 p
= (unsigned char*)soap_save_block(soap
, NULL
, 0);
2033 { while ((int)((c
= soap_get(soap
)) != EOF
) && c
!= SOAP_LT
&& c
!= SOAP_TT
)
2036 soap_unget(soap
, c
);
2040 if (c
>= 0 && c
<= 79)
2041 { int b
= soap_base64i
[c
];
2043 { soap
->error
= SOAP_TYPE
;
2049 else if (!soap_blank(c
))
2050 { soap
->error
= SOAP_TYPE
;
2054 *s
++ = (char)((m
>> 16) & 0xFF);
2055 *s
++ = (char)((m
>> 8) & 0xFF);
2056 *s
++ = (char)(m
& 0xFF);
2063 /******************************************************************************/
2069 soap_xop_forward(struct soap
*soap
, unsigned char **ptr
, int *size
, char **id
, char **type
, char **options
)
2070 { /* Check MTOM xop:Include element (within hex/base64Binary) */
2071 /* TODO: this code to be obsoleted with new import/xop.h conventions */
2072 short body
= soap
->body
; /* should save type too? */
2073 if (!soap_peek_element(soap
))
2074 { if (!soap_element_begin_in(soap
, "xop:Include", 0, NULL
))
2075 { if (soap_dime_forward(soap
, ptr
, size
, id
, type
, options
)
2076 || (soap
->body
&& soap_element_end_in(soap
, "xop:Include")))
2086 /******************************************************************************/
2092 soap_dime_forward(struct soap
*soap
, unsigned char **ptr
, int *size
, char **id
, char **type
, char **options
)
2093 { struct soap_xlist
*xp
;
2101 *id
= soap_strdup(soap
, soap
->href
);
2102 xp
= (struct soap_xlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_xlist
));
2104 return soap
->error
= SOAP_EOM
;
2105 xp
->next
= soap
->xlist
;
2110 xp
->options
= options
;
2117 /******************************************************************************/
2122 soap_strdup(struct soap
*soap
, const char *s
)
2124 if (s
&& (t
= (char*)soap_malloc(soap
, strlen(s
) + 1)))
2130 /******************************************************************************/
2135 soap_wstrdup(struct soap
*soap
, const wchar_t *s
)
2136 { wchar_t *t
= NULL
;
2141 if ((t
= (wchar_t*)soap_malloc(soap
, sizeof(wchar_t)*(n
+1))))
2142 memcpy(t
, s
, sizeof(wchar_t)*(n
+1));
2148 /******************************************************************************/
2153 soap_new_block(struct soap
*soap
)
2154 { struct soap_blist
*p
;
2155 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "New block sequence (prev=%p)\n", soap
->blist
));
2156 if (!(p
= (struct soap_blist
*)SOAP_MALLOC(soap
, sizeof(struct soap_blist
))))
2157 { soap
->error
= SOAP_EOM
;
2160 p
->next
= soap
->blist
;
2168 /******************************************************************************/
2173 soap_push_block(struct soap
*soap
, struct soap_blist
*b
, size_t n
)
2177 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n
, (unsigned int)b
->size
+ (unsigned int)n
));
2178 if (!(p
= (char*)SOAP_MALLOC(soap
, n
+ sizeof(char*) + sizeof(size_t))))
2179 { soap
->error
= SOAP_EOM
;
2182 *(char**)p
= b
->ptr
;
2183 *(size_t*)(p
+ sizeof(char*)) = n
;
2186 return p
+ sizeof(char*) + sizeof(size_t);
2190 /******************************************************************************/
2195 soap_pop_block(struct soap
*soap
, struct soap_blist
*b
)
2201 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Pop block\n"));
2203 b
->size
-= *(size_t*)(p
+ sizeof(char*));
2204 b
->ptr
= *(char**)p
;
2209 /******************************************************************************/
2214 soap_update_pointers(struct soap
*soap
, char *start
, char *end
, char *p1
, char *p2
)
2216 #ifndef WITH_NOIDREF
2218 register struct soap_ilist
*ip
= NULL
;
2219 register struct soap_flist
*fp
= NULL
;
2221 register struct soap_xlist
*xp
= NULL
;
2223 register void *p
, **q
;
2224 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2225 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2226 { if (ip
->ptr
&& (char*)ip
->ptr
>= start
&& (char*)ip
->ptr
< end
)
2227 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Update id='%s' %p -> %p\n", ip
->id
, ip
->ptr
, (char*)ip
->ptr
+ (p1
-p2
)));
2228 ip
->ptr
= (char*)ip
->ptr
+ (p1
-p2
);
2230 for (q
= &ip
->link
; q
; q
= (void**)p
)
2232 if (p
&& (char*)p
>= start
&& (char*)p
< end
)
2233 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Link update id='%s' %p\n", ip
->id
, p
));
2234 *q
= (char*)p
+ (p1
-p2
);
2237 for (q
= &ip
->copy
; q
; q
= (void**)p
)
2239 if (p
&& (char*)p
>= start
&& (char*)p
< end
)
2240 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy chain update id='%s' %p\n", ip
->id
, p
));
2241 *q
= (char*)p
+ (p1
-p2
);
2244 for (fp
= ip
->flist
; fp
; fp
= fp
->next
)
2245 { if ((char*)fp
->ptr
>= start
&& (char*)fp
->ptr
< end
)
2246 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy list update id='%s' %p\n", ip
->id
, fp
));
2247 fp
->ptr
= (char*)fp
->ptr
+ (p1
-p2
);
2253 for (xp
= soap
->xlist
; xp
; xp
= xp
->next
)
2254 { if (xp
->ptr
&& (char*)xp
->ptr
>= start
&& (char*)xp
->ptr
< end
)
2255 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Update id='%s' %p -> %p\n", xp
->id
? xp
->id
: SOAP_STR_EOS
, xp
->ptr
, (char*)xp
->ptr
+ (p1
-p2
)));
2256 xp
->ptr
= (unsigned char**)((char*)xp
->ptr
+ (p1
-p2
));
2257 xp
->size
= (int*)((char*)xp
->size
+ (p1
-p2
));
2258 xp
->type
= (char**)((char*)xp
->type
+ (p1
-p2
));
2259 xp
->options
= (char**)((char*)xp
->options
+ (p1
-p2
));
2264 (void)soap
; (void)start
; (void)end
; (void)p1
; (void)p2
;
2269 /******************************************************************************/
2270 #ifndef WITH_NOIDREF
2273 soap_has_copies(struct soap
*soap
, register const char *start
, register const char *end
)
2275 register struct soap_ilist
*ip
= NULL
;
2276 register struct soap_flist
*fp
= NULL
;
2277 register const char *p
;
2278 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2279 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2280 { for (p
= (const char*)ip
->copy
; p
; p
= *(const char**)p
)
2281 if (p
>= start
&& p
< end
)
2283 for (fp
= ip
->flist
; fp
; fp
= fp
->next
)
2284 if ((const char*)fp
->ptr
>= start
&& (const char*)fp
->ptr
< end
)
2293 /******************************************************************************/
2294 #ifndef WITH_NOIDREF
2299 soap_resolve(struct soap
*soap
)
2301 register struct soap_ilist
*ip
= NULL
;
2302 register struct soap_flist
*fp
= NULL
;
2304 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving forwarded data\n"));
2305 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2306 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2308 { register void *p
, **q
, *r
;
2309 q
= (void**)ip
->link
;
2312 DBGLOG(TEST
, if (q
) SOAP_MESSAGE(fdebug
, "Traversing link chain to resolve id='%s'\n", ip
->id
));
2316 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "... link %p -> %p\n", q
, r
));
2320 else if (*ip
->id
== '#')
2321 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Missing data for id='%s'\n", ip
->id
));
2322 strcpy(soap
->id
, ip
->id
+ 1);
2323 return soap
->error
= SOAP_MISSING_ID
;
2329 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolution phase\n"));
2330 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2331 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2332 { if (ip
->ptr
&& !soap_has_copies(soap
, (const char*)ip
->ptr
, (const char*)ip
->ptr
+ ip
->size
))
2334 { register void *p
, **q
= (void**)ip
->copy
;
2335 DBGLOG(TEST
, if (q
) SOAP_MESSAGE(fdebug
, "Traversing copy chain to resolve id='%s'\n", ip
->id
));
2338 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "... copy %p -> %p (%u bytes)\n", ip
->ptr
, q
, (unsigned int)ip
->size
));
2340 memcpy(q
, ip
->ptr
, ip
->size
);
2345 for (fp
= ip
->flist
; fp
; fp
= ip
->flist
)
2346 { register unsigned int k
= fp
->level
;
2347 register void *p
= ip
->ptr
;
2348 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip
->type
, p
, ip
->level
, fp
->level
, ip
->id
));
2349 while (ip
->level
< k
)
2350 { register void **q
= (void**)soap_malloc(soap
, sizeof(void*));
2354 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level, new location=%p holds=%p...\n", q
, *q
));
2359 fp
->fcopy(soap
, ip
->type
, fp
->type
, fp
->ptr
, fp
->len
, p
, ip
->size
);
2361 soap_fcopy(soap
, ip
->type
, fp
->type
, fp
->ptr
, fp
->len
, p
, ip
->size
);
2362 ip
->flist
= fp
->next
;
2363 SOAP_FREE(soap
, fp
);
2371 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2372 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2373 { if (ip
->copy
|| ip
->flist
)
2374 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip
->id
));
2379 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolution done\n"));
2385 /******************************************************************************/
2390 soap_size_block(struct soap
*soap
, struct soap_blist
*b
, size_t n
)
2394 { b
->size
-= *(size_t*)(b
->ptr
+ sizeof(char*)) - n
;
2395 *(size_t*)(b
->ptr
+ sizeof(char*)) = n
;
2401 /******************************************************************************/
2406 soap_first_block(struct soap
*soap
, struct soap_blist
*b
)
2413 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "First block\n"));
2422 return r
+ sizeof(char*) + sizeof(size_t);
2426 /******************************************************************************/
2431 soap_next_block(struct soap
*soap
, struct soap_blist
*b
)
2437 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Next block\n"));
2438 b
->ptr
= *(char**)p
;
2441 return b
->ptr
+ sizeof(char*) + sizeof(size_t);
2447 /******************************************************************************/
2452 soap_block_size(struct soap
*soap
, struct soap_blist
*b
)
2455 return *(size_t*)(b
->ptr
+ sizeof(char*));
2459 /******************************************************************************/
2464 soap_end_block(struct soap
*soap
, struct soap_blist
*b
)
2469 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of block sequence, free all remaining blocks\n"));
2470 for (p
= b
->ptr
; p
; p
= q
)
2474 if (soap
->blist
== b
)
2475 soap
->blist
= b
->next
;
2477 { struct soap_blist
*bp
;
2478 for (bp
= soap
->blist
; bp
; bp
= bp
->next
)
2479 { if (bp
->next
== b
)
2480 { bp
->next
= b
->next
;
2487 DBGLOG(TEST
, if (soap
->blist
) SOAP_MESSAGE(fdebug
, "Restore previous block sequence\n"));
2491 /******************************************************************************/
2496 soap_save_block(struct soap
*soap
, struct soap_blist
*b
, char *p
, int flag
)
2497 { register size_t n
;
2498 register char *q
, *s
;
2503 p
= (char*)soap_malloc(soap
, b
->size
);
2504 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)b
->size
, b
->ptr
, p
));
2506 { for (s
= p
, q
= soap_first_block(soap
, b
); q
; q
= soap_next_block(soap
, b
))
2507 { n
= soap_block_size(soap
, b
);
2508 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy %u bytes from %p to %p\n", (unsigned int)n
, q
, s
));
2509 #ifndef WITH_NOIDREF
2511 soap_update_pointers(soap
, q
, q
+ n
, s
, q
);
2518 soap
->error
= SOAP_EOM
;
2520 soap_end_block(soap
, b
);
2525 /******************************************************************************/
2530 soap_putsize(struct soap
*soap
, const char *type
, int size
)
2531 { return soap_putsizes(soap
, type
, &size
, 1);
2535 /******************************************************************************/
2540 soap_putsizes(struct soap
*soap
, const char *type
, const int *size
, int dim
)
2541 { return soap_putsizesoffsets(soap
, type
, size
, NULL
, dim
);
2545 /******************************************************************************/
2550 soap_putsizesoffsets(struct soap
*soap
, const char *type
, const int *size
, const int *offset
, int dim
)
2553 if (!type
|| strlen(type
) + 13 > sizeof(soap
->type
)) /* prevent overruns */
2555 if (soap
->version
== 2)
2557 #ifdef HAVE_SNPRINTF
2558 soap_snprintf(soap
->type
, sizeof(soap
->type
) - 1, "%s[%d", type
, size
[0]);
2560 sprintf(soap
->type
, "%s[%d", type
, size
[0]);
2562 for (i
= 1; i
< dim
; i
++)
2564 #ifdef HAVE_SNPRINTF
2565 l
= strlen(soap
->type
);
2566 soap_snprintf(soap
->type
+ l
, sizeof(soap
->type
) - l
- 1, " %d", size
[i
]);
2568 if ((l
= strlen(soap
->type
)) + 13 > sizeof(soap
->type
))
2570 sprintf(soap
->type
+ l
, " %d", size
[i
]);
2577 #ifdef HAVE_SNPRINTF
2578 soap_snprintf(soap
->type
, sizeof(soap
->type
) - 1, "%s[%d", type
, size
[0] + offset
[0]);
2580 sprintf(soap
->type
, "%s[%d", type
, size
[0] + offset
[0]);
2582 for (i
= 1; i
< dim
; i
++)
2584 #ifdef HAVE_SNPRINTF
2585 l
= strlen(soap
->type
);
2586 soap_snprintf(soap
->type
+ l
, sizeof(soap
->type
) - l
- 1, ",%d", size
[i
] + offset
[i
]);
2588 if ((l
= strlen(soap
->type
)) + 13 > sizeof(soap
->type
))
2590 sprintf(soap
->type
+ l
, ",%d", size
[i
] + offset
[i
]);
2596 #ifdef HAVE_SNPRINTF
2597 soap_snprintf(soap
->type
, sizeof(soap
->type
) - 1, "%s[%d", type
, size
[0]);
2599 sprintf(soap
->type
, "%s[%d", type
, size
[0]);
2601 for (i
= 1; i
< dim
; i
++)
2603 #ifdef HAVE_SNPRINTF
2604 l
= strlen(soap
->type
);
2605 soap_snprintf(soap
->type
+ l
, sizeof(soap
->type
) - l
- 1, ",%d", size
[i
]);
2607 if ((l
= strlen(soap
->type
)) + 13 > sizeof(soap
->type
))
2609 sprintf(soap
->type
+ l
, ",%d", size
[i
]);
2614 strcat(soap
->type
, "]");
2619 /******************************************************************************/
2624 soap_putoffset(struct soap
*soap
, int offset
)
2625 { return soap_putoffsets(soap
, &offset
, 1);
2629 /******************************************************************************/
2634 soap_putoffsets(struct soap
*soap
, const int *offset
, int dim
)
2637 #ifdef HAVE_SNPRINTF
2638 soap_snprintf(soap
->arrayOffset
, sizeof(soap
->arrayOffset
) - 1, "[%d", offset
[0]);
2640 if (sizeof(soap
->arrayOffset
) < 13) /* prevent overruns */
2642 sprintf(soap
->arrayOffset
, "[%d", offset
[0]);
2644 for (i
= 1; i
< dim
; i
++)
2646 #ifdef HAVE_SNPRINTF
2647 l
= strlen(soap
->arrayOffset
);
2648 soap_snprintf(soap
->arrayOffset
+ l
, sizeof(soap
->arrayOffset
) - l
- 1, ",%d", offset
[i
]);
2650 if ((l
= strlen(soap
->arrayOffset
)) + 13 > sizeof(soap
->arrayOffset
))
2652 sprintf(soap
->arrayOffset
+ l
, ",%d", offset
[i
]);
2655 strcat(soap
->arrayOffset
, "]");
2656 return soap
->arrayOffset
;
2660 /******************************************************************************/
2665 soap_size(const int *size
, int dim
)
2666 { register int i
, n
= size
[0];
2667 for (i
= 1; i
< dim
; i
++)
2673 /******************************************************************************/
2678 soap_getoffsets(const char *attr
, const int *size
, int *offset
, int dim
)
2679 { register int i
, j
= 0;
2681 for (i
= 0; i
< dim
&& attr
&& *attr
; i
++)
2684 j
+= offset
[i
] = (int)soap_strtol(attr
, NULL
, 10);
2685 attr
= strchr(attr
, ',');
2688 for (i
= 0; i
< dim
&& attr
&& *attr
; i
++)
2691 j
+= (int)soap_strtol(attr
, NULL
, 10);
2692 attr
= strchr(attr
, ',');
2698 /******************************************************************************/
2703 soap_getsize(const char *attr1
, const char *attr2
, int *j
)
2704 { register int n
, k
;
2713 { k
= (int)soap_strtol(attr1
, &s
, 10);
2715 if (k
< 0 || n
> SOAP_MAXARRAYSIZE
|| s
== attr1
)
2717 attr1
= strchr(s
, ',');
2719 attr1
= strchr(s
, ' ');
2720 if (attr2
&& *attr2
)
2723 k
= (int)soap_strtol(attr2
, &s
, 10);
2737 /******************************************************************************/
2742 soap_getsizes(const char *attr
, int *size
, int dim
)
2743 { register int i
, k
, n
;
2746 i
= (int)strlen(attr
);
2749 { for (i
= i
-1; i
>= 0; i
--)
2750 if (attr
[i
] == '[' || attr
[i
] == ',' || attr
[i
] == ' ')
2752 k
= (int)soap_strtol(attr
+ i
+ 1, NULL
, 10);
2753 n
*= size
[--dim
] = k
;
2754 if (k
< 0 || n
> SOAP_MAXARRAYSIZE
)
2756 } while (i
>= 0 && attr
[i
] != '[');
2761 /******************************************************************************/
2766 soap_getposition(const char *attr
, int *pos
)
2767 { register int i
, n
;
2773 { pos
[n
++] = (int)soap_strtol(attr
+ i
, NULL
, 10);
2774 while (attr
[i
] && attr
[i
] != ',' && attr
[i
] != ']')
2778 } while (n
< SOAP_MAXDIMS
&& attr
[i
] && attr
[i
] != ']');
2783 /******************************************************************************/
2788 soap_push_namespace(struct soap
*soap
, const char *id
, const char *ns
)
2789 { register struct soap_nlist
*np
;
2790 register struct Namespace
*p
;
2791 register short i
= -1;
2792 register size_t n
, k
;
2795 p
= soap
->local_namespaces
;
2797 { for (i
= 0; p
->id
; p
++, i
++)
2798 { if (p
->ns
&& !strcmp(ns
, p
->ns
))
2801 { if (!strcmp(ns
, p
->out
))
2805 { if (!soap_tag_cmp(ns
, p
->in
))
2806 { if ((p
->out
= (char*)SOAP_MALLOC(soap
, k
)))
2817 np
= (struct soap_nlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_nlist
) + n
+ k
);
2819 { soap
->error
= SOAP_EOM
;
2822 np
->next
= soap
->nlist
;
2824 np
->level
= soap
->level
;
2826 strcpy((char*)np
->id
, id
);
2827 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push namespace binding (level=%u) '%s' '%s'\n", soap
->level
, id
, ns
));
2829 { np
->ns
= strcpy((char*)np
->id
+ n
+ 1, ns
);
2830 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns
));
2834 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push OK ('%s' matches '%s' in namespace table)\n", id
, p
->id
));
2840 /******************************************************************************/
2845 soap_pop_namespace(struct soap
*soap
)
2846 { register struct soap_nlist
*np
, *nq
;
2847 for (np
= soap
->nlist
; np
&& np
->level
>= soap
->level
; np
= nq
)
2849 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Pop namespace binding (level=%u) '%s'\n", soap
->level
, np
->id
));
2850 SOAP_FREE(soap
, np
);
2856 /******************************************************************************/
2861 soap_match_namespace(struct soap
*soap
, const char *id1
, const char *id2
, size_t n1
, size_t n2
)
2862 { register struct soap_nlist
*np
= soap
->nlist
;
2864 while (np
&& (strncmp(np
->id
, id1
, n1
) || np
->id
[n1
]))
2867 { if (!(soap
->mode
& SOAP_XML_IGNORENS
))
2869 || ((s
= soap
->local_namespaces
[np
->index
].id
) && (strncmp(s
, id2
, n2
) || (s
[n2
] && s
[n2
] != '_'))))
2870 return SOAP_NAMESPACE
;
2874 return (soap
->mode
& SOAP_XML_IGNORENS
) ? SOAP_OK
: SOAP_NAMESPACE
;
2875 if ((n1
== 3 && n1
== n2
&& !strncmp(id1
, "xml", 3) && !strncmp(id1
, id2
, 3))
2876 || (soap
->mode
& SOAP_XML_IGNORENS
))
2878 return soap
->error
= SOAP_SYNTAX_ERROR
;
2882 /******************************************************************************/
2887 soap_current_namespace(struct soap
*soap
, const char *tag
)
2888 { register struct soap_nlist
*np
;
2889 register const char *s
;
2890 if (!tag
|| !strncmp(tag
, "xml", 3))
2893 if (!(s
= strchr(tag
, ':')))
2894 { while (np
&& *np
->id
) /* find default namespace, if present */
2898 { while (np
&& (strncmp(np
->id
, tag
, s
- tag
) || np
->id
[s
- tag
]))
2901 soap
->error
= SOAP_NAMESPACE
;
2904 { if (np
->index
>= 0)
2905 return soap
->namespaces
[np
->index
].ns
;
2907 return soap_strdup(soap
, np
->ns
);
2913 /******************************************************************************/
2918 soap_tag_cmp(const char *s
, const char *t
)
2920 { register int c1
= *s
;
2921 register int c2
= *t
;
2922 if (!c1
|| c1
== '"')
2926 { if (c1
>= 'A' && c1
<= 'Z')
2928 if (c2
>= 'A' && c2
<= 'Z')
2937 if (c2
>= 'A' && c2
<= 'Z')
2941 if (!c1
|| c1
== '"')
2943 if (c1
>= 'A' && c1
<= 'Z')
2945 if (c1
== c2
&& !soap_tag_cmp(s
+ 1, t
+ 1))
2955 if (*t
== '*' && !t
[1])
2961 /******************************************************************************/
2966 soap_match_tag(struct soap
*soap
, const char *tag1
, const char *tag2
)
2967 { register const char *s
, *t
;
2969 if (!tag1
|| !tag2
|| !*tag2
)
2971 s
= strchr(tag1
, ':');
2972 t
= strchr(tag2
, ':');
2975 { if (t
[1] && SOAP_STRCMP(s
+ 1, t
+ 1))
2976 return SOAP_TAG_MISMATCH
;
2977 if (t
!= tag2
&& (err
= soap_match_namespace(soap
, tag1
, tag2
, s
- tag1
, t
- tag2
)))
2978 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags '%s' and '%s' match but namespaces differ\n", tag1
, tag2
));
2979 if (err
== SOAP_NAMESPACE
)
2980 return SOAP_TAG_MISMATCH
;
2985 { err
= soap_match_namespace(soap
, tag1
, tag2
, 0, t
- tag2
);
2986 if (err
== SOAP_NAMESPACE
)
2987 return SOAP_TAG_MISMATCH
;
2989 else if (SOAP_STRCMP(tag1
, t
+ 1))
2990 { return SOAP_TAG_MISMATCH
;
2992 else if (t
!= tag2
&& (err
= soap_match_namespace(soap
, tag1
, tag2
, 0, t
- tag2
)))
2993 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags '%s' and '%s' match but namespaces differ\n", tag1
, tag2
));
2994 if (err
== SOAP_NAMESPACE
)
2995 return SOAP_TAG_MISMATCH
;
2998 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags and (default) namespaces match: '%s' '%s'\n", tag1
, tag2
));
3002 { if (SOAP_STRCMP(s
+ 1, tag2
))
3003 return SOAP_TAG_MISMATCH
;
3005 else if (SOAP_STRCMP(tag1
, tag2
))
3006 return SOAP_TAG_MISMATCH
;
3007 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags match: '%s' '%s'\n", tag1
, tag2
));
3012 /******************************************************************************/
3017 soap_match_array(struct soap
*soap
, const char *type
)
3018 { if (*soap
->arrayType
)
3019 if (soap_match_tag(soap
, soap
->arrayType
, type
)
3020 && soap_match_tag(soap
, soap
->arrayType
, "xsd:anyType")
3021 && soap_match_tag(soap
, soap
->arrayType
, "xsd:ur-type")
3023 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array type mismatch: '%s' '%s'\n", soap
->arrayType
, type
));
3024 return SOAP_TAG_MISMATCH
;
3030 /******************************************************************************\
3034 \******************************************************************************/
3036 /******************************************************************************/
3043 { unsigned char buf
[4];
3044 if (!soap_ssl_init_done
)
3046 RAND_pseudo_bytes(buf
, 4);
3052 /******************************************************************************/
3053 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3058 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3059 soap_ssl_server_context(struct soap
*soap
, unsigned short flags
, const char *keyfile
, const char *keyid
, const char *password
, const char *cafile
, const char *capath
, const char *dhfile
, const char *randfile
, const char *sid
)
3061 soap_ssl_server_context(struct soap
*soap
, unsigned short flags
, const char *keyfile
, const char *password
, const char *cafile
, const char *capath
, const char *dhfile
, const char *randfile
, const char *sid
)
3064 soap
->keyfile
= keyfile
;
3065 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3066 soap
->keyid
= keyid
;
3068 soap
->password
= password
;
3069 soap
->cafile
= cafile
;
3070 soap
->capath
= capath
;
3071 soap
->crlfile
= NULL
;
3073 soap
->dhfile
= dhfile
;
3074 soap
->randfile
= randfile
;
3076 soap
->ssl_flags
= flags
| (dhfile
== NULL
? SOAP_SSL_RSA
: 0);
3080 int n
= (int)soap_strtoul(dhfile
, &s
, 10);
3081 if (!soap
->dh_params
)
3082 gnutls_dh_params_init(&soap
->dh_params
);
3083 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3084 if (n
>= 512 && s
&& *s
== '\0')
3085 gnutls_dh_params_generate2(soap
->dh_params
, (unsigned int)n
);
3087 { unsigned int dparams_len
;
3088 unsigned char dparams_buf
[1024];
3089 FILE *fd
= fopen(dhfile
, "r");
3091 return soap_set_receiver_error(soap
, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR
);
3092 dparams_len
= (unsigned int)fread(dparams_buf
, 1, sizeof(dparams_buf
), fd
);
3094 gnutls_datum_t dparams
= { dparams_buf
, dparams_len
};
3095 if (gnutls_dh_params_import_pkcs3(soap
->dh_params
, &dparams
, GNUTLS_X509_FMT_PEM
))
3096 return soap_set_receiver_error(soap
, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR
);
3100 { if (!soap
->rsa_params
)
3101 gnutls_rsa_params_init(&soap
->rsa_params
);
3102 gnutls_rsa_params_generate2(soap
->rsa_params
, SOAP_SSL_RSA_BITS
);
3105 { gnutls_deinit(soap
->session
);
3106 soap
->session
= NULL
;
3109 { gnutls_certificate_free_credentials(soap
->xcred
);
3113 err
= soap
->fsslauth(soap
);
3117 SSL_CTX_set_session_id_context(soap
->ctx
, (unsigned char*)sid
, (unsigned int)strlen(sid
));
3119 SSL_CTX_set_session_cache_mode(soap
->ctx
, SSL_SESS_CACHE_OFF
);
3127 /******************************************************************************/
3128 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3133 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3134 soap_ssl_client_context(struct soap
*soap
, unsigned short flags
, const char *keyfile
, const char *keyid
, const char *password
, const char *cafile
, const char *capath
, const char *randfile
)
3136 soap_ssl_client_context(struct soap
*soap
, unsigned short flags
, const char *keyfile
, const char *password
, const char *cafile
, const char *capath
, const char *randfile
)
3138 { soap
->keyfile
= keyfile
;
3139 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3140 soap
->keyid
= keyid
;
3142 soap
->password
= password
;
3143 soap
->cafile
= cafile
;
3144 soap
->capath
= capath
;
3145 soap
->ssl_flags
= SOAP_SSL_CLIENT
| flags
;
3147 soap
->dhfile
= NULL
;
3148 soap
->randfile
= randfile
;
3149 soap
->fsslverify
= (flags
& SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
) == 0 ? ssl_verify_callback
: ssl_verify_callback_allow_expired_certificate
;
3153 { gnutls_deinit(soap
->session
);
3154 soap
->session
= NULL
;
3157 { gnutls_certificate_free_credentials(soap
->xcred
);
3161 return soap
->fsslauth(soap
);
3166 /******************************************************************************/
3167 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3173 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
3174 if (!soap_ssl_init_done
)
3175 { soap_ssl_init_done
= 1;
3178 OpenSSL_add_all_algorithms(); /* 2.8.1 change (wsseapi.c) */
3179 OpenSSL_add_all_digests();
3181 SSL_load_error_strings();
3183 if (!RAND_load_file("/dev/urandom", 1024))
3185 RAND_seed(buf
, sizeof(buf
));
3186 while (!RAND_status())
3188 RAND_seed(&r
, sizeof(int));
3193 # if defined(HAVE_PTHREAD_H)
3194 gcry_control(GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pthread
);
3195 # elif defined(HAVE_PTH_H)
3196 gcry_control(GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pth
);
3198 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM
, 0);
3199 gcry_control(GCRYCTL_DISABLE_SECMEM
, 0);
3200 gcry_control(GCRYCTL_INITIALIZATION_FINISHED
, 0); /* libgcrypt init done */
3201 gnutls_global_init();
3208 /******************************************************************************/
3209 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3214 soap_ssl_error(struct soap
*soap
, int ret
)
3217 int err
= SSL_get_error(soap
->ssl
, ret
);
3218 const char *msg
= soap_code_str(h_ssl_error_codes
, err
);
3220 strcpy(soap
->msgbuf
, msg
);
3222 return ERR_error_string(err
, soap
->msgbuf
);
3223 if (ERR_peek_error())
3225 strcat(soap
->msgbuf
, "\n");
3226 while ((r
= ERR_get_error()))
3227 ERR_error_string_n(r
, soap
->msgbuf
+ strlen(soap
->msgbuf
), sizeof(soap
->msgbuf
) - strlen(soap
->msgbuf
));
3232 strcpy(soap
->msgbuf
, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information.");
3235 #ifdef HAVE_SNPRINTF
3236 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "Error observed by underlying SSL/TLS BIO: %s", strerror(errno
));
3238 { const char *s
= strerror(errno
);
3239 size_t l
= strlen(s
);
3240 sprintf(soap
->msgbuf
, "Error observed by underlying SSL/TLS BIO: %s", l
+ 44 < sizeof(soap
->msgbuf
) ? s
: SOAP_STR_EOS
);
3246 return soap
->msgbuf
;
3249 return gnutls_strerror(ret
);
3255 /******************************************************************************/
3256 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3259 ssl_auth_init(struct soap
*soap
)
3264 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3267 if (!soap_ssl_init_done
)
3271 { if (!(soap
->ctx
= SSL_CTX_new(SSLv23_method())))
3272 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR
);
3273 /* The following alters the behavior of SSL read/write: */
3275 SSL_CTX_set_mode(soap
->ctx
, SSL_MODE_ENABLE_PARTIAL_WRITE
| SSL_MODE_AUTO_RETRY
);
3279 { if (!RAND_load_file(soap
->randfile
, -1))
3280 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR
);
3282 if (soap
->cafile
|| soap
->capath
)
3283 { if (!SSL_CTX_load_verify_locations(soap
->ctx
, soap
->cafile
, soap
->capath
))
3284 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR
);
3285 if (soap
->cafile
&& (soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3286 SSL_CTX_set_client_CA_list(soap
->ctx
, SSL_load_client_CA_file(soap
->cafile
));
3288 if (!(soap
->ssl_flags
& SOAP_SSL_NO_DEFAULT_CA_PATH
))
3289 { if (!SSL_CTX_set_default_verify_paths(soap
->ctx
))
3290 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR
);
3292 /* This code assumes a typical scenario, see alternative code below */
3294 { if (!SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->keyfile
))
3295 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR
);
3297 { SSL_CTX_set_default_passwd_cb_userdata(soap
->ctx
, (void*)soap
->password
);
3298 SSL_CTX_set_default_passwd_cb(soap
->ctx
, ssl_password
);
3300 if (!SSL_CTX_use_PrivateKey_file(soap
->ctx
, soap
->keyfile
, SSL_FILETYPE_PEM
))
3301 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR
);
3302 #ifndef WM_SECURE_KEY_STORAGE
3303 if (!SSL_CTX_use_PrivateKey_file(soap
->ctx
, soap
->keyfile
, SSL_FILETYPE_PEM
))
3304 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR
);
3307 #if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
3308 if (NULL
== (pkey
= ipcom_key_db_pkey_get(soap
->keyid
)))
3309 return soap_set_receiver_error(soap
, "SSL error", "Can't find key", SOAP_SSL_ERROR
);
3310 if (0 == SSL_CTX_use_PrivateKey(soap
->ctx
, pkey
))
3311 return soap_set_receiver_error(soap
, "SSL error", "Can't read key", SOAP_SSL_ERROR
);
3313 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
3316 { SSL_CTX_set_default_passwd_cb_userdata(soap
->ctx
, (void*)soap
->password
);
3317 SSL_CTX_set_default_passwd_cb(soap
->ctx
, ssl_password
);
3319 if (!soap
->cafile
|| !SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->cafile
))
3320 { if (soap
->keyfile
)
3321 { if (!SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->keyfile
))
3322 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR
);
3323 if (!SSL_CTX_use_PrivateKey_file(soap
->ctx
, soap
->keyfile
, SSL_FILETYPE_PEM
))
3324 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR
);
3328 if ((soap
->ssl_flags
& SOAP_SSL_RSA
))
3329 { RSA
*rsa
= RSA_generate_key(SOAP_SSL_RSA_BITS
, RSA_F4
, NULL
, NULL
);
3330 if (!SSL_CTX_set_tmp_rsa(soap
->ctx
, rsa
))
3333 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR
);
3337 else if (soap
->dhfile
)
3340 int n
= (int)soap_strtoul(soap
->dhfile
, &s
, 10);
3341 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3342 if (n
>= 512 && s
&& *s
== '\0')
3343 #if defined(VXWORKS)
3344 DH_generate_parameters_ex(dh
, n
, 2/*or 5*/, NULL
);
3346 dh
= DH_generate_parameters(n
, 2/*or 5*/, NULL
, NULL
);
3350 bio
= BIO_new_file(soap
->dhfile
, "r");
3352 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR
);
3353 dh
= PEM_read_bio_DHparams(bio
, NULL
, NULL
, NULL
);
3356 if (!dh
|| DH_check(dh
, &n
) != 1 || SSL_CTX_set_tmp_dh(soap
->ctx
, dh
) < 0)
3359 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR
);
3363 flags
= (SSL_OP_ALL
| SSL_OP_NO_SSLv2
); /* disable SSL v2 */
3364 if ((soap
->ssl_flags
& SOAP_SSLv3
))
3365 flags
|= SSL_OP_NO_TLSv1
;
3366 if ((soap
->ssl_flags
& SOAP_TLSv1
))
3367 flags
|= SSL_OP_NO_SSLv3
;
3368 #ifdef SSL_OP_NO_TICKET
3369 /* TLS extension is enabled by default in OPENSSL v0.9.8k
3370 Disable it by adding SSL_OP_NO_TICKET */
3371 flags
|= SSL_OP_NO_TICKET
;
3373 SSL_CTX_set_options(soap
->ctx
, flags
);
3374 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3375 mode
= (SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
);
3376 else if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
3377 mode
= SSL_VERIFY_PEER
;
3379 mode
= SSL_VERIFY_NONE
;
3380 SSL_CTX_set_verify(soap
->ctx
, mode
, soap
->fsslverify
);
3381 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
3382 SSL_CTX_set_verify_depth(soap
->ctx
, 1);
3384 SSL_CTX_set_verify_depth(soap
->ctx
, 9);
3389 if (!soap_ssl_init_done
)
3392 { gnutls_certificate_allocate_credentials(&soap
->xcred
);
3394 { if (gnutls_certificate_set_x509_trust_file(soap
->xcred
, soap
->cafile
, GNUTLS_X509_FMT_PEM
) < 0)
3395 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR
);
3398 { if (gnutls_certificate_set_x509_crl_file(soap
->xcred
, soap
->crlfile
, GNUTLS_X509_FMT_PEM
) < 0)
3399 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR
);
3402 { if (gnutls_certificate_set_x509_key_file(soap
->xcred
, soap
->keyfile
, soap
->keyfile
, GNUTLS_X509_FMT_PEM
) < 0) /* TODO: GNUTLS need to concat cert and key in single key file */
3403 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR
);
3406 if ((soap
->ssl_flags
& SOAP_SSL_CLIENT
))
3407 { gnutls_init(&soap
->session
, GNUTLS_CLIENT
);
3408 if (soap
->cafile
|| soap
->crlfile
|| soap
->keyfile
)
3409 { ret
= gnutls_priority_set_direct(soap
->session
, "PERFORMANCE", NULL
);
3411 return soap_set_receiver_error(soap
, soap_ssl_error(soap
, ret
), "SSL/TLS set priority error", SOAP_SSL_ERROR
);
3412 gnutls_credentials_set(soap
->session
, GNUTLS_CRD_CERTIFICATE
, soap
->xcred
);
3416 gnutls_anon_allocate_client_credentials(&soap
->acred
);
3417 gnutls_init(&soap
->session
, GNUTLS_CLIENT
);
3418 gnutls_priority_set_direct(soap
->session
, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL
);
3419 gnutls_credentials_set(soap
->session
, GNUTLS_CRD_ANON
, soap
->acred
);
3423 { if (!soap
->keyfile
)
3424 return soap_set_receiver_error(soap
, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR
);
3425 if ((soap
->ssl_flags
& SOAP_SSL_RSA
) && soap
->rsa_params
)
3426 gnutls_certificate_set_rsa_export_params(soap
->xcred
, soap
->rsa_params
);
3427 else if (soap
->dh_params
)
3428 gnutls_certificate_set_dh_params(soap
->xcred
, soap
->dh_params
);
3430 gnutls_priority_init(&soap
->cache
, "NORMAL", NULL
);
3431 gnutls_init(&soap
->session
, GNUTLS_SERVER
);
3432 gnutls_priority_set(soap
->session
, soap
->cache
);
3433 gnutls_credentials_set(soap
->session
, GNUTLS_CRD_CERTIFICATE
, soap
->xcred
);
3434 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3435 gnutls_certificate_server_set_request(soap
->session
, GNUTLS_CERT_REQUEST
);
3436 gnutls_session_enable_compatibility_mode(soap
->session
);
3437 if ((soap
->ssl_flags
& SOAP_TLSv1
))
3438 { int protocol_priority
[] = { GNUTLS_TLS1_0
, 0 };
3439 if (gnutls_protocol_set_priority(soap
->session
, protocol_priority
) != GNUTLS_E_SUCCESS
)
3440 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR
);
3449 /******************************************************************************/
3453 ssl_password(char *buf
, int num
, int rwflag
, void *userdata
)
3454 { if (num
< (int)strlen((char*)userdata
) + 1)
3456 return (int)strlen(strcpy(buf
, (char*)userdata
));
3461 /******************************************************************************/
3465 ssl_verify_callback(int ok
, X509_STORE_CTX
*store
)
3470 int err
= X509_STORE_CTX_get_error(store
);
3471 X509
*cert
= X509_STORE_CTX_get_current_cert(store
);
3472 fprintf(stderr
, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store
), X509_verify_cert_error_string(err
));
3473 X509_NAME_oneline(X509_get_issuer_name(cert
), buf
, sizeof(buf
));
3474 fprintf(stderr
, "certificate issuer %s\n", buf
);
3475 X509_NAME_oneline(X509_get_subject_name(cert
), buf
, sizeof(buf
));
3476 fprintf(stderr
, "certificate subject %s\n", buf
);
3477 /* accept self signed certificates and certificates out of date */
3479 { case X509_V_ERR_CERT_NOT_YET_VALID
:
3480 case X509_V_ERR_CERT_HAS_EXPIRED
:
3481 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
:
3482 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
3483 X509_STORE_CTX_set_error(store
, X509_V_OK
);
3488 /* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */
3494 /******************************************************************************/
3498 ssl_verify_callback_allow_expired_certificate(int ok
, X509_STORE_CTX
*store
)
3499 { ok
= ssl_verify_callback(ok
, store
);
3501 { /* accept self signed certificates and certificates out of date */
3502 switch (X509_STORE_CTX_get_error(store
))
3503 { case X509_V_ERR_CERT_NOT_YET_VALID
:
3504 case X509_V_ERR_CERT_HAS_EXPIRED
:
3505 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
:
3506 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
:
3507 X509_STORE_CTX_set_error(store
, X509_V_OK
);
3511 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3517 /******************************************************************************/
3520 ssl_verify(struct soap
*soap
, const char *host
)
3521 { unsigned int status
;
3522 const char *err
= NULL
;
3523 int r
= gnutls_certificate_verify_peers2(soap
->session
, &status
);
3525 err
= "Certificate verify error";
3526 else if ((status
& GNUTLS_CERT_INVALID
))
3527 err
= "The certificate is not trusted";
3528 else if ((status
& GNUTLS_CERT_SIGNER_NOT_FOUND
))
3529 err
= "The certificate hasn't got a known issuer";
3530 else if ((status
& GNUTLS_CERT_REVOKED
))
3531 err
= "The certificate has been revoked";
3532 else if (gnutls_certificate_type_get(soap
->session
) == GNUTLS_CRT_X509
)
3533 { gnutls_x509_crt_t cert
;
3534 const gnutls_datum_t
*cert_list
;
3535 unsigned int cert_list_size
;
3536 if (gnutls_x509_crt_init(&cert
) < 0)
3537 err
= "Could not get X509 certificates";
3538 else if ((cert_list
= gnutls_certificate_get_peers(soap
->session
, &cert_list_size
)) == NULL
)
3539 err
= "Could not get X509 certificates";
3540 else if (gnutls_x509_crt_import(cert
, &cert_list
[0], GNUTLS_X509_FMT_DER
) < 0)
3541 err
= "Error parsing X509 certificate";
3542 else if (!(soap
->ssl_flags
& SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
) && gnutls_x509_crt_get_expiration_time(cert
) < time(NULL
))
3543 err
= "The certificate has expired";
3544 else if (!(soap
->ssl_flags
& SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
) && gnutls_x509_crt_get_activation_time(cert
) > time(NULL
))
3545 err
= "The certificate is not yet activated";
3546 else if (host
&& !(soap
->ssl_flags
& SOAP_SSL_SKIP_HOST_CHECK
))
3547 { if (!gnutls_x509_crt_check_hostname(cert
, host
))
3548 err
= "Certificate host name mismatch";
3550 gnutls_x509_crt_deinit(cert
);
3556 /******************************************************************************/
3557 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3563 soap_ssl_accept(struct soap
*soap
)
3564 { SOAP_SOCKET sk
= soap
->socket
;
3568 if (!soap_valid_socket(sk
))
3569 return soap_set_receiver_error(soap
, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR
);
3570 soap
->ssl_flags
&= ~SOAP_SSL_CLIENT
;
3571 if (!soap
->ctx
&& (soap
->error
= soap
->fsslauth(soap
)))
3574 { soap
->ssl
= SSL_new(soap
->ctx
);
3576 return soap_set_receiver_error(soap
, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR
);
3579 SSL_clear(soap
->ssl
);
3580 bio
= BIO_new_socket((int)sk
, BIO_NOCLOSE
);
3581 SSL_set_bio(soap
->ssl
, bio
, bio
);
3582 /* Set SSL sockets to non-blocking */
3584 if (soap
->accept_timeout
)
3585 { SOAP_SOCKNONBLOCK(sk
)
3586 retries
= 10*soap
->accept_timeout
;
3589 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
3590 while ((r
= SSL_accept(soap
->ssl
)) <= 0)
3594 err
= SSL_get_error(soap
->ssl
, r
);
3595 if (err
== SSL_ERROR_WANT_ACCEPT
|| err
== SSL_ERROR_WANT_READ
|| err
== SSL_ERROR_WANT_WRITE
)
3596 { if (err
== SSL_ERROR_WANT_READ
)
3597 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
3599 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
3604 { soap
->errnum
= soap_socket_errno(sk
);
3609 { soap_set_receiver_error(soap
, soap_ssl_error(soap
, r
), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR
);
3610 soap_closesock(soap
);
3611 return SOAP_SSL_ERROR
;
3613 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3616 if ((err
= SSL_get_verify_result(soap
->ssl
)) != X509_V_OK
)
3617 { soap_closesock(soap
);
3618 return soap_set_sender_error(soap
, X509_verify_cert_error_string(err
), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR
);
3620 peer
= SSL_get_peer_certificate(soap
->ssl
);
3622 { soap_closesock(soap
);
3623 return soap_set_sender_error(soap
, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR
);
3630 if (!soap_valid_socket(sk
))
3631 return soap_set_receiver_error(soap
, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR
);
3632 soap
->ssl_flags
&= ~SOAP_SSL_CLIENT
;
3633 if (!soap
->session
&& (soap
->error
= soap
->fsslauth(soap
)))
3634 { soap_closesock(soap
);
3637 gnutls_transport_set_ptr(soap
->session
, (gnutls_transport_ptr_t
)(long)sk
);
3638 /* Set SSL sockets to non-blocking */
3639 if (soap
->accept_timeout
)
3640 { SOAP_SOCKNONBLOCK(sk
)
3641 retries
= 10*soap
->accept_timeout
;
3644 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
3645 while ((r
= gnutls_handshake(soap
->session
)))
3647 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
3650 if (r
== GNUTLS_E_AGAIN
|| r
== GNUTLS_E_INTERRUPTED
)
3651 { if (!gnutls_record_get_direction(soap
->session
))
3652 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
3654 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
3659 { soap
->errnum
= soap_socket_errno(sk
);
3664 { soap_closesock(soap
);
3665 return soap_set_receiver_error(soap
, soap_ssl_error(soap
, r
), "SSL/TLS handshake failed", SOAP_SSL_ERROR
);
3667 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3668 { const char *err
= ssl_verify(soap
, NULL
);
3670 { soap_closesock(soap
);
3671 return soap_set_receiver_error(soap
, "SSL/TLS error", err
, SOAP_SSL_ERROR
);
3675 if (soap
->recv_timeout
|| soap
->send_timeout
)
3676 SOAP_SOCKNONBLOCK(sk
)
3679 soap
->imode
|= SOAP_ENC_SSL
;
3680 soap
->omode
|= SOAP_ENC_SSL
;
3687 /******************************************************************************\
3689 * TCP/UDP [SSL/TLS] IPv4 and IPv6
3691 \******************************************************************************/
3693 /******************************************************************************/
3697 tcp_init(struct soap
*soap
)
3698 { soap
->errmode
= 1;
3704 if (WSAStartup(MAKEWORD(1, 1), &w
))
3714 /******************************************************************************/
3718 tcp_error(struct soap
*soap
)
3719 { register const char *msg
= NULL
;
3720 switch (soap
->errmode
)
3722 msg
= soap_strerror(soap
);
3725 msg
= "WSAStartup failed";
3730 msg
= soap_code_str(h_error_codes
, soap
->errnum
);
3734 #ifdef HAVE_SNPRINTF
3735 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "TCP/UDP IP error %d", soap
->errnum
);
3737 sprintf(soap
->msgbuf
, "TCP/UDP IP error %d", soap
->errnum
);
3748 /******************************************************************************/
3753 tcp_gethost(struct soap
*soap
, const char *addr
, struct in_addr
*inaddr
)
3754 { soap_int32 iadd
= -1;
3755 struct hostent hostent
, *host
= &hostent
;
3758 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3759 iadd
= inet_addr((char*)addr
);
3761 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3762 struct hostent_data ht_data
;
3765 iadd
= inet_addr((void*)addr
);
3767 iadd
= inet_addr(addr
);
3771 { memcpy(inaddr
, &iadd
, sizeof(iadd
));
3774 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) || defined(__ANDROID__)
3775 if (gethostbyname_r(addr
, &hostent
, soap
->buf
, SOAP_BUFLEN
, &host
, &soap
->errnum
) < 0)
3777 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3778 memset((void*)&ht_data
, 0, sizeof(ht_data
));
3779 if (gethostbyname_r(addr
, &hostent
, &ht_data
) < 0)
3781 soap
->errnum
= h_errno
;
3783 #elif defined(HAVE_GETHOSTBYNAME_R)
3784 host
= gethostbyname_r(addr
, &hostent
, soap
->buf
, SOAP_BUFLEN
, &soap
->errnum
);
3785 #elif defined(VXWORKS)
3786 /* If the DNS resolver library resolvLib has been configured in the vxWorks
3787 * image, a query for the host IP address is sent to the DNS server, if the
3788 * name was not found in the local host table. */
3789 hostint
= hostGetByName((char*)addr
);
3790 if (hostint
== ERROR
)
3792 soap
->errnum
= soap_errno
;
3796 if (!(host
= gethostbyname((void*)addr
)))
3797 soap
->errnum
= h_errno
;
3799 if (!(host
= gethostbyname(addr
)))
3800 soap
->errnum
= h_errno
;
3804 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Host name not found\n"));
3808 inaddr
->s_addr
= hostint
;
3810 memcpy(inaddr
, host
->h_addr
, host
->h_length
);
3818 /******************************************************************************/
3822 tcp_connect(struct soap
*soap
, const char *endpoint
, const char *host
, int port
)
3825 struct addrinfo hints
, *res
, *ressave
;
3831 int len
= SOAP_BUFLEN
;
3833 int len
= SOAP_BUFLEN
+ 1; /* speeds up windows xfer */
3837 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3840 if (soap_valid_socket(soap
->socket
))
3841 soap
->fclosesocket(soap
, soap
->socket
);
3842 soap
->socket
= SOAP_INVALID_SOCKET
;
3845 soap_set_sender_error(soap
, tcp_error(soap
), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR
);
3846 return SOAP_INVALID_SOCKET
;
3850 memset((void*)&hints
, 0, sizeof(hints
));
3851 hints
.ai_family
= PF_UNSPEC
;
3853 if ((soap
->omode
& SOAP_IO_UDP
))
3854 hints
.ai_socktype
= SOCK_DGRAM
;
3857 hints
.ai_socktype
= SOCK_STREAM
;
3859 if (soap
->proxy_host
)
3860 err
= getaddrinfo(soap
->proxy_host
, soap_int2s(soap
, soap
->proxy_port
), &hints
, &res
);
3862 err
= getaddrinfo(host
, soap_int2s(soap
, port
), &hints
, &res
);
3864 { soap_set_sender_error(soap
, SOAP_GAI_STRERROR(err
), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR
);
3865 return SOAP_INVALID_SOCKET
;
3869 sk
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
3876 if ((soap
->omode
& SOAP_IO_UDP
))
3877 sk
= socket(AF_INET
, SOCK_DGRAM
, 0);
3880 sk
= socket(AF_INET
, SOCK_STREAM
, 0);
3882 if (!soap_valid_socket(sk
))
3886 { res
= res
->ai_next
;
3890 soap
->errnum
= soap_socket_errno(sk
);
3891 soap_set_sender_error(soap
, tcp_error(soap
), "socket failed in tcp_connect()", SOAP_TCP_ERROR
);
3893 freeaddrinfo(ressave
);
3895 return SOAP_INVALID_SOCKET
;
3897 #ifdef SOCKET_CLOSE_ON_EXEC
3900 SetHandleInformation((HANDLE
)sk
, HANDLE_FLAG_INHERIT
, 0);
3903 fcntl(sk
, F_SETFD
, 1);
3907 if (soap
->connect_flags
== SO_LINGER
)
3908 { struct linger linger
;
3909 memset((void*)&linger
, 0, sizeof(linger
));
3911 linger
.l_linger
= soap
->linger_time
;
3912 if (setsockopt(sk
, SOL_SOCKET
, SO_LINGER
, (char*)&linger
, sizeof(struct linger
)))
3913 { soap
->errnum
= soap_socket_errno(sk
);
3914 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR
);
3915 soap
->fclosesocket(soap
, sk
);
3917 freeaddrinfo(ressave
);
3919 return SOAP_INVALID_SOCKET
;
3922 else if (soap
->connect_flags
&& setsockopt(sk
, SOL_SOCKET
, soap
->connect_flags
, (char*)&set
, sizeof(int)))
3923 { soap
->errnum
= soap_socket_errno(sk
);
3924 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR
);
3925 soap
->fclosesocket(soap
, sk
);
3927 freeaddrinfo(ressave
);
3929 return SOAP_INVALID_SOCKET
;
3931 if ((soap
->keep_alive
|| soap
->tcp_keep_alive
) && setsockopt(sk
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
3932 { soap
->errnum
= soap_socket_errno(sk
);
3933 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR
);
3934 soap
->fclosesocket(soap
, sk
);
3936 freeaddrinfo(ressave
);
3938 return SOAP_INVALID_SOCKET
;
3940 if (setsockopt(sk
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
3941 { soap
->errnum
= soap_socket_errno(sk
);
3942 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR
);
3943 soap
->fclosesocket(soap
, sk
);
3945 freeaddrinfo(ressave
);
3947 return SOAP_INVALID_SOCKET
;
3949 if (setsockopt(sk
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
3950 { soap
->errnum
= soap_socket_errno(sk
);
3951 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR
);
3952 soap
->fclosesocket(soap
, sk
);
3954 freeaddrinfo(ressave
);
3956 return SOAP_INVALID_SOCKET
;
3959 if (soap
->tcp_keep_idle
&& setsockopt((SOAP_SOCKET
)sk
, IPPROTO_TCP
, TCP_KEEPIDLE
, (char*)&(soap
->tcp_keep_idle
), sizeof(int)))
3960 { soap
->errnum
= soap_socket_errno(sk
);
3961 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR
);
3962 soap
->fclosesocket(soap
, (SOAP_SOCKET
)sk
);
3964 freeaddrinfo(ressave
);
3966 return SOAP_INVALID_SOCKET
;
3969 #ifdef TCP_KEEPINTVL
3970 if (soap
->tcp_keep_intvl
&& setsockopt((SOAP_SOCKET
)sk
, IPPROTO_TCP
, TCP_KEEPINTVL
, (char*)&(soap
->tcp_keep_intvl
), sizeof(int)))
3971 { soap
->errnum
= soap_socket_errno(sk
);
3972 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR
);
3973 soap
->fclosesocket(soap
, (SOAP_SOCKET
)sk
);
3975 freeaddrinfo(ressave
);
3977 return SOAP_INVALID_SOCKET
;
3981 if (soap
->tcp_keep_cnt
&& setsockopt((SOAP_SOCKET
)sk
, IPPROTO_TCP
, TCP_KEEPCNT
, (char*)&(soap
->tcp_keep_cnt
), sizeof(int)))
3982 { soap
->errnum
= soap_socket_errno(sk
);
3983 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR
);
3984 soap
->fclosesocket(soap
, (SOAP_SOCKET
)sk
);
3986 freeaddrinfo(ressave
);
3988 return SOAP_INVALID_SOCKET
;
3992 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(sk
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
3993 { soap
->errnum
= soap_socket_errno(sk
);
3994 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR
);
3995 soap
->fclosesocket(soap
, sk
);
3997 freeaddrinfo(ressave
);
3999 return SOAP_INVALID_SOCKET
;
4003 if ((soap
->omode
& SOAP_IO_UDP
) && soap
->ipv6_multicast_if
)
4004 { struct sockaddr_in6
*in6addr
= (struct sockaddr_in6
*)res
->ai_addr
;
4005 in6addr
->sin6_scope_id
= soap
->ipv6_multicast_if
;
4008 #ifdef IP_MULTICAST_TTL
4009 if ((soap
->omode
& SOAP_IO_UDP
))
4010 { if (soap
->ipv4_multicast_ttl
)
4011 { unsigned char ttl
= soap
->ipv4_multicast_ttl
;
4012 if (setsockopt(sk
, IPPROTO_IP
, IP_MULTICAST_TTL
, (char*)&ttl
, sizeof(ttl
)))
4013 { soap
->errnum
= soap_socket_errno(sk
);
4014 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR
);
4015 soap
->fclosesocket(soap
, sk
);
4016 return SOAP_INVALID_SOCKET
;
4019 if ((soap
->omode
& SOAP_IO_UDP
) && soap
->ipv4_multicast_if
&& !soap
->ipv6_multicast_if
)
4020 { if (setsockopt(sk
, IPPROTO_IP
, IP_MULTICAST_IF
, (char*)soap
->ipv4_multicast_if
, sizeof(struct in_addr
)))
4022 { soap
->errnum
= soap_socket_errno(sk
);
4023 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR
);
4024 soap
->fclosesocket(soap
, sk
);
4025 return SOAP_INVALID_SOCKET
;
4028 #ifndef IP_MULTICAST_IF
4029 #define IP_MULTICAST_IF 2
4031 if (setsockopt(sk
, IPPROTO_IP
, IP_MULTICAST_IF
, (char*)soap
->ipv4_multicast_if
, sizeof(struct in_addr
)))
4032 { soap
->errnum
= soap_socket_errno(sk
);
4033 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR
);
4034 soap
->fclosesocket(soap
, sk
);
4035 return SOAP_INVALID_SOCKET
;
4042 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Opening socket=%d to host='%s' port=%d\n", sk
, host
, port
));
4044 soap
->peerlen
= sizeof(soap
->peer
);
4045 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
4046 soap
->peer
.sin_family
= AF_INET
;
4048 if (soap
->proxy_host
)
4049 { if (soap
->fresolve(soap
, soap
->proxy_host
, &soap
->peer
.sin_addr
))
4050 { soap_set_sender_error(soap
, tcp_error(soap
), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR
);
4051 soap
->fclosesocket(soap
, sk
);
4052 return SOAP_INVALID_SOCKET
;
4054 soap
->peer
.sin_port
= htons((short)soap
->proxy_port
);
4057 { if (soap
->fresolve(soap
, host
, &soap
->peer
.sin_addr
))
4058 { soap_set_sender_error(soap
, tcp_error(soap
), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR
);
4059 soap
->fclosesocket(soap
, sk
);
4060 return SOAP_INVALID_SOCKET
;
4062 soap
->peer
.sin_port
= htons((short)port
);
4066 if ((soap
->omode
& SOAP_IO_UDP
))
4070 if ((soap
->omode
& SOAP_IO_UDP
))
4071 { memcpy(&soap
->peer
, res
->ai_addr
, res
->ai_addrlen
);
4072 soap
->peerlen
= res
->ai_addrlen
;
4073 freeaddrinfo(ressave
);
4078 if (soap
->connect_timeout
)
4079 SOAP_SOCKNONBLOCK(sk
)
4087 if (connect(sk
, res
->ai_addr
, (int)res
->ai_addrlen
))
4089 if (connect(sk
, (struct sockaddr
*)&soap
->peer
, sizeof(soap
->peer
)))
4091 { err
= soap_socket_errno(sk
);
4093 if (err
== SOAP_EADDRINUSE
)
4094 { soap
->fclosesocket(soap
, sk
);
4098 else if (soap
->connect_timeout
&& (err
== SOAP_EINPROGRESS
|| err
== SOAP_EAGAIN
|| err
== SOAP_EWOULDBLOCK
))
4103 r
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
, soap
->connect_timeout
);
4107 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connect timeout\n"));
4108 soap_set_sender_error(soap
, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4109 soap
->fclosesocket(soap
, sk
);
4111 freeaddrinfo(ressave
);
4113 return SOAP_INVALID_SOCKET
;
4115 r
= soap
->errnum
= soap_socket_errno(sk
);
4116 if (r
!= SOAP_EINTR
)
4117 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
4118 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4119 soap
->fclosesocket(soap
, sk
);
4121 freeaddrinfo(ressave
);
4123 return SOAP_INVALID_SOCKET
;
4126 k
= (SOAP_SOCKLEN_T
)sizeof(soap
->errnum
);
4127 if (!getsockopt(sk
, SOL_SOCKET
, SO_ERROR
, (char*)&soap
->errnum
, &k
) && !soap
->errnum
) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4129 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
4131 soap
->errnum
= soap_socket_errno(sk
);
4132 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4133 soap
->fclosesocket(soap
, sk
);
4135 freeaddrinfo(ressave
);
4137 return SOAP_INVALID_SOCKET
;
4142 { res
= res
->ai_next
;
4143 soap
->fclosesocket(soap
, sk
);
4147 if (err
&& err
!= SOAP_EINTR
)
4148 { soap
->errnum
= err
;
4149 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
4150 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4151 soap
->fclosesocket(soap
, sk
);
4153 freeaddrinfo(ressave
);
4155 return SOAP_INVALID_SOCKET
;
4162 soap
->peerlen
= 0; /* IPv6: already connected so use send() */
4163 freeaddrinfo(ressave
);
4166 soap
->imode
&= ~SOAP_ENC_SSL
;
4167 soap
->omode
&= ~SOAP_ENC_SSL
;
4168 if (!soap_tag_cmp(endpoint
, "https:*"))
4170 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
4175 if (soap
->proxy_host
)
4176 { soap_mode m
= soap
->mode
; /* preserve settings */
4177 soap_mode om
= soap
->omode
; /* make sure we only parse HTTP */
4178 size_t n
= soap
->count
; /* save the content length */
4179 const char *userid
, *passwd
;
4180 int status
= soap
->status
; /* save the current status/command */
4181 short keep_alive
= soap
->keep_alive
; /* save the KA status */
4182 soap
->omode
&= ~SOAP_ENC
; /* mask IO and ENC */
4183 soap
->omode
|= SOAP_IO_BUFFER
;
4184 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connecting to %s proxy server %s for destination endpoint %s\n", soap
->proxy_http_version
, soap
->proxy_host
, endpoint
));
4186 if (soap
->ntlm_challenge
)
4187 { if (soap_ntlm_handshake(soap
, SOAP_CONNECT
, endpoint
, host
, port
))
4191 if (soap_begin_send(soap
))
4192 { soap
->fclosesocket(soap
, sk
);
4193 return SOAP_INVALID_SOCKET
;
4195 soap
->status
= SOAP_CONNECT
;
4196 soap
->keep_alive
= 1;
4197 if ((soap
->error
= soap
->fpost(soap
, endpoint
, host
, port
, NULL
, NULL
, 0))
4198 || soap_end_send_flush(soap
))
4199 { soap
->fclosesocket(soap
, sk
);
4200 return SOAP_INVALID_SOCKET
;
4202 soap
->keep_alive
= keep_alive
;
4205 soap
->imode
&= ~SOAP_ENC
; /* mask IO and ENC */
4206 userid
= soap
->userid
; /* preserve */
4207 passwd
= soap
->passwd
; /* preserve */
4208 if ((soap
->error
= soap
->fparse(soap
)))
4209 { soap
->fclosesocket(soap
, sk
);
4210 return SOAP_INVALID_SOCKET
;
4212 soap
->status
= status
; /* restore */
4213 soap
->userid
= userid
; /* restore */
4214 soap
->passwd
= passwd
; /* restore */
4215 soap
->imode
= om
; /* restore */
4216 soap
->count
= n
; /* restore */
4217 if (soap_begin_send(soap
))
4218 { soap
->fclosesocket(soap
, sk
);
4219 return SOAP_INVALID_SOCKET
;
4222 { strncpy(soap
->endpoint
, endpoint
, sizeof(soap
->endpoint
)); /* restore */
4223 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
4228 soap
->ssl_flags
|= SOAP_SSL_CLIENT
;
4229 if (!soap
->ctx
&& (soap
->error
= soap
->fsslauth(soap
)))
4230 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL required, but no ctx set\n"));
4231 soap
->fclosesocket(soap
, sk
);
4232 soap
->error
= SOAP_SSL_ERROR
;
4233 return SOAP_INVALID_SOCKET
;
4236 { soap
->ssl
= SSL_new(soap
->ctx
);
4238 { soap
->fclosesocket(soap
, sk
);
4239 soap
->error
= SOAP_SSL_ERROR
;
4240 return SOAP_INVALID_SOCKET
;
4244 SSL_clear(soap
->ssl
);
4246 { if (!strcmp(soap
->session_host
, host
) && soap
->session_port
== port
)
4247 SSL_set_session(soap
->ssl
, soap
->session
);
4248 SSL_SESSION_free(soap
->session
);
4249 soap
->session
= NULL
;
4251 soap
->imode
|= SOAP_ENC_SSL
;
4252 soap
->omode
|= SOAP_ENC_SSL
;
4253 bio
= BIO_new_socket((int)sk
, BIO_NOCLOSE
);
4254 SSL_set_bio(soap
->ssl
, bio
, bio
);
4255 /* Connect timeout: set SSL sockets to non-blocking */
4257 if (soap
->connect_timeout
)
4258 { SOAP_SOCKNONBLOCK(sk
)
4259 retries
= 10*soap
->connect_timeout
;
4264 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
4265 /* Try connecting until success or timeout (when nonblocking) */
4267 { if ((r
= SSL_connect(soap
->ssl
)) <= 0)
4268 { int err
= SSL_get_error(soap
->ssl
, r
);
4269 if (err
== SSL_ERROR_WANT_CONNECT
|| err
== SSL_ERROR_WANT_READ
|| err
== SSL_ERROR_WANT_WRITE
)
4271 if (err
== SSL_ERROR_WANT_READ
)
4272 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
4274 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
4276 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL_connect/select error in tcp_connect\n"));
4277 soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4278 soap
->fclosesocket(soap
, sk
);
4279 return SOAP_INVALID_SOCKET
;
4281 if (s
== 0 && retries
-- <= 0)
4282 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL/TLS connect timeout\n"));
4283 soap_set_sender_error(soap
, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4284 soap
->fclosesocket(soap
, sk
);
4285 return SOAP_INVALID_SOCKET
;
4289 { soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR
);
4290 soap
->fclosesocket(soap
, sk
);
4291 return SOAP_INVALID_SOCKET
;
4294 } while (!SSL_is_init_finished(soap
->ssl
));
4295 /* Set SSL sockets to nonblocking */
4296 SOAP_SOCKNONBLOCK(sk
)
4297 /* Check server credentials when required */
4298 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
4300 if ((err
= SSL_get_verify_result(soap
->ssl
)) != X509_V_OK
)
4301 { soap_set_sender_error(soap
, X509_verify_cert_error_string(err
), "SSL/TLS certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR
);
4302 soap
->fclosesocket(soap
, sk
);
4303 return SOAP_INVALID_SOCKET
;
4305 if (!(soap
->ssl_flags
& SOAP_SSL_SKIP_HOST_CHECK
))
4307 STACK_OF(CONF_VALUE
) *val
= NULL
;
4308 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
4309 GENERAL_NAMES
*names
= NULL
;
4314 X509
*peer
= SSL_get_peer_certificate(soap
->ssl
);
4316 { soap_set_sender_error(soap
, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR
);
4317 soap
->fclosesocket(soap
, sk
);
4318 return SOAP_INVALID_SOCKET
;
4320 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL)
4321 ext_count
= X509_get_ext_count(peer
);
4324 for (i
= 0; i
< ext_count
; i
++)
4325 { X509_EXTENSION
*ext
= X509_get_ext(peer
, i
);
4326 const char *ext_str
= OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext
)));
4327 if (ext_str
&& !strcmp(ext_str
, "subjectAltName"))
4328 { X509V3_EXT_METHOD
*meth
= (X509V3_EXT_METHOD
*)X509V3_EXT_get(ext
);
4329 unsigned char *data
;
4332 data
= ext
->value
->data
;
4335 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4338 ext_data
= ASN1_item_d2i(NULL
, &data
, ext
->value
->length
, ASN1_ITEM_ptr(meth
->it
));
4340 { /* OpenSSL is not portable at this point (?):
4341 Some compilers appear to prefer
4342 meth->d2i(NULL, (const unsigned char**)&data, ...
4344 meth->d2i(NULL, &data, ext->value->length);
4346 ext_data
= meth
->d2i(NULL
, &data
, ext
->value
->length
);
4349 val
= meth
->i2v(meth
, ext_data
, NULL
);
4353 ASN1_item_free((ASN1_VALUE
*)ext_data
, ASN1_ITEM_ptr(meth
->it
));
4355 meth
->ext_free(ext_data
);
4357 void *ext_data
= meth
->d2i(NULL
, &data
, ext
->value
->length
);
4359 val
= meth
->i2v(meth
, ext_data
, NULL
);
4360 meth
->ext_free(ext_data
);
4364 for (j
= 0; j
< sk_CONF_VALUE_num(val
); j
++)
4365 { CONF_VALUE
*nval
= sk_CONF_VALUE_value(val
, j
);
4366 if (nval
&& !strcmp(nval
->name
, "DNS") && !strcmp(nval
->value
, host
))
4371 sk_CONF_VALUE_pop_free(val
, X509V3_conf_free
);
4380 names
= (GENERAL_NAMES
*)X509_get_ext_d2i(peer
, NID_subject_alt_name
, NULL
, NULL
);
4382 { val
= i2v_GENERAL_NAMES(NULL
, names
, val
);
4383 sk_GENERAL_NAME_pop_free(names
, GENERAL_NAME_free
);
4387 for (j
= 0; j
< sk_CONF_VALUE_num(val
); j
++)
4388 { CONF_VALUE
*nval
= sk_CONF_VALUE_value(val
, j
);
4389 if (nval
&& !strcmp(nval
->name
, "DNS") && !strcmp(nval
->value
, host
))
4394 sk_CONF_VALUE_pop_free(val
, X509V3_conf_free
);
4397 if (!ok
&& (subj
= X509_get_subject_name(peer
)))
4400 { ASN1_STRING
*name
;
4401 i
= X509_NAME_get_index_by_NID(subj
, NID_commonName
, i
);
4404 name
= X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj
, i
));
4406 { if (!soap_tag_cmp(host
, (const char*)M_ASN1_STRING_data(name
)))
4409 { unsigned char *tmp
= NULL
;
4410 ASN1_STRING_to_UTF8(&tmp
, name
);
4412 { if (!soap_tag_cmp(host
, (const char*)tmp
))
4414 else if (tmp
[0] == '*') /* wildcard domain */
4415 { const char *t
= strchr(host
, '.');
4416 if (t
&& !soap_tag_cmp(t
, (const char*)tmp
+1))
4427 { soap_set_sender_error(soap
, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR
);
4428 soap
->fclosesocket(soap
, sk
);
4429 return SOAP_INVALID_SOCKET
;
4435 soap
->ssl_flags
|= SOAP_SSL_CLIENT
;
4436 if (!soap
->session
&& (soap
->error
= soap
->fsslauth(soap
)))
4437 { soap
->fclosesocket(soap
, sk
);
4438 return SOAP_INVALID_SOCKET
;
4440 gnutls_transport_set_ptr(soap
->session
, (gnutls_transport_ptr_t
)(long)sk
);
4441 /* Set SSL sockets to non-blocking */
4442 if (soap
->connect_timeout
)
4443 { SOAP_SOCKNONBLOCK(sk
)
4444 retries
= 10*soap
->connect_timeout
;
4449 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
4450 while ((r
= gnutls_handshake(soap
->session
)))
4452 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
4455 if (r
== GNUTLS_E_AGAIN
|| r
== GNUTLS_E_INTERRUPTED
)
4456 { if (!gnutls_record_get_direction(soap
->session
))
4457 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
4459 s
= tcp_select(soap
, sk
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
4464 { soap
->errnum
= soap_socket_errno(sk
);
4469 { soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL/TLS handshake failed", SOAP_SSL_ERROR
);
4470 soap
->fclosesocket(soap
, sk
);
4471 return SOAP_INVALID_SOCKET
;
4473 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
4474 { const char *err
= ssl_verify(soap
, host
);
4476 { soap
->fclosesocket(soap
, sk
);
4477 soap
->error
= soap_set_sender_error(soap
, "SSL/TLS error", err
, SOAP_SSL_ERROR
);
4478 return SOAP_INVALID_SOCKET
;
4483 soap
->fclosesocket(soap
, sk
);
4484 soap
->error
= SOAP_SSL_ERROR
;
4485 return SOAP_INVALID_SOCKET
;
4488 if (soap
->recv_timeout
|| soap
->send_timeout
)
4489 SOAP_SOCKNONBLOCK(sk
)
4497 /******************************************************************************/
4501 tcp_select(struct soap
*soap
, SOAP_SOCKET sk
, int flags
, int timeout
)
4504 fd_set fd
[3], *rfd
, *sfd
, *efd
;
4506 int eintr
= SOAP_MAXEINTR
;
4509 #if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
4510 /* no FD_SETSIZE or select() is not MT safe on some QNX: always poll */
4513 /* if fd max set size exceeded, use poll() */
4514 if ((int)sk
>= (int)FD_SETSIZE
)
4517 { struct pollfd pollfd
;
4518 pollfd
.fd
= (int)sk
;
4520 if (flags
& SOAP_TCP_SELECT_RCV
)
4521 pollfd
.events
|= POLLIN
;
4522 if (flags
& SOAP_TCP_SELECT_SND
)
4523 pollfd
.events
|= POLLOUT
;
4524 if (flags
& SOAP_TCP_SELECT_ERR
)
4525 pollfd
.events
|= POLLERR
;
4527 timeout
/= -1000; /* -usec -> ms */
4529 { retries
= timeout
- 1;
4533 { r
= poll(&pollfd
, 1, timeout
);
4534 if (r
< 0 && (soap
->errnum
= soap_socket_errno(sk
)) == SOAP_EINTR
&& eintr
--)
4536 } while (r
== 0 && retries
--);
4539 if ((flags
& SOAP_TCP_SELECT_RCV
) && (pollfd
.revents
& POLLIN
))
4540 r
|= SOAP_TCP_SELECT_RCV
;
4541 if ((flags
& SOAP_TCP_SELECT_SND
) && (pollfd
.revents
& POLLOUT
))
4542 r
|= SOAP_TCP_SELECT_SND
;
4543 if ((flags
& SOAP_TCP_SELECT_ERR
) && (pollfd
.revents
& POLLERR
))
4544 r
|= SOAP_TCP_SELECT_ERR
;
4549 { soap
->error
= SOAP_FD_EXCEEDED
;
4555 retries
= timeout
- 1;
4557 { rfd
= sfd
= efd
= NULL
;
4558 if (flags
& SOAP_TCP_SELECT_RCV
)
4563 if (flags
& SOAP_TCP_SELECT_SND
)
4568 if (flags
& SOAP_TCP_SELECT_ERR
)
4574 { tv
.tv_sec
= -timeout
/ 1000000;
4575 tv
.tv_usec
= -timeout
% 1000000;
4581 r
= select((int)sk
+ 1, rfd
, sfd
, efd
, &tv
);
4582 if (r
< 0 && (soap
->errnum
= soap_socket_errno(sk
)) == SOAP_EINTR
&& eintr
--)
4584 } while (r
== 0 && retries
--);
4587 if ((flags
& SOAP_TCP_SELECT_RCV
) && FD_ISSET(sk
, rfd
))
4588 r
|= SOAP_TCP_SELECT_RCV
;
4589 if ((flags
& SOAP_TCP_SELECT_SND
) && FD_ISSET(sk
, sfd
))
4590 r
|= SOAP_TCP_SELECT_SND
;
4591 if ((flags
& SOAP_TCP_SELECT_ERR
) && FD_ISSET(sk
, efd
))
4592 r
|= SOAP_TCP_SELECT_ERR
;
4599 /******************************************************************************/
4603 tcp_accept(struct soap
*soap
, SOAP_SOCKET s
, struct sockaddr
*a
, int *n
)
4606 sk
= accept(s
, a
, (SOAP_SOCKLEN_T
*)n
); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4607 #ifdef SOCKET_CLOSE_ON_EXEC
4610 SetHandleInformation((HANDLE
)sk
, HANDLE_FLAG_INHERIT
, 0);
4613 fcntl(sk
, F_SETFD
, FD_CLOEXEC
);
4621 /******************************************************************************/
4625 tcp_disconnect(struct soap
*soap
)
4631 { SSL_SESSION_free(soap
->session
);
4632 soap
->session
= NULL
;
4635 { soap
->session
= SSL_get1_session(soap
->ssl
);
4637 { strcpy(soap
->session_host
, soap
->host
);
4638 soap
->session_port
= soap
->port
;
4641 r
= SSL_shutdown(soap
->ssl
);
4642 /* SSL shutdown does not work when reads are pending, non-blocking */
4644 { while (SSL_want_read(soap
->ssl
))
4645 { if (SSL_read(soap
->ssl
, NULL
, 0)
4646 || soap_socket_errno(soap
->socket
) != SOAP_EAGAIN
)
4647 { r
= SSL_shutdown(soap
->ssl
);
4653 { if (soap_valid_socket(soap
->socket
))
4654 { if (!soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_WR
))
4656 #if !defined(WITH_LEAN) && !defined(WIN32)
4658 wait up to 5 seconds for close_notify to be sent by peer (if peer not
4659 present, this avoids calling SSL_shutdown() which has a lengthy return
4662 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, 5);
4665 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connection lost...\n"));
4666 soap
->fclosesocket(soap
, soap
->socket
);
4667 soap
->socket
= SOAP_INVALID_SOCKET
;
4668 ERR_remove_state(0);
4669 SSL_free(soap
->ssl
);
4674 r
= SSL_shutdown(soap
->ssl
);
4680 { s
= ERR_get_error();
4682 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Shutdown failed: %d\n", SSL_get_error(soap
->ssl
, r
)));
4683 if (soap_valid_socket(soap
->socket
) && !(soap
->omode
& SOAP_IO_UDP
))
4684 { soap
->fclosesocket(soap
, soap
->socket
);
4685 soap
->socket
= SOAP_INVALID_SOCKET
;
4689 SSL_free(soap
->ssl
);
4692 return SOAP_SSL_ERROR
;
4693 ERR_remove_state(0);
4698 { gnutls_bye(soap
->session
, GNUTLS_SHUT_RDWR
);
4699 gnutls_deinit(soap
->session
);
4700 soap
->session
= NULL
;
4703 if (soap_valid_socket(soap
->socket
) && !(soap
->omode
& SOAP_IO_UDP
))
4704 { soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_RDWR
);
4705 soap
->fclosesocket(soap
, soap
->socket
);
4706 soap
->socket
= SOAP_INVALID_SOCKET
;
4713 /******************************************************************************/
4717 tcp_closesocket(struct soap
*soap
, SOAP_SOCKET sk
)
4719 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Close socket=%d\n", (int)sk
));
4720 return soap_closesocket(sk
);
4725 /******************************************************************************/
4729 tcp_shutdownsocket(struct soap
*soap
, SOAP_SOCKET sk
, int how
)
4731 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Shutdown socket=%d how=%d\n", (int)sk
, how
));
4732 return shutdown(sk
, how
);
4737 /******************************************************************************/
4743 soap_bind(struct soap
*soap
, const char *host
, int port
, int backlog
)
4746 struct addrinfo
*addrinfo
= NULL
;
4747 struct addrinfo hints
;
4748 struct addrinfo res
;
4750 #ifdef WITH_NO_IPV6_V6ONLY
4756 int len
= SOAP_BUFLEN
;
4758 int len
= SOAP_BUFLEN
+ 1; /* speeds up windows xfer */
4762 if (soap_valid_socket(soap
->master
))
4763 { soap
->fclosesocket(soap
, soap
->master
);
4764 soap
->master
= SOAP_INVALID_SOCKET
;
4766 soap
->socket
= SOAP_INVALID_SOCKET
;
4769 { soap_set_receiver_error(soap
, tcp_error(soap
), "TCP init failed in soap_bind()", SOAP_TCP_ERROR
);
4770 return SOAP_INVALID_SOCKET
;
4773 memset((void*)&hints
, 0, sizeof(hints
));
4774 hints
.ai_family
= PF_UNSPEC
;
4776 if ((soap
->omode
& SOAP_IO_UDP
))
4777 hints
.ai_socktype
= SOCK_DGRAM
;
4780 hints
.ai_socktype
= SOCK_STREAM
;
4781 hints
.ai_flags
= AI_PASSIVE
;
4783 err
= getaddrinfo(host
, soap_int2s(soap
, port
), &hints
, &addrinfo
);
4784 if (err
|| !addrinfo
)
4785 { soap_set_receiver_error(soap
, SOAP_GAI_STRERROR(err
), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR
);
4786 return SOAP_INVALID_SOCKET
;
4789 memcpy(&soap
->peer
, addrinfo
->ai_addr
, addrinfo
->ai_addrlen
);
4790 soap
->peerlen
= addrinfo
->ai_addrlen
;
4791 res
.ai_addr
= (struct sockaddr
*)&soap
->peer
;
4792 res
.ai_addrlen
= soap
->peerlen
;
4793 freeaddrinfo(addrinfo
);
4794 soap
->master
= (int)socket(res
.ai_family
, res
.ai_socktype
, res
.ai_protocol
);
4797 if ((soap
->omode
& SOAP_IO_UDP
))
4798 soap
->master
= (int)socket(AF_INET
, SOCK_DGRAM
, 0);
4801 soap
->master
= (int)socket(AF_INET
, SOCK_STREAM
, 0);
4804 if (!soap_valid_socket(soap
->master
))
4805 { soap
->errnum
= soap_socket_errno(soap
->master
);
4806 soap_set_receiver_error(soap
, tcp_error(soap
), "socket failed in soap_bind()", SOAP_TCP_ERROR
);
4807 return SOAP_INVALID_SOCKET
;
4811 if ((soap
->omode
& SOAP_IO_UDP
))
4812 soap
->socket
= soap
->master
;
4814 #ifdef SOCKET_CLOSE_ON_EXEC
4817 SetHandleInformation((HANDLE
)soap
->master
, HANDLE_FLAG_INHERIT
, 0);
4820 fcntl(soap
->master
, F_SETFD
, 1);
4824 if (soap
->bind_flags
&& setsockopt(soap
->master
, SOL_SOCKET
, soap
->bind_flags
, (char*)&set
, sizeof(int)))
4825 { soap
->errnum
= soap_socket_errno(soap
->master
);
4826 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR
);
4827 return SOAP_INVALID_SOCKET
;
4829 if (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) && (!((soap
->imode
| soap
->omode
) & SOAP_IO_UDP
)) && setsockopt(soap
->master
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
4830 { soap
->errnum
= soap_socket_errno(soap
->master
);
4831 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR
);
4832 return SOAP_INVALID_SOCKET
;
4834 if (setsockopt(soap
->master
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
4835 { soap
->errnum
= soap_socket_errno(soap
->master
);
4836 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR
);
4837 return SOAP_INVALID_SOCKET
;
4839 if (setsockopt(soap
->master
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
4840 { soap
->errnum
= soap_socket_errno(soap
->master
);
4841 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR
);
4842 return SOAP_INVALID_SOCKET
;
4845 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(soap
->master
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
4846 { soap
->errnum
= soap_socket_errno(soap
->master
);
4847 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR
);
4848 return SOAP_INVALID_SOCKET
;
4853 #ifdef WITH_IPV6_V6ONLY
4854 if (setsockopt(soap
->master
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char*)&set
, sizeof(int)))
4855 { soap
->errnum
= soap_socket_errno(soap
->master
);
4856 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt set IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR
);
4857 return SOAP_INVALID_SOCKET
;
4860 #ifdef WITH_NO_IPV6_V6ONLY
4861 if (setsockopt(soap
->master
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char*)&unset
, sizeof(int)))
4862 { soap
->errnum
= soap_socket_errno(soap
->master
);
4863 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt unset IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR
);
4864 return SOAP_INVALID_SOCKET
;
4868 if (bind(soap
->master
, res
.ai_addr
, (int)res
.ai_addrlen
))
4869 { soap
->errnum
= soap_socket_errno(soap
->master
);
4870 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4871 soap_closesock(soap
);
4872 soap_set_receiver_error(soap
, tcp_error(soap
), "bind failed in soap_bind()", SOAP_TCP_ERROR
);
4873 return SOAP_INVALID_SOCKET
;
4876 soap
->peerlen
= sizeof(soap
->peer
);
4877 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
4878 soap
->peer
.sin_family
= AF_INET
;
4881 { if (soap
->fresolve(soap
, host
, &soap
->peer
.sin_addr
))
4882 { soap_set_receiver_error(soap
, tcp_error(soap
), "get host by name failed in soap_bind()", SOAP_TCP_ERROR
);
4883 return SOAP_INVALID_SOCKET
;
4887 soap
->peer
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
4888 soap
->peer
.sin_port
= htons((short)port
);
4890 if (bind(soap
->master
, (struct sockaddr
*)&soap
->peer
, (int)soap
->peerlen
))
4891 { soap
->errnum
= soap_socket_errno(soap
->master
);
4892 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4893 soap_closesock(soap
);
4894 soap_set_receiver_error(soap
, tcp_error(soap
), "bind failed in soap_bind()", SOAP_TCP_ERROR
);
4895 return SOAP_INVALID_SOCKET
;
4898 if (!(soap
->omode
& SOAP_IO_UDP
) && listen(soap
->master
, backlog
))
4899 { soap
->errnum
= soap_socket_errno(soap
->master
);
4900 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4901 soap_closesock(soap
);
4902 soap_set_receiver_error(soap
, tcp_error(soap
), "listen failed in soap_bind()", SOAP_TCP_ERROR
);
4903 return SOAP_INVALID_SOCKET
;
4905 return soap
->master
;
4910 /******************************************************************************/
4916 soap_poll(struct soap
*soap
)
4920 if (soap_valid_socket(soap
->socket
))
4921 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ALL
, 0);
4922 if (r
> 0 && (r
& SOAP_TCP_SELECT_ERR
))
4925 else if (soap_valid_socket(soap
->master
))
4926 r
= tcp_select(soap
, soap
->master
, SOAP_TCP_SELECT_SND
, 0);
4928 return SOAP_OK
; /* OK when no socket! */
4932 if (soap
->imode
& SOAP_ENC_SSL
)
4934 if (soap_valid_socket(soap
->socket
)
4935 && (r
& SOAP_TCP_SELECT_SND
)
4936 && (!(r
& SOAP_TCP_SELECT_RCV
)
4937 || SSL_peek(soap
->ssl
, soap
->tmpbuf
, 1) > 0))
4943 if (soap_valid_socket(soap
->socket
)
4944 && (r
& SOAP_TCP_SELECT_SND
)
4945 && (!(r
& SOAP_TCP_SELECT_RCV
)
4946 || recv(soap
->socket
, (char*)&t
, 1, MSG_PEEK
) > 0))
4951 { if ((soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) && soap_socket_errno(soap
->master
) != SOAP_EINTR
)
4952 { soap_set_receiver_error(soap
, tcp_error(soap
), "select failed in soap_poll()", SOAP_TCP_ERROR
);
4953 return soap
->error
= SOAP_TCP_ERROR
;
4956 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Polling: other end down on socket=%d select=%d\n", soap
->socket
, r
));
4965 /******************************************************************************/
4971 soap_accept(struct soap
*soap
)
4972 { int n
= (int)sizeof(soap
->peer
);
4976 int len
= SOAP_BUFLEN
;
4978 int len
= SOAP_BUFLEN
+ 1; /* speeds up windows xfer */
4982 soap
->error
= SOAP_OK
;
4983 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
4984 soap
->socket
= SOAP_INVALID_SOCKET
;
4986 soap
->keep_alive
= 0;
4987 if (!soap_valid_socket(soap
->master
))
4989 soap_set_receiver_error(soap
, tcp_error(soap
), "no master socket in soap_accept()", SOAP_TCP_ERROR
);
4990 return SOAP_INVALID_SOCKET
;
4993 if ((soap
->omode
& SOAP_IO_UDP
))
4994 return soap
->socket
= soap
->master
;
4997 { if (soap
->accept_timeout
|| soap
->send_timeout
|| soap
->recv_timeout
)
5000 r
= tcp_select(soap
, soap
->master
, SOAP_TCP_SELECT_ALL
, soap
->accept_timeout
? soap
->accept_timeout
: 60);
5003 if (!r
&& soap
->accept_timeout
)
5004 { soap_set_receiver_error(soap
, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR
);
5005 return SOAP_INVALID_SOCKET
;
5009 if (r
!= SOAP_EINTR
)
5010 { soap_closesock(soap
);
5011 soap_set_sender_error(soap
, tcp_error(soap
), "accept failed in soap_accept()", SOAP_TCP_ERROR
);
5012 return SOAP_INVALID_SOCKET
;
5017 if (soap
->accept_timeout
)
5018 SOAP_SOCKNONBLOCK(soap
->master
)
5020 SOAP_SOCKBLOCK(soap
->master
)
5021 soap
->socket
= soap
->faccept(soap
, soap
->master
, (struct sockaddr
*)&soap
->peer
, &n
);
5022 soap
->peerlen
= (size_t)n
;
5023 if (soap_valid_socket(soap
->socket
))
5026 unsigned int ip1
, ip2
, ip3
, ip4
;
5028 getnameinfo((struct sockaddr
*)&soap
->peer
, n
, soap
->host
, sizeof(soap
->host
), port
, 16, NI_NUMERICHOST
| NI_NUMERICSERV
);
5029 sscanf(soap
->host
, "%u.%u.%u.%u", &ip1
, &ip2
, &ip3
, &ip4
);
5030 soap
->ip
= (unsigned long)ip1
<< 24 | (unsigned long)ip2
<< 16 | (unsigned long)ip3
<< 8 | (unsigned long)ip4
;
5031 soap
->port
= soap_strtol(port
, NULL
, 10);
5033 soap
->ip
= ntohl(soap
->peer
.sin_addr
.s_addr
);
5034 #ifdef HAVE_SNPRINTF
5035 soap_snprintf(soap
->host
, sizeof(soap
->host
), "%u.%u.%u.%u", (int)(soap
->ip
>>24)&0xFF, (int)(soap
->ip
>>16)&0xFF, (int)(soap
->ip
>>8)&0xFF, (int)soap
->ip
&0xFF);
5037 sprintf(soap
->host
, "%u.%u.%u.%u", (int)(soap
->ip
>>24)&0xFF, (int)(soap
->ip
>>16)&0xFF, (int)(soap
->ip
>>8)&0xFF, (int)soap
->ip
&0xFF);
5039 soap
->port
= (int)ntohs(soap
->peer
.sin_port
); /* does not return port number on some systems */
5041 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Accept socket=%d at port=%d from IP='%s'\n", soap
->socket
, soap
->port
, soap
->host
));
5043 if (soap
->accept_flags
== SO_LINGER
)
5044 { struct linger linger
;
5045 memset((void*)&linger
, 0, sizeof(linger
));
5047 linger
.l_linger
= soap
->linger_time
;
5048 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_LINGER
, (char*)&linger
, sizeof(struct linger
)))
5049 { soap
->errnum
= soap_socket_errno(soap
->socket
);
5050 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR
);
5051 soap_closesock(soap
);
5052 return SOAP_INVALID_SOCKET
;
5055 else if (soap
->accept_flags
&& setsockopt(soap
->socket
, SOL_SOCKET
, soap
->accept_flags
, (char*)&set
, sizeof(int)))
5056 { soap
->errnum
= soap_socket_errno(soap
->socket
);
5057 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR
);
5058 soap_closesock(soap
);
5059 return SOAP_INVALID_SOCKET
;
5061 if (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) && setsockopt(soap
->socket
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
5062 { soap
->errnum
= soap_socket_errno(soap
->socket
);
5063 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR
);
5064 soap_closesock(soap
);
5065 return SOAP_INVALID_SOCKET
;
5067 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
5068 { soap
->errnum
= soap_socket_errno(soap
->socket
);
5069 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR
);
5070 soap_closesock(soap
);
5071 return SOAP_INVALID_SOCKET
;
5073 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
5074 { soap
->errnum
= soap_socket_errno(soap
->socket
);
5075 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR
);
5076 soap_closesock(soap
);
5077 return SOAP_INVALID_SOCKET
;
5080 if (setsockopt(soap
->socket
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
5081 { soap
->errnum
= soap_socket_errno(soap
->socket
);
5082 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR
);
5083 soap_closesock(soap
);
5084 return SOAP_INVALID_SOCKET
;
5088 soap
->keep_alive
= (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) != 0);
5089 if (soap
->send_timeout
|| soap
->recv_timeout
)
5090 SOAP_SOCKNONBLOCK(soap
->socket
)
5092 SOAP_SOCKBLOCK(soap
->socket
)
5093 return soap
->socket
;
5095 err
= soap_socket_errno(soap
->socket
);
5096 if (err
!= 0 && err
!= SOAP_EINTR
&& err
!= SOAP_EAGAIN
&& err
!= SOAP_EWOULDBLOCK
)
5097 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Accept failed from %s\n", soap
->host
));
5099 soap_set_receiver_error(soap
, tcp_error(soap
), "accept failed in soap_accept()", SOAP_TCP_ERROR
);
5100 soap_closesock(soap
);
5101 return SOAP_INVALID_SOCKET
;
5108 /******************************************************************************/
5113 soap_closesock(struct soap
*soap
)
5114 { register int status
= soap
->error
;
5116 if (status
) /* close on error: attachment state is not to be trusted */
5117 { soap
->mime
.first
= NULL
;
5118 soap
->mime
.last
= NULL
;
5119 soap
->dime
.first
= NULL
;
5120 soap
->dime
.last
= NULL
;
5123 if (soap
->fdisconnect
&& (soap
->error
= soap
->fdisconnect(soap
)))
5125 if (status
== SOAP_EOF
|| status
== SOAP_TCP_ERROR
|| status
== SOAP_SSL_ERROR
|| !soap
->keep_alive
)
5126 { if (soap
->fclose
&& (soap
->error
= soap
->fclose(soap
)))
5128 soap
->keep_alive
= 0;
5131 if (!(soap
->mode
& SOAP_MIME_POSTCHECK
))
5132 { if (soap
->zlib_state
== SOAP_ZLIB_DEFLATE
)
5133 deflateEnd(soap
->d_stream
);
5134 else if (soap
->zlib_state
== SOAP_ZLIB_INFLATE
)
5135 inflateEnd(soap
->d_stream
);
5136 soap
->zlib_state
= SOAP_ZLIB_NONE
;
5139 return soap
->error
= status
;
5143 /******************************************************************************/
5149 soap_force_closesock(struct soap
*soap
)
5150 { soap
->keep_alive
= 0;
5151 if (soap_valid_socket(soap
->socket
))
5152 return soap_closesocket(soap
->socket
);
5158 /******************************************************************************/
5164 soap_cleanup(struct soap
*soap
)
5176 /******************************************************************************/
5181 soap_done(struct soap
*soap
)
5186 if (soap_check_state(soap
))
5188 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Done with context%s\n", soap
->state
== SOAP_COPY
? " copy" : ""));
5189 soap_free_temp(soap
);
5191 { struct soap_clist
*p
= soap
->clist
->next
;
5192 SOAP_FREE(soap
, soap
->clist
);
5195 if (soap
->state
== SOAP_INIT
)
5196 soap
->omode
&= ~SOAP_IO_UDP
; /* to force close the socket */
5197 soap
->keep_alive
= 0; /* to force close the socket */
5198 if (soap
->master
== soap
->socket
) /* do not close twice */
5199 soap
->master
= SOAP_INVALID_SOCKET
;
5200 soap_closesock(soap
);
5202 soap_free_cookies(soap
);
5204 while (soap
->plugins
)
5205 { register struct soap_plugin
*p
= soap
->plugins
->next
;
5206 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Removing plugin '%s'\n", soap
->plugins
->id
));
5207 if (soap
->plugins
->fcopy
|| soap
->state
== SOAP_INIT
)
5208 soap
->plugins
->fdelete(soap
, soap
->plugins
);
5209 SOAP_FREE(soap
, soap
->plugins
);
5212 soap
->fplugin
= fplugin
;
5213 soap
->fmalloc
= NULL
;
5215 soap
->fpost
= http_post
;
5216 soap
->fget
= http_get
;
5217 soap
->fput
= http_405
;
5218 soap
->fdel
= http_405
;
5219 soap
->fopt
= http_200
;
5220 soap
->fhead
= http_200
;
5222 soap
->fposthdr
= http_post_header
;
5223 soap
->fresponse
= http_response
;
5224 soap
->fparse
= http_parse
;
5225 soap
->fparsehdr
= http_parse_header
;
5227 soap
->fheader
= NULL
;
5230 soap
->fresolve
= tcp_gethost
;
5232 soap
->fresolve
= NULL
;
5234 soap
->faccept
= tcp_accept
;
5235 soap
->fopen
= tcp_connect
;
5236 soap
->fclose
= tcp_disconnect
;
5237 soap
->fclosesocket
= tcp_closesocket
;
5238 soap
->fshutdownsocket
= tcp_shutdownsocket
;
5239 soap
->fsend
= fsend
;
5240 soap
->frecv
= frecv
;
5241 soap
->fpoll
= soap_poll
;
5244 soap
->fclose
= NULL
;
5248 soap
->feltbegin
= NULL
;
5249 soap
->feltendin
= NULL
;
5250 soap
->feltbegout
= NULL
;
5251 soap
->feltendout
= NULL
;
5252 soap
->fprepareinitsend
= NULL
;
5253 soap
->fprepareinitrecv
= NULL
;
5254 soap
->fpreparesend
= NULL
;
5255 soap
->fpreparerecv
= NULL
;
5256 soap
->fpreparefinalsend
= NULL
;
5257 soap
->fpreparefinalrecv
= NULL
;
5258 soap
->ffiltersend
= NULL
;
5259 soap
->ffilterrecv
= NULL
;
5261 soap
->fseterror
= NULL
;
5262 soap
->fignore
= NULL
;
5263 soap
->fserveloop
= NULL
;
5266 { SSL_SESSION_free(soap
->session
);
5267 soap
->session
= NULL
;
5270 if (soap
->state
== SOAP_INIT
)
5271 { if (soap_valid_socket(soap
->master
))
5272 { soap
->fclosesocket(soap
, soap
->master
);
5273 soap
->master
= SOAP_INVALID_SOCKET
;
5278 { SSL_free(soap
->ssl
);
5281 if (soap
->state
== SOAP_INIT
)
5283 { SSL_CTX_free(soap
->ctx
);
5287 ERR_remove_state(0);
5290 if (soap
->state
== SOAP_INIT
)
5292 { gnutls_certificate_free_credentials(soap
->xcred
);
5296 { gnutls_anon_free_client_credentials(soap
->acred
);
5300 { gnutls_priority_deinit(soap
->cache
);
5303 if (soap
->dh_params
)
5304 { gnutls_dh_params_deinit(soap
->dh_params
);
5305 soap
->dh_params
= NULL
;
5307 if (soap
->rsa_params
)
5308 { gnutls_rsa_params_deinit(soap
->rsa_params
);
5309 soap
->rsa_params
= NULL
;
5313 { gnutls_deinit(soap
->session
);
5314 soap
->session
= NULL
;
5317 #ifdef WITH_C_LOCALE
5319 _free_locale(soap
->c_locale
);
5321 freelocale(soap
->c_locale
);
5326 { SOAP_FREE(soap
, (void*)soap
->d_stream
);
5327 soap
->d_stream
= NULL
;
5330 { SOAP_FREE(soap
, (void*)soap
->z_buf
);
5335 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free logfiles\n"));
5336 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
5337 { if (soap
->logfile
[i
])
5338 { SOAP_FREE(soap
, (void*)soap
->logfile
[i
]);
5339 soap
->logfile
[i
] = NULL
;
5341 soap_close_logfile(soap
, i
);
5343 soap
->state
= SOAP_NONE
;
5345 #ifdef SOAP_MEM_DEBUG
5346 soap_free_mht(soap
);
5351 /******************************************************************************\
5355 \******************************************************************************/
5357 /******************************************************************************/
5361 http_parse(struct soap
*soap
)
5362 { char header
[SOAP_HDRLEN
], *s
;
5363 unsigned short httpcmd
= 0;
5365 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Waiting for HTTP request/response...\n"));
5366 *soap
->endpoint
= '\0';
5368 if (!soap
->ntlm_challenge
)
5370 { soap
->userid
= NULL
;
5371 soap
->passwd
= NULL
;
5372 soap
->authrealm
= NULL
;
5375 soap
->ntlm_challenge
= NULL
;
5377 soap
->proxy_from
= NULL
;
5380 soap
->http_content
= NULL
;
5381 soap
->action
= NULL
;
5384 if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
5385 { if (soap
->error
== SOAP_EOF
)
5387 return soap
->error
= 414;
5389 if ((s
= strchr(soap
->msgbuf
, ' ')))
5390 { soap
->status
= (unsigned short)soap_strtoul(s
, &s
, 10);
5391 if (!soap_blank((soap_wchar
)*s
))
5396 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP status: %s\n", soap
->msgbuf
));
5398 { if (soap_getline(soap
, header
, SOAP_HDRLEN
))
5399 { if (soap
->error
== SOAP_EOF
)
5400 { soap
->error
= SOAP_OK
;
5401 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "EOF in HTTP header, continue anyway\n"));
5408 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP header: %s\n", header
));
5409 s
= strchr(header
, ':');
5414 while (*s
&& *s
<= 32);
5417 t
= s
+ strlen(s
) - 1;
5418 while (t
> s
&& *t
<= 32)
5420 if (t
>= s
&& *t
== '"')
5423 if ((soap
->error
= soap
->fparsehdr(soap
, header
, s
)))
5424 { if (soap
->error
< SOAP_STOP
)
5426 status
= soap
->error
;
5427 soap
->error
= SOAP_OK
;
5431 } while (soap
->status
== 100);
5432 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Finished HTTP header parsing, status = %d\n", soap
->status
));
5433 s
= strstr(soap
->msgbuf
, "HTTP/");
5434 if (s
&& s
[7] != '1')
5435 { if (soap
->keep_alive
== 1)
5436 soap
->keep_alive
= 0;
5437 if (soap
->status
== 0 && (soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
) /* soap->status == 0 for HTTP request */
5438 soap
->omode
= (soap
->omode
& ~SOAP_IO
) | SOAP_IO_STORE
; /* HTTP 1.0 does not support chunked transfers */
5440 if (soap
->keep_alive
< 0)
5441 soap
->keep_alive
= 1;
5442 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Keep alive connection = %d\n", soap
->keep_alive
));
5443 if (soap
->status
== 0)
5446 { if (!strncmp(soap
->msgbuf
, "POST ", l
= 5))
5448 else if (!strncmp(soap
->msgbuf
, "PUT ", l
= 4))
5450 else if (!strncmp(soap
->msgbuf
, "GET ", l
= 4))
5452 else if (!strncmp(soap
->msgbuf
, "DELETE ", l
= 7))
5454 else if (!strncmp(soap
->msgbuf
, "OPTIONS ", l
= 8))
5456 else if (!strncmp(soap
->msgbuf
, "HEAD ", l
= 5))
5460 { size_t m
= strlen(soap
->endpoint
);
5461 size_t n
= m
+ (s
- soap
->msgbuf
) - l
- 1;
5463 if (n
>= sizeof(soap
->endpoint
))
5464 n
= sizeof(soap
->endpoint
) - 1;
5468 if (k
> sizeof(soap
->path
))
5469 k
= sizeof(soap
->path
);
5470 strncpy(soap
->path
, soap
->msgbuf
+ l
, k
);
5471 soap
->path
[k
- 1] = '\0';
5472 if (*soap
->path
&& *soap
->path
!= '/')
5473 *soap
->endpoint
= '\0';
5474 strcat(soap
->endpoint
, soap
->path
);
5475 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Target endpoint='%s'\n", soap
->endpoint
));
5477 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP %s handler\n", soap
->msgbuf
));
5479 { case 2: soap
->error
= soap
->fput(soap
); break;
5480 case 3: soap
->error
= soap
->fget(soap
); break;
5481 case 4: soap
->error
= soap
->fdel(soap
); break;
5482 case 5: soap
->error
= soap
->fopt(soap
); break;
5483 case 6: soap
->error
= soap
->fhead(soap
); break;
5484 default: soap
->error
= 405; break;
5486 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP handler return = %d\n", soap
->error
));
5487 if (soap
->error
== SOAP_OK
)
5488 soap
->error
= SOAP_STOP
; /* prevents further processing */
5492 return soap
->error
= status
;
5495 return soap
->error
= status
;
5497 return soap
->error
= 405;
5501 if (soap
->length
> 0 || (soap
->http_content
&& (!soap
->keep_alive
|| soap
->recv_timeout
)) || (soap
->imode
& SOAP_IO
) == SOAP_IO_CHUNK
)
5504 { if ((soap
->status
>= 200 && soap
->status
<= 299) /* OK, Accepted, etc */
5505 || soap
->status
== 400 /* Bad Request */
5506 || soap
->status
== 500) /* Internal Server Error */
5508 /* force close afterwards in soap_closesock() */
5509 soap
->keep_alive
= 0;
5511 /* read HTTP body for error details */
5512 s
= soap_get_http_body(soap
, NULL
);
5514 return soap_set_receiver_error(soap
, soap
->msgbuf
, s
, soap
->status
);
5517 else if (soap
->status
>= 200 && soap
->status
<= 299)
5518 return soap
->error
= soap
->status
;
5519 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP error %d\n", soap
->status
));
5520 return soap_set_receiver_error(soap
, "HTTP Error", soap
->msgbuf
, soap
->status
);
5525 /******************************************************************************/
5529 http_parse_header(struct soap
*soap
, const char *key
, const char *val
)
5530 { if (!soap_tag_cmp(key
, "Host"))
5532 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
5533 if (soap
->imode
& SOAP_ENC_SSL
)
5534 strcpy(soap
->endpoint
, "https://");
5537 strcpy(soap
->endpoint
, "http://");
5538 strncat(soap
->endpoint
, val
, sizeof(soap
->endpoint
) - 8);
5541 else if (!soap_tag_cmp(key
, "Content-Type"))
5542 { const char *action
;
5543 soap
->http_content
= soap_strdup(soap
, val
);
5544 if (soap_get_header_attribute(soap
, val
, "application/dime"))
5545 soap
->imode
|= SOAP_ENC_DIME
;
5546 else if (soap_get_header_attribute(soap
, val
, "multipart/related")
5547 || soap_get_header_attribute(soap
, val
, "multipart/form-data"))
5548 { soap
->mime
.boundary
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "boundary"));
5549 soap
->mime
.start
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "start"));
5550 soap
->imode
|= SOAP_ENC_MIME
;
5552 action
= soap_get_header_attribute(soap
, val
, "action");
5554 { if (*action
== '"')
5555 { soap
->action
= soap_strdup(soap
, action
+ 1);
5557 soap
->action
[strlen(soap
->action
) - 1] = '\0';
5560 soap
->action
= soap_strdup(soap
, action
);
5564 else if (!soap_tag_cmp(key
, "Content-Length"))
5565 { soap
->length
= soap_strtoul(val
, NULL
, 10);
5569 else if (!soap_tag_cmp(key
, "Content-Encoding"))
5570 { if (!soap_tag_cmp(val
, "deflate"))
5572 soap
->zlib_in
= SOAP_ZLIB_DEFLATE
;
5574 return SOAP_ZLIB_ERROR
;
5576 else if (!soap_tag_cmp(val
, "gzip"))
5578 soap
->zlib_in
= SOAP_ZLIB_GZIP
;
5580 return SOAP_ZLIB_ERROR
;
5584 else if (!soap_tag_cmp(key
, "Accept-Encoding"))
5587 if (strchr(val
, '*') || soap_get_header_attribute(soap
, val
, "gzip"))
5588 soap
->zlib_out
= SOAP_ZLIB_GZIP
;
5591 if (strchr(val
, '*') || soap_get_header_attribute(soap
, val
, "deflate"))
5592 soap
->zlib_out
= SOAP_ZLIB_DEFLATE
;
5594 soap
->zlib_out
= SOAP_ZLIB_NONE
;
5597 else if (!soap_tag_cmp(key
, "Transfer-Encoding"))
5598 { soap
->imode
&= ~SOAP_IO
;
5599 if (!soap_tag_cmp(val
, "chunked"))
5600 soap
->imode
|= SOAP_IO_CHUNK
;
5602 else if (!soap_tag_cmp(key
, "Connection"))
5603 { if (!soap_tag_cmp(val
, "keep-alive"))
5604 soap
->keep_alive
= -soap
->keep_alive
;
5605 else if (!soap_tag_cmp(val
, "close"))
5606 soap
->keep_alive
= 0;
5609 else if (!soap_tag_cmp(key
, "Authorization") || !soap_tag_cmp(key
, "Proxy-Authorization"))
5612 if (!soap_tag_cmp(val
, "NTLM*"))
5613 soap
->ntlm_challenge
= soap_strdup(soap
, val
+ 4);
5616 if (!soap_tag_cmp(val
, "Basic *"))
5619 soap_base642s(soap
, val
+ 6, soap
->tmpbuf
, sizeof(soap
->tmpbuf
) - 1, &n
);
5620 soap
->tmpbuf
[n
] = '\0';
5621 if ((s
= strchr(soap
->tmpbuf
, ':')))
5623 soap
->userid
= soap_strdup(soap
, soap
->tmpbuf
);
5624 soap
->passwd
= soap_strdup(soap
, s
+ 1);
5628 else if (!soap_tag_cmp(key
, "WWW-Authenticate") || !soap_tag_cmp(key
, "Proxy-Authenticate"))
5631 if (!soap_tag_cmp(val
, "NTLM*"))
5632 soap
->ntlm_challenge
= soap_strdup(soap
, val
+ 4);
5635 soap
->authrealm
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
+ 6, "realm"));
5637 else if (!soap_tag_cmp(key
, "Expect"))
5638 { if (!soap_tag_cmp(val
, "100-continue"))
5639 { if ((soap
->error
= soap
->fposthdr(soap
, "HTTP/1.1 100 Continue", NULL
))
5640 || (soap
->error
= soap
->fposthdr(soap
, NULL
, NULL
)))
5645 else if (!soap_tag_cmp(key
, "SOAPAction"))
5647 { soap
->action
= soap_strdup(soap
, val
+ 1);
5649 soap
->action
[strlen(soap
->action
) - 1] = '\0';
5652 soap
->action
= soap_strdup(soap
, val
);
5654 else if (!soap_tag_cmp(key
, "Location"))
5655 { strncpy(soap
->endpoint
, val
, sizeof(soap
->endpoint
));
5656 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
5658 else if (!soap_tag_cmp(key
, "X-Forwarded-For"))
5659 { soap
->proxy_from
= soap_strdup(soap
, val
);
5662 else if (!soap_tag_cmp(key
, "Cookie")
5663 || !soap_tag_cmp(key
, "Cookie2")
5664 || !soap_tag_cmp(key
, "Set-Cookie")
5665 || !soap_tag_cmp(key
, "Set-Cookie2"))
5666 { soap_getcookies(soap
, val
);
5674 /******************************************************************************/
5675 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5680 soap_get_header_attribute(struct soap
*soap
, const char *line
, const char *key
)
5681 { register const char *s
= line
;
5684 { register short flag
;
5685 s
= soap_decode_key(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
);
5686 flag
= soap_tag_cmp(soap
->tmpbuf
, key
);
5687 s
= soap_decode_val(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
);
5689 return soap
->tmpbuf
;
5697 /******************************************************************************/
5698 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5703 soap_decode_key(char *buf
, size_t len
, const char *val
)
5704 { return soap_decode(buf
, len
, val
, "=,;");
5709 /******************************************************************************/
5710 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5715 soap_decode_val(char *buf
, size_t len
, const char *val
)
5720 return soap_decode(buf
, len
, val
+ 1, ",;");
5725 /******************************************************************************/
5726 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5729 soap_decode(char *buf
, size_t len
, const char *val
, const char *sep
)
5733 for (s
= val
; *s
; s
++)
5734 if (*s
!= ' ' && *s
!= '\t' && !strchr(sep
, *s
))
5739 while (*s
&& *s
!= '"' && --i
)
5743 { while (*s
&& !soap_blank((soap_wchar
)*s
) && !strchr(sep
, *s
) && --i
)
5744 { if (*s
== '%' && s
[1] && s
[2])
5745 { *t
++ = ((s
[1] >= 'A' ? (s
[1] & 0x7) + 9 : s
[1] - '0') << 4)
5746 + (s
[2] >= 'A' ? (s
[2] & 0x7) + 9 : s
[2] - '0');
5753 buf
[len
- 1] = '\0'; /* appease */
5756 while (*s
&& !strchr(sep
, *s
))
5763 /******************************************************************************/
5767 http_error(struct soap
*soap
, int status
)
5768 { register const char *msg
= SOAP_STR_EOS
;
5771 msg
= soap_code_str(h_http_error_codes
, status
);
5780 /******************************************************************************/
5785 http_get(struct soap
*soap
)
5787 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "HTTP GET request\n"));
5788 return SOAP_GET_METHOD
;
5793 /******************************************************************************/
5797 http_405(struct soap
*soap
)
5804 /******************************************************************************/
5808 http_200(struct soap
*soap
)
5809 { return soap_send_empty_response(soap
, 200);
5814 /******************************************************************************/
5818 http_post(struct soap
*soap
, const char *endpoint
, const char *host
, int port
, const char *path
, const char *action
, size_t count
)
5819 { register const char *s
;
5821 switch (soap
->status
)
5837 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "HTTP %s to %s\n", s
, endpoint
? endpoint
: "(null)"));
5839 if (!endpoint
|| (soap_tag_cmp(endpoint
, "http:*") && soap_tag_cmp(endpoint
, "https:*") && strncmp(endpoint
, "httpg:", 6)) && strncmp(endpoint
, "_beam:", 6) && strncmp(endpoint
, "_local:", 7) && strncmp(endpoint
, "_btobex:", 8))
5841 if (!endpoint
|| (soap_tag_cmp(endpoint
, "http:*") && soap_tag_cmp(endpoint
, "https:*") && strncmp(endpoint
, "httpg:", 6)))
5844 if (strlen(endpoint
) + strlen(soap
->http_version
) > sizeof(soap
->tmpbuf
) - 80
5845 || strlen(host
) + strlen(soap
->http_version
) > sizeof(soap
->tmpbuf
) - 80)
5846 return soap
->error
= SOAP_EOM
; /* prevent overrun (note that 'host' and 'soap->host' are substrings of 'endpoint') */
5847 if (soap
->status
== SOAP_CONNECT
)
5849 #ifdef HAVE_SNPRINTF
5850 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%s %s:%d HTTP/%s", s
, soap
->host
, soap
->port
, soap
->http_version
);
5852 sprintf(soap
->tmpbuf
, "%s %s:%d HTTP/%s", s
, soap
->host
, soap
->port
, soap
->http_version
);
5855 else if (soap
->proxy_host
&& endpoint
)
5857 #ifdef HAVE_SNPRINTF
5858 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%s %s HTTP/%s", s
, endpoint
, soap
->http_version
);
5860 sprintf(soap
->tmpbuf
, "%s %s HTTP/%s", s
, endpoint
, soap
->http_version
);
5865 #ifdef HAVE_SNPRINTF
5866 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%s /%s HTTP/%s", s
, (*path
== '/' ? path
+ 1 : path
), soap
->http_version
);
5868 sprintf(soap
->tmpbuf
, "%s /%s HTTP/%s", s
, (*path
== '/' ? path
+ 1 : path
), soap
->http_version
);
5871 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5874 if ((soap
->ssl
&& port
!= 443) || (!soap
->ssl
&& port
!= 80))
5880 if (*host
!= '[' && strchr(host
, ':'))
5882 #ifdef HAVE_SNPRINTF
5883 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "[%s]:%d", host
, port
); /* RFC 2732 */
5885 sprintf(soap
->tmpbuf
, "[%s]:%d", host
, port
); /* RFC 2732 */
5891 #ifdef HAVE_SNPRINTF
5892 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%s:%d", host
, port
);
5894 sprintf(soap
->tmpbuf
, "%s:%d", host
, port
);
5901 if (*host
!= '[' && strchr(host
, ':'))
5903 #ifdef HAVE_SNPRINTF
5904 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "[%s]", host
); /* RFC 2732 */
5906 sprintf(soap
->tmpbuf
, "[%s]", host
); /* RFC 2732 */
5911 strcpy(soap
->tmpbuf
, host
);
5913 if ((err
= soap
->fposthdr(soap
, "Host", soap
->tmpbuf
)))
5915 if ((err
= soap
->fposthdr(soap
, "User-Agent", "gSOAP/2.8")))
5917 if ((err
= soap_puthttphdr(soap
, SOAP_OK
, count
)))
5921 if ((err
= soap
->fposthdr(soap
, "Accept-Encoding", "gzip, deflate")))
5923 if ((err
= soap
->fposthdr(soap
, "Accept-Encoding", "deflate")))
5929 if (soap
->ntlm_challenge
&& strlen(soap
->ntlm_challenge
) + 6 < sizeof(soap
->tmpbuf
))
5930 { if (*soap
->ntlm_challenge
)
5932 #ifdef HAVE_SNPRINTF
5933 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "NTLM %s", soap
->ntlm_challenge
);
5935 sprintf(soap
->tmpbuf
, "NTLM %s", soap
->ntlm_challenge
);
5937 if (soap
->proxy_host
)
5938 { if ((err
= soap
->fposthdr(soap
, "Proxy-Authorization", soap
->tmpbuf
)))
5941 else if ((err
= soap
->fposthdr(soap
, "Authorization", soap
->tmpbuf
)))
5948 if (soap
->userid
&& soap
->passwd
&& strlen(soap
->userid
) + strlen(soap
->passwd
) < 761)
5949 { strcpy(soap
->tmpbuf
, "Basic ");
5950 #ifdef HAVE_SNPRINTF
5951 soap_snprintf(soap
->tmpbuf
+ 262, sizeof(soap
->tmpbuf
) - 262, "%s:%s", soap
->userid
, soap
->passwd
);
5953 sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->userid
, soap
->passwd
);
5955 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
5956 if ((err
= soap
->fposthdr(soap
, "Authorization", soap
->tmpbuf
)))
5959 if (soap
->proxy_userid
&& soap
->proxy_passwd
&& strlen(soap
->proxy_userid
) + strlen(soap
->proxy_passwd
) < 761)
5960 { strcpy(soap
->tmpbuf
, "Basic ");
5961 #ifdef HAVE_SNPRINTF
5962 soap_snprintf(soap
->tmpbuf
+ 262, sizeof(soap
->tmpbuf
) - 262, "%s:%s", soap
->proxy_userid
, soap
->proxy_passwd
);
5964 sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->proxy_userid
, soap
->proxy_passwd
);
5966 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
5967 if ((err
= soap
->fposthdr(soap
, "Proxy-Authorization", soap
->tmpbuf
)))
5976 if (soap_putcookies(soap
, host
, path
, soap
->ssl
!= NULL
))
5979 if (soap_putcookies(soap
, host
, path
, 0))
5983 if (action
&& soap
->status
!= SOAP_GET
&& soap
->status
!= SOAP_DEL
)
5985 #ifdef HAVE_SNPRINTF
5986 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "\"%s\"", action
);
5988 sprintf(soap
->tmpbuf
, "\"%s\"", strlen(action
) < sizeof(soap
->tmpbuf
) - 3 ? action
: SOAP_STR_EOS
);
5990 if ((err
= soap
->fposthdr(soap
, "SOAPAction", soap
->tmpbuf
)))
5993 return soap
->fposthdr(soap
, NULL
, NULL
);
5998 /******************************************************************************/
6002 http_send_header(struct soap
*soap
, const char *s
)
6003 { register const char *t
;
6005 { t
= strchr(s
, '\n'); /* disallow \n in HTTP headers */
6008 if (soap_send_raw(soap
, s
, t
- s
))
6017 /******************************************************************************/
6021 http_post_header(struct soap
*soap
, const char *key
, const char *val
)
6023 { if (http_send_header(soap
, key
))
6025 if (val
&& (soap_send_raw(soap
, ": ", 2) || http_send_header(soap
, val
)))
6028 return soap_send_raw(soap
, "\r\n", 2);
6033 /******************************************************************************/
6037 http_response(struct soap
*soap
, int status
, size_t count
)
6044 httpOutputEnable(soap
->rpmreqid
);
6046 if (!soap
->http_version
|| strlen(soap
->http_version
) > 4)
6047 return soap
->error
= SOAP_EOM
;
6049 if (soap
->rpmreqid
|| soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* RPM behaves as if standalone */
6051 if (soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* standalone application (socket) or CGI (stdin/out)? */
6054 #ifdef HAVE_SNPRINTF
6055 soap_snprintf(http
, sizeof(http
), "HTTP/%s", soap
->http_version
);
6057 sprintf(http
, "HTTP/%s", soap
->http_version
);
6061 strcpy(http
, "Status:");
6062 if (!status
|| status
== SOAP_HTML
|| status
== SOAP_FILE
)
6063 { if (count
|| ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
))
6068 else if (status
< 200 || status
>= 600)
6069 { const char *s
= *soap_faultcode(soap
);
6070 if (status
>= SOAP_GET_METHOD
&& status
<= SOAP_HTTP_METHOD
)
6072 else if (soap
->version
== 2 && (!s
|| !strcmp(s
, "SOAP-ENV:Sender")))
6077 line
= http_error(soap
, code
);
6078 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "HTTP Status = %d %s\n", code
, line
));
6079 #ifdef HAVE_SNPRINTF
6080 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%s %d %s", http
, code
, line
);
6082 sprintf(soap
->tmpbuf
, "%s %d %s", http
, code
, line
);
6084 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
6089 #ifdef HAVE_SNPRINTF
6090 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "Basic realm=\"%s\"", (soap
->authrealm
&& strlen(soap
->authrealm
) < sizeof(soap
->tmpbuf
) - 14) ? soap
->authrealm
: "gSOAP Web Service");
6092 sprintf(soap
->tmpbuf
, "Basic realm=\"%s\"", (soap
->authrealm
&& strlen(soap
->authrealm
) < sizeof(soap
->tmpbuf
) - 14) ? soap
->authrealm
: "gSOAP Web Service");
6094 if ((err
= soap
->fposthdr(soap
, "WWW-Authenticate", soap
->tmpbuf
)))
6097 else if ((status
>= 301 && status
<= 303) || status
== 307)
6098 { if ((err
= soap
->fposthdr(soap
, "Location", soap
->endpoint
)))
6102 if ((err
= soap
->fposthdr(soap
, "Server", "gSOAP/2.8"))
6103 || (err
= soap_puthttphdr(soap
, status
, count
)))
6106 if (soap_putsetcookies(soap
))
6109 return soap
->fposthdr(soap
, NULL
, NULL
);
6114 /******************************************************************************/
6119 soap_response(struct soap
*soap
, int status
)
6120 { register size_t count
;
6121 if (!(soap
->omode
& (SOAP_ENC_XML
| SOAP_IO_STORE
/* this tests for chunking too */))
6122 && (status
== SOAP_HTML
|| status
== SOAP_FILE
))
6123 soap
->omode
= (soap
->omode
& ~SOAP_IO
) | SOAP_IO_STORE
;
6124 soap
->status
= status
;
6125 count
= soap_count_attachments(soap
);
6126 if (soap_begin_send(soap
))
6129 if ((soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& !(soap
->mode
& SOAP_ENC_XML
))
6130 { register int n
= soap
->mode
;
6131 soap
->mode
&= ~(SOAP_IO
| SOAP_ENC_ZLIB
);
6132 if ((n
& SOAP_IO
) != SOAP_IO_FLUSH
)
6133 soap
->mode
|= SOAP_IO_BUFFER
;
6134 if ((soap
->error
= soap
->fresponse(soap
, status
, count
)))
6137 if ((n
& SOAP_IO
) == SOAP_IO_CHUNK
)
6138 { if (soap_flush(soap
))
6149 /******************************************************************************/
6154 soap_url(struct soap
*soap
, const char *s
, const char *t
)
6155 { if (!t
|| (*t
!= '/' && *t
!= '?') || strlen(s
) + strlen(t
) >= sizeof(soap
->msgbuf
))
6157 strcpy(soap
->msgbuf
, s
);
6158 strcat(soap
->msgbuf
, t
);
6159 return soap
->msgbuf
;
6163 /******************************************************************************/
6168 soap_encode_url(const char *s
, char *t
, size_t len
)
6170 register size_t n
= len
;
6171 while ((c
= *s
++) && --n
> 0)
6172 { if (c
> ' ' && c
< 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c
))
6176 *t
++ = (c
>> 4) + (c
> 159 ? '7' : '0');
6178 *t
++ = c
+ (c
> 9 ? '7' : '0');
6189 /******************************************************************************/
6194 soap_encode_url_string(struct soap
*soap
, const char *s
)
6196 { size_t n
= 3*strlen(s
)+1;
6197 char *t
= (char*)soap_malloc(soap
, n
);
6199 { soap_encode_url(s
, t
, n
);
6203 return SOAP_STR_EOS
;
6207 /******************************************************************************\
6211 \******************************************************************************/
6214 /******************************************************************************/
6218 soap_cookie(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
6219 { struct soap_cookie
*p
;
6221 domain
= soap
->cookie_domain
;
6223 path
= soap
->cookie_path
;
6225 path
= SOAP_STR_EOS
;
6226 else if (*path
== '/')
6228 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Search cookie='%s' domain='%s' path='%s'\n", name
, domain
? domain
: "(null)", path
? path
: "(null)"));
6229 for (p
= soap
->cookies
; p
; p
= p
->next
)
6230 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Cookie in database: %s='%s' domain='%s' path='%s' env=%hd\n", p
->name
, p
->value
? p
->value
: "(null)", p
->domain
? p
->domain
: "(null)", p
->path
? p
->path
: "(null)", p
->env
));
6231 if (!strcmp(p
->name
, name
)
6234 && !strcmp(p
->domain
, domain
)
6235 && (!*p
->path
|| !strncmp(p
->path
, path
, strlen(p
->path
))))
6241 /******************************************************************************/
6245 soap_set_cookie(struct soap
*soap
, const char *name
, const char *value
, const char *domain
, const char *path
)
6246 { struct soap_cookie
**p
, *q
;
6249 domain
= soap
->cookie_domain
;
6251 path
= soap
->cookie_path
;
6253 path
= SOAP_STR_EOS
;
6254 else if (*path
== '/')
6256 q
= soap_cookie(soap
, name
, domain
, path
);
6257 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set %scookie: %s='%s' domain='%s' path='%s'\n", q
? SOAP_STR_EOS
: "new ", name
, value
? value
: "(null)", domain
? domain
: "(null)", path
? path
: "(null)"));
6259 { if ((q
= (struct soap_cookie
*)SOAP_MALLOC(soap
, sizeof(struct soap_cookie
))))
6260 { if ((q
->name
= (char*)SOAP_MALLOC(soap
, strlen(name
)+1)))
6261 strcpy(q
->name
, name
);
6270 for (p
= &soap
->cookies
, n
= soap
->cookie_max
; *p
&& n
; p
= &(*p
)->next
, n
--)
6271 if (!strcmp((*p
)->name
, name
) && (*p
)->path
&& path
&& strcmp((*p
)->path
, path
) < 0)
6278 { SOAP_FREE(soap
, q
->name
);
6288 { if (!value
|| strcmp(value
, q
->value
))
6289 { SOAP_FREE(soap
, q
->value
);
6293 if (value
&& *value
&& !q
->value
&& (q
->value
= (char*)SOAP_MALLOC(soap
, strlen(value
)+1)))
6294 strcpy(q
->value
, value
);
6296 { if (!domain
|| strcmp(domain
, q
->domain
))
6297 { SOAP_FREE(soap
, q
->domain
);
6301 if (domain
&& !q
->domain
&& (q
->domain
= (char*)SOAP_MALLOC(soap
, strlen(domain
)+1)))
6302 strcpy(q
->domain
, domain
);
6304 { if (!path
|| strncmp(path
, q
->path
, strlen(q
->path
)))
6305 { SOAP_FREE(soap
, q
->path
);
6309 if (path
&& !q
->path
&& (q
->path
= (char*)SOAP_MALLOC(soap
, strlen(path
)+1)))
6310 strcpy(q
->path
, path
);
6317 /******************************************************************************/
6321 soap_clr_cookie(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
6322 { struct soap_cookie
**p
, *q
;
6324 domain
= soap
->cookie_domain
;
6326 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error in clear cookie='%s': cookie domain not set\n", name
? name
: "(null)"));
6330 path
= soap
->cookie_path
;
6332 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error in clear cookie='%s': cookie path not set\n", name
? name
: "(null)"));
6337 for (p
= &soap
->cookies
, q
= *p
; q
; q
= *p
)
6338 { if (!strcmp(q
->name
, name
) && !strcmp(q
->domain
, domain
) && !strncmp(q
->path
, path
, strlen(q
->path
)))
6340 SOAP_FREE(soap
, q
->value
);
6342 SOAP_FREE(soap
, q
->domain
);
6344 SOAP_FREE(soap
, q
->path
);
6353 /******************************************************************************/
6357 soap_cookie_value(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
6358 { struct soap_cookie
*p
;
6359 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
6364 /******************************************************************************/
6368 soap_env_cookie_value(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
6369 { struct soap_cookie
*p
;
6370 if ((p
= soap_cookie(soap
, name
, domain
, path
)) && p
->env
)
6375 /******************************************************************************/
6379 soap_cookie_expire(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
6380 { struct soap_cookie
*p
;
6381 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
6386 /******************************************************************************/
6390 soap_set_cookie_expire(struct soap
*soap
, const char *name
, long expire
, const char *domain
, const char *path
)
6391 { struct soap_cookie
*p
;
6392 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", expire
, name
, domain
? domain
: "(null)", path
? path
: "(null)"));
6393 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
6394 { p
->maxage
= expire
;
6401 /******************************************************************************/
6405 soap_set_cookie_session(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
6406 { struct soap_cookie
*p
;
6407 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
6415 /******************************************************************************/
6419 soap_clr_cookie_session(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
6420 { struct soap_cookie
*p
;
6421 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
6429 /******************************************************************************/
6433 soap_putsetcookies(struct soap
*soap
)
6434 { struct soap_cookie
*p
;
6437 for (p
= soap
->cookies
; p
; p
= p
->next
)
6441 || (!p
->env
&& !soap
->ssl
== !p
->secure
)
6446 s
+= soap_encode_url(p
->name
, s
, tmp
-s
+4064);
6447 if (p
->value
&& *p
->value
)
6449 s
+= soap_encode_url(p
->value
, s
, tmp
-s
+4064);
6451 if (p
->domain
&& (int)strlen(p
->domain
) < tmp
-s
+4064)
6452 { strcpy(s
, ";Domain=");
6453 strcat(s
, p
->domain
);
6455 else if (soap
->cookie_domain
&& (int)strlen(soap
->cookie_domain
) < tmp
-s
+4064)
6456 { strcpy(s
, ";Domain=");
6457 strcat(s
, soap
->cookie_domain
);
6459 strcat(s
, ";Path=/");
6464 t
= soap
->cookie_path
;
6468 if ((int)strlen(t
) < tmp
-s
+4064)
6469 { if (strchr(t
, '%')) /* already URL encoded? */
6474 s
+= soap_encode_url(t
, s
, tmp
-s
+4064);
6477 if (p
->version
> 0 && s
-tmp
< 4060)
6479 #ifdef HAVE_SNPRINTF
6480 soap_snprintf(s
, 4096 - (s
-tmp
), ";Version=%u", p
->version
);
6482 sprintf(s
, ";Version=%u", p
->version
);
6486 if (p
->maxage
>= 0 && s
-tmp
< 4060)
6488 #ifdef HAVE_SNPRINTF
6489 soap_snprintf(s
, 4096 - (s
-tmp
), ";Max-Age=%ld", p
->maxage
);
6491 sprintf(s
, ";Max-Age=%ld", p
->maxage
);
6501 strcpy(s
, ";Secure");
6502 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set-Cookie: %s\n", tmp
));
6503 if ((soap
->error
= soap
->fposthdr(soap
, "Set-Cookie", tmp
)))
6510 /******************************************************************************/
6514 soap_putcookies(struct soap
*soap
, const char *domain
, const char *path
, int secure
)
6515 { struct soap_cookie
**p
, *q
;
6516 unsigned int version
= 0;
6517 time_t now
= time(NULL
);
6519 if (!domain
|| !path
)
6523 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending cookies for domain='%s' path='%s'\n", domain
, path
));
6527 { if (q
->expire
&& now
> q
->expire
)
6528 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Cookie %s expired\n", q
->name
));
6529 SOAP_FREE(soap
, q
->name
);
6531 SOAP_FREE(soap
, q
->value
);
6533 SOAP_FREE(soap
, q
->domain
);
6535 SOAP_FREE(soap
, q
->path
);
6541 char *t
= q
->domain
;
6546 { const char *r
= strchr(t
, ':');
6551 flag
= !strncmp(t
, domain
, n
);
6553 /* domain-level cookies, cannot compile when WITH_NOIO set */
6556 { struct hostent
*hostent
= gethostbyname((char*)domain
);
6558 { const char *r
= strchr(hostent
->h_name
, '.');
6560 r
= hostent
->h_name
;
6561 flag
= !strncmp(t
, r
, n
);
6566 && (!q
->path
|| !strncmp(q
->path
, path
, strlen(q
->path
)))
6567 && (!q
->secure
|| secure
))
6570 n
+= 3*strlen(q
->name
);
6571 if (q
->value
&& *q
->value
)
6572 n
+= 3*strlen(q
->value
) + 1;
6573 if (q
->path
&& *q
->path
)
6574 n
+= strlen(q
->path
) + 9;
6576 n
+= strlen(q
->domain
) + 11;
6577 if (tmp
- s
+ n
> sizeof(tmp
))
6579 return SOAP_OK
; /* HTTP header size overflow */
6580 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Cookie: %s\n", tmp
));
6581 if ((soap
->error
= soap
->fposthdr(soap
, "Cookie", tmp
)))
6589 if (q
->version
!= version
&& s
-tmp
< 4060)
6591 #ifdef HAVE_SNPRINTF
6592 soap_snprintf(s
, 4096 - (s
-tmp
), "$Version=%u;", q
->version
);
6594 sprintf(s
, "$Version=%u;", q
->version
);
6596 version
= q
->version
;
6600 s
+= soap_encode_url(q
->name
, s
, tmp
+sizeof(tmp
)-s
-16);
6601 if (q
->value
&& *q
->value
)
6603 s
+= soap_encode_url(q
->value
, s
, tmp
+sizeof(tmp
)-s
-16);
6605 if (q
->path
&& (s
-tmp
) + strlen(q
->path
) < 4060)
6607 #ifdef HAVE_SNPRINTF
6608 soap_snprintf(s
, 4096 - (s
-tmp
), ";$Path=\"/%s\"", (*q
->path
== '/' ? q
->path
+ 1 : q
->path
));
6610 sprintf(s
, ";$Path=\"/%s\"", (*q
->path
== '/' ? q
->path
+ 1 : q
->path
));
6614 if (q
->domain
&& (s
-tmp
) + strlen(q
->domain
) < 4060)
6616 #ifdef HAVE_SNPRINTF
6617 soap_snprintf(s
, 4096 - (s
-tmp
), ";$Domain=\"%s\"", q
->domain
);
6619 sprintf(s
, ";$Domain=\"%s\"", q
->domain
);
6628 if ((soap
->error
= soap
->fposthdr(soap
, "Cookie", tmp
)))
6633 /******************************************************************************/
6637 soap_getcookies(struct soap
*soap
, const char *val
)
6638 { struct soap_cookie
*p
= NULL
, *q
;
6640 char *t
, tmp
[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6641 char *domain
= NULL
;
6643 unsigned int version
= 0;
6644 time_t now
= time(NULL
);
6649 { s
= soap_decode_key(tmp
, sizeof(tmp
), s
);
6650 if (!soap_tag_cmp(tmp
, "$Version"))
6651 { if ((s
= soap_decode_val(tmp
, sizeof(tmp
), s
)))
6653 p
->version
= (int)soap_strtol(tmp
, NULL
, 10);
6655 version
= (int)soap_strtol(tmp
, NULL
, 10);
6658 else if (!soap_tag_cmp(tmp
, "$Path"))
6659 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6661 { if ((t
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6668 SOAP_FREE(soap
, p
->path
);
6673 SOAP_FREE(soap
, path
);
6677 else if (!soap_tag_cmp(tmp
, "$Domain"))
6678 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6680 { if ((t
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6687 SOAP_FREE(soap
, p
->domain
);
6692 SOAP_FREE(soap
, domain
);
6696 else if (p
&& !soap_tag_cmp(tmp
, "Path"))
6698 SOAP_FREE(soap
, p
->path
);
6699 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6701 { if ((p
->path
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6702 strcpy(p
->path
, tmp
);
6707 else if (p
&& !soap_tag_cmp(tmp
, "Domain"))
6709 SOAP_FREE(soap
, p
->domain
);
6710 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6712 { if ((p
->domain
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6713 strcpy(p
->domain
, tmp
);
6718 else if (p
&& !soap_tag_cmp(tmp
, "Version"))
6719 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6720 p
->version
= (unsigned int)soap_strtoul(tmp
, NULL
, 10);
6722 else if (p
&& !soap_tag_cmp(tmp
, "Max-Age"))
6723 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6724 p
->expire
= now
+ soap_strtol(tmp
, NULL
, 10);
6726 else if (p
&& !soap_tag_cmp(tmp
, "Expires"))
6729 static const char mns
[] = "anebarprayunulugepctovec";
6730 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6731 if (strlen(tmp
) > 20)
6732 { memset((void*)&T
, 0, sizeof(T
));
6736 T
.tm_mday
= (int)soap_strtol(a
, NULL
, 10);
6739 T
.tm_mon
= (int)(strstr(mns
, a
) - mns
) / 2;
6742 T
.tm_year
= 100 + (int)soap_strtol(a
, NULL
, 10);
6745 T
.tm_hour
= (int)soap_strtol(a
, NULL
, 10);
6748 T
.tm_min
= (int)soap_strtol(a
, NULL
, 10);
6751 T
.tm_sec
= (int)soap_strtol(a
, NULL
, 10);
6752 p
->expire
= soap_timegm(&T
);
6755 else if (p
&& !soap_tag_cmp(tmp
, "Secure"))
6759 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p
->name
, p
->value
? p
->value
: "(null)", p
->domain
? p
->domain
: "(null)", p
->path
? p
->path
: "(null)", p
->expire
, p
->secure
));
6760 if ((q
= soap_set_cookie(soap
, p
->name
, p
->value
, p
->domain
, p
->path
)))
6761 { q
->version
= p
->version
;
6762 q
->expire
= p
->expire
;
6763 q
->secure
= p
->secure
;
6767 SOAP_FREE(soap
, p
->name
);
6769 SOAP_FREE(soap
, p
->value
);
6771 SOAP_FREE(soap
, p
->domain
);
6773 SOAP_FREE(soap
, p
->path
);
6776 if ((p
= (struct soap_cookie
*)SOAP_MALLOC(soap
, sizeof(struct soap_cookie
))))
6777 { p
->name
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1);
6778 strcpy(p
->name
, tmp
);
6779 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6781 { p
->value
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1);
6782 strcpy(p
->value
, tmp
);
6788 else if (*soap
->host
)
6789 { p
->domain
= (char*)SOAP_MALLOC(soap
, strlen(soap
->host
)+1);
6790 strcpy(p
->domain
, soap
->host
);
6796 else if (soap
->path
&& *soap
->path
)
6797 { p
->path
= (char*)SOAP_MALLOC(soap
, strlen(soap
->path
)+1);
6798 strcpy(p
->path
, soap
->path
);
6801 { p
->path
= (char*)SOAP_MALLOC(soap
, 2);
6802 strcpy(p
->path
, "/");
6806 p
->version
= version
;
6811 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p
->name
, p
->value
? p
->value
: "(null)", p
->domain
? p
->domain
: "(null)", p
->path
? p
->path
: "(null)", p
->expire
, p
->secure
));
6812 if ((q
= soap_set_cookie(soap
, p
->name
, p
->value
, p
->domain
, p
->path
)))
6813 { q
->version
= p
->version
;
6814 q
->expire
= p
->expire
;
6815 q
->secure
= p
->secure
;
6819 SOAP_FREE(soap
, p
->name
);
6821 SOAP_FREE(soap
, p
->value
);
6823 SOAP_FREE(soap
, p
->domain
);
6825 SOAP_FREE(soap
, p
->path
);
6829 SOAP_FREE(soap
, domain
);
6831 SOAP_FREE(soap
, path
);
6834 /******************************************************************************/
6838 soap_getenv_cookies(struct soap
*soap
)
6839 { struct soap_cookie
*p
;
6841 char key
[4096], val
[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6842 if (!(s
= getenv("HTTP_COOKIE")))
6845 { s
= soap_decode_key(key
, sizeof(key
), s
);
6846 s
= soap_decode_val(val
, sizeof(val
), s
);
6847 p
= soap_set_cookie(soap
, key
, val
, NULL
, NULL
);
6854 /******************************************************************************/
6858 soap_copy_cookies(struct soap
*copy
, const struct soap
*soap
)
6859 { struct soap_cookie
*p
, **q
, *r
;
6861 for (p
= soap
->cookies
; p
; p
= p
->next
)
6862 { if (!(*q
= (struct soap_cookie
*)SOAP_MALLOC(copy
, sizeof(struct soap_cookie
))))
6866 { if (((*q
)->name
= (char*)SOAP_MALLOC(copy
, strlen(p
->name
)+1)))
6867 strcpy((*q
)->name
, p
->name
);
6870 { if (((*q
)->value
= (char*)SOAP_MALLOC(copy
, strlen(p
->value
)+1)))
6871 strcpy((*q
)->value
, p
->value
);
6874 { if (((*q
)->domain
= (char*)SOAP_MALLOC(copy
, strlen(p
->domain
)+1)))
6875 strcpy((*q
)->domain
, p
->domain
);
6878 { if (((*q
)->path
= (char*)SOAP_MALLOC(copy
, strlen(p
->path
)+1)))
6879 strcpy((*q
)->path
, p
->path
);
6887 /******************************************************************************/
6891 soap_free_cookies(struct soap
*soap
)
6892 { struct soap_cookie
*p
;
6893 for (p
= soap
->cookies
; p
; p
= soap
->cookies
)
6894 { soap
->cookies
= p
->next
;
6895 SOAP_FREE(soap
, p
->name
);
6897 SOAP_FREE(soap
, p
->value
);
6899 SOAP_FREE(soap
, p
->domain
);
6901 SOAP_FREE(soap
, p
->path
);
6906 /******************************************************************************/
6907 #endif /* WITH_COOKIES */
6909 /******************************************************************************/
6910 #ifndef WITH_NOIDREF
6915 soap_hash(register const char *s
)
6916 { register size_t h
= 0;
6919 return h
% SOAP_IDHASH
;
6924 /******************************************************************************/
6925 #ifndef WITH_NOIDREF
6928 soap_init_pht(struct soap
*soap
)
6932 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
6933 soap
->pht
[i
] = NULL
;
6938 /******************************************************************************/
6943 soap_versioning(soap_new
)(soap_mode imode
, soap_mode omode
)
6944 { struct soap
*soap
= (struct soap
*)malloc(sizeof(struct soap
));
6946 soap_versioning(soap_init
)(soap
, imode
, omode
);
6951 /******************************************************************************/
6956 soap_free(struct soap
*soap
)
6962 /******************************************************************************/
6967 soap_del(struct soap
*soap
)
6972 /******************************************************************************/
6973 #ifndef WITH_NOIDREF
6976 soap_free_pht(struct soap
*soap
)
6977 { register struct soap_pblk
*pb
, *next
;
6979 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free pointer hashtable\n"));
6980 for (pb
= soap
->pblk
; pb
; pb
= next
)
6982 SOAP_FREE(soap
, pb
);
6986 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
6987 soap
->pht
[i
] = NULL
;
6992 /******************************************************************************/
6993 #ifndef WITH_NOIDREF
6998 soap_embed(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, const char *tag
, int type
)
7000 struct soap_plist
*pp
;
7002 if (soap
->version
== 2)
7005 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, type
, &pp
);
7007 i
= soap_pointer_lookup(soap
, p
, type
, &pp
);
7009 { if (soap_is_embedded(soap
, pp
)
7010 || soap_is_single(soap
, pp
))
7012 soap_set_embedded(soap
, pp
);
7019 /******************************************************************************/
7020 #ifndef WITH_NOIDREF
7025 soap_pointer_lookup(struct soap
*soap
, const void *p
, int type
, struct soap_plist
**ppp
)
7026 { register struct soap_plist
*pp
;
7029 { for (pp
= soap
->pht
[soap_hash_ptr(p
)]; pp
; pp
= pp
->next
)
7030 { if (pp
->ptr
== p
&& pp
->type
== type
)
7032 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup location=%p type=%d id=%d\n", p
, type
, pp
->id
));
7037 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup location=%p type=%d: not found\n", p
, type
));
7043 /******************************************************************************/
7044 #ifndef WITH_NOIDREF
7049 soap_pointer_enter(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int type
, struct soap_plist
**ppp
)
7050 { register size_t h
;
7051 register struct soap_plist
*pp
;
7053 if (!soap
->pblk
|| soap
->pidx
>= SOAP_PTRBLK
)
7054 { register struct soap_pblk
*pb
= (struct soap_pblk
*)SOAP_MALLOC(soap
, sizeof(struct soap_pblk
));
7056 { soap
->error
= SOAP_EOM
;
7059 pb
->next
= soap
->pblk
;
7063 *ppp
= pp
= &soap
->pblk
->plist
[soap
->pidx
++];
7065 h
= soap_hash_ptr(a
->__ptr
);
7067 h
= soap_hash_ptr(p
);
7068 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p
, a
? a
->__ptr
: NULL
, a
? a
->__size
: 0, n
, type
, soap
->idnum
+1));
7069 pp
->next
= soap
->pht
[h
];
7076 pp
->id
= ++soap
->idnum
;
7082 /******************************************************************************/
7083 #ifndef WITH_NOIDREF
7088 soap_array_pointer_lookup(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int type
, struct soap_plist
**ppp
)
7089 { register struct soap_plist
*pp
;
7091 if (!p
|| !a
->__ptr
)
7093 for (pp
= soap
->pht
[soap_hash_ptr(a
->__ptr
)]; pp
; pp
= pp
->next
)
7094 { if (pp
->type
== type
&& pp
->array
&& pp
->array
->__ptr
== a
->__ptr
)
7096 for (i
= 0; i
< n
; i
++)
7097 if (((const int*)&pp
->array
->__size
)[i
] != ((const int*)&a
->__size
)[i
])
7101 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array lookup location=%p type=%d id=%d\n", a
->__ptr
, type
, pp
->id
));
7106 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array lookup location=%p type=%d: not found\n", a
->__ptr
, type
));
7112 /******************************************************************************/
7117 soap_begin_count(struct soap
*soap
)
7118 { soap_free_ns(soap
);
7120 if ((soap
->mode
& SOAP_ENC_DIME
) || (soap
->omode
& SOAP_ENC_DIME
))
7121 soap
->mode
= soap
->omode
| SOAP_IO_LENGTH
| SOAP_ENC_DIME
;
7124 { soap
->mode
= soap
->omode
;
7125 if ((soap
->mode
& SOAP_IO_UDP
))
7126 soap
->mode
|= SOAP_ENC_XML
;
7127 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
7128 || (((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_ENC_XML
))
7130 && !soap
->fpreparesend
7133 soap
->mode
&= ~SOAP_IO_LENGTH
;
7135 soap
->mode
|= SOAP_IO_LENGTH
;
7138 if ((soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
)
7139 { if (!(soap
->mode
& SOAP_ENC_DIME
))
7140 soap
->mode
&= ~SOAP_IO_LENGTH
;
7141 if (soap
->mode
& SOAP_ENC_XML
)
7142 soap
->mode
|= SOAP_IO_BUFFER
;
7144 soap
->mode
|= SOAP_IO_STORE
;
7148 if ((soap
->mode
& SOAP_ENC_MTOM
) && (soap
->mode
& SOAP_ENC_DIME
))
7149 soap
->mode
|= SOAP_ENC_MIME
;
7150 else if (!(soap
->mode
& SOAP_ENC_MIME
))
7151 soap
->mode
&= ~SOAP_ENC_MTOM
;
7152 if (soap
->mode
& SOAP_ENC_MIME
)
7153 soap_select_mime_boundary(soap
);
7154 soap
->dime
.list
= soap
->dime
.last
; /* keep track of last DIME attachment */
7160 soap
->mustUnderstand
= 0;
7162 soap
->part
= SOAP_BEGIN
;
7166 soap_clr_attr(soap
);
7167 soap_set_local_namespaces(soap
);
7169 soap
->dime
.count
= 0; /* count # of attachments */
7170 soap
->dime
.size
= 0; /* accumulate total size of attachments */
7171 if (soap
->fprepareinitsend
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& (soap
->error
= soap
->fprepareinitsend(soap
)))
7174 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap
->socket
, (unsigned int)soap
->mode
, (unsigned long)soap
->count
));
7179 /******************************************************************************/
7184 soap_end_count(struct soap
*soap
)
7185 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of count phase\n"));
7187 if ((soap
->mode
& SOAP_IO_LENGTH
))
7188 { if (soap
->fpreparefinalsend
&& (soap
->error
= soap
->fpreparefinalsend(soap
)))
7196 /******************************************************************************/
7201 soap_begin_send(struct soap
*soap
)
7202 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Initializing for output to socket=%d/fd=%d\n", soap
->socket
, soap
->sendfd
));
7204 soap
->error
= SOAP_OK
;
7205 soap
->mode
= soap
->omode
| (soap
->mode
& (SOAP_IO_LENGTH
| SOAP_ENC_DIME
));
7207 if ((soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
)
7208 { if (soap
->mode
& SOAP_ENC_XML
)
7209 soap
->mode
|= SOAP_IO_BUFFER
;
7211 soap
->mode
|= SOAP_IO_STORE
;
7215 if ((soap
->mode
& SOAP_IO_UDP
))
7216 { soap
->mode
|= SOAP_ENC_XML
;
7217 if (soap
->count
> SOAP_BUFLEN
)
7218 return soap
->error
= SOAP_UDP_ERROR
;
7221 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
&& soap_valid_socket(soap
->socket
))
7222 { if (soap
->count
|| (soap
->mode
& SOAP_IO_LENGTH
) || (soap
->mode
& SOAP_ENC_XML
))
7223 soap
->mode
|= SOAP_IO_BUFFER
;
7225 soap
->mode
|= SOAP_IO_STORE
;
7227 soap
->mode
&= ~SOAP_IO_LENGTH
;
7228 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
7229 if (soap_new_block(soap
) == NULL
)
7231 if (!(soap
->mode
& SOAP_IO_KEEPALIVE
))
7232 soap
->keep_alive
= 0;
7234 if ((soap
->mode
& SOAP_ENC_MTOM
) && (soap
->mode
& SOAP_ENC_DIME
))
7235 { soap
->mode
|= SOAP_ENC_MIME
;
7236 soap
->mode
&= ~SOAP_ENC_DIME
;
7238 else if (!(soap
->mode
& SOAP_ENC_MIME
))
7239 soap
->mode
&= ~SOAP_ENC_MTOM
;
7240 if (soap
->mode
& SOAP_ENC_MIME
)
7241 soap_select_mime_boundary(soap
);
7244 #ifndef WITH_FASTCGI
7245 if (!soap_valid_socket(soap
->socket
) && !soap
->os
) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
7247 setmode(soap
->sendfd
, _O_BINARY
);
7249 _setmode(soap
->sendfd
, _O_BINARY
);
7255 if (soap
->mode
& SOAP_IO
)
7259 soap
->chunksize
= 0;
7263 soap
->mustUnderstand
= 0;
7267 soap_clr_attr(soap
);
7268 soap_set_local_namespaces(soap
);
7270 soap
->z_ratio_out
= 1.0;
7271 if ((soap
->mode
& SOAP_ENC_ZLIB
) && soap
->zlib_state
!= SOAP_ZLIB_DEFLATE
)
7273 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
7274 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
7275 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
7277 if (soap
->zlib_out
!= SOAP_ZLIB_DEFLATE
)
7278 { memcpy(soap
->z_buf
, "\37\213\10\0\0\0\0\0\0\377", 10);
7279 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
+ 10;
7280 soap
->d_stream
->avail_out
= SOAP_BUFLEN
- 10;
7281 soap
->z_crc
= crc32(0L, NULL
, 0);
7282 soap
->zlib_out
= SOAP_ZLIB_GZIP
;
7284 *((Byte
*)soap
->z_buf
+ 2) = 0xff;
7285 if (deflateInit2(soap
->d_stream
, soap
->z_level
, Z_DEFLATED
, -MAX_WBITS
, 8, Z_DEFAULT_STRATEGY
) != Z_OK
)
7286 return soap
->error
= SOAP_ZLIB_ERROR
;
7290 if (deflateInit(soap
->d_stream
, soap
->z_level
) != Z_OK
)
7291 return soap
->error
= SOAP_ZLIB_ERROR
;
7293 { if (deflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
7294 return soap
->error
= SOAP_ZLIB_ERROR
;
7296 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflate initialized\n"));
7297 soap
->zlib_state
= SOAP_ZLIB_DEFLATE
;
7304 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap
->socket
, soap
->mode
, (unsigned long)soap
->count
));
7305 soap
->part
= SOAP_BEGIN
;
7307 if (soap
->fprepareinitsend
&& (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
&& (soap
->error
= soap
->fprepareinitsend(soap
)))
7314 /******************************************************************************/
7315 #ifndef WITH_NOIDREF
7320 soap_embedded(struct soap
*soap
, const void *p
, int t
)
7321 { struct soap_plist
*pp
;
7322 if (soap_pointer_lookup(soap
, p
, t
, &pp
))
7325 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded %p type=%d mark set to 1\n", p
, t
));
7331 /******************************************************************************/
7332 #ifndef WITH_NOIDREF
7337 soap_reference(struct soap
*soap
, const void *p
, int t
)
7338 { struct soap_plist
*pp
;
7339 if (!p
|| (!soap
->encodingStyle
&& !(soap
->omode
& (SOAP_ENC_DIME
|SOAP_ENC_MIME
|SOAP_ENC_MTOM
|SOAP_XML_GRAPH
))) || (soap
->omode
& SOAP_XML_TREE
))
7341 if (soap_pointer_lookup(soap
, p
, t
, &pp
))
7342 { if (pp
->mark1
== 0)
7347 else if (!soap_pointer_enter(soap
, p
, NULL
, 0, t
, &pp
))
7349 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reference %p type=%d (%d %d)\n", p
, t
, (int)pp
->mark1
, (int)pp
->mark2
));
7355 /******************************************************************************/
7356 #ifndef WITH_NOIDREF
7361 soap_array_reference(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int t
)
7362 { struct soap_plist
*pp
;
7363 if (!p
|| !a
->__ptr
|| (!soap
->encodingStyle
&& !(soap
->omode
& (SOAP_ENC_DIME
|SOAP_ENC_MIME
|SOAP_ENC_MTOM
|SOAP_XML_GRAPH
))) || (soap
->omode
& SOAP_XML_TREE
))
7365 if (soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
))
7366 { if (pp
->mark1
== 0)
7371 else if (!soap_pointer_enter(soap
, p
, a
, n
, t
, &pp
))
7373 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p
, a
->__ptr
, n
, t
, (int)pp
->mark1
, (int)pp
->mark2
));
7379 /******************************************************************************/
7380 #ifndef WITH_NOIDREF
7385 soap_embedded_id(struct soap
*soap
, int id
, const void *p
, int t
)
7386 { struct soap_plist
*pp
= NULL
;
7387 if (!id
|| (!soap
->encodingStyle
&& !(soap
->omode
& SOAP_XML_GRAPH
)) || (soap
->omode
& SOAP_XML_TREE
))
7389 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded_id %p type=%d id=%d\n", p
, t
, id
));
7390 if (soap
->version
== 1 && soap
->part
!= SOAP_IN_HEADER
)
7392 { id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
7394 { if (soap
->mode
& SOAP_IO_LENGTH
)
7398 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id
, p
, t
, (int)pp
->mark1
, (int)pp
->mark2
));
7405 id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
7406 else if (id
&& !soap_pointer_lookup(soap
, p
, t
, &pp
))
7409 { if (soap
->mode
& SOAP_IO_LENGTH
)
7413 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id
, p
, t
, (int)pp
->mark1
, (int)pp
->mark2
));
7420 /******************************************************************************/
7421 #ifndef WITH_NOIDREF
7426 soap_is_embedded(struct soap
*soap
, struct soap_plist
*pp
)
7429 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Is embedded? %d %d\n", (int)pp
->mark1
, (int)pp
->mark2
));
7430 if (soap
->version
== 1 && soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
) && soap
->part
!= SOAP_IN_HEADER
)
7431 { if (soap
->mode
& SOAP_IO_LENGTH
)
7432 return pp
->mark1
!= 0;
7433 return pp
->mark2
!= 0;
7435 if (soap
->mode
& SOAP_IO_LENGTH
)
7436 return pp
->mark1
== 1;
7437 return pp
->mark2
== 1;
7442 /******************************************************************************/
7443 #ifndef WITH_NOIDREF
7448 soap_is_single(struct soap
*soap
, struct soap_plist
*pp
)
7449 { if (soap
->part
== SOAP_IN_HEADER
)
7453 if (soap
->mode
& SOAP_IO_LENGTH
)
7454 return pp
->mark1
== 0;
7455 return pp
->mark2
== 0;
7460 /******************************************************************************/
7461 #ifndef WITH_NOIDREF
7466 soap_set_embedded(struct soap
*soap
, struct soap_plist
*pp
)
7469 if (soap
->mode
& SOAP_IO_LENGTH
)
7477 /******************************************************************************/
7483 soap_attachment(struct soap
*soap
, const char *tag
, int id
, const void *p
, const struct soap_array
*a
, const char *aid
, const char *atype
, const char *aoptions
, int n
, const char *type
, int t
)
7485 #ifndef WITH_NOIDREF
7486 struct soap_plist
*pp
;
7488 if (!p
|| !a
->__ptr
|| (!aid
&& !atype
))
7489 return soap_element_id(soap
, tag
, id
, p
, a
, n
, type
, t
);
7490 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag
, aid
? aid
: SOAP_STR_EOS
, id
, atype
? atype
: SOAP_STR_EOS
));
7491 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
7493 { i
= soap_pointer_enter(soap
, p
, a
, n
, t
, &pp
);
7495 { soap
->error
= SOAP_EOM
;
7503 #ifdef HAVE_SNPRINTF
7504 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), soap
->dime_id_format
, id
);
7506 sprintf(soap
->tmpbuf
, soap
->dime_id_format
, id
);
7508 aid
= soap_strdup(soap
, soap
->tmpbuf
);
7510 /* Add MTOM xop:Include element when necessary */
7511 /* TODO: this code to be obsoleted with new import/xop.h conventions */
7512 if ((soap
->mode
& SOAP_ENC_MTOM
) && strcmp(tag
, "xop:Include"))
7513 { if (soap_element_begin_out(soap
, tag
, 0, type
)
7514 || soap_element_href(soap
, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid
)
7515 || soap_element_end_out(soap
, tag
))
7518 else if (soap_element_href(soap
, tag
, 0, "href", aid
))
7520 if (soap
->mode
& SOAP_IO_LENGTH
)
7521 { if (pp
->mark1
!= 3)
7522 { struct soap_multipart
*content
;
7523 if (soap
->mode
& SOAP_ENC_MTOM
)
7524 content
= soap_new_multipart(soap
, &soap
->mime
.first
, &soap
->mime
.last
, (char*)a
->__ptr
, a
->__size
);
7526 content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, (char*)a
->__ptr
, a
->__size
);
7528 { soap
->error
= SOAP_EOM
;
7531 if (!strncmp(aid
, "cid:", 4)) /* RFC 2111 */
7532 { if (soap
->mode
& SOAP_ENC_MTOM
)
7533 { char *s
= (char*)soap_malloc(soap
, strlen(aid
) - 1);
7536 strcpy(s
+ 1, aid
+ 4);
7542 content
->id
= aid
+ 4;
7546 content
->type
= atype
;
7547 content
->options
= aoptions
;
7548 content
->encoding
= SOAP_MIME_BINARY
;
7560 /******************************************************************************/
7561 #ifndef WITH_NOIDREF
7564 soap_init_iht(struct soap
*soap
)
7566 for (i
= 0; i
< SOAP_IDHASH
; i
++)
7567 soap
->iht
[i
] = NULL
;
7572 /******************************************************************************/
7573 #ifndef WITH_NOIDREF
7576 soap_free_iht(struct soap
*soap
)
7578 register struct soap_ilist
*ip
= NULL
, *p
= NULL
;
7579 register struct soap_flist
*fp
= NULL
, *fq
= NULL
;
7580 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free ID hashtable\n"));
7581 for (i
= 0; i
< SOAP_IDHASH
; i
++)
7582 { for (ip
= soap
->iht
[i
]; ip
; ip
= p
)
7583 { for (fp
= ip
->flist
; fp
; fp
= fq
)
7585 SOAP_FREE(soap
, fp
);
7588 SOAP_FREE(soap
, ip
);
7590 soap
->iht
[i
] = NULL
;
7596 /******************************************************************************/
7597 #ifndef WITH_NOIDREF
7602 soap_lookup(struct soap
*soap
, const char *id
)
7603 { register struct soap_ilist
*ip
= NULL
;
7604 for (ip
= soap
->iht
[soap_hash(id
)]; ip
; ip
= ip
->next
)
7605 if (!strcmp(ip
->id
, id
))
7612 /******************************************************************************/
7613 #ifndef WITH_NOIDREF
7618 soap_enter(struct soap
*soap
, const char *id
)
7619 { register size_t h
;
7620 register struct soap_ilist
*ip
;
7621 ip
= (struct soap_ilist
*)SOAP_MALLOC(soap
, sizeof(struct soap_ilist
) + strlen(id
));
7623 { strcpy((char*)ip
->id
, id
);
7624 h
= soap_hash(id
); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
7625 ip
->next
= soap
->iht
[h
];
7633 /******************************************************************************/
7638 soap_malloc(struct soap
*soap
, size_t n
)
7641 return (void*)SOAP_NON_NULL
;
7643 return SOAP_MALLOC(soap
, n
);
7645 p
= (char*)soap
->fmalloc(soap
, n
);
7647 { n
+= sizeof(short);
7648 n
+= (-(long)n
) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
7649 if (!(p
= (char*)SOAP_MALLOC(soap
, n
+ sizeof(void*) + sizeof(size_t))))
7650 { soap
->error
= SOAP_EOM
;
7653 /* set the canary to detect corruption */
7654 *(unsigned short*)(p
+ n
- sizeof(unsigned short)) = (unsigned short)SOAP_CANARY
;
7655 /* keep chain of alloced cells for destruction */
7656 *(void**)(p
+ n
) = soap
->alist
;
7657 *(size_t*)(p
+ n
+ sizeof(void*)) = n
;
7658 soap
->alist
= p
+ n
;
7665 /******************************************************************************/
7666 #ifdef SOAP_MEM_DEBUG
7668 soap_init_mht(struct soap
*soap
)
7670 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
7671 soap
->mht
[i
] = NULL
;
7675 /******************************************************************************/
7676 #ifdef SOAP_MEM_DEBUG
7678 soap_free_mht(struct soap
*soap
)
7680 register struct soap_mlist
*mp
, *mq
;
7681 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
7682 { for (mp
= soap
->mht
[i
]; mp
; mp
= mq
)
7685 fprintf(stderr
, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp
->file
, mp
->line
, mp
->ptr
);
7688 soap
->mht
[i
] = NULL
;
7693 /******************************************************************************/
7694 #ifdef SOAP_MEM_DEBUG
7698 soap_track_malloc(struct soap
*soap
, const char *file
, int line
, size_t size
)
7699 { register void *p
= malloc(size
);
7701 { register size_t h
= soap_hash_ptr(p
);
7702 register struct soap_mlist
*mp
= (struct soap_mlist
*)malloc(sizeof(struct soap_mlist
));
7703 if (soap
->fdebug
[SOAP_INDEX_TEST
])
7704 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%s(%d): malloc(%lu) = %p\n", file
, line
, (unsigned long)size
, p
));
7706 mp
->next
= soap
->mht
[h
];
7717 /******************************************************************************/
7718 #ifdef SOAP_MEM_DEBUG
7722 soap_track_free(struct soap
*soap
, const char *file
, int line
, void *p
)
7723 { register size_t h
= soap_hash_ptr(p
);
7724 register struct soap_mlist
*mp
;
7725 for (mp
= soap
->mht
[h
]; mp
; mp
= mp
->next
)
7731 if (soap
->fdebug
[SOAP_INDEX_TEST
])
7732 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%s(%d): free(%p)\n", file
, line
, p
));
7737 fprintf(stderr
, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file
, line
, p
, mp
->file
, mp
->line
);
7740 fprintf(stderr
, "%s(%d): free(%p) pointer not malloced\n", file
, line
, p
);
7744 /******************************************************************************/
7745 #ifdef SOAP_MEM_DEBUG
7747 soap_track_unlink(struct soap
*soap
, const void *p
)
7748 { register size_t h
= soap_hash_ptr(p
);
7749 register struct soap_mlist
*mp
;
7750 for (mp
= soap
->mht
[h
]; mp
; mp
= mp
->next
)
7758 /******************************************************************************/
7763 soap_dealloc(struct soap
*soap
, void *p
)
7764 { if (soap_check_state(soap
))
7767 { register char **q
;
7768 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7770 if (*(unsigned short*)(char*)(*q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7772 #ifdef SOAP_MEM_DEBUG
7773 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7775 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7776 DBGHEX(TEST
, *q
- 200, 200);
7777 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7778 soap
->error
= SOAP_MOE
;
7781 if (p
== (void*)(*q
- *(size_t*)(*q
+ sizeof(void*))))
7782 { *q
= **(char***)q
;
7783 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Freed data at %p\n", p
));
7788 soap_delete(soap
, p
);
7792 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free all soap_malloc() data\n"));
7794 { q
= (char*)soap
->alist
;
7795 if (*(unsigned short*)(char*)(q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7797 #ifdef SOAP_MEM_DEBUG
7798 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7800 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7801 DBGHEX(TEST
, q
- 200, 200);
7802 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7803 soap
->error
= SOAP_MOE
;
7806 soap
->alist
= *(void**)q
;
7807 q
-= *(size_t*)(q
+ sizeof(void*));
7810 /* we must assume these were deallocated: */
7811 soap
->http_content
= NULL
;
7812 soap
->action
= NULL
;
7814 soap
->header
= NULL
;
7815 soap
->userid
= NULL
;
7816 soap
->passwd
= NULL
;
7817 soap
->authrealm
= NULL
;
7819 soap
->ntlm_challenge
= NULL
;
7822 soap_clr_mime(soap
);
7828 /******************************************************************************/
7833 soap_delete(struct soap
*soap
, void *p
)
7834 { register struct soap_clist
**cp
;
7835 if (soap_check_state(soap
))
7840 { if (p
== (*cp
)->ptr
)
7841 { register struct soap_clist
*q
= *cp
;
7844 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: deletion callback failed for object type %d\n", q
->ptr
, q
->type
));
7845 #ifdef SOAP_MEM_DEBUG
7846 fprintf(stderr
, "new(object type = %d) = %p not freed: deletion callback failed\n", q
->type
, q
->ptr
);
7854 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: address not in list\n", p
));
7858 { register struct soap_clist
*q
= *cp
;
7861 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: deletion callback failed for object type %d\n", q
->ptr
, q
->type
));
7862 #ifdef SOAP_MEM_DEBUG
7863 fprintf(stderr
, "new(object type = %d) = %p not freed: deletion callback failed\n", q
->type
, q
->ptr
);
7869 soap
->fault
= NULL
; /* this was possibly deallocated */
7870 soap
->header
= NULL
; /* this was possibly deallocated */
7874 /******************************************************************************/
7879 soap_delegate_deletion(struct soap
*soap
, struct soap
*soap_to
)
7880 { register struct soap_clist
*cp
;
7882 #ifdef SOAP_MEM_DEBUG
7884 register struct soap_mlist
**mp
, *mq
;
7887 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7889 if (*(unsigned short*)(char*)(*q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7891 #ifdef SOAP_MEM_DEBUG
7892 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7894 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7895 DBGHEX(TEST
, *q
- 200, 200);
7896 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7897 soap
->error
= SOAP_MOE
;
7900 #ifdef SOAP_MEM_DEBUG
7901 p
= (void*)(*q
- *(size_t*)(*q
+ sizeof(void*)));
7902 h
= soap_hash_ptr(p
);
7903 for (mp
= &soap
->mht
[h
]; *mp
; mp
= &(*mp
)->next
)
7904 { if ((*mp
)->ptr
== p
)
7907 mq
->next
= soap_to
->mht
[h
];
7908 soap_to
->mht
[h
] = mq
;
7914 *q
= (char*)soap_to
->alist
;
7915 soap_to
->alist
= soap
->alist
;
7917 #ifdef SOAP_MEM_DEBUG
7920 { h
= soap_hash_ptr(cp
);
7921 for (mp
= &soap
->mht
[h
]; *mp
; mp
= &(*mp
)->next
)
7922 { if ((*mp
)->ptr
== cp
)
7925 mq
->next
= soap_to
->mht
[h
];
7926 soap_to
->mht
[h
] = mq
;
7933 cp
= soap_to
->clist
;
7937 cp
->next
= soap
->clist
;
7940 soap_to
->clist
= soap
->clist
;
7945 /******************************************************************************/
7950 soap_link(struct soap
*soap
, void *p
, int t
, int n
, int (*fdelete
)(struct soap_clist
*))
7951 { register struct soap_clist
*cp
;
7952 if ((cp
= (struct soap_clist
*)SOAP_MALLOC(soap
, sizeof(struct soap_clist
))))
7953 { cp
->next
= soap
->clist
;
7957 cp
->fdelete
= fdelete
;
7964 /******************************************************************************/
7969 soap_unlink(struct soap
*soap
, const void *p
)
7970 { register char **q
;
7971 register struct soap_clist
**cp
;
7973 { for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7974 { if (p
== (void*)(*q
- *(size_t*)(*q
+ sizeof(void*))))
7975 { *q
= **(char***)q
;
7976 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unlinked data %p\n", p
));
7977 #ifdef SOAP_MEM_DEBUG
7978 soap_track_unlink(soap
, p
);
7980 return SOAP_OK
; /* found and removed from dealloc chain */
7983 for (cp
= &soap
->clist
; *cp
; cp
= &(*cp
)->next
)
7984 { if (p
== (*cp
)->ptr
)
7985 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unlinked class instance %p\n", p
));
7989 return SOAP_OK
; /* found and removed from dealloc chain */
7997 /******************************************************************************/
7998 #ifndef WITH_NOIDREF
8003 soap_lookup_type(struct soap
*soap
, const char *id
)
8004 { register struct soap_ilist
*ip
;
8006 { ip
= soap_lookup(soap
, id
);
8008 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup id='%s' type=%d\n", id
, ip
->type
));
8012 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id
));
8018 /******************************************************************************/
8019 #ifndef WITH_NOIDREF
8024 soap_id_lookup(struct soap
*soap
, const char *id
, void **p
, int t
, size_t n
, unsigned int k
)
8025 { struct soap_ilist
*ip
;
8027 if (!p
|| !id
|| !*id
)
8029 ip
= soap_lookup(soap
, id
); /* lookup pointer to hash table entry for string id */
8031 { if (!(ip
= soap_enter(soap
, id
))) /* new hash table entry for string id */
8033 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id
, t
, p
, (unsigned int)n
));
8044 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id
, t
, ip
->ptr
, (unsigned int)n
));
8046 { strcpy(soap
->id
, id
);
8047 soap
->error
= SOAP_HREF
;
8048 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id
, ip
->type
, t
));
8051 while (ip
->level
< k
)
8052 { q
= (void**)soap_malloc(soap
, sizeof(void*));
8058 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
8062 else if (ip
->level
> k
)
8063 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving level %u pointers to href='%s'\n", ip
->level
, id
));
8064 while (ip
->level
> k
)
8065 { void *s
, **r
= &ip
->link
;
8066 q
= (void**)ip
->link
;
8068 { *r
= (void*)soap_malloc(soap
, sizeof(void*));
8079 ip
->level
= ip
->level
- 1;
8080 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
8082 q
= (void**)ip
->link
;
8087 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id
, t
, p
, (unsigned int)n
));
8088 while (ip
->level
< k
)
8089 { q
= (void**)soap_malloc(soap
, sizeof(void*));
8095 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
8097 q
= (void**)ip
->link
;
8106 /******************************************************************************/
8107 #ifndef WITH_NOIDREF
8112 soap_id_forward(struct soap
*soap
, const char *href
, void *p
, size_t len
, int st
, int tt
, size_t n
, unsigned int k
, void (*fcopy
)(struct soap
*, int, int, void*, size_t, const void*, size_t))
8113 { struct soap_ilist
*ip
;
8114 if (!p
|| !href
|| !*href
)
8116 ip
= soap_lookup(soap
, href
); /* lookup pointer to hash table entry for string id */
8118 { if (!(ip
= soap_enter(soap
, href
))) /* new hash table entry for string id */
8127 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href
, st
, (unsigned long)n
, k
, p
));
8129 else if (ip
->type
!= st
|| (ip
->level
== k
&& ip
->size
!= n
))
8130 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href
, ip
->type
, (unsigned long)ip
->size
, k
, st
, (unsigned long)n
));
8131 strcpy(soap
->id
, href
);
8132 soap
->error
= SOAP_HREF
;
8135 if (fcopy
|| n
< sizeof(void*) || *href
!= '#')
8136 { register struct soap_flist
*fp
= (struct soap_flist
*)SOAP_MALLOC(soap
, sizeof(struct soap_flist
));
8138 { soap
->error
= SOAP_EOM
;
8141 fp
->next
= ip
->flist
;
8149 fp
->fcopy
= soap_fcopy
;
8151 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st
, tt
, (unsigned long)n
, p
, k
, (unsigned long)len
, href
));
8154 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarding copying address %p for type=%d href='%s'\n", p
, st
, href
));
8155 *(void**)p
= ip
->copy
;
8163 /******************************************************************************/
8168 soap_id_enter(struct soap
*soap
, const char *id
, void *p
, int t
, size_t n
, unsigned int k
, const char *type
, const char *arrayType
, void *(*finstantiate
)(struct soap
*, int, const char*, const char*, size_t*))
8170 #ifndef WITH_NOIDREF
8171 struct soap_ilist
*ip
;
8173 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id
, t
, p
, (unsigned long)n
, k
));
8177 p
= finstantiate(soap
, t
, type
, arrayType
, &n
);
8179 p
= soap_malloc(soap
, n
);
8183 #ifndef WITH_NOIDREF
8187 #ifndef WITH_NOIDREF
8188 ip
= soap_lookup(soap
, id
); /* lookup pointer to hash table entry for string id */
8189 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Lookup entry id='%s for location=%p'\n", id
, p
));
8191 { if (!(ip
= soap_enter(soap
, id
))) /* new hash table entry for string id */
8200 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id
, t
, (unsigned long)n
, k
, p
));
8202 else if ((ip
->type
!= t
|| (ip
->level
== k
&& ip
->size
!= n
)) && (ip
->copy
|| ip
->flist
))
8203 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id
, ip
->type
, (unsigned long)ip
->size
, k
, t
, (unsigned long)n
));
8204 strcpy(soap
->id
, id
);
8205 soap
->error
= SOAP_HREF
;
8209 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Multiply defined id='%s'\n", id
));
8210 strcpy(soap
->id
, id
);
8211 soap
->error
= SOAP_DUPLICATE_ID
;
8218 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id
, t
, p
, (unsigned long)n
, k
));
8225 /******************************************************************************/
8230 soap_fcopy(struct soap
*soap
, int st
, int tt
, void *p
, size_t len
, const void *q
, size_t n
)
8231 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st
, tt
, q
, p
, (unsigned long)n
));
8233 (void)soap
; (void)st
; (void)tt
; (void)len
;
8237 /******************************************************************************/
8242 soap_end_send(struct soap
*soap
)
8246 if (soap
->dime
.list
)
8247 { /* SOAP body referenced attachments must appear first */
8248 soap
->dime
.last
->next
= soap
->dime
.first
;
8249 soap
->dime
.first
= soap
->dime
.list
->next
;
8250 soap
->dime
.list
->next
= NULL
;
8251 soap
->dime
.last
= soap
->dime
.list
;
8253 if (!(err
= soap_putdime(soap
)))
8254 err
= soap_putmime(soap
);
8255 soap
->mime
.list
= NULL
;
8256 soap
->mime
.first
= NULL
;
8257 soap
->mime
.last
= NULL
;
8258 soap
->dime
.list
= NULL
;
8259 soap
->dime
.first
= NULL
;
8260 soap
->dime
.last
= NULL
;
8264 return soap_end_send_flush(soap
);
8268 /******************************************************************************/
8273 soap_end_send_flush(struct soap
*soap
)
8274 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End send mode=0x%x\n", soap
->mode
));
8275 if (soap
->mode
& SOAP_IO
) /* need to flush the remaining data in buffer */
8276 { if (soap_flush(soap
))
8278 { if (soap
->mode
& SOAP_ENC_ZLIB
&& soap
->zlib_state
== SOAP_ZLIB_DEFLATE
)
8279 { soap
->zlib_state
= SOAP_ZLIB_NONE
;
8280 deflateEnd(soap
->d_stream
);
8288 if (soap
->mode
& SOAP_ENC_ZLIB
)
8290 soap
->d_stream
->avail_in
= 0;
8292 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflating remainder\n"));
8293 r
= deflate(soap
->d_stream
, Z_FINISH
);
8294 if (soap
->d_stream
->avail_out
!= SOAP_BUFLEN
)
8295 { if (soap_flush_raw(soap
, soap
->z_buf
, SOAP_BUFLEN
- soap
->d_stream
->avail_out
))
8296 { soap
->zlib_state
= SOAP_ZLIB_NONE
;
8297 deflateEnd(soap
->d_stream
);
8300 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
8301 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
8303 } while (r
== Z_OK
);
8304 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflated total %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
8305 soap
->z_ratio_out
= (float)soap
->d_stream
->total_out
/ (float)soap
->d_stream
->total_in
;
8306 soap
->mode
&= ~SOAP_ENC_ZLIB
;
8307 soap
->zlib_state
= SOAP_ZLIB_NONE
;
8308 if (deflateEnd(soap
->d_stream
) != Z_OK
|| r
!= Z_STREAM_END
)
8309 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to end deflate: %s\n", soap
->d_stream
->msg
? soap
->d_stream
->msg
: SOAP_STR_EOS
));
8310 return soap
->error
= SOAP_ZLIB_ERROR
;
8313 if (soap
->zlib_out
!= SOAP_ZLIB_DEFLATE
)
8314 { soap
->z_buf
[0] = soap
->z_crc
& 0xFF;
8315 soap
->z_buf
[1] = (soap
->z_crc
>> 8) & 0xFF;
8316 soap
->z_buf
[2] = (soap
->z_crc
>> 16) & 0xFF;
8317 soap
->z_buf
[3] = (soap
->z_crc
>> 24) & 0xFF;
8318 soap
->z_buf
[4] = soap
->d_stream
->total_in
& 0xFF;
8319 soap
->z_buf
[5] = (soap
->d_stream
->total_in
>> 8) & 0xFF;
8320 soap
->z_buf
[6] = (soap
->d_stream
->total_in
>> 16) & 0xFF;
8321 soap
->z_buf
[7] = (soap
->d_stream
->total_in
>> 24) & 0xFF;
8322 if (soap_flush_raw(soap
, soap
->z_buf
, 8))
8324 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip crc32=%lu\n", (unsigned long)soap
->z_crc
));
8329 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
8332 if (!(soap
->mode
& SOAP_ENC_XML
))
8334 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending buffered message of length %u\n", (unsigned int)soap
->blist
->size
));
8335 if (soap
->status
>= SOAP_POST
)
8336 soap
->error
= soap
->fpost(soap
, soap
->endpoint
, soap
->host
, soap
->port
, soap
->path
, soap
->action
, soap
->blist
->size
);
8337 else if (soap
->status
!= SOAP_STOP
)
8338 soap
->error
= soap
->fresponse(soap
, soap
->status
, soap
->blist
->size
);
8339 if (soap
->error
|| soap_flush(soap
))
8344 for (p
= soap_first_block(soap
, NULL
); p
; p
= soap_next_block(soap
, NULL
))
8345 { DBGMSG(SENT
, p
, soap_block_size(soap
, NULL
));
8346 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap
, NULL
), soap
->socket
, soap
->sendfd
));
8347 if ((soap
->error
= soap
->fsend(soap
, p
, soap_block_size(soap
, NULL
))))
8348 { soap_end_block(soap
, NULL
);
8352 soap_end_block(soap
, NULL
);
8353 if (soap
->fpreparefinalsend
&& (soap
->error
= soap
->fpreparefinalsend(soap
)))
8357 else if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
8358 { DBGMSG(SENT
, "\r\n0\r\n\r\n", 7);
8359 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Send 7 bytes to socket=%d/fd=%d\n", soap
->socket
, soap
->sendfd
));
8360 if ((soap
->error
= soap
->fsend(soap
, "\r\n0\r\n\r\n", 7)))
8367 if (!soap
->ssl
&& soap_valid_socket(soap
->socket
) && !soap
->keep_alive
&& !(soap
->omode
& SOAP_IO_UDP
))
8368 soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_WR
); /* Send TCP FIN */
8370 if (soap_valid_socket(soap
->socket
) && !soap
->keep_alive
&& !(soap
->omode
& SOAP_IO_UDP
))
8371 soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_WR
); /* Send TCP FIN */
8374 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of send phase\n"));
8375 soap
->omode
&= ~SOAP_SEC_WSUID
;
8377 soap
->part
= SOAP_END
;
8382 /******************************************************************************/
8387 soap_end_recv(struct soap
*soap
)
8388 { soap
->part
= SOAP_END
;
8390 soap
->wsuid
= NULL
; /* reset before next send */
8391 soap
->c14nexclude
= NULL
; /* reset before next send */
8394 soap
->ffilterrecv
= NULL
;
8395 if ((soap
->mode
& SOAP_ENC_DIME
) && soap_getdime(soap
))
8396 { soap
->dime
.first
= NULL
;
8397 soap
->dime
.last
= NULL
;
8400 soap
->dime
.list
= soap
->dime
.first
;
8401 soap
->dime
.first
= NULL
;
8402 soap
->dime
.last
= NULL
;
8403 /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
8404 if (soap
->mode
& SOAP_ENC_MIME
)
8405 { if (soap
->mode
& SOAP_MIME_POSTCHECK
)
8406 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Post checking MIME attachments\n"));
8407 if (!soap
->keep_alive
)
8408 soap
->keep_alive
= -1;
8409 #ifndef WITH_NOIDREF
8414 if (soap_getmime(soap
))
8417 soap
->mime
.list
= soap
->mime
.first
;
8418 soap
->mime
.first
= NULL
;
8419 soap
->mime
.last
= NULL
;
8420 soap
->mime
.boundary
= NULL
;
8422 { struct soap_multipart
*content
;
8423 for (content
= soap
->mime
.list
; content
; content
= content
->next
)
8424 soap_resolve_attachment(soap
, content
);
8427 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "End of receive message ok\n"));
8429 if (soap
->mode
& SOAP_ENC_ZLIB
)
8430 { /* Make sure end of compressed content is reached */
8431 while (soap
->d_stream
->next_out
!= Z_NULL
)
8432 if ((int)soap_get1(soap
) == EOF
)
8434 soap
->mode
&= ~SOAP_ENC_ZLIB
;
8435 memcpy(soap
->buf
, soap
->z_buf
, SOAP_BUFLEN
);
8436 soap
->bufidx
= (char*)soap
->d_stream
->next_in
- soap
->z_buf
;
8437 soap
->buflen
= soap
->z_buflen
;
8438 soap
->zlib_state
= SOAP_ZLIB_NONE
;
8439 if (inflateEnd(soap
->d_stream
) != Z_OK
)
8440 return soap
->error
= SOAP_ZLIB_ERROR
;
8441 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Inflate end ok\n"));
8443 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
8446 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Inflate gzip crc check\n"));
8447 for (i
= 0; i
< 8; i
++)
8448 { if ((int)(c
= soap_get1(soap
)) == EOF
)
8449 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Gzip error: unable to read crc value\n"));
8450 return soap
->error
= SOAP_ZLIB_ERROR
;
8452 soap
->z_buf
[i
] = (char)c
;
8454 if (soap
->z_crc
!= ((uLong
)(unsigned char)soap
->z_buf
[0] | ((uLong
)(unsigned char)soap
->z_buf
[1] << 8) | ((uLong
)(unsigned char)soap
->z_buf
[2] << 16) | ((uLong
)(unsigned char)soap
->z_buf
[3] << 24)))
8455 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Gzip inflate error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap
->z_crc
));
8456 return soap
->error
= SOAP_ZLIB_ERROR
;
8458 if (soap
->d_stream
->total_out
!= ((uLong
)(unsigned char)soap
->z_buf
[4] | ((uLong
)(unsigned char)soap
->z_buf
[5] << 8) | ((uLong
)(unsigned char)soap
->z_buf
[6] << 16) | ((uLong
)(unsigned char)soap
->z_buf
[7] << 24)))
8459 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Gzip inflate error: incorrect message length\n"));
8460 return soap
->error
= SOAP_ZLIB_ERROR
;
8463 soap
->zlib_in
= SOAP_ZLIB_NONE
;
8467 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
8468 while (soap
->ahead
!= EOF
&& !soap_recv_raw(soap
))
8470 #ifndef WITH_NOIDREF
8471 if (soap_resolve(soap
))
8476 { if (soap
->mode
& SOAP_ENC_MTOM
)
8477 return soap
->error
= SOAP_MIME_HREF
;
8478 return soap
->error
= SOAP_DIME_HREF
;
8483 if (soap
->fpreparefinalrecv
)
8484 return soap
->error
= soap
->fpreparefinalrecv(soap
);
8490 /******************************************************************************/
8495 soap_free_temp(struct soap
*soap
)
8496 { register struct soap_attribute
*tp
, *tq
;
8497 register struct Namespace
*ns
;
8499 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free any remaining temp blocks\n"));
8501 soap_end_block(soap
, NULL
);
8502 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free attribute storage\n"));
8503 for (tp
= soap
->attributes
; tp
; tp
= tq
)
8506 SOAP_FREE(soap
, tp
->value
);
8507 SOAP_FREE(soap
, tp
);
8509 soap
->attributes
= NULL
;
8512 SOAP_FREE(soap
, soap
->labbuf
);
8513 soap
->labbuf
= NULL
;
8517 ns
= soap
->local_namespaces
;
8519 { for (; ns
->id
; ns
++)
8521 { SOAP_FREE(soap
, ns
->out
);
8525 SOAP_FREE(soap
, soap
->local_namespaces
);
8526 soap
->local_namespaces
= NULL
;
8530 { struct soap_xlist
*xp
= soap
->xlist
->next
;
8531 SOAP_FREE(soap
, soap
->xlist
);
8535 #ifndef WITH_NOIDREF
8536 soap_free_pht(soap
);
8537 soap_free_iht(soap
);
8542 /******************************************************************************/
8545 soap_free_ns(struct soap
*soap
)
8546 { register struct soap_nlist
*np
, *nq
;
8547 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free namespace stack\n"));
8548 for (np
= soap
->nlist
; np
; np
= nq
)
8550 SOAP_FREE(soap
, np
);
8556 /******************************************************************************/
8558 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8560 soap_init_logs(struct soap
*soap
)
8562 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
8563 { soap
->logfile
[i
] = NULL
;
8564 soap
->fdebug
[i
] = NULL
;
8570 /******************************************************************************/
8571 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8575 soap_open_logfile(struct soap
*soap
, int i
)
8576 { if (soap
->logfile
[i
])
8577 soap
->fdebug
[i
] = fopen(soap
->logfile
[i
], i
< 2 ? "ab" : "a");
8581 /******************************************************************************/
8584 soap_close_logfile(struct soap
*soap
, int i
)
8585 { if (soap
->fdebug
[i
])
8586 { fclose(soap
->fdebug
[i
]);
8587 soap
->fdebug
[i
] = NULL
;
8592 /******************************************************************************/
8597 soap_close_logfiles(struct soap
*soap
)
8599 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
8600 soap_close_logfile(soap
, i
);
8604 /******************************************************************************/
8607 soap_set_logfile(struct soap
*soap
, int i
, const char *logfile
)
8610 soap_close_logfile(soap
, i
);
8611 s
= soap
->logfile
[i
];
8612 soap
->logfile
[i
] = logfile
;
8614 SOAP_FREE(soap
, (void*)s
);
8616 if ((t
= (char*)SOAP_MALLOC(soap
, strlen(logfile
) + 1)))
8618 soap
->logfile
[i
] = t
;
8622 /******************************************************************************/
8626 soap_set_recv_logfile(struct soap
*soap
, const char *logfile
)
8629 soap_set_logfile(soap
, SOAP_INDEX_RECV
, logfile
);
8633 /******************************************************************************/
8637 soap_set_sent_logfile(struct soap
*soap
, const char *logfile
)
8640 soap_set_logfile(soap
, SOAP_INDEX_SENT
, logfile
);
8644 /******************************************************************************/
8648 soap_set_test_logfile(struct soap
*soap
, const char *logfile
)
8651 soap_set_logfile(soap
, SOAP_INDEX_TEST
, logfile
);
8655 /******************************************************************************/
8660 soap_copy(const struct soap
*soap
)
8661 { return soap_copy_context((struct soap
*)malloc(sizeof(struct soap
)), soap
);
8665 /******************************************************************************/
8670 soap_copy_context(struct soap
*copy
, const struct soap
*soap
)
8673 if (soap_check_state(soap
))
8676 { register struct soap_plugin
*p
= NULL
;
8677 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copying context\n"));
8681 memcpy(copy
, soap
, sizeof(struct soap
));
8683 copy
->state
= SOAP_COPY
;
8684 copy
->error
= SOAP_OK
;
8685 copy
->userid
= NULL
;
8686 copy
->passwd
= NULL
;
8688 copy
->ntlm_challenge
= NULL
;
8694 copy
->attributes
= NULL
;
8695 copy
->labbuf
= NULL
;
8698 #ifdef SOAP_MEM_DEBUG
8699 soap_init_mht(copy
);
8701 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8702 soap_init_logs(copy
);
8705 soap_set_test_logfile(copy
, soap
->logfile
[SOAP_INDEX_TEST
]);
8706 soap_set_sent_logfile(copy
, soap
->logfile
[SOAP_INDEX_SENT
]);
8707 soap_set_recv_logfile(copy
, soap
->logfile
[SOAP_INDEX_RECV
]);
8709 copy
->namespaces
= soap
->local_namespaces
;
8710 copy
->local_namespaces
= NULL
;
8711 soap_set_local_namespaces(copy
); /* copy content of soap->local_namespaces */
8712 copy
->namespaces
= soap
->namespaces
; /* point to shared read-only namespaces table */
8713 #ifdef WITH_C_LOCALE
8715 copy
->c_locale
= _create_locale(LC_ALL
, "C");
8717 copy
->c_locale
= duplocale(soap
->c_locale
);
8720 copy
->c_locale
= NULL
;
8725 copy
->session
= NULL
;
8728 copy
->session
= NULL
;
8731 copy
->d_stream
= (z_stream
*)SOAP_MALLOC(copy
, sizeof(z_stream
));
8732 copy
->d_stream
->zalloc
= Z_NULL
;
8733 copy
->d_stream
->zfree
= Z_NULL
;
8734 copy
->d_stream
->opaque
= Z_NULL
;
8737 #ifndef WITH_NOIDREF
8738 soap_init_iht(copy
);
8739 soap_init_pht(copy
);
8741 copy
->header
= NULL
;
8743 copy
->action
= NULL
;
8746 copy
->cookies
= soap_copy_cookies(copy
, soap
);
8748 copy
->cookies
= NULL
;
8751 copy
->plugins
= NULL
;
8752 for (p
= soap
->plugins
; p
; p
= p
->next
)
8753 { register struct soap_plugin
*q
= (struct soap_plugin
*)SOAP_MALLOC(copy
, sizeof(struct soap_plugin
));
8756 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copying plugin '%s'\n", p
->id
));
8758 if (p
->fcopy
&& p
->fcopy(copy
, q
, p
))
8759 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not copy plugin '%s'\n", p
->id
));
8763 q
->next
= copy
->plugins
;
8771 /******************************************************************************/
8776 soap_copy_stream(struct soap
*copy
, struct soap
*soap
)
8777 { struct soap_attribute
*tp
= NULL
, *tq
;
8780 copy
->header
= soap
->header
;
8781 copy
->mode
= soap
->mode
;
8782 copy
->imode
= soap
->imode
;
8783 copy
->omode
= soap
->omode
;
8784 copy
->master
= soap
->master
;
8785 copy
->socket
= soap
->socket
;
8786 copy
->sendsk
= soap
->sendsk
;
8787 copy
->recvsk
= soap
->recvsk
;
8788 copy
->recv_timeout
= soap
->recv_timeout
;
8789 copy
->send_timeout
= soap
->send_timeout
;
8790 #if defined(__cplusplus) && !defined(WITH_LEAN)
8791 copy
->os
= soap
->os
;
8792 copy
->is
= soap
->is
;
8794 copy
->sendfd
= soap
->sendfd
;
8795 copy
->recvfd
= soap
->recvfd
;
8796 copy
->bufidx
= soap
->bufidx
;
8797 copy
->buflen
= soap
->buflen
;
8798 copy
->ahead
= soap
->ahead
;
8799 copy
->cdata
= soap
->cdata
;
8800 copy
->chunksize
= soap
->chunksize
;
8801 copy
->chunkbuflen
= soap
->chunkbuflen
;
8802 copy
->keep_alive
= soap
->keep_alive
;
8803 copy
->tcp_keep_alive
= soap
->tcp_keep_alive
;
8804 copy
->tcp_keep_idle
= soap
->tcp_keep_idle
;
8805 copy
->tcp_keep_intvl
= soap
->tcp_keep_intvl
;
8806 copy
->tcp_keep_cnt
= soap
->tcp_keep_cnt
;
8807 copy
->max_keep_alive
= soap
->max_keep_alive
;
8809 copy
->peer
= soap
->peer
;
8810 copy
->peerlen
= soap
->peerlen
;
8811 copy
->ip
= soap
->ip
;
8812 copy
->port
= soap
->port
;
8813 memcpy(copy
->host
, soap
->host
, sizeof(soap
->host
));
8814 memcpy(copy
->endpoint
, soap
->endpoint
, sizeof(soap
->endpoint
));
8817 copy
->bio
= soap
->bio
;
8818 copy
->ctx
= soap
->ctx
;
8819 copy
->ssl
= soap
->ssl
;
8822 copy
->session
= soap
->session
;
8825 copy
->zlib_state
= soap
->zlib_state
;
8826 copy
->zlib_in
= soap
->zlib_in
;
8827 copy
->zlib_out
= soap
->zlib_out
;
8828 if (!copy
->d_stream
)
8829 copy
->d_stream
= (z_stream
*)SOAP_MALLOC(copy
, sizeof(z_stream
));
8831 memcpy(copy
->d_stream
, soap
->d_stream
, sizeof(z_stream
));
8832 copy
->z_crc
= soap
->z_crc
;
8833 copy
->z_ratio_in
= soap
->z_ratio_in
;
8834 copy
->z_ratio_out
= soap
->z_ratio_out
;
8836 copy
->z_buflen
= soap
->z_buflen
;
8837 copy
->z_level
= soap
->z_level
;
8838 if (soap
->z_buf
&& soap
->zlib_state
!= SOAP_ZLIB_NONE
)
8839 { copy
->z_buf
= (char*)SOAP_MALLOC(copy
, SOAP_BUFLEN
);
8841 memcpy(copy
->z_buf
, soap
->z_buf
, SOAP_BUFLEN
);
8843 copy
->z_dict
= soap
->z_dict
;
8844 copy
->z_dict_len
= soap
->z_dict_len
;
8846 memcpy(copy
->buf
, soap
->buf
, sizeof(soap
->buf
));
8847 /* copy XML parser state */
8849 soap_set_local_namespaces(copy
);
8850 copy
->version
= soap
->version
;
8851 if (soap
->nlist
&& soap
->local_namespaces
)
8852 { register struct soap_nlist
*np
= NULL
, *nq
;
8853 /* copy reversed nlist */
8854 for (nq
= soap
->nlist
; nq
; nq
= nq
->next
)
8855 { register struct soap_nlist
*nr
= np
;
8856 size_t n
= sizeof(struct soap_nlist
) + strlen(nq
->id
);
8857 np
= (struct soap_nlist
*)SOAP_MALLOC(copy
, n
);
8864 { register const char *s
= np
->ns
;
8865 copy
->level
= np
->level
; /* preserve element nesting level */
8866 if (!s
&& np
->index
>= 0)
8867 { s
= soap
->local_namespaces
[np
->index
].out
;
8869 s
= soap
->local_namespaces
[np
->index
].ns
;
8871 if (s
&& soap_push_namespace(copy
, np
->id
, s
) == NULL
)
8875 SOAP_FREE(copy
, nq
);
8878 memcpy(copy
->tag
, soap
->tag
, sizeof(copy
->tag
));
8879 memcpy(copy
->id
, soap
->id
, sizeof(copy
->id
));
8880 memcpy(copy
->href
, soap
->href
, sizeof(copy
->href
));
8881 memcpy(copy
->type
, soap
->type
, sizeof(copy
->type
));
8882 copy
->other
= soap
->other
;
8883 copy
->root
= soap
->root
;
8884 copy
->null
= soap
->null
;
8885 copy
->body
= soap
->body
;
8886 copy
->part
= soap
->part
;
8887 copy
->mustUnderstand
= soap
->mustUnderstand
;
8888 copy
->level
= soap
->level
;
8889 copy
->peeked
= soap
->peeked
;
8890 /* copy attributes */
8891 for (tq
= soap
->attributes
; tq
; tq
= tq
->next
)
8892 { struct soap_attribute
*tr
= tp
;
8893 size_t n
= sizeof(struct soap_attribute
) + strlen(tq
->name
);
8894 tp
= (struct soap_attribute
*)SOAP_MALLOC(copy
, n
);
8897 { tp
->value
= (char*)SOAP_MALLOC(copy
, tp
->size
);
8899 strcpy(tp
->value
, tq
->value
);
8904 copy
->attributes
= tp
;
8908 /******************************************************************************/
8913 soap_free_stream(struct soap
*soap
)
8914 { soap
->socket
= SOAP_INVALID_SOCKET
;
8915 soap
->sendsk
= SOAP_INVALID_SOCKET
;
8916 soap
->recvsk
= SOAP_INVALID_SOCKET
;
8926 soap
->session
= NULL
;
8927 soap
->dh_params
= NULL
;
8928 soap
->rsa_params
= NULL
;
8932 SOAP_FREE(soap
, soap
->z_buf
);
8938 /******************************************************************************/
8943 soap_initialize(struct soap
*soap
)
8944 { soap_versioning(soap_init
)(soap
, SOAP_IO_DEFAULT
, SOAP_IO_DEFAULT
);
8948 /******************************************************************************/
8953 soap_versioning(soap_init
)(struct soap
*soap
, soap_mode imode
, soap_mode omode
)
8955 soap
->state
= SOAP_INIT
;
8956 #ifdef SOAP_MEM_DEBUG
8957 soap_init_mht(soap
);
8959 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8960 soap_init_logs(soap
);
8963 #ifdef TANDEM_NONSTOP
8964 soap_set_test_logfile(soap
, "TESTLOG");
8965 soap_set_sent_logfile(soap
, "SENTLOG");
8966 soap_set_recv_logfile(soap
, "RECVLOG");
8968 soap_set_test_logfile(soap
, "TEST.log");
8969 soap_set_sent_logfile(soap
, "SENT.log");
8970 soap_set_recv_logfile(soap
, "RECV.log");
8974 soap_mode(soap
, imode
);
8975 soap_imode(soap
, imode
);
8976 soap_omode(soap
, omode
);
8977 soap
->plugins
= NULL
;
8979 for (i
= 0; i
< sizeof(soap
->data
)/sizeof(*soap
->data
); i
++)
8980 soap
->data
[i
] = NULL
;
8981 soap
->userid
= NULL
;
8982 soap
->passwd
= NULL
;
8983 soap
->authrealm
= NULL
;
8985 soap
->ntlm_challenge
= NULL
;
8988 soap
->fpost
= http_post
;
8989 soap
->fget
= http_get
;
8990 soap
->fput
= http_405
;
8991 soap
->fdel
= http_405
;
8992 soap
->fopt
= http_200
;
8993 soap
->fhead
= http_200
;
8995 soap
->fposthdr
= http_post_header
;
8996 soap
->fresponse
= http_response
;
8997 soap
->fparse
= http_parse
;
8998 soap
->fparsehdr
= http_parse_header
;
9000 soap
->fheader
= NULL
;
9001 soap
->fconnect
= NULL
;
9002 soap
->fdisconnect
= NULL
;
9004 soap
->ipv6_multicast_if
= 0; /* in_addr_t value */
9005 soap
->ipv4_multicast_if
= NULL
; /* points to struct in_addr or in_addr_t */
9006 soap
->ipv4_multicast_ttl
= 0; /* 0: use default */
9008 soap
->fresolve
= tcp_gethost
;
9010 soap
->fresolve
= NULL
;
9012 soap
->faccept
= tcp_accept
;
9013 soap
->fopen
= tcp_connect
;
9014 soap
->fclose
= tcp_disconnect
;
9015 soap
->fclosesocket
= tcp_closesocket
;
9016 soap
->fshutdownsocket
= tcp_shutdownsocket
;
9017 soap
->fsend
= fsend
;
9018 soap
->frecv
= frecv
;
9019 soap
->fpoll
= soap_poll
;
9022 soap
->fclose
= NULL
;
9025 soap
->fseterror
= NULL
;
9026 soap
->fignore
= NULL
;
9027 soap
->fserveloop
= NULL
;
9028 soap
->fplugin
= fplugin
;
9029 soap
->fmalloc
= NULL
;
9031 soap
->feltbegin
= NULL
;
9032 soap
->feltendin
= NULL
;
9033 soap
->feltbegout
= NULL
;
9034 soap
->feltendout
= NULL
;
9035 soap
->fprepareinitsend
= NULL
;
9036 soap
->fprepareinitrecv
= NULL
;
9037 soap
->fpreparesend
= NULL
;
9038 soap
->fpreparerecv
= NULL
;
9039 soap
->fpreparefinalsend
= NULL
;
9040 soap
->fpreparefinalrecv
= NULL
;
9041 soap
->ffiltersend
= NULL
;
9042 soap
->ffilterrecv
= NULL
;
9043 soap
->fdimereadopen
= NULL
;
9044 soap
->fdimewriteopen
= NULL
;
9045 soap
->fdimereadclose
= NULL
;
9046 soap
->fdimewriteclose
= NULL
;
9047 soap
->fdimeread
= NULL
;
9048 soap
->fdimewrite
= NULL
;
9049 soap
->fmimereadopen
= NULL
;
9050 soap
->fmimewriteopen
= NULL
;
9051 soap
->fmimereadclose
= NULL
;
9052 soap
->fmimewriteclose
= NULL
;
9053 soap
->fmimeread
= NULL
;
9054 soap
->fmimewrite
= NULL
;
9056 soap
->float_format
= "%.9G"; /* Alternative: use "%G" */
9057 soap
->double_format
= "%.17lG"; /* Alternative: use "%lG" */
9058 soap
->dime_id_format
= "cid:id%d"; /* default DIME id format */
9059 soap
->http_version
= "1.1";
9060 soap
->proxy_http_version
= "1.0";
9061 soap
->http_content
= NULL
;
9064 soap
->keep_alive
= 0;
9065 soap
->tcp_keep_alive
= 0;
9066 soap
->tcp_keep_idle
= 0;
9067 soap
->tcp_keep_intvl
= 0;
9068 soap
->tcp_keep_cnt
= 0;
9069 soap
->max_keep_alive
= SOAP_MAXKEEPALIVE
;
9070 soap
->recv_timeout
= 0;
9071 soap
->send_timeout
= 0;
9072 soap
->connect_timeout
= 0;
9073 soap
->accept_timeout
= 0;
9074 soap
->socket_flags
= 0;
9075 soap
->connect_flags
= 0;
9076 soap
->bind_flags
= 0;
9077 soap
->accept_flags
= 0;
9078 soap
->linger_time
= 0;
9080 soap
->labbuf
= NULL
;
9083 soap
->encodingStyle
= NULL
;
9084 #ifndef WITH_NONAMESPACES
9085 soap
->namespaces
= namespaces
;
9087 soap
->namespaces
= NULL
;
9089 soap
->local_namespaces
= NULL
;
9094 soap
->attributes
= NULL
;
9095 soap
->header
= NULL
;
9097 soap
->master
= SOAP_INVALID_SOCKET
;
9098 soap
->socket
= SOAP_INVALID_SOCKET
;
9099 soap
->sendsk
= SOAP_INVALID_SOCKET
;
9100 soap
->recvsk
= SOAP_INVALID_SOCKET
;
9105 soap
->dime
.list
= NULL
;
9106 soap
->dime
.first
= NULL
;
9107 soap
->dime
.last
= NULL
;
9108 soap
->mime
.list
= NULL
;
9109 soap
->mime
.first
= NULL
;
9110 soap
->mime
.last
= NULL
;
9111 soap
->mime
.boundary
= NULL
;
9112 soap
->mime
.start
= NULL
;
9119 soap
->recvfd
= stdin
;
9120 soap
->sendfd
= stdout
;
9122 soap
->host
[0] = '\0';
9124 soap
->action
= NULL
;
9125 soap
->proxy_host
= NULL
;
9126 soap
->proxy_port
= 8080;
9127 soap
->proxy_userid
= NULL
;
9128 soap
->proxy_passwd
= NULL
;
9129 soap
->prolog
= NULL
;
9131 soap
->zlib_state
= SOAP_ZLIB_NONE
;
9132 soap
->zlib_in
= SOAP_ZLIB_NONE
;
9133 soap
->zlib_out
= SOAP_ZLIB_NONE
;
9134 soap
->d_stream
= (z_stream
*)SOAP_MALLOC(soap
, sizeof(z_stream
));
9135 soap
->d_stream
->zalloc
= Z_NULL
;
9136 soap
->d_stream
->zfree
= Z_NULL
;
9137 soap
->d_stream
->opaque
= Z_NULL
;
9140 soap
->z_dict
= NULL
;
9141 soap
->z_dict_len
= 0;
9145 soap
->c14nexclude
= NULL
;
9146 soap
->cookies
= NULL
;
9147 soap
->cookie_domain
= NULL
;
9148 soap
->cookie_path
= NULL
;
9149 soap
->cookie_max
= 32;
9152 soap
->rpmreqid
= NULL
;
9157 #ifndef WITH_NOIDREF
9158 soap_init_iht(soap
);
9159 soap_init_pht(soap
);
9162 if (!soap_ssl_init_done
)
9164 soap
->fsslauth
= ssl_auth_init
;
9165 soap
->fsslverify
= ssl_verify_callback
;
9169 soap
->session
= NULL
;
9170 soap
->ssl_flags
= SOAP_SSL_DEFAULT
;
9171 soap
->keyfile
= NULL
;
9173 soap
->password
= NULL
;
9174 soap
->cafile
= NULL
;
9175 soap
->capath
= NULL
;
9176 soap
->crlfile
= NULL
;
9177 soap
->dhfile
= NULL
;
9178 soap
->randfile
= NULL
;
9181 if (!soap_ssl_init_done
)
9183 soap
->fsslauth
= ssl_auth_init
;
9184 soap
->fsslverify
= NULL
;
9188 soap
->session
= NULL
;
9189 soap
->ssl_flags
= SOAP_SSL_DEFAULT
;
9190 soap
->keyfile
= NULL
;
9192 soap
->password
= NULL
;
9193 soap
->cafile
= NULL
;
9194 soap
->capath
= NULL
;
9195 soap
->crlfile
= NULL
;
9196 soap
->dh_params
= NULL
;
9197 soap
->rsa_params
= NULL
;
9199 #ifdef WITH_C_LOCALE
9201 soap
->c_locale
= _create_locale(LC_ALL
, "C");
9203 soap
->c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
);
9206 soap
->c_locale
= NULL
;
9211 soap
->dime
.chunksize
= 0;
9212 soap
->dime
.buflen
= 0;
9217 soap
->mustUnderstand
= 0;
9219 soap
->part
= SOAP_END
;
9230 soap
->endpoint
[0] = '\0';
9231 soap
->error
= SOAP_OK
;
9235 /******************************************************************************/
9240 soap_begin(struct soap
*soap
)
9241 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reinitializing context\n"));
9242 if (!soap
->keep_alive
)
9249 soap
->mustUnderstand
= 0;
9252 soap
->part
= SOAP_END
;
9259 soap
->error
= SOAP_OK
;
9264 soap
->endpoint
[0] = '\0';
9265 soap
->encodingStyle
= SOAP_STR_EOS
;
9267 soap
->dime
.chunksize
= 0;
9268 soap
->dime
.buflen
= 0;
9270 soap_free_temp(soap
);
9274 /******************************************************************************/
9279 soap_end(struct soap
*soap
)
9280 { if (soap_check_state(soap
))
9282 soap_free_temp(soap
);
9283 soap_dealloc(soap
, NULL
);
9285 { register struct soap_clist
*cp
= soap
->clist
->next
;
9286 SOAP_FREE(soap
, soap
->clist
);
9289 soap_closesock(soap
);
9291 soap_close_logfiles(soap
);
9299 /******************************************************************************/
9304 soap_set_version(struct soap
*soap
, short version
)
9305 { soap_set_local_namespaces(soap
);
9306 if (soap
->version
!= version
)
9308 { soap
->local_namespaces
[0].ns
= soap_env1
;
9309 soap
->local_namespaces
[1].ns
= soap_enc1
;
9311 else if (version
== 2)
9312 { soap
->local_namespaces
[0].ns
= soap_env2
;
9313 soap
->local_namespaces
[1].ns
= soap_enc2
;
9315 soap
->version
= version
;
9320 /******************************************************************************/
9325 soap_set_namespaces(struct soap
*soap
, const struct Namespace
*p
)
9326 { register struct Namespace
*ns
= soap
->local_namespaces
;
9327 register struct soap_nlist
*np
, *nq
, *nr
;
9328 register unsigned int level
= soap
->level
;
9329 soap
->namespaces
= p
;
9330 soap
->local_namespaces
= NULL
;
9331 soap_set_local_namespaces(soap
);
9332 /* reverse the namespace list */
9345 /* then push on new stack */
9347 { register const char *s
;
9348 soap
->level
= np
->level
; /* preserve element nesting level */
9350 if (!s
&& np
->index
>= 0 && ns
)
9351 { s
= ns
[np
->index
].out
;
9353 s
= ns
[np
->index
].ns
;
9355 if (s
&& soap_push_namespace(soap
, np
->id
, s
) == NULL
)
9359 SOAP_FREE(soap
, nq
);
9363 for (i
= 0; ns
[i
].id
; i
++)
9365 { SOAP_FREE(soap
, ns
[i
].out
);
9369 SOAP_FREE(soap
, ns
);
9371 soap
->level
= level
; /* restore level */
9376 /******************************************************************************/
9381 soap_set_local_namespaces(struct soap
*soap
)
9382 { if (soap
->namespaces
&& !soap
->local_namespaces
)
9383 { register const struct Namespace
*ns1
;
9384 register struct Namespace
*ns2
;
9385 register size_t n
= 1;
9386 for (ns1
= soap
->namespaces
; ns1
->id
; ns1
++)
9388 n
*= sizeof(struct Namespace
);
9389 ns2
= (struct Namespace
*)SOAP_MALLOC(soap
, n
);
9391 { memcpy(ns2
, soap
->namespaces
, n
);
9393 { if (!strcmp(ns2
[0].ns
, soap_env1
))
9395 else if (!strcmp(ns2
[0].ns
, soap_env2
))
9398 soap
->local_namespaces
= ns2
;
9399 for (; ns2
->id
; ns2
++)
9406 /******************************************************************************/
9412 soap_tagsearch(const char *big
, const char *little
)
9414 { register size_t n
= strlen(little
);
9415 register const char *s
= big
;
9417 { register const char *t
= s
;
9419 for (i
= 0; i
< n
; i
++, t
++)
9420 { if (*t
!= little
[i
])
9423 if (*t
== '\0' || *t
== ' ')
9424 { if (i
== n
|| (i
&& little
[i
-1] == ':'))
9437 /******************************************************************************/
9443 soap_lookup_ns(struct soap
*soap
, const char *tag
, size_t n
)
9444 { register struct soap_nlist
*np
;
9445 for (np
= soap
->nlist
; np
; np
= np
->next
)
9446 { if (!strncmp(np
->id
, tag
, n
) && !np
->id
[n
])
9454 /******************************************************************************/
9456 static struct soap_nlist
*
9457 soap_push_ns(struct soap
*soap
, const char *id
, const char *ns
, short utilized
)
9458 { register struct soap_nlist
*np
;
9460 if (soap_tagsearch(soap
->c14nexclude
, id
))
9463 { for (np
= soap
->nlist
; np
; np
= np
->next
)
9464 { if (!strcmp(np
->id
, id
) && (!np
->ns
|| !strcmp(np
->ns
, ns
)))
9468 { if ((np
->level
< soap
->level
|| !np
->ns
) && np
->index
== 1)
9474 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap
->level
, id
, ns
? ns
: "(null)", utilized
));
9480 np
= (struct soap_nlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_nlist
) + n
+ k
+ 1);
9482 { soap
->error
= SOAP_EOM
;
9485 np
->next
= soap
->nlist
;
9487 strcpy((char*)np
->id
, id
);
9489 np
->ns
= strcpy((char*)np
->id
+ n
+ 1, ns
);
9492 np
->level
= soap
->level
;
9493 np
->index
= utilized
;
9498 /******************************************************************************/
9501 soap_utilize_ns(struct soap
*soap
, const char *tag
)
9502 { register struct soap_nlist
*np
;
9504 const char *t
= strchr(tag
, ':');
9507 if (n
>= sizeof(soap
->tmpbuf
))
9508 n
= sizeof(soap
->tmpbuf
) - 1;
9510 np
= soap_lookup_ns(soap
, tag
, n
);
9511 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Utilizing namespace of '%s'\n", tag
));
9513 { if (np
->index
<= 0)
9514 soap_push_ns(soap
, np
->id
, np
->ns
, 1);
9516 else if (strncmp(tag
, "xml", 3))
9517 { strncpy(soap
->tmpbuf
, tag
, n
);
9518 soap
->tmpbuf
[n
] = '\0';
9519 soap_push_ns(soap
, soap
->tmpbuf
, NULL
, 1);
9524 /******************************************************************************/
9529 soap_element(struct soap
*soap
, const char *tag
, int id
, const char *type
)
9532 register const char *s
;
9534 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element begin tag='%s' level='%u' id='%d' type='%s'\n", tag
, soap
->level
, id
, type
? type
: SOAP_STR_EOS
));
9538 if (soap
->wsuid
&& soap_tagsearch(soap
->wsuid
, tag
))
9540 for (s
= tag
, i
= 0; *s
&& i
< sizeof(soap
->tag
) - 1; s
++, i
++)
9541 soap
->tag
[i
] = *s
== ':' ? '-' : *s
;
9542 soap
->tag
[i
] = '\0';
9543 if (soap_set_attr(soap
, "wsu:Id", soap
->tag
, 1))
9546 if ((soap
->mode
& SOAP_XML_CANONICAL
) && !(soap
->mode
& SOAP_DOM_ASIS
))
9547 { if (soap
->evlev
>= soap
->level
)
9549 if (soap
->event
== SOAP_SEC_BEGIN
&& !soap
->evlev
)
9550 { register struct soap_nlist
*np
;
9551 /* non-nested wsu:Id found: clear xmlns, re-emit them for exc-c14n */
9552 for (np
= soap
->nlist
; np
; np
= np
->next
)
9553 { if (np
->index
== 2)
9554 { struct soap_nlist
*np1
= soap_push_ns(soap
, np
->id
, np
->ns
, 1);
9559 soap
->evlev
= soap
->level
;
9563 if (soap
->mode
& SOAP_XML_DOM
)
9564 { register struct soap_dom_element
*elt
= (struct soap_dom_element
*)soap_malloc(soap
, sizeof(struct soap_dom_element
));
9569 elt
->prnt
= soap
->dom
;
9570 elt
->name
= soap_strdup(soap
, tag
);
9581 { struct soap_dom_element
*p
= soap
->dom
->elts
;
9588 soap
->dom
->elts
= elt
;
9597 { if (!(soap
->mode
& SOAP_XML_CANONICAL
)
9598 && soap_send(soap
, soap
->prolog
? soap
->prolog
: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
9601 else if (soap
->mode
& SOAP_XML_INDENT
)
9602 { if (soap
->ns
== 1 && soap_send_raw(soap
, soap_indent
, soap
->level
< sizeof(soap_indent
) ? soap
->level
: sizeof(soap_indent
) - 1))
9606 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tag
, ':')))
9607 { struct Namespace
*ns
= soap
->local_namespaces
;
9609 if (soap_send_raw(soap
, "<", 1)
9610 || soap_send(soap
, s
+ 1))
9612 if (soap
->nlist
&& !strncmp(soap
->nlist
->id
, tag
, n
) && !soap
->nlist
->id
[n
])
9614 for (; ns
&& ns
->id
; ns
++)
9615 { if (*ns
->id
&& (ns
->out
|| ns
->ns
) && !strncmp(ns
->id
, tag
, n
) && !ns
->id
[n
])
9616 { soap_push_ns(soap
, ns
->id
, ns
->out
? ns
->out
: ns
->ns
, 0);
9617 if (soap_attribute(soap
, "xmlns", ns
->out
? ns
->out
: ns
->ns
))
9625 if (soap_send_raw(soap
, "<", 1)
9626 || soap_send(soap
, tag
))
9632 { struct Namespace
*ns
= soap
->local_namespaces
;
9637 if ((soap
->mode
& SOAP_XML_DEFAULTNS
))
9638 { if (soap
->version
)
9639 k
= 4; /* first four required entries */
9640 else if (!(soap
->mode
& SOAP_XML_NOTYPE
) || (soap
->mode
& SOAP_XML_NIL
))
9642 k
= 2; /* next two entries */
9645 k
= 0; /* no entries */
9648 while (k
-- && ns
->id
)
9649 { if (*ns
->id
&& (ns
->out
|| ns
->ns
))
9651 #ifdef HAVE_SNPRINTF
9652 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "xmlns:%s", ns
->id
);
9654 sprintf(soap
->tmpbuf
, "xmlns:%s", ns
->id
);
9656 if (soap_attribute(soap
, soap
->tmpbuf
, ns
->out
? ns
->out
: ns
->ns
))
9663 soap
->ns
= 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
9665 if (soap
->mode
& SOAP_XML_CANONICAL
)
9666 soap_utilize_ns(soap
, tag
);
9670 #ifdef HAVE_SNPRINTF
9671 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "_%d", id
);
9673 sprintf(soap
->tmpbuf
, "_%d", id
);
9675 if (soap
->version
== 2)
9676 { if (soap_attribute(soap
, "SOAP-ENC:id", soap
->tmpbuf
))
9679 else if (soap_attribute(soap
, "id", soap
->tmpbuf
))
9682 if (type
&& *type
&& !(soap
->mode
& SOAP_XML_NOTYPE
) && soap
->part
!= SOAP_IN_HEADER
)
9683 { const char *t
= type
;
9685 if (soap
->mode
& SOAP_XML_DEFAULTNS
)
9686 { t
= strchr(type
, ':');
9693 if (soap
->attributes
? soap_set_attr(soap
, "xsi:type", t
, 1) : soap_attribute(soap
, "xsi:type", t
))
9696 if (soap
->mode
& SOAP_XML_CANONICAL
)
9697 soap_utilize_ns(soap
, type
);
9700 if (soap
->null
&& soap
->position
> 0)
9702 #ifdef HAVE_SNPRINTF
9703 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
) - 1, "[%d", soap
->positions
[0]);
9705 sprintf(soap
->tmpbuf
, "[%d", soap
->positions
[0]);
9707 for (i
= 1; i
< soap
->position
; i
++)
9708 { register size_t l
= strlen(soap
->tmpbuf
);
9709 #ifdef HAVE_SNPRINTF
9710 soap_snprintf(soap
->tmpbuf
+ l
, sizeof(soap
->tmpbuf
)-l
-1, ",%d", soap
->positions
[i
]);
9712 if (l
+ 13 < sizeof(soap
->tmpbuf
))
9713 sprintf(soap
->tmpbuf
+ l
, ",%d", soap
->positions
[i
]);
9716 strcat(soap
->tmpbuf
, "]");
9717 if (soap_attribute(soap
, "SOAP-ENC:position", soap
->tmpbuf
))
9720 if (soap
->mustUnderstand
)
9721 { if (soap
->actor
&& *soap
->actor
)
9722 { if (soap_attribute(soap
, soap
->version
== 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap
->actor
))
9725 if (soap_attribute(soap
, "SOAP-ENV:mustUnderstand", soap
->version
== 2 ? "true" : "1"))
9727 soap
->mustUnderstand
= 0;
9730 { if (soap
->encodingStyle
&& soap
->local_namespaces
&& soap
->local_namespaces
[0].id
&& soap
->local_namespaces
[1].id
)
9731 { if (!*soap
->encodingStyle
)
9732 { if (soap
->local_namespaces
[1].out
)
9733 soap
->encodingStyle
= soap
->local_namespaces
[1].out
;
9735 soap
->encodingStyle
= soap
->local_namespaces
[1].ns
;
9737 if (soap
->encodingStyle
&& soap_attribute(soap
, "SOAP-ENV:encodingStyle", soap
->encodingStyle
))
9741 soap
->encodingStyle
= NULL
;
9746 if (soap
->event
== SOAP_SEC_BEGIN
)
9752 /******************************************************************************/
9757 soap_element_begin_out(struct soap
*soap
, const char *tag
, int id
, const char *type
)
9760 if (soap_element(soap
, tag
, id
, type
))
9763 if (soap_element_start_end_out(soap
, NULL
))
9765 if (soap
->feltbegout
)
9766 return soap
->error
= soap
->feltbegout(soap
, tag
);
9769 return soap_element_start_end_out(soap
, NULL
);
9774 /******************************************************************************/
9776 #ifndef HAVE_STRRCHR
9780 soap_strrchr(const char *s
, int t
)
9781 { register char *r
= NULL
;
9790 /******************************************************************************/
9796 soap_strtol(const char *s
, char **t
, int b
)
9797 { register long n
= 0;
9799 while (*s
> 0 && *s
<= 32)
9809 while ((c
= *s
) && c
>= '0' && c
<= '9')
9810 { if (n
>= 214748364 && (n
> 214748364 || c
>= '8'))
9819 else /* assume b == 16 and value is always positive */
9821 { if (c
>= '0' && c
<= '9')
9823 else if (c
>= 'A' && c
<= 'F')
9825 else if (c
>= 'a' && c
<= 'f')
9841 /******************************************************************************/
9843 #ifndef HAVE_STRTOUL
9847 soap_strtoul(const char *s
, char **t
, int b
)
9848 { unsigned long n
= 0;
9850 while (*s
> 0 && *s
<= 32)
9855 while ((c
= *s
) && c
>= '0' && c
<= '9')
9856 { if (n
>= 429496729 && (n
> 429496729 || c
>= '6'))
9865 { if (c
>= '0' && c
<= '9')
9867 else if (c
>= 'A' && c
<= 'F')
9869 else if (c
>= 'a' && c
<= 'f')
9885 /******************************************************************************/
9890 soap_array_begin_out(struct soap
*soap
, const char *tag
, int id
, const char *type
, const char *offset
)
9891 { if (!type
|| !*type
)
9892 return soap_element_begin_out(soap
, tag
, id
, NULL
);
9893 if (soap_element(soap
, tag
, id
, "SOAP-ENC:Array"))
9895 if (soap
->version
== 2)
9897 s
= soap_strrchr(type
, '[');
9898 if (s
&& (size_t)(s
- type
) < sizeof(soap
->tmpbuf
))
9899 { strncpy(soap
->tmpbuf
, type
, s
- type
);
9900 soap
->tmpbuf
[s
- type
] = '\0';
9901 if (soap_attribute(soap
, "SOAP-ENC:itemType", soap
->tmpbuf
))
9905 { strncpy(soap
->tmpbuf
, s
, sizeof(soap
->tmpbuf
));
9906 soap
->tmpbuf
[sizeof(soap
->tmpbuf
) - 1] = '\0';
9907 soap
->tmpbuf
[strlen(soap
->tmpbuf
) - 1] = '\0';
9908 if (soap_attribute(soap
, "SOAP-ENC:arraySize", soap
->tmpbuf
))
9914 { if (offset
&& soap_attribute(soap
, "SOAP-ENC:offset", offset
))
9916 if (soap_attribute(soap
, "SOAP-ENC:arrayType", type
))
9920 if ((soap
->mode
& SOAP_XML_CANONICAL
))
9921 soap_utilize_ns(soap
, type
);
9923 return soap_element_start_end_out(soap
, NULL
);
9927 /******************************************************************************/
9932 soap_element_start_end_out(struct soap
*soap
, const char *tag
)
9933 { register struct soap_attribute
*tp
;
9935 if (soap
->mode
& SOAP_XML_CANONICAL
)
9936 { struct soap_nlist
*np
;
9937 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9938 { if (tp
->visible
&& tp
->name
)
9939 soap_utilize_ns(soap
, tp
->name
);
9941 for (np
= soap
->nlist
; np
; np
= np
->next
)
9942 { if (np
->index
== 1 && np
->ns
)
9945 #ifdef HAVE_SNPRINTF
9946 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "xmlns:%s", np
->id
);
9948 sprintf(soap
->tmpbuf
, "xmlns:%s", np
->id
);
9952 strcpy(soap
->tmpbuf
, "xmlns");
9953 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Enabling utilized binding (level=%u) %s='%s'\n", np
->level
, soap
->tmpbuf
, np
->ns
));
9954 soap_set_attr(soap
, soap
->tmpbuf
, np
->ns
, 1);
9961 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9962 { register struct soap_dom_attribute
**att
;
9963 att
= &soap
->dom
->atts
;
9964 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9966 { *att
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
9969 (*att
)->next
= NULL
;
9970 (*att
)->nstr
= NULL
;
9971 (*att
)->name
= soap_strdup(soap
, tp
->name
);
9972 (*att
)->data
= soap_strdup(soap
, tp
->value
);
9973 (*att
)->wide
= NULL
;
9974 (*att
)->soap
= soap
;
9975 att
= &(*att
)->next
;
9982 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9987 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tp
->name
, ':')))
9988 { size_t n
= s
- tp
->name
;
9989 if (soap
->nlist
&& !strncmp(soap
->nlist
->id
, tp
->name
, n
) && !soap
->nlist
->id
[n
])
9993 if (soap_send(soap
, " ") || soap_send(soap
, s
))
9998 if (soap_send(soap
, " ") || soap_send(soap
, tp
->name
))
10000 if (tp
->visible
== 2 && tp
->value
)
10001 if (soap_send_raw(soap
, "=\"", 2)
10002 || soap_string_out(soap
, tp
->value
, tp
->flag
)
10003 || soap_send_raw(soap
, "\"", 1))
10004 return soap
->error
;
10011 if (soap
->mode
& SOAP_XML_CANONICAL
)
10012 { if (soap_send_raw(soap
, ">", 1)
10013 || soap_element_end_out(soap
, tag
))
10014 return soap
->error
;
10018 soap
->level
--; /* decrement level just before /> */
10019 return soap_send_raw(soap
, "/>", 2);
10021 return soap_send_raw(soap
, ">", 1);
10025 /******************************************************************************/
10030 soap_element_end_out(struct soap
*soap
, const char *tag
)
10037 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element ending tag='%s'\n", tag
));
10039 if (soap
->feltendout
&& (soap
->error
= soap
->feltendout(soap
, tag
)))
10040 return soap
->error
;
10041 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10042 { if (soap
->dom
->prnt
)
10043 soap
->dom
= soap
->dom
->prnt
;
10048 if (soap
->mode
& SOAP_XML_CANONICAL
)
10049 soap_pop_namespace(soap
);
10050 if (soap
->mode
& SOAP_XML_INDENT
)
10052 { if (soap_send_raw(soap
, soap_indent
, soap
->level
< sizeof(soap_indent
) ? soap
->level
: sizeof(soap_indent
) - 1))
10053 return soap
->error
;
10057 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tag
, ':')))
10058 { soap_pop_namespace(soap
);
10062 if (soap_send_raw(soap
, "</", 2)
10063 || soap_send(soap
, tag
))
10064 return soap
->error
;
10065 soap
->level
--; /* decrement level just before > */
10066 return soap_send_raw(soap
, ">", 1);
10070 /******************************************************************************/
10075 soap_element_ref(struct soap
*soap
, const char *tag
, int id
, int href
)
10076 { register const char *s
= "ref";
10077 register int n
= 1;
10078 if (soap
->version
== 1)
10082 else if (soap
->version
== 2)
10083 s
= "SOAP-ENC:ref";
10084 #ifdef HAVE_SNPRINTF
10085 soap_snprintf(soap
->href
, sizeof(soap
->href
), "#_%d", href
);
10087 sprintf(soap
->href
, "#_%d", href
);
10089 return soap_element_href(soap
, tag
, id
, s
, soap
->href
+ n
);
10093 /******************************************************************************/
10098 soap_element_href(struct soap
*soap
, const char *tag
, int id
, const char *ref
, const char *val
)
10099 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element '%s' reference %s='%s'\n", tag
, ref
, val
));
10100 if (soap_element(soap
, tag
, id
, NULL
)
10101 || soap_attribute(soap
, ref
, val
)
10102 || soap_element_start_end_out(soap
, tag
))
10103 return soap
->error
;
10108 /******************************************************************************/
10113 soap_element_null(struct soap
*soap
, const char *tag
, int id
, const char *type
)
10114 { struct soap_attribute
*tp
= NULL
;
10115 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10118 if (tp
|| (soap
->version
== 2 && soap
->position
> 0) || id
> 0 || (soap
->mode
& SOAP_XML_NIL
))
10119 { if (soap_element(soap
, tag
, id
, type
)
10120 || (!tp
&& soap_attribute(soap
, "xsi:nil", "true")))
10121 return soap
->error
;
10122 return soap_element_start_end_out(soap
, tag
);
10125 soap
->position
= 0;
10126 soap
->mustUnderstand
= 0;
10131 /******************************************************************************/
10136 soap_element_nil(struct soap
*soap
, const char *tag
)
10137 { if (soap_element(soap
, tag
, -1, NULL
)
10138 || ((soap
->mode
& SOAP_XML_NIL
) && soap_attribute(soap
, "xsi:nil", "true")))
10139 return soap
->error
;
10140 return soap_element_start_end_out(soap
, tag
);
10144 /******************************************************************************/
10149 soap_element_id(struct soap
*soap
, const char *tag
, int id
, const void *p
, const struct soap_array
*a
, int n
, const char *type
, int t
)
10151 { soap
->error
= soap_element_null(soap
, tag
, id
, type
);
10154 #ifndef WITH_NOIDREF
10155 if ((!soap
->encodingStyle
&& !(soap
->omode
& SOAP_XML_GRAPH
)) || (soap
->omode
& SOAP_XML_TREE
))
10158 { struct soap_plist
*pp
;
10160 id
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
10162 id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
10164 { if (soap_is_embedded(soap
, pp
))
10165 { soap_element_ref(soap
, tag
, 0, id
);
10168 if (soap_is_single(soap
, pp
))
10170 soap_set_embedded(soap
, pp
);
10180 /******************************************************************************/
10185 soap_element_result(struct soap
*soap
, const char *tag
)
10186 { if (soap
->version
== 2 && soap
->encodingStyle
)
10187 { if (soap_element(soap
, "SOAP-RPC:result", 0, NULL
)
10188 || soap_attribute(soap
, "xmlns:SOAP-RPC", soap_rpc
)
10189 || soap_element_start_end_out(soap
, NULL
)
10190 || soap_string_out(soap
, tag
, 0)
10191 || soap_element_end_out(soap
, "SOAP-RPC:result"))
10192 return soap
->error
;
10198 /******************************************************************************/
10203 soap_check_result(struct soap
*soap
, const char *tag
)
10204 { if (soap
->version
== 2 && soap
->encodingStyle
)
10205 { soap_instring(soap
, ":result", NULL
, NULL
, 0, 2, -1, -1);
10206 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
10212 /******************************************************************************/
10217 soap_attribute(struct soap
*soap
, const char *name
, const char *value
)
10219 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Attribute '%s'='%s'\n", name
, value
));
10221 if ((soap
->mode
& SOAP_XML_DOM
) && !(soap
->mode
& SOAP_XML_CANONICAL
) && soap
->dom
)
10222 { register struct soap_dom_attribute
*a
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
10224 return soap
->error
;
10225 a
->next
= soap
->dom
->atts
;
10227 a
->name
= soap_strdup(soap
, name
);
10228 a
->data
= soap_strdup(soap
, value
);
10231 soap
->dom
->atts
= a
;
10236 if (soap
->mode
& SOAP_XML_CANONICAL
)
10237 { /* push namespace */
10238 if (!strncmp(name
, "xmlns", 5) && (name
[5] == ':' || name
[5] == '\0'))
10239 soap_push_ns(soap
, name
+ 5 + (name
[5] == ':'), value
, 0);
10240 else if (soap_set_attr(soap
, name
, value
, 1))
10241 return soap
->error
;
10245 { if (soap_send(soap
, " ") || soap_send(soap
, name
))
10246 return soap
->error
;
10248 if (soap_send_raw(soap
, "=\"", 2)
10249 || soap_string_out(soap
, value
, 1)
10250 || soap_send_raw(soap
, "\"", 1))
10251 return soap
->error
;
10257 /******************************************************************************/
10262 soap_element_begin_in(struct soap
*soap
, const char *tag
, int nillable
, const char *type
)
10263 { if (!soap_peek_element(soap
))
10265 return soap
->error
= SOAP_TAG_MISMATCH
;
10266 if (tag
&& *tag
== '-')
10268 if (!(soap
->error
= soap_match_tag(soap
, soap
->tag
, tag
)))
10269 { soap
->peeked
= 0;
10270 if (type
&& *soap
->type
&& soap_match_tag(soap
, soap
->type
, type
))
10271 return soap
->error
= SOAP_TYPE
;
10272 if (!nillable
&& soap
->null
&& (soap
->mode
& SOAP_XML_STRICT
))
10273 return soap
->error
= SOAP_NULL
;
10276 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Begin element found (level=%u) '%s'='%s'\n", soap
->level
, soap
->tag
, tag
? tag
: SOAP_STR_EOS
));
10277 soap
->error
= SOAP_OK
;
10280 else if (soap
->error
== SOAP_NO_TAG
&& tag
&& *tag
== '-')
10281 soap
->error
= SOAP_OK
;
10282 return soap
->error
;
10286 /******************************************************************************/
10291 soap_element_end_in(struct soap
*soap
, const char *tag
)
10292 { register soap_wchar c
;
10294 register int n
= 0;
10295 if (tag
&& *tag
== '-')
10297 if (soap
->error
== SOAP_NO_TAG
)
10298 soap
->error
= SOAP_OK
;
10300 /* this whitespace or mixed content is significant for DOM */
10301 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10302 { if (!soap
->peeked
&& !soap_string_in(soap
, 3, -1, -1))
10303 return soap
->error
;
10304 if (soap
->dom
->prnt
)
10305 soap
->dom
= soap
->dom
->prnt
;
10314 { while (((c
= soap_get(soap
)) != SOAP_TT
))
10315 { if ((int)c
== EOF
)
10316 return soap
->error
= SOAP_CHK_EOF
;
10320 { c
= soap_get(soap
);
10324 soap_unget(soap
, c
);
10329 n
= sizeof(soap
->tag
);
10330 while (soap_notblank(c
= soap_get(soap
)))
10336 return soap
->error
= SOAP_CHK_EOF
;
10337 while (soap_blank(c
))
10338 c
= soap_get(soap
);
10340 return soap
->error
= SOAP_SYNTAX_ERROR
;
10343 if (soap
->feltendin
)
10345 return soap
->error
= soap
->feltendin(soap
, soap
->tag
, tag
);
10348 if (tag
&& (soap
->mode
& SOAP_XML_STRICT
))
10349 { soap_pop_namespace(soap
);
10350 if (soap_match_tag(soap
, soap
->tag
, tag
))
10351 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End element tag '%s' does not match '%s'\n", soap
->tag
, tag
? tag
: SOAP_STR_EOS
));
10352 return soap
->error
= SOAP_SYNTAX_ERROR
;
10356 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End element found (level=%u) '%s'='%s'\n", soap
->level
, soap
->tag
, tag
? tag
: SOAP_STR_EOS
));
10362 /******************************************************************************/
10367 soap_attr_value(struct soap
*soap
, const char *name
, int flag
)
10368 { register struct soap_attribute
*tp
;
10370 return SOAP_STR_EOS
;
10371 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10372 { if (tp
->visible
&& !soap_match_tag(soap
, tp
->name
, name
))
10376 { if (flag
== 2 && (soap
->mode
& SOAP_XML_STRICT
))
10377 soap
->error
= SOAP_PROHIBITED
;
10381 else if (flag
== 1 && (soap
->mode
& SOAP_XML_STRICT
))
10382 soap
->error
= SOAP_REQUIRED
;
10384 soap
->error
= SOAP_OK
;
10389 /******************************************************************************/
10394 soap_set_attr(struct soap
*soap
, const char *name
, const char *value
, int flag
)
10395 { register struct soap_attribute
*tp
;
10398 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set attribute %s='%s'\n", name
, value
? value
: SOAP_STR_EOS
));
10399 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10400 { if (!strcmp(tp
->name
, name
))
10404 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Allocate attribute %s\n", name
));
10405 if (!(tp
= (struct soap_attribute
*)SOAP_MALLOC(soap
, sizeof(struct soap_attribute
) + strlen(name
))))
10406 return soap
->error
= SOAP_EOM
;
10409 if ((soap
->mode
& SOAP_XML_CANONICAL
))
10410 { struct soap_attribute
**tpp
= &soap
->attributes
;
10411 const char *s
= strchr(name
, ':');
10412 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inserting attribute %s for c14n\n", name
));
10413 if (!strncmp(name
, "xmlns", 5))
10414 { for (; *tpp
; tpp
= &(*tpp
)->next
)
10415 if (strncmp((*tpp
)->name
, "xmlns", 5) || strcmp((*tpp
)->name
+ 5, name
+ 5) > 0)
10419 { for (; *tpp
; tpp
= &(*tpp
)->next
)
10420 if (strncmp((*tpp
)->name
, "xmlns", 5) && ((*tpp
)->ns
|| strcmp((*tpp
)->name
, name
) > 0))
10424 { struct soap_nlist
*np
= soap_lookup_ns(soap
, name
, s
- name
);
10428 { struct soap_attribute
*tq
;
10429 for (tq
= soap
->attributes
; tq
; tq
= tq
->next
)
10430 { if (!strncmp(tq
->name
, "xmlns:", 6) && !strncmp(tq
->name
+ 6, name
, s
- name
) && !tq
->name
[6 + s
- name
])
10436 for (; *tpp
; tpp
= &(*tpp
)->next
)
10438 if (strncmp((*tpp
)->name
, "xmlns", 5) && (*tpp
)->ns
&& tp
->ns
&& ((k
= strcmp((*tpp
)->ns
, tp
->ns
)) > 0 || (!k
&& strcmp((*tpp
)->name
, name
) > 0)))
10447 { tp
->next
= soap
->attributes
;
10448 soap
->attributes
= tp
;
10450 strcpy((char*)tp
->name
, name
);
10453 else if (tp
->visible
)
10456 else if (value
&& tp
->value
&& tp
->size
<= strlen(value
))
10457 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free attribute value of %s (free %p)\n", name
, tp
->value
));
10458 SOAP_FREE(soap
, tp
->value
);
10464 { tp
->size
= strlen(value
) + 1;
10465 if (!(tp
->value
= (char*)SOAP_MALLOC(soap
, tp
->size
)))
10466 return soap
->error
= SOAP_EOM
;
10467 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Allocate attribute value for %s (%p)\n", tp
->name
, tp
->value
));
10469 strcpy(tp
->value
, value
);
10470 if (!strncmp(tp
->name
, "xmlns:", 6))
10471 tp
->ns
= tp
->value
;
10473 tp
->flag
= (short)flag
;
10475 if (!strcmp(name
, "wsu:Id"))
10476 { soap
->event
= SOAP_SEC_BEGIN
;
10477 strncpy(soap
->id
, value
, sizeof(soap
->id
));
10478 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
10488 /******************************************************************************/
10493 soap_clr_attr(struct soap
*soap
)
10494 { register struct soap_attribute
*tp
;
10496 if ((soap
->mode
& SOAP_XML_CANONICAL
))
10497 { while (soap
->attributes
)
10498 { tp
= soap
->attributes
->next
;
10499 if (soap
->attributes
->value
)
10500 SOAP_FREE(soap
, soap
->attributes
->value
);
10501 SOAP_FREE(soap
, soap
->attributes
);
10502 soap
->attributes
= tp
;
10507 { for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10513 /******************************************************************************/
10516 soap_getattrval(struct soap
*soap
, char *s
, size_t n
, soap_wchar d
)
10517 { register size_t i
;
10518 for (i
= 0; i
< n
; i
++)
10519 { register soap_wchar c
= soap_get(soap
);
10524 soap_unget(soap
, '/');
10531 { soap_unget(soap
, c
);
10557 { soap_unget(soap
, c
);
10564 return soap
->error
= SOAP_CHK_EOF
;
10569 return soap
->error
= SOAP_EOM
;
10573 /******************************************************************************/
10579 soap_store_lab(struct soap
*soap
, const char *s
, size_t n
)
10580 { soap
->labidx
= 0;
10581 return soap_append_lab(soap
, s
, n
);
10586 /******************************************************************************/
10592 soap_append_lab(struct soap
*soap
, const char *s
, size_t n
)
10593 { if (soap
->labidx
+ n
>= soap
->lablen
)
10594 { register char *t
= soap
->labbuf
;
10595 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap
->lablen
));
10596 if (soap
->lablen
== 0)
10597 soap
->lablen
= SOAP_LABLEN
;
10598 while (soap
->labidx
+ n
>= soap
->lablen
)
10599 soap
->lablen
<<= 1;
10600 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "New look-aside buffer size=%lu\n", (unsigned long)soap
->lablen
));
10601 soap
->labbuf
= (char*)SOAP_MALLOC(soap
, soap
->lablen
);
10604 SOAP_FREE(soap
, t
);
10605 return soap
->error
= SOAP_EOM
;
10608 { memcpy(soap
->labbuf
, t
, soap
->labidx
);
10609 SOAP_FREE(soap
, t
);
10613 { memcpy(soap
->labbuf
+ soap
->labidx
, s
, n
);
10621 /******************************************************************************/
10626 soap_peek_element(struct soap
*soap
)
10629 register struct soap_dom_attribute
**att
= NULL
;
10630 register char *lead
= NULL
;
10632 register struct soap_attribute
*tp
, *tq
= NULL
;
10633 register const char *t
;
10635 register soap_wchar c
;
10639 return soap
->error
= SOAP_NO_TAG
;
10643 soap
->id
[0] = '\0';
10644 soap
->href
[0] = '\0';
10645 soap
->type
[0] = '\0';
10646 soap
->arrayType
[0] = '\0';
10647 soap
->arraySize
[0] = '\0';
10648 soap
->arrayOffset
[0] = '\0';
10651 soap
->position
= 0;
10653 soap
->mustUnderstand
= 0;
10655 c
= soap_getchar(soap
);
10656 if (c
== 0xEF && soap_get0(soap
) == 0xBB)
10657 { c
= soap_get1(soap
);
10658 if ((c
= soap_get1(soap
)) == 0xBF)
10659 soap
->mode
&= ~SOAP_ENC_LATIN
;
10661 soap_unget(soap
, (0x0F << 12) | (0xBB << 6) | (c
& 0x3F)); /* UTF-8 */
10663 else if ((c
== 0xFE && soap_get0(soap
) == 0xFF) /* UTF-16 BE */
10664 || (c
== 0xFF && soap_get0(soap
) == 0xFE)) /* UTF-16 LE */
10665 return soap
->error
= SOAP_UTF_ERROR
;
10667 soap_unget(soap
, c
);
10668 c
= soap_get(soap
);
10670 /* whitespace leading to tag is not insignificant for DOM */
10672 { soap
->labidx
= 0;
10674 { if (soap_append_lab(soap
, NULL
, 0))
10675 return soap
->error
;
10676 s
= soap
->labbuf
+ soap
->labidx
;
10677 i
= soap
->lablen
- soap
->labidx
;
10678 soap
->labidx
= soap
->lablen
;
10679 while (soap_blank(c
) && i
--)
10681 c
= soap_get(soap
);
10684 while (soap_blank(c
));
10686 lead
= soap
->labbuf
;
10690 while (soap_blank(c
))
10691 c
= soap_get(soap
);
10694 { *soap
->tag
= '\0';
10696 return soap
->error
= SOAP_CHK_EOF
;
10697 soap_unget(soap
, c
);
10699 /* whitespace leading to end tag is significant for DOM */
10700 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10701 { if (lead
&& *lead
)
10702 soap
->dom
->tail
= soap_strdup(soap
, lead
);
10704 soap
->dom
->tail
= (char*)SOAP_STR_EOS
;
10707 return soap
->error
= SOAP_NO_TAG
;
10709 do c
= soap_get1(soap
);
10710 while (soap_blank(c
));
10712 i
= sizeof(soap
->tag
);
10713 while (c
!= '>' && c
!= '/' && soap_notblank(c
) && (int)c
!= EOF
)
10716 c
= soap_get1(soap
);
10719 while (soap_blank(c
))
10720 c
= soap_get1(soap
);
10722 if (soap
->mode
& SOAP_XML_DOM
)
10723 { register struct soap_dom_element
*elt
;
10724 elt
= (struct soap_dom_element
*)soap_malloc(soap
, sizeof(struct soap_dom_element
));
10726 return soap
->error
;
10729 elt
->name
= soap_strdup(soap
, soap
->tag
);
10730 elt
->prnt
= soap
->dom
;
10737 elt
->head
= soap_strdup(soap
, lead
);
10741 { struct soap_dom_element
*p
= soap
->dom
->elts
;
10748 soap
->dom
->elts
= elt
;
10754 soap_pop_namespace(soap
);
10755 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10757 while ((int)c
!= EOF
&& c
!= '>' && c
!= '/')
10758 { s
= soap
->tmpbuf
;
10759 i
= sizeof(soap
->tmpbuf
);
10760 while (c
!= '=' && c
!= '>' && c
!= '/' && soap_notblank(c
) && (int)c
!= EOF
)
10763 c
= soap_get1(soap
);
10766 if (i
== sizeof(soap
->tmpbuf
))
10767 return soap
->error
= SOAP_SYNTAX_ERROR
;
10769 /* add attribute name to dom */
10771 { *att
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
10773 return soap
->error
;
10774 (*att
)->next
= NULL
;
10775 (*att
)->nstr
= NULL
;
10776 (*att
)->name
= soap_strdup(soap
, soap
->tmpbuf
);
10777 (*att
)->data
= NULL
;
10778 (*att
)->wide
= NULL
;
10779 (*att
)->soap
= soap
;
10782 if (!strncmp(soap
->tmpbuf
, "xmlns", 5))
10783 { if (soap
->tmpbuf
[5] == ':')
10784 t
= soap
->tmpbuf
+ 6;
10785 else if (soap
->tmpbuf
[5])
10793 for (tp
= soap
->attributes
; tp
; tq
= tp
, tp
= tp
->next
)
10794 { if (!SOAP_STRCMP(tp
->name
, soap
->tmpbuf
))
10798 { tp
= (struct soap_attribute
*)SOAP_MALLOC(soap
, sizeof(struct soap_attribute
) + strlen(soap
->tmpbuf
));
10800 return soap
->error
= SOAP_EOM
;
10801 strcpy((char*)tp
->name
, soap
->tmpbuf
);
10805 /* if attribute name is qualified, append it to the end of the list */
10806 if (tq
&& strchr(soap
->tmpbuf
, ':'))
10811 { tp
->next
= soap
->attributes
;
10812 soap
->attributes
= tp
;
10815 while (soap_blank(c
))
10816 c
= soap_get1(soap
);
10818 { do c
= soap_getutf8(soap
);
10819 while (soap_blank(c
));
10820 if (c
!= SOAP_QT
&& c
!= SOAP_AP
)
10821 { soap_unget(soap
, c
);
10822 c
= ' '; /* blank delimiter */
10824 if (soap_getattrval(soap
, tp
->value
, tp
->size
, c
))
10827 if (soap
->error
!= SOAP_EOM
)
10828 return soap
->error
;
10829 soap
->error
= SOAP_OK
;
10830 if (soap_store_lab(soap
, tp
->value
, tp
->size
))
10831 return soap
->error
;
10833 SOAP_FREE(soap
, tp
->value
);
10836 { if (soap_getattrval(soap
, soap
->labbuf
+ soap
->labidx
, soap
->lablen
- soap
->labidx
, c
))
10837 { if (soap
->error
!= SOAP_EOM
)
10838 return soap
->error
;
10839 soap
->error
= SOAP_OK
;
10840 soap
->labidx
= soap
->lablen
;
10841 if (soap_append_lab(soap
, NULL
, 0))
10842 return soap
->error
;
10848 tp
->size
= soap
->lablen
;
10850 { tp
->size
= strlen(soap
->labbuf
) + 1;
10851 if (tp
->size
< SOAP_LABLEN
)
10852 tp
->size
= SOAP_LABLEN
;
10854 if (!(tp
->value
= (char*)SOAP_MALLOC(soap
, tp
->size
)))
10855 return soap
->error
= SOAP_EOM
;
10856 strcpy(tp
->value
, soap
->labbuf
);
10859 if (soap
->error
!= SOAP_EOM
)
10860 return soap
->error
;
10861 soap
->error
= SOAP_OK
;
10862 if (soap_new_block(soap
) == NULL
)
10863 return soap
->error
;
10865 { if (!(s
= (char*)soap_push_block(soap
, NULL
, SOAP_BLKLEN
)))
10866 return soap
->error
;
10867 if (soap_getattrval(soap
, s
, SOAP_BLKLEN
, c
))
10868 { if (soap
->error
!= SOAP_EOM
)
10869 return soap
->error
;
10870 soap
->error
= SOAP_OK
;
10875 n
= tp
->size
+ soap
->blist
->size
;
10876 if (!(s
= (char*)SOAP_MALLOC(soap
, n
)))
10877 return soap
->error
= SOAP_EOM
;
10879 { memcpy(s
, tp
->value
, tp
->size
);
10880 SOAP_FREE(soap
, tp
->value
);
10882 soap_save_block(soap
, NULL
, s
+ tp
->size
, 0);
10887 do c
= soap_get1(soap
);
10888 while (soap_blank(c
));
10889 tp
->visible
= 2; /* seen this attribute w/ value */
10892 (*att
)->data
= soap_strdup(soap
, tp
->value
);
10896 tp
->visible
= 1; /* seen this attribute w/o value */
10899 att
= &(*att
)->next
;
10901 if (t
&& tp
->value
)
10902 { if (soap_push_namespace(soap
, t
, tp
->value
) == NULL
)
10903 return soap
->error
;
10908 { soap
->dom
->nstr
= soap_current_namespace(soap
, soap
->tag
);
10909 for (att
= &soap
->dom
->atts
; *att
; att
= &(*att
)->next
)
10910 (*att
)->nstr
= soap_current_namespace(soap
, (*att
)->name
);
10914 return soap
->error
= SOAP_CHK_EOF
;
10915 if (!(soap
->body
= (c
!= '/')))
10916 do c
= soap_get1(soap
);
10917 while (soap_blank(c
));
10919 if (soap
->mode
& SOAP_XML_DOM
)
10920 { if (!soap
->body
&& soap
->dom
->prnt
)
10921 soap
->dom
= soap
->dom
->prnt
;
10924 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10925 { if (tp
->visible
&& tp
->value
)
10927 #ifndef WITH_NOIDREF
10928 if (!strcmp(tp
->name
, "id"))
10929 { if ((soap
->version
> 0 && !(soap
->imode
& SOAP_XML_TREE
))
10930 || (soap
->mode
& SOAP_XML_GRAPH
))
10932 strncpy(soap
->id
+ 1, tp
->value
, sizeof(soap
->id
) - 2);
10933 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
10936 else if (!strcmp(tp
->name
, "href"))
10937 { if ((soap
->version
== 1 && !(soap
->imode
& SOAP_XML_TREE
))
10938 || (soap
->mode
& SOAP_XML_GRAPH
)
10939 || (soap
->mode
& SOAP_ENC_MTOM
)
10940 || (soap
->mode
& SOAP_ENC_DIME
))
10941 { strncpy(soap
->href
, tp
->value
, sizeof(soap
->href
) - 1);
10942 soap
->href
[sizeof(soap
->href
) - 1] = '\0';
10945 else if (!strcmp(tp
->name
, "ref"))
10946 { if ((soap
->version
== 2 && !(soap
->imode
& SOAP_XML_TREE
))
10947 || (soap
->mode
& SOAP_XML_GRAPH
))
10948 { *soap
->href
= '#';
10949 strncpy(soap
->href
+ (*tp
->value
!= '#'), tp
->value
, sizeof(soap
->href
) - 2);
10950 soap
->href
[sizeof(soap
->href
) - 1] = '\0';
10955 if (!soap_match_tag(soap
, tp
->name
, "xsi:type"))
10956 { strncpy(soap
->type
, tp
->value
, sizeof(soap
->type
) - 1);
10957 soap
->type
[sizeof(soap
->type
) - 1] = '\0';
10959 else if ((!soap_match_tag(soap
, tp
->name
, "xsi:null")
10960 || !soap_match_tag(soap
, tp
->name
, "xsi:nil"))
10961 && (!strcmp(tp
->value
, "1")
10962 || !strcmp(tp
->value
, "true")))
10965 else if (soap
->version
== 1)
10966 { if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:arrayType"))
10967 { s
= soap_strrchr(tp
->value
, '[');
10968 if (s
&& (size_t)(s
- tp
->value
) < sizeof(soap
->arrayType
))
10969 { strncpy(soap
->arrayType
, tp
->value
, s
- tp
->value
);
10970 soap
->arrayType
[s
- tp
->value
] = '\0';
10971 strncpy(soap
->arraySize
, s
, sizeof(soap
->arraySize
));
10974 strncpy(soap
->arrayType
, tp
->value
, sizeof(soap
->arrayType
));
10975 soap
->arraySize
[sizeof(soap
->arraySize
) - 1] = '\0';
10976 soap
->arrayType
[sizeof(soap
->arrayType
) - 1] = '\0';
10978 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:offset"))
10979 strncpy(soap
->arrayOffset
, tp
->value
, sizeof(soap
->arrayOffset
));
10980 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:position"))
10981 soap
->position
= soap_getposition(tp
->value
, soap
->positions
);
10982 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:root"))
10983 soap
->root
= ((!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")));
10984 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:mustUnderstand")
10985 && (!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")))
10986 soap
->mustUnderstand
= 1;
10987 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:actor"))
10988 { if ((!soap
->actor
|| strcmp(soap
->actor
, tp
->value
))
10989 && strcmp(tp
->value
, "http://schemas.xmlsoap.org/soap/actor/next"))
10993 else if (soap
->version
== 2)
10995 #ifndef WITH_NOIDREF
10996 if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:id"))
10998 strncpy(soap
->id
+ 1, tp
->value
, sizeof(soap
->id
) - 2);
10999 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
11001 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:ref"))
11002 { *soap
->href
= '#';
11003 strncpy(soap
->href
+ (*tp
->value
!= '#'), tp
->value
, sizeof(soap
->href
) - 2);
11004 soap
->href
[sizeof(soap
->href
) - 1] = '\0';
11008 if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:itemType"))
11009 strncpy(soap
->arrayType
, tp
->value
, sizeof(soap
->arrayType
) - 1);
11010 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:arraySize"))
11011 strncpy(soap
->arraySize
, tp
->value
, sizeof(soap
->arraySize
) - 1);
11012 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:mustUnderstand")
11013 && (!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")))
11014 soap
->mustUnderstand
= 1;
11015 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:role"))
11016 { if ((!soap
->actor
|| strcmp(soap
->actor
, tp
->value
))
11017 && strcmp(tp
->value
, "http://www.w3.org/2003/05/soap-envelope/role/next"))
11022 { if (!soap_match_tag(soap
, tp
->name
, "wsdl:required") && !strcmp(tp
->value
, "true"))
11023 soap
->mustUnderstand
= 1;
11028 if (soap
->feltbegin
)
11029 return soap
->error
= soap
->feltbegin(soap
, soap
->tag
);
11031 return soap
->error
= SOAP_OK
;
11035 /******************************************************************************/
11040 soap_retry(struct soap
*soap
)
11041 { soap
->error
= SOAP_OK
;
11046 /******************************************************************************/
11051 soap_revert(struct soap
*soap
)
11052 { if (!soap
->peeked
)
11053 { soap
->peeked
= 1;
11057 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reverting to last element '%s' (level=%u)\n", soap
->tag
, soap
->level
));
11061 /******************************************************************************/
11066 soap_string_out(struct soap
*soap
, const char *s
, int flag
)
11067 { register const char *t
;
11068 register soap_wchar c
;
11069 register soap_wchar mask
= (soap_wchar
)0xFFFFFF80UL
;
11071 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
11072 { soap
->dom
->data
= soap_strdup(soap
, s
);
11076 if (flag
== 2 || soap
->mode
& SOAP_C_UTFSTRING
)
11084 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "	", 5))
11085 return soap
->error
;
11090 if (flag
|| !(soap
->mode
& SOAP_XML_CANONICAL
))
11091 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "
", 5))
11092 return soap
->error
;
11097 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "
", 5))
11098 return soap
->error
;
11102 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "&", 5))
11103 return soap
->error
;
11107 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "<", 4))
11108 return soap
->error
;
11113 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, ">", 4))
11114 return soap
->error
;
11120 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, """, 6))
11121 return soap
->error
;
11126 #ifndef WITH_LEANER
11128 if (soap
->mode
& SOAP_C_MBSTRING
)
11130 register int m
= mbtowc(&wc
, t
- 1, MB_CUR_MAX
);
11131 if (m
> 0 && !((soap_wchar
)wc
== c
&& m
== 1 && c
< 0x80))
11132 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_pututf8(soap
, (unsigned long)wc
))
11133 return soap
->error
;
11140 #ifndef WITH_NOSTRINGTOUTF8
11141 if ((c
& mask
) || !(c
& 0xFFFFFFE0UL
))
11142 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_pututf8(soap
, (unsigned char)c
))
11143 return soap
->error
;
11149 return soap_send_raw(soap
, s
, t
- s
- 1);
11153 /******************************************************************************/
11158 soap_string_in(struct soap
*soap
, int flag
, long minlen
, long maxlen
)
11159 { register char *s
;
11162 register long l
= 0;
11163 register int n
= 0, f
= 0, m
= 0;
11164 register soap_wchar c
;
11165 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
11166 char buf
[MB_LEN_MAX
> 8 ? MB_LEN_MAX
: 8];
11170 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Reading string content, flag=%d\n", flag
));
11171 if (soap
->peeked
&& *soap
->tag
)
11174 struct soap_attribute
*tp
;
11175 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String content includes tag '%s' and attributes\n", soap
->tag
));
11178 strncpy(t
+ 1, soap
->tag
, sizeof(soap
->tmpbuf
) - 2);
11179 t
[sizeof(soap
->tmpbuf
) - 1] = '\0';
11181 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
11183 { if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
11186 strcpy(t
, tp
->name
);
11188 if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
11189 break; /* too many or large attribute values */
11193 strcpy(t
, tp
->value
);
11204 m
= (int)strlen(soap
->tmpbuf
);
11213 { register int state
= 0;
11215 soap
->labidx
= 0; /* use look-aside buffer */
11217 if (soap_new_block(soap
) == NULL
)
11224 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
11226 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
11227 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
11228 soap
->labidx
= soap
->lablen
; /* claim this space */
11230 register size_t k
= SOAP_BLKLEN
;
11231 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
11234 for (i
= 0; i
< k
; i
++)
11236 { *s
++ = *t
++; /* copy multibyte characters */
11240 c
= soap_getchar(soap
);
11243 if ((c
>= 0x80 || c
< SOAP_AP
) && state
!= 1 && !(soap
->mode
& SOAP_ENC_LATIN
))
11244 { if ((c
& 0x7FFFFFFF) >= 0x80)
11245 { soap_unget(soap
, c
);
11246 c
= soap_getutf8(soap
);
11248 if ((c
& 0x7FFFFFFF) >= 0x80 && (!flag
|| (soap
->mode
& SOAP_C_UTFSTRING
)))
11252 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
11254 { if (c
< 0x010000)
11255 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
11257 { if (c
< 0x200000)
11258 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
11260 { if (c
< 0x04000000)
11261 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
11263 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
11264 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
11266 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
11268 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
11270 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
11272 *t
++ = (char)(0x80 | (c
& 0x3F));
11273 m
= (int)(t
- buf
) - 1;
11361 { c
= soap_getchar(soap
);
11364 soap_unget(soap
, c
);
11369 c
= soap_getchar(soap
);
11378 { c
= soap_getchar(soap
);
11380 { do c
= soap_getchar(soap
);
11381 while ((int)c
!= EOF
&& c
!= '[');
11384 t
= (char*)"![CDATA[";
11389 { if ((c
= soap_getchar(soap
)) == '-')
11393 soap_unget(soap
, c
);
11398 soap_unget(soap
, c
);
11405 else if (f
&& n
== 0)
11406 { soap_revget1(soap
);
11412 soap_unget(soap
, c
);
11422 #ifndef WITH_LEANER
11424 if (soap
->mode
& SOAP_C_MBSTRING
)
11425 { m
= wctomb(buf
, (wchar_t)(c
& 0x7FFFFFFF));
11426 if (m
>= 1 && m
<= (int)MB_CUR_MAX
)
11432 { *s
++ = SOAP_UNKNOWN_CHAR
;
11439 *s
++ = (char)(c
& 0xFF);
11442 if (maxlen
>= 0 && l
> maxlen
)
11443 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
11444 soap
->error
= SOAP_LENGTH
;
11452 soap
->labidx
= 0; /* use look-aside buffer */
11454 if (soap_new_block(soap
) == NULL
)
11461 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
11463 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
11464 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
11465 soap
->labidx
= soap
->lablen
; /* claim this space */
11467 register size_t k
= SOAP_BLKLEN
;
11468 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
11471 for (i
= 0; i
< k
; i
++)
11473 { *s
++ = *t
++; /* copy multibyte characters */
11479 c
= soap_getchar(soap
);
11482 if ((soap
->mode
& SOAP_C_UTFSTRING
))
11483 { if (((c
= soap_get(soap
)) & 0x80000000) && c
>= -0x7FFFFF80 && c
< SOAP_AP
)
11487 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
11489 { if (c
< 0x010000)
11490 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
11492 { if (c
< 0x200000)
11493 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
11495 { if (c
< 0x04000000)
11496 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
11498 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
11499 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
11501 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
11503 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
11505 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
11507 *t
++ = (char)(0x80 | (c
& 0x3F));
11508 m
= (int)(t
- buf
) - 1;
11515 c
= soap_getutf8(soap
);
11544 { c
= soap_getchar(soap
);
11549 { c
= soap_get(soap
);
11553 soap_unget(soap
, c
);
11557 case (soap_wchar
)('<' | 0x80000000):
11566 case (soap_wchar
)('>' | 0x80000000):
11575 case (soap_wchar
)('&' | 0x80000000):
11584 case (soap_wchar
)('"' | 0x80000000):
11589 t
= (char*)"quot;";
11593 case (soap_wchar
)('\'' | 0x80000000):
11598 t
= (char*)"apos;";
11606 if (c
== '<' && !flag
)
11609 c
= soap_getchar(soap
);
11610 soap_unget(soap
, c
);
11624 #ifndef WITH_LEANER
11626 if (soap
->mode
& SOAP_C_MBSTRING
)
11627 { m
= wctomb(buf
, (wchar_t)(c
& 0x7FFFFFFF));
11628 if (m
>= 1 && m
<= (int)MB_CUR_MAX
)
11634 { *s
++ = SOAP_UNKNOWN_CHAR
;
11641 *s
++ = (char)(c
& 0xFF);
11644 if (maxlen
>= 0 && l
> maxlen
)
11645 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
11646 soap
->error
= SOAP_LENGTH
;
11652 soap_unget(soap
, c
);
11655 t
= soap_strdup(soap
, soap
->labbuf
);
11657 soap_size_block(soap
, NULL
, i
+ 1);
11658 t
= soap_save_block(soap
, NULL
, 0);
11661 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too short: %ld chars, minlen=%ld\n", l
, minlen
));
11662 soap
->error
= SOAP_LENGTH
;
11666 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
11668 soap
->dom
->tail
= t
;
11670 soap
->dom
->data
= t
;
11674 if (soap_s2QName(soap
, t
, &t
, minlen
, maxlen
))
11680 /******************************************************************************/
11681 #ifndef WITH_LEANER
11686 soap_wstring_out(struct soap
*soap
, const wchar_t *s
, int flag
)
11689 register soap_wchar c
;
11691 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
11692 { wchar_t *r
= (wchar_t*)s
;
11696 soap
->dom
->wide
= r
= (wchar_t*)soap_malloc(soap
, n
* sizeof(wchar_t));
11712 if (flag
|| !(soap
->mode
& SOAP_XML_CANONICAL
))
11739 if (c
>= 0x20 && c
< 0x80)
11741 if (soap_send_raw(soap
, &tmp
, 1))
11742 return soap
->error
;
11745 { /* check for UTF16 encoding when wchar_t is too small to hold UCS */
11746 if (sizeof(wchar_t) < 4 && (c
& 0xFC00) == 0xD800)
11747 { register soap_wchar d
= *s
++;
11748 if ((d
& 0xFC00) == 0xDC00)
11749 c
= ((c
- 0xD800) << 10) + (d
- 0xDC00) + 0x10000;
11751 c
= 0xFFFD; /* Malformed */
11753 if (soap_pututf8(soap
, (unsigned long)c
))
11754 return soap
->error
;
11758 if (soap_send(soap
, t
))
11759 return soap
->error
;
11766 /******************************************************************************/
11767 #ifndef WITH_LEANER
11772 soap_wstring_in(struct soap
*soap
, int flag
, long minlen
, long maxlen
)
11774 register int i
, n
= 0, f
= 0;
11775 register long l
= 0;
11776 register soap_wchar c
;
11778 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Reading wide string content\n"));
11783 struct soap_attribute
*tp
;
11786 strncpy(t
+ 1, soap
->tag
, sizeof(soap
->tmpbuf
) - 2);
11787 t
[sizeof(soap
->tmpbuf
) - 1] = '\0';
11789 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
11791 { if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
11794 strcpy(t
, tp
->name
);
11796 if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
11801 strcpy(t
, tp
->value
);
11819 if (soap_new_block(soap
) == NULL
)
11822 { if (!(s
= (wchar_t*)soap_push_block(soap
, NULL
, sizeof(wchar_t)*SOAP_BLKLEN
)))
11824 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
11826 { *s
++ = (wchar_t)*t
++;
11831 c
= soap_getutf8(soap
);
11839 soap_unget(soap
, '/');
11858 { c
= soap_getutf8(soap
);
11861 soap_unget(soap
, c
);
11867 *s
++ = (soap_wchar
)'<';
11869 { *s
++ = (soap_wchar
)'&';
11875 *s
++ = (soap_wchar
)'>';
11877 { *s
++ = (soap_wchar
)'&';
11883 *s
++ = (soap_wchar
)'"';
11885 { *s
++ = (soap_wchar
)'&';
11886 t
= (char*)"quot;";
11892 /* use UTF16 encoding when wchar_t is too small to hold UCS */
11893 if (sizeof(wchar_t) < 4 && c
> 0xFFFF)
11894 { register soap_wchar c1
, c2
;
11895 c1
= 0xD800 - (0x10000 >> 10) + (c
>> 10);
11896 c2
= 0xDC00 + (c
& 0x3FF);
11898 soap_unget(soap
, c2
);
11900 *s
++ = (wchar_t)c
& 0x7FFFFFFF;
11903 if (maxlen
>= 0 && l
> maxlen
)
11904 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
11905 soap
->error
= SOAP_LENGTH
;
11911 soap_unget(soap
, c
);
11913 soap_size_block(soap
, NULL
, sizeof(wchar_t) * (i
+ 1));
11915 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too short: %ld chars, minlen=%ld\n", l
, minlen
));
11916 soap
->error
= SOAP_LENGTH
;
11919 s
= (wchar_t*)soap_save_block(soap
, NULL
, NULL
, 0);
11921 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
11922 soap
->dom
->wide
= s
;
11929 /******************************************************************************/
11934 soap_int2s(struct soap
*soap
, int n
)
11935 { return soap_long2s(soap
, (long)n
);
11939 /******************************************************************************/
11944 soap_outint(struct soap
*soap
, const char *tag
, int id
, const int *p
, const char *type
, int n
)
11945 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11946 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
11947 return soap
->error
;
11948 return soap_element_end_out(soap
, tag
);
11952 /******************************************************************************/
11957 soap_s2int(struct soap
*soap
, const char *s
, int *p
)
11966 n
= soap_strtol(s
, &r
, 10);
11973 || soap_errno
== SOAP_ERANGE
11977 soap
->error
= SOAP_TYPE
;
11980 return soap
->error
;
11984 /******************************************************************************/
11989 soap_inint(struct soap
*soap
, const char *tag
, int *p
, const char *type
, int t
)
11990 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11994 && soap_match_tag(soap
, soap
->type
, type
)
11995 && soap_match_tag(soap
, soap
->type
, ":int")
11996 && soap_match_tag(soap
, soap
->type
, ":short")
11997 && soap_match_tag(soap
, soap
->type
, ":byte"))
11998 { soap
->error
= SOAP_TYPE
;
12003 p
= (int*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(int), 0, NULL
, NULL
, NULL
);
12005 p
= (int*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(int), 0, NULL
);
12007 { if (soap_s2int(soap
, soap_value(soap
), p
))
12010 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12016 /******************************************************************************/
12021 soap_long2s(struct soap
*soap
, long n
)
12023 #ifdef HAVE_SNPRINTF
12024 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%ld", n
);
12026 sprintf(soap
->tmpbuf
, "%ld", n
);
12028 return soap
->tmpbuf
;
12032 /******************************************************************************/
12037 soap_outlong(struct soap
*soap
, const char *tag
, int id
, const long *p
, const char *type
, int n
)
12038 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12039 || soap_string_out(soap
, soap_long2s(soap
, *p
), 0))
12040 return soap
->error
;
12041 return soap_element_end_out(soap
, tag
);
12045 /******************************************************************************/
12050 soap_s2long(struct soap
*soap
, const char *s
, long *p
)
12058 *p
= soap_strtol(s
, &r
, 10);
12062 || soap_errno
== SOAP_ERANGE
12066 soap
->error
= SOAP_TYPE
;
12068 return soap
->error
;
12072 /******************************************************************************/
12077 soap_inlong(struct soap
*soap
, const char *tag
, long *p
, const char *type
, int t
)
12078 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12082 && soap_match_tag(soap
, soap
->type
, type
)
12083 && soap_match_tag(soap
, soap
->type
, ":int")
12084 && soap_match_tag(soap
, soap
->type
, ":short")
12085 && soap_match_tag(soap
, soap
->type
, ":byte"))
12086 { soap
->error
= SOAP_TYPE
;
12091 p
= (long*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(long), 0, NULL
, NULL
, NULL
);
12093 p
= (long*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(long), 0, NULL
);
12095 { if (soap_s2long(soap
, soap_value(soap
), p
))
12098 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12104 /******************************************************************************/
12109 soap_LONG642s(struct soap
*soap
, LONG64 n
)
12111 #ifdef HAVE_SNPRINTF
12112 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), SOAP_LONG_FORMAT
, n
);
12114 sprintf(soap
->tmpbuf
, SOAP_LONG_FORMAT
, n
);
12116 return soap
->tmpbuf
;
12120 /******************************************************************************/
12125 soap_outLONG64(struct soap
*soap
, const char *tag
, int id
, const LONG64
*p
, const char *type
, int n
)
12126 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12127 || soap_string_out(soap
, soap_LONG642s(soap
, *p
), 0))
12128 return soap
->error
;
12129 return soap_element_end_out(soap
, tag
);
12133 /******************************************************************************/
12138 soap_s2LONG64(struct soap
*soap
, const char *s
, LONG64
*p
)
12141 #ifdef HAVE_STRTOLL
12148 *p
= soap_strtoll(s
, &r
, 10);
12152 || soap_errno
== SOAP_ERANGE
12157 # ifdef HAVE_SSCANF
12158 if (sscanf(s
, SOAP_LONG_FORMAT
, p
) != 1)
12161 soap
->error
= SOAP_TYPE
;
12163 return soap
->error
;
12167 /******************************************************************************/
12172 soap_inLONG64(struct soap
*soap
, const char *tag
, LONG64
*p
, const char *type
, int t
)
12173 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12177 && soap_match_tag(soap
, soap
->type
, type
)
12178 && soap_match_tag(soap
, soap
->type
, ":integer")
12179 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
12180 && soap_match_tag(soap
, soap
->type
, ":negativeInteger")
12181 && soap_match_tag(soap
, soap
->type
, ":nonPositiveInteger")
12182 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
12183 && soap_match_tag(soap
, soap
->type
, ":long")
12184 && soap_match_tag(soap
, soap
->type
, ":int")
12185 && soap_match_tag(soap
, soap
->type
, ":short")
12186 && soap_match_tag(soap
, soap
->type
, ":byte"))
12187 { soap
->error
= SOAP_TYPE
;
12192 p
= (LONG64
*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(LONG64
), 0, NULL
, NULL
, NULL
);
12194 p
= (LONG64
*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(LONG64
), 0, NULL
);
12196 { if (soap_s2LONG64(soap
, soap_value(soap
), p
))
12199 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12205 /******************************************************************************/
12210 soap_byte2s(struct soap
*soap
, char n
)
12211 { return soap_long2s(soap
, (long)n
);
12215 /******************************************************************************/
12220 soap_outbyte(struct soap
*soap
, const char *tag
, int id
, const char *p
, const char *type
, int n
)
12221 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12222 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
12223 return soap
->error
;
12224 return soap_element_end_out(soap
, tag
);
12228 /******************************************************************************/
12233 soap_s2byte(struct soap
*soap
, const char *s
, char *p
)
12237 n
= soap_strtol(s
, &r
, 10);
12238 if (s
== r
|| *r
|| n
< -128 || n
> 127)
12239 soap
->error
= SOAP_TYPE
;
12242 return soap
->error
;
12246 /******************************************************************************/
12251 soap_inbyte(struct soap
*soap
, const char *tag
, char *p
, const char *type
, int t
)
12252 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12256 && soap_match_tag(soap
, soap
->type
, type
)
12257 && soap_match_tag(soap
, soap
->type
, ":byte"))
12258 { soap
->error
= SOAP_TYPE
;
12263 p
= (char*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(char), 0, NULL
, NULL
, NULL
);
12265 p
= (char*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(char), 0, NULL
);
12267 { if (soap_s2byte(soap
, soap_value(soap
), p
))
12270 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12276 /******************************************************************************/
12281 soap_short2s(struct soap
*soap
, short n
)
12282 { return soap_long2s(soap
, (long)n
);
12286 /******************************************************************************/
12291 soap_outshort(struct soap
*soap
, const char *tag
, int id
, const short *p
, const char *type
, int n
)
12292 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12293 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
12294 return soap
->error
;
12295 return soap_element_end_out(soap
, tag
);
12299 /******************************************************************************/
12304 soap_s2short(struct soap
*soap
, const char *s
, short *p
)
12308 n
= soap_strtol(s
, &r
, 10);
12309 if (s
== r
|| *r
|| n
< -32768 || n
> 32767)
12310 soap
->error
= SOAP_TYPE
;
12313 return soap
->error
;
12317 /******************************************************************************/
12322 soap_inshort(struct soap
*soap
, const char *tag
, short *p
, const char *type
, int t
)
12323 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12327 && soap_match_tag(soap
, soap
->type
, type
)
12328 && soap_match_tag(soap
, soap
->type
, ":short")
12329 && soap_match_tag(soap
, soap
->type
, ":byte"))
12330 { soap
->error
= SOAP_TYPE
;
12335 p
= (short*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(short), 0, NULL
, NULL
, NULL
);
12337 p
= (short*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(short), 0, NULL
);
12339 { if (soap_s2short(soap
, soap_value(soap
), p
))
12342 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12348 /******************************************************************************/
12353 soap_float2s(struct soap
*soap
, float n
)
12355 if (soap_isnan((double)n
))
12357 if (soap_ispinff(n
))
12359 if (soap_isninff(n
))
12361 #if defined(HAVE_SPRINTF_L)
12363 _sprintf_s_l(soap
->tmpbuf
, _countof(soap
->tmpbuf
), soap
->float_format
, soap
->c_locale
, n
);
12365 sprintf_l(soap
->tmpbuf
, soap
->c_locale
, soap
->float_format
, n
);
12368 # ifdef HAVE_SNPRINTF
12369 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), soap
->float_format
, n
);
12371 sprintf(soap
->tmpbuf
, soap
->float_format
, n
);
12373 s
= strchr(soap
->tmpbuf
, ','); /* convert decimal comma to DP */
12377 return soap
->tmpbuf
;
12381 /******************************************************************************/
12386 soap_outfloat(struct soap
*soap
, const char *tag
, int id
, const float *p
, const char *type
, int n
)
12387 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12388 || soap_string_out(soap
, soap_float2s(soap
, *p
), 0))
12389 return soap
->error
;
12390 return soap_element_end_out(soap
, tag
);
12394 /******************************************************************************/
12399 soap_s2float(struct soap
*soap
, const char *s
, float *p
)
12402 return soap
->error
= SOAP_TYPE
;
12403 if (!soap_tag_cmp(s
, "INF"))
12405 else if (!soap_tag_cmp(s
, "+INF"))
12407 else if (!soap_tag_cmp(s
, "-INF"))
12409 else if (!soap_tag_cmp(s
, "NaN"))
12413 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
12414 #if defined(HAVE_STRTOD_L)
12417 *p
= (float)_strtod_l(s
, &r
, soap
->c_locale
);
12419 *p
= (float)strtod_l(s
, &r
, soap
->c_locale
);
12422 #elif defined(HAVE_STRTOD)
12424 *p
= (float)strtod(s
, &r
);
12426 #elif defined(HAVE_STRTOF_L)
12428 *p
= strtof_l((char*)s
, &r
, soap
->c_locale
);
12430 #elif defined(HAVE_STRTOF)
12432 *p
= strtof((char*)s
, &r
);
12436 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
12437 if (sscanf_l(s
, soap
->c_locale
, "%f", p
) != 1)
12438 soap
->error
= SOAP_TYPE
;
12439 #elif defined(HAVE_SSCANF)
12440 if (sscanf(s
, "%f", p
) != 1)
12441 soap
->error
= SOAP_TYPE
;
12443 soap
->error
= SOAP_TYPE
;
12448 return soap
->error
;
12452 /******************************************************************************/
12454 static int soap_isnumeric(struct soap
*soap
, const char *type
)
12455 { if (soap_match_tag(soap
, soap
->type
, type
)
12456 && soap_match_tag(soap
, soap
->type
, ":float")
12457 && soap_match_tag(soap
, soap
->type
, ":double")
12458 && soap_match_tag(soap
, soap
->type
, ":decimal")
12459 && soap_match_tag(soap
, soap
->type
, ":integer")
12460 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
12461 && soap_match_tag(soap
, soap
->type
, ":negativeInteger")
12462 && soap_match_tag(soap
, soap
->type
, ":nonPositiveInteger")
12463 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
12464 && soap_match_tag(soap
, soap
->type
, ":long")
12465 && soap_match_tag(soap
, soap
->type
, ":int")
12466 && soap_match_tag(soap
, soap
->type
, ":short")
12467 && soap_match_tag(soap
, soap
->type
, ":byte")
12468 && soap_match_tag(soap
, soap
->type
, ":unsignedLong")
12469 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
12470 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12471 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12472 { soap
->error
= SOAP_TYPE
;
12480 /******************************************************************************/
12485 soap_infloat(struct soap
*soap
, const char *tag
, float *p
, const char *type
, int t
)
12486 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12489 if (*soap
->type
!= '\0' && soap_isnumeric(soap
, type
))
12492 p
= (float*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(float), 0, NULL
, NULL
, NULL
);
12494 p
= (float*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(float), 0, NULL
);
12496 { if (soap_s2float(soap
, soap_value(soap
), p
))
12499 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12505 /******************************************************************************/
12510 soap_double2s(struct soap
*soap
, double n
)
12514 if (soap_ispinfd(n
))
12516 if (soap_isninfd(n
))
12518 #if defined(HAVE_SPRINTF_L)
12520 _sprintf_s_l(soap
->tmpbuf
, _countof(soap
->tmpbuf
), soap
->double_format
, soap
->c_locale
, n
);
12522 sprintf_l(soap
->tmpbuf
, soap
->c_locale
, soap
->double_format
, n
);
12525 # ifdef HAVE_SNPRINTF
12526 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), soap
->double_format
, n
);
12528 sprintf(soap
->tmpbuf
, soap
->double_format
, n
);
12530 s
= strchr(soap
->tmpbuf
, ','); /* convert decimal comma to DP */
12534 return soap
->tmpbuf
;
12538 /******************************************************************************/
12543 soap_outdouble(struct soap
*soap
, const char *tag
, int id
, const double *p
, const char *type
, int n
)
12544 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12545 || soap_string_out(soap
, soap_double2s(soap
, *p
), 0))
12546 return soap
->error
;
12547 return soap_element_end_out(soap
, tag
);
12551 /******************************************************************************/
12556 soap_s2double(struct soap
*soap
, const char *s
, double *p
)
12559 return soap
->error
= SOAP_TYPE
;
12560 if (!soap_tag_cmp(s
, "INF"))
12562 else if (!soap_tag_cmp(s
, "+INF"))
12564 else if (!soap_tag_cmp(s
, "-INF"))
12566 else if (!soap_tag_cmp(s
, "NaN"))
12570 #if defined(HAVE_STRTOD_L)
12573 *p
= _strtod_l(s
, &r
, soap
->c_locale
);
12575 *p
= strtod_l(s
, &r
, soap
->c_locale
);
12578 #elif defined(HAVE_STRTOD)
12580 *p
= strtod(s
, &r
);
12584 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
12585 if (sscanf_l(s
, soap
->c_locale
, "%lf", p
) != 1)
12586 soap
->error
= SOAP_TYPE
;
12587 #elif defined(HAVE_SSCANF)
12588 if (sscanf(s
, "%lf", p
) != 1)
12589 soap
->error
= SOAP_TYPE
;
12591 soap
->error
= SOAP_TYPE
;
12596 return soap
->error
;
12600 /******************************************************************************/
12605 soap_indouble(struct soap
*soap
, const char *tag
, double *p
, const char *type
, int t
)
12606 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12609 if (*soap
->type
!= '\0' && soap_isnumeric(soap
, type
))
12612 p
= (double*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(double), 0, NULL
, NULL
, NULL
);
12614 p
= (double*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(double), 0, NULL
);
12616 { if (soap_s2double(soap
, soap_value(soap
), p
))
12619 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12625 /******************************************************************************/
12630 soap_unsignedByte2s(struct soap
*soap
, unsigned char n
)
12631 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
12635 /******************************************************************************/
12640 soap_outunsignedByte(struct soap
*soap
, const char *tag
, int id
, const unsigned char *p
, const char *type
, int n
)
12641 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12642 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
12643 return soap
->error
;
12644 return soap_element_end_out(soap
, tag
);
12648 /******************************************************************************/
12653 soap_s2unsignedByte(struct soap
*soap
, const char *s
, unsigned char *p
)
12657 n
= soap_strtoul(s
, &r
, 10);
12658 if (s
== r
|| *r
|| n
> 255)
12659 soap
->error
= SOAP_TYPE
;
12660 *p
= (unsigned char)n
;
12662 return soap
->error
;
12666 /******************************************************************************/
12671 soap_inunsignedByte(struct soap
*soap
, const char *tag
, unsigned char *p
, const char *type
, int t
)
12672 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12676 && soap_match_tag(soap
, soap
->type
, type
)
12677 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12678 { soap
->error
= SOAP_TYPE
;
12683 p
= (unsigned char*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned char), 0, NULL
, NULL
, NULL
);
12685 p
= (unsigned char*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned char), 0, NULL
);
12687 { if (soap_s2unsignedByte(soap
, soap_value(soap
), p
))
12690 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12696 /******************************************************************************/
12701 soap_unsignedShort2s(struct soap
*soap
, unsigned short n
)
12702 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
12706 /******************************************************************************/
12711 soap_outunsignedShort(struct soap
*soap
, const char *tag
, int id
, const unsigned short *p
, const char *type
, int n
)
12712 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12713 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
12714 return soap
->error
;
12715 return soap_element_end_out(soap
, tag
);
12719 /******************************************************************************/
12724 soap_s2unsignedShort(struct soap
*soap
, const char *s
, unsigned short *p
)
12728 n
= soap_strtoul(s
, &r
, 10);
12729 if (s
== r
|| *r
|| n
> 65535)
12730 soap
->error
= SOAP_TYPE
;
12731 *p
= (unsigned short)n
;
12733 return soap
->error
;
12737 /******************************************************************************/
12742 soap_inunsignedShort(struct soap
*soap
, const char *tag
, unsigned short *p
, const char *type
, int t
)
12743 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12747 && soap_match_tag(soap
, soap
->type
, type
)
12748 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12749 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12750 { soap
->error
= SOAP_TYPE
;
12755 p
= (unsigned short*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned short), 0, NULL
, NULL
, NULL
);
12757 p
= (unsigned short*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned short), 0, NULL
);
12759 { if (soap_s2unsignedShort(soap
, soap_value(soap
), p
))
12762 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12768 /******************************************************************************/
12773 soap_unsignedInt2s(struct soap
*soap
, unsigned int n
)
12774 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
12778 /******************************************************************************/
12783 soap_outunsignedInt(struct soap
*soap
, const char *tag
, int id
, const unsigned int *p
, const char *type
, int n
)
12784 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12785 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
12786 return soap
->error
;
12787 return soap_element_end_out(soap
, tag
);
12791 /******************************************************************************/
12796 soap_s2unsignedInt(struct soap
*soap
, const char *s
, unsigned int *p
)
12804 *p
= (unsigned int)soap_strtoul(s
, &r
, 10);
12805 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
12808 || soap_errno
== SOAP_ERANGE
12812 soap
->error
= SOAP_TYPE
;
12814 return soap
->error
;
12818 /******************************************************************************/
12823 soap_inunsignedInt(struct soap
*soap
, const char *tag
, unsigned int *p
, const char *type
, int t
)
12824 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12828 && soap_match_tag(soap
, soap
->type
, type
)
12829 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
12830 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12831 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12832 { soap
->error
= SOAP_TYPE
;
12837 p
= (unsigned int*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned int), 0, NULL
, NULL
, NULL
);
12839 p
= (unsigned int*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned int), 0, NULL
);
12841 { if (soap_s2unsignedInt(soap
, soap_value(soap
), p
))
12844 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12850 /******************************************************************************/
12855 soap_unsignedLong2s(struct soap
*soap
, unsigned long n
)
12857 #ifdef HAVE_SNPRINTF
12858 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%lu", n
);
12860 sprintf(soap
->tmpbuf
, "%lu", n
);
12862 return soap
->tmpbuf
;
12866 /******************************************************************************/
12871 soap_outunsignedLong(struct soap
*soap
, const char *tag
, int id
, const unsigned long *p
, const char *type
, int n
)
12872 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12873 || soap_string_out(soap
, soap_unsignedLong2s(soap
, *p
), 0))
12874 return soap
->error
;
12875 return soap_element_end_out(soap
, tag
);
12879 /******************************************************************************/
12884 soap_s2unsignedLong(struct soap
*soap
, const char *s
, unsigned long *p
)
12892 *p
= soap_strtoul(s
, &r
, 10);
12893 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
12896 || soap_errno
== SOAP_ERANGE
12900 soap
->error
= SOAP_TYPE
;
12902 return soap
->error
;
12906 /******************************************************************************/
12911 soap_inunsignedLong(struct soap
*soap
, const char *tag
, unsigned long *p
, const char *type
, int t
)
12912 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12916 && soap_match_tag(soap
, soap
->type
, type
)
12917 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
12918 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12919 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12920 { soap
->error
= SOAP_TYPE
;
12925 p
= (unsigned long*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned long), 0, NULL
, NULL
, NULL
);
12927 p
= (unsigned long*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned long), 0, NULL
);
12929 { if (soap_s2unsignedLong(soap
, soap_value(soap
), p
))
12932 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12938 /******************************************************************************/
12943 soap_ULONG642s(struct soap
*soap
, ULONG64 n
)
12945 #ifdef HAVE_SNPRINTF
12946 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), SOAP_ULONG_FORMAT
, n
);
12948 sprintf(soap
->tmpbuf
, SOAP_ULONG_FORMAT
, n
);
12950 return soap
->tmpbuf
;
12954 /******************************************************************************/
12959 soap_outULONG64(struct soap
*soap
, const char *tag
, int id
, const ULONG64
*p
, const char *type
, int n
)
12960 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12961 || soap_string_out(soap
, soap_ULONG642s(soap
, *p
), 0))
12962 return soap
->error
;
12963 return soap_element_end_out(soap
, tag
);
12967 /******************************************************************************/
12972 soap_s2ULONG64(struct soap
*soap
, const char *s
, ULONG64
*p
)
12975 #ifdef HAVE_STRTOULL
12982 *p
= soap_strtoull(s
, &r
, 10);
12983 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
12986 || soap_errno
== SOAP_ERANGE
12992 if (sscanf(s
, SOAP_ULONG_FORMAT
, p
) != 1)
12995 soap
->error
= SOAP_TYPE
;
12997 return soap
->error
;
13001 /******************************************************************************/
13006 soap_inULONG64(struct soap
*soap
, const char *tag
, ULONG64
*p
, const char *type
, int t
)
13007 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
13010 && soap_match_tag(soap
, soap
->type
, type
)
13011 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
13012 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
13013 && soap_match_tag(soap
, soap
->type
, ":unsignedLong")
13014 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
13015 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
13016 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
13017 { soap
->error
= SOAP_TYPE
;
13021 p
= (ULONG64
*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(ULONG64
), 0, NULL
, NULL
, NULL
);
13023 p
= (ULONG64
*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(ULONG64
), 0, NULL
);
13025 { if (soap_s2ULONG64(soap
, soap_value(soap
), p
))
13028 if (soap
->body
&& soap_element_end_in(soap
, tag
))
13034 /******************************************************************************/
13039 soap_s2string(struct soap
*soap
, const char *s
, char **t
, long minlen
, long maxlen
)
13041 { long l
= (long)strlen(s
);
13042 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
13043 return soap
->error
= SOAP_LENGTH
;
13044 if (!(*t
= soap_strdup(soap
, s
)))
13045 return soap
->error
= SOAP_EOM
;
13046 if (!(soap
->mode
& (SOAP_ENC_LATIN
| SOAP_C_UTFSTRING
)))
13048 /* remove non-ASCII chars */
13049 for (s
= *t
; *s
; s
++)
13055 return soap
->error
;
13059 /******************************************************************************/
13064 soap_s2QName(struct soap
*soap
, const char *s
, char **t
, long minlen
, long maxlen
)
13066 { long l
= (long)strlen(s
);
13067 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
13068 return soap
->error
= SOAP_LENGTH
;
13070 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Normalized namespace(s) of QNames '%s'", s
));
13071 /* convert (by prefix normalize prefix) all QNames in s */
13074 struct soap_nlist
*np
;
13075 register const char *p
;
13077 while (*s
&& soap_blank((soap_wchar
)*s
))
13081 /* find next QName */
13083 while (s
[n
] && !soap_blank((soap_wchar
)s
[n
]))
13086 /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
13087 if (!np
|| *s
== '#' || !strncmp(s
, "xml:", 4))
13088 { soap_append_lab(soap
, s
, n
);
13090 else /* we normalize the QName by replacing its prefix */
13092 for (p
= s
; *p
&& p
< s
+ n
; p
++)
13096 { size_t k
= p
- s
;
13097 while (np
&& (strncmp(np
->id
, s
, k
) || np
->id
[k
]))
13102 { while (np
&& *np
->id
)
13106 /* replace prefix */
13108 { if (np
->index
>= 0 && soap
->local_namespaces
&& (q
= soap
->local_namespaces
[np
->index
].id
))
13109 { size_t k
= strlen(q
);
13111 soap_append_lab(soap
, q
, k
);
13113 { soap_append_lab(soap
, "\"", 1);
13114 soap_append_lab(soap
, soap
->local_namespaces
[np
->index
].ns
, strlen(soap
->local_namespaces
[np
->index
].ns
));
13115 soap_append_lab(soap
, "\"", 1);
13119 { soap_append_lab(soap
, "\"", 1);
13120 soap_append_lab(soap
, np
->ns
, strlen(np
->ns
));
13121 soap_append_lab(soap
, "\"", 1);
13124 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s
, np
->index
, np
->ns
? np
->ns
: SOAP_STR_EOS
));
13125 return soap
->error
= SOAP_NAMESPACE
;
13128 else if (s
[n
]) /* no namespace, part of string */
13129 { soap_append_lab(soap
, s
, n
);
13131 else /* no namespace: assume "" namespace */
13132 { soap_append_lab(soap
, "\"\"", 2);
13134 soap_append_lab(soap
, ":", 1);
13135 soap_append_lab(soap
, p
, n
- (p
-s
));
13137 /* advance to next and add spacing */
13140 soap_append_lab(soap
, " ", 1);
13142 soap_append_lab(soap
, SOAP_STR_EOS
, 1);
13143 *t
= soap_strdup(soap
, soap
->labbuf
);
13144 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, " into '%s'\n", *t
));
13146 return soap
->error
;
13150 /******************************************************************************/
13155 soap_QName2s(struct soap
*soap
, const char *s
)
13156 { const char *t
= NULL
;
13158 { soap
->labidx
= 0;
13162 while (*s
&& soap_blank((soap_wchar
)*s
))
13166 /* find next QName */
13168 while (s
[n
] && !soap_blank((soap_wchar
)s
[n
]))
13170 /* normal prefix: pass string as is */
13174 if ((soap
->mode
& SOAP_XML_CANONICAL
))
13175 soap_utilize_ns(soap
, s
);
13176 if ((soap
->mode
& SOAP_XML_DEFAULTNS
))
13177 { const char *r
= strchr(s
, ':');
13178 if (r
&& soap
->nlist
&& !strncmp(soap
->nlist
->id
, s
, r
-s
) && !soap
->nlist
->id
[r
-s
])
13184 soap_append_lab(soap
, s
, n
);
13186 else /* URL-based string prefix */
13189 q
= strchr(s
, '"');
13191 { struct Namespace
*p
= soap
->local_namespaces
;
13193 { for (; p
->id
; p
++)
13195 if (!soap_tag_cmp(s
, p
->ns
))
13198 if (!soap_tag_cmp(s
, p
->in
))
13202 /* URL is in the namespace table? */
13204 { const char *r
= p
->id
;
13206 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && soap
->nlist
&& !strcmp(soap
->nlist
->id
, r
))
13210 soap_append_lab(soap
, r
, strlen(r
));
13212 else /* not in namespace table: create xmlns binding */
13213 { char *r
= soap_strdup(soap
, s
);
13215 #ifdef HAVE_SNPRINTF
13216 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "xmlns:_%d", soap
->idnum
++);
13218 sprintf(soap
->tmpbuf
, "xmlns:_%d", soap
->idnum
++);
13220 soap_set_attr(soap
, soap
->tmpbuf
, r
, 1);
13221 soap_append_lab(soap
, soap
->tmpbuf
+ 6, strlen(soap
->tmpbuf
+ 6));
13223 soap_append_lab(soap
, q
+ 1, n
- (q
-s
) - 1);
13226 /* advance to next and add spacing */
13229 soap_append_lab(soap
, " ", 1);
13231 soap_append_lab(soap
, SOAP_STR_EOS
, 1);
13232 t
= soap_strdup(soap
, soap
->labbuf
);
13238 /******************************************************************************/
13243 soap_s2wchar(struct soap
*soap
, const char *s
, wchar_t **t
, long minlen
, long maxlen
)
13247 *t
= r
= (wchar_t*)soap_malloc(soap
, sizeof(wchar_t) * (strlen(s
) + 1));
13249 return soap
->error
= SOAP_EOM
;
13250 if (soap
->mode
& SOAP_ENC_LATIN
)
13252 *r
++ = (wchar_t)*s
++;
13255 { /* Convert UTF8 to wchar */
13257 { register soap_wchar c
, c1
, c2
, c3
, c4
;
13258 c
= (unsigned char)*s
++;
13262 { c1
= (soap_wchar
)*s
++ & 0x3F;
13264 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x1F) << 6) | c1
);
13266 { c2
= (soap_wchar
)*s
++ & 0x3F;
13268 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x0F) << 12) | (c1
<< 6) | c2
);
13270 { c3
= (soap_wchar
)*s
++ & 0x3F;
13272 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x07) << 18) | (c1
<< 12) | (c2
<< 6) | c3
);
13274 { c4
= (soap_wchar
)*s
++ & 0x3F;
13276 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x03) << 24) | (c1
<< 18) | (c2
<< 12) | (c3
<< 6) | c4
);
13278 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x01) << 30) | (c1
<< 24) | (c2
<< 18) | (c3
<< 12) | (c4
<< 6) | (soap_wchar
)(*s
++ & 0x3F));
13286 l
= (long)(r
- *t
);
13287 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
13288 return soap
->error
= SOAP_LENGTH
;
13290 return soap
->error
;
13294 /******************************************************************************/
13299 soap_wchar2s(struct soap
*soap
, const wchar_t *s
)
13300 { register soap_wchar c
;
13301 register char *r
, *t
;
13302 const wchar_t *q
= s
;
13305 { if (c
> 0 && c
< 0x80)
13310 r
= t
= (char*)soap_malloc(soap
, n
+ 1);
13312 { /* Convert wchar to UTF8 */
13314 { if (c
> 0 && c
< 0x80)
13318 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
13320 { if (c
< 0x010000)
13321 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
13323 { if (c
< 0x200000)
13324 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
13326 { if (c
< 0x04000000)
13327 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
13329 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
13330 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
13332 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
13334 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
13336 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
13338 *t
++ = (char)(0x80 | (c
& 0x3F));
13347 /******************************************************************************/
13352 soap_outstring(struct soap
*soap
, const char *tag
, int id
, char *const*p
, const char *type
, int n
)
13353 { id
= soap_element_id(soap
, tag
, id
, *p
, NULL
, 0, type
, n
);
13355 return soap
->error
;
13356 if (!**p
&& (soap
->mode
& SOAP_C_NILSTRING
))
13357 return soap_element_null(soap
, tag
, id
, type
);
13358 if (soap_element_begin_out(soap
, tag
, id
, type
)
13359 || soap_string_out(soap
, *p
, 0)
13360 || soap_element_end_out(soap
, tag
))
13361 return soap
->error
;
13366 /******************************************************************************/
13371 soap_instring(struct soap
*soap
, const char *tag
, char **p
, const char *type
, int t
, int flag
, long minlen
, long maxlen
)
13373 if (soap_element_begin_in(soap
, tag
, 1, NULL
))
13374 { if (!tag
|| *tag
!= '-' || soap
->error
!= SOAP_NO_TAG
)
13376 soap
->error
= SOAP_OK
;
13379 { if (!(p
= (char**)soap_malloc(soap
, sizeof(char*))))
13384 else if (soap
->body
)
13385 { *p
= soap_string_in(soap
, flag
, minlen
, maxlen
);
13386 if (!*p
|| !(char*)soap_id_enter(soap
, soap
->id
, *p
, t
, sizeof(char*), 0, NULL
, NULL
, NULL
))
13388 if (!**p
&& tag
&& *tag
== '-')
13389 { soap
->error
= SOAP_NO_TAG
;
13393 else if (tag
&& *tag
== '-')
13394 { soap
->error
= SOAP_NO_TAG
;
13397 else if (!*soap
->href
&& minlen
> 0)
13398 { soap
->error
= SOAP_LENGTH
;
13402 *p
= soap_strdup(soap
, SOAP_STR_EOS
);
13404 p
= (char**)soap_id_lookup(soap
, soap
->href
, (void**)p
, t
, sizeof(char**), 0);
13405 if (soap
->body
&& soap_element_end_in(soap
, tag
))
13411 /******************************************************************************/
13412 #ifndef WITH_LEANER
13417 soap_outwstring(struct soap
*soap
, const char *tag
, int id
, wchar_t *const*p
, const char *type
, int n
)
13418 { id
= soap_element_id(soap
, tag
, id
, *p
, NULL
, 0, type
, n
);
13420 return soap
->error
;
13421 if (!**p
&& (soap
->mode
& SOAP_C_NILSTRING
))
13422 return soap_element_null(soap
, tag
, id
, type
);
13423 if (soap_element_begin_out(soap
, tag
, id
, type
)
13424 || soap_wstring_out(soap
, *p
, 0)
13425 || soap_element_end_out(soap
, tag
))
13426 return soap
->error
;
13432 /******************************************************************************/
13433 #ifndef WITH_LEANER
13438 soap_inwstring(struct soap
*soap
, const char *tag
, wchar_t **p
, const char *type
, int t
, long minlen
, long maxlen
)
13440 if (soap_element_begin_in(soap
, tag
, 1, NULL
))
13441 { if (!tag
|| *tag
!= '-' || soap
->error
!= SOAP_NO_TAG
)
13443 soap
->error
= SOAP_OK
;
13446 { if (!(p
= (wchar_t**)soap_malloc(soap
, sizeof(wchar_t*))))
13450 { *p
= soap_wstring_in(soap
, 1, minlen
, maxlen
);
13451 if (!*p
|| !(wchar_t*)soap_id_enter(soap
, soap
->id
, *p
, t
, sizeof(wchar_t*), 0, NULL
, NULL
, NULL
))
13453 if (!**p
&& tag
&& *tag
== '-')
13454 { soap
->error
= SOAP_NO_TAG
;
13458 else if (tag
&& *tag
== '-')
13459 { soap
->error
= SOAP_NO_TAG
;
13462 else if (soap
->null
)
13465 *p
= soap_wstrdup(soap
, (wchar_t*)SOAP_STR_EOS
);
13467 p
= (wchar_t**)soap_id_lookup(soap
, soap
->href
, (void**)p
, t
, sizeof(wchar_t**), 0);
13468 if (soap
->body
&& soap_element_end_in(soap
, tag
))
13475 /******************************************************************************/
13480 soap_timegm(struct tm
*T
)
13482 #if defined(HAVE_TIMEGM)
13488 if (t
== (time_t)-1)
13490 #ifdef HAVE_GMTIME_R
13497 if (g
== (time_t)-1)
13505 /******************************************************************************/
13510 soap_dateTime2s(struct soap
*soap
, time_t n
)
13511 { struct tm T
, *pT
= &T
;
13512 #if defined(HAVE_GMTIME_R)
13513 if (gmtime_r(&n
, pT
))
13514 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%SZ", pT
);
13515 #elif defined(HAVE_GMTIME)
13516 if ((pT
= gmtime(&n
)))
13517 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%SZ", pT
);
13518 #elif defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)
13519 #if defined(HAVE_LOCALTIME_R)
13520 if (localtime_r(&n
, pT
))
13521 { strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S%z", pT
);
13522 memmove(soap
->tmpbuf
+ 23, soap
->tmpbuf
+ 22, 3); /* 2000-03-01T02:00:00+0300 */
13523 soap
->tmpbuf
[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
13526 if ((pT
= localtime(&n
)))
13527 { strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S%z", pT
);
13528 memmove(soap
->tmpbuf
+ 23, soap
->tmpbuf
+ 22, 3); /* 2000-03-01T02:00:00+0300 */
13529 soap
->tmpbuf
[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
13532 #elif defined(HAVE_GETTIMEOFDAY)
13533 struct timezone tz
;
13534 memset((void*)&tz
, 0, sizeof(tz
));
13535 #if defined(HAVE_LOCALTIME_R)
13536 if (localtime_r(&n
, pT
))
13537 { struct timeval tv
;
13538 gettimeofday(&tv
, &tz
);
13539 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
13540 #ifdef HAVE_SNPRINTF
13541 soap_snprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), sizeof(soap
->tmpbuf
) - strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
13543 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
13547 if ((pT
= localtime(&n
)))
13548 { struct timeval tv
;
13549 gettimeofday(&tv
, &tz
);
13550 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
13551 #ifdef HAVE_SNPRINTF
13552 soap_snprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), sizeof(soap
->tmpbuf
) - strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
13554 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
13558 #elif defined(HAVE_FTIME)
13560 memset((void*)&t
, 0, sizeof(t
));
13561 #if defined(HAVE_LOCALTIME_R)
13562 if (localtime_r(&n
, pT
))
13564 #ifdef __BORLANDC__
13569 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
13570 #ifdef HAVE_SNPRINTF
13571 soap_snprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), sizeof(soap
->tmpbuf
) - strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
13573 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
13577 if ((pT
= localtime(&n
)))
13579 #ifdef __BORLANDC__
13584 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
13585 #ifdef HAVE_SNPRINTF
13586 soap_snprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), sizeof(soap
->tmpbuf
) - strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
13588 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
13592 #elif defined(HAVE_LOCALTIME_R)
13593 if (localtime_r(&n
, pT
))
13594 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
13596 if ((pT
= localtime(&n
)))
13597 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
13600 strcpy(soap
->tmpbuf
, "1969-12-31T23:59:59Z");
13601 return soap
->tmpbuf
;
13605 /******************************************************************************/
13610 soap_outdateTime(struct soap
*soap
, const char *tag
, int id
, const time_t *p
, const char *type
, int n
)
13611 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
13612 || soap_string_out(soap
, soap_dateTime2s(soap
, *p
), 0))
13613 return soap
->error
;
13614 return soap_element_end_out(soap
, tag
);
13618 /******************************************************************************/
13623 soap_s2dateTime(struct soap
*soap
, const char *s
, time_t *p
)
13629 memset((void*)&T
, 0, sizeof(T
));
13630 if (strchr(s
, '-'))
13631 t
= "%d-%d-%dT%d:%d:%d%31s";
13632 else if (strchr(s
, ':'))
13633 t
= "%4d%2d%2dT%d:%d:%d%31s";
13634 else /* parse non-XSD-standard alternative ISO 8601 format */
13635 t
= "%4d%2d%2dT%2d%2d%2d%31s";
13636 if (sscanf(s
, t
, &T
.tm_year
, &T
.tm_mon
, &T
.tm_mday
, &T
.tm_hour
, &T
.tm_min
, &T
.tm_sec
, zone
) < 6)
13637 return soap
->error
= SOAP_TYPE
;
13638 if (T
.tm_year
== 1)
13644 { for (s
= zone
+ 1; *s
; s
++)
13645 if (*s
< '0' || *s
> '9')
13652 #ifndef WITH_NOZONE
13653 if (*s
== '+' || *s
== '-')
13654 { int h
= 0, m
= 0;
13657 sscanf(s
, "%d:%d", &h
, &m
);
13662 { m
= (int)soap_strtol(s
, NULL
, 10);
13668 /* put hour and min in range */
13669 T
.tm_hour
+= T
.tm_min
/ 60;
13675 T
.tm_mday
+= T
.tm_hour
/ 24;
13681 /* note: day of the month may be out of range, timegm() handles it */
13684 *p
= soap_timegm(&T
);
13686 else /* no UTC or timezone, so assume we got a localtime */
13691 return soap
->error
;
13695 /******************************************************************************/
13700 soap_indateTime(struct soap
*soap
, const char *tag
, time_t *p
, const char *type
, int t
)
13701 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
13704 && soap_match_tag(soap
, soap
->type
, type
)
13705 && soap_match_tag(soap
, soap
->type
, ":dateTime"))
13706 { soap
->error
= SOAP_TYPE
;
13710 p
= (time_t*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(time_t), 0, NULL
, NULL
, NULL
);
13712 p
= (time_t*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(time_t), 0, NULL
);
13714 { if (soap_s2dateTime(soap
, soap_value(soap
), p
))
13717 if (soap
->body
&& soap_element_end_in(soap
, tag
))
13723 /******************************************************************************/
13728 soap_outliteral(struct soap
*soap
, const char *tag
, char *const*p
, const char *type
)
13730 const char *t
= NULL
;
13731 if (tag
&& *tag
!= '-')
13732 { if (soap
->local_namespaces
&& (t
= strchr(tag
, ':')))
13733 { size_t n
= t
- tag
;
13734 if (n
>= sizeof(soap
->tmpbuf
))
13735 n
= sizeof(soap
->tmpbuf
) - 1;
13736 strncpy(soap
->tmpbuf
, tag
, n
);
13737 soap
->tmpbuf
[n
] = '\0';
13738 for (i
= 0; soap
->local_namespaces
[i
].id
; i
++)
13739 if (!strcmp(soap
->tmpbuf
, soap
->local_namespaces
[i
].id
))
13742 if (soap_element(soap
, t
, 0, type
)
13743 || soap_attribute(soap
, "xmlns", soap
->local_namespaces
[i
].ns
? soap
->local_namespaces
[i
].ns
: SOAP_STR_EOS
)
13744 || soap_element_start_end_out(soap
, NULL
))
13745 return soap
->error
;
13749 if (soap_element_begin_out(soap
, t
, 0, type
))
13750 return soap
->error
;
13754 { if (soap_send(soap
, *p
)) /* send as-is */
13755 return soap
->error
;
13758 return soap_element_end_out(soap
, t
);
13763 /******************************************************************************/
13768 soap_inliteral(struct soap
*soap
, const char *tag
, char **p
)
13769 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
13770 { if (soap
->error
!= SOAP_NO_TAG
|| soap_unget(soap
, soap_get(soap
)) == SOAP_TT
)
13772 soap
->error
= SOAP_OK
;
13775 { if (!(p
= (char**)soap_malloc(soap
, sizeof(char*))))
13778 if (soap
->body
|| (tag
&& *tag
== '-'))
13779 { *p
= soap_string_in(soap
, 0, -1, -1);
13782 if (!**p
&& tag
&& *tag
== '-')
13783 { soap
->error
= SOAP_NO_TAG
;
13787 else if (soap
->null
)
13790 *p
= soap_strdup(soap
, SOAP_STR_EOS
);
13791 if (soap
->body
&& soap_element_end_in(soap
, tag
))
13797 /******************************************************************************/
13798 #ifndef WITH_LEANER
13803 soap_outwliteral(struct soap
*soap
, const char *tag
, wchar_t *const*p
, const char *type
)
13805 const char *t
= NULL
;
13806 if (tag
&& *tag
!= '-')
13807 { if (soap
->local_namespaces
&& (t
= strchr(tag
, ':')))
13808 { size_t n
= t
- tag
;
13809 if (n
>= sizeof(soap
->tmpbuf
))
13810 n
= sizeof(soap
->tmpbuf
) - 1;
13811 strncpy(soap
->tmpbuf
, tag
, n
);
13812 soap
->tmpbuf
[n
] = '\0';
13813 for (i
= 0; soap
->local_namespaces
[i
].id
; i
++)
13814 if (!strcmp(soap
->tmpbuf
, soap
->local_namespaces
[i
].id
))
13817 if (soap_element(soap
, t
, 0, type
)
13818 || soap_attribute(soap
, "xmlns", soap
->local_namespaces
[i
].ns
? soap
->local_namespaces
[i
].ns
: SOAP_STR_EOS
)
13819 || soap_element_start_end_out(soap
, NULL
))
13820 return soap
->error
;
13824 if (soap_element_begin_out(soap
, t
, 0, type
))
13825 return soap
->error
;
13830 const wchar_t *s
= *p
;
13832 { if (soap_pututf8(soap
, (unsigned long)c
)) /* send as-is in UTF8 */
13833 return soap
->error
;
13837 return soap_element_end_out(soap
, t
);
13843 /******************************************************************************/
13844 #ifndef WITH_LEANER
13849 soap_inwliteral(struct soap
*soap
, const char *tag
, wchar_t **p
)
13850 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
13851 { if (soap
->error
!= SOAP_NO_TAG
|| soap_unget(soap
, soap_get(soap
)) == SOAP_TT
)
13853 soap
->error
= SOAP_OK
;
13856 { if (!(p
= (wchar_t**)soap_malloc(soap
, sizeof(wchar_t*))))
13860 { *p
= soap_wstring_in(soap
, 0, -1, -1);
13863 if (!**p
&& tag
&& *tag
== '-')
13864 { soap
->error
= SOAP_NO_TAG
;
13868 else if (tag
&& *tag
== '-')
13869 { soap
->error
= SOAP_NO_TAG
;
13872 else if (soap
->null
)
13875 *p
= soap_wstrdup(soap
, (wchar_t*)SOAP_STR_EOS
);
13876 if (soap
->body
&& soap_element_end_in(soap
, tag
))
13883 /******************************************************************************/
13888 soap_value(struct soap
*soap
)
13889 { register size_t i
;
13890 register soap_wchar c
= 0;
13891 register char *s
= soap
->tmpbuf
;
13893 return SOAP_STR_EOS
;
13894 do c
= soap_get(soap
);
13895 while (soap_blank(c
));
13896 for (i
= 0; i
< sizeof(soap
->tmpbuf
) - 1; i
++)
13897 { if (c
== SOAP_TT
|| c
== SOAP_LT
|| (int)c
== EOF
)
13900 c
= soap_get(soap
);
13902 for (s
--; i
> 0; i
--, s
--)
13903 { if (!soap_blank((soap_wchar
)*s
))
13907 soap
->tmpbuf
[sizeof(soap
->tmpbuf
) - 1] = '\0'; /* appease */
13908 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element content value='%s'\n", soap
->tmpbuf
));
13909 if (c
== SOAP_TT
|| c
== SOAP_LT
|| (int)c
== EOF
)
13910 soap_unget(soap
, c
);
13911 else if (soap
->mode
& SOAP_XML_STRICT
)
13912 { soap
->error
= SOAP_LENGTH
;
13916 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
13917 soap
->dom
->data
= soap_strdup(soap
, soap
->tmpbuf
);
13919 return soap
->tmpbuf
; /* return non-null pointer */
13923 /******************************************************************************/
13924 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
13929 soap_getline(struct soap
*soap
, char *s
, int len
)
13934 { c
= soap_getchar(soap
);
13935 if (c
== '\r' || c
== '\n')
13938 return soap
->error
= SOAP_CHK_EOF
;
13943 c
= soap_getchar(soap
); /* got \r or something else, now get \n */
13945 { if (i
+ 1 == len
) /* empty line: end of HTTP/MIME header */
13947 c
= soap_get0(soap
);
13948 if (c
!= ' ' && c
!= '\t') /* HTTP line continuation? */
13951 else if ((int)c
== EOF
)
13952 return soap
->error
= SOAP_CHK_EOF
;
13954 return soap
->error
= SOAP_HDR
;
13961 /******************************************************************************/
13964 soap_count_attachments(struct soap
*soap
)
13966 #ifndef WITH_LEANER
13967 register struct soap_multipart
*content
;
13968 register size_t count
= soap
->count
;
13969 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count
));
13970 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
13971 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the size of DIME attachments\n"));
13972 for (content
= soap
->dime
.first
; content
; content
= content
->next
)
13973 { count
+= 12 + ((content
->size
+3)&(~3));
13975 count
+= ((strlen(content
->id
)+3)&(~3));
13977 count
+= ((strlen(content
->type
)+3)&(~3));
13978 if (content
->options
)
13979 count
+= ((((unsigned char)content
->options
[2] << 8) | ((unsigned char)content
->options
[3]))+7)&(~3);
13980 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content
->size
));
13983 if ((soap
->mode
& SOAP_ENC_MIME
) && soap
->mime
.boundary
)
13984 { register size_t n
= strlen(soap
->mime
.boundary
);
13985 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the size of MIME attachments\n"));
13986 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
13987 { register const char *s
;
13988 /* count \r\n--boundary\r\n */
13990 /* count Content-Type: ...\r\n */
13992 count
+= 16 + strlen(content
->type
);
13993 /* count Content-Transfer-Encoding: ...\r\n */
13994 s
= soap_code_str(mime_codes
, content
->encoding
);
13996 count
+= 29 + strlen(s
);
13997 /* count Content-ID: ...\r\n */
13999 count
+= 14 + strlen(content
->id
);
14000 /* count Content-Location: ...\r\n */
14001 if (content
->location
)
14002 count
+= 20 + strlen(content
->location
);
14003 /* count Content-Description: ...\r\n */
14004 if (content
->description
)
14005 count
+= 23 + strlen(content
->description
);
14006 /* count \r\n...content */
14007 count
+= 2 + content
->size
;
14008 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content
->size
));
14010 /* count \r\n--boundary-- */
14013 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "New count=%lu\n", (unsigned long)count
));
14016 return soap
->count
;
14021 /******************************************************************************/
14022 #ifndef WITH_LEANER
14025 soap_putdimefield(struct soap
*soap
, const char *s
, size_t n
)
14026 { if (soap_send_raw(soap
, s
, n
))
14027 return soap
->error
;
14028 return soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)n
&3);
14033 /******************************************************************************/
14034 #ifndef WITH_LEANER
14039 soap_dime_option(struct soap
*soap
, unsigned short optype
, const char *option
)
14043 { n
= strlen(option
);
14044 s
= (char*)soap_malloc(soap
, n
+ 5);
14046 { s
[0] = (char)(optype
>> 8);
14047 s
[1] = (char)(optype
& 0xFF);
14048 s
[2] = (char)(n
>> 8);
14049 s
[3] = (char)(n
& 0xFF);
14050 strcpy(s
+ 4, option
);
14058 /******************************************************************************/
14059 #ifndef WITH_LEANER
14064 soap_putdimehdr(struct soap
*soap
)
14065 { unsigned char tmp
[12];
14066 size_t optlen
= 0, idlen
= 0, typelen
= 0;
14067 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Put DIME header id='%s'\n", soap
->dime
.id
? soap
->dime
.id
: SOAP_STR_EOS
));
14068 if (soap
->dime
.options
)
14069 optlen
= (((unsigned char)soap
->dime
.options
[2] << 8) | ((unsigned char)soap
->dime
.options
[3])) + 4;
14071 { idlen
= strlen(soap
->dime
.id
);
14072 if (idlen
> 0x0000FFFF)
14073 idlen
= 0x0000FFFF;
14075 if (soap
->dime
.type
)
14076 { typelen
= strlen(soap
->dime
.type
);
14077 if (typelen
> 0x0000FFFF)
14078 typelen
= 0x0000FFFF;
14080 tmp
[0] = SOAP_DIME_VERSION
| (soap
->dime
.flags
& 0x7);
14081 tmp
[1] = soap
->dime
.flags
& 0xF0;
14082 tmp
[2] = (char)(optlen
>> 8);
14083 tmp
[3] = (char)(optlen
& 0xFF);
14084 tmp
[4] = (char)(idlen
>> 8);
14085 tmp
[5] = (char)(idlen
& 0xFF);
14086 tmp
[6] = (char)(typelen
>> 8);
14087 tmp
[7] = (char)(typelen
& 0xFF);
14088 tmp
[8] = (char)(soap
->dime
.size
>> 24);
14089 tmp
[9] = (char)((soap
->dime
.size
>> 16) & 0xFF);
14090 tmp
[10] = (char)((soap
->dime
.size
>> 8) & 0xFF);
14091 tmp
[11] = (char)(soap
->dime
.size
& 0xFF);
14092 if (soap_send_raw(soap
, (char*)tmp
, 12)
14093 || soap_putdimefield(soap
, soap
->dime
.options
, optlen
)
14094 || soap_putdimefield(soap
, soap
->dime
.id
, idlen
)
14095 || soap_putdimefield(soap
, soap
->dime
.type
, typelen
))
14096 return soap
->error
;
14102 /******************************************************************************/
14103 #ifndef WITH_LEANER
14108 soap_putdime(struct soap
*soap
)
14109 { struct soap_multipart
*content
;
14110 if (!(soap
->mode
& SOAP_ENC_DIME
))
14112 for (content
= soap
->dime
.first
; content
; content
= content
->next
)
14114 soap
->dime
.size
= content
->size
;
14115 soap
->dime
.id
= content
->id
;
14116 soap
->dime
.type
= content
->type
;
14117 soap
->dime
.options
= content
->options
;
14118 soap
->dime
.flags
= SOAP_DIME_VERSION
| SOAP_DIME_MEDIA
;
14119 if (soap
->fdimereadopen
&& ((handle
= soap
->fdimereadopen(soap
, (void*)content
->ptr
, content
->id
, content
->type
, content
->options
)) || soap
->error
))
14120 { size_t size
= content
->size
;
14122 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadopen failed\n"));
14123 return soap
->error
;
14125 if (!size
&& ((soap
->mode
& SOAP_ENC_XML
) || (soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
))
14126 { size_t chunksize
= sizeof(soap
->tmpbuf
);
14127 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked streaming DIME\n"));
14129 { size
= soap
->fdimeread(soap
, handle
, soap
->tmpbuf
, chunksize
);
14130 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimeread returned %lu bytes\n", (unsigned long)size
));
14131 if (size
< chunksize
)
14132 { soap
->dime
.flags
&= ~SOAP_DIME_CF
;
14133 if (!content
->next
)
14134 soap
->dime
.flags
|= SOAP_DIME_ME
;
14137 soap
->dime
.flags
|= SOAP_DIME_CF
;
14138 soap
->dime
.size
= size
;
14139 if (soap_putdimehdr(soap
)
14140 || soap_putdimefield(soap
, soap
->tmpbuf
, size
))
14143 { soap
->dime
.flags
&= ~(SOAP_DIME_MB
| SOAP_DIME_MEDIA
);
14144 soap
->dime
.id
= NULL
;
14145 soap
->dime
.type
= NULL
;
14146 soap
->dime
.options
= NULL
;
14148 } while (size
>= chunksize
);
14151 { if (!content
->next
)
14152 soap
->dime
.flags
|= SOAP_DIME_ME
;
14153 if (soap_putdimehdr(soap
))
14154 return soap
->error
;
14157 if (size
< sizeof(soap
->tmpbuf
))
14160 bufsize
= sizeof(soap
->tmpbuf
);
14161 if (!(bufsize
= soap
->fdimeread(soap
, handle
, soap
->tmpbuf
, bufsize
)))
14162 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size
, (unsigned long)content
->size
));
14163 soap
->error
= SOAP_CHK_EOF
;
14166 if (soap_send_raw(soap
, soap
->tmpbuf
, bufsize
))
14170 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadclose\n"));
14171 soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)soap
->dime
.size
&3);
14173 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadclose\n"));
14174 if (soap
->fdimereadclose
)
14175 soap
->fdimereadclose(soap
, handle
);
14178 { if (!content
->next
)
14179 soap
->dime
.flags
|= SOAP_DIME_ME
;
14180 if (soap_putdimehdr(soap
)
14181 || soap_putdimefield(soap
, (char*)content
->ptr
, content
->size
))
14182 return soap
->error
;
14190 /******************************************************************************/
14191 #ifndef WITH_LEANER
14194 soap_getdimefield(struct soap
*soap
, size_t n
)
14195 { register soap_wchar c
;
14198 register char *p
= NULL
;
14200 { p
= (char*)soap_malloc(soap
, n
+ 1);
14203 for (i
= n
; i
> 0; i
--)
14204 { if ((int)(c
= soap_get1(soap
)) == EOF
)
14205 { soap
->error
= SOAP_CHK_EOF
;
14211 if ((soap
->error
= soap_move(soap
, (size_t)(-(long)n
&3))))
14215 soap
->error
= SOAP_EOM
;
14222 /******************************************************************************/
14223 #ifndef WITH_LEANER
14228 soap_getdimehdr(struct soap
*soap
)
14229 { register soap_wchar c
;
14232 unsigned char tmp
[12];
14233 size_t optlen
, idlen
, typelen
;
14234 if (!(soap
->mode
& SOAP_ENC_DIME
))
14235 return soap
->error
= SOAP_DIME_END
;
14236 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME header\n"));
14237 if (soap
->dime
.buflen
|| soap
->dime
.chunksize
)
14238 { if (soap_move(soap
, soap
->dime
.size
- soap_tell(soap
)))
14239 return soap
->error
= SOAP_CHK_EOF
;
14240 soap_unget(soap
, soap_getchar(soap
)); /* skip padding and get hdr */
14241 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "... From chunked\n"));
14245 for (i
= 12; i
> 0; i
--)
14246 { if ((int)(c
= soap_getchar(soap
)) == EOF
)
14247 return soap
->error
= SOAP_CHK_EOF
;
14250 if ((tmp
[0] & 0xF8) != SOAP_DIME_VERSION
)
14251 return soap
->error
= SOAP_DIME_MISMATCH
;
14252 soap
->dime
.flags
= (tmp
[0] & 0x7) | (tmp
[1] & 0xF0);
14253 optlen
= (tmp
[2] << 8) | tmp
[3];
14254 idlen
= (tmp
[4] << 8) | tmp
[5];
14255 typelen
= (tmp
[6] << 8) | tmp
[7];
14256 soap
->dime
.size
= ((size_t)tmp
[8] << 24) | ((size_t)tmp
[9] << 16) | ((size_t)tmp
[10] << 8) | ((size_t)tmp
[11]);
14257 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME size=%lu flags=0x%X\n", (unsigned long)soap
->dime
.size
, soap
->dime
.flags
));
14258 if (!(soap
->dime
.options
= soap_getdimefield(soap
, optlen
)) && soap
->error
)
14259 return soap
->error
;
14260 if (!(soap
->dime
.id
= soap_getdimefield(soap
, idlen
)) && soap
->error
)
14261 return soap
->error
;
14262 if (!(soap
->dime
.type
= soap_getdimefield(soap
, typelen
)) && soap
->error
)
14263 return soap
->error
;
14264 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME id='%s', type='%s', options='%s'\n", soap
->dime
.id
? soap
->dime
.id
: SOAP_STR_EOS
, soap
->dime
.type
? soap
->dime
.type
: "", soap
->dime
.options
? soap
->dime
.options
+4 : SOAP_STR_EOS
));
14265 if (soap
->dime
.flags
& SOAP_DIME_ME
)
14266 soap
->mode
&= ~SOAP_ENC_DIME
;
14272 /******************************************************************************/
14273 #ifndef WITH_LEANER
14278 soap_getdime(struct soap
*soap
)
14279 { while (soap
->dime
.flags
& SOAP_DIME_CF
)
14280 { if (soap_getdimehdr(soap
))
14281 return soap
->error
;
14282 if (soap_move(soap
, soap
->dime
.size
))
14283 return soap
->error
= SOAP_EOF
;
14285 if (soap_move(soap
, (size_t)(((soap
->dime
.size
+3)&(~3)) - soap_tell(soap
))))
14286 return soap
->error
= SOAP_EOF
;
14288 { register struct soap_multipart
*content
;
14289 if (soap_getdimehdr(soap
))
14291 if (soap
->fdimewriteopen
&& ((soap
->dime
.ptr
= (char*)soap
->fdimewriteopen(soap
, soap
->dime
.id
, soap
->dime
.type
, soap
->dime
.options
)) || soap
->error
))
14292 { const char *id
, *type
, *options
;
14294 if (!soap
->dime
.ptr
)
14295 return soap
->error
;
14296 id
= soap
->dime
.id
;
14297 type
= soap
->dime
.type
;
14298 options
= soap
->dime
.options
;
14300 { size
= soap
->dime
.size
;
14302 { n
= soap
->buflen
- soap
->bufidx
;
14305 if ((soap
->error
= soap
->fdimewrite(soap
, (void*)soap
->dime
.ptr
, soap
->buf
+ soap
->bufidx
, n
)))
14309 { soap
->bufidx
+= n
;
14312 if (soap_recv(soap
))
14313 { soap
->error
= SOAP_EOF
;
14317 if (soap_move(soap
, (size_t)(-(long)soap
->dime
.size
&3)))
14318 { soap
->error
= SOAP_EOF
;
14321 if (!(soap
->dime
.flags
& SOAP_DIME_CF
))
14323 if (soap_getdimehdr(soap
))
14327 if (soap
->fdimewriteclose
)
14328 soap
->fdimewriteclose(soap
, (void*)soap
->dime
.ptr
);
14329 soap
->dime
.size
= 0;
14330 soap
->dime
.id
= id
;
14331 soap
->dime
.type
= type
;
14332 soap
->dime
.options
= options
;
14334 else if (soap
->dime
.flags
& SOAP_DIME_CF
)
14335 { const char *id
, *type
, *options
;
14336 id
= soap
->dime
.id
;
14337 type
= soap
->dime
.type
;
14338 options
= soap
->dime
.options
;
14339 if (soap_new_block(soap
) == NULL
)
14342 { register soap_wchar c
;
14345 if (soap
->dime
.size
> SOAP_MAXDIMESIZE
)
14346 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap
->dime
.size
, (unsigned long)SOAP_MAXDIMESIZE
));
14347 return soap
->error
= SOAP_DIME_ERROR
;
14349 s
= (char*)soap_push_block(soap
, NULL
, soap
->dime
.size
);
14351 return soap
->error
= SOAP_EOM
;
14352 for (i
= soap
->dime
.size
; i
> 0; i
--)
14353 { if ((int)(c
= soap_get1(soap
)) == EOF
)
14354 return soap
->error
= SOAP_EOF
;
14357 if (soap_move(soap
, (size_t)(-(long)soap
->dime
.size
&3)))
14358 return soap
->error
= SOAP_EOF
;
14359 if (!(soap
->dime
.flags
& SOAP_DIME_CF
))
14361 if (soap_getdimehdr(soap
))
14362 return soap
->error
;
14364 soap
->dime
.size
= soap
->blist
->size
++; /* allocate one more byte in blist for the terminating '\0' */
14365 if (!(soap
->dime
.ptr
= soap_save_block(soap
, NULL
, NULL
, 0)))
14366 return soap
->error
;
14367 soap
->dime
.ptr
[soap
->dime
.size
] = '\0'; /* make 0-terminated */
14368 soap
->dime
.id
= id
;
14369 soap
->dime
.type
= type
;
14370 soap
->dime
.options
= options
;
14373 soap
->dime
.ptr
= soap_getdimefield(soap
, soap
->dime
.size
);
14374 content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, soap
->dime
.ptr
, soap
->dime
.size
);
14376 return soap
->error
= SOAP_EOM
;
14377 content
->id
= soap
->dime
.id
;
14378 content
->type
= soap
->dime
.type
;
14379 content
->options
= soap
->dime
.options
;
14381 return soap
->error
;
14382 soap_resolve_attachment(soap
, content
);
14384 if (soap
->error
!= SOAP_DIME_END
)
14385 return soap
->error
;
14386 return soap
->error
= SOAP_OK
;
14391 /******************************************************************************/
14392 #ifndef WITH_LEANER
14397 soap_getmimehdr(struct soap
*soap
)
14398 { struct soap_multipart
*content
;
14400 { if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
14401 return soap
->error
;
14403 while (!*soap
->msgbuf
);
14404 if (soap
->msgbuf
[0] == '-' && soap
->msgbuf
[1] == '-')
14405 { char *s
= soap
->msgbuf
+ strlen(soap
->msgbuf
) - 1;
14406 /* remove white space */
14407 while (soap_blank((soap_wchar
)*s
))
14410 if (soap
->mime
.boundary
)
14411 { if (strcmp(soap
->msgbuf
+ 2, soap
->mime
.boundary
))
14412 return soap
->error
= SOAP_MIME_ERROR
;
14415 soap
->mime
.boundary
= soap_strdup(soap
, soap
->msgbuf
+ 2);
14416 if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
14417 return soap
->error
;
14419 if (soap_set_mime_attachment(soap
, NULL
, 0, SOAP_MIME_NONE
, NULL
, NULL
, NULL
, NULL
))
14420 return soap
->error
= SOAP_EOM
;
14421 content
= soap
->mime
.last
;
14423 { register char *key
= soap
->msgbuf
;
14424 register char *val
;
14427 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "MIME header: %s\n", key
));
14428 val
= strchr(soap
->msgbuf
, ':');
14432 while (*val
&& *val
<= 32);
14433 if (!soap_tag_cmp(key
, "Content-ID"))
14434 content
->id
= soap_strdup(soap
, val
);
14435 else if (!soap_tag_cmp(key
, "Content-Location"))
14436 content
->location
= soap_strdup(soap
, val
);
14437 else if (!soap_tag_cmp(key
, "Content-Disposition"))
14438 content
->id
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "name"));
14439 else if (!soap_tag_cmp(key
, "Content-Type"))
14440 content
->type
= soap_strdup(soap
, val
);
14441 else if (!soap_tag_cmp(key
, "Content-Description"))
14442 content
->description
= soap_strdup(soap
, val
);
14443 else if (!soap_tag_cmp(key
, "Content-Transfer-Encoding"))
14444 content
->encoding
= (enum soap_mime_encoding
)soap_code_int(mime_codes
, val
, (long)SOAP_MIME_NONE
);
14446 if (soap_getline(soap
, key
, sizeof(soap
->msgbuf
)))
14447 return soap
->error
;
14454 /******************************************************************************/
14455 #ifndef WITH_LEANER
14460 soap_getmime(struct soap
*soap
)
14461 { while (soap_get_mime_attachment(soap
, NULL
))
14463 return soap
->error
;
14468 /******************************************************************************/
14469 #ifndef WITH_LEANER
14474 soap_post_check_mime_attachments(struct soap
*soap
)
14475 { soap
->imode
|= SOAP_MIME_POSTCHECK
;
14480 /******************************************************************************/
14481 #ifndef WITH_LEANER
14486 soap_check_mime_attachments(struct soap
*soap
)
14487 { if (soap
->mode
& SOAP_MIME_POSTCHECK
)
14488 return soap_get_mime_attachment(soap
, NULL
) != NULL
;
14494 /******************************************************************************/
14495 #ifndef WITH_LEANER
14498 struct soap_multipart
*
14500 soap_get_mime_attachment(struct soap
*soap
, void *handle
)
14501 { register soap_wchar c
= 0;
14502 register size_t i
, m
= 0;
14503 register char *s
, *t
= NULL
;
14504 register struct soap_multipart
*content
;
14505 register short flag
= 0;
14506 if (!(soap
->mode
& SOAP_ENC_MIME
))
14508 content
= soap
->mime
.last
;
14510 { if (soap_getmimehdr(soap
))
14512 content
= soap
->mime
.last
;
14514 else if (content
!= soap
->mime
.first
)
14515 { if (soap
->fmimewriteopen
&& ((content
->ptr
= (char*)soap
->fmimewriteopen(soap
, (void*)handle
, content
->id
, content
->type
, content
->description
, content
->encoding
)) || soap
->error
))
14516 { if (!content
->ptr
)
14520 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Parsing MIME content id='%s' type='%s'\n", content
->id
? content
->id
: SOAP_STR_EOS
, content
->type
? content
->type
: SOAP_STR_EOS
));
14521 if (!content
->ptr
&& soap_new_block(soap
) == NULL
)
14522 { soap
->error
= SOAP_EOM
;
14526 { if (content
->ptr
)
14528 else if (!(s
= (char*)soap_push_block(soap
, NULL
, sizeof(soap
->tmpbuf
))))
14529 { soap
->error
= SOAP_EOM
;
14532 for (i
= 0; i
< sizeof(soap
->tmpbuf
); i
++)
14539 { c
= soap_get1(soap
);
14541 { if (content
->ptr
&& soap
->fmimewriteclose
)
14542 soap
->fmimewriteclose(soap
, (void*)content
->ptr
);
14543 soap
->error
= SOAP_CHK_EOF
;
14547 if (flag
|| c
== '\r')
14548 { t
= soap
->msgbuf
;
14549 memset(t
, 0, sizeof(soap
->msgbuf
));
14551 if (soap
->mime
.boundary
)
14552 strncat(t
, soap
->mime
.boundary
, sizeof(soap
->msgbuf
)-4);
14553 do c
= soap_getchar(soap
);
14556 { if (content
->ptr
&& soap
->fmimewriteclose
)
14557 soap
->fmimewriteclose(soap
, (void*)content
->ptr
);
14558 soap
->error
= SOAP_CHK_EOF
;
14564 flag
= (c
== '\r');
14565 m
= t
- soap
->msgbuf
+ 1 - flag
;
14572 if (content
->ptr
&& soap
->fmimewrite
)
14573 { if ((soap
->error
= soap
->fmimewrite(soap
, (void*)content
->ptr
, soap
->tmpbuf
, i
)))
14578 *s
= '\0'; /* make 0-terminated */
14580 { if (!soap
->error
&& soap
->fmimewrite
)
14581 soap
->error
= soap
->fmimewrite(soap
, (void*)content
->ptr
, soap
->tmpbuf
, i
);
14582 if (soap
->fmimewriteclose
)
14583 soap
->fmimewriteclose(soap
, (void*)content
->ptr
);
14588 { content
->size
= soap_size_block(soap
, NULL
, i
+1) - 1; /* last block with '\0' */
14589 content
->ptr
= soap_save_block(soap
, NULL
, NULL
, 0);
14591 soap_resolve_attachment(soap
, content
);
14592 if (c
== '-' && soap_getchar(soap
) == '-')
14593 { soap
->mode
&= ~SOAP_ENC_MIME
;
14594 if ((soap
->mode
& SOAP_MIME_POSTCHECK
) && soap_end_recv(soap
))
14595 { if (soap
->keep_alive
< 0)
14596 soap
->keep_alive
= 0;
14597 soap_closesock(soap
);
14602 { while (c
!= '\r' && (int)c
!= EOF
&& soap_blank(c
))
14603 c
= soap_getchar(soap
);
14604 if (c
!= '\r' || soap_getchar(soap
) != '\n')
14605 { soap
->error
= SOAP_MIME_ERROR
;
14608 if (soap_getmimehdr(soap
))
14616 /******************************************************************************/
14617 #ifndef WITH_LEANER
14622 soap_match_cid(struct soap
*soap
, const char *s
, const char *t
)
14623 { register size_t n
;
14628 if (!strncmp(s
, "cid:", 4))
14635 if (!strncmp(s
, t
, n
) && !s
[n
])
14637 soap_decode(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
, SOAP_STR_EOS
);
14638 if (!strncmp(soap
->tmpbuf
, t
, n
) && !soap
->tmpbuf
[n
])
14645 /******************************************************************************/
14646 #ifndef WITH_LEANER
14649 soap_resolve_attachment(struct soap
*soap
, struct soap_multipart
*content
)
14651 { register struct soap_xlist
**xp
= &soap
->xlist
;
14652 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving attachment data for id='%s'\n", content
->id
));
14654 { register struct soap_xlist
*xq
= *xp
;
14655 if (!soap_match_cid(soap
, xq
->id
, content
->id
))
14656 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Found matching attachment id='%s' for content id='%s'\n", xq
->id
, content
->id
));
14658 *xq
->ptr
= (unsigned char*)content
->ptr
;
14659 *xq
->size
= (int)content
->size
;
14660 *xq
->type
= (char*)content
->type
;
14661 if (content
->options
)
14662 *xq
->options
= (char*)content
->options
;
14664 *xq
->options
= (char*)content
->description
;
14665 SOAP_FREE(soap
, xq
);
14675 /******************************************************************************/
14676 #ifndef WITH_LEANER
14681 soap_putmimehdr(struct soap
*soap
, struct soap_multipart
*content
)
14683 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "MIME attachment type='%s'\n", content
->type
? content
->type
: SOAP_STR_EOS
));
14684 if (soap_send3(soap
, "\r\n--", soap
->mime
.boundary
, "\r\n"))
14685 return soap
->error
;
14686 if (content
->type
&& soap_send3(soap
, "Content-Type: ", content
->type
, "\r\n"))
14687 return soap
->error
;
14688 s
= soap_code_str(mime_codes
, content
->encoding
);
14689 if (s
&& soap_send3(soap
, "Content-Transfer-Encoding: ", s
, "\r\n"))
14690 return soap
->error
;
14691 if (content
->id
&& soap_send3(soap
, "Content-ID: ", content
->id
, "\r\n"))
14692 return soap
->error
;
14693 if (content
->location
&& soap_send3(soap
, "Content-Location: ", content
->location
, "\r\n"))
14694 return soap
->error
;
14695 if (content
->description
&& soap_send3(soap
, "Content-Description: ", content
->description
, "\r\n"))
14696 return soap
->error
;
14697 return soap_send_raw(soap
, "\r\n", 2);
14702 /******************************************************************************/
14703 #ifndef WITH_LEANER
14708 soap_putmime(struct soap
*soap
)
14709 { struct soap_multipart
*content
;
14710 if (!(soap
->mode
& SOAP_ENC_MIME
) || !soap
->mime
.boundary
)
14712 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending MIME attachments\n"));
14713 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
14715 if (soap
->fmimereadopen
&& ((handle
= soap
->fmimereadopen(soap
, (void*)content
->ptr
, content
->id
, content
->type
, content
->description
)) || soap
->error
))
14716 { size_t size
= content
->size
;
14718 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimereadopen failed\n"));
14719 return soap
->error
;
14721 if (soap_putmimehdr(soap
, content
))
14722 return soap
->error
;
14724 { if ((soap
->mode
& SOAP_ENC_XML
) || (soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
14725 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked streaming MIME\n"));
14727 { size
= soap
->fmimeread(soap
, handle
, soap
->tmpbuf
, sizeof(soap
->tmpbuf
));
14728 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimeread returned %lu bytes\n", (unsigned long)size
));
14729 if (soap_send_raw(soap
, soap
->tmpbuf
, size
))
14734 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
14740 if (size
< sizeof(soap
->tmpbuf
))
14743 bufsize
= sizeof(soap
->tmpbuf
);
14744 if (!(bufsize
= soap
->fmimeread(soap
, handle
, soap
->tmpbuf
, bufsize
)))
14745 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size
, (unsigned long)content
->size
));
14746 soap
->error
= SOAP_EOF
;
14749 if (soap_send_raw(soap
, soap
->tmpbuf
, bufsize
))
14754 if (soap
->fmimereadclose
)
14755 soap
->fmimereadclose(soap
, handle
);
14758 { if (soap_putmimehdr(soap
, content
)
14759 || soap_send_raw(soap
, content
->ptr
, content
->size
))
14760 return soap
->error
;
14763 return soap_send3(soap
, "\r\n--", soap
->mime
.boundary
, "--");
14768 /******************************************************************************/
14769 #ifndef WITH_LEANER
14774 soap_set_dime(struct soap
*soap
)
14775 { soap
->omode
|= SOAP_ENC_DIME
;
14776 soap
->dime
.first
= NULL
;
14777 soap
->dime
.last
= NULL
;
14782 /******************************************************************************/
14783 #ifndef WITH_LEANER
14788 soap_set_mime(struct soap
*soap
, const char *boundary
, const char *start
)
14789 { soap
->omode
|= SOAP_ENC_MIME
;
14790 soap
->mime
.first
= NULL
;
14791 soap
->mime
.last
= NULL
;
14792 soap
->mime
.boundary
= soap_strdup(soap
, boundary
);
14793 soap
->mime
.start
= soap_strdup(soap
, start
);
14798 /******************************************************************************/
14799 #ifndef WITH_LEANER
14804 soap_clr_dime(struct soap
*soap
)
14805 { soap
->omode
&= ~SOAP_ENC_DIME
;
14806 soap
->dime
.first
= NULL
;
14807 soap
->dime
.last
= NULL
;
14812 /******************************************************************************/
14813 #ifndef WITH_LEANER
14818 soap_clr_mime(struct soap
*soap
)
14819 { soap
->omode
&= ~SOAP_ENC_MIME
;
14820 soap
->mime
.first
= NULL
;
14821 soap
->mime
.last
= NULL
;
14822 soap
->mime
.boundary
= NULL
;
14823 soap
->mime
.start
= NULL
;
14828 /******************************************************************************/
14829 #ifndef WITH_LEANER
14831 static struct soap_multipart
*
14832 soap_new_multipart(struct soap
*soap
, struct soap_multipart
**first
, struct soap_multipart
**last
, char *ptr
, size_t size
)
14833 { struct soap_multipart
*content
;
14834 content
= (struct soap_multipart
*)soap_malloc(soap
, sizeof(struct soap_multipart
));
14836 { content
->next
= NULL
;
14837 content
->ptr
= ptr
;
14838 content
->size
= size
;
14839 content
->id
= NULL
;
14840 content
->type
= NULL
;
14841 content
->options
= NULL
;
14842 content
->encoding
= SOAP_MIME_NONE
;
14843 content
->location
= NULL
;
14844 content
->description
= NULL
;
14848 (*last
)->next
= content
;
14856 /******************************************************************************/
14857 #ifndef WITH_LEANER
14862 soap_set_dime_attachment(struct soap
*soap
, char *ptr
, size_t size
, const char *type
, const char *id
, unsigned short optype
, const char *option
)
14863 { struct soap_multipart
*content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, ptr
, size
);
14866 content
->id
= soap_strdup(soap
, id
);
14867 content
->type
= soap_strdup(soap
, type
);
14868 content
->options
= soap_dime_option(soap
, optype
, option
);
14874 /******************************************************************************/
14875 #ifndef WITH_LEANER
14880 soap_set_mime_attachment(struct soap
*soap
, char *ptr
, size_t size
, enum soap_mime_encoding encoding
, const char *type
, const char *id
, const char *location
, const char *description
)
14881 { struct soap_multipart
*content
= soap_new_multipart(soap
, &soap
->mime
.first
, &soap
->mime
.last
, ptr
, size
);
14884 content
->id
= soap_strdup(soap
, id
);
14885 content
->type
= soap_strdup(soap
, type
);
14886 content
->encoding
= encoding
;
14887 content
->location
= soap_strdup(soap
, location
);
14888 content
->description
= soap_strdup(soap
, description
);
14894 /******************************************************************************/
14895 #ifndef WITH_LEANER
14898 struct soap_multipart
*
14900 soap_next_multipart(struct soap_multipart
*content
)
14902 return content
->next
;
14908 /******************************************************************************/
14909 #ifndef WITH_LEANER
14912 soap_select_mime_boundary(struct soap
*soap
)
14913 { while (!soap
->mime
.boundary
|| soap_valid_mime_boundary(soap
))
14914 { register char *s
= soap
->mime
.boundary
;
14915 register size_t n
= 0;
14920 s
= soap
->mime
.boundary
= (char*)soap_malloc(soap
, n
+ 1);
14928 { *s
++ = soap_base64o
[soap_random
& 0x3F];
14933 if (!soap
->mime
.start
)
14934 soap
->mime
.start
= "<SOAP-ENV:Envelope>";
14939 /******************************************************************************/
14940 #ifndef WITH_LEANER
14943 soap_valid_mime_boundary(struct soap
*soap
)
14944 { register struct soap_multipart
*content
;
14946 if (soap
->fmimeread
)
14948 k
= strlen(soap
->mime
.boundary
);
14949 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
14950 { if (content
->ptr
&& content
->size
>= k
)
14951 { register const char *p
= (const char*)content
->ptr
;
14953 for (i
= 0; i
< content
->size
- k
; i
++, p
++)
14954 { if (!strncmp(p
, soap
->mime
.boundary
, k
))
14964 /******************************************************************************/
14968 soap_getgziphdr(struct soap
*soap
)
14970 soap_wchar c
= 0, f
= 0;
14971 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get gzip header\n"));
14972 for (i
= 0; i
< 9; i
++)
14973 { if ((int)(c
= soap_get1(soap
) == EOF
))
14974 return soap
->error
= SOAP_ZLIB_ERROR
;
14975 if (i
== 1 && c
== 8)
14980 if (f
& 0x04) /* FEXTRA */
14981 { for (i
= soap_get1(soap
) | (soap_get1(soap
) << 8); i
; i
--)
14982 { if ((int)soap_get1(soap
) == EOF
)
14983 return soap
->error
= SOAP_ZLIB_ERROR
;
14986 if (f
& 0x08) /* skip FNAME */
14988 c
= soap_get1(soap
);
14989 while (c
&& (int)c
!= EOF
);
14991 if ((int)c
!= EOF
&& (f
& 0x10)) /* skip FCOMMENT */
14993 c
= soap_get1(soap
);
14994 while (c
&& (int)c
!= EOF
);
14996 if ((int)c
!= EOF
&& (f
& 0x02)) /* skip FHCRC (CRC32 is used) */
14997 { if ((int)(c
= soap_get1(soap
)) != EOF
)
14998 c
= soap_get1(soap
);
15001 return soap
->error
= SOAP_ZLIB_ERROR
;
15007 /******************************************************************************/
15012 soap_begin_serve(struct soap
*soap
)
15014 #ifdef WITH_FASTCGI
15015 if (FCGI_Accept() < 0)
15016 { soap
->error
= SOAP_EOF
;
15017 return soap_send_fault(soap
);
15021 if (soap_begin_recv(soap
)
15022 || soap_envelope_begin_in(soap
)
15023 || soap_recv_header(soap
)
15024 || soap_body_begin_in(soap
))
15025 { if (soap
->error
< SOAP_STOP
)
15027 #ifdef WITH_FASTCGI
15028 soap_send_fault(soap
);
15030 return soap_send_fault(soap
);
15033 return soap_closesock(soap
);
15039 /******************************************************************************/
15044 soap_begin_recv(struct soap
*soap
)
15045 { register soap_wchar c
;
15046 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Initializing for input from socket=%d/fd=%d\n", soap
->socket
, soap
->recvfd
));
15047 soap
->error
= SOAP_OK
;
15048 soap
->filterstop
= SOAP_OK
;
15049 soap_free_temp(soap
);
15050 soap_set_local_namespaces(soap
);
15051 soap
->version
= 0; /* don't assume we're parsing SOAP content by default */
15052 #ifndef WITH_NOIDREF
15053 soap_free_iht(soap
);
15055 if ((soap
->imode
& SOAP_IO
) == SOAP_IO_CHUNK
)
15056 soap
->omode
|= SOAP_IO_CHUNK
;
15057 soap
->imode
&= ~(SOAP_IO
| SOAP_ENC_MIME
);
15058 soap
->mode
= soap
->imode
;
15059 if (!soap
->keep_alive
)
15060 { soap
->buflen
= 0;
15063 if (!(soap
->mode
& SOAP_IO_KEEPALIVE
))
15064 soap
->keep_alive
= 0;
15068 soap
->part
= SOAP_BEGIN
;
15074 *soap
->endpoint
= '\0';
15075 soap
->action
= NULL
;
15076 soap
->header
= NULL
;
15077 soap
->fault
= NULL
;
15079 soap
->fform
= NULL
;
15080 #ifndef WITH_LEANER
15082 soap
->dime
.chunksize
= 0;
15083 soap
->dime
.buflen
= 0;
15084 soap
->dime
.list
= NULL
;
15085 soap
->dime
.first
= NULL
;
15086 soap
->dime
.last
= NULL
;
15087 soap
->mime
.list
= NULL
;
15088 soap
->mime
.first
= NULL
;
15089 soap
->mime
.last
= NULL
;
15090 soap
->mime
.boundary
= NULL
;
15091 soap
->mime
.start
= NULL
;
15095 #ifndef WITH_FASTCGI
15096 if (!soap_valid_socket(soap
->socket
) && !soap
->is
) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
15097 #ifdef __BORLANDC__
15098 setmode(soap
->recvfd
, _O_BINARY
);
15100 _setmode(soap
->recvfd
, _O_BINARY
);
15106 soap
->mode
&= ~SOAP_ENC_ZLIB
;
15107 soap
->zlib_in
= SOAP_ZLIB_NONE
;
15108 soap
->zlib_out
= SOAP_ZLIB_NONE
;
15109 soap
->d_stream
->next_in
= Z_NULL
;
15110 soap
->d_stream
->avail_in
= 0;
15111 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
15112 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
15113 soap
->z_ratio_in
= 1.0;
15115 #ifdef WITH_OPENSSL
15119 #ifndef WITH_LEANER
15120 if (soap
->fprepareinitrecv
&& (soap
->error
= soap
->fprepareinitrecv(soap
)))
15121 return soap
->error
;
15123 c
= soap_getchar(soap
);
15126 { if (soap_getgziphdr(soap
))
15127 return soap
->error
;
15128 if (inflateInit2(soap
->d_stream
, -MAX_WBITS
) != Z_OK
)
15129 return soap
->error
= SOAP_ZLIB_ERROR
;
15131 { if (inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
15132 return soap
->error
= SOAP_ZLIB_ERROR
;
15134 soap
->zlib_state
= SOAP_ZLIB_INFLATE
;
15135 soap
->mode
|= SOAP_ENC_ZLIB
;
15136 soap
->zlib_in
= SOAP_ZLIB_GZIP
;
15137 soap
->z_crc
= crc32(0L, NULL
, 0);
15138 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip initialized\n"));
15140 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
15141 memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
15142 /* should not chunk over plain transport, so why bother to check? */
15143 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
15144 /* soap->z_buflen = soap->bufidx; */
15146 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
15147 soap
->d_stream
->avail_in
= (unsigned int)(soap
->buflen
- soap
->bufidx
);
15148 soap
->z_buflen
= soap
->buflen
;
15149 soap
->buflen
= soap
->bufidx
;
15153 while (soap_blank(c
))
15154 c
= soap_getchar(soap
);
15155 #ifndef WITH_LEANER
15156 if (c
== '-' && soap_get0(soap
) == '-')
15157 soap
->mode
|= SOAP_ENC_MIME
;
15158 else if ((c
& 0xFFFC) == (SOAP_DIME_VERSION
| SOAP_DIME_MB
) && (soap_get0(soap
) & 0xFFF0) == 0x20)
15159 soap
->mode
|= SOAP_ENC_DIME
;
15163 if (c
== 0xEF && soap_get0(soap
) == 0xBB)
15164 { c
= soap_get1(soap
);
15165 if ((c
= soap_get1(soap
)) == 0xBF)
15166 { soap
->mode
&= ~SOAP_ENC_LATIN
;
15167 c
= soap_getchar(soap
);
15170 c
= (0x0F << 12) | (0xBB << 6) | (c
& 0x3F); /* UTF-8 */
15172 else if ((c
== 0xFE && soap_get0(soap
) == 0xFF) /* UTF-16 BE */
15173 || (c
== 0xFF && soap_get0(soap
) == 0xFE)) /* UTF-16 LE */
15174 return soap
->error
= SOAP_UTF_ERROR
;
15176 while (soap_blank(c
))
15177 c
= soap_getchar(soap
);
15180 return soap
->error
= SOAP_CHK_EOF
;
15181 soap_unget(soap
, c
);
15182 #ifndef WITH_NOHTTP
15183 /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
15184 if (((c
>= 'A' && c
<= 'Z') || (c
>= 'a' && c
<= 'z')) && !(soap
->mode
& (SOAP_ENC_MIME
| SOAP_ENC_DIME
| SOAP_ENC_ZLIB
| SOAP_ENC_XML
)))
15185 { soap_mode m
= soap
->imode
;
15186 soap
->mode
&= ~SOAP_IO
;
15187 soap
->error
= soap
->fparse(soap
);
15188 if (soap
->error
&& soap
->error
< SOAP_STOP
)
15189 { soap
->keep_alive
= 0; /* force close later */
15190 return soap
->error
;
15192 if (soap
->error
== SOAP_STOP
)
15194 { soap
->error
= soap
->fform(soap
);
15195 if (soap
->error
== SOAP_OK
)
15196 soap
->error
= SOAP_STOP
; /* prevents further processing */
15198 return soap
->error
;
15200 soap
->mode
= soap
->imode
; /* if imode is changed, effectuate */
15201 soap
->imode
= m
; /* restore imode */
15203 soap
->mode
&= ~SOAP_ENC_ZLIB
;
15205 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
15206 { soap
->chunkbuflen
= soap
->buflen
;
15207 soap
->buflen
= soap
->bufidx
;
15208 soap
->chunksize
= 0;
15210 /* Note: fparse should not use soap_unget to push back last char */
15212 if (soap
->status
> 200 && soap
->length
== 0 && !(soap
->http_content
&& (!soap
->keep_alive
|| soap
->recv_timeout
)) && (soap
->imode
& SOAP_IO
) != SOAP_IO_CHUNK
)
15214 if (soap
->status
&& !soap
->body
)
15215 return soap
->error
= soap
->status
;
15217 if (soap
->zlib_in
!= SOAP_ZLIB_NONE
)
15220 if (soap
->zlib_in
!= SOAP_ZLIB_DEFLATE
)
15221 { c
= soap_get1(soap
);
15223 return soap
->error
= SOAP_EOF
;
15225 { if (soap_getgziphdr(soap
))
15226 return soap
->error
;
15227 if (inflateInit2(soap
->d_stream
, -MAX_WBITS
) != Z_OK
)
15228 return soap
->error
= SOAP_ZLIB_ERROR
;
15229 soap
->z_crc
= crc32(0L, NULL
, 0);
15230 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip initialized\n"));
15233 { soap_revget1(soap
);
15234 if (inflateInit(soap
->d_stream
) != Z_OK
)
15235 return soap
->error
= SOAP_ZLIB_ERROR
;
15236 soap
->zlib_in
= SOAP_ZLIB_DEFLATE
;
15241 if (inflateInit(soap
->d_stream
) != Z_OK
)
15242 return soap
->error
= SOAP_ZLIB_ERROR
;
15244 { if (inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
15245 return soap
->error
= SOAP_ZLIB_ERROR
;
15247 soap
->zlib_state
= SOAP_ZLIB_INFLATE
;
15248 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflate initialized\n"));
15249 soap
->mode
|= SOAP_ENC_ZLIB
;
15251 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
15252 memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
15253 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
15254 soap
->d_stream
->avail_in
= (unsigned int)(soap
->buflen
- soap
->bufidx
);
15255 soap
->z_buflen
= soap
->buflen
;
15256 soap
->buflen
= soap
->bufidx
;
15259 #ifndef WITH_LEANER
15260 if (soap
->fpreparerecv
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_CHUNK
&& soap
->buflen
> soap
->bufidx
)
15262 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Invoking fpreparerecv\n"));
15263 if ((r
= soap
->fpreparerecv(soap
, soap
->buf
+ soap
->bufidx
, soap
->buflen
- soap
->bufidx
)))
15264 return soap
->error
= r
;
15267 if (soap_get0(soap
) == (int)EOF
)
15268 { if (soap
->status
== 0 || soap
->status
== 200)
15269 return soap
->error
= SOAP_NO_DATA
; /* HTTP OK: always expect data */
15270 return soap
->error
= soap
->status
;
15273 { if (soap
->error
== SOAP_FORM
&& soap
->fform
)
15274 { soap
->error
= soap
->fform(soap
);
15275 if (soap
->error
== SOAP_OK
)
15276 soap
->error
= SOAP_STOP
; /* prevents further processing */
15278 return soap
->error
;
15282 #ifndef WITH_LEANER
15283 if (soap
->mode
& SOAP_ENC_MIME
)
15284 { do /* skip preamble */
15285 { if ((int)(c
= soap_getchar(soap
)) == EOF
)
15286 return soap
->error
= SOAP_CHK_EOF
;
15287 } while (c
!= '-' || soap_get0(soap
) != '-');
15288 soap_unget(soap
, c
);
15289 if (soap_getmimehdr(soap
))
15290 return soap
->error
;
15291 if (soap
->mime
.start
)
15293 { if (!soap
->mime
.last
->id
)
15295 if (!soap_match_cid(soap
, soap
->mime
.start
, soap
->mime
.last
->id
))
15297 } while (soap_get_mime_attachment(soap
, NULL
));
15299 if (soap_get_header_attribute(soap
, soap
->mime
.first
->type
, "application/dime"))
15300 soap
->mode
|= SOAP_ENC_DIME
;
15302 if (soap
->mode
& SOAP_ENC_DIME
)
15303 { if (soap_getdimehdr(soap
))
15304 return soap
->error
;
15305 if (soap
->dime
.flags
& SOAP_DIME_CF
)
15306 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked DIME SOAP message\n"));
15307 soap
->dime
.chunksize
= soap
->dime
.size
;
15308 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.chunksize
)
15309 { soap
->dime
.buflen
= soap
->buflen
;
15310 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
15313 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
15315 soap
->count
= soap
->buflen
- soap
->bufidx
;
15322 /******************************************************************************/
15327 soap_envelope_begin_out(struct soap
*soap
)
15329 #ifndef WITH_LEANER
15331 if ((soap
->mode
& SOAP_ENC_MIME
) && soap
->mime
.boundary
&& soap
->mime
.start
&& strlen(soap
->mime
.boundary
) + strlen(soap
->mime
.start
) < sizeof(soap
->tmpbuf
) - 80 )
15333 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
15334 s
= "application/dime";
15335 else if (soap
->version
== 2)
15336 { if (soap
->mode
& SOAP_ENC_MTOM
)
15337 s
= "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
15339 s
= "application/soap+xml; charset=utf-8";
15341 else if (soap
->mode
& SOAP_ENC_MTOM
)
15342 s
= "application/xop+xml; charset=utf-8; type=\"text/xml\"";
15344 s
= "text/xml; charset=utf-8";
15345 #ifdef HAVE_SNPRINTF
15346 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap
->mime
.boundary
, s
, soap
->mime
.start
);
15348 sprintf(soap
->tmpbuf
, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap
->mime
.boundary
, s
, soap
->mime
.start
);
15350 n
= strlen(soap
->tmpbuf
);
15351 if (soap_send_raw(soap
, soap
->tmpbuf
, n
))
15352 return soap
->error
;
15354 if (soap
->mode
& SOAP_IO_LENGTH
)
15355 soap
->dime
.size
= soap
->count
; /* DIME in MIME correction */
15356 if (!(soap
->mode
& SOAP_IO_LENGTH
) && (soap
->mode
& SOAP_ENC_DIME
))
15357 { if (soap_putdimehdr(soap
))
15358 return soap
->error
;
15361 if (soap
->version
== 0)
15363 soap
->part
= SOAP_IN_ENVELOPE
;
15364 return soap_element_begin_out(soap
, "SOAP-ENV:Envelope", 0, NULL
);
15368 /******************************************************************************/
15373 soap_envelope_end_out(struct soap
*soap
)
15374 { if (soap
->version
== 0)
15376 if (soap_element_end_out(soap
, "SOAP-ENV:Envelope")
15377 || soap_send_raw(soap
, "\r\n", 2)) /* 2.8: always emit \r\n */
15378 return soap
->error
;
15379 #ifndef WITH_LEANER
15380 if ((soap
->mode
& SOAP_IO_LENGTH
) && (soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
15381 { soap
->dime
.size
= soap
->count
- soap
->dime
.size
; /* DIME in MIME correction */
15382 #ifdef HAVE_SNPRINTF
15383 soap_snprintf(soap
->id
, sizeof(soap
->id
), soap
->dime_id_format
, 0);
15385 sprintf(soap
->id
, soap
->dime_id_format
, 0);
15387 soap
->dime
.id
= soap
->id
;
15388 if (soap
->local_namespaces
)
15389 { if (soap
->local_namespaces
[0].out
)
15390 soap
->dime
.type
= (char*)soap
->local_namespaces
[0].out
;
15392 soap
->dime
.type
= (char*)soap
->local_namespaces
[0].ns
;
15394 soap
->dime
.options
= NULL
;
15395 soap
->dime
.flags
= SOAP_DIME_MB
| SOAP_DIME_ABSURI
;
15396 if (!soap
->dime
.first
)
15397 soap
->dime
.flags
|= SOAP_DIME_ME
;
15398 soap
->count
+= 12 + ((strlen(soap
->dime
.id
)+3)&(~3)) + (soap
->dime
.type
? ((strlen(soap
->dime
.type
)+3)&(~3)) : 0);
15400 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
15401 return soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)soap
->dime
.size
&3);
15403 soap
->part
= SOAP_END_ENVELOPE
;
15408 /******************************************************************************/
15414 soap_get_http_body(struct soap
*soap
, size_t *len
)
15418 register size_t l
= 0, n
= 0;
15420 /* get HTTP body length */
15421 if (!(soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) != SOAP_IO_CHUNK
)
15422 { n
= soap
->length
;
15426 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Parsing HTTP body (mode=0x%x,len=%lu)\n", soap
->mode
, (unsigned long)n
));
15428 soap
->labidx
= 0; /* use look-aside buffer */
15430 if (soap_new_block(soap
) == NULL
)
15436 register size_t i
, k
;
15437 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
15439 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
15440 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
15441 soap
->labidx
= soap
->lablen
; /* claim this space */
15443 register size_t i
, k
= SOAP_BLKLEN
;
15444 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
15447 for (i
= 0; i
< k
; i
++)
15448 { register soap_wchar c
;
15450 if (n
> 0 && l
> n
)
15452 c
= soap_get1(soap
);
15455 *s
++ = (char)(c
& 0xFF);
15461 *len
= l
- 1; /* len excludes terminating \0 */
15463 if ((s
= (char*)soap_malloc(soap
, l
)))
15464 memcpy(s
, soap
->labbuf
, l
);
15466 soap_size_block(soap
, NULL
, i
+1);
15467 s
= soap_save_block(soap
, NULL
, 0);
15477 /******************************************************************************/
15482 soap_envelope_begin_in(struct soap
*soap
)
15483 { register struct Namespace
*p
;
15484 soap
->part
= SOAP_IN_ENVELOPE
;
15485 if (soap_element_begin_in(soap
, "SOAP-ENV:Envelope", 0, NULL
))
15486 { if (soap
->error
== SOAP_TAG_MISMATCH
)
15487 { if (!soap_element_begin_in(soap
, "Envelope", 0, NULL
))
15488 soap
->error
= SOAP_VERSIONMISMATCH
;
15489 else if (soap
->status
== 0 || (soap
->status
>= 200 && soap
->status
<= 299))
15490 return SOAP_OK
; /* allow non-SOAP XML content to be captured */
15491 soap
->error
= soap
->status
;
15493 else if (soap
->status
)
15494 soap
->error
= soap
->status
;
15495 return soap
->error
;
15497 p
= soap
->local_namespaces
;
15499 { const char *ns
= p
[0].out
;
15502 if (!strcmp(ns
, soap_env1
))
15503 { soap
->version
= 1; /* make sure we use SOAP 1.1 */
15505 SOAP_FREE(soap
, p
[1].out
);
15506 if ((p
[1].out
= (char*)SOAP_MALLOC(soap
, sizeof(soap_enc1
))))
15507 strcpy(p
[1].out
, soap_enc1
);
15509 else if (!strcmp(ns
, soap_env2
))
15510 { soap
->version
= 2; /* make sure we use SOAP 1.2 */
15512 SOAP_FREE(soap
, p
[1].out
);
15513 if ((p
[1].out
= (char*)SOAP_MALLOC(soap
, sizeof(soap_enc2
))))
15514 strcpy(p
[1].out
, soap_enc2
);
15521 /******************************************************************************/
15526 soap_envelope_end_in(struct soap
*soap
)
15527 { if (soap
->version
== 0)
15529 soap
->part
= SOAP_END_ENVELOPE
;
15530 return soap_element_end_in(soap
, "SOAP-ENV:Envelope");
15534 /******************************************************************************/
15539 soap_body_begin_out(struct soap
*soap
)
15540 { if (soap
->version
== 1)
15541 soap
->encoding
= 1;
15543 if ((soap
->mode
& SOAP_SEC_WSUID
) && soap_set_attr(soap
, "wsu:Id", "Body", 1))
15544 return soap
->error
;
15546 if (soap
->version
== 0)
15548 soap
->part
= SOAP_IN_BODY
;
15549 return soap_element_begin_out(soap
, "SOAP-ENV:Body", 0, NULL
);
15553 /******************************************************************************/
15558 soap_body_end_out(struct soap
*soap
)
15559 { if (soap
->version
== 0)
15561 if (soap_element_end_out(soap
, "SOAP-ENV:Body"))
15562 return soap
->error
;
15563 soap
->part
= SOAP_END_BODY
;
15568 /******************************************************************************/
15573 soap_body_begin_in(struct soap
*soap
)
15574 { if (soap
->version
== 0)
15576 soap
->part
= SOAP_IN_BODY
;
15577 if (soap_element_begin_in(soap
, "SOAP-ENV:Body", 0, NULL
))
15578 return soap
->error
;
15580 soap
->part
= SOAP_NO_BODY
;
15585 /******************************************************************************/
15590 soap_body_end_in(struct soap
*soap
)
15591 { if (soap
->version
== 0)
15593 if (soap
->part
== SOAP_NO_BODY
)
15594 return soap
->error
= SOAP_OK
;
15595 soap
->part
= SOAP_END_BODY
;
15596 return soap_element_end_in(soap
, "SOAP-ENV:Body");
15600 /******************************************************************************/
15605 soap_recv_header(struct soap
*soap
)
15606 { if (soap_getheader(soap
) && soap
->error
== SOAP_TAG_MISMATCH
)
15607 soap
->error
= SOAP_OK
;
15608 if (soap
->error
== SOAP_OK
&& soap
->fheader
)
15609 soap
->error
= soap
->fheader(soap
);
15610 return soap
->error
;
15614 /******************************************************************************/
15619 soap_set_endpoint(struct soap
*soap
, const char *endpoint
)
15620 { register const char *s
;
15621 register size_t i
, n
;
15622 soap
->endpoint
[0] = '\0';
15623 soap
->host
[0] = '\0';
15624 soap
->path
[0] = '/';
15625 soap
->path
[1] = '\0';
15627 if (!endpoint
|| !*endpoint
)
15629 #ifdef WITH_OPENSSL
15630 if (!soap_tag_cmp(endpoint
, "https:*"))
15633 strncpy(soap
->endpoint
, endpoint
, sizeof(soap
->endpoint
));
15634 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
15635 s
= strchr(endpoint
, ':');
15636 if (s
&& s
[1] == '/' && s
[2] == '/')
15641 if (n
>= sizeof(soap
->host
))
15642 n
= sizeof(soap
->host
) - 1;
15646 for (i
= 0; i
< n
; i
++)
15652 soap
->host
[i
] = s
[i
];
15656 { for (i
= 0; i
< n
; i
++)
15657 { soap
->host
[i
] = s
[i
];
15658 if (s
[i
] == '/' || s
[i
] == ':')
15663 for (i
= 0; i
< n
; i
++)
15664 { soap
->host
[i
] = s
[i
];
15665 if (s
[i
] == '/' || s
[i
] == ':')
15669 soap
->host
[i
] = '\0';
15671 { soap
->port
= (int)soap_strtol(s
+ i
+ 1, NULL
, 10);
15672 for (i
++; i
< n
; i
++)
15677 { strncpy(soap
->path
, s
+ i
, sizeof(soap
->path
));
15678 soap
->path
[sizeof(soap
->path
) - 1] = '\0';
15683 /******************************************************************************/
15688 soap_connect(struct soap
*soap
, const char *endpoint
, const char *action
)
15689 { return soap_connect_command(soap
, SOAP_POST
, endpoint
, action
);
15693 /******************************************************************************/
15698 soap_connect_command(struct soap
*soap
, int http_command
, const char *endpoints
, const char *action
)
15701 if (endpoints
&& (s
= strchr(endpoints
, ' ')))
15702 { endpoint
= (char*)SOAP_MALLOC(soap
, strlen(endpoints
) + 1);
15704 { strncpy(endpoint
, endpoints
, s
- endpoints
);
15705 endpoint
[s
- endpoints
] = '\0';
15706 if (soap_try_connect_command(soap
, http_command
, endpoint
, action
) != SOAP_TCP_ERROR
)
15710 soap
->error
= SOAP_OK
;
15714 s
= strchr(endpoints
, ' ');
15716 s
= endpoints
+ strlen(endpoints
);
15718 SOAP_FREE(soap
, endpoint
);
15721 soap_try_connect_command(soap
, http_command
, endpoints
, action
);
15722 return soap
->error
;
15726 /******************************************************************************/
15729 soap_try_connect_command(struct soap
*soap
, int http_command
, const char *endpoint
, const char *action
)
15730 { char host
[sizeof(soap
->host
)];
15733 soap
->error
= SOAP_OK
;
15734 strcpy(host
, soap
->host
); /* save previous host name: if != then reconnect */
15735 port
= soap
->port
; /* save previous port to compare */
15736 soap
->status
= http_command
;
15737 soap_set_endpoint(soap
, endpoint
);
15738 #ifndef WITH_LEANER
15739 if (soap
->fconnect
)
15740 { if ((soap
->error
= soap
->fconnect(soap
, endpoint
, soap
->host
, soap
->port
)))
15741 return soap
->error
;
15745 soap
->action
= soap_strdup(soap
, action
);
15746 if (soap
->fopen
&& *soap
->host
)
15747 { if (!soap
->keep_alive
|| !soap_valid_socket(soap
->socket
) || strcmp(soap
->host
, host
) || soap
->port
!= port
|| !soap
->fpoll
|| soap
->fpoll(soap
))
15748 { soap
->error
= SOAP_OK
;
15750 if (!strncmp(endpoint
, "soap.udp:", 9))
15751 soap
->omode
|= SOAP_IO_UDP
;
15754 { soap
->keep_alive
= 0; /* to force close */
15755 soap
->omode
&= ~SOAP_IO_UDP
; /* to force close */
15757 soap_closesock(soap
);
15758 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Connect/reconnect to '%s' host='%s' path='%s' port=%d\n", endpoint
?endpoint
:"(null)", soap
->host
, soap
->path
, soap
->port
));
15759 if (!soap
->keep_alive
|| !soap_valid_socket(soap
->socket
))
15760 { soap
->socket
= soap
->fopen(soap
, endpoint
, soap
->host
, soap
->port
);
15762 return soap
->error
;
15763 soap
->keep_alive
= ((soap
->omode
& SOAP_IO_KEEPALIVE
) != 0);
15768 if (soap_ntlm_handshake(soap
, SOAP_GET
, endpoint
, soap
->host
, soap
->port
))
15769 return soap
->error
;
15771 count
= soap_count_attachments(soap
);
15772 if (soap_begin_send(soap
))
15773 return soap
->error
;
15774 if (http_command
== SOAP_GET
)
15775 { soap
->mode
&= ~SOAP_IO
;
15776 soap
->mode
|= SOAP_IO_BUFFER
;
15778 #ifndef WITH_NOHTTP
15779 if ((soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& !(soap
->mode
& SOAP_ENC_XML
) && endpoint
)
15780 { unsigned int k
= soap
->mode
;
15781 soap
->mode
&= ~(SOAP_IO
| SOAP_ENC_ZLIB
);
15782 if ((k
& SOAP_IO
) != SOAP_IO_FLUSH
)
15783 soap
->mode
|= SOAP_IO_BUFFER
;
15784 if ((soap
->error
= soap
->fpost(soap
, endpoint
, soap
->host
, soap
->port
, soap
->path
, action
, count
)))
15785 return soap
->error
;
15786 #ifndef WITH_LEANER
15787 if ((k
& SOAP_IO
) == SOAP_IO_CHUNK
)
15788 { if (soap_flush(soap
))
15789 return soap
->error
;
15794 if (http_command
== SOAP_GET
|| http_command
== SOAP_DEL
)
15795 return soap_end_send_flush(soap
);
15801 /******************************************************************************/
15805 soap_ntlm_handshake(struct soap
*soap
, int command
, const char *endpoint
, const char *host
, int port
)
15806 { /* requires libntlm from http://www.nongnu.org/libntlm/ */
15807 const char *userid
= (soap
->proxy_userid
? soap
->proxy_userid
: soap
->userid
);
15808 const char *passwd
= (soap
->proxy_passwd
? soap
->proxy_passwd
: soap
->passwd
);
15809 struct SOAP_ENV__Header
*oldheader
;
15810 if (soap
->ntlm_challenge
&& userid
&& passwd
&& soap
->authrealm
)
15811 { tSmbNtlmAuthRequest req
;
15812 tSmbNtlmAuthResponse res
;
15813 tSmbNtlmAuthChallenge ch
;
15814 short k
= soap
->keep_alive
;
15815 size_t l
= soap
->length
;
15816 size_t c
= soap
->count
;
15817 soap_mode m
= soap
->mode
, o
= soap
->omode
;
15818 int s
= soap
->status
;
15819 char *a
= soap
->action
;
15820 short v
= soap
->version
;
15821 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "NTLM '%s'\n", soap
->ntlm_challenge
));
15822 if (!*soap
->ntlm_challenge
)
15823 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
15824 /* S -> C 401 Unauthorized
15825 WWW-Authenticate: NTLM
15827 buildSmbNtlmAuthRequest(&req
, userid
, soap
->authrealm
);
15828 soap
->ntlm_challenge
= soap_s2base64(soap
, (unsigned char*)&req
, NULL
, SmbLength(&req
));
15829 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "NTLM C->S Type 2: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap
->ntlm_challenge
));
15831 Authorization: NTLM TlRMTVNTUAABAAAAA7IAAAoACgApAAAACQAJACAAAABMSUdIVENJVFlVUlNBLU1JTk9S
15833 soap
->omode
= SOAP_IO_BUFFER
;
15834 if (soap_begin_send(soap
))
15835 return soap
->error
;
15836 soap
->keep_alive
= 1;
15837 soap
->status
= command
;
15838 if (soap
->fpost(soap
, endpoint
, host
, port
, soap
->path
, soap
->action
, 0)
15839 || soap_end_send_flush(soap
))
15840 return soap
->error
;
15842 soap
->keep_alive
= k
;
15843 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "NTLM S->C Type 2: waiting on server NTLM response\n"));
15844 oldheader
= soap
->header
;
15845 if (soap_begin_recv(soap
))
15846 if (soap
->error
== SOAP_EOF
)
15847 return soap
->error
;
15848 soap_end_recv(soap
);
15849 soap
->header
= oldheader
;
15851 if (soap
->status
!= 401 && soap
->status
!= 407)
15852 return soap
->error
= SOAP_NTLM_ERROR
;
15853 soap
->error
= SOAP_OK
;
15855 /* S -> C 401 Unauthorized
15856 WWW-Authenticate: NTLM TlRMTVNTUAACAAAAAAAAACgAAAABggAAU3J2Tm9uY2UAAAAAAAAAAA==
15858 soap_base642s(soap
, soap
->ntlm_challenge
, (char*)&ch
, sizeof(tSmbNtlmAuthChallenge
), NULL
);
15859 buildSmbNtlmAuthResponse(&ch
, &res
, userid
, passwd
);
15860 soap
->ntlm_challenge
= soap_s2base64(soap
, (unsigned char*)&res
, NULL
, SmbLength(&res
));
15861 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "NTLM C->S Type 3: sending NTLM authorization to server\nAuthorization: NTLM %s\n", soap
->ntlm_challenge
));
15863 Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
15865 soap
->userid
= NULL
;
15866 soap
->passwd
= NULL
;
15867 soap
->proxy_userid
= NULL
;
15868 soap
->proxy_passwd
= NULL
;
15869 soap
->keep_alive
= k
;
15883 /******************************************************************************/
15888 soap_s2base64(struct soap
*soap
, const unsigned char *s
, char *t
, int n
)
15890 register unsigned long m
;
15893 t
= (char*)soap_malloc(soap
, (n
+ 2) / 3 * 4 + 1);
15900 for (; n
> 2; n
-= 3, s
+= 3)
15902 m
= (m
<< 8) | s
[1];
15903 m
= (m
<< 8) | s
[2];
15904 for (i
= 4; i
> 0; m
>>= 6)
15905 t
[--i
] = soap_base64o
[m
& 0x3F];
15909 if (n
> 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
15911 for (i
= 0; i
< n
; i
++)
15912 m
= (m
<< 8) | *s
++;
15915 for (i
= 4; i
> 0; m
>>= 6)
15916 t
[--i
] = soap_base64o
[m
& 0x3F];
15917 for (i
= 3; i
> n
; i
--)
15925 /******************************************************************************/
15930 soap_base642s(struct soap
*soap
, const char *s
, char *t
, size_t l
, int *n
)
15931 { register size_t i
, j
;
15932 register soap_wchar c
;
15933 register unsigned long m
;
15934 register const char *p
;
15940 return SOAP_NON_NULL
;
15943 { l
= (strlen(s
) + 3) / 4 * 3 + 1; /* make sure enough space for \0 */
15944 t
= (char*)soap_malloc(soap
, l
);
15951 for (i
= 0; ; i
+= 3, l
-= 3)
15956 if (c
== '=' || !c
)
15960 *t
++ = (char)((m
>> 4) & 0xFF);
15965 *t
++ = (char)((m
>> 10) & 0xFF);
15966 *t
++ = (char)((m
>> 2) & 0xFF);
15978 if (c
>= 0 && c
<= 79)
15979 { int b
= soap_base64i
[c
];
15981 { soap
->error
= SOAP_TYPE
;
15987 else if (!soap_blank(c
+ '+'))
15988 { soap
->error
= SOAP_TYPE
;
15999 *t
++ = (char)((m
>> 16) & 0xFF);
16000 *t
++ = (char)((m
>> 8) & 0xFF);
16001 *t
++ = (char)(m
& 0xFF);
16006 /******************************************************************************/
16011 soap_s2hex(struct soap
*soap
, const unsigned char *s
, char *t
, int n
)
16012 { register char *p
;
16014 t
= (char*)soap_malloc(soap
, 2 * n
+ 1);
16020 { for (; n
> 0; n
--)
16021 { register int m
= *s
++;
16022 *t
++ = (char)((m
>> 4) + (m
> 159 ? 'a' - 10 : '0'));
16024 *t
++ = (char)(m
+ (m
> 9 ? 'a' - 10 : '0'));
16032 /******************************************************************************/
16037 soap_hex2s(struct soap
*soap
, const char *s
, char *t
, size_t l
, int *n
)
16038 { register const char *p
;
16044 return SOAP_NON_NULL
;
16047 { l
= strlen(s
) / 2 + 1; /* make sure enough space for \0 */
16048 t
= (char*)soap_malloc(soap
, l
);
16054 { register int d1
, d2
;
16061 *t
++ = (char)(((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0'));
16072 /******************************************************************************/
16073 #ifndef WITH_NOHTTP
16078 soap_puthttphdr(struct soap
*soap
, int status
, size_t count
)
16079 { if (soap
->status
!= SOAP_GET
&& soap
->status
!= SOAP_DEL
&& soap
->status
!= SOAP_CONNECT
)
16080 { register const char *s
= "text/xml; charset=utf-8";
16081 register int err
= SOAP_OK
;
16082 #ifndef WITH_LEANER
16083 register const char *r
= NULL
;
16085 if ((status
== SOAP_FILE
|| soap
->status
== SOAP_PUT
|| soap
->status
== SOAP_POST_FILE
) && soap
->http_content
&& !strchr(s
, 10) && !strchr(s
, 13))
16086 s
= soap
->http_content
;
16087 else if (status
== SOAP_HTML
)
16088 s
= "text/html; charset=utf-8";
16089 else if (count
|| ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
))
16090 { if (soap
->version
== 2)
16091 s
= "application/soap+xml; charset=utf-8";
16093 #ifndef WITH_LEANER
16094 if (soap
->mode
& (SOAP_ENC_DIME
| SOAP_ENC_MTOM
))
16095 { if (soap
->mode
& SOAP_ENC_MTOM
)
16096 { if (soap
->version
== 2)
16097 r
= "application/soap+xml";
16100 s
= "application/xop+xml";
16103 s
= "application/dime";
16105 if ((soap
->mode
& SOAP_ENC_MIME
) && soap
->mime
.boundary
&& strlen(soap
->mime
.boundary
) + strlen(soap
->mime
.start
? soap
->mime
.start
: SOAP_STR_EOS
) < sizeof(soap
->tmpbuf
) - 80)
16106 { register const char *t
;
16107 #ifdef HAVE_SNPRINTF
16108 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap
->mime
.boundary
);
16110 sprintf(soap
->tmpbuf
, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap
->mime
.boundary
);
16112 t
= strchr(s
, ';');
16114 strncat(soap
->tmpbuf
, s
, t
- s
);
16116 strcat(soap
->tmpbuf
, s
);
16117 if (soap
->mime
.start
&& strlen(soap
->tmpbuf
) + strlen(soap
->mime
.start
) + 11 < sizeof(soap
->tmpbuf
))
16118 { strcat(soap
->tmpbuf
, "\"; start=\"");
16119 strcat(soap
->tmpbuf
, soap
->mime
.start
);
16121 strcat(soap
->tmpbuf
, "\"");
16122 if (r
&& strlen(soap
->tmpbuf
) + strlen(r
) + 15 < sizeof(soap
->tmpbuf
))
16123 { strcat(soap
->tmpbuf
, "; start-info=\"");
16124 strcat(soap
->tmpbuf
, r
);
16125 strcat(soap
->tmpbuf
, "\"");
16129 strncpy(soap
->tmpbuf
, s
, sizeof(soap
->tmpbuf
));
16130 soap
->tmpbuf
[sizeof(soap
->tmpbuf
) - 1] = '\0';
16132 if (status
== SOAP_OK
&& soap
->version
== 2 && soap
->action
&& strlen(soap
->action
) + strlen(s
) < sizeof(soap
->tmpbuf
) - 80)
16134 #ifdef HAVE_SNPRINTF
16135 size_t l
= strlen(s
);
16136 soap_snprintf(soap
->tmpbuf
+ l
, sizeof(soap
->tmpbuf
) - l
, "; action=\"%s\"", soap
->action
);
16138 sprintf(soap
->tmpbuf
+ strlen(s
), "; action=\"%s\"", soap
->action
);
16142 if ((err
= soap
->fposthdr(soap
, "Content-Type", s
)))
16145 if ((soap
->omode
& SOAP_ENC_ZLIB
))
16148 err
= soap
->fposthdr(soap
, "Content-Encoding", soap
->zlib_out
== SOAP_ZLIB_DEFLATE
? "deflate" : "gzip");
16150 err
= soap
->fposthdr(soap
, "Content-Encoding", "deflate");
16156 #ifndef WITH_LEANER
16157 if ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
)
16158 err
= soap
->fposthdr(soap
, "Transfer-Encoding", "chunked");
16163 #ifdef HAVE_SNPRINTF
16164 soap_snprintf(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%lu", (unsigned long)count
);
16166 sprintf(soap
->tmpbuf
, "%lu", (unsigned long)count
);
16168 err
= soap
->fposthdr(soap
, "Content-Length", soap
->tmpbuf
);
16173 return soap
->fposthdr(soap
, "Connection", soap
->keep_alive
? "keep-alive" : "close");
16178 /******************************************************************************/
16181 soap_set_validation_fault(struct soap
*soap
, const char *s
, const char *t
)
16186 #ifdef HAVE_SNPRINTF
16187 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "Validation constraint violation: %s%s in element '%s'", s
, t
? t
: SOAP_STR_EOS
, soap
->tag
);
16189 if (strlen(soap
->tag
) + strlen(t
) < sizeof(soap
->msgbuf
) - 100)
16190 sprintf(soap
->msgbuf
, "Validation constraint violation: %s%s in element '%s'", s
, t
, soap
->tag
);
16192 sprintf(soap
->msgbuf
, "Validation constraint violation: %s", s
);
16197 #ifdef HAVE_SNPRINTF
16198 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "Validation constraint violation: %s%s", s
, t
? t
: SOAP_STR_EOS
);
16200 if (strlen(soap
->tag
) + strlen(t
) < sizeof(soap
->msgbuf
) - 100)
16201 sprintf(soap
->msgbuf
, "Validation constraint violation: %s%s", s
, t
);
16203 sprintf(soap
->msgbuf
, "Validation constraint violation: %s", s
);
16206 return soap
->msgbuf
;
16210 /******************************************************************************/
16215 soap_set_fault(struct soap
*soap
)
16216 { const char **c
= soap_faultcode(soap
);
16217 const char **s
= soap_faultstring(soap
);
16218 if (soap
->fseterror
)
16219 soap
->fseterror(soap
, c
, s
);
16221 { if (soap
->version
== 2)
16222 *c
= "SOAP-ENV:Sender";
16224 *c
= "SOAP-ENV:Client";
16228 switch (soap
->error
)
16231 case SOAP_CLI_FAULT
:
16232 *s
= "Client fault";
16234 case SOAP_SVR_FAULT
:
16235 *s
= "Server fault";
16237 case SOAP_TAG_MISMATCH
:
16238 *s
= soap_set_validation_fault(soap
, "tag name or namespace mismatch", NULL
);
16241 *s
= soap_set_validation_fault(soap
, "data type mismatch ", soap
->type
);
16243 case SOAP_SYNTAX_ERROR
:
16244 *s
= "Well-formedness violation";
16247 *s
= "No tag: no XML root element or missing SOAP message body element";
16249 case SOAP_MUSTUNDERSTAND
:
16250 *c
= "SOAP-ENV:MustUnderstand";
16251 #ifdef HAVE_SNPRINTF
16252 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "The data in element '%s' must be understood but cannot be handled", soap
->tag
);
16254 strncpy(soap
->msgbuf
, soap
->tag
, sizeof(soap
->msgbuf
));
16255 soap
->msgbuf
[sizeof(soap
->msgbuf
) - 1] = '\0';
16259 case SOAP_VERSIONMISMATCH
:
16260 *c
= "SOAP-ENV:VersionMismatch";
16261 *s
= "Invalid SOAP message or SOAP version mismatch";
16263 case SOAP_DATAENCODINGUNKNOWN
:
16264 *c
= "SOAP-ENV:DataEncodingUnknown";
16265 *s
= "Unsupported SOAP data encoding";
16267 case SOAP_NAMESPACE
:
16268 *s
= soap_set_validation_fault(soap
, "namespace error", NULL
);
16270 case SOAP_USER_ERROR
:
16271 *s
= "User data error";
16273 case SOAP_FATAL_ERROR
:
16274 *s
= "Fatal error";
16276 case SOAP_NO_METHOD
:
16277 #ifdef HAVE_SNPRINTF
16278 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "Method '%s' not implemented: method name or namespace not recognized", soap
->tag
);
16280 sprintf(soap
->msgbuf
, "Method '%s' not implemented: method name or namespace not recognized", soap
->tag
);
16285 *s
= "Data required for operation";
16287 case SOAP_GET_METHOD
:
16288 *s
= "HTTP GET method not implemented";
16290 case SOAP_PUT_METHOD
:
16291 *s
= "HTTP PUT method not implemented";
16293 case SOAP_HTTP_METHOD
:
16294 *s
= "HTTP method not implemented";
16297 *s
= "Out of memory";
16300 *s
= "Memory overflow or memory corruption error";
16303 *s
= "Header line too long";
16306 *s
= "Array index out of bounds";
16309 *s
= soap_set_validation_fault(soap
, "nil not allowed", NULL
);
16311 case SOAP_DUPLICATE_ID
:
16312 *s
= soap_set_validation_fault(soap
, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap
->id
);
16313 if (soap
->version
== 2)
16314 *soap_faultsubcode(soap
) = "SOAP-ENC:DuplicateID";
16316 case SOAP_MISSING_ID
:
16317 *s
= soap_set_validation_fault(soap
, "missing id for ref ", soap
->id
);
16318 if (soap
->version
== 2)
16319 *soap_faultsubcode(soap
) = "SOAP-ENC:MissingID";
16322 *s
= soap_set_validation_fault(soap
, "incompatible object type id-ref ", soap
->id
);
16327 case SOAP_UDP_ERROR
:
16328 *s
= "Message too large for UDP packet";
16330 case SOAP_TCP_ERROR
:
16331 *s
= tcp_error(soap
);
16334 case SOAP_HTTP_ERROR
:
16335 *s
= "An HTTP processing error occurred";
16337 case SOAP_NTLM_ERROR
:
16338 *s
= "An HTTP NTLM authentication error occurred";
16340 case SOAP_SSL_ERROR
:
16341 #ifdef WITH_OPENSSL
16342 *s
= "SSL/TLS error";
16344 *s
= "OpenSSL not installed: recompile with -DWITH_OPENSSL";
16347 case SOAP_PLUGIN_ERROR
:
16348 *s
= "Plugin registry error";
16350 case SOAP_DIME_ERROR
:
16351 *s
= "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE";
16353 case SOAP_DIME_HREF
:
16354 *s
= "DIME href to missing attachment";
16356 case SOAP_DIME_MISMATCH
:
16357 *s
= "DIME version/transmission error";
16359 case SOAP_DIME_END
:
16360 *s
= "End of DIME error";
16362 case SOAP_MIME_ERROR
:
16363 *s
= "MIME format error";
16365 case SOAP_MIME_HREF
:
16366 *s
= "MIME href to missing attachment";
16368 case SOAP_MIME_END
:
16369 *s
= "End of MIME error";
16371 case SOAP_ZLIB_ERROR
:
16373 #ifdef HAVE_SNPRINTF
16374 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "Zlib/gzip error: '%s'", soap
->d_stream
->msg
? soap
->d_stream
->msg
: SOAP_STR_EOS
);
16376 sprintf(soap
->msgbuf
, "Zlib/gzip error: '%s'", soap
->d_stream
->msg
? soap
->d_stream
->msg
: SOAP_STR_EOS
);
16380 *s
= "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
16383 case SOAP_REQUIRED
:
16384 *s
= soap_set_validation_fault(soap
, "missing required attribute", NULL
);
16386 case SOAP_PROHIBITED
:
16387 *s
= soap_set_validation_fault(soap
, "prohibited attribute present", NULL
);
16390 *s
= soap_set_validation_fault(soap
, "occurrence violation", NULL
);
16393 *s
= soap_set_validation_fault(soap
, "content range or length violation", NULL
);
16395 case SOAP_FD_EXCEEDED
:
16396 *s
= "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
16398 case SOAP_UTF_ERROR
:
16399 *s
= "UTF content encoding error";
16402 *s
= "Stopped: no response sent or received (informative)";
16407 *s
= soap_strerror(soap
); /* *s = soap->msgbuf */
16409 if (strlen(soap
->msgbuf
) + 25 < sizeof(soap
->msgbuf
))
16410 { memmove(soap
->msgbuf
+ 25, soap
->msgbuf
, strlen(soap
->msgbuf
) + 1);
16411 memcpy(soap
->msgbuf
, "End of file or no input: ", 25);
16416 *s
= "End of file or no input";
16420 #ifndef WITH_NOHTTP
16422 if (soap
->error
> 200 && soap
->error
< 600)
16424 #ifdef HAVE_SNPRINTF
16425 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "HTTP Error: %d %s", soap
->error
, http_error(soap
, soap
->error
));
16427 sprintf(soap
->msgbuf
, "HTTP Error: %d %s", soap
->error
, http_error(soap
, soap
->error
));
16435 #ifdef HAVE_SNPRINTF
16436 soap_snprintf(soap
->msgbuf
, sizeof(soap
->msgbuf
), "Error %d", soap
->error
);
16438 sprintf(soap
->msgbuf
, "Error %d", soap
->error
);
16446 /******************************************************************************/
16451 soap_send_fault(struct soap
*soap
)
16452 { register int status
= soap
->error
;
16453 if (status
== SOAP_OK
|| status
== SOAP_STOP
)
16454 return soap_closesock(soap
);
16455 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Sending back fault struct for error code %d\n", soap
->error
));
16456 soap
->keep_alive
= 0; /* to terminate connection */
16457 soap_set_fault(soap
);
16458 if (soap
->error
< 200 && soap
->error
!= SOAP_FAULT
)
16459 soap
->header
= NULL
;
16460 if (status
!= SOAP_EOF
|| (!soap
->recv_timeout
&& !soap
->send_timeout
))
16461 { register int r
= 1;
16463 if (soap
->fpoll
&& soap
->fpoll(soap
))
16466 else if (soap_valid_socket(soap
->socket
))
16467 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_SND
, 0);
16470 if (!(r
& SOAP_TCP_SELECT_SND
)
16471 || ((r
& SOAP_TCP_SELECT_RCV
)
16472 && recv(soap
->socket
, (char*)&t
, 1, MSG_PEEK
) < 0))
16479 { soap
->error
= SOAP_OK
;
16480 soap
->encodingStyle
= NULL
; /* no encodingStyle in Faults */
16481 soap_serializeheader(soap
);
16482 soap_serializefault(soap
);
16483 soap_begin_count(soap
);
16484 if (soap
->mode
& SOAP_IO_LENGTH
)
16485 { soap_envelope_begin_out(soap
);
16486 soap_putheader(soap
);
16487 soap_body_begin_out(soap
);
16488 soap_putfault(soap
);
16489 soap_body_end_out(soap
);
16490 soap_envelope_end_out(soap
);
16492 soap_end_count(soap
);
16493 if (soap_response(soap
, status
)
16494 || soap_envelope_begin_out(soap
)
16495 || soap_putheader(soap
)
16496 || soap_body_begin_out(soap
)
16497 || soap_putfault(soap
)
16498 || soap_body_end_out(soap
)
16499 || soap_envelope_end_out(soap
))
16500 return soap_closesock(soap
);
16501 soap_end_send(soap
);
16504 soap
->error
= status
;
16505 return soap_closesock(soap
);
16509 /******************************************************************************/
16514 soap_recv_fault(struct soap
*soap
, int check
)
16515 { register int status
= soap
->error
;
16516 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Check if receiving SOAP Fault\n"));
16518 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
16519 if (soap
->error
!= SOAP_NO_TAG
16520 && (soap
->error
!= SOAP_TAG_MISMATCH
|| soap
->level
!= 2))
16521 return soap
->error
;
16523 else if (soap
->version
== 0) /* check == 1 but no SOAP: do not parse SOAP Fault */
16525 soap
->error
= SOAP_OK
;
16526 if (soap_getfault(soap
))
16527 { /* check flag set: check if SOAP Fault is present, if not just return */
16528 if (check
&& soap
->error
== SOAP_TAG_MISMATCH
&& soap
->level
== 2)
16529 return soap
->error
= SOAP_OK
;
16530 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Error: soap_get_soapfault() failed at level %u tag '%s'\n", soap
->level
, soap
->tag
));
16531 *soap_faultcode(soap
) = (soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
16532 soap
->error
= status
;
16533 soap_set_fault(soap
);
16536 { register const char *s
= *soap_faultcode(soap
);
16537 if (!soap_match_tag(soap
, s
, "SOAP-ENV:Server") || !soap_match_tag(soap
, s
, "SOAP-ENV:Receiver"))
16538 status
= SOAP_SVR_FAULT
;
16539 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:Client") || !soap_match_tag(soap
, s
, "SOAP-ENV:Sender"))
16540 status
= SOAP_CLI_FAULT
;
16541 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:MustUnderstand"))
16542 status
= SOAP_MUSTUNDERSTAND
;
16543 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:VersionMismatch"))
16544 status
= SOAP_VERSIONMISMATCH
;
16546 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Received SOAP Fault code %s\n", s
));
16547 status
= SOAP_FAULT
;
16549 if (!soap_body_end_in(soap
))
16550 soap_envelope_end_in(soap
);
16552 soap_end_recv(soap
);
16553 soap
->error
= status
;
16554 return soap_closesock(soap
);
16558 /******************************************************************************/
16559 #ifndef WITH_NOHTTP
16564 soap_send_empty_response(struct soap
*soap
, int httpstatuscode
)
16565 { register soap_mode m
= soap
->omode
;
16566 if (!(m
& SOAP_IO_UDP
))
16568 if ((m
& SOAP_IO
) == SOAP_IO_CHUNK
)
16569 soap
->omode
= (m
& ~SOAP_IO
) | SOAP_IO_BUFFER
;
16570 soap_response(soap
, httpstatuscode
);
16571 soap_end_send(soap
); /* force end of sends */
16572 soap
->error
= SOAP_STOP
; /* stops the server (from returning a response) */
16575 return soap_closesock(soap
);
16580 /******************************************************************************/
16581 #ifndef WITH_NOHTTP
16586 soap_recv_empty_response(struct soap
*soap
)
16587 { if (!(soap
->omode
& SOAP_IO_UDP
))
16588 { if (!soap_begin_recv(soap
))
16592 soap_get_http_body(soap
, NULL
); /* read (empty?) HTTP body and discard */
16594 soap_end_recv(soap
);
16596 else if (soap
->error
== SOAP_NO_DATA
|| soap
->error
== 202)
16597 soap
->error
= SOAP_OK
;
16599 return soap_closesock(soap
);
16604 /******************************************************************************/
16608 soap_strerror(struct soap
*soap
)
16609 { register int err
= soap
->errnum
;
16610 *soap
->msgbuf
= '\0';
16614 # ifdef HAVE_STRERROR_R
16615 # ifdef _GNU_SOURCE
16616 return strerror_r(err
, soap
->msgbuf
, sizeof(soap
->msgbuf
)); /* GNU-specific */
16618 strerror_r(err
, soap
->msgbuf
, sizeof(soap
->msgbuf
)); /* XSI-compliant */
16621 return strerror(err
);
16626 *soap
->msgbuf
= '\0';
16627 len
= FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, err
, MAKELANGID(LANG_NEUTRAL
, SUBLANG_DEFAULT
), (LPSTR
)soap
->msgbuf
, (DWORD
)sizeof(soap
->msgbuf
), NULL
);
16630 *soap
->msgbuf
= '\0';
16631 len
= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, err
, 0, (LPTSTR
)soap
->msgbuf
, (DWORD
)(sizeof(soap
->msgbuf
)/sizeof(TCHAR
)), NULL
);
16632 for (i
= 0; i
<= len
; i
++)
16633 { if (((TCHAR
*)soap
->msgbuf
)[i
] < 0x80)
16634 soap
->msgbuf
[i
] = (char)((TCHAR
*)soap
->msgbuf
)[i
];
16636 soap
->msgbuf
[i
] = '?';
16642 { char *s
= soap
->msgbuf
;
16644 int rt
= soap
->recv_timeout
, st
= soap
->send_timeout
;
16645 int ru
= ' ', su
= ' ';
16647 strcpy(s
, "Operation interrupted or timed out");
16659 #ifdef HAVE_SNPRINTF
16660 size_t l
= strlen(s
);
16661 soap_snprintf(s
+ l
, sizeof(soap
->msgbuf
) - l
, " (%d%cs recv delay)", rt
, ru
);
16663 sprintf(s
+ strlen(s
), " (%d%cs recv delay)", rt
, ru
);
16668 #ifdef HAVE_SNPRINTF
16669 size_t l
= strlen(s
);
16670 soap_snprintf(s
+ l
, sizeof(soap
->msgbuf
) - l
, " (%d%cs send delay)", st
, su
);
16672 sprintf(s
+ strlen(s
), " (%d%cs send delay)", st
, su
);
16677 return soap
->msgbuf
;
16682 /******************************************************************************/
16685 soap_set_error(struct soap
*soap
, const char *faultcode
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
16686 { *soap_faultcode(soap
) = faultcode
;
16687 if (faultsubcodeQName
)
16688 *soap_faultsubcode(soap
) = faultsubcodeQName
;
16689 *soap_faultstring(soap
) = faultstring
;
16690 if (faultdetailXML
&& *faultdetailXML
)
16691 { register const char **s
= soap_faultdetail(soap
);
16693 *s
= faultdetailXML
;
16695 return soap
->error
= soaperror
;
16699 /******************************************************************************/
16704 soap_set_sender_error(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
16705 { return soap_set_error(soap
, soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL
, faultstring
, faultdetailXML
, soaperror
);
16709 /******************************************************************************/
16714 soap_set_receiver_error(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
16715 { return soap_set_error(soap
, soap
->version
== 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL
, faultstring
, faultdetailXML
, soaperror
);
16719 /******************************************************************************/
16722 soap_copy_fault(struct soap
*soap
, const char *faultcode
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
16723 { char *r
= NULL
, *s
= NULL
, *t
= NULL
;
16724 if (faultsubcodeQName
)
16725 r
= soap_strdup(soap
, faultsubcodeQName
);
16727 s
= soap_strdup(soap
, faultstring
);
16728 if (faultdetailXML
)
16729 t
= soap_strdup(soap
, faultdetailXML
);
16730 return soap_set_error(soap
, faultcode
, r
, s
, t
, SOAP_FAULT
);
16734 /******************************************************************************/
16739 soap_sender_fault(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
)
16740 { return soap_sender_fault_subcode(soap
, NULL
, faultstring
, faultdetailXML
);
16744 /******************************************************************************/
16749 soap_sender_fault_subcode(struct soap
*soap
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
16750 { return soap_copy_fault(soap
, soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName
, faultstring
, faultdetailXML
);
16754 /******************************************************************************/
16759 soap_receiver_fault(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
)
16760 { return soap_receiver_fault_subcode(soap
, NULL
, faultstring
, faultdetailXML
);
16764 /******************************************************************************/
16769 soap_receiver_fault_subcode(struct soap
*soap
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
16770 { return soap_copy_fault(soap
, soap
->version
== 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName
, faultstring
, faultdetailXML
);
16774 /******************************************************************************/
16776 #ifndef WITH_NOSTDLIB
16780 soap_print_fault(struct soap
*soap
, FILE *fd
)
16781 { if (soap_check_state(soap
))
16782 fprintf(fd
, "Error: soap struct state not initialized\n");
16783 else if (soap
->error
)
16784 { const char **c
, *v
= NULL
, *s
, *d
;
16785 c
= soap_faultcode(soap
);
16787 soap_set_fault(soap
);
16788 if (soap
->version
== 2)
16789 v
= soap_check_faultsubcode(soap
);
16790 s
= *soap_faultstring(soap
);
16791 d
= soap_check_faultdetail(soap
);
16792 fprintf(fd
, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap
->version
? "SOAP 1." : "Error ", soap
->version
? (int)soap
->version
: soap
->error
, *c
, v
? v
: "no subcode", s
? s
: "[no reason]", d
? d
: "[no detail]");
16798 /******************************************************************************/
16801 #ifndef WITH_NOSTDLIB
16802 #ifndef WITH_COMPAT
16806 soap_stream_fault(struct soap
*soap
, std::ostream
& os
)
16807 { if (soap_check_state(soap
))
16808 os
<< "Error: soap struct state not initialized\n";
16809 else if (soap
->error
)
16810 { const char **c
, *v
= NULL
, *s
, *d
;
16811 c
= soap_faultcode(soap
);
16813 soap_set_fault(soap
);
16814 if (soap
->version
== 2)
16815 v
= soap_check_faultsubcode(soap
);
16816 s
= *soap_faultstring(soap
);
16817 d
= soap_check_faultdetail(soap
);
16818 os
<< (soap
->version
? "SOAP 1." : "Error ")
16819 << (soap
->version
? (int)soap
->version
: soap
->error
)
16820 << " fault: " << *c
16821 << "[" << (v
? v
: "no subcode") << "]"
16823 << "\"" << (s
? s
: "[no reason]") << "\""
16825 << "Detail: " << (d
? d
: "[no detail]")
16834 /******************************************************************************/
16836 #ifndef WITH_NOSTDLIB
16840 soap_sprint_fault(struct soap
*soap
, char *buf
, size_t len
)
16841 { if (soap_check_state(soap
))
16842 { strncpy(buf
, "Error: soap struct not initialized", len
);
16843 buf
[len
- 1] = '\0';
16845 else if (soap
->error
)
16846 { const char **c
, *v
= NULL
, *s
, *d
;
16847 c
= soap_faultcode(soap
);
16849 soap_set_fault(soap
);
16850 if (soap
->version
== 2)
16851 v
= *soap_faultsubcode(soap
);
16852 s
= *soap_faultstring(soap
);
16853 d
= soap_check_faultdetail(soap
);
16854 #ifdef HAVE_SNPRINTF
16855 soap_snprintf(buf
, len
, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap
->version
? "SOAP 1." : "Error ", soap
->version
? (int)soap
->version
: soap
->error
, *c
, v
? v
: "no subcode", s
? s
: "[no reason]", d
? d
: "[no detail]");
16857 if (len
> 40 + (v
? strlen(v
) : 0) + (s
? strlen(s
) : 0) + (d
? strlen(d
) : 0))
16858 sprintf(buf
, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap
->version
? "SOAP 1." : "Error ", soap
->version
? (int)soap
->version
: soap
->error
, *c
, v
? v
: "no subcode", s
? s
: "[no reason]", d
? d
: "[no detail]");
16860 sprintf(buf
, "%s%d fault: %s\n", soap
->version
? "SOAP 1." : "Error ", soap
->version
? (int)soap
->version
: soap
->error
, *c
);
16870 /******************************************************************************/
16872 #ifndef WITH_NOSTDLIB
16876 soap_print_fault_location(struct soap
*soap
, FILE *fd
)
16880 if (soap
->error
&& soap
->error
!= SOAP_STOP
&& soap
->bufidx
<= soap
->buflen
&& soap
->buflen
> 0 && soap
->buflen
<= SOAP_BUFLEN
)
16881 { i
= (int)soap
->bufidx
- 1;
16885 soap
->buf
[i
] = '\0';
16886 if ((int)soap
->buflen
>= i
+ 1024)
16889 j
= (int)soap
->buflen
- 1;
16891 soap
->buf
[j
] = '\0';
16892 fprintf(fd
, "%s%c\n<!-- ** HERE ** -->\n", soap
->buf
, c1
);
16893 if (soap
->bufidx
< soap
->buflen
)
16894 fprintf(fd
, "%s\n", soap
->buf
+ soap
->bufidx
);
16895 soap
->buf
[i
] = (char)c1
;
16896 soap
->buf
[j
] = (char)c2
;
16903 /******************************************************************************/
16908 soap_register_plugin_arg(struct soap
*soap
, int (*fcreate
)(struct soap
*, struct soap_plugin
*, void*), void *arg
)
16909 { register struct soap_plugin
*p
;
16911 if (!(p
= (struct soap_plugin
*)SOAP_MALLOC(soap
, sizeof(struct soap_plugin
))))
16912 return soap
->error
= SOAP_EOM
;
16917 r
= fcreate(soap
, p
, arg
);
16918 if (!r
&& p
->fdelete
)
16919 { p
->next
= soap
->plugins
;
16921 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Registered '%s' plugin\n", p
->id
));
16924 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p
->id
? p
->id
: "?", r
));
16925 SOAP_FREE(soap
, p
);
16930 /******************************************************************************/
16933 fplugin(struct soap
*soap
, const char *id
)
16934 { register struct soap_plugin
*p
;
16935 for (p
= soap
->plugins
; p
; p
= p
->next
)
16936 if (p
->id
== id
|| !strcmp(p
->id
, id
))
16942 /******************************************************************************/
16947 soap_lookup_plugin(struct soap
*soap
, const char *id
)
16948 { return soap
->fplugin(soap
, id
);
16952 /******************************************************************************/
16957 /******************************************************************************\
16959 * C++ soap struct methods
16961 \******************************************************************************/
16969 /******************************************************************************/
16971 soap::soap(soap_mode m
)
16972 { soap_init1(this, m
);
16976 /******************************************************************************/
16978 soap::soap(soap_mode im
, soap_mode om
)
16979 { soap_init2(this, im
, om
);
16983 /******************************************************************************/
16985 soap::soap(const struct soap
& soap
)
16986 { soap_copy_context(this, &soap
);
16990 /******************************************************************************/
16993 { soap_destroy(this);
16999 /******************************************************************************/