6 gSOAP XML Web services tools
7 Copyright (C) 2000-2010, 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:
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-2010, 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 --------------------------------------------------------------------------------
55 Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
56 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
57 tab (the project file needs to be selected in the file view) and add
58 "wsock32.lib" to the "Object/library modules" entry
60 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
61 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
62 when locally allocated data exceeds 64K.
67 # pragma convert(819) /* EBCDIC to ASCII */
77 # pragma comment(lib, "winsock.lib")
79 # pragma comment(lib, "wsock32.lib")
81 # pragma warning(disable : 4996) /* disable deprecation warnings */
86 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.0 2010-09-20 00:00:00 GMT")
89 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.0 2010-09-20 00:00:00 GMT")
92 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
93 #ifndef SOAP_UNKNOWN_CHAR
94 #define SOAP_UNKNOWN_CHAR (127)
98 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
99 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
100 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
101 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
102 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
104 #define soap_blank(c) ((c) >= 0 && (c) <= 32)
105 #define soap_notblank(c) ((c) > 32)
107 #if defined(WIN32) && !defined(UNDER_CE)
108 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
110 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
113 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
114 static void soap_init_logs(struct soap
*);
117 static void soap_close_logfile(struct soap
*, int);
118 static void soap_set_logfile(struct soap
*, int, const char*);
121 #ifdef SOAP_MEM_DEBUG
122 static void soap_init_mht(struct soap
*);
123 static void soap_free_mht(struct soap
*);
124 static void soap_track_unlink(struct soap
*, const void*);
128 static int soap_set_error(struct soap
*, const char*, const char*, const char*, const char*, int);
129 static int soap_copy_fault(struct soap
*, const char*, const char*, const char*, const char*);
130 static int soap_getattrval(struct soap
*, char*, size_t, soap_wchar
);
134 static void soap_free_ns(struct soap
*soap
);
135 static soap_wchar
soap_char(struct soap
*);
136 static soap_wchar
soap_get_pi(struct soap
*);
137 static int soap_isxdigit(int);
138 static void *fplugin(struct soap
*, const char*);
139 static size_t soap_count_attachments(struct soap
*soap
);
140 static int soap_try_connect_command(struct soap
*, int http_command
, const char *endpoint
, const char *action
);
142 static void soap_update_ptrs(struct soap
*, char*, char*, char*, char*);
143 static int soap_has_copies(struct soap
*, const char*, const char*);
144 static void soap_init_iht(struct soap
*);
145 static void soap_free_iht(struct soap
*);
146 static void soap_init_pht(struct soap
*);
147 static void soap_free_pht(struct soap
*);
152 static const char *soap_set_validation_fault(struct soap
*, const char*, const char*);
153 static int soap_isnumeric(struct soap
*, const char*);
154 static struct soap_nlist
*soap_push_ns(struct soap
*soap
, const char *id
, const char *ns
, short utilized
);
155 static void soap_utilize_ns(struct soap
*soap
, const char *tag
, size_t n
);
160 static struct soap_multipart
*soap_new_multipart(struct soap
*, struct soap_multipart
**, struct soap_multipart
**, char*, size_t);
161 static int soap_putdimefield(struct soap
*, const char*, size_t);
162 static char *soap_getdimefield(struct soap
*, size_t);
163 static void soap_select_mime_boundary(struct soap
*);
164 static int soap_valid_mime_boundary(struct soap
*);
165 static void soap_resolve_attachment(struct soap
*, struct soap_multipart
*);
170 static int soap_getgziphdr(struct soap
*);
174 # ifndef SOAP_SSL_RSA_BITS
175 # define SOAP_SSL_RSA_BITS 2048
177 static int soap_ssl_init_done
= 0;
178 static int ssl_auth_init(struct soap
*);
179 static int ssl_verify_callback(int, X509_STORE_CTX
*);
180 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX
*);
181 static int ssl_password(char*, int, int, void *);
185 # ifndef SOAP_SSL_RSA_BITS
186 # define SOAP_SSL_RSA_BITS 2048
188 static int soap_ssl_init_done
= 0;
189 static const char *ssl_verify(struct soap
*soap
, const char *host
);
190 # if defined(HAVE_PTHREAD_H)
191 # include <pthread.h>
192 /* make GNUTLS thread safe with pthreads */
193 GCRY_THREAD_OPTION_PTHREAD_IMPL
;
194 # elif defined(HAVE_PTH_H)
196 /* make GNUTLS thread safe with PTH */
197 GCRY_THREAD_OPTION_PTH_IMPL
;
201 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
203 static const char *soap_decode(char*, size_t, const char*, const char*);
209 static soap_wchar
soap_getchunkchar(struct soap
*);
210 static const char *http_error(struct soap
*, int);
211 static int http_put(struct soap
*);
212 static int http_get(struct soap
*);
213 static int http_405(struct soap
*);
214 static int http_post(struct soap
*, const char*, const char*, int, const char*, const char*, size_t);
215 static int http_send_header(struct soap
*, const char*);
216 static int http_post_header(struct soap
*, const char*, const char*);
217 static int http_response(struct soap
*, int, size_t);
218 static int http_parse(struct soap
*);
219 static int http_parse_header(struct soap
*, const char*, const char*);
226 static int fsend(struct soap
*, const char*, size_t);
227 static size_t frecv(struct soap
*, char*, size_t);
228 static int tcp_init(struct soap
*);
229 static const char *tcp_error(struct soap
*);
231 static int tcp_gethost(struct soap
*, const char *addr
, struct in_addr
*inaddr
);
233 static SOAP_SOCKET
tcp_connect(struct soap
*, const char *endpoint
, const char *host
, int port
);
234 static SOAP_SOCKET
tcp_accept(struct soap
*, SOAP_SOCKET
, struct sockaddr
*, int*);
235 static int tcp_select(struct soap
*, SOAP_SOCKET
, int, int);
236 static int tcp_disconnect(struct soap
*);
237 static int tcp_closesocket(struct soap
*, SOAP_SOCKET
);
238 static int tcp_shutdownsocket(struct soap
*, SOAP_SOCKET
, int);
239 static const char *soap_strerror(struct soap
*);
242 #define SOAP_TCP_SELECT_RCV 0x1
243 #define SOAP_TCP_SELECT_SND 0x2
244 #define SOAP_TCP_SELECT_ERR 0x4
245 #define SOAP_TCP_SELECT_ALL 0x7
248 #define SOAP_SOCKBLOCK(fd) \
249 { u_long blocking = 0; \
250 ioctlsocket(fd, FIONBIO, &blocking); \
252 #define SOAP_SOCKNONBLOCK(fd) \
253 { u_long nonblocking = 1; \
254 ioctlsocket(fd, FIONBIO, &nonblocking); \
256 #elif defined(VXWORKS)
257 #define SOAP_SOCKBLOCK(fd) \
258 { u_long blocking = 0; \
259 ioctl(fd, FIONBIO, (int)(&blocking)); \
261 #define SOAP_SOCKNONBLOCK(fd) \
262 { u_long nonblocking = 1; \
263 ioctl(fd, FIONBIO, (int)(&nonblocking)); \
266 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
267 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
268 #elif defined(SYMBIAN)
269 #define SOAP_SOCKBLOCK(fd) \
270 { long blocking = 0; \
271 ioctl(fd, 0/*FIONBIO*/, &blocking); \
273 #define SOAP_SOCKNONBLOCK(fd) \
274 { long nonblocking = 1; \
275 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
278 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
279 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
284 #if defined(PALM) && !defined(PALM_2)
285 unsigned short errno
;
289 static const char soap_env1
[42] = "http://schemas.xmlsoap.org/soap/envelope/";
290 static const char soap_enc1
[42] = "http://schemas.xmlsoap.org/soap/encoding/";
291 static const char soap_env2
[40] = "http://www.w3.org/2003/05/soap-envelope";
292 static const char soap_enc2
[40] = "http://www.w3.org/2003/05/soap-encoding";
293 static const char soap_rpc
[35] = "http://www.w3.org/2003/05/soap-rpc";
297 const struct soap_double_nan soap_double_nan
= {0xFFFFFFFF, 0xFFFFFFFF};
298 static const char soap_base64o
[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
299 static const char soap_base64i
[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63";
303 static const char soap_indent
[11] = "\n\t\t\t\t\t\t\t\t\t";
304 /* Alternative indentation form for SOAP_XML_INDENT:
305 static const char soap_indent[21] = "\n ";
310 # define SOAP_CANARY (0xC0DE)
313 static const char soap_padding
[4] = "\0\0\0";
314 #define SOAP_STR_PADDING (soap_padding)
315 #define SOAP_STR_EOS (soap_padding)
316 #define SOAP_NON_NULL (soap_padding)
319 static const struct soap_code_map html_entity_codes
[] = /* entities for XHTML parsing */
422 static const struct soap_code_map h_error_codes
[] =
424 #ifdef HOST_NOT_FOUND
425 { HOST_NOT_FOUND
, "Host not found" },
428 { TRY_AGAIN
, "Try Again" },
431 { NO_RECOVERY
, "No Recovery" },
434 { NO_DATA
, "No Data" },
437 { NO_ADDRESS
, "No Address" },
446 static const struct soap_code_map h_http_error_codes
[] =
450 { 203, "Non-Authoritative Information" },
451 { 204, "No Content" },
452 { 205, "Reset Content" },
453 { 206, "Partial Content" },
454 { 300, "Multiple Choices" },
455 { 301, "Moved Permanently" },
457 { 303, "See Other" },
458 { 304, "Not Modified" },
459 { 305, "Use Proxy" },
460 { 307, "Temporary Redirect" },
461 { 400, "Bad Request" },
462 { 401, "Unauthorized" },
463 { 402, "Payment Required" },
464 { 403, "Forbidden" },
465 { 404, "Not Found" },
466 { 405, "Method Not Allowed" },
467 { 406, "Not Acceptable" },
468 { 407, "Proxy Authentication Required" },
469 { 408, "Request Time-out" },
472 { 411, "Length Required" },
473 { 412, "Precondition Failed" },
474 { 413, "Request Entity Too Large" },
475 { 414, "Request-URI Too Large" },
476 { 415, "Unsupported Media Type" },
477 { 416, "Requested range not satisfiable" },
478 { 417, "Expectation Failed" },
479 { 500, "Internal Server Error" },
480 { 501, "Not Implemented" },
481 { 502, "Bad Gateway" },
482 { 503, "Service Unavailable" },
483 { 504, "Gateway Time-out" },
484 { 505, "HTTP Version not supported" },
491 static const struct soap_code_map h_ssl_error_codes
[] =
493 #define _SSL_ERROR(e) { e, #e }
494 _SSL_ERROR(SSL_ERROR_SSL
),
495 _SSL_ERROR(SSL_ERROR_ZERO_RETURN
),
496 _SSL_ERROR(SSL_ERROR_WANT_READ
),
497 _SSL_ERROR(SSL_ERROR_WANT_WRITE
),
498 _SSL_ERROR(SSL_ERROR_WANT_CONNECT
),
499 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP
),
500 _SSL_ERROR(SSL_ERROR_SYSCALL
),
506 static const struct soap_code_map mime_codes
[] =
507 { { SOAP_MIME_7BIT
, "7bit" },
508 { SOAP_MIME_8BIT
, "8bit" },
509 { SOAP_MIME_BINARY
, "binary" },
510 { SOAP_MIME_QUOTED_PRINTABLE
, "quoted-printable" },
511 { SOAP_MIME_BASE64
, "base64" },
512 { SOAP_MIME_IETF_TOKEN
, "ietf-token" },
513 { SOAP_MIME_X_TOKEN
, "x-token" },
519 static int tcp_done
= 0;
522 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
526 /******************************************************************************/
530 fsend(struct soap
*soap
, const char *s
, size_t n
)
531 { register int nwritten
, err
;
532 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
534 { soap
->os
->write(s
, (std::streamsize
)n
);
535 if (soap
->os
->good())
542 { if (soap_valid_socket(soap
->socket
))
544 if (soap
->send_timeout
)
549 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ALL
, soap
->send_timeout
);
554 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ALL
, soap
->send_timeout
);
557 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
);
565 if (err
!= SOAP_EINTR
&& err
!= SOAP_EAGAIN
&& err
!= SOAP_EWOULDBLOCK
)
571 nwritten
= SSL_write(soap
->ssl
, s
, (int)n
);
573 nwritten
= BIO_write(soap
->bio
, s
, (int)n
);
578 nwritten
= gnutls_record_send(soap
->session
, s
, n
);
582 if ((soap
->omode
& SOAP_IO_UDP
))
584 nwritten
= sendto(soap
->socket
, (char*)s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, (SOAP_WINSOCKINT
)soap
->peerlen
);
586 nwritten
= send(soap
->socket
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
);
587 /* retry and back-off algorithm */
588 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
592 if ((soap
->connect_flags
& SO_BROADCAST
))
593 udp_repeat
= 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
595 udp_repeat
= 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
596 udp_delay
= (soap_random
% 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
598 { tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ERR
, -1000 * udp_delay
);
600 nwritten
= sendto(soap
->socket
, (char*)s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, (SOAP_WINSOCKINT
)soap
->peerlen
);
602 nwritten
= send(soap
->socket
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
);
604 if (udp_delay
> 500) /* UDP_UPPER_DELAY */
607 while (nwritten
< 0 && --udp_repeat
> 0);
612 #if !defined(PALM) && !defined(AS400)
613 nwritten
= send(soap
->socket
, s
, (int)n
, soap
->socket_flags
);
615 nwritten
= send(soap
->socket
, (void*)s
, n
, soap
->socket_flags
);
620 err
= soap_socket_errno(soap
->socket
);
622 if (soap
->ssl
&& (r
= SSL_get_error(soap
->ssl
, nwritten
)) != SSL_ERROR_NONE
&& r
!= SSL_ERROR_WANT_READ
&& r
!= SSL_ERROR_WANT_WRITE
)
623 { soap
->errnum
= err
;
629 { if (nwritten
== GNUTLS_E_INTERRUPTED
)
631 else if (nwritten
== GNUTLS_E_AGAIN
)
635 if (err
== SOAP_EWOULDBLOCK
|| err
== SOAP_EAGAIN
)
637 #if defined(WITH_OPENSSL)
638 if (soap
->ssl
&& r
== SSL_ERROR_WANT_READ
)
639 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
641 #elif defined(WITH_GNUTLS)
642 if (soap
->session
&& !gnutls_record_get_direction(soap
->session
))
643 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
646 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
647 if (!r
&& soap
->send_timeout
)
649 if (r
< 0 && soap
->errnum
!= SOAP_EINTR
)
652 else if (err
&& err
!= SOAP_EINTR
)
653 { soap
->errnum
= err
;
656 nwritten
= 0; /* and call write() again */
662 nwritten
= fwrite((void*)s
, 1, n
, stdout
);
666 nwritten
= fwrite(s
, 1, n
, soap
->sendfd
);
671 nwritten
= (httpBlockPut(soap
->rpmreqid
, (char*)s
, n
) == 0) ? n
: -1;
674 nwritten
= fwrite(s
, sizeof(char), n
, fdopen(soap
->sendfd
, "w"));
677 nwritten
= _write(soap
->sendfd
, s
, (unsigned int)n
);
679 nwritten
= write(soap
->sendfd
, s
, (unsigned int)n
);
691 if (err
&& err
!= SOAP_EINTR
&& err
!= SOAP_EWOULDBLOCK
&& err
!= SOAP_EAGAIN
)
692 { soap
->errnum
= err
;
695 nwritten
= 0; /* and call write() again */
706 /******************************************************************************/
711 soap_send_raw(struct soap
*soap
, const char *s
, size_t n
)
714 if (soap
->mode
& SOAP_IO_LENGTH
)
717 if (soap
->fpreparesend
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
)
718 return soap
->error
= soap
->fpreparesend(soap
, s
, n
);
722 if (soap
->mode
& SOAP_IO
)
723 { register size_t i
= SOAP_BUFLEN
- soap
->bufidx
;
725 { memcpy(soap
->buf
+ soap
->bufidx
, s
, i
);
726 soap
->bufidx
= SOAP_BUFLEN
;
727 if (soap_flush(soap
))
733 memcpy(soap
->buf
+ soap
->bufidx
, s
, n
);
737 return soap_flush_raw(soap
, s
, n
);
741 /******************************************************************************/
746 soap_flush(struct soap
*soap
)
747 { register size_t n
= soap
->bufidx
;
751 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
753 if (soap
->fpreparesend
&& (r
= soap
->fpreparesend(soap
, soap
->buf
, n
)))
754 return soap
->error
= r
;
759 if (soap
->mode
& SOAP_ENC_ZLIB
)
760 { soap
->d_stream
->next_in
= (Byte
*)soap
->buf
;
761 soap
->d_stream
->avail_in
= (unsigned int)n
;
763 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)n
);
766 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflating %u bytes\n", soap
->d_stream
->avail_in
));
767 if (deflate(soap
->d_stream
, Z_NO_FLUSH
) != Z_OK
)
768 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to deflate: %s\n", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
769 return soap
->error
= SOAP_ZLIB_ERROR
;
771 if (!soap
->d_stream
->avail_out
)
772 { if (soap_flush_raw(soap
, soap
->z_buf
, SOAP_BUFLEN
))
774 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
775 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
777 } while (soap
->d_stream
->avail_in
);
781 return soap_flush_raw(soap
, soap
->buf
, n
);
787 /******************************************************************************/
792 soap_flush_raw(struct soap
*soap
, const char *s
, size_t n
)
793 { if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
795 if (!(t
= (char*)soap_push_block(soap
, NULL
, n
)))
796 return soap
->error
= SOAP_EOM
;
801 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
803 sprintf(t
, "\r\n%lX\r\n" + (soap
->chunksize
? 0 : 2), (unsigned long)n
);
804 DBGMSG(SENT
, t
, strlen(t
));
805 if ((soap
->error
= soap
->fsend(soap
, t
, strlen(t
))))
807 soap
->chunksize
+= n
;
811 return soap
->error
= soap
->fsend(soap
, s
, n
);
815 /******************************************************************************/
820 soap_send(struct soap
*soap
, const char *s
)
822 return soap_send_raw(soap
, s
, strlen(s
));
827 /******************************************************************************/
833 soap_send2(struct soap
*soap
, const char *s1
, const char *s2
)
834 { if (soap_send(soap
, s1
))
836 return soap_send(soap
, s2
);
841 /******************************************************************************/
847 soap_send3(struct soap
*soap
, const char *s1
, const char *s2
, const char *s3
)
848 { if (soap_send(soap
, s1
)
849 || soap_send(soap
, s2
))
851 return soap_send(soap
, s3
);
856 /******************************************************************************/
860 frecv(struct soap
*soap
, char *s
, size_t n
)
862 register int retries
= 100; /* max 100 retries with non-blocking sockets */
864 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
866 { if (soap
->is
->good())
867 return soap
->is
->read(s
, (std::streamsize
)n
).gcount();
871 if (soap_valid_socket(soap
->socket
))
875 register int err
= 0;
878 if (soap
->recv_timeout
&& !soap
->ssl
) /* SSL: sockets are nonblocking */
880 if (soap
->recv_timeout
)
883 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
);
889 if (r
!= SOAP_EINTR
&& r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
895 { r
= SSL_read(soap
->ssl
, s
, (int)n
);
898 err
= SSL_get_error(soap
->ssl
, r
);
899 if (err
!= SSL_ERROR_NONE
&& err
!= SSL_ERROR_WANT_READ
&& err
!= SSL_ERROR_WANT_WRITE
)
903 { r
= BIO_read(soap
->bio
, s
, (int)n
);
912 { r
= (int)gnutls_record_recv(soap
->session
, s
, n
);
920 if ((soap
->omode
& SOAP_IO_UDP
))
921 { SOAP_SOCKLEN_T k
= (SOAP_SOCKLEN_T
)sizeof(soap
->peer
);
922 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
923 r
= recvfrom(soap
->socket
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, &k
); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
924 soap
->peerlen
= (size_t)k
;
926 soap
->ip
= ntohl(soap
->peer
.sin_addr
.s_addr
);
931 r
= recv(soap
->socket
, s
, (int)n
, soap
->socket_flags
);
933 /* CycleSyncDisplay(curStatusMsg); */
937 r
= soap_socket_errno(soap
->socket
);
938 if (r
!= SOAP_EINTR
&& r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
943 #if defined(WITH_OPENSSL)
944 if (soap
->ssl
&& err
== SSL_ERROR_WANT_WRITE
)
945 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
947 #elif defined(WITH_GNUTLS)
948 if (soap
->session
&& gnutls_record_get_direction(soap
->session
))
949 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
952 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
953 if (!r
&& soap
->recv_timeout
)
957 if (r
!= SOAP_EINTR
&& r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
963 r
= soap_socket_errno(soap
->socket
);
964 if (r
!= SOAP_EINTR
&& retries
-- <= 0)
972 return fread(s
, 1, n
, stdin
);
975 return fread(s
, 1, n
, soap
->recvfd
);
979 r
= httpBlockRead(soap
->rpmreqid
, s
, n
);
983 r
= _read(soap
->recvfd
, s
, (unsigned int)n
);
985 r
= read(soap
->recvfd
, s
, (unsigned int)n
);
989 soap
->errnum
= soap_errno
;
997 /******************************************************************************/
1001 soap_getchunkchar(struct soap
*soap
)
1002 { if (soap
->bufidx
< soap
->buflen
)
1003 return soap
->buf
[soap
->bufidx
++];
1005 soap
->buflen
= soap
->chunkbuflen
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1006 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes from socket %d\n", (unsigned int)soap
->buflen
, soap
->socket
));
1007 DBGMSG(RECV
, soap
->buf
, soap
->buflen
);
1009 return soap
->buf
[soap
->bufidx
++];
1015 /******************************************************************************/
1018 soap_isxdigit(int c
)
1019 { return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a' && c
<= 'f');
1023 /******************************************************************************/
1028 soap_recv_raw(struct soap
*soap
)
1029 { register size_t ret
;
1030 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
1034 if (soap
->mode
& SOAP_ENC_ZLIB
)
1035 { if (soap
->d_stream
->next_out
== Z_NULL
)
1037 if (soap
->d_stream
->avail_in
|| !soap
->d_stream
->avail_out
)
1038 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflating\n"));
1039 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
1040 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
1041 r
= inflate(soap
->d_stream
, Z_NO_FLUSH
);
1042 if (r
== Z_NEED_DICT
&& soap
->z_dict
)
1043 r
= inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
);
1044 if (r
== Z_OK
|| r
== Z_STREAM_END
)
1046 ret
= soap
->buflen
= SOAP_BUFLEN
- soap
->d_stream
->avail_out
;
1047 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
1048 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)ret
);
1049 if (r
== Z_STREAM_END
)
1050 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
1051 soap
->z_ratio_in
= (float)soap
->d_stream
->total_in
/ (float)soap
->d_stream
->total_out
;
1052 soap
->d_stream
->next_out
= Z_NULL
;
1055 { soap
->count
+= ret
;
1056 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- decompressed ----\n"));
1057 DBGMSG(RECV
, soap
->buf
, ret
);
1058 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n----\n"));
1060 if (soap
->fpreparerecv
&& (r
= soap
->fpreparerecv(soap
, soap
->buf
, ret
)))
1061 return soap
->error
= r
;
1066 else if (r
!= Z_BUF_ERROR
)
1067 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflate error: %s\n", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
1068 soap
->d_stream
->next_out
= Z_NULL
;
1069 soap
->error
= SOAP_ZLIB_ERROR
;
1074 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
&& !soap
->chunksize
)
1075 { memcpy(soap
->buf
, soap
->z_buf
, SOAP_BUFLEN
);
1076 soap
->buflen
= soap
->z_buflen
;
1078 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- compressed ----\n"));
1082 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
) /* read HTTP chunked transfer */
1084 { register soap_wchar c
;
1086 if (soap
->chunksize
)
1087 { soap
->buflen
= ret
= soap
->frecv(soap
, soap
->buf
, soap
->chunksize
> SOAP_BUFLEN
? SOAP_BUFLEN
: soap
->chunksize
);
1088 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Getting chunk: read %u bytes\n", (unsigned int)ret
));
1089 DBGMSG(RECV
, soap
->buf
, ret
);
1091 soap
->chunksize
-= ret
;
1095 if (!soap
->chunkbuflen
)
1096 { soap
->chunkbuflen
= ret
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1097 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret
, soap
->socket
));
1098 DBGMSG(RECV
, soap
->buf
, ret
);
1101 return soap
->ahead
= EOF
;
1104 soap
->bufidx
= soap
->buflen
;
1105 soap
->buflen
= soap
->chunkbuflen
;
1106 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap
->bufidx
, (unsigned int)soap
->buflen
));
1107 while (!soap_isxdigit((int)(c
= soap_getchunkchar(soap
))))
1108 { if ((int)c
== EOF
)
1109 return soap
->ahead
= EOF
;
1113 while (soap_isxdigit((int)(c
= soap_getchunkchar(soap
))) && t
- tmp
< 7);
1114 while ((int)c
!= EOF
&& c
!= '\n')
1115 c
= soap_getchunkchar(soap
);
1117 return soap
->ahead
= EOF
;
1119 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunk size = %s (hex)\n", tmp
));
1120 soap
->chunksize
= soap_strtoul(tmp
, &t
, 16);
1121 if (!soap
->chunksize
)
1122 { soap
->chunkbuflen
= 0;
1123 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of chunked message\n"));
1124 while ((int)c
!= EOF
&& c
!= '\n')
1125 c
= soap_getchunkchar(soap
);
1130 soap
->buflen
= soap
->bufidx
+ soap
->chunksize
;
1131 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap
->bufidx
, (unsigned int)soap
->buflen
, tmp
));
1132 if (soap
->buflen
> soap
->chunkbuflen
)
1133 { soap
->buflen
= soap
->chunkbuflen
;
1134 soap
->chunksize
-= soap
->buflen
- soap
->bufidx
;
1135 soap
->chunkbuflen
= 0;
1136 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap
->buflen
- soap
->bufidx
)));
1138 else if (soap
->chunkbuflen
)
1139 soap
->chunksize
= 0;
1140 ret
= soap
->buflen
- soap
->bufidx
;
1148 soap
->buflen
= ret
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1149 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes from socket %d\n", (unsigned int)ret
, soap
->socket
));
1150 DBGMSG(RECV
, soap
->buf
, ret
);
1153 if (soap
->mode
& SOAP_ENC_ZLIB
)
1154 { memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
1155 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
1156 soap
->d_stream
->avail_in
= (unsigned int)ret
;
1157 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
1158 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
1159 r
= inflate(soap
->d_stream
, Z_NO_FLUSH
);
1160 if (r
== Z_NEED_DICT
&& soap
->z_dict
)
1161 r
= inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
);
1162 if (r
== Z_OK
|| r
== Z_STREAM_END
)
1164 soap
->z_buflen
= soap
->buflen
;
1165 soap
->buflen
= SOAP_BUFLEN
- soap
->d_stream
->avail_out
;
1166 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
1167 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)soap
->buflen
);
1168 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated %u bytes\n", (unsigned int)soap
->buflen
));
1169 if (ret
&& !soap
->buflen
&& r
!= Z_STREAM_END
)
1172 if (r
== Z_STREAM_END
)
1173 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated total %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
1174 soap
->z_ratio_in
= (float)soap
->d_stream
->total_in
/ (float)soap
->d_stream
->total_out
;
1175 soap
->d_stream
->next_out
= Z_NULL
;
1177 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- decompressed ----\n"));
1178 DBGMSG(RECV
, soap
->buf
, ret
);
1180 if (soap
->fpreparerecv
&& (r
= soap
->fpreparerecv(soap
, soap
->buf
, ret
)))
1181 return soap
->error
= r
;
1185 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to inflate: (%d) %s\n", r
, soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
1186 soap
->d_stream
->next_out
= Z_NULL
;
1187 soap
->error
= SOAP_ZLIB_ERROR
;
1193 if (soap
->fpreparerecv
1195 && soap
->zlib_in
== SOAP_ZLIB_NONE
1197 && (r
= soap
->fpreparerecv(soap
, soap
->buf
+ soap
->bufidx
, ret
)))
1198 return soap
->error
= r
;
1205 /******************************************************************************/
1210 soap_recv(struct soap
*soap
)
1213 if (soap
->mode
& SOAP_ENC_DIME
)
1214 { if (soap
->dime
.buflen
)
1217 unsigned char tmp
[12];
1218 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME hdr for chunked DIME is in buffer\n"));
1219 soap
->count
+= soap
->dime
.buflen
- soap
->buflen
;
1220 soap
->buflen
= soap
->dime
.buflen
;
1221 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Skip padding (%ld bytes)\n", -(long)soap
->dime
.size
&3));
1222 for (i
= -(long)soap
->dime
.size
&3; i
> 0; i
--)
1224 if (soap
->bufidx
>= soap
->buflen
)
1225 if (soap_recv_raw(soap
))
1228 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME hdr for next chunk\n"));
1230 for (i
= 12; i
> 0; i
--)
1231 { *s
++ = soap
->buf
[soap
->bufidx
++];
1232 if (soap
->bufidx
>= soap
->buflen
)
1233 if (soap_recv_raw(soap
))
1236 soap
->dime
.flags
= tmp
[0] & 0x7;
1237 soap
->dime
.size
= ((size_t)tmp
[8] << 24) | ((size_t)tmp
[9] << 16) | ((size_t)tmp
[10] << 8) | ((size_t)tmp
[11]);
1238 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME chunk (%u bytes)\n", (unsigned int)soap
->dime
.size
));
1239 if (soap
->dime
.flags
& SOAP_DIME_CF
)
1240 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "More chunking\n"));
1241 soap
->dime
.chunksize
= soap
->dime
.size
;
1242 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.size
)
1243 { soap
->dime
.buflen
= soap
->buflen
;
1244 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
1247 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
1250 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Last chunk\n"));
1251 soap
->dime
.buflen
= 0;
1252 soap
->dime
.chunksize
= 0;
1254 soap
->count
= soap
->buflen
- soap
->bufidx
;
1255 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%u bytes remaining\n", (unsigned int)soap
->count
));
1258 if (soap
->dime
.chunksize
)
1259 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap
->dime
.chunksize
));
1260 if (soap_recv_raw(soap
))
1262 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.chunksize
)
1263 { soap
->dime
.buflen
= soap
->buflen
;
1264 soap
->count
-= soap
->buflen
- soap
->bufidx
- soap
->dime
.chunksize
;
1265 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
1268 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
1269 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%lu bytes remaining, count=%u\n", (unsigned long)(soap
->buflen
-soap
->bufidx
), (unsigned int)soap
->count
));
1274 return soap_recv_raw(soap
);
1278 /******************************************************************************/
1283 soap_getchar(struct soap
*soap
)
1284 { register soap_wchar c
;
1291 return soap_get1(soap
);
1295 /******************************************************************************/
1298 const struct soap_code_map
*
1300 soap_code(const struct soap_code_map
*code_map
, const char *str
)
1301 { if (code_map
&& str
)
1302 { while (code_map
->string
)
1303 { if (!strcmp(str
, code_map
->string
)) /* case sensitive */
1312 /******************************************************************************/
1317 soap_code_int(const struct soap_code_map
*code_map
, const char *str
, long other
)
1319 { while (code_map
->string
)
1320 { if (!soap_tag_cmp(str
, code_map
->string
)) /* case insensitive */
1321 return code_map
->code
;
1329 /******************************************************************************/
1334 soap_code_str(const struct soap_code_map
*code_map
, long code
)
1337 while (code_map
->code
!= code
&& code_map
->string
)
1339 return code_map
->string
;
1343 /******************************************************************************/
1348 soap_code_bits(const struct soap_code_map
*code_map
, const char *str
)
1349 { register long bits
= 0;
1351 { while (str
&& *str
)
1352 { const struct soap_code_map
*p
;
1353 for (p
= code_map
; p
->string
; p
++)
1354 { register size_t n
= strlen(p
->string
);
1355 if (!strncmp(p
->string
, str
, n
) && soap_blank((soap_wchar
)str
[n
]))
1358 while (*str
> 0 && *str
<= 32)
1371 /******************************************************************************/
1376 soap_code_list(struct soap
*soap
, const struct soap_code_map
*code_map
, long code
)
1377 { register char *t
= soap
->tmpbuf
;
1379 { while (code_map
->string
)
1380 { if (code_map
->code
& code
)
1381 { register const char *s
= code_map
->string
;
1382 if (t
!= soap
->tmpbuf
)
1384 while (*s
&& t
< soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 1)
1386 if (t
== soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 1)
1393 return soap
->tmpbuf
;
1397 /******************************************************************************/
1400 soap_char(struct soap
*soap
)
1403 register soap_wchar c
;
1404 register char *s
= tmp
;
1405 for (i
= 0; i
< 7; i
++)
1406 { c
= soap_get1(soap
);
1407 if (c
== ';' || (int)c
== EOF
)
1413 { if (tmp
[1] == 'x' || tmp
[1] == 'X')
1414 return (soap_wchar
)soap_strtol(tmp
+ 2, NULL
, 16);
1415 return (soap_wchar
)soap_strtol(tmp
+ 1, NULL
, 10);
1417 if (!strcmp(tmp
, "lt"))
1419 if (!strcmp(tmp
, "gt"))
1421 if (!strcmp(tmp
, "amp"))
1423 if (!strcmp(tmp
, "quot"))
1425 if (!strcmp(tmp
, "apos"))
1428 return (soap_wchar
)soap_code_int(html_entity_codes
, tmp
, SOAP_UNKNOWN_CHAR
);
1430 return SOAP_UNKNOWN_CHAR
; /* use this to represent unknown code */
1435 /******************************************************************************/
1439 soap_get0(struct soap
*soap
)
1440 { if (soap
->bufidx
>= soap
->buflen
&& soap_recv(soap
))
1442 return (unsigned char)soap
->buf
[soap
->bufidx
];
1447 /******************************************************************************/
1451 soap_get1(struct soap
*soap
)
1452 { if (soap
->bufidx
>= soap
->buflen
&& soap_recv(soap
))
1454 return (unsigned char)soap
->buf
[soap
->bufidx
++];
1459 /******************************************************************************/
1464 soap_get(struct soap
*soap
)
1465 { register soap_wchar c
;
1468 { if ((int)c
!= EOF
)
1472 c
= soap_get1(soap
);
1473 while ((int)c
!= EOF
)
1476 { c
= soap_get1(soap
);
1478 { c
= soap_get0(soap
);
1482 c
= soap_get1(soap
);
1485 { soap_unget(soap
, ']');
1490 { soap_revget1(soap
);
1499 do c
= soap_get1(soap
);
1500 while (soap_blank(c
));
1501 if (c
== '!' || c
== '?' || c
== '%')
1502 { register int k
= 1;
1504 { c
= soap_get1(soap
);
1506 { do c
= soap_get1(soap
);
1507 while ((int)c
!= EOF
&& c
!= '[');
1511 c
= soap_get1(soap
);
1514 if (c
== '-' && (c
= soap_get1(soap
)) == '-')
1516 { c
= soap_get1(soap
);
1517 if (c
== '-' && (c
= soap_get1(soap
)) == '-')
1519 } while ((int)c
!= EOF
);
1523 c
= soap_get_pi(soap
);
1524 while ((int)c
!= EOF
)
1531 c
= soap_get1(soap
);
1535 c
= soap_get1(soap
);
1549 return soap_char(soap
) | 0x80000000;
1557 /******************************************************************************/
1560 soap_get_pi(struct soap
*soap
)
1562 register char *s
= buf
;
1563 register int i
= sizeof(buf
);
1564 register soap_wchar c
= soap_getchar(soap
);
1565 /* This is a quick way to parse XML PI and we could use a callback instead to
1566 * enable applications to intercept processing instructions */
1567 while ((int)c
!= EOF
&& c
!= '?')
1569 { if (soap_blank(c
))
1573 c
= soap_getchar(soap
);
1576 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "XML PI <?%s?>\n", buf
));
1577 if (!strncmp(buf
, "xml ", 4))
1578 { s
= strstr(buf
, " encoding=");
1580 { if (!soap_tag_cmp(s
+ 11, "iso-8859-1*")
1581 || !soap_tag_cmp(s
+ 11, "latin1*"))
1582 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Switching to latin1 encoding\n"));
1583 soap
->mode
|= SOAP_ENC_LATIN
;
1585 else if (!soap_tag_cmp(s
+ 11, "utf-8*"))
1586 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Switching to utf-8 encoding\n"));
1587 soap
->mode
&= ~SOAP_ENC_LATIN
;
1592 c
= soap_getchar(soap
);
1597 /******************************************************************************/
1603 soap_move(struct soap
*soap
, long n
)
1604 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Moving %ld bytes forward\n", (long)n
));
1606 if ((int)soap_getchar(soap
) == EOF
)
1613 /******************************************************************************/
1619 soap_tell(struct soap
*soap
)
1620 { return soap
->count
- soap
->buflen
+ soap
->bufidx
- (soap
->ahead
!= 0);
1625 /******************************************************************************/
1630 soap_pututf8(struct soap
*soap
, register unsigned long c
)
1632 if (c
< 0x80 && c
> 0)
1634 return soap_send_raw(soap
, tmp
, 1);
1638 { register char *t
= tmp
;
1640 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
1643 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
1646 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
1648 { if (c
< 0x04000000)
1649 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
1651 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
1652 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
1654 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
1656 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
1658 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
1660 *t
++ = (char)(0x80 | (c
& 0x3F));
1664 sprintf(tmp
, "&#%lu;", c
);
1666 return soap_send(soap
, tmp
);
1670 /******************************************************************************/
1675 soap_getutf8(struct soap
*soap
)
1676 { register soap_wchar c
, c1
, c2
, c3
, c4
;
1683 if (c
< 0x80 || (soap
->mode
& SOAP_ENC_LATIN
))
1685 c1
= soap_get1(soap
);
1687 { soap_revget1(soap
); /* doesn't look like this is UTF8 */
1692 return ((soap_wchar
)(c
& 0x1F) << 6) | c1
;
1693 c2
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1695 return ((soap_wchar
)(c
& 0x0F) << 12) | (c1
<< 6) | c2
;
1696 c3
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1698 return ((soap_wchar
)(c
& 0x07) << 18) | (c1
<< 12) | (c2
<< 6) | c3
;
1699 c4
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1701 return ((soap_wchar
)(c
& 0x03) << 24) | (c1
<< 18) | (c2
<< 12) | (c3
<< 6) | c4
;
1702 return ((soap_wchar
)(c
& 0x01) << 30) | (c1
<< 24) | (c2
<< 18) | (c3
<< 12) | (c4
<< 6) | (soap_wchar
)(soap_get1(soap
) & 0x3F);
1706 /******************************************************************************/
1711 soap_puthex(struct soap
*soap
, const unsigned char *s
, int n
)
1715 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1716 { if (!(soap
->dom
->data
= soap_s2hex(soap
, s
, NULL
, n
)))
1721 for (i
= 0; i
< n
; i
++)
1722 { register int m
= *s
++;
1723 d
[0] = (char)((m
>> 4) + (m
> 159 ? '7' : '0'));
1725 d
[1] = (char)(m
+ (m
> 9 ? '7' : '0'));
1726 if (soap_send_raw(soap
, d
, 2))
1733 /******************************************************************************/
1738 soap_gethex(struct soap
*soap
, int *n
)
1741 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1742 { soap
->dom
->data
= soap_string_in(soap
, 0, -1, -1);
1743 return (unsigned char*)soap_hex2s(soap
, soap
->dom
->data
, NULL
, 0, n
);
1750 register size_t i
, k
;
1751 if (soap_append_lab(soap
, NULL
, 0))
1753 s
= soap
->labbuf
+ soap
->labidx
;
1754 k
= soap
->lablen
- soap
->labidx
;
1755 soap
->labidx
= soap
->lablen
;
1756 for (i
= 0; i
< k
; i
++)
1757 { register char d1
, d2
;
1758 register soap_wchar c
;
1760 if (soap_isxdigit(c
))
1763 if (soap_isxdigit(c
))
1766 { soap
->error
= SOAP_TYPE
;
1772 soap_unget(soap
, c
);
1774 *n
= (int)(soap
->lablen
+ i
- k
);
1775 p
= (unsigned char*)soap_malloc(soap
, soap
->lablen
+ i
- k
);
1777 memcpy(p
, soap
->labbuf
, soap
->lablen
+ i
- k
);
1780 *s
++ = ((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0');
1784 if (soap_new_block(soap
) == NULL
)
1788 register char *s
= (char*)soap_push_block(soap
, NULL
, SOAP_BLKLEN
);
1790 { soap_end_block(soap
, NULL
);
1793 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
1794 { register char d1
, d2
;
1795 register soap_wchar c
= soap_get(soap
);
1796 if (soap_isxdigit(c
))
1799 if (soap_isxdigit(c
))
1802 { soap_end_block(soap
, NULL
);
1803 soap
->error
= SOAP_TYPE
;
1809 soap_unget(soap
, c
);
1811 *n
= (int)soap_size_block(soap
, NULL
, i
);
1812 p
= (unsigned char*)soap_save_block(soap
, NULL
, 0);
1815 *s
++ = ((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0');
1822 /******************************************************************************/
1827 soap_putbase64(struct soap
*soap
, const unsigned char *s
, int n
)
1829 register unsigned long m
;
1834 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1835 { if (!(soap
->dom
->data
= soap_s2base64(soap
, s
, NULL
, n
)))
1840 for (; n
> 2; n
-= 3, s
+= 3)
1842 m
= (m
<< 8) | s
[1];
1843 m
= (m
<< 8) | s
[2];
1844 for (i
= 4; i
> 0; m
>>= 6)
1845 d
[--i
] = soap_base64o
[m
& 0x3F];
1846 if (soap_send_raw(soap
, d
, 4))
1851 for (i
= 0; i
< n
; i
++)
1852 m
= (m
<< 8) | *s
++;
1855 for (i
++; i
> 0; m
>>= 6)
1856 d
[--i
] = soap_base64o
[m
& 0x3F];
1857 for (i
= 3; i
> n
; i
--)
1859 if (soap_send_raw(soap
, d
, 4))
1866 /******************************************************************************/
1871 soap_getbase64(struct soap
*soap
, int *n
, int malloc_flag
)
1874 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1875 { soap
->dom
->data
= soap_string_in(soap
, 0, -1, -1);
1876 return (unsigned char*)soap_base642s(soap
, soap
->dom
->data
, NULL
, 0, n
);
1882 { register size_t i
, k
;
1884 if (soap_append_lab(soap
, NULL
, 2))
1886 s
= soap
->labbuf
+ soap
->labidx
;
1887 k
= soap
->lablen
- soap
->labidx
;
1888 soap
->labidx
= 3 * (soap
->lablen
/ 3);
1892 { for (i
= 0; i
< k
- 2; i
+= 3)
1893 { register unsigned long m
= 0;
1896 { register soap_wchar c
= soap_get(soap
);
1897 if (c
== '=' || c
< 0)
1901 *s
++ = (char)((m
>> 4) & 0xFF);
1905 *s
++ = (char)((m
>> 10) & 0xFF);
1906 *s
++ = (char)((m
>> 2) & 0xFF);
1910 *n
= (int)(soap
->lablen
+ i
- k
);
1911 p
= (unsigned char*)soap_malloc(soap
, soap
->lablen
+ i
- k
);
1913 memcpy(p
, soap
->labbuf
, soap
->lablen
+ i
- k
);
1915 { while ((int)((c
= soap_get(soap
)) != EOF
) && c
!= SOAP_LT
&& c
!= SOAP_TT
)
1918 soap_unget(soap
, c
);
1922 if (c
>= 0 && c
<= 79)
1923 { register int b
= soap_base64i
[c
];
1925 { soap
->error
= SOAP_TYPE
;
1931 else if (!soap_blank(c
+ '+'))
1932 { soap
->error
= SOAP_TYPE
;
1936 *s
++ = (char)((m
>> 16) & 0xFF);
1937 *s
++ = (char)((m
>> 8) & 0xFF);
1938 *s
++ = (char)(m
& 0xFF);
1943 if (soap_new_block(soap
) == NULL
)
1947 register char *s
= (char*)soap_push_block(soap
, NULL
, 3 * SOAP_BLKLEN
); /* must be multiple of 3 */
1949 { soap_end_block(soap
, NULL
);
1952 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
1953 { register unsigned long m
= 0;
1956 { register soap_wchar c
= soap_get(soap
);
1957 if (c
== '=' || c
< 0)
1962 *s
++ = (char)((m
>> 4) & 0xFF);
1966 *s
++ = (char)((m
>> 10) & 0xFF);
1967 *s
++ = (char)((m
>> 2) & 0xFF);
1971 *n
= (int)soap_size_block(soap
, NULL
, i
);
1972 p
= (unsigned char*)soap_save_block(soap
, NULL
, 0);
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 { 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);
2004 /******************************************************************************/
2010 soap_xop_forward(struct soap
*soap
, unsigned char **ptr
, int *size
, char **id
, char **type
, char **options
)
2011 { /* Check MTOM xop:Include element (within hex/base64Binary) */
2012 /* TODO: this code to be obsoleted with new import/xop.h conventions */
2013 int body
= soap
->body
; /* should save type too? */
2014 if (!soap_peek_element(soap
))
2015 { if (!soap_element_begin_in(soap
, "xop:Include", 0, NULL
) && *soap
->href
)
2016 { if (soap_dime_forward(soap
, ptr
, size
, id
, type
, options
))
2019 if (soap
->body
&& soap_element_end_in(soap
, NULL
))
2028 /******************************************************************************/
2034 soap_dime_forward(struct soap
*soap
, unsigned char **ptr
, int *size
, char **id
, char **type
, char **options
)
2035 { struct soap_xlist
*xp
;
2043 *id
= soap_strdup(soap
, soap
->href
);
2044 xp
= (struct soap_xlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_xlist
));
2046 return soap
->error
= SOAP_EOM
;
2047 xp
->next
= soap
->xlist
;
2052 xp
->options
= options
;
2059 /******************************************************************************/
2064 soap_strdup(struct soap
*soap
, const char *s
)
2066 if (s
&& (t
= (char*)soap_malloc(soap
, strlen(s
) + 1)))
2072 /******************************************************************************/
2077 soap_wstrdup(struct soap
*soap
, const wchar_t *s
)
2078 { wchar_t *t
= NULL
;
2083 if ((t
= (wchar_t*)soap_malloc(soap
, sizeof(wchar_t)*(n
+1))))
2084 memcpy(t
, s
, sizeof(wchar_t)*(n
+1));
2090 /******************************************************************************/
2095 soap_new_block(struct soap
*soap
)
2096 { struct soap_blist
*p
;
2097 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "New block sequence (prev=%p)\n", soap
->blist
));
2098 if (!(p
= (struct soap_blist
*)SOAP_MALLOC(soap
, sizeof(struct soap_blist
))))
2099 { soap
->error
= SOAP_EOM
;
2102 p
->next
= soap
->blist
;
2110 /******************************************************************************/
2115 soap_push_block(struct soap
*soap
, struct soap_blist
*b
, size_t n
)
2119 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n
, (unsigned int)b
->size
+ (unsigned int)n
));
2120 if (!(p
= (char*)SOAP_MALLOC(soap
, n
+ sizeof(char*) + sizeof(size_t))))
2121 { soap
->error
= SOAP_EOM
;
2124 *(char**)p
= b
->ptr
;
2125 *(size_t*)(p
+ sizeof(char*)) = n
;
2128 return p
+ sizeof(char*) + sizeof(size_t);
2132 /******************************************************************************/
2137 soap_pop_block(struct soap
*soap
, struct soap_blist
*b
)
2143 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Pop block\n"));
2145 b
->size
-= *(size_t*)(p
+ sizeof(char*));
2146 b
->ptr
= *(char**)p
;
2151 /******************************************************************************/
2152 #ifndef WITH_NOIDREF
2155 soap_update_ptrs(struct soap
*soap
, char *start
, char *end
, char *p1
, char *p2
)
2157 register struct soap_ilist
*ip
= NULL
;
2158 register struct soap_flist
*fp
= NULL
;
2160 register struct soap_xlist
*xp
= NULL
;
2162 register void *p
, **q
;
2163 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2164 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2165 { if (ip
->ptr
&& (char*)ip
->ptr
>= start
&& (char*)ip
->ptr
< end
)
2166 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Update id='%s' %p -> %p\n", ip
->id
, ip
->ptr
, (char*)ip
->ptr
+ (p1
-p2
)));
2167 ip
->ptr
= (char*)ip
->ptr
+ (p1
-p2
);
2169 for (q
= &ip
->link
; q
; q
= (void**)p
)
2171 if (p
&& (char*)p
>= start
&& (char*)p
< end
)
2172 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Link update id='%s' %p\n", ip
->id
, p
));
2173 *q
= (char*)p
+ (p1
-p2
);
2176 for (q
= &ip
->copy
; q
; q
= (void**)p
)
2178 if (p
&& (char*)p
>= start
&& (char*)p
< end
)
2179 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy chain update id='%s' %p\n", ip
->id
, p
));
2180 *q
= (char*)p
+ (p1
-p2
);
2183 for (fp
= ip
->flist
; fp
; fp
= fp
->next
)
2184 { if ((char*)fp
->ptr
>= start
&& (char*)fp
->ptr
< end
)
2185 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy list update id='%s' %p\n", ip
->id
, fp
));
2186 fp
->ptr
= (char*)fp
->ptr
+ (p1
-p2
);
2192 for (xp
= soap
->xlist
; xp
; xp
= xp
->next
)
2193 { if (xp
->ptr
&& (char*)xp
->ptr
>= start
&& (char*)xp
->ptr
< end
)
2194 { 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
)));
2195 xp
->ptr
= (unsigned char**)((char*)xp
->ptr
+ (p1
-p2
));
2196 xp
->size
= (int*)((char*)xp
->size
+ (p1
-p2
));
2197 xp
->type
= (char**)((char*)xp
->type
+ (p1
-p2
));
2198 xp
->options
= (char**)((char*)xp
->options
+ (p1
-p2
));
2206 /******************************************************************************/
2207 #ifndef WITH_NOIDREF
2210 soap_has_copies(struct soap
*soap
, register const char *start
, register const char *end
)
2212 register struct soap_ilist
*ip
= NULL
;
2213 register struct soap_flist
*fp
= NULL
;
2214 register const char *p
;
2215 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2216 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2217 { for (p
= (const char*)ip
->copy
; p
; p
= *(const char**)p
)
2218 if (p
>= start
&& p
< end
)
2220 for (fp
= ip
->flist
; fp
; fp
= fp
->next
)
2221 if ((const char*)fp
->ptr
>= start
&& (const char*)fp
->ptr
< end
)
2230 /******************************************************************************/
2231 #ifndef WITH_NOIDREF
2236 soap_resolve(struct soap
*soap
)
2238 register struct soap_ilist
*ip
= NULL
;
2239 register struct soap_flist
*fp
= NULL
;
2241 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving forwarded data\n"));
2242 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2243 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2245 { register void *p
, **q
, *r
;
2246 q
= (void**)ip
->link
;
2249 DBGLOG(TEST
, if (q
) SOAP_MESSAGE(fdebug
, "Traversing link chain to resolve id='%s'\n", ip
->id
));
2253 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "... link %p -> %p\n", q
, r
));
2257 else if (*ip
->id
== '#')
2258 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Missing data for id='%s'\n", ip
->id
));
2259 strcpy(soap
->id
, ip
->id
+ 1);
2260 return soap
->error
= SOAP_MISSING_ID
;
2266 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolution phase\n"));
2267 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2268 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2269 { if (ip
->ptr
&& !soap_has_copies(soap
, (const char*)ip
->ptr
, (const char*)ip
->ptr
+ ip
->size
))
2271 { register void *p
, **q
= (void**)ip
->copy
;
2272 DBGLOG(TEST
, if (q
) SOAP_MESSAGE(fdebug
, "Traversing copy chain to resolve id='%s'\n", ip
->id
));
2275 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "... copy %p -> %p (%u bytes)\n", ip
->ptr
, q
, (unsigned int)ip
->size
));
2277 memcpy(q
, ip
->ptr
, ip
->size
);
2282 for (fp
= ip
->flist
; fp
; fp
= ip
->flist
)
2283 { register unsigned int k
= fp
->level
;
2284 register void *p
= ip
->ptr
;
2285 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
));
2286 while (ip
->level
< k
)
2287 { register void **q
= (void**)soap_malloc(soap
, sizeof(void*));
2291 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level, new location=%p holds=%p...\n", q
, *q
));
2296 fp
->fcopy(soap
, ip
->type
, fp
->type
, fp
->ptr
, fp
->len
, p
, ip
->size
);
2298 soap_fcopy(soap
, ip
->type
, fp
->type
, fp
->ptr
, fp
->len
, p
, ip
->size
);
2299 ip
->flist
= fp
->next
;
2300 SOAP_FREE(soap
, fp
);
2308 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2309 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2310 { if (ip
->copy
|| ip
->flist
)
2311 { 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
));
2316 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolution done\n"));
2322 /******************************************************************************/
2327 soap_size_block(struct soap
*soap
, struct soap_blist
*b
, size_t n
)
2331 { b
->size
-= *(size_t*)(b
->ptr
+ sizeof(char*)) - n
;
2332 *(size_t*)(b
->ptr
+ sizeof(char*)) = n
;
2338 /******************************************************************************/
2343 soap_first_block(struct soap
*soap
, struct soap_blist
*b
)
2350 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "First block\n"));
2359 return r
+ sizeof(char*) + sizeof(size_t);
2363 /******************************************************************************/
2368 soap_next_block(struct soap
*soap
, struct soap_blist
*b
)
2374 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Next block\n"));
2375 b
->ptr
= *(char**)p
;
2378 return b
->ptr
+ sizeof(char*) + sizeof(size_t);
2384 /******************************************************************************/
2389 soap_block_size(struct soap
*soap
, struct soap_blist
*b
)
2392 return *(size_t*)(b
->ptr
+ sizeof(char*));
2396 /******************************************************************************/
2401 soap_end_block(struct soap
*soap
, struct soap_blist
*b
)
2406 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of block sequence, free all remaining blocks\n"));
2407 for (p
= b
->ptr
; p
; p
= q
)
2411 if (soap
->blist
== b
)
2412 soap
->blist
= b
->next
;
2414 { struct soap_blist
*bp
;
2415 for (bp
= soap
->blist
; bp
; bp
= bp
->next
)
2416 { if (bp
->next
== b
)
2417 { bp
->next
= b
->next
;
2424 DBGLOG(TEST
, if (soap
->blist
) SOAP_MESSAGE(fdebug
, "Restore previous block sequence\n"));
2428 /******************************************************************************/
2433 soap_save_block(struct soap
*soap
, struct soap_blist
*b
, char *p
, int flag
)
2434 { register size_t n
;
2435 register char *q
, *s
;
2438 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
));
2441 p
= (char*)soap_malloc(soap
, b
->size
);
2443 { for (s
= p
, q
= soap_first_block(soap
, b
); q
; q
= soap_next_block(soap
, b
))
2444 { n
= soap_block_size(soap
, b
);
2445 #ifndef WITH_NOIDREF
2447 soap_update_ptrs(soap
, q
, q
+ n
, s
, q
);
2449 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy %u bytes from %p to %p\n", (unsigned int)n
, q
, s
));
2455 soap
->error
= SOAP_EOM
;
2457 soap_end_block(soap
, b
);
2462 /******************************************************************************/
2467 soap_putsize(struct soap
*soap
, const char *type
, int size
)
2468 { return soap_putsizes(soap
, type
, &size
, 1);
2472 /******************************************************************************/
2477 soap_putsizes(struct soap
*soap
, const char *type
, const int *size
, int dim
)
2478 { return soap_putsizesoffsets(soap
, type
, size
, NULL
, dim
);
2482 /******************************************************************************/
2487 soap_putsizesoffsets(struct soap
*soap
, const char *type
, const int *size
, const int *offset
, int dim
)
2491 if (soap
->version
== 2)
2492 { sprintf(soap
->type
, "%s[%d", type
, size
[0]);
2493 for (i
= 1; i
< dim
; i
++)
2494 sprintf(soap
->type
+ strlen(soap
->type
), " %d", size
[i
]);
2498 { sprintf(soap
->type
, "%s[%d", type
, size
[0] + offset
[0]);
2499 for (i
= 1; i
< dim
; i
++)
2500 sprintf(soap
->type
+ strlen(soap
->type
), ",%d", size
[i
] + offset
[i
]);
2503 { sprintf(soap
->type
, "%s[%d", type
, size
[0]);
2504 for (i
= 1; i
< dim
; i
++)
2505 sprintf(soap
->type
+ strlen(soap
->type
), ",%d", size
[i
]);
2507 strcat(soap
->type
, "]");
2513 /******************************************************************************/
2518 soap_putoffset(struct soap
*soap
, int offset
)
2519 { return soap_putoffsets(soap
, &offset
, 1);
2523 /******************************************************************************/
2528 soap_putoffsets(struct soap
*soap
, const int *offset
, int dim
)
2530 sprintf(soap
->arrayOffset
, "[%d", offset
[0]);
2531 for (i
= 1; i
< dim
; i
++)
2532 sprintf(soap
->arrayOffset
+ strlen(soap
->arrayOffset
), ",%d", offset
[i
]);
2533 strcat(soap
->arrayOffset
, "]");
2534 return soap
->arrayOffset
;
2538 /******************************************************************************/
2543 soap_size(const int *size
, int dim
)
2544 { register int i
, n
= size
[0];
2545 for (i
= 1; i
< dim
; i
++)
2551 /******************************************************************************/
2556 soap_getoffsets(const char *attr
, const int *size
, int *offset
, int dim
)
2557 { register int i
, j
= 0;
2559 for (i
= 0; i
< dim
&& attr
&& *attr
; i
++)
2562 j
+= offset
[i
] = (int)soap_strtol(attr
, NULL
, 10);
2563 attr
= strchr(attr
, ',');
2566 for (i
= 0; i
< dim
&& attr
&& *attr
; i
++)
2569 j
+= (int)soap_strtol(attr
, NULL
, 10);
2570 attr
= strchr(attr
, ',');
2576 /******************************************************************************/
2581 soap_getsize(const char *attr1
, const char *attr2
, int *j
)
2582 { register int n
, k
;
2591 { k
= (int)soap_strtol(attr1
, &s
, 10);
2593 if (k
< 0 || n
> SOAP_MAXARRAYSIZE
|| s
== attr1
)
2595 attr1
= strchr(s
, ',');
2597 attr1
= strchr(s
, ' ');
2598 if (attr2
&& *attr2
)
2601 k
= (int)soap_strtol(attr2
, &s
, 10);
2615 /******************************************************************************/
2620 soap_getsizes(const char *attr
, int *size
, int dim
)
2621 { register int i
, k
, n
;
2624 i
= (int)strlen(attr
);
2627 { for (i
= i
-1; i
>= 0; i
--)
2628 if (attr
[i
] == '[' || attr
[i
] == ',' || attr
[i
] == ' ')
2630 k
= (int)soap_strtol(attr
+ i
+ 1, NULL
, 10);
2631 n
*= size
[--dim
] = k
;
2632 if (k
< 0 || n
> SOAP_MAXARRAYSIZE
)
2634 } while (i
>= 0 && attr
[i
] != '[');
2639 /******************************************************************************/
2644 soap_getposition(const char *attr
, int *pos
)
2645 { register int i
, n
;
2651 { pos
[n
++] = (int)soap_strtol(attr
+ i
, NULL
, 10);
2652 while (attr
[i
] && attr
[i
] != ',' && attr
[i
] != ']')
2656 } while (n
< SOAP_MAXDIMS
&& attr
[i
] && attr
[i
] != ']');
2661 /******************************************************************************/
2666 soap_push_namespace(struct soap
*soap
, const char *id
, const char *ns
)
2667 { register struct soap_nlist
*np
;
2668 register struct Namespace
*p
;
2669 register short i
= -1;
2670 register size_t n
, k
;
2673 p
= soap
->local_namespaces
;
2675 { for (i
= 0; p
->id
; p
++, i
++)
2676 { if (p
->ns
&& !strcmp(ns
, p
->ns
))
2678 { SOAP_FREE(soap
, p
->out
);
2684 { if (!strcmp(ns
, p
->out
))
2688 { if (!soap_tag_cmp(ns
, p
->in
))
2689 { if ((p
->out
= (char*)SOAP_MALLOC(soap
, k
)))
2700 np
= (struct soap_nlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_nlist
) + n
+ k
);
2702 { soap
->error
= SOAP_EOM
;
2705 np
->next
= soap
->nlist
;
2707 np
->level
= soap
->level
;
2710 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push namespace binding (level=%u) '%s' '%s'\n", soap
->level
, id
, ns
));
2712 { np
->ns
= strcpy(np
->id
+ n
+ 1, ns
);
2713 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns
));
2717 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push OK ('%s' matches '%s' in namespace table)\n", id
, p
->id
));
2723 /******************************************************************************/
2728 soap_pop_namespace(struct soap
*soap
)
2729 { register struct soap_nlist
*np
, *nq
;
2730 for (np
= soap
->nlist
; np
&& np
->level
>= soap
->level
; np
= nq
)
2732 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Pop namespace binding (level=%u) '%s'\n", soap
->level
, np
->id
));
2733 SOAP_FREE(soap
, np
);
2739 /******************************************************************************/
2744 soap_match_namespace(struct soap
*soap
, const char *id1
, const char *id2
, size_t n1
, size_t n2
)
2745 { register struct soap_nlist
*np
= soap
->nlist
;
2747 while (np
&& (strncmp(np
->id
, id1
, n1
) || np
->id
[n1
]))
2750 { if (!(soap
->mode
& SOAP_XML_IGNORENS
))
2752 || ((s
= soap
->local_namespaces
[np
->index
].id
) && (strncmp(s
, id2
, n2
) || (s
[n2
] && s
[n2
] != '_'))))
2753 return SOAP_NAMESPACE
;
2757 return (soap
->mode
& SOAP_XML_IGNORENS
) ? SOAP_OK
: SOAP_NAMESPACE
;
2758 if ((n1
== 3 && n1
== n2
&& !strncmp(id1
, "xml", 3) && !strncmp(id1
, id2
, 3))
2759 || (soap
->mode
& SOAP_XML_IGNORENS
))
2761 return soap
->error
= SOAP_SYNTAX_ERROR
;
2765 /******************************************************************************/
2770 soap_current_namespace(struct soap
*soap
, const char *tag
)
2771 { register struct soap_nlist
*np
;
2772 register const char *s
;
2773 if (!tag
|| !strncmp(tag
, "xml", 3))
2776 if (!(s
= strchr(tag
, ':')))
2777 { while (np
&& *np
->id
) /* find default namespace, if present */
2781 { while (np
&& (strncmp(np
->id
, tag
, s
- tag
) || np
->id
[s
- tag
]))
2784 soap
->error
= SOAP_NAMESPACE
;
2787 { if (np
->index
>= 0)
2788 return soap
->namespaces
[np
->index
].ns
;
2790 return soap_strdup(soap
, np
->ns
);
2796 /******************************************************************************/
2801 soap_tag_cmp(const char *s
, const char *t
)
2803 { register int c1
= *s
;
2804 register int c2
= *t
;
2805 if (!c1
|| c1
== '"')
2809 { if (c1
>= 'A' && c1
<= 'Z')
2811 if (c2
>= 'A' && c2
<= 'Z')
2820 if (c2
>= 'A' && c2
<= 'Z')
2824 if (!c1
|| c1
== '"')
2826 if (c1
>= 'A' && c1
<= 'Z')
2828 if (c1
== c2
&& !soap_tag_cmp(s
+ 1, t
+ 1))
2838 if (*t
== '*' && !t
[1])
2844 /******************************************************************************/
2849 soap_match_tag(struct soap
*soap
, const char *tag1
, const char *tag2
)
2850 { register const char *s
, *t
;
2852 if (!tag1
|| !tag2
|| !*tag2
)
2854 s
= strchr(tag1
, ':');
2855 t
= strchr(tag2
, ':');
2858 { if (t
[1] && SOAP_STRCMP(s
+ 1, t
+ 1))
2859 return SOAP_TAG_MISMATCH
;
2860 if (t
!= tag2
&& (err
= soap_match_namespace(soap
, tag1
, tag2
, s
- tag1
, t
- tag2
)))
2861 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags '%s' and '%s' match but namespaces differ\n", tag1
, tag2
));
2862 if (err
== SOAP_NAMESPACE
)
2863 return SOAP_TAG_MISMATCH
;
2867 else if (SOAP_STRCMP(tag1
, t
+ 1))
2868 { return SOAP_TAG_MISMATCH
;
2870 else if (t
!= tag2
&& (err
= soap_match_namespace(soap
, tag1
, tag2
, 0, t
- tag2
)))
2871 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags '%s' and '%s' match but namespaces differ\n", tag1
, tag2
));
2872 if (err
== SOAP_NAMESPACE
)
2873 return SOAP_TAG_MISMATCH
;
2876 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags and (default) namespaces match: '%s' '%s'\n", tag1
, tag2
));
2880 { if (SOAP_STRCMP(s
+ 1, tag2
))
2881 return SOAP_TAG_MISMATCH
;
2883 else if (SOAP_STRCMP(tag1
, tag2
))
2884 return SOAP_TAG_MISMATCH
;
2885 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags match: '%s' '%s'\n", tag1
, tag2
));
2890 /******************************************************************************/
2895 soap_match_array(struct soap
*soap
, const char *type
)
2896 { if (*soap
->arrayType
)
2897 if (soap_match_tag(soap
, soap
->arrayType
, type
)
2898 && soap_match_tag(soap
, soap
->arrayType
, "xsd:anyType")
2899 && soap_match_tag(soap
, soap
->arrayType
, "xsd:ur-type")
2901 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array type mismatch: '%s' '%s'\n", soap
->arrayType
, type
));
2902 return SOAP_TAG_MISMATCH
;
2908 /******************************************************************************\
2912 \******************************************************************************/
2914 /******************************************************************************/
2921 { unsigned char buf
[4];
2922 if (!soap_ssl_init_done
)
2924 RAND_pseudo_bytes(buf
, 4);
2930 /******************************************************************************/
2931 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
2936 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
)
2938 soap
->keyfile
= keyfile
;
2939 soap
->password
= password
;
2940 soap
->cafile
= cafile
;
2941 soap
->capath
= capath
;
2942 soap
->crlfile
= NULL
;
2944 soap
->dhfile
= dhfile
;
2945 soap
->randfile
= randfile
;
2947 soap
->ssl_flags
= flags
| (dhfile
== NULL
? SOAP_SSL_RSA
: 0);
2951 int n
= (int)soap_strtoul(dhfile
, &s
, 10);
2952 if (!soap
->dh_params
)
2953 gnutls_dh_params_init(&soap
->dh_params
);
2954 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
2955 if (n
>= 512 && s
&& *s
== '\0')
2956 gnutls_dh_params_generate2(soap
->dh_params
, (unsigned int)n
);
2958 { unsigned int dparams_len
;
2959 unsigned char dparams_buf
[1024];
2960 FILE *fd
= fopen(dhfile
, "r");
2962 return soap_set_receiver_error(soap
, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR
);
2963 dparams_len
= (unsigned int)fread(dparams_buf
, 1, sizeof(dparams_buf
), fd
);
2965 gnutls_datum_t dparams
= { dparams_buf
, dparams_len
};
2966 if (gnutls_dh_params_import_pkcs3(soap
->dh_params
, &dparams
, GNUTLS_X509_FMT_PEM
))
2967 return soap_set_receiver_error(soap
, "SSL/TLS error", "Invalid DH file", SOAP_SSL_ERROR
);
2971 { if (!soap
->rsa_params
)
2972 gnutls_rsa_params_init(&soap
->rsa_params
);
2973 gnutls_rsa_params_generate2(soap
->rsa_params
, SOAP_SSL_RSA_BITS
);
2976 { gnutls_deinit(soap
->session
);
2977 soap
->session
= NULL
;
2980 { gnutls_certificate_free_credentials(soap
->xcred
);
2984 err
= soap
->fsslauth(soap
);
2988 SSL_CTX_set_session_id_context(soap
->ctx
, (unsigned char*)sid
, (unsigned int)strlen(sid
));
2990 SSL_CTX_set_session_cache_mode(soap
->ctx
, SSL_SESS_CACHE_OFF
);
2998 /******************************************************************************/
2999 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3004 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
)
3005 { soap
->keyfile
= keyfile
;
3006 soap
->password
= password
;
3007 soap
->cafile
= cafile
;
3008 soap
->capath
= capath
;
3009 soap
->ssl_flags
= SOAP_SSL_CLIENT
| flags
;
3011 soap
->dhfile
= NULL
;
3012 soap
->randfile
= randfile
;
3013 soap
->fsslverify
= (flags
& SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
) == 0 ? ssl_verify_callback
: ssl_verify_callback_allow_expired_certificate
;
3017 { gnutls_deinit(soap
->session
);
3018 soap
->session
= NULL
;
3021 { gnutls_certificate_free_credentials(soap
->xcred
);
3025 return soap
->fsslauth(soap
);
3030 /******************************************************************************/
3031 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3037 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
3038 if (!soap_ssl_init_done
)
3039 { soap_ssl_init_done
= 1;
3043 SSL_load_error_strings();
3045 if (!RAND_load_file("/dev/urandom", 1024))
3047 RAND_seed(buf
, sizeof(buf
));
3048 while (!RAND_status())
3050 RAND_seed(&r
, sizeof(int));
3055 # if defined(HAVE_PTHREAD_H)
3056 gcry_control(GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pthread
);
3057 # elif defined(HAVE_PTH_H)
3058 gcry_control(GCRYCTL_SET_THREAD_CBS
, &gcry_threads_pth
);
3060 gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM
, 0);
3061 gcry_control(GCRYCTL_DISABLE_SECMEM
, 0);
3062 gcry_control(GCRYCTL_INITIALIZATION_FINISHED
, 0); /* libgcrypt init done */
3063 gnutls_global_init();
3070 /******************************************************************************/
3071 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3076 soap_ssl_error(struct soap
*soap
, int ret
)
3079 int err
= SSL_get_error(soap
->ssl
, ret
);
3080 const char *msg
= soap_code_str(h_ssl_error_codes
, err
);
3082 strcpy(soap
->msgbuf
, msg
);
3084 return ERR_error_string(err
, soap
->msgbuf
);
3085 if (ERR_peek_error())
3087 strcat(soap
->msgbuf
, "\n");
3088 while ((r
= ERR_get_error()))
3089 ERR_error_string_n(r
, soap
->msgbuf
+ strlen(soap
->msgbuf
), sizeof(soap
->msgbuf
) - strlen(soap
->msgbuf
));
3094 strcpy(soap
->msgbuf
, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
3097 sprintf(soap
->msgbuf
, "Error observed by underlying BIO: %s", strerror(errno
));
3101 return soap
->msgbuf
;
3104 return gnutls_strerror(ret
);
3110 /******************************************************************************/
3111 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3114 ssl_auth_init(struct soap
*soap
)
3119 if (!soap_ssl_init_done
)
3123 { if (!(soap
->ctx
= SSL_CTX_new(SSLv23_method())))
3124 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't setup context", SOAP_SSL_ERROR
);
3125 /* The following alters the behavior of SSL read/write: */
3127 SSL_CTX_set_mode(soap
->ctx
, SSL_MODE_ENABLE_PARTIAL_WRITE
| SSL_MODE_AUTO_RETRY
);
3131 { if (!RAND_load_file(soap
->randfile
, -1))
3132 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't load randomness", SOAP_SSL_ERROR
);
3134 if (soap
->cafile
|| soap
->capath
)
3135 { if (!SSL_CTX_load_verify_locations(soap
->ctx
, soap
->cafile
, soap
->capath
))
3136 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR
);
3137 if (soap
->cafile
&& (soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3138 SSL_CTX_set_client_CA_list(soap
->ctx
, SSL_load_client_CA_file(soap
->cafile
));
3140 if (!(soap
->ssl_flags
& SOAP_SSL_NO_DEFAULT_CA_PATH
))
3141 { if (!SSL_CTX_set_default_verify_paths(soap
->ctx
))
3142 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR
);
3144 /* This code assumes a typical scenario, see alternative code below */
3146 { if (!SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->keyfile
))
3147 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read certificate key file", SOAP_SSL_ERROR
);
3149 { SSL_CTX_set_default_passwd_cb_userdata(soap
->ctx
, (void*)soap
->password
);
3150 SSL_CTX_set_default_passwd_cb(soap
->ctx
, ssl_password
);
3152 if (!SSL_CTX_use_PrivateKey_file(soap
->ctx
, soap
->keyfile
, SSL_FILETYPE_PEM
))
3153 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR
);
3155 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
3158 { SSL_CTX_set_default_passwd_cb_userdata(soap
->ctx
, (void*)soap
->password
);
3159 SSL_CTX_set_default_passwd_cb(soap
->ctx
, ssl_password
);
3161 if (!soap
->cafile
|| !SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->cafile
))
3162 { if (soap
->keyfile
)
3163 { if (!SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->keyfile
))
3164 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read certificate or key file", SOAP_SSL_ERROR
);
3165 if (!SSL_CTX_use_PrivateKey_file(soap
->ctx
, soap
->keyfile
, SSL_FILETYPE_PEM
))
3166 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR
);
3170 if ((soap
->ssl_flags
& SOAP_SSL_RSA
))
3171 { RSA
*rsa
= RSA_generate_key(SOAP_SSL_RSA_BITS
, RSA_F4
, NULL
, NULL
);
3172 if (!SSL_CTX_set_tmp_rsa(soap
->ctx
, rsa
))
3175 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't set RSA key", SOAP_SSL_ERROR
);
3179 else if (soap
->dhfile
)
3182 int n
= (int)soap_strtoul(soap
->dhfile
, &s
, 10);
3183 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3184 if (n
>= 512 && s
&& *s
== '\0')
3185 dh
= DH_generate_parameters(n
, 2/*or 5*/, NULL
, NULL
);
3188 bio
= BIO_new_file(soap
->dhfile
, "r");
3190 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read DH file", SOAP_SSL_ERROR
);
3191 dh
= PEM_read_bio_DHparams(bio
, NULL
, NULL
, NULL
);
3194 if (!dh
|| DH_check(dh
, &n
) != 1 || SSL_CTX_set_tmp_dh(soap
->ctx
, dh
) < 0)
3197 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't set DH parameters", SOAP_SSL_ERROR
);
3201 flags
= (SSL_OP_ALL
| SSL_OP_NO_SSLv2
);
3202 if ((soap
->ssl_flags
& SOAP_SSLv3
))
3203 flags
|= SSL_OP_NO_TLSv1
;
3204 if ((soap
->ssl_flags
& SOAP_TLSv1
))
3205 flags
|= SSL_OP_NO_SSLv3
;
3206 #ifdef SSL_OP_NO_TICKET
3207 /* TLS extension is enabled by default in OPENSSL v0.9.8k
3208 Disable it by adding SSL_OP_NO_TICKET */
3209 flags
|= SSL_OP_NO_TICKET
;
3211 SSL_CTX_set_options(soap
->ctx
, flags
);
3212 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3213 mode
= (SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
);
3214 else if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
3215 mode
= SSL_VERIFY_PEER
;
3217 mode
= SSL_VERIFY_NONE
;
3218 SSL_CTX_set_verify(soap
->ctx
, mode
, soap
->fsslverify
);
3219 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
3220 SSL_CTX_set_verify_depth(soap
->ctx
, 1);
3222 SSL_CTX_set_verify_depth(soap
->ctx
, 9);
3227 if (!soap_ssl_init_done
)
3230 { gnutls_certificate_allocate_credentials(&soap
->xcred
);
3232 { if (gnutls_certificate_set_x509_trust_file(soap
->xcred
, soap
->cafile
, GNUTLS_X509_FMT_PEM
) < 0)
3233 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read CA file", SOAP_SSL_ERROR
);
3236 { if (gnutls_certificate_set_x509_crl_file(soap
->xcred
, soap
->crlfile
, GNUTLS_X509_FMT_PEM
) < 0)
3237 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read CRL file", SOAP_SSL_ERROR
);
3240 { 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 */
3241 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR
);
3244 if ((soap
->ssl_flags
& SOAP_SSL_CLIENT
))
3245 { gnutls_init(&soap
->session
, GNUTLS_CLIENT
);
3246 if (soap
->cafile
|| soap
->crlfile
|| soap
->keyfile
)
3247 { ret
= gnutls_priority_set_direct(soap
->session
, "PERFORMANCE", NULL
);
3249 return soap_set_receiver_error(soap
, soap_ssl_error(soap
, ret
), "SSL/TLS set priority error", SOAP_SSL_ERROR
);
3250 gnutls_credentials_set(soap
->session
, GNUTLS_CRD_CERTIFICATE
, soap
->xcred
);
3254 gnutls_anon_allocate_client_credentials(&soap
->acred
);
3255 gnutls_init(&soap
->session
, GNUTLS_CLIENT
);
3256 gnutls_priority_set_direct(soap
->session
, "PERFORMANCE:+ANON-DH:!ARCFOUR-128", NULL
);
3257 gnutls_credentials_set(soap
->session
, GNUTLS_CRD_ANON
, soap
->acred
);
3261 { if (!soap
->keyfile
)
3262 return soap_set_receiver_error(soap
, "SSL/TLS error", "No key file: anonymous server authentication not supported in this release", SOAP_SSL_ERROR
);
3263 if ((soap
->ssl_flags
& SOAP_SSL_RSA
) && soap
->rsa_params
)
3264 gnutls_certificate_set_rsa_export_params(soap
->xcred
, soap
->rsa_params
);
3265 else if (soap
->dh_params
)
3266 gnutls_certificate_set_dh_params(soap
->xcred
, soap
->dh_params
);
3268 gnutls_priority_init(&soap
->cache
, "NORMAL", NULL
);
3269 gnutls_init(&soap
->session
, GNUTLS_SERVER
);
3270 gnutls_priority_set(soap
->session
, soap
->cache
);
3271 gnutls_credentials_set(soap
->session
, GNUTLS_CRD_CERTIFICATE
, soap
->xcred
);
3272 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3273 gnutls_certificate_server_set_request(soap
->session
, GNUTLS_CERT_REQUEST
);
3274 gnutls_session_enable_compatibility_mode(soap
->session
);
3275 if ((soap
->ssl_flags
& SOAP_TLSv1
))
3276 { int protocol_priority
[] = { GNUTLS_TLS1_0
, 0 };
3277 if (gnutls_protocol_set_priority(soap
->session
, protocol_priority
) != GNUTLS_E_SUCCESS
)
3278 return soap_set_receiver_error(soap
, "SSL/TLS error", "Can't set TLS v1.0 protocol", SOAP_SSL_ERROR
);
3287 /******************************************************************************/
3291 ssl_password(char *buf
, int num
, int rwflag
, void *userdata
)
3292 { if (num
< (int)strlen((char*)userdata
) + 1)
3294 return (int)strlen(strcpy(buf
, (char*)userdata
));
3299 /******************************************************************************/
3303 ssl_verify_callback(int ok
, X509_STORE_CTX
*store
)
3308 X509
*cert
= X509_STORE_CTX_get_current_cert(store
);
3309 fprintf(stderr
, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store
), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store
)));
3310 X509_NAME_oneline(X509_get_issuer_name(cert
), data
, sizeof(data
));
3311 fprintf(stderr
, "certificate issuer %s\n", data
);
3312 X509_NAME_oneline(X509_get_subject_name(cert
), data
, sizeof(data
));
3313 fprintf(stderr
, "certificate subject %s\n", data
);
3316 /* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */
3322 /******************************************************************************/
3326 ssl_verify_callback_allow_expired_certificate(int ok
, X509_STORE_CTX
*store
)
3327 { ok
= ssl_verify_callback(ok
, store
);
3328 if (ok
== 0 && X509_STORE_CTX_get_error(store
) == X509_V_ERR_CERT_HAS_EXPIRED
)
3331 fprintf(stderr
, "ignoring certificate expiration\n");
3333 X509_STORE_CTX_set_error(store
, X509_V_OK
);
3336 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3342 /******************************************************************************/
3345 ssl_verify(struct soap
*soap
, const char *host
)
3346 { unsigned int status
;
3347 const char *err
= NULL
;
3348 int r
= gnutls_certificate_verify_peers2(soap
->session
, &status
);
3350 err
= "Certificate verify error";
3351 else if ((status
& GNUTLS_CERT_INVALID
))
3352 err
= "The certificate is not trusted";
3353 else if ((status
& GNUTLS_CERT_SIGNER_NOT_FOUND
))
3354 err
= "The certificate hasn't got a known issuer";
3355 else if ((status
& GNUTLS_CERT_REVOKED
))
3356 err
= "The certificate has been revoked";
3357 else if (gnutls_certificate_type_get(soap
->session
) == GNUTLS_CRT_X509
)
3358 { gnutls_x509_crt_t cert
;
3359 const gnutls_datum_t
*cert_list
;
3360 unsigned int cert_list_size
;
3361 if (gnutls_x509_crt_init(&cert
) < 0)
3362 err
= "Could not get X509 certificates";
3363 else if ((cert_list
= gnutls_certificate_get_peers(soap
->session
, &cert_list_size
)) == NULL
)
3364 err
= "Could not get X509 certificates";
3365 else if (gnutls_x509_crt_import(cert
, &cert_list
[0], GNUTLS_X509_FMT_DER
) < 0)
3366 err
= "Error parsing X509 certificate";
3367 else if (!(soap
->ssl_flags
& SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
) && gnutls_x509_crt_get_expiration_time(cert
) < time(NULL
))
3368 err
= "The certificate has expired";
3369 else if (!(soap
->ssl_flags
& SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
) && gnutls_x509_crt_get_activation_time(cert
) > time(NULL
))
3370 err
= "The certificate is not yet activated";
3371 else if (host
&& !(soap
->ssl_flags
& SOAP_SSL_SKIP_HOST_CHECK
))
3372 { if (!gnutls_x509_crt_check_hostname(cert
, host
))
3373 err
= "Certificate host name mismatch";
3375 gnutls_x509_crt_deinit(cert
);
3381 /******************************************************************************/
3382 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3388 soap_ssl_accept(struct soap
*soap
)
3389 { SOAP_SOCKET fd
= soap
->socket
;
3393 if (!soap_valid_socket(fd
))
3394 return soap_set_receiver_error(soap
, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR
);
3395 soap
->ssl_flags
&= ~SOAP_SSL_CLIENT
;
3396 if (!soap
->ctx
&& (soap
->error
= soap
->fsslauth(soap
)))
3399 { soap
->ssl
= SSL_new(soap
->ctx
);
3401 return soap_set_receiver_error(soap
, "SSL/TLS error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR
);
3404 SSL_clear(soap
->ssl
);
3405 bio
= BIO_new_socket((int)fd
, BIO_NOCLOSE
);
3406 SSL_set_bio(soap
->ssl
, bio
, bio
);
3407 /* Set SSL sockets to non-blocking */
3409 if (soap
->accept_timeout
)
3410 { SOAP_SOCKNONBLOCK(fd
)
3411 retries
= 10*soap
->accept_timeout
;
3414 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
3415 while ((r
= SSL_accept(soap
->ssl
)) <= 0)
3419 err
= SSL_get_error(soap
->ssl
, r
);
3420 if (err
== SSL_ERROR_WANT_ACCEPT
|| err
== SSL_ERROR_WANT_READ
|| err
== SSL_ERROR_WANT_WRITE
)
3421 { if (err
== SSL_ERROR_WANT_READ
)
3422 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
3424 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
3425 if (s
< 0 && soap
->errnum
!= SOAP_EINTR
)
3429 { soap
->errnum
= soap_socket_errno(fd
);
3434 { soap_set_receiver_error(soap
, soap_ssl_error(soap
, r
), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR
);
3435 soap_closesock(soap
);
3436 return SOAP_SSL_ERROR
;
3438 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3441 if ((err
= SSL_get_verify_result(soap
->ssl
)) != X509_V_OK
)
3442 { soap_closesock(soap
);
3443 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
);
3445 peer
= SSL_get_peer_certificate(soap
->ssl
);
3447 { soap_closesock(soap
);
3448 return soap_set_sender_error(soap
, "SSL/TLS error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR
);
3455 if (!soap_valid_socket(fd
))
3456 return soap_set_receiver_error(soap
, "SSL/TLS error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR
);
3457 soap
->ssl_flags
&= ~SOAP_SSL_CLIENT
;
3458 if (!soap
->session
&& (soap
->error
= soap
->fsslauth(soap
)))
3459 { soap_closesock(soap
);
3462 gnutls_transport_set_ptr(soap
->session
, (gnutls_transport_ptr_t
)(long)fd
);
3463 /* Set SSL sockets to non-blocking */
3464 if (soap
->accept_timeout
)
3465 { SOAP_SOCKNONBLOCK(fd
)
3466 retries
= 10*soap
->accept_timeout
;
3469 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
3470 while ((r
= gnutls_handshake(soap
->session
)))
3472 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
3475 if (r
== GNUTLS_E_AGAIN
|| r
== GNUTLS_E_INTERRUPTED
)
3476 { if (!gnutls_record_get_direction(soap
->session
))
3477 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
3479 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
3480 if (s
< 0 && soap
->errnum
!= SOAP_EINTR
)
3484 { soap
->errnum
= soap_socket_errno(fd
);
3489 { soap_closesock(soap
);
3490 return soap_set_receiver_error(soap
, soap_ssl_error(soap
, r
), "SSL/TLS handshake failed", SOAP_SSL_ERROR
);
3492 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3493 { const char *err
= ssl_verify(soap
, NULL
);
3495 { soap_closesock(soap
);
3496 return soap_set_receiver_error(soap
, "SSL/TLS error", err
, SOAP_SSL_ERROR
);
3500 if (soap
->recv_timeout
|| soap
->send_timeout
)
3501 SOAP_SOCKNONBLOCK(fd
)
3504 soap
->imode
|= SOAP_ENC_SSL
;
3505 soap
->omode
|= SOAP_ENC_SSL
;
3512 /******************************************************************************\
3514 * TCP/UDP [SSL/TLS] IPv4 and IPv6
3516 \******************************************************************************/
3518 /******************************************************************************/
3522 tcp_init(struct soap
*soap
)
3523 { soap
->errmode
= 1;
3529 if (WSAStartup(MAKEWORD(1, 1), &w
))
3539 /******************************************************************************/
3543 tcp_error(struct soap
*soap
)
3544 { register const char *msg
= NULL
;
3545 switch (soap
->errmode
)
3547 msg
= soap_strerror(soap
);
3550 msg
= "WSAStartup failed";
3555 msg
= soap_code_str(h_error_codes
, soap
->errnum
);
3558 { sprintf(soap
->msgbuf
, "TCP/UDP IP error %d", soap
->errnum
);
3568 /******************************************************************************/
3573 tcp_gethost(struct soap
*soap
, const char *addr
, struct in_addr
*inaddr
)
3574 { soap_int32 iadd
= -1;
3575 struct hostent hostent
, *host
= &hostent
;
3578 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3579 iadd
= inet_addr((char*)addr
);
3581 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3582 struct hostent_data ht_data
;
3585 iadd
= inet_addr((void*)addr
);
3587 iadd
= inet_addr(addr
);
3591 { memcpy(inaddr
, &iadd
, sizeof(iadd
));
3594 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
3595 if (gethostbyname_r(addr
, &hostent
, soap
->buf
, SOAP_BUFLEN
, &host
, &soap
->errnum
) < 0)
3597 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3598 memset((void*)&ht_data
, 0, sizeof(ht_data
));
3599 if (gethostbyname_r(addr
, &hostent
, &ht_data
) < 0)
3601 soap
->errnum
= h_errno
;
3603 #elif defined(HAVE_GETHOSTBYNAME_R)
3604 host
= gethostbyname_r(addr
, &hostent
, soap
->buf
, SOAP_BUFLEN
, &soap
->errnum
);
3605 #elif defined(VXWORKS)
3606 /* If the DNS resolver library resolvLib has been configured in the vxWorks
3607 * image, a query for the host IP address is sent to the DNS server, if the
3608 * name was not found in the local host table. */
3609 hostint
= hostGetByName((char*)addr
);
3610 if (hostint
== ERROR
)
3612 soap
->errnum
= soap_errno
;
3616 if (!(host
= gethostbyname((void*)addr
)))
3617 soap
->errnum
= h_errno
;
3619 if (!(host
= gethostbyname(addr
)))
3620 soap
->errnum
= h_errno
;
3624 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Host name not found\n"));
3628 inaddr
->s_addr
= hostint
;
3630 memcpy(inaddr
, host
->h_addr
, host
->h_length
);
3638 /******************************************************************************/
3642 tcp_connect(struct soap
*soap
, const char *endpoint
, const char *host
, int port
)
3645 struct addrinfo hints
, *res
, *ressave
;
3651 int len
= SOAP_BUFLEN
;
3653 int len
= SOAP_BUFLEN
+ 1; /* speeds up windows xfer */
3657 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3660 if (soap_valid_socket(soap
->socket
))
3661 soap
->fclosesocket(soap
, soap
->socket
);
3662 soap
->socket
= SOAP_INVALID_SOCKET
;
3665 soap_set_sender_error(soap
, tcp_error(soap
), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR
);
3666 return SOAP_INVALID_SOCKET
;
3670 memset((void*)&hints
, 0, sizeof(hints
));
3671 hints
.ai_family
= PF_UNSPEC
;
3673 if ((soap
->omode
& SOAP_IO_UDP
))
3674 hints
.ai_socktype
= SOCK_DGRAM
;
3677 hints
.ai_socktype
= SOCK_STREAM
;
3679 if (soap
->proxy_host
)
3680 err
= getaddrinfo(soap
->proxy_host
, soap_int2s(soap
, soap
->proxy_port
), &hints
, &res
);
3682 err
= getaddrinfo(host
, soap_int2s(soap
, port
), &hints
, &res
);
3684 { soap_set_sender_error(soap
, SOAP_GAI_STRERROR(err
), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR
);
3685 return SOAP_INVALID_SOCKET
;
3689 fd
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
3696 if ((soap
->omode
& SOAP_IO_UDP
))
3697 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
3700 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
3702 if (!soap_valid_socket(fd
))
3706 { res
= res
->ai_next
;
3710 soap
->errnum
= soap_socket_errno(fd
);
3711 soap_set_sender_error(soap
, tcp_error(soap
), "socket failed in tcp_connect()", SOAP_TCP_ERROR
);
3713 freeaddrinfo(ressave
);
3715 return SOAP_INVALID_SOCKET
;
3717 #ifdef SOCKET_CLOSE_ON_EXEC
3720 SetHandleInformation((HANDLE
)fd
, HANDLE_FLAG_INHERIT
, 0);
3723 fcntl(fd
, F_SETFD
, 1);
3727 if (soap
->connect_flags
== SO_LINGER
)
3728 { struct linger linger
;
3729 memset((void*)&linger
, 0, sizeof(linger
));
3731 linger
.l_linger
= soap
->linger_time
;
3732 if (setsockopt(fd
, SOL_SOCKET
, SO_LINGER
, (char*)&linger
, sizeof(struct linger
)))
3733 { soap
->errnum
= soap_socket_errno(fd
);
3734 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR
);
3735 soap
->fclosesocket(soap
, fd
);
3737 freeaddrinfo(ressave
);
3739 return SOAP_INVALID_SOCKET
;
3742 else if (soap
->connect_flags
&& setsockopt(fd
, SOL_SOCKET
, soap
->connect_flags
, (char*)&set
, sizeof(int)))
3743 { soap
->errnum
= soap_socket_errno(fd
);
3744 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR
);
3745 soap
->fclosesocket(soap
, fd
);
3747 freeaddrinfo(ressave
);
3749 return SOAP_INVALID_SOCKET
;
3751 if ((soap
->keep_alive
|| soap
->tcp_keep_alive
) && setsockopt(fd
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
3752 { soap
->errnum
= soap_socket_errno(fd
);
3753 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR
);
3754 soap
->fclosesocket(soap
, fd
);
3756 freeaddrinfo(ressave
);
3758 return SOAP_INVALID_SOCKET
;
3760 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
3761 { soap
->errnum
= soap_socket_errno(fd
);
3762 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR
);
3763 soap
->fclosesocket(soap
, fd
);
3765 freeaddrinfo(ressave
);
3767 return SOAP_INVALID_SOCKET
;
3769 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
3770 { soap
->errnum
= soap_socket_errno(fd
);
3771 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR
);
3772 soap
->fclosesocket(soap
, fd
);
3774 freeaddrinfo(ressave
);
3776 return SOAP_INVALID_SOCKET
;
3779 if (soap
->tcp_keep_idle
&& setsockopt((SOAP_SOCKET
)fd
, IPPROTO_TCP
, TCP_KEEPIDLE
, (char*)&(soap
->tcp_keep_idle
), sizeof(int)))
3780 { soap
->errnum
= soap_socket_errno(fd
);
3781 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR
);
3782 soap
->fclosesocket(soap
, (SOAP_SOCKET
)fd
);
3784 freeaddrinfo(ressave
);
3786 return SOAP_INVALID_SOCKET
;
3789 #ifdef TCP_KEEPINTVL
3790 if (soap
->tcp_keep_intvl
&& setsockopt((SOAP_SOCKET
)fd
, IPPROTO_TCP
, TCP_KEEPINTVL
, (char*)&(soap
->tcp_keep_intvl
), sizeof(int)))
3791 { soap
->errnum
= soap_socket_errno(fd
);
3792 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR
);
3793 soap
->fclosesocket(soap
, (SOAP_SOCKET
)fd
);
3795 freeaddrinfo(ressave
);
3797 return SOAP_INVALID_SOCKET
;
3801 if (soap
->tcp_keep_cnt
&& setsockopt((SOAP_SOCKET
)fd
, IPPROTO_TCP
, TCP_KEEPCNT
, (char*)&(soap
->tcp_keep_cnt
), sizeof(int)))
3802 { soap
->errnum
= soap_socket_errno(fd
);
3803 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR
);
3804 soap
->fclosesocket(soap
, (SOAP_SOCKET
)fd
);
3806 freeaddrinfo(ressave
);
3808 return SOAP_INVALID_SOCKET
;
3812 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
3813 { soap
->errnum
= soap_socket_errno(fd
);
3814 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR
);
3815 soap
->fclosesocket(soap
, fd
);
3817 freeaddrinfo(ressave
);
3819 return SOAP_INVALID_SOCKET
;
3823 if ((soap
->omode
& SOAP_IO_UDP
) && soap
->ipv6_multicast_if
)
3824 { struct sockaddr_in6
*in6addr
= (struct sockaddr_in6
*)res
->ai_addr
;
3825 in6addr
->sin6_scope_id
= soap
->ipv6_multicast_if
;
3828 #ifdef IP_MULTICAST_TTL
3829 if ((soap
->omode
& SOAP_IO_UDP
) && soap
->ipv4_multicast_if
&& !soap
->ipv6_multicast_if
)
3830 { if (soap
->ipv4_multicast_ttl
> 0)
3831 { char ttl
= (char)(soap
->ipv4_multicast_ttl
);
3832 if (setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_TTL
, (char*)&ttl
, sizeof(ttl
)))
3833 { soap
->errnum
= soap_socket_errno(fd
);
3834 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR
);
3835 soap
->fclosesocket(soap
, fd
);
3836 return SOAP_INVALID_SOCKET
;
3840 if (setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_IF
, (char*)soap
->ipv4_multicast_if
, sizeof(struct in_addr
)))
3841 { soap
->errnum
= soap_socket_errno(fd
);
3842 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR
);
3843 soap
->fclosesocket(soap
, fd
);
3844 return SOAP_INVALID_SOCKET
;
3847 #ifndef IP_MULTICAST_IF
3848 #define IP_MULTICAST_IF 2
3850 if (setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_IF
, (char*)soap
->ipv4_multicast_if
, sizeof(struct in_addr
)))
3851 { soap
->errnum
= soap_socket_errno(fd
);
3852 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR
);
3853 soap
->fclosesocket(soap
, fd
);
3854 return SOAP_INVALID_SOCKET
;
3860 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Opening socket %d to host='%s' port=%d\n", fd
, host
, port
));
3862 soap
->peerlen
= sizeof(soap
->peer
);
3863 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
3864 soap
->peer
.sin_family
= AF_INET
;
3866 if (soap
->proxy_host
)
3867 { if (soap
->fresolve(soap
, soap
->proxy_host
, &soap
->peer
.sin_addr
))
3868 { soap_set_sender_error(soap
, tcp_error(soap
), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR
);
3869 soap
->fclosesocket(soap
, fd
);
3870 return SOAP_INVALID_SOCKET
;
3872 soap
->peer
.sin_port
= htons((short)soap
->proxy_port
);
3875 { if (soap
->fresolve(soap
, host
, &soap
->peer
.sin_addr
))
3876 { soap_set_sender_error(soap
, tcp_error(soap
), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR
);
3877 soap
->fclosesocket(soap
, fd
);
3878 return SOAP_INVALID_SOCKET
;
3880 soap
->peer
.sin_port
= htons((short)port
);
3884 if ((soap
->omode
& SOAP_IO_UDP
))
3888 if ((soap
->omode
& SOAP_IO_UDP
))
3889 { memcpy(&soap
->peer
, res
->ai_addr
, res
->ai_addrlen
);
3890 soap
->peerlen
= res
->ai_addrlen
;
3891 freeaddrinfo(ressave
);
3896 if (soap
->connect_timeout
)
3897 SOAP_SOCKNONBLOCK(fd
)
3905 if (connect(fd
, res
->ai_addr
, (int)res
->ai_addrlen
))
3907 if (connect(fd
, (struct sockaddr
*)&soap
->peer
, sizeof(soap
->peer
)))
3909 { err
= soap_socket_errno(fd
);
3911 if (err
== SOAP_EADDRINUSE
)
3912 { soap
->fclosesocket(soap
, fd
);
3916 else if (soap
->connect_timeout
&& (err
== SOAP_EINPROGRESS
|| err
== SOAP_EAGAIN
|| err
== SOAP_EWOULDBLOCK
))
3921 r
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_SND
, soap
->connect_timeout
);
3925 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connect timeout\n"));
3926 soap_set_sender_error(soap
, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3927 soap
->fclosesocket(soap
, fd
);
3929 freeaddrinfo(ressave
);
3931 return SOAP_INVALID_SOCKET
;
3934 if (r
!= SOAP_EINTR
)
3935 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
3936 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3937 soap
->fclosesocket(soap
, fd
);
3939 freeaddrinfo(ressave
);
3941 return SOAP_INVALID_SOCKET
;
3944 k
= (SOAP_SOCKLEN_T
)sizeof(soap
->errnum
);
3945 if (!getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, (char*)&soap
->errnum
, &k
) && !soap
->errnum
) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
3947 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
3949 soap
->errnum
= soap_socket_errno(fd
);
3950 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3951 soap
->fclosesocket(soap
, fd
);
3953 freeaddrinfo(ressave
);
3955 return SOAP_INVALID_SOCKET
;
3960 { res
= res
->ai_next
;
3961 soap
->fclosesocket(soap
, fd
);
3965 if (err
&& err
!= SOAP_EINTR
)
3966 { soap
->errnum
= err
;
3967 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
3968 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3969 soap
->fclosesocket(soap
, fd
);
3971 freeaddrinfo(ressave
);
3973 return SOAP_INVALID_SOCKET
;
3980 soap
->peerlen
= 0; /* IPv6: already connected so use send() */
3981 freeaddrinfo(ressave
);
3984 soap
->imode
&= ~SOAP_ENC_SSL
;
3985 soap
->omode
&= ~SOAP_ENC_SSL
;
3986 if (!soap_tag_cmp(endpoint
, "https:*"))
3988 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
3993 if (soap
->proxy_host
)
3994 { soap_mode m
= soap
->mode
; /* preserve settings */
3995 soap_mode om
= soap
->omode
; /* make sure we only parse HTTP */
3996 size_t n
= soap
->count
; /* save the content length */
3997 const char *userid
, *passwd
;
3998 soap
->omode
&= ~SOAP_ENC
; /* mask IO and ENC */
3999 soap
->omode
|= SOAP_IO_BUFFER
;
4000 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connecting to %s proxy server\n", soap
->proxy_http_version
));
4001 sprintf(soap
->tmpbuf
, "CONNECT %s:%d HTTP/%s", host
, port
, soap
->proxy_http_version
);
4002 if (soap_begin_send(soap
)
4003 || (soap
->error
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
4004 { soap
->fclosesocket(soap
, fd
);
4005 return SOAP_INVALID_SOCKET
;
4008 if (soap
->proxy_userid
&& soap
->proxy_passwd
&& strlen(soap
->proxy_userid
) + strlen(soap
->proxy_passwd
) < 761)
4009 { sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->proxy_userid
, soap
->proxy_passwd
);
4010 strcpy(soap
->tmpbuf
, "Basic ");
4011 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
4012 if ((soap
->error
= soap
->fposthdr(soap
, "Proxy-Authorization", soap
->tmpbuf
)))
4013 { soap
->fclosesocket(soap
, fd
);
4018 if ((soap
->error
= soap
->fposthdr(soap
, NULL
, NULL
))
4019 || soap_flush(soap
))
4020 { soap
->fclosesocket(soap
, fd
);
4021 return SOAP_INVALID_SOCKET
;
4025 soap
->imode
&= ~SOAP_ENC
; /* mask IO and ENC */
4026 userid
= soap
->userid
; /* preserve */
4027 passwd
= soap
->passwd
; /* preserve */
4028 if ((soap
->error
= soap
->fparse(soap
)))
4029 { soap
->fclosesocket(soap
, fd
);
4030 return SOAP_INVALID_SOCKET
;
4032 soap
->userid
= userid
; /* restore */
4033 soap
->passwd
= passwd
; /* restore */
4034 soap
->imode
= om
; /* restore */
4035 soap
->count
= n
; /* restore */
4036 if (soap_begin_send(soap
))
4037 { soap
->fclosesocket(soap
, fd
);
4038 return SOAP_INVALID_SOCKET
;
4041 strncpy(soap
->endpoint
, endpoint
, sizeof(soap
->endpoint
)-1); /* restore */
4045 soap
->ssl_flags
|= SOAP_SSL_CLIENT
;
4046 if (!soap
->ctx
&& (soap
->error
= soap
->fsslauth(soap
)))
4047 { soap
->fclosesocket(soap
, fd
);
4048 return SOAP_INVALID_SOCKET
;
4051 { soap
->ssl
= SSL_new(soap
->ctx
);
4053 { soap
->fclosesocket(soap
, fd
);
4054 soap
->error
= SOAP_SSL_ERROR
;
4055 return SOAP_INVALID_SOCKET
;
4059 SSL_clear(soap
->ssl
);
4061 { if (!strcmp(soap
->session_host
, host
) && soap
->session_port
== port
)
4062 SSL_set_session(soap
->ssl
, soap
->session
);
4063 SSL_SESSION_free(soap
->session
);
4064 soap
->session
= NULL
;
4066 soap
->imode
|= SOAP_ENC_SSL
;
4067 soap
->omode
|= SOAP_ENC_SSL
;
4068 bio
= BIO_new_socket((int)fd
, BIO_NOCLOSE
);
4069 SSL_set_bio(soap
->ssl
, bio
, bio
);
4070 /* Connect timeout: set SSL sockets to non-blocking */
4072 if (soap
->connect_timeout
)
4073 { SOAP_SOCKNONBLOCK(fd
)
4074 retries
= 10*soap
->connect_timeout
;
4079 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
4080 /* Try connecting until success or timeout (when nonblocking) */
4082 { if ((r
= SSL_connect(soap
->ssl
)) <= 0)
4083 { int err
= SSL_get_error(soap
->ssl
, r
);
4084 if (err
== SSL_ERROR_WANT_CONNECT
|| err
== SSL_ERROR_WANT_READ
|| err
== SSL_ERROR_WANT_WRITE
)
4086 if (err
== SSL_ERROR_WANT_READ
)
4087 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
4089 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
4090 if (s
< 0 && soap
->errnum
!= SOAP_EINTR
)
4091 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL_connect/select error in tcp_connect\n"));
4092 soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4093 soap
->fclosesocket(soap
, fd
);
4094 return SOAP_INVALID_SOCKET
;
4096 if (s
== 0 && retries
-- <= 0)
4097 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL/TLS connect timeout\n"));
4098 soap_set_sender_error(soap
, "Timeout", "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4099 soap
->fclosesocket(soap
, fd
);
4100 return SOAP_INVALID_SOCKET
;
4104 { soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR
);
4105 soap
->fclosesocket(soap
, fd
);
4106 return SOAP_INVALID_SOCKET
;
4109 } while (!SSL_is_init_finished(soap
->ssl
));
4110 /* Set SSL sockets to nonblocking */
4111 SOAP_SOCKNONBLOCK(fd
)
4112 /* Check server credentials when required */
4113 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
4115 if ((err
= SSL_get_verify_result(soap
->ssl
)) != X509_V_OK
)
4116 { 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
);
4117 soap
->fclosesocket(soap
, fd
);
4118 return SOAP_INVALID_SOCKET
;
4120 if (!(soap
->ssl_flags
& SOAP_SSL_SKIP_HOST_CHECK
))
4125 peer
= SSL_get_peer_certificate(soap
->ssl
);
4127 { soap_set_sender_error(soap
, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR
);
4128 soap
->fclosesocket(soap
, fd
);
4129 return SOAP_INVALID_SOCKET
;
4131 ext_count
= X509_get_ext_count(peer
);
4134 for (i
= 0; i
< ext_count
; i
++)
4135 { X509_EXTENSION
*ext
= X509_get_ext(peer
, i
);
4136 const char *ext_str
= OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext
)));
4137 if (ext_str
&& !strcmp(ext_str
, "subjectAltName"))
4138 { X509V3_EXT_METHOD
*meth
= (X509V3_EXT_METHOD
*)X509V3_EXT_get(ext
);
4140 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
4141 const unsigned char *data
;
4143 unsigned char *data
;
4145 STACK_OF(CONF_VALUE
) *val
;
4149 data
= ext
->value
->data
;
4150 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4152 ext_data
= ASN1_item_d2i(NULL
, &data
, ext
->value
->length
, ASN1_ITEM_ptr(meth
->it
));
4154 { /* OpenSSL not perfectly portable at this point (?):
4155 Some compilers appear to prefer
4156 meth->d2i(NULL, (const unsigned char**)&data, ...
4158 meth->d2i(NULL, &data, ext->value->length);
4160 ext_data
= meth
->d2i(NULL
, &data
, ext
->value
->length
);
4163 ext_data
= meth
->d2i(NULL
, &data
, ext
->value
->length
);
4166 { val
= meth
->i2v(meth
, ext_data
, NULL
);
4168 { for (j
= 0; j
< sk_CONF_VALUE_num(val
); j
++)
4169 { CONF_VALUE
*nval
= sk_CONF_VALUE_value(val
, j
);
4170 if (nval
&& !strcmp(nval
->name
, "DNS") && !strcmp(nval
->value
, host
))
4175 sk_CONF_VALUE_pop_free(val
, X509V3_conf_free
);
4177 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4179 ASN1_item_free((ASN1_VALUE
*)ext_data
, ASN1_ITEM_ptr(meth
->it
));
4181 meth
->ext_free(ext_data
);
4183 meth
->ext_free(ext_data
);
4191 if (!ok
&& (subj
= X509_get_subject_name(peer
)))
4194 { ASN1_STRING
*name
;
4195 i
= X509_NAME_get_index_by_NID(subj
, NID_commonName
, i
);
4198 name
= X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj
, i
));
4200 { if (!soap_tag_cmp(host
, (const char*)M_ASN1_STRING_data(name
)))
4203 { unsigned char *tmp
= NULL
;
4204 ASN1_STRING_to_UTF8(&tmp
, name
);
4206 { if (!soap_tag_cmp(host
, (const char*)tmp
))
4216 { soap_set_sender_error(soap
, "SSL/TLS error", "SSL/TLS certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR
);
4217 soap
->fclosesocket(soap
, fd
);
4218 return SOAP_INVALID_SOCKET
;
4224 soap
->ssl_flags
|= SOAP_SSL_CLIENT
;
4225 if (!soap
->session
&& (soap
->error
= soap
->fsslauth(soap
)))
4226 { soap
->fclosesocket(soap
, fd
);
4227 return SOAP_INVALID_SOCKET
;
4229 gnutls_transport_set_ptr(soap
->session
, (gnutls_transport_ptr_t
)(long)fd
);
4230 /* Set SSL sockets to non-blocking */
4231 if (soap
->connect_timeout
)
4232 { SOAP_SOCKNONBLOCK(fd
)
4233 retries
= 10*soap
->connect_timeout
;
4238 retries
= 100; /* timeout: 10 sec retries, 100 times 0.1 sec */
4239 while ((r
= gnutls_handshake(soap
->session
)))
4241 /* GNUTLS repeat handhake when GNUTLS_E_AGAIN */
4244 if (r
== GNUTLS_E_AGAIN
|| r
== GNUTLS_E_INTERRUPTED
)
4245 { if (!gnutls_record_get_direction(soap
->session
))
4246 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
4248 s
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
4249 if (s
< 0 && soap
->errnum
!= SOAP_EINTR
)
4253 { soap
->errnum
= soap_socket_errno(fd
);
4258 { soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL/TLS handshake failed", SOAP_SSL_ERROR
);
4259 soap
->fclosesocket(soap
, fd
);
4260 return SOAP_INVALID_SOCKET
;
4262 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
4263 { const char *err
= ssl_verify(soap
, host
);
4265 { soap
->fclosesocket(soap
, fd
);
4266 soap
->error
= soap_set_sender_error(soap
, "SSL/TLS error", err
, SOAP_SSL_ERROR
);
4267 return SOAP_INVALID_SOCKET
;
4272 soap
->fclosesocket(soap
, fd
);
4273 soap
->error
= SOAP_SSL_ERROR
;
4274 return SOAP_INVALID_SOCKET
;
4277 if (soap
->recv_timeout
|| soap
->send_timeout
)
4278 SOAP_SOCKNONBLOCK(fd
)
4286 /******************************************************************************/
4290 tcp_select(struct soap
*soap
, SOAP_SOCKET s
, int flags
, int timeout
)
4293 fd_set fd
[3], *rfd
, *sfd
, *efd
;
4296 /* if fd max set size exceeded, use poll() when available */
4297 #if defined(__QNX__) || defined(QNX) /* select() is not MT safe on some QNX */
4300 if ((int)s
>= (int)FD_SETSIZE
)
4303 { struct pollfd pollfd
;
4307 if (flags
& SOAP_TCP_SELECT_RCV
)
4308 pollfd
.events
|= POLLIN
;
4309 if (flags
& SOAP_TCP_SELECT_SND
)
4310 pollfd
.events
|= POLLOUT
;
4311 if (flags
& SOAP_TCP_SELECT_ERR
)
4312 pollfd
.events
|= POLLERR
;
4314 timeout
/= -1000; /* -usec -> ms */
4315 else if (timeout
<= 1000000) /* avoid overflow */
4316 timeout
*= 1000; /* sec -> ms */
4318 { retries
= timeout
/ 1000000;
4319 timeout
= 1000000000;
4321 do r
= poll(&pollfd
, 1, timeout
);
4322 while (r
== 0 && retries
--);
4325 if ((flags
& SOAP_TCP_SELECT_RCV
) && (pollfd
.revents
& POLLIN
))
4326 r
|= SOAP_TCP_SELECT_RCV
;
4327 if ((flags
& SOAP_TCP_SELECT_SND
) && (pollfd
.revents
& POLLOUT
))
4328 r
|= SOAP_TCP_SELECT_SND
;
4329 if ((flags
& SOAP_TCP_SELECT_ERR
) && (pollfd
.revents
& POLLERR
))
4330 r
|= SOAP_TCP_SELECT_ERR
;
4333 soap
->errnum
= soap_socket_errno(s
);
4337 { soap
->error
= SOAP_FD_EXCEEDED
;
4342 rfd
= sfd
= efd
= NULL
;
4343 if (flags
& SOAP_TCP_SELECT_RCV
)
4348 if (flags
& SOAP_TCP_SELECT_SND
)
4353 if (flags
& SOAP_TCP_SELECT_ERR
)
4359 { tv
.tv_sec
= timeout
;
4363 { tv
.tv_sec
= -timeout
/ 1000000;
4364 tv
.tv_usec
= -timeout
% 1000000;
4366 r
= select((int)s
+ 1, rfd
, sfd
, efd
, &tv
);
4369 if ((flags
& SOAP_TCP_SELECT_RCV
) && FD_ISSET(s
, rfd
))
4370 r
|= SOAP_TCP_SELECT_RCV
;
4371 if ((flags
& SOAP_TCP_SELECT_SND
) && FD_ISSET(s
, sfd
))
4372 r
|= SOAP_TCP_SELECT_SND
;
4373 if ((flags
& SOAP_TCP_SELECT_ERR
) && FD_ISSET(s
, efd
))
4374 r
|= SOAP_TCP_SELECT_ERR
;
4377 soap
->errnum
= soap_socket_errno(s
);
4383 /******************************************************************************/
4387 tcp_accept(struct soap
*soap
, SOAP_SOCKET s
, struct sockaddr
*a
, int *n
)
4389 fd
= accept(s
, a
, (SOAP_SOCKLEN_T
*)n
); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4390 #ifdef SOCKET_CLOSE_ON_EXEC
4393 SetHandleInformation((HANDLE
)fd
, HANDLE_FLAG_INHERIT
, 0);
4396 fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
4404 /******************************************************************************/
4408 tcp_disconnect(struct soap
*soap
)
4414 { SSL_SESSION_free(soap
->session
);
4415 soap
->session
= NULL
;
4418 { soap
->session
= SSL_get1_session(soap
->ssl
);
4420 { strcpy(soap
->session_host
, soap
->host
);
4421 soap
->session_port
= soap
->port
;
4424 r
= SSL_shutdown(soap
->ssl
);
4425 /* SSL shutdown does not work when reads are pending */
4426 while (SSL_want_read(soap
->ssl
))
4427 { SSL_read(soap
->ssl
, NULL
, 0);
4428 if (soap_socket_errno(soap
->socket
) != SOAP_EAGAIN
)
4429 { r
= SSL_shutdown(soap
->ssl
);
4434 { if (soap_valid_socket(soap
->socket
))
4435 { if (!soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_WR
))
4439 wait up to 10 seconds for close_notify to be sent by peer (if peer not
4440 present, this avoids calling SSL_shutdown() which has a lengthy return
4443 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, 10);
4444 if (r
<= 0 && soap
->errnum
!= SOAP_EINTR
)
4446 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connection lost...\n"));
4447 soap
->fclosesocket(soap
, soap
->socket
);
4448 soap
->socket
= SOAP_INVALID_SOCKET
;
4449 ERR_remove_state(0);
4453 r
= SSL_shutdown(soap
->ssl
);
4459 { s
= ERR_get_error();
4461 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Shutdown failed: %d\n", SSL_get_error(soap
->ssl
, r
)));
4462 if (soap_valid_socket(soap
->socket
) && !(soap
->omode
& SOAP_IO_UDP
))
4463 { soap
->fclosesocket(soap
, soap
->socket
);
4464 soap
->socket
= SOAP_INVALID_SOCKET
;
4468 SSL_free(soap
->ssl
);
4471 return SOAP_SSL_ERROR
;
4472 ERR_remove_state(0);
4477 { gnutls_bye(soap
->session
, GNUTLS_SHUT_RDWR
);
4478 gnutls_deinit(soap
->session
);
4479 soap
->session
= NULL
;
4482 if (soap_valid_socket(soap
->socket
) && !(soap
->omode
& SOAP_IO_UDP
))
4483 { soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_RDWR
);
4484 soap
->fclosesocket(soap
, soap
->socket
);
4485 soap
->socket
= SOAP_INVALID_SOCKET
;
4492 /******************************************************************************/
4496 tcp_closesocket(struct soap
*soap
, SOAP_SOCKET fd
)
4497 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Close socket %d\n", (int)fd
));
4498 return soap_closesocket(fd
);
4503 /******************************************************************************/
4507 tcp_shutdownsocket(struct soap
*soap
, SOAP_SOCKET fd
, int how
)
4508 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Shutdown socket %d how=%d\n", (int)fd
, how
));
4509 return shutdown(fd
, how
);
4514 /******************************************************************************/
4520 soap_bind(struct soap
*soap
, const char *host
, int port
, int backlog
)
4523 struct addrinfo
*addrinfo
= NULL
;
4524 struct addrinfo hints
;
4525 struct addrinfo res
;
4527 #ifdef WITH_NO_IPV6_V6ONLY
4533 int len
= SOAP_BUFLEN
;
4535 int len
= SOAP_BUFLEN
+ 1; /* speeds up windows xfer */
4539 if (soap_valid_socket(soap
->master
))
4540 { soap
->fclosesocket(soap
, soap
->master
);
4541 soap
->master
= SOAP_INVALID_SOCKET
;
4543 soap
->socket
= SOAP_INVALID_SOCKET
;
4546 { soap_set_receiver_error(soap
, tcp_error(soap
), "TCP init failed in soap_bind()", SOAP_TCP_ERROR
);
4547 return SOAP_INVALID_SOCKET
;
4550 memset((void*)&hints
, 0, sizeof(hints
));
4551 hints
.ai_family
= PF_UNSPEC
;
4553 if ((soap
->omode
& SOAP_IO_UDP
))
4554 hints
.ai_socktype
= SOCK_DGRAM
;
4557 hints
.ai_socktype
= SOCK_STREAM
;
4558 hints
.ai_flags
= AI_PASSIVE
;
4560 err
= getaddrinfo(host
, soap_int2s(soap
, port
), &hints
, &addrinfo
);
4561 if (err
|| !addrinfo
)
4562 { soap_set_receiver_error(soap
, SOAP_GAI_STRERROR(err
), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR
);
4563 return SOAP_INVALID_SOCKET
;
4566 memcpy(&soap
->peer
, addrinfo
->ai_addr
, addrinfo
->ai_addrlen
);
4567 soap
->peerlen
= addrinfo
->ai_addrlen
;
4568 res
.ai_addr
= (struct sockaddr
*)&soap
->peer
;
4569 res
.ai_addrlen
= soap
->peerlen
;
4570 freeaddrinfo(addrinfo
);
4571 soap
->master
= (int)socket(res
.ai_family
, res
.ai_socktype
, res
.ai_protocol
);
4574 if ((soap
->omode
& SOAP_IO_UDP
))
4575 soap
->master
= (int)socket(AF_INET
, SOCK_DGRAM
, 0);
4578 soap
->master
= (int)socket(AF_INET
, SOCK_STREAM
, 0);
4581 if (!soap_valid_socket(soap
->master
))
4582 { soap
->errnum
= soap_socket_errno(soap
->master
);
4583 soap_set_receiver_error(soap
, tcp_error(soap
), "socket failed in soap_bind()", SOAP_TCP_ERROR
);
4584 return SOAP_INVALID_SOCKET
;
4587 if ((soap
->omode
& SOAP_IO_UDP
))
4588 soap
->socket
= soap
->master
;
4590 #ifdef SOCKET_CLOSE_ON_EXEC
4593 SetHandleInformation((HANDLE
)soap
->master
, HANDLE_FLAG_INHERIT
, 0);
4596 fcntl(soap
->master
, F_SETFD
, 1);
4600 if (soap
->bind_flags
&& setsockopt(soap
->master
, SOL_SOCKET
, soap
->bind_flags
, (char*)&set
, sizeof(int)))
4601 { soap
->errnum
= soap_socket_errno(soap
->master
);
4602 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR
);
4603 return SOAP_INVALID_SOCKET
;
4605 if (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) && setsockopt(soap
->master
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
4606 { soap
->errnum
= soap_socket_errno(soap
->master
);
4607 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR
);
4608 return SOAP_INVALID_SOCKET
;
4610 if (setsockopt(soap
->master
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
4611 { soap
->errnum
= soap_socket_errno(soap
->master
);
4612 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR
);
4613 return SOAP_INVALID_SOCKET
;
4615 if (setsockopt(soap
->master
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
4616 { soap
->errnum
= soap_socket_errno(soap
->master
);
4617 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR
);
4618 return SOAP_INVALID_SOCKET
;
4621 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(soap
->master
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
4622 { soap
->errnum
= soap_socket_errno(soap
->master
);
4623 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR
);
4624 return SOAP_INVALID_SOCKET
;
4629 #ifdef WITH_IPV6_V6ONLY
4630 if (setsockopt(soap
->master
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char*)&set
, sizeof(int)))
4631 { soap
->errnum
= soap_socket_errno(soap
->master
);
4632 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR
);
4633 return SOAP_INVALID_SOCKET
;
4636 #ifdef WITH_NO_IPV6_V6ONLY
4637 if (setsockopt(soap
->master
, IPPROTO_IPV6
, IPV6_V6ONLY
, (char*)&unset
, sizeof(int)))
4638 { soap
->errnum
= soap_socket_errno(soap
->master
);
4639 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR
);
4640 return SOAP_INVALID_SOCKET
;
4644 if (bind(soap
->master
, res
.ai_addr
, (int)res
.ai_addrlen
))
4645 { soap
->errnum
= soap_socket_errno(soap
->master
);
4646 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4647 soap_closesock(soap
);
4648 soap_set_receiver_error(soap
, tcp_error(soap
), "bind failed in soap_bind()", SOAP_TCP_ERROR
);
4649 return SOAP_INVALID_SOCKET
;
4652 soap
->peerlen
= sizeof(soap
->peer
);
4653 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
4654 soap
->peer
.sin_family
= AF_INET
;
4657 { if (soap
->fresolve(soap
, host
, &soap
->peer
.sin_addr
))
4658 { soap_set_receiver_error(soap
, tcp_error(soap
), "get host by name failed in soap_bind()", SOAP_TCP_ERROR
);
4659 return SOAP_INVALID_SOCKET
;
4663 soap
->peer
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
4664 soap
->peer
.sin_port
= htons((short)port
);
4666 if (bind(soap
->master
, (struct sockaddr
*)&soap
->peer
, (int)soap
->peerlen
))
4667 { soap
->errnum
= soap_socket_errno(soap
->master
);
4668 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4669 soap_closesock(soap
);
4670 soap_set_receiver_error(soap
, tcp_error(soap
), "bind failed in soap_bind()", SOAP_TCP_ERROR
);
4671 return SOAP_INVALID_SOCKET
;
4674 if (!(soap
->omode
& SOAP_IO_UDP
) && listen(soap
->master
, backlog
))
4675 { soap
->errnum
= soap_socket_errno(soap
->master
);
4676 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4677 soap_closesock(soap
);
4678 soap_set_receiver_error(soap
, tcp_error(soap
), "listen failed in soap_bind()", SOAP_TCP_ERROR
);
4679 return SOAP_INVALID_SOCKET
;
4681 return soap
->master
;
4686 /******************************************************************************/
4692 soap_poll(struct soap
*soap
)
4696 if (soap_valid_socket(soap
->socket
))
4697 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ALL
, 0);
4698 if (r
> 0 && (r
& SOAP_TCP_SELECT_ERR
))
4701 else if (soap_valid_socket(soap
->master
))
4702 r
= tcp_select(soap
, soap
->master
, SOAP_TCP_SELECT_SND
, 0);
4704 return SOAP_OK
; /* OK when no socket! */
4708 if (soap
->imode
& SOAP_ENC_SSL
)
4710 if (soap_valid_socket(soap
->socket
)
4711 && (r
& SOAP_TCP_SELECT_SND
)
4712 && (!(r
& SOAP_TCP_SELECT_RCV
)
4713 || SSL_peek(soap
->ssl
, soap
->tmpbuf
, 1) > 0))
4718 if (soap_valid_socket(soap
->socket
)
4719 && (r
& SOAP_TCP_SELECT_SND
)
4720 && (!(r
& SOAP_TCP_SELECT_RCV
)
4721 || recv(soap
->socket
, soap
->tmpbuf
, 1, MSG_PEEK
) > 0))
4725 { if ((soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) && soap_socket_errno(soap
->master
) != SOAP_EINTR
)
4726 { soap_set_receiver_error(soap
, tcp_error(soap
), "select failed in soap_poll()", SOAP_TCP_ERROR
);
4727 return soap
->error
= SOAP_TCP_ERROR
;
4730 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Polling: other end down on socket=%d select=%d\n", soap
->socket
, r
));
4739 /******************************************************************************/
4745 soap_accept(struct soap
*soap
)
4746 { int n
= (int)sizeof(soap
->peer
);
4749 int len
= SOAP_BUFLEN
;
4751 int len
= SOAP_BUFLEN
+ 1; /* speeds up windows xfer */
4755 soap
->error
= SOAP_OK
;
4757 if ((soap
->omode
& SOAP_IO_UDP
))
4758 return soap
->socket
= soap
->master
;
4760 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
4761 soap
->socket
= SOAP_INVALID_SOCKET
;
4763 soap
->keep_alive
= 0;
4764 if (soap_valid_socket(soap
->master
))
4767 { if (soap
->accept_timeout
|| soap
->send_timeout
|| soap
->recv_timeout
)
4770 r
= tcp_select(soap
, soap
->master
, SOAP_TCP_SELECT_ALL
, soap
->accept_timeout
? soap
->accept_timeout
: 60);
4773 if (!r
&& soap
->accept_timeout
)
4774 { soap_set_receiver_error(soap
, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR
);
4775 return SOAP_INVALID_SOCKET
;
4779 if (r
!= SOAP_EINTR
)
4780 { soap_closesock(soap
);
4781 soap_set_sender_error(soap
, tcp_error(soap
), "accept failed in soap_accept()", SOAP_TCP_ERROR
);
4782 return SOAP_INVALID_SOCKET
;
4787 if (soap
->accept_timeout
)
4788 SOAP_SOCKNONBLOCK(soap
->master
)
4790 SOAP_SOCKBLOCK(soap
->master
)
4791 soap
->socket
= soap
->faccept(soap
, soap
->master
, (struct sockaddr
*)&soap
->peer
, &n
);
4792 soap
->peerlen
= (size_t)n
;
4793 if (soap_valid_socket(soap
->socket
))
4796 /* Use soap->host to store the numeric form of the remote host */
4797 getnameinfo((struct sockaddr
*)&soap
->peer
, n
, soap
->host
, sizeof(soap
->host
), NULL
, 0, NI_NUMERICHOST
| NI_NUMERICSERV
);
4798 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Accept socket %d from %s\n", soap
->socket
, soap
->host
));
4799 soap
->ip
= 0; /* info stored in soap->peer and soap->host */
4800 soap
->port
= 0; /* info stored in soap->peer and soap->host */
4802 soap
->ip
= ntohl(soap
->peer
.sin_addr
.s_addr
);
4803 soap
->port
= (int)ntohs(soap
->peer
.sin_port
); /* does not return port number on some systems */
4804 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap
->socket
, soap
->port
, (int)(soap
->ip
>>24)&0xFF, (int)(soap
->ip
>>16)&0xFF, (int)(soap
->ip
>>8)&0xFF, (int)soap
->ip
&0xFF));
4807 if (soap
->accept_flags
== SO_LINGER
)
4808 { struct linger linger
;
4809 memset((void*)&linger
, 0, sizeof(linger
));
4811 linger
.l_linger
= soap
->linger_time
;
4812 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_LINGER
, (char*)&linger
, sizeof(struct linger
)))
4813 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4814 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR
);
4815 soap_closesock(soap
);
4816 return SOAP_INVALID_SOCKET
;
4819 else if (soap
->accept_flags
&& setsockopt(soap
->socket
, SOL_SOCKET
, soap
->accept_flags
, (char*)&set
, sizeof(int)))
4820 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4821 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR
);
4822 soap_closesock(soap
);
4823 return SOAP_INVALID_SOCKET
;
4825 if (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) && setsockopt(soap
->socket
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
4826 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4827 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR
);
4828 soap_closesock(soap
);
4829 return SOAP_INVALID_SOCKET
;
4831 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
4832 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4833 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR
);
4834 soap_closesock(soap
);
4835 return SOAP_INVALID_SOCKET
;
4837 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
4838 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4839 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR
);
4840 soap_closesock(soap
);
4841 return SOAP_INVALID_SOCKET
;
4844 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(soap
->socket
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
4845 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4846 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR
);
4847 soap_closesock(soap
);
4848 return SOAP_INVALID_SOCKET
;
4852 soap
->keep_alive
= (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) != 0);
4853 if (soap
->send_timeout
|| soap
->recv_timeout
)
4854 SOAP_SOCKNONBLOCK(soap
->socket
)
4856 SOAP_SOCKBLOCK(soap
->socket
)
4857 return soap
->socket
;
4859 err
= soap_socket_errno(soap
->socket
);
4860 if (err
!= 0 && err
!= SOAP_EINTR
&& err
!= SOAP_EAGAIN
&& err
!= SOAP_EWOULDBLOCK
)
4861 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Accept failed from %s\n", soap
->host
));
4863 soap_set_receiver_error(soap
, tcp_error(soap
), "accept failed in soap_accept()", SOAP_TCP_ERROR
);
4864 soap_closesock(soap
);
4865 return SOAP_INVALID_SOCKET
;
4871 soap_set_receiver_error(soap
, tcp_error(soap
), "no master socket in soap_accept()", SOAP_TCP_ERROR
);
4872 return SOAP_INVALID_SOCKET
;
4878 /******************************************************************************/
4883 soap_closesock(struct soap
*soap
)
4884 { register int status
= soap
->error
;
4886 if (status
) /* close on error: attachment state is not to be trusted */
4887 { soap
->mime
.first
= NULL
;
4888 soap
->mime
.last
= NULL
;
4889 soap
->dime
.first
= NULL
;
4890 soap
->dime
.last
= NULL
;
4893 if (soap
->fdisconnect
&& (soap
->error
= soap
->fdisconnect(soap
)))
4895 if (status
== SOAP_EOF
|| status
== SOAP_TCP_ERROR
|| status
== SOAP_SSL_ERROR
|| !soap
->keep_alive
)
4896 { if (soap
->fclose
&& (soap
->error
= soap
->fclose(soap
)))
4898 soap
->keep_alive
= 0;
4901 if (soap
->zlib_state
== SOAP_ZLIB_DEFLATE
)
4902 deflateEnd(soap
->d_stream
);
4903 else if (soap
->zlib_state
== SOAP_ZLIB_INFLATE
)
4904 inflateEnd(soap
->d_stream
);
4905 soap
->zlib_state
= SOAP_ZLIB_NONE
;
4907 return soap
->error
= status
;
4911 /******************************************************************************/
4917 soap_cleanup(struct soap
*soap
)
4929 /******************************************************************************/
4934 soap_done(struct soap
*soap
)
4939 if (soap_check_state(soap
))
4941 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Done with context\n"));
4942 soap_free_temp(soap
);
4944 { struct soap_clist
*p
= soap
->clist
->next
;
4945 SOAP_FREE(soap
, soap
->clist
);
4948 if (soap
->state
== SOAP_INIT
)
4949 soap
->omode
&= ~SOAP_IO_UDP
; /* to force close the socket */
4950 soap
->keep_alive
= 0; /* to force close the socket */
4951 soap_closesock(soap
);
4953 soap_free_cookies(soap
);
4955 while (soap
->plugins
)
4956 { register struct soap_plugin
*p
= soap
->plugins
->next
;
4957 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Removing plugin '%s'\n", soap
->plugins
->id
));
4958 if (soap
->plugins
->fcopy
|| soap
->state
== SOAP_INIT
)
4959 soap
->plugins
->fdelete(soap
, soap
->plugins
);
4960 SOAP_FREE(soap
, soap
->plugins
);
4963 soap
->fplugin
= fplugin
;
4964 soap
->fmalloc
= NULL
;
4966 soap
->fpost
= http_post
;
4967 soap
->fput
= http_put
;
4968 soap
->fget
= http_get
;
4969 soap
->fdel
= http_405
;
4970 soap
->fopt
= http_405
;
4971 soap
->fhead
= http_405
;
4973 soap
->fposthdr
= http_post_header
;
4974 soap
->fresponse
= http_response
;
4975 soap
->fparse
= http_parse
;
4976 soap
->fparsehdr
= http_parse_header
;
4978 soap
->fheader
= NULL
;
4981 soap
->fresolve
= tcp_gethost
;
4983 soap
->fresolve
= NULL
;
4985 soap
->faccept
= tcp_accept
;
4986 soap
->fopen
= tcp_connect
;
4987 soap
->fclose
= tcp_disconnect
;
4988 soap
->fclosesocket
= tcp_closesocket
;
4989 soap
->fshutdownsocket
= tcp_shutdownsocket
;
4990 soap
->fsend
= fsend
;
4991 soap
->frecv
= frecv
;
4992 soap
->fpoll
= soap_poll
;
4995 soap
->fclose
= NULL
;
4999 soap
->fprepareinitsend
= NULL
;
5000 soap
->fprepareinitrecv
= NULL
;
5001 soap
->fpreparesend
= NULL
;
5002 soap
->fpreparerecv
= NULL
;
5003 soap
->fpreparefinalsend
= NULL
;
5004 soap
->fpreparefinalrecv
= NULL
;
5006 soap
->fseterror
= NULL
;
5007 soap
->fignore
= NULL
;
5008 soap
->fserveloop
= NULL
;
5011 { SSL_SESSION_free(soap
->session
);
5012 soap
->session
= NULL
;
5015 if (soap
->state
== SOAP_INIT
)
5016 { if (soap_valid_socket(soap
->master
))
5017 { soap
->fclosesocket(soap
, soap
->master
);
5018 soap
->master
= SOAP_INVALID_SOCKET
;
5023 { SSL_free(soap
->ssl
);
5026 if (soap
->state
== SOAP_INIT
)
5028 { SSL_CTX_free(soap
->ctx
);
5032 ERR_remove_state(0);
5035 if (soap
->state
== SOAP_INIT
)
5037 { gnutls_certificate_free_credentials(soap
->xcred
);
5041 { gnutls_anon_free_client_credentials(soap
->acred
);
5045 { gnutls_priority_deinit(soap
->cache
);
5048 if (soap
->dh_params
)
5049 { gnutls_dh_params_deinit(soap
->dh_params
);
5050 soap
->dh_params
= NULL
;
5052 if (soap
->rsa_params
)
5053 { gnutls_rsa_params_deinit(soap
->rsa_params
);
5054 soap
->rsa_params
= NULL
;
5058 { gnutls_deinit(soap
->session
);
5059 soap
->session
= NULL
;
5062 #ifdef WITH_C_LOCALE
5063 freelocale(soap
->c_locale
);
5067 { SOAP_FREE(soap
, (void*)soap
->d_stream
);
5068 soap
->d_stream
= NULL
;
5071 { SOAP_FREE(soap
, (void*)soap
->z_buf
);
5076 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free logfiles\n"));
5077 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
5078 { if (soap
->logfile
[i
])
5079 { SOAP_FREE(soap
, (void*)soap
->logfile
[i
]);
5080 soap
->logfile
[i
] = NULL
;
5082 soap_close_logfile(soap
, i
);
5084 soap
->state
= SOAP_NONE
;
5086 #ifdef SOAP_MEM_DEBUG
5087 soap_free_mht(soap
);
5092 /******************************************************************************\
5096 \******************************************************************************/
5098 /******************************************************************************/
5102 http_parse(struct soap
*soap
)
5103 { char header
[SOAP_HDRLEN
], *s
;
5104 unsigned short httpcmd
= 0, status
= 0;
5105 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Waiting for HTTP request/response...\n"));
5106 *soap
->endpoint
= '\0';
5108 soap
->userid
= NULL
;
5109 soap
->passwd
= NULL
;
5110 soap
->action
= NULL
;
5111 soap
->authrealm
= NULL
;
5112 soap
->proxy_from
= NULL
;
5113 soap
->http_content
= NULL
;
5116 { if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
5117 { if (soap
->error
== SOAP_EOF
)
5119 return soap
->error
= 414;
5121 if ((s
= strchr(soap
->msgbuf
, ' ')))
5122 { soap
->status
= (unsigned short)soap_strtoul(s
, &s
, 10);
5123 if (!soap_blank((soap_wchar
)*s
))
5128 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP status: %s\n", soap
->msgbuf
));
5130 { if (soap_getline(soap
, header
, SOAP_HDRLEN
))
5131 { if (soap
->error
== SOAP_EOF
)
5132 { soap
->error
= SOAP_OK
;
5133 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "EOF in HTTP header, continue anyway\n"));
5140 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP header: %s\n", header
));
5141 s
= strchr(header
, ':');
5146 while (*s
&& *s
<= 32);
5149 t
= s
+ strlen(s
) - 1;
5150 while (t
> s
&& *t
<= 32)
5152 if (t
>= s
&& *t
== '"')
5155 if ((soap
->error
= soap
->fparsehdr(soap
, header
, s
)))
5156 { if (soap
->error
< SOAP_STOP
)
5158 status
= soap
->error
;
5159 soap
->error
= SOAP_OK
;
5163 } while (soap
->status
== 100);
5164 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Finished HTTP header parsing, status = %d\n", soap
->status
));
5165 s
= strstr(soap
->msgbuf
, "HTTP/");
5166 if (s
&& s
[7] != '1')
5167 { if (soap
->keep_alive
== 1)
5168 soap
->keep_alive
= 0;
5169 if (soap
->status
== 0 && (soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
) /* soap->status == 0 for HTTP request */
5170 { soap
->imode
|= SOAP_IO_CHUNK
;
5171 soap
->omode
= (soap
->omode
& ~SOAP_IO
) | SOAP_IO_STORE
;
5174 if (soap
->keep_alive
< 0)
5175 soap
->keep_alive
= 1;
5176 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Keep alive connection = %d\n", soap
->keep_alive
));
5177 if (soap
->status
== 0)
5180 { if (!strncmp(soap
->msgbuf
, "POST ", l
= 5))
5182 else if (!strncmp(soap
->msgbuf
, "PUT ", l
= 4))
5184 else if (!strncmp(soap
->msgbuf
, "GET ", l
= 4))
5186 else if (!strncmp(soap
->msgbuf
, "DELETE ", l
= 7))
5188 else if (!strncmp(soap
->msgbuf
, "OPTIONS ", l
= 8))
5190 else if (!strncmp(soap
->msgbuf
, "HEAD ", l
= 5))
5194 { size_t m
= strlen(soap
->endpoint
);
5195 size_t n
= m
+ (s
- soap
->msgbuf
) - l
- 1;
5198 if (n
>= sizeof(soap
->endpoint
))
5199 n
= sizeof(soap
->endpoint
) - 1;
5200 strncpy(soap
->path
, soap
->msgbuf
+ l
, n
- m
);
5201 soap
->path
[n
- m
] = '\0';
5202 strcat(soap
->endpoint
, soap
->path
);
5203 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Target endpoint='%s'\n", soap
->endpoint
));
5205 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP %s handler\n", soap
->msgbuf
));
5207 { case 2: soap
->error
= soap
->fput(soap
); break;
5208 case 3: soap
->error
= soap
->fget(soap
); break;
5209 case 4: soap
->error
= soap
->fdel(soap
); break;
5210 case 5: soap
->error
= soap
->fopt(soap
); break;
5211 case 6: soap
->error
= soap
->fhead(soap
); break;
5212 default: soap
->error
= 405; break;
5214 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP handler return = %d\n", soap
->error
));
5215 if (soap
->error
== SOAP_OK
)
5216 soap
->error
= SOAP_STOP
; /* prevents further processing */
5220 return soap
->error
= status
;
5223 return soap
->error
= status
;
5225 return soap
->error
= 405;
5227 /* Status OK (HTTP 200) */
5228 if (soap
->status
== 0 || soap
->status
== 200)
5230 /* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors
5231 may not have a body. When content length, content type, or chunking is
5232 used assume there is a message to parse, either XML or HTTP.
5234 if (soap
->length
> 0 || (soap
->http_content
&& soap
->recv_timeout
) || (soap
->imode
& SOAP_IO
) == SOAP_IO_CHUNK
)
5235 { if (((soap
->status
> 200 && soap
->status
<= 299) || soap
->status
== 400 || soap
->status
== 500))
5237 /* force close afterwards in soap_closesock() */
5238 soap
->keep_alive
= 0;
5240 /* read HTTP body for error details */
5241 s
= soap_get_http_body(soap
);
5243 return soap_set_receiver_error(soap
, soap
->msgbuf
, s
, soap
->status
);
5246 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP error %d\n", soap
->status
));
5247 return soap_set_receiver_error(soap
, "HTTP Error", soap
->msgbuf
, soap
->status
);
5252 /******************************************************************************/
5256 http_parse_header(struct soap
*soap
, const char *key
, const char *val
)
5257 { if (!soap_tag_cmp(key
, "Host"))
5259 #if defined(WITH_OPENSSL) || defined(WITH_GNUTLS)
5260 if (soap
->imode
& SOAP_ENC_SSL
)
5261 strcpy(soap
->endpoint
, "https://");
5264 strcpy(soap
->endpoint
, "http://");
5265 strncat(soap
->endpoint
, val
, sizeof(soap
->endpoint
) - 8);
5266 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
5269 else if (!soap_tag_cmp(key
, "Content-Type"))
5270 { const char *action
;
5271 soap
->http_content
= soap_strdup(soap
, val
);
5272 if (soap_get_header_attribute(soap
, val
, "application/dime"))
5273 soap
->imode
|= SOAP_ENC_DIME
;
5274 else if (soap_get_header_attribute(soap
, val
, "multipart/related")
5275 || soap_get_header_attribute(soap
, val
, "multipart/form-data"))
5276 { soap
->mime
.boundary
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "boundary"));
5277 soap
->mime
.start
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "start"));
5278 soap
->imode
|= SOAP_ENC_MIME
;
5280 action
= soap_get_header_attribute(soap
, val
, "action");
5282 { if (*action
== '"')
5283 { soap
->action
= soap_strdup(soap
, action
+ 1);
5284 soap
->action
[strlen(soap
->action
) - 1] = '\0';
5287 soap
->action
= soap_strdup(soap
, action
);
5291 else if (!soap_tag_cmp(key
, "Content-Length"))
5292 { soap
->length
= soap_strtoul(val
, NULL
, 10);
5294 else if (!soap_tag_cmp(key
, "Content-Encoding"))
5295 { if (!soap_tag_cmp(val
, "deflate"))
5297 soap
->zlib_in
= SOAP_ZLIB_DEFLATE
;
5299 return SOAP_ZLIB_ERROR
;
5301 else if (!soap_tag_cmp(val
, "gzip"))
5303 soap
->zlib_in
= SOAP_ZLIB_GZIP
;
5305 return SOAP_ZLIB_ERROR
;
5309 else if (!soap_tag_cmp(key
, "Accept-Encoding"))
5312 if (strchr(val
, '*') || soap_get_header_attribute(soap
, val
, "gzip"))
5313 soap
->zlib_out
= SOAP_ZLIB_GZIP
;
5316 if (strchr(val
, '*') || soap_get_header_attribute(soap
, val
, "deflate"))
5317 soap
->zlib_out
= SOAP_ZLIB_DEFLATE
;
5319 soap
->zlib_out
= SOAP_ZLIB_NONE
;
5322 else if (!soap_tag_cmp(key
, "Transfer-Encoding"))
5323 { soap
->imode
&= ~SOAP_IO
;
5324 if (!soap_tag_cmp(val
, "chunked"))
5325 soap
->imode
|= SOAP_IO_CHUNK
;
5327 else if (!soap_tag_cmp(key
, "Connection"))
5328 { if (!soap_tag_cmp(val
, "keep-alive"))
5329 soap
->keep_alive
= -soap
->keep_alive
;
5330 else if (!soap_tag_cmp(val
, "close"))
5331 soap
->keep_alive
= 0;
5334 else if (!soap_tag_cmp(key
, "Authorization"))
5335 { if (!soap_tag_cmp(val
, "Basic *"))
5338 soap_base642s(soap
, val
+ 6, soap
->tmpbuf
, sizeof(soap
->tmpbuf
) - 1, &n
);
5339 soap
->tmpbuf
[n
] = '\0';
5340 if ((s
= strchr(soap
->tmpbuf
, ':')))
5342 soap
->userid
= soap_strdup(soap
, soap
->tmpbuf
);
5343 soap
->passwd
= soap_strdup(soap
, s
+ 1);
5347 else if (!soap_tag_cmp(key
, "WWW-Authenticate"))
5348 { soap
->authrealm
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
+ 6, "realm"));
5350 else if (!soap_tag_cmp(key
, "Expect"))
5351 { if (!soap_tag_cmp(val
, "100-continue"))
5352 { if ((soap
->error
= soap
->fposthdr(soap
, "HTTP/1.1 100 Continue", NULL
))
5353 || (soap
->error
= soap
->fposthdr(soap
, NULL
, NULL
)))
5358 else if (!soap_tag_cmp(key
, "SOAPAction"))
5360 { soap
->action
= soap_strdup(soap
, val
+ 1);
5361 soap
->action
[strlen(soap
->action
) - 1] = '\0';
5364 soap
->action
= soap_strdup(soap
, val
);
5366 else if (!soap_tag_cmp(key
, "Location"))
5367 { strncpy(soap
->endpoint
, val
, sizeof(soap
->endpoint
));
5368 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
5370 else if (!soap_tag_cmp(key
, "X-Forwarded-For"))
5371 { soap
->proxy_from
= soap_strdup(soap
, val
);
5374 else if (!soap_tag_cmp(key
, "Cookie")
5375 || !soap_tag_cmp(key
, "Cookie2")
5376 || !soap_tag_cmp(key
, "Set-Cookie")
5377 || !soap_tag_cmp(key
, "Set-Cookie2"))
5378 { soap_getcookies(soap
, val
);
5386 /******************************************************************************/
5387 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5392 soap_get_header_attribute(struct soap
*soap
, const char *line
, const char *key
)
5393 { register const char *s
= line
;
5396 { register short flag
;
5397 s
= soap_decode_key(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
);
5398 flag
= soap_tag_cmp(soap
->tmpbuf
, key
);
5399 s
= soap_decode_val(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
);
5401 return soap
->tmpbuf
;
5409 /******************************************************************************/
5410 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5415 soap_decode_key(char *buf
, size_t len
, const char *val
)
5416 { return soap_decode(buf
, len
, val
, "=,;");
5421 /******************************************************************************/
5422 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5427 soap_decode_val(char *buf
, size_t len
, const char *val
)
5432 return soap_decode(buf
, len
, val
+ 1, ",;");
5437 /******************************************************************************/
5438 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5441 soap_decode(char *buf
, size_t len
, const char *val
, const char *sep
)
5444 for (s
= val
; *s
; s
++)
5445 if (*s
!= ' ' && *s
!= '\t' && !strchr(sep
, *s
))
5449 while (*s
&& *s
!= '"' && --len
)
5453 { while (*s
&& !soap_blank((soap_wchar
)*s
) && !strchr(sep
, *s
) && --len
)
5455 { *t
++ = ((s
[1] >= 'A' ? (s
[1] & 0x7) + 9 : s
[1] - '0') << 4)
5456 + (s
[2] >= 'A' ? (s
[2] & 0x7) + 9 : s
[2] - '0');
5464 while (*s
&& !strchr(sep
, *s
))
5471 /******************************************************************************/
5475 http_error(struct soap
*soap
, int status
)
5476 { register const char *msg
= SOAP_STR_EOS
;
5478 msg
= soap_code_str(h_http_error_codes
, status
);
5487 /******************************************************************************/
5491 http_put(struct soap
*soap
)
5492 { return http_parse(soap
);
5496 /******************************************************************************/
5501 http_get(struct soap
*soap
)
5502 { return SOAP_GET_METHOD
;
5507 /******************************************************************************/
5511 http_405(struct soap
*soap
)
5517 /******************************************************************************/
5521 http_post(struct soap
*soap
, const char *endpoint
, const char *host
, int port
, const char *path
, const char *action
, size_t count
)
5522 { register const char *s
;
5524 if (soap
->status
== SOAP_GET
)
5529 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))
5531 if (!endpoint
|| (soap_tag_cmp(endpoint
, "http:*") && soap_tag_cmp(endpoint
, "https:*") && strncmp(endpoint
, "httpg:", 6)))
5534 if (strlen(endpoint
) + strlen(soap
->http_version
) > sizeof(soap
->tmpbuf
) - 80)
5535 return soap
->error
= SOAP_EOM
;
5536 if (soap
->proxy_host
&& soap_tag_cmp(endpoint
, "https:*"))
5537 sprintf(soap
->tmpbuf
, "%s %s HTTP/%s", s
, endpoint
, soap
->http_version
);
5539 sprintf(soap
->tmpbuf
, "%s /%s HTTP/%s", s
, (*path
== '/' ? path
+ 1 : path
), soap
->http_version
);
5540 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5543 if ((soap
->ssl
&& soap
->port
!= 443) || (!soap
->ssl
&& soap
->port
!= 80))
5544 sprintf(soap
->tmpbuf
, "%s:%d", host
, port
);
5546 strcpy(soap
->tmpbuf
, host
);
5549 sprintf(soap
->tmpbuf
, "%s:%d", host
, port
);
5551 strcpy(soap
->tmpbuf
, host
);
5553 if ((err
= soap
->fposthdr(soap
, "Host", soap
->tmpbuf
))
5554 || (err
= soap
->fposthdr(soap
, "User-Agent", "gSOAP/2.7"))
5555 || (err
= soap_puthttphdr(soap
, SOAP_OK
, count
)))
5559 if ((err
= soap
->fposthdr(soap
, "Accept-Encoding", "gzip, deflate")))
5561 if ((err
= soap
->fposthdr(soap
, "Accept-Encoding", "deflate")))
5566 if (soap
->userid
&& soap
->passwd
&& strlen(soap
->userid
) + strlen(soap
->passwd
) < 761)
5567 { sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->userid
, soap
->passwd
);
5568 strcpy(soap
->tmpbuf
, "Basic ");
5569 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
5570 if ((err
= soap
->fposthdr(soap
, "Authorization", soap
->tmpbuf
)))
5573 if (soap
->proxy_userid
&& soap
->proxy_passwd
&& strlen(soap
->proxy_userid
) + strlen(soap
->proxy_passwd
) < 761)
5574 { sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->proxy_userid
, soap
->proxy_passwd
);
5575 strcpy(soap
->tmpbuf
, "Basic ");
5576 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
5577 if ((err
= soap
->fposthdr(soap
, "Proxy-Authorization", soap
->tmpbuf
)))
5583 if (soap_putcookies(soap
, host
, path
, soap
->ssl
!= NULL
))
5586 if (soap_putcookies(soap
, host
, path
, 0))
5590 if (soap
->status
!= SOAP_GET
&& (soap
->version
== 1 || (action
&& *action
)))
5591 { sprintf(soap
->tmpbuf
, "\"%s\"", action
&& strlen(action
) < sizeof(soap
->tmpbuf
) - 3 ? action
: SOAP_STR_EOS
);
5592 if ((err
= soap
->fposthdr(soap
, "SOAPAction", soap
->tmpbuf
)))
5595 return soap
->fposthdr(soap
, NULL
, NULL
);
5600 /******************************************************************************/
5604 http_send_header(struct soap
*soap
, const char *s
)
5605 { register const char *t
;
5607 { t
= strchr(s
, '\n'); /* disallow \n in HTTP headers */
5610 if (soap_send_raw(soap
, s
, t
- s
))
5619 /******************************************************************************/
5623 http_post_header(struct soap
*soap
, const char *key
, const char *val
)
5625 { if (http_send_header(soap
, key
))
5627 if (val
&& (soap_send_raw(soap
, ": ", 2) || http_send_header(soap
, val
)))
5630 return soap_send_raw(soap
, "\r\n", 2);
5635 /******************************************************************************/
5639 http_response(struct soap
*soap
, int status
, size_t count
)
5643 httpOutputEnable(soap
->rpmreqid
);
5645 if (strlen(soap
->http_version
) > 4)
5646 return soap
->error
= SOAP_EOM
;
5647 if (!status
|| status
== SOAP_HTML
|| status
== SOAP_FILE
)
5649 if (count
|| ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
))
5653 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Status = %s\n", s
));
5655 if (soap
->rpmreqid
|| soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* RPM behaves as if standalone */
5657 if (soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* standalone application (socket) or CGI (stdin/out)? */
5659 { sprintf(soap
->tmpbuf
, "HTTP/%s %s", soap
->http_version
, s
);
5660 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5663 else if ((err
= soap
->fposthdr(soap
, "Status", s
))) /* CGI header */
5666 else if (status
>= 200 && status
< 600)
5667 { sprintf(soap
->tmpbuf
, "HTTP/%s %d %s", soap
->http_version
, status
, http_error(soap
, status
));
5668 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5672 { sprintf(soap
->tmpbuf
, "Basic realm=\"%s\"", (soap
->authrealm
&& strlen(soap
->authrealm
) < sizeof(soap
->tmpbuf
) - 14) ? soap
->authrealm
: "gSOAP Web Service");
5673 if ((err
= soap
->fposthdr(soap
, "WWW-Authenticate", soap
->tmpbuf
)))
5676 else if ((status
>= 301 && status
<= 303) || status
== 307)
5677 { if ((err
= soap
->fposthdr(soap
, "Location", soap
->endpoint
)))
5683 { const char *s
= *soap_faultcode(soap
);
5684 if (status
>= SOAP_GET_METHOD
&& status
<= SOAP_HTTP_METHOD
)
5685 s
= "405 Method Not Allowed";
5686 else if (soap
->version
== 2 && (!s
|| !strcmp(s
, "SOAP-ENV:Sender")))
5687 s
= "400 Bad Request";
5689 s
= "500 Internal Server Error";
5690 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error %s (status=%d)\n", s
, status
));
5692 if (soap
->rpmreqid
|| soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* RPM behaves as if standalone */
5694 if (soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* standalone application */
5696 { sprintf(soap
->tmpbuf
, "HTTP/%s %s", soap
->http_version
, s
);
5697 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5700 else if ((err
= soap
->fposthdr(soap
, "Status", s
))) /* CGI */
5703 if ((err
= soap
->fposthdr(soap
, "Server", "gSOAP/2.7"))
5704 || (err
= soap_puthttphdr(soap
, status
, count
)))
5707 if (soap_putsetcookies(soap
))
5710 return soap
->fposthdr(soap
, NULL
, NULL
);
5715 /******************************************************************************/
5720 soap_response(struct soap
*soap
, int status
)
5721 { register size_t count
;
5722 if (!(soap
->omode
& (SOAP_ENC_XML
| SOAP_IO_STORE
/* this tests for chunking too */))
5723 && (status
== SOAP_HTML
|| status
== SOAP_FILE
))
5724 soap
->omode
= (soap
->omode
& ~SOAP_IO
) | SOAP_IO_STORE
;
5725 soap
->status
= status
;
5726 count
= soap_count_attachments(soap
);
5727 if (soap_begin_send(soap
))
5730 if ((soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& !(soap
->mode
& SOAP_ENC_XML
))
5731 { register int n
= soap
->mode
;
5732 soap
->mode
&= ~(SOAP_IO
| SOAP_ENC_ZLIB
);
5733 if ((n
& SOAP_IO
) != SOAP_IO_FLUSH
)
5734 soap
->mode
|= SOAP_IO_BUFFER
;
5735 if ((soap
->error
= soap
->fresponse(soap
, status
, count
)))
5738 if ((n
& SOAP_IO
) == SOAP_IO_CHUNK
)
5739 { if (soap_flush(soap
))
5750 /******************************************************************************\
5754 \******************************************************************************/
5757 /******************************************************************************/
5761 soap_encode_cookie(const char *s
, char *t
, size_t len
)
5763 register size_t n
= len
;
5764 while ((c
= *s
++) && --n
> 0)
5765 { if (c
> ' ' && c
< 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c
))
5769 *t
++ = (c
>> 4) + (c
> 159 ? '7' : '0');
5771 *t
++ = c
+ (c
> 9 ? '7' : '0');
5781 /******************************************************************************/
5785 soap_cookie(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5786 { struct soap_cookie
*p
;
5788 domain
= soap
->cookie_domain
;
5790 path
= soap
->cookie_path
;
5792 path
= SOAP_STR_EOS
;
5793 else if (*path
== '/')
5795 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Search cookie %s domain=%s path=%s\n", name
, domain
?domain
:"(null)", path
?path
:"(null)"));
5796 for (p
= soap
->cookies
; p
; p
= p
->next
)
5797 { 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
));
5798 if (!strcmp(p
->name
, name
)
5801 && !strcmp(p
->domain
, domain
)
5802 && (!*p
->path
|| !strncmp(p
->path
, path
, strlen(p
->path
))))
5808 /******************************************************************************/
5812 soap_set_cookie(struct soap
*soap
, const char *name
, const char *value
, const char *domain
, const char *path
)
5813 { struct soap_cookie
**p
, *q
;
5816 domain
= soap
->cookie_domain
;
5818 path
= soap
->cookie_path
;
5820 path
= SOAP_STR_EOS
;
5821 else if (*path
== '/')
5823 q
= soap_cookie(soap
, name
, domain
, path
);
5824 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)"));
5826 { if ((q
= (struct soap_cookie
*)SOAP_MALLOC(soap
, sizeof(struct soap_cookie
))))
5827 { if ((q
->name
= (char*)SOAP_MALLOC(soap
, strlen(name
)+1)))
5828 strcpy(q
->name
, name
);
5837 for (p
= &soap
->cookies
, n
= soap
->cookie_max
; *p
&& n
; p
= &(*p
)->next
, n
--)
5838 if (!strcmp((*p
)->name
, name
) && (*p
)->path
&& path
&& strcmp((*p
)->path
, path
) < 0)
5845 { SOAP_FREE(soap
, q
->name
);
5855 { if (!value
|| strcmp(value
, q
->value
))
5856 { SOAP_FREE(soap
, q
->value
);
5860 if (value
&& *value
&& !q
->value
&& (q
->value
= (char*)SOAP_MALLOC(soap
, strlen(value
)+1)))
5861 strcpy(q
->value
, value
);
5863 { if (!domain
|| strcmp(domain
, q
->domain
))
5864 { SOAP_FREE(soap
, q
->domain
);
5868 if (domain
&& !q
->domain
&& (q
->domain
= (char*)SOAP_MALLOC(soap
, strlen(domain
)+1)))
5869 strcpy(q
->domain
, domain
);
5871 { if (!path
|| strncmp(path
, q
->path
, strlen(q
->path
)))
5872 { SOAP_FREE(soap
, q
->path
);
5876 if (path
&& !q
->path
&& (q
->path
= (char*)SOAP_MALLOC(soap
, strlen(path
)+1)))
5877 strcpy(q
->path
, path
);
5884 /******************************************************************************/
5888 soap_clr_cookie(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5889 { struct soap_cookie
**p
, *q
;
5891 domain
= soap
->cookie_domain
;
5893 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error in clear cookie %s: cookie domain not set\n", name
?name
:"(null)"));
5897 path
= soap
->cookie_path
;
5899 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error in clear cookie %s: cookie path not set\n", name
?name
:"(null)"));
5904 for (p
= &soap
->cookies
, q
= *p
; q
; q
= *p
)
5905 { if (!strcmp(q
->name
, name
) && !strcmp(q
->domain
, domain
) && !strncmp(q
->path
, path
, strlen(q
->path
)))
5907 SOAP_FREE(soap
, q
->value
);
5909 SOAP_FREE(soap
, q
->domain
);
5911 SOAP_FREE(soap
, q
->path
);
5920 /******************************************************************************/
5924 soap_cookie_value(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5925 { struct soap_cookie
*p
;
5926 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5931 /******************************************************************************/
5935 soap_env_cookie_value(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5936 { struct soap_cookie
*p
;
5937 if ((p
= soap_cookie(soap
, name
, domain
, path
)) && p
->env
)
5942 /******************************************************************************/
5946 soap_cookie_expire(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5947 { struct soap_cookie
*p
;
5948 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5953 /******************************************************************************/
5957 soap_set_cookie_expire(struct soap
*soap
, const char *name
, long expire
, const char *domain
, const char *path
)
5958 { struct soap_cookie
*p
;
5959 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire
, name
, domain
?domain
:"(null)", path
?path
:"(null)"));
5960 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5961 { p
->maxage
= expire
;
5968 /******************************************************************************/
5972 soap_set_cookie_session(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5973 { struct soap_cookie
*p
;
5974 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5982 /******************************************************************************/
5986 soap_clr_cookie_session(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5987 { struct soap_cookie
*p
;
5988 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5996 /******************************************************************************/
6000 soap_putsetcookies(struct soap
*soap
)
6001 { struct soap_cookie
*p
;
6004 for (p
= soap
->cookies
; p
; p
= p
->next
)
6008 || (!p
->env
&& !soap
->ssl
== !p
->secure
)
6013 s
+= soap_encode_cookie(p
->name
, s
, tmp
-s
+4064);
6014 if (p
->value
&& *p
->value
)
6016 s
+= soap_encode_cookie(p
->value
, s
, tmp
-s
+4064);
6018 if (p
->domain
&& (int)strlen(p
->domain
) < tmp
-s
+4064)
6019 { strcpy(s
, ";Domain=");
6020 strcat(s
, p
->domain
);
6022 else if (soap
->cookie_domain
&& (int)strlen(soap
->cookie_domain
) < tmp
-s
+4064)
6023 { strcpy(s
, ";Domain=");
6024 strcat(s
, soap
->cookie_domain
);
6026 strcat(s
, ";Path=/");
6031 t
= soap
->cookie_path
;
6035 if ((int)strlen(t
) < tmp
-s
+4064)
6036 { if (strchr(t
, '%')) /* already URL encoded? */
6041 s
+= soap_encode_cookie(t
, s
, tmp
-s
+4064);
6044 if (p
->version
> 0 && s
-tmp
< 4060)
6045 { sprintf(s
, ";Version=%u", p
->version
);
6048 if (p
->maxage
>= 0 && s
-tmp
< 4060)
6049 { sprintf(s
, ";Max-Age=%ld", p
->maxage
);
6058 strcpy(s
, ";Secure");
6059 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set-Cookie: %s\n", tmp
));
6060 if ((soap
->error
= soap
->fposthdr(soap
, "Set-Cookie", tmp
)))
6067 /******************************************************************************/
6071 soap_putcookies(struct soap
*soap
, const char *domain
, const char *path
, int secure
)
6072 { struct soap_cookie
**p
, *q
;
6073 unsigned int version
= 0;
6074 time_t now
= time(NULL
);
6077 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending cookies for domain=%s path=%s\n", domain
, path
));
6081 { if (q
->expire
&& now
> q
->expire
)
6082 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Cookie %s expired\n", q
->name
));
6083 SOAP_FREE(soap
, q
->name
);
6085 SOAP_FREE(soap
, q
->value
);
6087 SOAP_FREE(soap
, q
->domain
);
6089 SOAP_FREE(soap
, q
->path
);
6095 char *t
= q
->domain
;
6100 { const char *r
= strchr(t
, ':');
6105 flag
= !strncmp(t
, domain
, n
);
6107 /* domain-level cookies, cannot compile when WITH_NOIO set */
6110 { struct hostent
*hostent
= gethostbyname((char*)domain
);
6112 { const char *r
= strchr(hostent
->h_name
, '.');
6114 r
= hostent
->h_name
;
6115 flag
= !strncmp(t
, r
, n
);
6120 && (!q
->path
|| !strncmp(q
->path
, path
, strlen(q
->path
)))
6121 && (!q
->secure
|| secure
))
6123 if (q
->version
!= version
)
6124 { sprintf(s
, "$Version=%u;", q
->version
);
6125 version
= q
->version
;
6128 s
+= soap_encode_cookie(q
->name
, s
, tmp
-s
+4080);
6129 if (q
->value
&& *q
->value
)
6131 s
+= soap_encode_cookie(q
->value
, s
, tmp
-s
+4080);
6133 if (q
->path
&& *q
->path
&& (int)strlen(q
->path
) < tmp
-s
+4080)
6134 { sprintf(s
, ";$Path=\"/%s\"", (*q
->path
== '/' ? q
->path
+ 1 : q
->path
));
6137 if (q
->domain
&& (int)strlen(q
->domain
) < tmp
-s
+4080)
6138 sprintf(s
, ";$Domain=\"%s\"", q
->domain
);
6139 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Cookie: %s\n", tmp
));
6140 if ((soap
->error
= soap
->fposthdr(soap
, "Cookie", tmp
)))
6149 /******************************************************************************/
6153 soap_getcookies(struct soap
*soap
, const char *val
)
6154 { struct soap_cookie
*p
= NULL
, *q
;
6156 char *t
, tmp
[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6157 char *domain
= NULL
;
6159 unsigned int version
= 0;
6160 time_t now
= time(NULL
);
6165 { s
= soap_decode_key(tmp
, sizeof(tmp
), s
);
6166 if (!soap_tag_cmp(tmp
, "$Version"))
6167 { if ((s
= soap_decode_val(tmp
, sizeof(tmp
), s
)))
6169 p
->version
= (int)soap_strtol(tmp
, NULL
, 10);
6171 version
= (int)soap_strtol(tmp
, NULL
, 10);
6174 else if (!soap_tag_cmp(tmp
, "$Path"))
6175 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6177 { if ((t
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6184 SOAP_FREE(soap
, p
->path
);
6189 SOAP_FREE(soap
, path
);
6193 else if (!soap_tag_cmp(tmp
, "$Domain"))
6194 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6196 { if ((t
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6203 SOAP_FREE(soap
, p
->domain
);
6208 SOAP_FREE(soap
, domain
);
6212 else if (p
&& !soap_tag_cmp(tmp
, "Path"))
6214 SOAP_FREE(soap
, p
->path
);
6215 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6217 { if ((p
->path
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6218 strcpy(p
->path
, tmp
);
6223 else if (p
&& !soap_tag_cmp(tmp
, "Domain"))
6225 SOAP_FREE(soap
, p
->domain
);
6226 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6228 { if ((p
->domain
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6229 strcpy(p
->domain
, tmp
);
6234 else if (p
&& !soap_tag_cmp(tmp
, "Version"))
6235 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6236 p
->version
= (unsigned int)soap_strtoul(tmp
, NULL
, 10);
6238 else if (p
&& !soap_tag_cmp(tmp
, "Max-Age"))
6239 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6240 p
->expire
= now
+ soap_strtol(tmp
, NULL
, 10);
6242 else if (p
&& !soap_tag_cmp(tmp
, "Expires"))
6245 static const char mns
[] = "anebarprayunulugepctovec";
6246 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6247 if (strlen(tmp
) > 20)
6248 { memset((void*)&T
, 0, sizeof(T
));
6252 T
.tm_mday
= (int)soap_strtol(a
, NULL
, 10);
6255 T
.tm_mon
= (int)(strstr(mns
, a
) - mns
) / 2;
6258 T
.tm_year
= 100 + (int)soap_strtol(a
, NULL
, 10);
6261 T
.tm_hour
= (int)soap_strtol(a
, NULL
, 10);
6264 T
.tm_min
= (int)soap_strtol(a
, NULL
, 10);
6267 T
.tm_sec
= (int)soap_strtol(a
, NULL
, 10);
6268 p
->expire
= soap_timegm(&T
);
6271 else if (p
&& !soap_tag_cmp(tmp
, "Secure"))
6275 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p
->name
, p
->value
?p
->value
:"(null)", p
->domain
?p
->domain
:"(null)", p
->path
?p
->path
:"(null)", p
->expire
, p
->secure
));
6276 if ((q
= soap_set_cookie(soap
, p
->name
, p
->value
, p
->domain
, p
->path
)))
6277 { q
->version
= p
->version
;
6278 q
->expire
= p
->expire
;
6279 q
->secure
= p
->secure
;
6283 SOAP_FREE(soap
, p
->name
);
6285 SOAP_FREE(soap
, p
->value
);
6287 SOAP_FREE(soap
, p
->domain
);
6289 SOAP_FREE(soap
, p
->path
);
6292 if ((p
= (struct soap_cookie
*)SOAP_MALLOC(soap
, sizeof(struct soap_cookie
))))
6293 { p
->name
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1);
6294 strcpy(p
->name
, tmp
);
6295 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6297 { p
->value
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1);
6298 strcpy(p
->value
, tmp
);
6304 else if (*soap
->host
)
6305 { p
->domain
= (char*)SOAP_MALLOC(soap
, strlen(soap
->host
)+1);
6306 strcpy(p
->domain
, soap
->host
);
6312 else if (soap
->path
&& *soap
->path
)
6313 { p
->path
= (char*)SOAP_MALLOC(soap
, strlen(soap
->path
)+1);
6314 strcpy(p
->path
, soap
->path
);
6317 { p
->path
= (char*)SOAP_MALLOC(soap
, 2);
6318 strcpy(p
->path
, "/");
6322 p
->version
= version
;
6327 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p
->name
, p
->value
?p
->value
:"(null)", p
->domain
?p
->domain
:"(null)", p
->path
?p
->path
:"(null)", p
->expire
, p
->secure
));
6328 if ((q
= soap_set_cookie(soap
, p
->name
, p
->value
, p
->domain
, p
->path
)))
6329 { q
->version
= p
->version
;
6330 q
->expire
= p
->expire
;
6331 q
->secure
= p
->secure
;
6335 SOAP_FREE(soap
, p
->name
);
6337 SOAP_FREE(soap
, p
->value
);
6339 SOAP_FREE(soap
, p
->domain
);
6341 SOAP_FREE(soap
, p
->path
);
6345 SOAP_FREE(soap
, domain
);
6347 SOAP_FREE(soap
, path
);
6350 /******************************************************************************/
6354 soap_getenv_cookies(struct soap
*soap
)
6355 { struct soap_cookie
*p
;
6357 char key
[4096], val
[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6358 if (!(s
= getenv("HTTP_COOKIE")))
6361 { s
= soap_decode_key(key
, sizeof(key
), s
);
6362 s
= soap_decode_val(val
, sizeof(val
), s
);
6363 p
= soap_set_cookie(soap
, key
, val
, NULL
, NULL
);
6370 /******************************************************************************/
6374 soap_copy_cookies(struct soap
*copy
, const struct soap
*soap
)
6375 { struct soap_cookie
*p
, **q
, *r
;
6377 for (p
= soap
->cookies
; p
; p
= p
->next
)
6378 { if (!(*q
= (struct soap_cookie
*)SOAP_MALLOC(copy
, sizeof(struct soap_cookie
))))
6382 { if (((*q
)->name
= (char*)SOAP_MALLOC(copy
, strlen(p
->name
)+1)))
6383 strcpy((*q
)->name
, p
->name
);
6386 { if (((*q
)->value
= (char*)SOAP_MALLOC(copy
, strlen(p
->value
)+1)))
6387 strcpy((*q
)->value
, p
->value
);
6390 { if (((*q
)->domain
= (char*)SOAP_MALLOC(copy
, strlen(p
->domain
)+1)))
6391 strcpy((*q
)->domain
, p
->domain
);
6394 { if (((*q
)->path
= (char*)SOAP_MALLOC(copy
, strlen(p
->path
)+1)))
6395 strcpy((*q
)->path
, p
->path
);
6403 /******************************************************************************/
6407 soap_free_cookies(struct soap
*soap
)
6408 { struct soap_cookie
*p
;
6409 for (p
= soap
->cookies
; p
; p
= soap
->cookies
)
6410 { soap
->cookies
= p
->next
;
6411 SOAP_FREE(soap
, p
->name
);
6413 SOAP_FREE(soap
, p
->value
);
6415 SOAP_FREE(soap
, p
->domain
);
6417 SOAP_FREE(soap
, p
->path
);
6422 /******************************************************************************/
6423 #endif /* WITH_COOKIES */
6425 /******************************************************************************/
6426 #ifndef WITH_NOIDREF
6431 soap_hash(register const char *s
)
6432 { register size_t h
= 0;
6435 return h
% SOAP_IDHASH
;
6440 /******************************************************************************/
6441 #ifndef WITH_NOIDREF
6444 soap_init_pht(struct soap
*soap
)
6448 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
6449 soap
->pht
[i
] = NULL
;
6454 /******************************************************************************/
6459 soap_new1(soap_mode mode
)
6460 { return soap_new2(mode
, mode
);
6464 /******************************************************************************/
6470 { return soap_new2(SOAP_IO_DEFAULT
, SOAP_IO_DEFAULT
);
6474 /******************************************************************************/
6479 soap_new2(soap_mode imode
, soap_mode omode
)
6480 { struct soap
*soap
= (struct soap
*)malloc(sizeof(struct soap
));
6482 soap_init2(soap
, imode
, omode
);
6487 /******************************************************************************/
6492 soap_free(struct soap
*soap
)
6498 /******************************************************************************/
6503 soap_del(struct soap
*soap
)
6508 /******************************************************************************/
6509 #ifndef WITH_NOIDREF
6512 soap_free_pht(struct soap
*soap
)
6513 { register struct soap_pblk
*pb
, *next
;
6515 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free pointer hashtable\n"));
6516 for (pb
= soap
->pblk
; pb
; pb
= next
)
6518 SOAP_FREE(soap
, pb
);
6522 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
6523 soap
->pht
[i
] = NULL
;
6528 /******************************************************************************/
6529 #ifndef WITH_NOIDREF
6534 soap_embed(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, const char *tag
, int type
)
6536 struct soap_plist
*pp
;
6537 if (soap
->version
== 2)
6540 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, type
, &pp
);
6542 i
= soap_pointer_lookup(soap
, p
, type
, &pp
);
6544 { if (soap_is_embedded(soap
, pp
)
6545 || soap_is_single(soap
, pp
))
6547 soap_set_embedded(soap
, pp
);
6554 /******************************************************************************/
6555 #ifndef WITH_NOIDREF
6560 soap_pointer_lookup(struct soap
*soap
, const void *p
, int type
, struct soap_plist
**ppp
)
6561 { register struct soap_plist
*pp
;
6564 { for (pp
= soap
->pht
[soap_hash_ptr(p
)]; pp
; pp
= pp
->next
)
6565 { if (pp
->ptr
== p
&& pp
->type
== type
)
6567 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup location=%p type=%d id=%d\n", p
, type
, pp
->id
));
6572 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup location=%p type=%d: not found\n", p
, type
));
6578 /******************************************************************************/
6579 #ifndef WITH_NOIDREF
6584 soap_pointer_enter(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int type
, struct soap_plist
**ppp
)
6585 { register size_t h
;
6586 register struct soap_plist
*pp
;
6587 if (!soap
->pblk
|| soap
->pidx
>= SOAP_PTRBLK
)
6588 { register struct soap_pblk
*pb
= (struct soap_pblk
*)SOAP_MALLOC(soap
, sizeof(struct soap_pblk
));
6590 { soap
->error
= SOAP_EOM
;
6593 pb
->next
= soap
->pblk
;
6597 *ppp
= pp
= &soap
->pblk
->plist
[soap
->pidx
++];
6599 h
= soap_hash_ptr(a
->__ptr
);
6601 h
= soap_hash_ptr(p
);
6602 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));
6603 pp
->next
= soap
->pht
[h
];
6610 pp
->id
= ++soap
->idnum
;
6616 /******************************************************************************/
6617 #ifndef WITH_NOIDREF
6622 soap_array_pointer_lookup(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int type
, struct soap_plist
**ppp
)
6623 { register struct soap_plist
*pp
;
6625 if (!p
|| !a
->__ptr
)
6627 for (pp
= soap
->pht
[soap_hash_ptr(a
->__ptr
)]; pp
; pp
= pp
->next
)
6628 { if (pp
->type
== type
&& pp
->array
&& pp
->array
->__ptr
== a
->__ptr
)
6630 for (i
= 0; i
< n
; i
++)
6631 if (((const int*)&pp
->array
->__size
)[i
] != ((const int*)&a
->__size
)[i
])
6635 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array lookup location=%p type=%d id=%d\n", a
->__ptr
, type
, pp
->id
));
6640 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array lookup location=%p type=%d: not found\n", a
->__ptr
, type
));
6646 /******************************************************************************/
6651 soap_begin_count(struct soap
*soap
)
6652 { soap_free_ns(soap
);
6654 if ((soap
->mode
& SOAP_ENC_DIME
) || (soap
->omode
& SOAP_ENC_DIME
))
6655 soap
->mode
= soap
->omode
| SOAP_IO_LENGTH
| SOAP_ENC_DIME
;
6658 { soap
->mode
= soap
->omode
;
6659 if ((soap
->mode
& SOAP_IO_UDP
))
6660 soap
->mode
|= SOAP_ENC_XML
;
6661 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
6662 || (((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_ENC_XML
))
6664 && !soap
->fpreparesend
6667 soap
->mode
&= ~SOAP_IO_LENGTH
;
6669 soap
->mode
|= SOAP_IO_LENGTH
;
6672 if ((soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
)
6673 { if (!(soap
->mode
& SOAP_ENC_DIME
))
6674 soap
->mode
&= ~SOAP_IO_LENGTH
;
6675 if (soap
->mode
& SOAP_ENC_XML
)
6676 soap
->mode
|= SOAP_IO_BUFFER
;
6678 soap
->mode
|= SOAP_IO_STORE
;
6681 if (!soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
))
6682 soap
->mode
|= SOAP_XML_TREE
;
6684 if ((soap
->mode
& SOAP_ENC_MTOM
) && (soap
->mode
& SOAP_ENC_DIME
))
6685 soap
->mode
|= SOAP_ENC_MIME
;
6686 else if (!(soap
->mode
& SOAP_ENC_MIME
))
6687 soap
->mode
&= ~SOAP_ENC_MTOM
;
6688 if (soap
->mode
& SOAP_ENC_MIME
)
6689 soap_select_mime_boundary(soap
);
6690 soap
->dime
.list
= soap
->dime
.last
; /* keep track of last DIME attachment */
6696 soap
->mustUnderstand
= 0;
6698 soap
->part
= SOAP_BEGIN
;
6700 soap_clr_attr(soap
);
6701 soap_set_local_namespaces(soap
);
6702 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
));
6704 soap
->dime
.count
= 0; /* count # of attachments */
6705 soap
->dime
.size
= 0; /* accumulate total size of attachments */
6706 if (soap
->fprepareinitsend
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
)
6707 return soap
->error
= soap
->fprepareinitsend(soap
);
6713 /******************************************************************************/
6718 soap_end_count(struct soap
*soap
)
6719 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of count phase\n"));
6721 if (soap
->fpreparefinalsend
&& (soap
->mode
& SOAP_IO_LENGTH
))
6722 return soap
->error
= soap
->fpreparefinalsend(soap
);
6728 /******************************************************************************/
6733 soap_begin_send(struct soap
*soap
)
6734 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Initializing for output\n"));
6736 soap
->error
= SOAP_OK
;
6737 soap
->mode
= soap
->omode
| (soap
->mode
& (SOAP_IO_LENGTH
| SOAP_ENC_DIME
));
6739 if ((soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
)
6740 { if (soap
->mode
& SOAP_ENC_XML
)
6741 soap
->mode
|= SOAP_IO_BUFFER
;
6743 soap
->mode
|= SOAP_IO_STORE
;
6747 if ((soap
->mode
& SOAP_IO_UDP
))
6748 { soap
->mode
|= SOAP_ENC_XML
;
6749 if (soap
->count
> SOAP_BUFLEN
)
6750 return soap
->error
= SOAP_UDP_ERROR
;
6753 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
&& soap_valid_socket(soap
->socket
))
6754 { if (soap
->count
|| (soap
->mode
& SOAP_IO_LENGTH
) || (soap
->mode
& SOAP_ENC_XML
))
6755 soap
->mode
|= SOAP_IO_BUFFER
;
6757 soap
->mode
|= SOAP_IO_STORE
;
6759 soap
->mode
&= ~SOAP_IO_LENGTH
;
6760 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
6761 if (soap_new_block(soap
) == NULL
)
6763 if (!(soap
->mode
& SOAP_IO_KEEPALIVE
))
6764 soap
->keep_alive
= 0;
6765 if (!soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
))
6766 soap
->mode
|= SOAP_XML_TREE
;
6768 if ((soap
->mode
& SOAP_ENC_MTOM
) && (soap
->mode
& SOAP_ENC_DIME
))
6769 { soap
->mode
|= SOAP_ENC_MIME
;
6770 soap
->mode
&= ~SOAP_ENC_DIME
;
6772 else if (!(soap
->mode
& SOAP_ENC_MIME
))
6773 soap
->mode
&= ~SOAP_ENC_MTOM
;
6774 if (soap
->mode
& SOAP_ENC_MIME
)
6775 soap_select_mime_boundary(soap
);
6778 #ifndef WITH_FASTCGI
6779 if (!soap_valid_socket(soap
->socket
)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
6781 setmode(soap
->sendfd
, _O_BINARY
);
6783 _setmode(soap
->sendfd
, _O_BINARY
);
6789 if (soap
->mode
& SOAP_IO
)
6793 soap
->chunksize
= 0;
6797 soap
->mustUnderstand
= 0;
6801 soap_clr_attr(soap
);
6802 soap_set_local_namespaces(soap
);
6804 soap
->z_ratio_out
= 1.0;
6805 if ((soap
->mode
& SOAP_ENC_ZLIB
) && soap
->zlib_state
!= SOAP_ZLIB_DEFLATE
)
6807 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
6808 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
6809 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
6811 if (soap
->zlib_out
!= SOAP_ZLIB_DEFLATE
)
6812 { memcpy(soap
->z_buf
, "\37\213\10\0\0\0\0\0\0\377", 10);
6813 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
+ 10;
6814 soap
->d_stream
->avail_out
= SOAP_BUFLEN
- 10;
6815 soap
->z_crc
= crc32(0L, NULL
, 0);
6816 soap
->zlib_out
= SOAP_ZLIB_GZIP
;
6818 *((Byte
*)soap
->z_buf
+ 2) = 0xff;
6819 if (deflateInit2(soap
->d_stream
, soap
->z_level
, Z_DEFLATED
, -MAX_WBITS
, 8, Z_DEFAULT_STRATEGY
) != Z_OK
)
6820 return soap
->error
= SOAP_ZLIB_ERROR
;
6824 if (deflateInit(soap
->d_stream
, soap
->z_level
) != Z_OK
)
6825 return soap
->error
= SOAP_ZLIB_ERROR
;
6827 { if (deflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
6828 return soap
->error
= SOAP_ZLIB_ERROR
;
6830 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflate initialized\n"));
6831 soap
->zlib_state
= SOAP_ZLIB_DEFLATE
;
6838 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap
->socket
, soap
->mode
, (unsigned long)soap
->count
));
6839 soap
->part
= SOAP_BEGIN
;
6841 if (soap
->fprepareinitsend
&& (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
6842 soap
->fprepareinitsend(soap
);
6848 /******************************************************************************/
6849 #ifndef WITH_NOIDREF
6854 soap_embedded(struct soap
*soap
, const void *p
, int t
)
6855 { struct soap_plist
*pp
;
6856 if (soap_pointer_lookup(soap
, p
, t
, &pp
))
6859 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded %p type=%d mark set to 1\n", p
, t
));
6865 /******************************************************************************/
6866 #ifndef WITH_NOIDREF
6871 soap_reference(struct soap
*soap
, const void *p
, int t
)
6872 { struct soap_plist
*pp
;
6873 if (!p
|| (soap
->mode
& SOAP_XML_TREE
))
6875 if (soap_pointer_lookup(soap
, p
, t
, &pp
))
6876 { if (pp
->mark1
== 0)
6881 else if (soap_pointer_enter(soap
, p
, NULL
, 0, t
, &pp
))
6887 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reference %p type=%d (%d %d)\n", p
, t
, (int)pp
->mark1
, (int)pp
->mark2
));
6893 /******************************************************************************/
6894 #ifndef WITH_NOIDREF
6899 soap_array_reference(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int t
)
6901 struct soap_plist
*pp
;
6902 if (!p
|| !a
->__ptr
)
6904 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
6906 { if (pp
->mark1
== 0)
6911 else if (!soap_pointer_enter(soap
, p
, a
, n
, t
, &pp
))
6917 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
));
6923 /******************************************************************************/
6924 #ifndef WITH_NOIDREF
6929 soap_embedded_id(struct soap
*soap
, int id
, const void *p
, int t
)
6930 { struct soap_plist
*pp
= NULL
;
6931 if (soap
->mode
& SOAP_XML_TREE
)
6933 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded_id %p type=%d id=%d\n", p
, t
, id
));
6934 if (soap
->version
== 1 && soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
) && soap
->part
!= SOAP_IN_HEADER
)
6936 { id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
6938 { if (soap
->mode
& SOAP_IO_LENGTH
)
6942 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
));
6949 id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
6950 else if (id
&& !soap_pointer_lookup(soap
, p
, t
, &pp
))
6953 { if (soap
->mode
& SOAP_IO_LENGTH
)
6957 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
));
6964 /******************************************************************************/
6965 #ifndef WITH_NOIDREF
6970 soap_is_embedded(struct soap
*soap
, struct soap_plist
*pp
)
6973 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Is embedded? %d %d\n", (int)pp
->mark1
, (int)pp
->mark2
));
6974 if (soap
->version
== 1 && soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
) && soap
->part
!= SOAP_IN_HEADER
)
6975 { if (soap
->mode
& SOAP_IO_LENGTH
)
6976 return pp
->mark1
!= 0;
6977 return pp
->mark2
!= 0;
6979 if (soap
->mode
& SOAP_IO_LENGTH
)
6980 return pp
->mark1
== 1;
6981 return pp
->mark2
== 1;
6986 /******************************************************************************/
6987 #ifndef WITH_NOIDREF
6992 soap_is_single(struct soap
*soap
, struct soap_plist
*pp
)
6993 { if (soap
->part
== SOAP_IN_HEADER
)
6997 if (soap
->mode
& SOAP_IO_LENGTH
)
6998 return pp
->mark1
== 0;
6999 return pp
->mark2
== 0;
7004 /******************************************************************************/
7005 #ifndef WITH_NOIDREF
7010 soap_set_embedded(struct soap
*soap
, struct soap_plist
*pp
)
7013 if (soap
->mode
& SOAP_IO_LENGTH
)
7021 /******************************************************************************/
7027 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
)
7029 #ifndef WITH_NOIDREF
7030 struct soap_plist
*pp
;
7032 if (!p
|| !a
->__ptr
|| (!aid
&& !atype
))
7033 return soap_element_id(soap
, tag
, id
, p
, a
, n
, type
, t
);
7034 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
));
7035 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
7037 { i
= soap_pointer_enter(soap
, p
, a
, n
, t
, &pp
);
7039 { soap
->error
= SOAP_EOM
;
7046 { sprintf(soap
->tmpbuf
, soap
->dime_id_format
, id
);
7047 aid
= soap_strdup(soap
, soap
->tmpbuf
);
7049 /* Add MTOM xop:Include element when necessary */
7050 /* TODO: this code to be obsoleted with new import/xop.h conventions */
7051 if ((soap
->mode
& SOAP_ENC_MTOM
) && strcmp(tag
, "xop:Include"))
7052 { if (soap_element_begin_out(soap
, tag
, 0, type
)
7053 || soap_element_href(soap
, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid
)
7054 || soap_element_end_out(soap
, tag
))
7057 else if (soap_element_href(soap
, tag
, 0, "href", aid
))
7059 if (soap
->mode
& SOAP_IO_LENGTH
)
7060 { if (pp
->mark1
!= 3)
7061 { struct soap_multipart
*content
;
7062 if (soap
->mode
& SOAP_ENC_MTOM
)
7063 content
= soap_new_multipart(soap
, &soap
->mime
.first
, &soap
->mime
.last
, (char*)a
->__ptr
, a
->__size
);
7065 content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, (char*)a
->__ptr
, a
->__size
);
7067 { soap
->error
= SOAP_EOM
;
7070 if (!strncmp(aid
, "cid:", 4)) /* RFC 2111 */
7071 { if (soap
->mode
& SOAP_ENC_MTOM
)
7072 { char *s
= (char*)soap_malloc(soap
, strlen(aid
) - 1);
7075 strcpy(s
+ 1, aid
+ 4);
7081 content
->id
= aid
+ 4;
7085 content
->type
= atype
;
7086 content
->options
= aoptions
;
7087 content
->encoding
= SOAP_MIME_BINARY
;
7099 /******************************************************************************/
7100 #ifndef WITH_NOIDREF
7103 soap_init_iht(struct soap
*soap
)
7105 for (i
= 0; i
< SOAP_IDHASH
; i
++)
7106 soap
->iht
[i
] = NULL
;
7111 /******************************************************************************/
7112 #ifndef WITH_NOIDREF
7115 soap_free_iht(struct soap
*soap
)
7117 register struct soap_ilist
*ip
= NULL
, *p
= NULL
;
7118 register struct soap_flist
*fp
= NULL
, *fq
= NULL
;
7119 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free ID hashtable\n"));
7120 for (i
= 0; i
< SOAP_IDHASH
; i
++)
7121 { for (ip
= soap
->iht
[i
]; ip
; ip
= p
)
7122 { for (fp
= ip
->flist
; fp
; fp
= fq
)
7124 SOAP_FREE(soap
, fp
);
7127 SOAP_FREE(soap
, ip
);
7129 soap
->iht
[i
] = NULL
;
7135 /******************************************************************************/
7136 #ifndef WITH_NOIDREF
7141 soap_lookup(struct soap
*soap
, const char *id
)
7142 { register struct soap_ilist
*ip
= NULL
;
7143 for (ip
= soap
->iht
[soap_hash(id
)]; ip
; ip
= ip
->next
)
7144 if (!strcmp(ip
->id
, id
))
7151 /******************************************************************************/
7152 #ifndef WITH_NOIDREF
7157 soap_enter(struct soap
*soap
, const char *id
)
7158 { register size_t h
;
7159 register struct soap_ilist
*ip
;
7160 ip
= (struct soap_ilist
*)SOAP_MALLOC(soap
, sizeof(struct soap_ilist
) + strlen(id
));
7162 { h
= soap_hash(id
);
7164 ip
->next
= soap
->iht
[h
];
7172 /******************************************************************************/
7177 soap_malloc(struct soap
*soap
, size_t n
)
7180 return (void*)SOAP_NON_NULL
;
7182 return SOAP_MALLOC(soap
, n
);
7184 p
= (char*)soap
->fmalloc(soap
, n
);
7186 { n
+= sizeof(short);
7187 n
+= (-(long)n
) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
7188 if (!(p
= (char*)SOAP_MALLOC(soap
, n
+ sizeof(void*) + sizeof(size_t))))
7189 { soap
->error
= SOAP_EOM
;
7192 /* set the canary to detect corruption */
7193 *(unsigned short*)(p
+ n
- sizeof(unsigned short)) = (unsigned short)SOAP_CANARY
;
7194 /* keep chain of alloced cells for destruction */
7195 *(void**)(p
+ n
) = soap
->alist
;
7196 *(size_t*)(p
+ n
+ sizeof(void*)) = n
;
7197 soap
->alist
= p
+ n
;
7204 /******************************************************************************/
7205 #ifdef SOAP_MEM_DEBUG
7207 soap_init_mht(struct soap
*soap
)
7209 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
7210 soap
->mht
[i
] = NULL
;
7214 /******************************************************************************/
7215 #ifdef SOAP_MEM_DEBUG
7217 soap_free_mht(struct soap
*soap
)
7219 register struct soap_mlist
*mp
, *mq
;
7220 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
7221 { for (mp
= soap
->mht
[i
]; mp
; mp
= mq
)
7224 fprintf(stderr
, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp
->file
, mp
->line
, mp
->ptr
);
7227 soap
->mht
[i
] = NULL
;
7232 /******************************************************************************/
7233 #ifdef SOAP_MEM_DEBUG
7237 soap_track_malloc(struct soap
*soap
, const char *file
, int line
, size_t size
)
7238 { register void *p
= malloc(size
);
7240 { register size_t h
= soap_hash_ptr(p
);
7241 register struct soap_mlist
*mp
= (struct soap_mlist
*)malloc(sizeof(struct soap_mlist
));
7242 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%s(%d): malloc(%lu) = %p\n", file
, line
, (unsigned long)size
, p
));
7243 mp
->next
= soap
->mht
[h
];
7254 /******************************************************************************/
7255 #ifdef SOAP_MEM_DEBUG
7259 soap_track_free(struct soap
*soap
, const char *file
, int line
, void *p
)
7260 { register size_t h
= soap_hash_ptr(p
);
7261 register struct soap_mlist
*mp
;
7262 for (mp
= soap
->mht
[h
]; mp
; mp
= mp
->next
)
7268 if (soap
->fdebug
[SOAP_INDEX_TEST
])
7269 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%s(%d): free(%p)\n", file
, line
, p
));
7274 fprintf(stderr
, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file
, line
, p
, mp
->file
, mp
->line
);
7277 fprintf(stderr
, "%s(%d): free(%p) pointer not malloced\n", file
, line
, p
);
7281 /******************************************************************************/
7282 #ifdef SOAP_MEM_DEBUG
7284 soap_track_unlink(struct soap
*soap
, const void *p
)
7285 { register size_t h
= soap_hash_ptr(p
);
7286 register struct soap_mlist
*mp
;
7287 for (mp
= soap
->mht
[h
]; mp
; mp
= mp
->next
)
7295 /******************************************************************************/
7300 soap_dealloc(struct soap
*soap
, void *p
)
7301 { if (soap_check_state(soap
))
7304 { register char **q
;
7305 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7307 if (*(unsigned short*)(char*)(*q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7309 #ifdef SOAP_MEM_DEBUG
7310 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7312 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7313 DBGHEX(TEST
, *q
- 200, 200);
7314 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7315 soap
->error
= SOAP_MOE
;
7318 if (p
== (void*)(*q
- *(size_t*)(*q
+ sizeof(void*))))
7319 { *q
= **(char***)q
;
7320 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Freed data at %p\n", p
));
7325 soap_delete(soap
, p
);
7329 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free all soap_malloc() data\n"));
7331 { q
= (char*)soap
->alist
;
7332 if (*(unsigned short*)(char*)(q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7334 #ifdef SOAP_MEM_DEBUG
7335 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7337 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7338 DBGHEX(TEST
, q
- 200, 200);
7339 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7340 soap
->error
= SOAP_MOE
;
7343 soap
->alist
= *(void**)q
;
7344 q
-= *(size_t*)(q
+ sizeof(void*));
7347 /* we must assume these were deallocated: */
7348 soap
->action
= NULL
;
7350 soap
->header
= NULL
;
7351 soap
->userid
= NULL
;
7352 soap
->passwd
= NULL
;
7353 soap
->authrealm
= NULL
;
7354 soap
->http_content
= NULL
;
7356 soap_clr_mime(soap
);
7362 /******************************************************************************/
7367 soap_delete(struct soap
*soap
, void *p
)
7368 { register struct soap_clist
**cp
;
7369 if (soap_check_state(soap
))
7374 { if (p
== (*cp
)->ptr
)
7375 { register struct soap_clist
*q
= *cp
;
7378 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: deletion callback failed for object type %d\n", q
->ptr
, q
->type
));
7379 #ifdef SOAP_MEM_DEBUG
7380 fprintf(stderr
, "new(object type = %d) = %p not freed: deletion callback failed\n", q
->type
, q
->ptr
);
7388 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: address not in list\n", p
));
7392 { register struct soap_clist
*q
= *cp
;
7395 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: deletion callback failed for object type %d\n", q
->ptr
, q
->type
));
7396 #ifdef SOAP_MEM_DEBUG
7397 fprintf(stderr
, "new(object type = %d) = %p not freed: deletion callback failed\n", q
->type
, q
->ptr
);
7403 soap
->fault
= NULL
; /* this was possibly deallocated */
7404 soap
->header
= NULL
; /* this was possibly deallocated */
7408 /******************************************************************************/
7413 soap_delegate_deletion(struct soap
*soap
, struct soap
*soap_to
)
7414 { register struct soap_clist
*cp
;
7416 #ifdef SOAP_MEM_DEBUG
7418 register struct soap_mlist
**mp
, *mq
;
7421 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7423 if (*(unsigned short*)(char*)(*q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7425 #ifdef SOAP_MEM_DEBUG
7426 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7428 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7429 DBGHEX(TEST
, *q
- 200, 200);
7430 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7431 soap
->error
= SOAP_MOE
;
7434 #ifdef SOAP_MEM_DEBUG
7435 p
= (void*)(*q
- *(size_t*)(*q
+ sizeof(void*)));
7436 h
= soap_hash_ptr(p
);
7437 for (mp
= &soap
->mht
[h
]; *mp
; mp
= &(*mp
)->next
)
7438 { if ((*mp
)->ptr
== p
)
7441 mq
->next
= soap_to
->mht
[h
];
7442 soap_to
->mht
[h
] = mq
;
7448 *q
= (char*)soap_to
->alist
;
7449 soap_to
->alist
= soap
->alist
;
7451 cp
= soap_to
->clist
;
7455 cp
->next
= soap
->clist
;
7458 soap_to
->clist
= soap
->clist
;
7463 /******************************************************************************/
7468 soap_link(struct soap
*soap
, void *p
, int t
, int n
, int (*fdelete
)(struct soap_clist
*))
7469 { register struct soap_clist
*cp
;
7470 if ((cp
= (struct soap_clist
*)SOAP_MALLOC(soap
, sizeof(struct soap_clist
))))
7471 { cp
->next
= soap
->clist
;
7475 cp
->fdelete
= fdelete
;
7482 /******************************************************************************/
7487 soap_unlink(struct soap
*soap
, const void *p
)
7488 { register char **q
;
7489 register struct soap_clist
**cp
;
7492 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7493 { if (p
== (void*)(*q
- *(size_t*)(*q
+ sizeof(void*))))
7494 { *q
= **(char***)q
;
7495 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unlinked data %p\n", p
));
7496 #ifdef SOAP_MEM_DEBUG
7497 soap_track_unlink(soap
, p
);
7502 for (cp
= &soap
->clist
; *cp
; cp
= &(*cp
)->next
)
7503 { if (p
== (*cp
)->ptr
)
7504 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unlinked class instance %p\n", p
));
7514 /******************************************************************************/
7515 #ifndef WITH_NOIDREF
7520 soap_lookup_type(struct soap
*soap
, const char *id
)
7521 { register struct soap_ilist
*ip
;
7523 { ip
= soap_lookup(soap
, id
);
7525 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup id='%s' type=%d\n", id
, ip
->type
));
7529 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id
));
7535 /******************************************************************************/
7536 #ifndef WITH_NOIDREF
7541 soap_id_lookup(struct soap
*soap
, const char *id
, void **p
, int t
, size_t n
, unsigned int k
)
7542 { struct soap_ilist
*ip
;
7544 if (!p
|| !id
|| !*id
)
7546 ip
= soap_lookup(soap
, id
); /* lookup pointer to hash table entry for string id */
7548 { if (!(ip
= soap_enter(soap
, id
))) /* new hash table entry for string id */
7550 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id
, t
, p
, (unsigned int)n
));
7561 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id
, t
, ip
->ptr
, (unsigned int)n
));
7563 { strcpy(soap
->id
, id
);
7564 soap
->error
= SOAP_HREF
;
7565 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id
, ip
->type
, t
));
7568 while (ip
->level
< k
)
7569 { q
= (void**)soap_malloc(soap
, sizeof(void*));
7575 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
7579 else if (ip
->level
> k
)
7580 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving level %u pointers to href='%s'\n", ip
->level
, id
));
7581 while (ip
->level
> k
)
7582 { void *s
, **r
= &ip
->link
;
7583 q
= (void**)ip
->link
;
7585 { *r
= (void*)soap_malloc(soap
, sizeof(void*));
7596 ip
->level
= ip
->level
- 1;
7597 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
7599 q
= (void**)ip
->link
;
7604 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id
, t
, p
, (unsigned int)n
));
7605 while (ip
->level
< k
)
7606 { q
= (void**)soap_malloc(soap
, sizeof(void*));
7612 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
7614 q
= (void**)ip
->link
;
7623 /******************************************************************************/
7624 #ifndef WITH_NOIDREF
7629 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))
7630 { struct soap_ilist
*ip
;
7631 if (!p
|| !href
|| !*href
)
7633 ip
= soap_lookup(soap
, href
); /* lookup pointer to hash table entry for string id */
7635 { if (!(ip
= soap_enter(soap
, href
))) /* new hash table entry for string id */
7644 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
));
7646 else if (ip
->type
!= st
|| (ip
->level
== k
&& ip
->size
!= n
))
7647 { 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
));
7648 strcpy(soap
->id
, href
);
7649 soap
->error
= SOAP_HREF
;
7652 if (fcopy
|| n
< sizeof(void*) || *href
!= '#')
7653 { register struct soap_flist
*fp
= (struct soap_flist
*)SOAP_MALLOC(soap
, sizeof(struct soap_flist
));
7655 { soap
->error
= SOAP_EOM
;
7658 fp
->next
= ip
->flist
;
7666 fp
->fcopy
= soap_fcopy
;
7668 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
));
7671 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarding copying address %p for type=%d href='%s'\n", p
, st
, href
));
7672 *(void**)p
= ip
->copy
;
7680 /******************************************************************************/
7685 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*))
7687 #ifndef WITH_NOIDREF
7688 struct soap_ilist
*ip
;
7690 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id
, t
, p
, (unsigned long)n
, k
));
7694 p
= finstantiate(soap
, t
, type
, arrayType
, &n
);
7696 p
= soap_malloc(soap
, n
);
7700 #ifndef WITH_NOIDREF
7704 #ifndef WITH_NOIDREF
7705 ip
= soap_lookup(soap
, id
); /* lookup pointer to hash table entry for string id */
7706 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Lookup entry id='%s for location=%p'\n", id
, p
));
7708 { if (!(ip
= soap_enter(soap
, id
))) /* new hash table entry for string id */
7717 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
));
7719 else if ((ip
->type
!= t
|| (ip
->level
== k
&& ip
->size
!= n
)) && (ip
->copy
|| ip
->flist
))
7720 { 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
));
7721 strcpy(soap
->id
, id
);
7722 soap
->error
= SOAP_HREF
;
7726 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Multiply defined id='%s'\n", id
));
7727 strcpy(soap
->id
, id
);
7728 soap
->error
= SOAP_DUPLICATE_ID
;
7735 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
));
7742 /******************************************************************************/
7747 soap_fcopy(struct soap
*soap
, int st
, int tt
, void *p
, size_t len
, const void *q
, size_t n
)
7748 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st
, tt
, q
, p
, (unsigned long)n
));
7753 /******************************************************************************/
7758 soap_end_send(struct soap
*soap
)
7762 if (soap
->dime
.list
)
7763 { /* SOAP body referenced attachments must appear first */
7764 soap
->dime
.last
->next
= soap
->dime
.first
;
7765 soap
->dime
.first
= soap
->dime
.list
->next
;
7766 soap
->dime
.list
->next
= NULL
;
7767 soap
->dime
.last
= soap
->dime
.list
;
7769 if (!(err
= soap_putdime(soap
)))
7770 err
= soap_putmime(soap
);
7771 soap
->mime
.list
= NULL
;
7772 soap
->mime
.first
= NULL
;
7773 soap
->mime
.last
= NULL
;
7774 soap
->dime
.list
= NULL
;
7775 soap
->dime
.first
= NULL
;
7776 soap
->dime
.last
= NULL
;
7780 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End send\n"));
7781 if (soap
->mode
& SOAP_IO
) /* need to flush the remaining data in buffer */
7782 { if (soap_flush(soap
))
7784 { if (soap
->mode
& SOAP_ENC_ZLIB
&& soap
->zlib_state
== SOAP_ZLIB_DEFLATE
)
7785 { soap
->zlib_state
= SOAP_ZLIB_NONE
;
7786 deflateEnd(soap
->d_stream
);
7794 if (soap
->mode
& SOAP_ENC_ZLIB
)
7796 soap
->d_stream
->avail_in
= 0;
7798 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflating remainder\n"));
7799 r
= deflate(soap
->d_stream
, Z_FINISH
);
7800 if (soap
->d_stream
->avail_out
!= SOAP_BUFLEN
)
7801 { if (soap_flush_raw(soap
, soap
->z_buf
, SOAP_BUFLEN
- soap
->d_stream
->avail_out
))
7802 { soap
->zlib_state
= SOAP_ZLIB_NONE
;
7803 deflateEnd(soap
->d_stream
);
7806 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
7807 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
7809 } while (r
== Z_OK
);
7810 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflated total %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
7811 soap
->z_ratio_out
= (float)soap
->d_stream
->total_out
/ (float)soap
->d_stream
->total_in
;
7812 soap
->mode
&= ~SOAP_ENC_ZLIB
;
7813 soap
->zlib_state
= SOAP_ZLIB_NONE
;
7814 if (deflateEnd(soap
->d_stream
) != Z_OK
|| r
!= Z_STREAM_END
)
7815 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to end deflate: %s\n", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
7816 return soap
->error
= SOAP_ZLIB_ERROR
;
7819 if (soap
->zlib_out
!= SOAP_ZLIB_DEFLATE
)
7820 { soap
->z_buf
[0] = soap
->z_crc
& 0xFF;
7821 soap
->z_buf
[1] = (soap
->z_crc
>> 8) & 0xFF;
7822 soap
->z_buf
[2] = (soap
->z_crc
>> 16) & 0xFF;
7823 soap
->z_buf
[3] = (soap
->z_crc
>> 24) & 0xFF;
7824 soap
->z_buf
[4] = soap
->d_stream
->total_in
& 0xFF;
7825 soap
->z_buf
[5] = (soap
->d_stream
->total_in
>> 8) & 0xFF;
7826 soap
->z_buf
[6] = (soap
->d_stream
->total_in
>> 16) & 0xFF;
7827 soap
->z_buf
[7] = (soap
->d_stream
->total_in
>> 24) & 0xFF;
7828 if (soap_flush_raw(soap
, soap
->z_buf
, 8))
7830 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip crc32=%lu\n", (unsigned long)soap
->z_crc
));
7835 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
7838 if (!(soap
->mode
& SOAP_ENC_XML
))
7840 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending buffered message of length %u\n", (unsigned int)soap
->blist
->size
));
7841 if (soap
->status
>= SOAP_POST
)
7842 soap
->error
= soap
->fpost(soap
, soap
->endpoint
, soap
->host
, soap
->port
, soap
->path
, soap
->action
, soap
->blist
->size
);
7843 else if (soap
->status
!= SOAP_STOP
)
7844 soap
->error
= soap
->fresponse(soap
, soap
->status
, soap
->blist
->size
);
7845 if (soap
->error
|| soap_flush(soap
))
7850 for (p
= soap_first_block(soap
, NULL
); p
; p
= soap_next_block(soap
, NULL
))
7851 { DBGMSG(SENT
, p
, soap_block_size(soap
, NULL
));
7852 if ((soap
->error
= soap
->fsend(soap
, p
, soap_block_size(soap
, NULL
))))
7853 { soap_end_block(soap
, NULL
);
7857 soap_end_block(soap
, NULL
);
7860 else if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
7861 { DBGMSG(SENT
, "\r\n0\r\n\r\n", 7);
7862 if ((soap
->error
= soap
->fsend(soap
, "\r\n0\r\n\r\n", 7)))
7869 if (!soap
->ssl
&& soap_valid_socket(soap
->socket
) && !soap
->keep_alive
&& !(soap
->omode
& SOAP_IO_UDP
))
7870 soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_WR
); /* Send TCP FIN */
7872 if (soap_valid_socket(soap
->socket
) && !soap
->keep_alive
&& !(soap
->omode
& SOAP_IO_UDP
))
7873 soap
->fshutdownsocket(soap
, soap
->socket
, SOAP_SHUT_WR
); /* Send TCP FIN */
7876 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of send phase\n"));
7877 soap
->omode
&= ~SOAP_XML_SEC
;
7879 soap
->part
= SOAP_END
;
7884 /******************************************************************************/
7889 soap_end_recv(struct soap
*soap
)
7890 { soap
->part
= SOAP_END
;
7892 soap
->wsuid
= NULL
; /* reset before next send */
7893 soap
->c14nexclude
= NULL
; /* reset before next send */
7896 if ((soap
->mode
& SOAP_ENC_DIME
) && soap_getdime(soap
))
7897 { soap
->dime
.first
= NULL
;
7898 soap
->dime
.last
= NULL
;
7901 soap
->dime
.list
= soap
->dime
.first
;
7902 soap
->dime
.first
= NULL
;
7903 soap
->dime
.last
= NULL
;
7904 /* Check if MIME attachments and mime-post-check flag is set, if so call soap_resolve() and return */
7905 if (soap
->mode
& SOAP_ENC_MIME
)
7907 if (soap
->mode
& SOAP_MIME_POSTCHECK
)
7908 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Post checking MIME attachments\n"));
7909 if (!soap
->keep_alive
)
7910 soap
->keep_alive
= -1;
7911 #ifndef WITH_NOIDREF
7916 if (soap_getmime(soap
))
7919 soap
->mime
.list
= soap
->mime
.first
;
7920 soap
->mime
.first
= NULL
;
7921 soap
->mime
.last
= NULL
;
7922 soap
->mime
.boundary
= NULL
;
7924 { struct soap_multipart
*content
;
7925 for (content
= soap
->mime
.list
; content
; content
= content
->next
)
7926 soap_resolve_attachment(soap
, content
);
7929 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "End of receive message ok\n"));
7931 if (soap
->mode
& SOAP_ENC_ZLIB
)
7932 { /* Make sure end of compressed content is reached */
7933 while (soap
->d_stream
->next_out
!= Z_NULL
)
7934 if ((int)soap_get1(soap
) == EOF
)
7936 soap
->mode
&= ~SOAP_ENC_ZLIB
;
7937 memcpy(soap
->buf
, soap
->z_buf
, SOAP_BUFLEN
);
7938 soap
->bufidx
= (char*)soap
->d_stream
->next_in
- soap
->z_buf
;
7939 soap
->buflen
= soap
->z_buflen
;
7940 soap
->zlib_state
= SOAP_ZLIB_NONE
;
7941 if (inflateEnd(soap
->d_stream
) != Z_OK
)
7942 return soap
->error
= SOAP_ZLIB_ERROR
;
7943 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Inflate end ok\n"));
7945 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
7948 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Inflate gzip crc check\n"));
7949 for (i
= 0; i
< 8; i
++)
7950 { if ((int)(c
= soap_get1(soap
)) == EOF
)
7951 return soap
->error
= SOAP_EOF
;
7952 soap
->z_buf
[i
] = (char)c
;
7954 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)))
7955 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap
->z_crc
));
7956 return soap
->error
= SOAP_ZLIB_ERROR
;
7958 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)))
7959 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Gzip error: incorrect message length\n"));
7960 return soap
->error
= SOAP_ZLIB_ERROR
;
7963 soap
->zlib_in
= SOAP_ZLIB_NONE
;
7967 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
7968 while ((int)soap_getchar(soap
) != EOF
) /* advance to last chunk */
7970 #ifndef WITH_NOIDREF
7971 if (soap_resolve(soap
))
7976 { if (soap
->mode
& SOAP_ENC_MTOM
)
7977 return soap
->error
= SOAP_MIME_HREF
;
7978 return soap
->error
= SOAP_DIME_HREF
;
7983 if (soap
->fpreparefinalrecv
)
7984 return soap
->error
= soap
->fpreparefinalrecv(soap
);
7990 /******************************************************************************/
7995 soap_free_temp(struct soap
*soap
)
7996 { register struct soap_attribute
*tp
, *tq
;
7997 register struct Namespace
*ns
;
7999 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free any remaining temp blocks\n"));
8001 soap_end_block(soap
, NULL
);
8002 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free attribute storage\n"));
8003 for (tp
= soap
->attributes
; tp
; tp
= tq
)
8006 SOAP_FREE(soap
, tp
->value
);
8007 SOAP_FREE(soap
, tp
);
8009 soap
->attributes
= NULL
;
8012 SOAP_FREE(soap
, soap
->labbuf
);
8013 soap
->labbuf
= NULL
;
8017 ns
= soap
->local_namespaces
;
8019 { for (; ns
->id
; ns
++)
8021 { if (soap
->encodingStyle
== ns
->out
)
8022 soap
->encodingStyle
= SOAP_STR_EOS
;
8023 SOAP_FREE(soap
, ns
->out
);
8026 if (soap
->encodingStyle
== ns
->ns
)
8027 soap
->encodingStyle
= SOAP_STR_EOS
;
8029 SOAP_FREE(soap
, soap
->local_namespaces
);
8030 soap
->local_namespaces
= NULL
;
8034 { struct soap_xlist
*xp
= soap
->xlist
->next
;
8035 SOAP_FREE(soap
, soap
->xlist
);
8039 #ifndef WITH_NOIDREF
8040 soap_free_pht(soap
);
8041 soap_free_iht(soap
);
8046 /******************************************************************************/
8049 soap_free_ns(struct soap
*soap
)
8050 { register struct soap_nlist
*np
, *nq
;
8051 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free namespace stack\n"));
8052 for (np
= soap
->nlist
; np
; np
= nq
)
8054 SOAP_FREE(soap
, np
);
8060 /******************************************************************************/
8062 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8064 soap_init_logs(struct soap
*soap
)
8066 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
8067 { soap
->logfile
[i
] = NULL
;
8068 soap
->fdebug
[i
] = NULL
;
8074 /******************************************************************************/
8075 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8079 soap_open_logfile(struct soap
*soap
, int i
)
8080 { if (soap
->logfile
[i
])
8081 soap
->fdebug
[i
] = fopen(soap
->logfile
[i
], i
< 2 ? "ab" : "a");
8085 /******************************************************************************/
8088 soap_close_logfile(struct soap
*soap
, int i
)
8089 { if (soap
->fdebug
[i
])
8090 { fclose(soap
->fdebug
[i
]);
8091 soap
->fdebug
[i
] = NULL
;
8096 /******************************************************************************/
8101 soap_close_logfiles(struct soap
*soap
)
8103 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
8104 soap_close_logfile(soap
, i
);
8108 /******************************************************************************/
8111 soap_set_logfile(struct soap
*soap
, int i
, const char *logfile
)
8114 soap_close_logfile(soap
, i
);
8115 s
= soap
->logfile
[i
];
8116 soap
->logfile
[i
] = logfile
;
8118 SOAP_FREE(soap
, (void*)s
);
8120 if ((t
= (char*)SOAP_MALLOC(soap
, strlen(logfile
) + 1)))
8122 soap
->logfile
[i
] = t
;
8126 /******************************************************************************/
8131 soap_set_recv_logfile(struct soap
*soap
, const char *logfile
)
8132 { soap_set_logfile(soap
, SOAP_INDEX_RECV
, logfile
);
8136 /******************************************************************************/
8141 soap_set_sent_logfile(struct soap
*soap
, const char *logfile
)
8142 { soap_set_logfile(soap
, SOAP_INDEX_SENT
, logfile
);
8146 /******************************************************************************/
8151 soap_set_test_logfile(struct soap
*soap
, const char *logfile
)
8152 { soap_set_logfile(soap
, SOAP_INDEX_TEST
, logfile
);
8156 /******************************************************************************/
8161 soap_copy(const struct soap
*soap
)
8162 { return soap_copy_context((struct soap
*)malloc(sizeof(struct soap
)), soap
);
8166 /******************************************************************************/
8171 soap_copy_context(struct soap
*copy
, const struct soap
*soap
)
8172 { if (soap_check_state(soap
))
8175 { register struct soap_plugin
*p
= NULL
;
8179 memcpy(copy
, soap
, sizeof(struct soap
));
8181 copy
->state
= SOAP_COPY
;
8182 copy
->error
= SOAP_OK
;
8183 copy
->userid
= NULL
;
8184 copy
->passwd
= NULL
;
8189 copy
->attributes
= NULL
;
8190 copy
->labbuf
= NULL
;
8193 #ifdef SOAP_MEM_DEBUG
8194 soap_init_mht(copy
);
8196 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8197 soap_init_logs(copy
);
8200 soap_set_test_logfile(copy
, soap
->logfile
[SOAP_INDEX_TEST
]);
8201 soap_set_sent_logfile(copy
, soap
->logfile
[SOAP_INDEX_SENT
]);
8202 soap_set_recv_logfile(copy
, soap
->logfile
[SOAP_INDEX_RECV
]);
8204 #ifdef WITH_C_LOCALE
8205 copy
->c_locale
= duplocale(soap
->c_locale
);
8207 copy
->c_locale
= NULL
;
8212 copy
->session
= NULL
;
8215 copy
->session
= NULL
;
8218 copy
->d_stream
= (z_stream
*)SOAP_MALLOC(copy
, sizeof(z_stream
));
8219 copy
->d_stream
->zalloc
= Z_NULL
;
8220 copy
->d_stream
->zfree
= Z_NULL
;
8221 copy
->d_stream
->opaque
= Z_NULL
;
8224 copy
->local_namespaces
= NULL
;
8225 #ifndef WITH_NOIDREF
8226 soap_init_iht(copy
);
8227 soap_init_pht(copy
);
8229 copy
->header
= NULL
;
8231 copy
->action
= NULL
;
8234 copy
->cookies
= soap_copy_cookies(copy
, soap
);
8236 copy
->cookies
= NULL
;
8239 copy
->plugins
= NULL
;
8240 for (p
= soap
->plugins
; p
; p
= p
->next
)
8241 { register struct soap_plugin
*q
= (struct soap_plugin
*)SOAP_MALLOC(copy
, sizeof(struct soap_plugin
));
8244 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copying plugin '%s'\n", p
->id
));
8246 if (p
->fcopy
&& p
->fcopy(copy
, q
, p
))
8247 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not copy plugin '%s'\n", p
->id
));
8251 q
->next
= copy
->plugins
;
8259 /******************************************************************************/
8264 soap_copy_stream(struct soap
*copy
, struct soap
*soap
)
8265 { copy
->mode
= soap
->mode
;
8266 copy
->imode
= soap
->imode
;
8267 copy
->omode
= soap
->omode
;
8268 copy
->socket
= soap
->socket
;
8269 copy
->recv_timeout
= soap
->recv_timeout
;
8270 copy
->send_timeout
= soap
->send_timeout
;
8271 #if defined(__cplusplus) && !defined(WITH_LEAN)
8272 copy
->os
= soap
->os
;
8273 copy
->is
= soap
->is
;
8275 copy
->sendfd
= soap
->sendfd
;
8276 copy
->recvfd
= soap
->recvfd
;
8277 copy
->bufidx
= soap
->bufidx
;
8278 copy
->buflen
= soap
->buflen
;
8279 copy
->ahead
= soap
->ahead
;
8280 copy
->cdata
= soap
->cdata
;
8281 copy
->chunksize
= soap
->chunksize
;
8282 copy
->chunkbuflen
= soap
->chunkbuflen
;
8283 copy
->keep_alive
= soap
->keep_alive
;
8284 copy
->tcp_keep_alive
= soap
->tcp_keep_alive
;
8285 copy
->tcp_keep_idle
= soap
->tcp_keep_idle
;
8286 copy
->tcp_keep_intvl
= soap
->tcp_keep_intvl
;
8287 copy
->tcp_keep_cnt
= soap
->tcp_keep_cnt
;
8288 copy
->max_keep_alive
= soap
->max_keep_alive
;
8290 copy
->peer
= soap
->peer
;
8291 copy
->peerlen
= soap
->peerlen
;
8294 copy
->bio
= soap
->bio
;
8295 copy
->ssl
= soap
->ssl
;
8296 copy
->ctx
= soap
->ctx
;
8299 copy
->session
= soap
->session
; /* TODO: GNUTLS provides a dup? */
8302 copy
->zlib_state
= soap
->zlib_state
;
8303 copy
->zlib_in
= soap
->zlib_in
;
8304 copy
->zlib_out
= soap
->zlib_out
;
8305 copy
->d_stream
= (z_stream
*)SOAP_MALLOC(copy
, sizeof(z_stream
));
8306 memcpy(copy
->d_stream
, soap
->d_stream
, sizeof(z_stream
));
8307 copy
->z_crc
= soap
->z_crc
;
8308 copy
->z_ratio_in
= soap
->z_ratio_in
;
8309 copy
->z_ratio_out
= soap
->z_ratio_out
;
8311 copy
->z_buflen
= soap
->z_buflen
;
8312 copy
->z_level
= soap
->z_level
;
8313 if (soap
->z_buf
&& soap
->zlib_state
!= SOAP_ZLIB_NONE
)
8314 { copy
->z_buf
= (char*)SOAP_MALLOC(copy
, SOAP_BUFLEN
);
8315 memcpy(copy
->z_buf
, soap
->z_buf
, sizeof(soap
->z_buf
));
8317 copy
->z_dict
= soap
->z_dict
;
8318 copy
->z_dict_len
= soap
->z_dict_len
;
8320 memcpy(copy
->buf
, soap
->buf
, sizeof(soap
->buf
));
8324 /******************************************************************************/
8329 soap_free_stream(struct soap
*soap
)
8330 { soap
->socket
= SOAP_INVALID_SOCKET
;
8339 soap
->session
= NULL
; /* TODO: GNUTLS free (when dupped)? */
8340 soap
->dh_params
= NULL
;
8341 soap
->rsa_params
= NULL
;
8345 SOAP_FREE(soap
, soap
->d_stream
);
8346 soap
->d_stream
= NULL
;
8348 SOAP_FREE(soap
, soap
->z_buf
);
8354 /******************************************************************************/
8359 soap_init(struct soap
*soap
)
8360 { soap
->state
= SOAP_INIT
;
8361 #ifdef SOAP_MEM_DEBUG
8362 soap_init_mht(soap
);
8364 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8365 soap_init_logs(soap
);
8368 soap_set_test_logfile(soap
, "TEST.log");
8369 soap_set_sent_logfile(soap
, "SENT.log");
8370 soap_set_recv_logfile(soap
, "RECV.log");
8373 soap_imode(soap
, SOAP_IO_DEFAULT
);
8374 soap_omode(soap
, SOAP_IO_DEFAULT
);
8375 soap
->plugins
= NULL
;
8377 soap
->userid
= NULL
;
8378 soap
->passwd
= NULL
;
8380 soap
->fpost
= http_post
;
8381 soap
->fput
= http_put
;
8382 soap
->fget
= http_get
;
8383 soap
->fdel
= http_405
;
8384 soap
->fopt
= http_405
;
8385 soap
->fhead
= http_405
;
8387 soap
->fposthdr
= http_post_header
;
8388 soap
->fresponse
= http_response
;
8389 soap
->fparse
= http_parse
;
8390 soap
->fparsehdr
= http_parse_header
;
8392 soap
->fheader
= NULL
;
8393 soap
->fconnect
= NULL
;
8394 soap
->fdisconnect
= NULL
;
8396 soap
->ipv6_multicast_if
= 0;
8397 soap
->ipv4_multicast_if
= NULL
;
8399 soap
->fresolve
= tcp_gethost
;
8401 soap
->fresolve
= NULL
;
8403 soap
->faccept
= tcp_accept
;
8404 soap
->fopen
= tcp_connect
;
8405 soap
->fclose
= tcp_disconnect
;
8406 soap
->fclosesocket
= tcp_closesocket
;
8407 soap
->fshutdownsocket
= tcp_shutdownsocket
;
8408 soap
->fsend
= fsend
;
8409 soap
->frecv
= frecv
;
8410 soap
->fpoll
= soap_poll
;
8413 soap
->fclose
= NULL
;
8416 soap
->fseterror
= NULL
;
8417 soap
->fignore
= NULL
;
8418 soap
->fserveloop
= NULL
;
8419 soap
->fplugin
= fplugin
;
8420 soap
->fmalloc
= NULL
;
8422 soap
->fprepareinitsend
= NULL
;
8423 soap
->fprepareinitrecv
= NULL
;
8424 soap
->fpreparesend
= NULL
;
8425 soap
->fpreparerecv
= NULL
;
8426 soap
->fpreparefinalsend
= NULL
;
8427 soap
->fpreparefinalrecv
= NULL
;
8428 soap
->fdimereadopen
= NULL
;
8429 soap
->fdimewriteopen
= NULL
;
8430 soap
->fdimereadclose
= NULL
;
8431 soap
->fdimewriteclose
= NULL
;
8432 soap
->fdimeread
= NULL
;
8433 soap
->fdimewrite
= NULL
;
8434 soap
->fmimereadopen
= NULL
;
8435 soap
->fmimewriteopen
= NULL
;
8436 soap
->fmimereadclose
= NULL
;
8437 soap
->fmimewriteclose
= NULL
;
8438 soap
->fmimeread
= NULL
;
8439 soap
->fmimewrite
= NULL
;
8441 soap
->float_format
= "%.9G"; /* Alternative: use "%G" */
8442 soap
->double_format
= "%.17lG"; /* Alternative: use "%lG" */
8443 soap
->dime_id_format
= "cid:id%d"; /* default DIME id format */
8444 soap
->http_version
= "1.1";
8445 soap
->proxy_http_version
= "1.0";
8446 soap
->http_content
= NULL
;
8449 soap
->keep_alive
= 0;
8450 soap
->tcp_keep_alive
= 0;
8451 soap
->tcp_keep_idle
= 0;
8452 soap
->tcp_keep_intvl
= 0;
8453 soap
->tcp_keep_cnt
= 0;
8454 soap
->max_keep_alive
= SOAP_MAXKEEPALIVE
;
8455 soap
->recv_timeout
= 0;
8456 soap
->send_timeout
= 0;
8457 soap
->connect_timeout
= 0;
8458 soap
->accept_timeout
= 0;
8459 soap
->socket_flags
= 0;
8460 soap
->connect_flags
= 0;
8461 soap
->bind_flags
= 0;
8462 soap
->accept_flags
= 0;
8463 soap
->linger_time
= 0;
8465 soap
->labbuf
= NULL
;
8468 soap
->encodingStyle
= SOAP_STR_EOS
;
8469 #ifndef WITH_NONAMESPACES
8470 soap
->namespaces
= namespaces
;
8472 soap
->namespaces
= NULL
;
8474 soap
->local_namespaces
= NULL
;
8479 soap
->attributes
= NULL
;
8480 soap
->header
= NULL
;
8482 soap
->master
= SOAP_INVALID_SOCKET
;
8483 soap
->socket
= SOAP_INVALID_SOCKET
;
8488 soap
->dime
.list
= NULL
;
8489 soap
->dime
.first
= NULL
;
8490 soap
->dime
.last
= NULL
;
8491 soap
->mime
.list
= NULL
;
8492 soap
->mime
.first
= NULL
;
8493 soap
->mime
.last
= NULL
;
8494 soap
->mime
.boundary
= NULL
;
8495 soap
->mime
.start
= NULL
;
8502 soap
->recvfd
= stdin
;
8503 soap
->sendfd
= stdout
;
8505 soap
->host
[0] = '\0';
8507 soap
->action
= NULL
;
8508 soap
->proxy_host
= NULL
;
8509 soap
->proxy_port
= 8080;
8510 soap
->proxy_userid
= NULL
;
8511 soap
->proxy_passwd
= NULL
;
8512 soap
->authrealm
= NULL
;
8513 soap
->prolog
= NULL
;
8515 soap
->zlib_state
= SOAP_ZLIB_NONE
;
8516 soap
->zlib_in
= SOAP_ZLIB_NONE
;
8517 soap
->zlib_out
= SOAP_ZLIB_NONE
;
8518 soap
->d_stream
= (z_stream
*)SOAP_MALLOC(soap
, sizeof(z_stream
));
8519 soap
->d_stream
->zalloc
= Z_NULL
;
8520 soap
->d_stream
->zfree
= Z_NULL
;
8521 soap
->d_stream
->opaque
= Z_NULL
;
8524 soap
->z_dict
= NULL
;
8525 soap
->z_dict_len
= 0;
8529 soap
->c14nexclude
= NULL
;
8530 soap
->cookies
= NULL
;
8531 soap
->cookie_domain
= NULL
;
8532 soap
->cookie_path
= NULL
;
8533 soap
->cookie_max
= 32;
8536 soap
->rpmreqid
= NULL
;
8541 #ifndef WITH_NOIDREF
8542 soap_init_iht(soap
);
8543 soap_init_pht(soap
);
8546 if (!soap_ssl_init_done
)
8548 soap
->fsslauth
= ssl_auth_init
;
8549 soap
->fsslverify
= ssl_verify_callback
;
8553 soap
->session
= NULL
;
8554 soap
->ssl_flags
= SOAP_SSL_DEFAULT
;
8555 soap
->keyfile
= NULL
;
8556 soap
->password
= NULL
;
8557 soap
->cafile
= NULL
;
8558 soap
->capath
= NULL
;
8559 soap
->crlfile
= NULL
;
8560 soap
->dhfile
= NULL
;
8561 soap
->randfile
= NULL
;
8564 if (!soap_ssl_init_done
)
8566 soap
->fsslauth
= ssl_auth_init
;
8567 soap
->fsslverify
= NULL
;
8571 soap
->session
= NULL
;
8572 soap
->ssl_flags
= SOAP_SSL_DEFAULT
;
8573 soap
->keyfile
= NULL
;
8574 soap
->password
= NULL
;
8575 soap
->cafile
= NULL
;
8576 soap
->capath
= NULL
;
8577 soap
->crlfile
= NULL
;
8578 soap
->dh_params
= NULL
;
8579 soap
->rsa_params
= NULL
;
8581 #ifdef WITH_C_LOCALE
8582 soap
->c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
);
8584 soap
->c_locale
= NULL
;
8589 soap
->dime
.chunksize
= 0;
8590 soap
->dime
.buflen
= 0;
8595 soap
->mustUnderstand
= 0;
8597 soap
->part
= SOAP_END
;
8606 soap
->endpoint
[0] = '\0';
8607 soap
->error
= SOAP_OK
;
8611 /******************************************************************************/
8616 soap_init1(struct soap
*soap
, soap_mode mode
)
8617 { soap_init2(soap
, mode
, mode
);
8621 /******************************************************************************/
8626 soap_init2(struct soap
*soap
, soap_mode imode
, soap_mode omode
)
8628 soap_imode(soap
, imode
);
8629 soap_omode(soap
, omode
);
8633 /******************************************************************************/
8638 soap_begin(struct soap
*soap
)
8639 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reinitializing context\n"));
8640 if (!soap
->keep_alive
)
8644 soap
->keep_alive
= (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) != 0);
8648 soap
->mustUnderstand
= 0;
8651 soap
->part
= SOAP_END
;
8656 soap
->error
= SOAP_OK
;
8661 soap
->endpoint
[0] = '\0';
8663 soap
->dime
.chunksize
= 0;
8664 soap
->dime
.buflen
= 0;
8666 soap_free_temp(soap
);
8670 /******************************************************************************/
8675 soap_end(struct soap
*soap
)
8676 { if (soap_check_state(soap
))
8678 soap_free_temp(soap
);
8679 soap_dealloc(soap
, NULL
);
8681 { register struct soap_clist
*cp
= soap
->clist
->next
;
8682 SOAP_FREE(soap
, soap
->clist
);
8685 soap_closesock(soap
);
8687 soap_close_logfiles(soap
);
8695 /******************************************************************************/
8700 soap_set_namespaces(struct soap
*soap
, const struct Namespace
*p
)
8701 { register struct Namespace
*ns
= soap
->local_namespaces
;
8702 register struct soap_nlist
*np
, *nq
, *nr
;
8703 register unsigned int level
= soap
->level
;
8704 soap
->namespaces
= p
;
8705 soap
->local_namespaces
= NULL
;
8706 soap_set_local_namespaces(soap
);
8707 /* reverse the namespace list */
8720 /* then push on new stack */
8722 { register const char *s
;
8723 soap
->level
= np
->level
; /* preserve element nesting level */
8725 if (!s
&& np
->index
>= 0 && ns
)
8726 { s
= ns
[np
->index
].out
;
8728 s
= ns
[np
->index
].ns
;
8730 if (s
&& soap_push_namespace(soap
, np
->id
, s
) == NULL
)
8734 SOAP_FREE(soap
, nq
);
8738 for (i
= 0; ns
[i
].id
; i
++)
8740 { SOAP_FREE(soap
, ns
[i
].out
);
8744 SOAP_FREE(soap
, ns
);
8746 soap
->level
= level
; /* restore level */
8751 /******************************************************************************/
8756 soap_set_local_namespaces(struct soap
*soap
)
8757 { if (soap
->namespaces
&& !soap
->local_namespaces
)
8758 { register const struct Namespace
*ns1
;
8759 register struct Namespace
*ns2
;
8760 register size_t n
= 1;
8761 for (ns1
= soap
->namespaces
; ns1
->id
; ns1
++)
8763 n
*= sizeof(struct Namespace
);
8764 ns2
= (struct Namespace
*)SOAP_MALLOC(soap
, n
);
8766 { memcpy(ns2
, soap
->namespaces
, n
);
8768 { if (!strcmp(ns2
[0].ns
, soap_env1
))
8773 soap
->local_namespaces
= ns2
;
8779 /******************************************************************************/
8785 soap_tagsearch(const char *big
, const char *little
)
8787 { register size_t n
= strlen(little
);
8788 register const char *s
= big
;
8790 { register const char *t
= s
;
8792 for (i
= 0; i
< n
; i
++, t
++)
8793 { if (*t
!= little
[i
])
8796 if (*t
== '\0' || *t
== ' ')
8797 { if (i
== n
|| (i
&& little
[i
-1] == ':'))
8810 /******************************************************************************/
8816 soap_lookup_ns(struct soap
*soap
, const char *tag
, size_t n
)
8817 { register struct soap_nlist
*np
;
8818 for (np
= soap
->nlist
; np
; np
= np
->next
)
8819 { if (!strncmp(np
->id
, tag
, n
) && !np
->id
[n
])
8827 /******************************************************************************/
8829 static struct soap_nlist
*
8830 soap_push_ns(struct soap
*soap
, const char *id
, const char *ns
, short utilized
)
8831 { register struct soap_nlist
*np
;
8833 if (soap_tagsearch(soap
->c14nexclude
, id
))
8836 { for (np
= soap
->nlist
; np
; np
= np
->next
)
8837 { if (!strcmp(np
->id
, id
) && (!np
->ns
|| !strcmp(np
->ns
, ns
)))
8841 { if ((np
->level
< soap
->level
|| !np
->ns
) && np
->index
== 1)
8847 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap
->level
, id
, ns
?ns
:"(null)", utilized
));
8853 np
= (struct soap_nlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_nlist
) + n
+ k
+ 1);
8855 { soap
->error
= SOAP_EOM
;
8858 np
->next
= soap
->nlist
;
8862 np
->ns
= strcpy(np
->id
+ n
+ 1, ns
);
8865 np
->level
= soap
->level
;
8866 np
->index
= utilized
;
8871 /******************************************************************************/
8874 soap_utilize_ns(struct soap
*soap
, const char *tag
, size_t n
)
8875 { register struct soap_nlist
*np
= soap_lookup_ns(soap
, tag
, n
);
8876 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Utilizing namespace of '%s'\n", tag
));
8878 { if (np
->index
== 0)
8879 soap_push_ns(soap
, np
->id
, np
->ns
, 1);
8881 else if (strncmp(tag
, "xml", 3))
8882 { strncpy(soap
->tmpbuf
, tag
, n
);
8883 soap
->tmpbuf
[n
] = '\0';
8884 soap_push_ns(soap
, soap
->tmpbuf
, NULL
, 1);
8889 /******************************************************************************/
8894 soap_element(struct soap
*soap
, const char *tag
, int id
, const char *type
)
8897 register const char *s
;
8899 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element begin tag='%s' id='%d' type='%s'\n", tag
, id
, type
?type
:SOAP_STR_EOS
));
8902 if (soap
->wsuid
&& soap_tagsearch(soap
->wsuid
, tag
))
8904 for (s
= tag
, i
= 0; *s
&& i
< sizeof(soap
->tag
); s
++, i
++)
8905 soap
->tag
[i
] = *s
== ':' ? '-' : *s
;
8906 soap
->tag
[sizeof(soap
->tag
) - 1] = '\0';
8907 if (soap_set_attr(soap
, "wsu:Id", soap
->tag
, 1))
8911 if (soap
->part
== SOAP_BEGIN_SECURITY
&& (soap
->mode
& SOAP_XML_CANONICAL
) && !(soap
->mode
& SOAP_DOM_ASIS
))
8912 { register struct soap_nlist
*np
;
8913 /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */
8914 for (np
= soap
->nlist
; np
; np
= np
->next
)
8915 { if (np
->index
== 2)
8919 if (soap
->mode
& SOAP_XML_DOM
)
8920 { register struct soap_dom_element
*elt
= (struct soap_dom_element
*)soap_malloc(soap
, sizeof(struct soap_dom_element
));
8925 elt
->prnt
= soap
->dom
;
8926 elt
->name
= soap_strdup(soap
, tag
);
8937 { struct soap_dom_element
*p
= soap
->dom
->elts
;
8944 soap
->dom
->elts
= elt
;
8954 { if (!(soap
->mode
& SOAP_XML_CANONICAL
)
8955 && soap_send(soap
, soap
->prolog
? soap
->prolog
: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
8958 else if (soap
->mode
& SOAP_XML_INDENT
)
8959 { if (soap
->ns
== 1 && soap_send_raw(soap
, soap_indent
, soap
->level
< sizeof(soap_indent
) ? soap
->level
: sizeof(soap_indent
) - 1))
8963 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tag
, ':')))
8964 { struct Namespace
*ns
= soap
->local_namespaces
;
8966 if (soap_send_raw(soap
, "<", 1)
8967 || soap_send(soap
, s
+ 1))
8969 if (soap
->nlist
&& !strncmp(soap
->nlist
->id
, tag
, n
) && !soap
->nlist
->id
[n
])
8971 for (; ns
&& ns
->id
; ns
++)
8972 { if (*ns
->id
&& (ns
->out
|| ns
->ns
) && !strncmp(ns
->id
, tag
, n
) && !ns
->id
[n
])
8973 { soap_push_ns(soap
, ns
->id
, ns
->out
? ns
->out
: ns
->ns
, 0);
8974 if (soap_attribute(soap
, "xmlns", ns
->out
? ns
->out
: ns
->ns
))
8982 if (soap_send_raw(soap
, "<", 1)
8983 || soap_send(soap
, tag
))
8989 { struct Namespace
*ns
;
8992 if ((soap
->mode
& SOAP_XML_DEFAULTNS
))
8993 k
= 4; /* only produce the first four required entries */
8995 for (ns
= soap
->local_namespaces
; ns
&& ns
->id
&& k
; ns
++, k
--)
8996 { if (*ns
->id
&& (ns
->out
|| ns
->ns
))
8997 { sprintf(soap
->tmpbuf
, "xmlns:%s", ns
->id
);
8998 if (soap_attribute(soap
, soap
->tmpbuf
, ns
->out
? ns
->out
: ns
->ns
))
9003 soap
->ns
= 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
9005 if (soap
->mode
& SOAP_XML_CANONICAL
)
9006 { const char *t
= strchr(tag
, ':');
9008 soap_utilize_ns(soap
, tag
, t
- tag
);
9012 { sprintf(soap
->tmpbuf
, "_%d", id
);
9013 if (soap_attribute(soap
, "id", soap
->tmpbuf
))
9016 if (type
&& *type
&& (!(soap
->mode
& SOAP_XML_SEC
) || soap
->part
== SOAP_IN_BODY
))
9017 { if (soap_attribute(soap
, "xsi:type", type
))
9020 if (soap
->mode
& SOAP_XML_CANONICAL
)
9021 { const char *t
= strchr(type
, ':');
9023 soap_utilize_ns(soap
, type
, t
- type
);
9027 if (soap
->null
&& soap
->position
> 0)
9029 sprintf(soap
->tmpbuf
, "[%d", soap
->positions
[0]);
9030 for (i
= 1; i
< soap
->position
; i
++)
9031 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), ",%d", soap
->positions
[i
]);
9032 strcat(soap
->tmpbuf
, "]");
9033 if (soap_attribute(soap
, "SOAP-ENC:position", soap
->tmpbuf
))
9036 if (soap
->mustUnderstand
)
9037 { if (soap
->actor
&& *soap
->actor
)
9038 { if (soap_attribute(soap
, soap
->version
== 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap
->actor
))
9041 if (soap_attribute(soap
, "SOAP-ENV:mustUnderstand", soap
->version
== 2 ? "true" : "1"))
9043 soap
->mustUnderstand
= 0;
9046 { if (soap
->encodingStyle
&& soap
->local_namespaces
)
9047 { if (!*soap
->encodingStyle
)
9048 { if (soap
->local_namespaces
[1].out
)
9049 soap
->encodingStyle
= soap
->local_namespaces
[1].out
;
9051 soap
->encodingStyle
= soap
->local_namespaces
[1].ns
;
9053 if (soap
->encodingStyle
&& soap_attribute(soap
, "SOAP-ENV:encodingStyle", soap
->encodingStyle
))
9060 if (soap
->part
== SOAP_BEGIN_SECURITY
&& (soap
->mode
& SOAP_XML_CANONICAL
))
9061 soap
->part
= SOAP_IN_SECURITY
;
9066 /******************************************************************************/
9071 soap_element_begin_out(struct soap
*soap
, const char *tag
, int id
, const char *type
)
9074 if (soap_element(soap
, tag
, id
, type
))
9076 return soap_element_start_end_out(soap
, NULL
);
9080 /******************************************************************************/
9082 #ifndef HAVE_STRRCHR
9086 soap_strrchr(const char *s
, int t
)
9087 { register char *r
= NULL
;
9096 /******************************************************************************/
9102 soap_strtol(const char *s
, char **t
, int b
)
9103 { register long n
= 0;
9105 while (*s
> 0 && *s
<= 32)
9115 while ((c
= *s
) && c
>= '0' && c
<= '9')
9116 { if (n
>= 214748364 && (n
> 214748364 || c
>= '8'))
9125 else /* assume b == 16 and value is always positive */
9127 { if (c
>= '0' && c
<= '9')
9129 else if (c
>= 'A' && c
<= 'F')
9131 else if (c
>= 'a' && c
<= 'f')
9147 /******************************************************************************/
9149 #ifndef HAVE_STRTOUL
9153 soap_strtoul(const char *s
, char **t
, int b
)
9154 { unsigned long n
= 0;
9156 while (*s
> 0 && *s
<= 32)
9161 while ((c
= *s
) && c
>= '0' && c
<= '9')
9162 { if (n
>= 429496729 && (n
> 429496729 || c
>= '6'))
9171 { if (c
>= '0' && c
<= '9')
9173 else if (c
>= 'A' && c
<= 'F')
9175 else if (c
>= 'a' && c
<= 'f')
9191 /******************************************************************************/
9196 soap_array_begin_out(struct soap
*soap
, const char *tag
, int id
, const char *type
, const char *offset
)
9197 { if (!type
|| !*type
)
9198 return soap_element_begin_out(soap
, tag
, id
, NULL
);
9199 if (soap_element(soap
, tag
, id
, "SOAP-ENC:Array"))
9201 if (soap
->version
== 2)
9203 s
= soap_strrchr(type
, '[');
9204 if ((size_t)(s
- type
) < sizeof(soap
->tmpbuf
))
9205 { strncpy(soap
->tmpbuf
, type
, s
- type
);
9206 soap
->tmpbuf
[s
- type
] = '\0';
9207 if (soap_attribute(soap
, "SOAP-ENC:itemType", soap
->tmpbuf
))
9209 if (s
&& (soap_attribute(soap
, "SOAP-ENC:arraySize", s
+ 1)))
9214 { if (offset
&& soap_attribute(soap
, "SOAP-ENC:offset", offset
))
9216 if (soap_attribute(soap
, "SOAP-ENC:arrayType", type
))
9220 if ((soap
->mode
& SOAP_XML_CANONICAL
))
9221 { const char *s
= strchr(type
, ':');
9223 soap_utilize_ns(soap
, type
, s
- type
);
9226 return soap_element_start_end_out(soap
, NULL
);
9230 /******************************************************************************/
9235 soap_element_start_end_out(struct soap
*soap
, const char *tag
)
9236 { register struct soap_attribute
*tp
;
9238 if (soap
->mode
& SOAP_XML_CANONICAL
)
9239 { struct soap_nlist
*np
;
9240 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9241 { if (tp
->visible
&& tp
->name
)
9242 { const char *s
= strchr(tp
->name
, ':');
9244 soap_utilize_ns(soap
, tp
->name
, s
- tp
->name
);
9247 for (np
= soap
->nlist
; np
; np
= np
->next
)
9248 { if (np
->index
== 1 && np
->ns
)
9249 { sprintf(soap
->tmpbuf
, "xmlns:%s", np
->id
);
9250 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Enabling utilized binding (level=%u) %s='%s'\n", np
->level
, soap
->tmpbuf
, np
->ns
));
9251 soap_set_attr(soap
, soap
->tmpbuf
, np
->ns
, 1);
9258 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9259 { register struct soap_dom_attribute
**att
;
9260 att
= &soap
->dom
->atts
;
9261 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9263 { *att
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
9266 (*att
)->next
= NULL
;
9267 (*att
)->nstr
= NULL
;
9268 (*att
)->name
= soap_strdup(soap
, tp
->name
);
9269 (*att
)->data
= soap_strdup(soap
, tp
->value
);
9270 (*att
)->wide
= NULL
;
9271 (*att
)->soap
= soap
;
9272 att
= &(*att
)->next
;
9279 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9284 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tp
->name
, ':')))
9285 { size_t n
= s
- tp
->name
;
9286 if (soap
->nlist
&& !strncmp(soap
->nlist
->id
, tp
->name
, n
) && !soap
->nlist
->id
[n
])
9290 if (soap_send(soap
, " ") || soap_send(soap
, s
))
9295 if (soap_send(soap
, " ") || soap_send(soap
, tp
->name
))
9297 if (tp
->visible
== 2 && tp
->value
)
9298 if (soap_send_raw(soap
, "=\"", 2)
9299 || soap_string_out(soap
, tp
->value
, tp
->flag
)
9300 || soap_send_raw(soap
, "\"", 1))
9308 if (soap
->mode
& SOAP_XML_CANONICAL
)
9309 { if (soap_send_raw(soap
, ">", 1)
9310 || soap_element_end_out(soap
, tag
))
9315 soap
->level
--; /* decrement level just before /> */
9316 return soap_send_raw(soap
, "/>", 2);
9318 return soap_send_raw(soap
, ">", 1);
9322 /******************************************************************************/
9327 soap_element_end_out(struct soap
*soap
, const char *tag
)
9334 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element ending tag='%s'\n", tag
));
9336 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9337 { if (soap
->dom
->prnt
)
9338 soap
->dom
= soap
->dom
->prnt
;
9343 if (soap
->mode
& SOAP_XML_CANONICAL
)
9344 soap_pop_namespace(soap
);
9345 if (soap
->mode
& SOAP_XML_INDENT
)
9347 { if (soap_send_raw(soap
, soap_indent
, soap
->level
< sizeof(soap_indent
) ? soap
->level
: sizeof(soap_indent
) - 1))
9352 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tag
, ':')))
9353 { soap_pop_namespace(soap
);
9357 if (soap_send_raw(soap
, "</", 2)
9358 || soap_send(soap
, tag
))
9360 soap
->level
--; /* decrement level just before > */
9361 return soap_send_raw(soap
, ">", 1);
9365 /******************************************************************************/
9370 soap_element_ref(struct soap
*soap
, const char *tag
, int id
, int href
)
9371 { register int n
= 0;
9372 const char *s
= "href";
9373 if (soap
->version
== 2)
9374 { s
= "SOAP-ENC:ref";
9377 sprintf(soap
->href
, "#_%d", href
);
9378 return soap_element_href(soap
, tag
, id
, s
, soap
->href
+ n
);
9382 /******************************************************************************/
9387 soap_element_href(struct soap
*soap
, const char *tag
, int id
, const char *ref
, const char *val
)
9388 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element '%s' reference %s='%s'\n", tag
, ref
, val
));
9389 if (soap_element(soap
, tag
, id
, NULL
)
9390 || soap_attribute(soap
, ref
, val
)
9391 || soap_element_start_end_out(soap
, tag
))
9397 /******************************************************************************/
9402 soap_element_null(struct soap
*soap
, const char *tag
, int id
, const char *type
)
9403 { struct soap_attribute
*tp
= NULL
;
9404 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9407 if (tp
|| (soap
->version
== 2 && soap
->position
> 0) || id
> 0 || (soap
->mode
& SOAP_XML_NIL
))
9408 { if (soap_element(soap
, tag
, id
, type
)
9409 || (!tp
&& soap_attribute(soap
, "xsi:nil", "true")))
9411 return soap_element_start_end_out(soap
, tag
);
9415 soap
->mustUnderstand
= 0;
9420 /******************************************************************************/
9425 soap_element_nil(struct soap
*soap
, const char *tag
)
9426 { if (soap_element(soap
, tag
, -1, NULL
)
9427 || soap_attribute(soap
, "xsi:nil", "true"))
9429 return soap_element_start_end_out(soap
, tag
);
9433 /******************************************************************************/
9438 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
)
9440 { soap_element_null(soap
, tag
, id
, type
);
9443 #ifndef WITH_NOIDREF
9444 if (soap
->mode
& SOAP_XML_TREE
)
9447 { struct soap_plist
*pp
;
9449 id
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
9451 id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
9453 { if (soap_is_embedded(soap
, pp
))
9454 { soap_element_ref(soap
, tag
, 0, id
);
9457 if (soap_is_single(soap
, pp
))
9459 soap_set_embedded(soap
, pp
);
9469 /******************************************************************************/
9474 soap_element_result(struct soap
*soap
, const char *tag
)
9475 { if (soap
->version
== 2 && soap
->encodingStyle
)
9476 { if (soap_element(soap
, "SOAP-RPC:result", 0, NULL
)
9477 || soap_attribute(soap
, "xmlns:SOAP-RPC", soap_rpc
)
9478 || soap_element_start_end_out(soap
, NULL
)
9479 || soap_string_out(soap
, tag
, 0)
9480 || soap_element_end_out(soap
, "SOAP-RPC:result"))
9487 /******************************************************************************/
9492 soap_check_result(struct soap
*soap
, const char *tag
)
9493 { if (soap
->version
== 2 && soap
->encodingStyle
)
9494 { soap_instring(soap
, ":result", NULL
, NULL
, 0, 2, -1, -1);
9495 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
9500 /******************************************************************************/
9505 soap_attribute(struct soap
*soap
, const char *name
, const char *value
)
9507 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Attribute '%s'='%s'\n", name
, value
));
9509 if ((soap
->mode
& SOAP_XML_DOM
) && !(soap
->mode
& SOAP_XML_CANONICAL
) && soap
->dom
)
9510 { register struct soap_dom_attribute
*a
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
9513 a
->next
= soap
->dom
->atts
;
9515 a
->name
= soap_strdup(soap
, name
);
9516 a
->data
= soap_strdup(soap
, value
);
9519 soap
->dom
->atts
= a
;
9524 if (soap
->mode
& SOAP_XML_CANONICAL
)
9525 { /* TODO: consider using this code to handle default namespace bindings
9526 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
9527 { if (name[5] == ':')
9528 soap_push_ns(soap, name + 6, value, 0);
9530 soap_push_ns(soap, "", value, 0);
9533 if (!strncmp(name
, "xmlns:", 6))
9534 soap_push_ns(soap
, name
+ 6, value
, 0);
9535 else if (soap_set_attr(soap
, name
, value
, 1))
9540 { if (soap_send(soap
, " ") || soap_send(soap
, name
))
9543 if (soap_send_raw(soap
, "=\"", 2)
9544 || soap_string_out(soap
, value
, 1)
9545 || soap_send_raw(soap
, "\"", 1))
9552 /******************************************************************************/
9557 soap_element_begin_in(struct soap
*soap
, const char *tag
, int nillable
, const char *type
)
9558 { if (!soap_peek_element(soap
))
9560 return soap
->error
= SOAP_TAG_MISMATCH
;
9561 if (tag
&& *tag
== '-')
9563 if (!(soap
->error
= soap_match_tag(soap
, soap
->tag
, tag
)))
9565 if (type
&& *soap
->type
&& soap_match_tag(soap
, soap
->type
, type
))
9566 return soap
->error
= SOAP_TYPE
;
9567 if (!nillable
&& soap
->null
&& (soap
->mode
& SOAP_XML_STRICT
))
9568 return soap
->error
= SOAP_NULL
;
9571 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Begin element found (level=%u) '%s'='%s'\n", soap
->level
, soap
->tag
, tag
?tag
:SOAP_STR_EOS
));
9574 else if (soap
->error
== SOAP_NO_TAG
&& tag
&& *tag
== '-')
9575 soap
->error
= SOAP_OK
;
9580 /******************************************************************************/
9585 soap_element_end_in(struct soap
*soap
, const char *tag
)
9586 { register soap_wchar c
;
9589 if (tag
&& *tag
== '-')
9591 if (soap
->error
== SOAP_NO_TAG
)
9592 soap
->error
= SOAP_OK
;
9594 /* this whitespace or mixed content is significant for DOM */
9595 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9596 { if (!soap
->peeked
&& !soap_string_in(soap
, 3, -1, -1))
9598 if (soap
->dom
->prnt
)
9599 soap
->dom
= soap
->dom
->prnt
;
9608 { while (((c
= soap_get(soap
)) != SOAP_TT
))
9609 { if ((int)c
== EOF
)
9610 return soap
->error
= SOAP_EOF
;
9614 { c
= soap_get(soap
);
9618 soap_unget(soap
, c
);
9623 n
= sizeof(soap
->tag
);
9624 while (soap_notblank(c
= soap_get(soap
)))
9630 return soap
->error
= SOAP_EOF
;
9631 while (soap_blank(c
))
9634 return soap
->error
= SOAP_SYNTAX_ERROR
;
9635 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End element found (level=%u) '%s'='%s'\n", soap
->level
, soap
->tag
, tag
?tag
:SOAP_STR_EOS
));
9637 if (tag
&& (soap
->mode
& SOAP_XML_STRICT
))
9638 { soap_pop_namespace(soap
);
9639 if (soap_match_tag(soap
, soap
->tag
, tag
))
9640 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End element tag name does not match\n"));
9641 return soap
->error
= SOAP_SYNTAX_ERROR
;
9650 /******************************************************************************/
9655 soap_attr_value(struct soap
*soap
, const char *name
, int flag
)
9656 { register struct soap_attribute
*tp
;
9658 return SOAP_STR_EOS
;
9659 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9660 { if (tp
->visible
&& !soap_match_tag(soap
, tp
->name
, name
))
9664 { if (flag
== 2 && (soap
->mode
& SOAP_XML_STRICT
))
9665 soap
->error
= SOAP_PROHIBITED
;
9669 else if (flag
== 1 && (soap
->mode
& SOAP_XML_STRICT
))
9670 soap
->error
= SOAP_REQUIRED
;
9672 soap
->error
= SOAP_OK
;
9677 /******************************************************************************/
9682 soap_set_attr(struct soap
*soap
, const char *name
, const char *value
, int flag
)
9683 { register struct soap_attribute
*tp
;
9686 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set attribute %s='%s'\n", name
, value
?value
:SOAP_STR_EOS
));
9687 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9688 { if (!strcmp(tp
->name
, name
))
9692 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Allocate attribute %s\n", name
));
9693 if (!(tp
= (struct soap_attribute
*)SOAP_MALLOC(soap
, sizeof(struct soap_attribute
) + strlen(name
))))
9694 return soap
->error
= SOAP_EOM
;
9697 if ((soap
->mode
& SOAP_XML_CANONICAL
))
9698 { struct soap_attribute
**tpp
= &soap
->attributes
;
9699 const char *s
= strchr(name
, ':');
9700 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inserting attribute %s for c14n\n", name
))
9701 if (!strncmp(name
, "xmlns", 5))
9702 { for (; *tpp
; tpp
= &(*tpp
)->next
)
9703 if (strncmp((*tpp
)->name
, "xmlns", 5) || strcmp((*tpp
)->name
+ 5, name
+ 5) > 0)
9707 { for (; *tpp
; tpp
= &(*tpp
)->next
)
9708 if (strncmp((*tpp
)->name
, "xmlns", 5) && ((*tpp
)->ns
|| strcmp((*tpp
)->name
, name
) > 0))
9713 for (; *tpp
; tpp
= &(*tpp
)->next
)
9714 { if (!strncmp((*tpp
)->name
, "xmlns:", 6) && !strncmp((*tpp
)->name
+ 6, name
, s
- name
) && !(*tpp
)->name
[6 + s
- name
])
9716 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Canonicalization: prefix %s=%p (%s)\n", name
, (*tpp
)->ns
, (*tpp
)->ns
));
9717 tp
->ns
= (*tpp
)->ns
;
9720 else if (strncmp((*tpp
)->name
, "xmlns", 5) && (*tpp
)->ns
&& tp
->ns
&& ((k
= strcmp((*tpp
)->ns
, tp
->ns
)) > 0 || (!k
&& strcmp((*tpp
)->name
, name
) > 0)))
9729 { tp
->next
= soap
->attributes
;
9730 soap
->attributes
= tp
;
9732 strcpy(tp
->name
, name
);
9735 else if (tp
->visible
)
9738 else if (value
&& tp
->value
&& tp
->size
<= strlen(value
))
9739 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free attribute value of %s (free %p)\n", name
, tp
->value
));
9740 SOAP_FREE(soap
, tp
->value
);
9746 { tp
->size
= strlen(value
) + 1;
9747 if (!(tp
->value
= (char*)SOAP_MALLOC(soap
, tp
->size
)))
9748 return soap
->error
= SOAP_EOM
;
9749 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Allocate attribute value for %s (%p)\n", tp
->name
, tp
->value
));
9751 strcpy(tp
->value
, value
);
9752 if (!strncmp(tp
->name
, "xmlns:", 6))
9757 if (soap
->part
!= SOAP_IN_SECURITY
&& !strcmp(name
, "wsu:Id"))
9758 { soap
->part
= SOAP_BEGIN_SECURITY
;
9759 strncpy(soap
->id
, value
, sizeof(soap
->id
));
9760 soap
->id
[sizeof(soap
->id
)-1] = '\0';
9770 /******************************************************************************/
9775 soap_clr_attr(struct soap
*soap
)
9776 { register struct soap_attribute
*tp
;
9778 if ((soap
->mode
& SOAP_XML_CANONICAL
))
9779 { while (soap
->attributes
)
9780 { tp
= soap
->attributes
->next
;
9781 if (soap
->attributes
->value
)
9782 SOAP_FREE(soap
, soap
->attributes
->value
);
9783 SOAP_FREE(soap
, soap
->attributes
);
9784 soap
->attributes
= tp
;
9789 { for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9795 /******************************************************************************/
9798 soap_getattrval(struct soap
*soap
, char *s
, size_t n
, soap_wchar d
)
9799 { register size_t i
;
9800 for (i
= 0; i
< n
; i
++)
9801 { register soap_wchar c
= soap_get(soap
);
9806 soap_unget(soap
, '/');
9813 { soap_unget(soap
, c
);
9839 { soap_unget(soap
, c
);
9845 return soap
->error
= SOAP_EOF
;
9849 return soap
->error
= SOAP_EOM
;
9853 /******************************************************************************/
9859 soap_store_lab(struct soap
*soap
, const char *s
, size_t n
)
9861 return soap_append_lab(soap
, s
, n
);
9866 /******************************************************************************/
9872 soap_append_lab(struct soap
*soap
, const char *s
, size_t n
)
9873 { if (soap
->labidx
+ n
>= soap
->lablen
)
9874 { register char *t
= soap
->labbuf
;
9875 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap
->lablen
));
9876 if (soap
->lablen
== 0)
9877 soap
->lablen
= SOAP_LABLEN
;
9878 while (soap
->labidx
+ n
>= soap
->lablen
)
9880 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, ", new size=%lu\n", (unsigned long)soap
->lablen
));
9881 soap
->labbuf
= (char*)SOAP_MALLOC(soap
, soap
->lablen
);
9885 return soap
->error
= SOAP_EOM
;
9888 { memcpy(soap
->labbuf
, t
, soap
->labidx
);
9893 { memcpy(soap
->labbuf
+ soap
->labidx
, s
, n
);
9901 /******************************************************************************/
9906 soap_peek_element(struct soap
*soap
)
9909 register struct soap_dom_attribute
**att
= NULL
;
9910 register char *lead
= NULL
;
9912 register struct soap_attribute
*tp
, *tq
= NULL
;
9913 register const char *t
;
9915 register soap_wchar c
;
9919 return soap
->error
= SOAP_NO_TAG
;
9924 soap
->href
[0] = '\0';
9925 soap
->type
[0] = '\0';
9926 soap
->arrayType
[0] = '\0';
9927 soap
->arraySize
[0] = '\0';
9928 soap
->arrayOffset
[0] = '\0';
9933 soap
->mustUnderstand
= 0;
9935 if ((c
= soap_getchar(soap
)) != 0xEF || (c
= soap_get1(soap
)) != 0xBB || (c
= soap_get1(soap
)) != 0xBF)
9936 soap_unget(soap
, c
);
9939 /* whitespace leading to tag is not insignificant for DOM */
9943 { if (soap_append_lab(soap
, NULL
, 0))
9945 s
= soap
->labbuf
+ soap
->labidx
;
9946 i
= soap
->lablen
- soap
->labidx
;
9947 soap
->labidx
= soap
->lablen
;
9948 while (soap_blank(c
) && i
--)
9953 while (soap_blank(c
));
9955 lead
= soap
->labbuf
;
9959 while (soap_blank(c
))
9963 { *soap
->tag
= '\0';
9965 return soap
->error
= SOAP_EOF
;
9966 soap_unget(soap
, c
);
9968 /* whitespace leading to end tag is significant for DOM */
9969 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9970 { if (lead
&& *lead
)
9971 soap
->dom
->tail
= soap_strdup(soap
, lead
);
9973 soap
->dom
->tail
= (char*)SOAP_STR_EOS
;
9976 return soap
->error
= SOAP_NO_TAG
;
9979 do c
= soap_get1(soap
);
9980 while (soap_blank(c
));
9981 i
= sizeof(soap
->tag
);
9982 while (c
!= '>' && c
!= '/' && soap_notblank(c
) && (int)c
!= EOF
)
9985 c
= soap_get1(soap
);
9987 while (soap_blank(c
))
9988 c
= soap_get1(soap
);
9991 if (soap
->mode
& SOAP_XML_DOM
)
9992 { register struct soap_dom_element
*elt
;
9993 elt
= (struct soap_dom_element
*)soap_malloc(soap
, sizeof(struct soap_dom_element
));
9998 elt
->name
= soap_strdup(soap
, soap
->tag
);
9999 elt
->prnt
= soap
->dom
;
10006 elt
->head
= soap_strdup(soap
, lead
);
10010 { struct soap_dom_element
*p
= soap
->dom
->elts
;
10017 soap
->dom
->elts
= elt
;
10023 soap_pop_namespace(soap
);
10024 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10026 while ((int)c
!= EOF
&& c
!= '>' && c
!= '/')
10027 { s
= soap
->tmpbuf
;
10028 i
= sizeof(soap
->tmpbuf
);
10029 while (c
!= '=' && c
!= '>' && c
!= '/' && soap_notblank(c
) && (int)c
!= EOF
)
10032 c
= soap_get1(soap
);
10035 if (i
== sizeof(soap
->tmpbuf
))
10036 return soap
->error
= SOAP_SYNTAX_ERROR
;
10038 /* add attribute name to dom */
10040 { *att
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
10042 return soap
->error
;
10043 (*att
)->next
= NULL
;
10044 (*att
)->nstr
= NULL
;
10045 (*att
)->name
= soap_strdup(soap
, soap
->tmpbuf
);
10046 (*att
)->data
= NULL
;
10047 (*att
)->wide
= NULL
;
10048 (*att
)->soap
= soap
;
10051 if (!strncmp(soap
->tmpbuf
, "xmlns", 5))
10052 { if (soap
->tmpbuf
[5] == ':')
10053 t
= soap
->tmpbuf
+ 6;
10054 else if (soap
->tmpbuf
[5])
10062 for (tp
= soap
->attributes
; tp
; tq
= tp
, tp
= tp
->next
)
10063 { if (!SOAP_STRCMP(tp
->name
, soap
->tmpbuf
))
10067 { tp
= (struct soap_attribute
*)SOAP_MALLOC(soap
, sizeof(struct soap_attribute
) + strlen(soap
->tmpbuf
));
10069 return soap
->error
= SOAP_EOM
;
10070 strcpy(tp
->name
, soap
->tmpbuf
);
10073 /* if attribute name is qualified, append it to the end of the list */
10074 if (tq
&& strchr(soap
->tmpbuf
, ':'))
10079 { tp
->next
= soap
->attributes
;
10080 soap
->attributes
= tp
;
10083 while (soap_blank(c
))
10084 c
= soap_get1(soap
);
10086 { do c
= soap_getutf8(soap
);
10087 while (soap_blank(c
));
10088 if (c
!= SOAP_QT
&& c
!= SOAP_AP
)
10089 { soap_unget(soap
, c
);
10090 c
= ' '; /* blank delimiter */
10092 if (soap_getattrval(soap
, tp
->value
, tp
->size
, c
))
10095 if (soap
->error
!= SOAP_EOM
)
10096 return soap
->error
;
10097 soap
->error
= SOAP_OK
;
10098 if (soap_store_lab(soap
, tp
->value
, tp
->size
))
10099 return soap
->error
;
10101 SOAP_FREE(soap
, tp
->value
);
10103 { if (soap_getattrval(soap
, soap
->labbuf
+ soap
->labidx
, soap
->lablen
- soap
->labidx
, c
))
10104 { if (soap
->error
!= SOAP_EOM
)
10105 return soap
->error
;
10106 soap
->error
= SOAP_OK
;
10107 soap
->labidx
= soap
->lablen
;
10108 if (soap_append_lab(soap
, NULL
, 0))
10109 return soap
->error
;
10115 tp
->size
= soap
->lablen
;
10117 { tp
->size
= strlen(soap
->labbuf
) + 1;
10118 if (tp
->size
< SOAP_LABLEN
)
10119 tp
->size
= SOAP_LABLEN
;
10121 if (!(tp
->value
= (char*)SOAP_MALLOC(soap
, tp
->size
)))
10122 return soap
->error
= SOAP_EOM
;
10123 strcpy(tp
->value
, soap
->labbuf
);
10126 if (soap
->error
!= SOAP_EOM
)
10127 return soap
->error
;
10128 soap
->error
= SOAP_OK
;
10129 if (soap_new_block(soap
) == NULL
)
10130 return soap
->error
;
10132 { if (!(s
= (char*)soap_push_block(soap
, NULL
, SOAP_BLKLEN
)))
10133 return soap
->error
;
10134 if (soap_getattrval(soap
, s
, SOAP_BLKLEN
, c
))
10135 { if (soap
->error
!= SOAP_EOM
)
10136 return soap
->error
;
10137 soap
->error
= SOAP_OK
;
10142 n
= tp
->size
+ soap
->blist
->size
;
10143 if (!(s
= (char*)SOAP_MALLOC(soap
, n
)))
10144 return soap
->error
= SOAP_EOM
;
10146 { memcpy(s
, tp
->value
, tp
->size
);
10147 SOAP_FREE(soap
, tp
->value
);
10149 soap_save_block(soap
, NULL
, s
+ tp
->size
, 0);
10154 do c
= soap_get1(soap
);
10155 while (soap_blank(c
));
10156 tp
->visible
= 2; /* seen this attribute w/ value */
10159 (*att
)->data
= soap_strdup(soap
, tp
->value
);
10163 tp
->visible
= 1; /* seen this attribute w/o value */
10166 att
= &(*att
)->next
;
10168 if (t
&& tp
->value
)
10169 { if (soap_push_namespace(soap
, t
, tp
->value
) == NULL
)
10170 return soap
->error
;
10175 { soap
->dom
->nstr
= soap_current_namespace(soap
, soap
->tag
);
10176 for (att
= &soap
->dom
->atts
; *att
; att
= &(*att
)->next
)
10177 (*att
)->nstr
= soap_current_namespace(soap
, (*att
)->name
);
10181 return soap
->error
= SOAP_EOF
;
10182 if (!(soap
->body
= (c
!= '/')))
10183 do c
= soap_get1(soap
);
10184 while (soap_blank(c
));
10186 if (soap
->mode
& SOAP_XML_DOM
)
10187 { if (!soap
->body
&& soap
->dom
->prnt
)
10188 soap
->dom
= soap
->dom
->prnt
;
10191 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10192 { if (tp
->visible
&& tp
->value
)
10194 #ifndef WITH_NOIDREF
10195 if (!strcmp(tp
->name
, "id"))
10196 { if ((soap
->version
> 0 && !(soap
->mode
& SOAP_XML_TREE
))
10197 || (soap
->mode
& SOAP_XML_GRAPH
))
10199 strncpy(soap
->id
+ 1, tp
->value
, sizeof(soap
->id
) - 2);
10200 soap
->id
[sizeof(soap
->id
)-1] = '\0';
10203 else if (!strcmp(tp
->name
, "href"))
10204 { if (soap
->version
== 1
10205 || (soap
->mode
& SOAP_XML_GRAPH
)
10206 || (soap
->mode
& SOAP_ENC_MTOM
)
10207 || (soap
->mode
& SOAP_ENC_DIME
))
10208 { strncpy(soap
->href
, tp
->value
, sizeof(soap
->href
) - 1);
10209 soap
->href
[sizeof(soap
->href
)-1] = '\0';
10214 if (!soap_match_tag(soap
, tp
->name
, "xsi:type"))
10215 { strncpy(soap
->type
, tp
->value
, sizeof(soap
->type
) - 1);
10216 soap
->type
[sizeof(soap
->type
)-1] = '\0';
10218 else if ((!soap_match_tag(soap
, tp
->name
, "xsi:null")
10219 || !soap_match_tag(soap
, tp
->name
, "xsi:nil"))
10220 && (!strcmp(tp
->value
, "1")
10221 || !strcmp(tp
->value
, "true")))
10224 else if (soap
->version
== 1)
10225 { if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:arrayType"))
10226 { s
= soap_strrchr(tp
->value
, '[');
10227 if (s
&& (size_t)(s
- tp
->value
) < sizeof(soap
->arrayType
))
10228 { strncpy(soap
->arrayType
, tp
->value
, s
- tp
->value
);
10229 soap
->arrayType
[s
- tp
->value
] = '\0';
10230 strncpy(soap
->arraySize
, s
, sizeof(soap
->arraySize
) - 1);
10233 strncpy(soap
->arrayType
, tp
->value
, sizeof(soap
->arrayType
) - 1);
10234 soap
->arraySize
[sizeof(soap
->arrayType
)-1] = '\0';
10235 soap
->arrayType
[sizeof(soap
->arrayType
)-1] = '\0';
10237 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:offset"))
10238 strncpy(soap
->arrayOffset
, tp
->value
, sizeof(soap
->arrayOffset
));
10239 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:position"))
10240 soap
->position
= soap_getposition(tp
->value
, soap
->positions
);
10241 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:root"))
10242 soap
->root
= ((!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")));
10243 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:mustUnderstand")
10244 && (!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")))
10245 soap
->mustUnderstand
= 1;
10246 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:actor"))
10247 { if ((!soap
->actor
|| strcmp(soap
->actor
, tp
->value
))
10248 && strcmp(tp
->value
, "http://schemas.xmlsoap.org/soap/actor/next"))
10252 else if (soap
->version
== 2)
10254 #ifndef WITH_NOIDREF
10255 if (!strcmp(tp
->name
, "ref")
10256 || !soap_match_tag(soap
, tp
->name
, "SOAP-ENC:ref"))
10257 { *soap
->href
= '#';
10258 strncpy(soap
->href
+ 1, tp
->value
, sizeof(soap
->href
) - 2);
10259 soap
->href
[sizeof(soap
->href
)-1] = '\0';
10263 if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:itemType"))
10264 strncpy(soap
->arrayType
, tp
->value
, sizeof(soap
->arrayType
) - 1);
10265 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:arraySize"))
10266 strncpy(soap
->arraySize
, tp
->value
, sizeof(soap
->arraySize
) - 1);
10267 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:mustUnderstand")
10268 && (!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")))
10269 soap
->mustUnderstand
= 1;
10270 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:role"))
10271 { if ((!soap
->actor
|| strcmp(soap
->actor
, tp
->value
))
10272 && strcmp(tp
->value
, "http://www.w3.org/2003/05/soap-envelope/role/next"))
10277 { if (!soap_match_tag(soap
, tp
->name
, "wsdl:required") && !strcmp(tp
->value
, "true"))
10278 soap
->mustUnderstand
= 1;
10282 return soap
->error
= SOAP_OK
;
10286 /******************************************************************************/
10291 soap_retry(struct soap
*soap
)
10292 { soap
->error
= SOAP_OK
;
10297 /******************************************************************************/
10302 soap_revert(struct soap
*soap
)
10303 { if (!soap
->peeked
)
10304 { soap
->peeked
= 1;
10308 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reverting to last element '%s' (level=%u)\n", soap
->tag
, soap
->level
));
10312 /******************************************************************************/
10317 soap_string_out(struct soap
*soap
, const char *s
, int flag
)
10318 { register const char *t
;
10319 register soap_wchar c
;
10320 register soap_wchar mask
= (soap_wchar
)0xFFFFFF80UL
;
10322 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10323 { soap
->dom
->data
= soap_strdup(soap
, s
);
10327 if (flag
== 2 || soap
->mode
& SOAP_C_UTFSTRING
)
10335 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "	", 5))
10336 return soap
->error
;
10341 if (flag
|| !(soap
->mode
& SOAP_XML_CANONICAL
))
10342 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "
", 5))
10343 return soap
->error
;
10348 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "
", 5))
10349 return soap
->error
;
10353 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "&", 5))
10354 return soap
->error
;
10358 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "<", 4))
10359 return soap
->error
;
10364 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, ">", 4))
10365 return soap
->error
;
10371 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, """, 6))
10372 return soap
->error
;
10377 #ifndef WITH_LEANER
10379 if (soap
->mode
& SOAP_C_MBSTRING
)
10381 register int m
= mbtowc(&wc
, t
- 1, MB_CUR_MAX
);
10382 if (m
> 0 && wc
!= c
)
10383 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_pututf8(soap
, wc
))
10384 return soap
->error
;
10391 #ifndef WITH_NOSTRINGTOUTF8
10392 if ((c
& mask
) || !(c
& 0xFFFFFFE0UL
))
10393 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_pututf8(soap
, (unsigned char)c
))
10394 return soap
->error
;
10400 return soap_send_raw(soap
, s
, t
- s
- 1);
10404 /******************************************************************************/
10409 soap_string_in(struct soap
*soap
, int flag
, long minlen
, long maxlen
)
10410 { register char *s
;
10413 register long l
= 0;
10414 register int n
= 0, f
= 0, m
= 0;
10415 register soap_wchar c
;
10416 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
10417 char buf
[MB_LEN_MAX
> 8 ? MB_LEN_MAX
: 8];
10421 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Reading string content, flag=%d\n", flag
));
10422 if (soap
->peeked
&& *soap
->tag
)
10425 struct soap_attribute
*tp
;
10426 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String content includes tag '%s' and attributes\n", soap
->tag
));
10429 t
[sizeof(soap
->tmpbuf
)-1] = '\0';
10430 strncpy(t
+ 1, soap
->tag
, sizeof(soap
->tmpbuf
) - 2);
10432 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10434 { if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
10437 strcpy(t
, tp
->name
);
10439 if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
10440 break; /* too many or large attribute values */
10444 strcpy(t
, tp
->value
);
10455 m
= (int)strlen(soap
->tmpbuf
);
10464 { register int state
= 0;
10466 soap
->labidx
= 0; /* use look-aside buffer */
10468 if (soap_new_block(soap
) == NULL
)
10475 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
10477 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
10478 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
10479 soap
->labidx
= soap
->lablen
; /* claim this space */
10481 register size_t k
= SOAP_BLKLEN
;
10482 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
10485 for (i
= 0; i
< k
; i
++)
10487 { *s
++ = *t
++; /* copy multibyte characters */
10491 c
= soap_getchar(soap
);
10494 if (c
>= 0x80 && state
!= 1 && !(soap
->mode
& SOAP_ENC_LATIN
))
10495 { soap_unget(soap
, c
);
10496 c
= soap_getutf8(soap
);
10497 if (soap
->mode
& SOAP_C_UTFSTRING
)
10501 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
10503 { if (c
< 0x010000)
10504 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
10506 { if (c
< 0x200000)
10507 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
10509 { if (c
< 0x04000000)
10510 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
10512 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
10513 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
10515 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
10517 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
10519 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
10521 *t
++ = (char)(0x80 | (c
& 0x3F));
10522 m
= (int)(t
- buf
) - 1;
10601 { c
= soap_getchar(soap
);
10604 soap_unget(soap
, c
);
10609 c
= soap_getchar(soap
);
10618 { c
= soap_getchar(soap
);
10620 { do c
= soap_getchar(soap
);
10621 while ((int)c
!= EOF
&& c
!= '[');
10624 t
= (char*)"![CDATA[";
10629 { if ((c
= soap_getchar(soap
)) == '-')
10633 soap_unget(soap
, c
);
10638 soap_unget(soap
, c
);
10645 else if (f
&& n
== 0)
10646 { soap_revget1(soap
);
10652 soap_unget(soap
, c
);
10662 #ifndef WITH_LEANER
10664 if (soap
->mode
& SOAP_C_MBSTRING
)
10665 { m
= wctomb(buf
, c
& 0x7FFFFFFF);
10666 if (m
>= 1 && m
<= (int)MB_CUR_MAX
)
10672 { *s
++ = SOAP_UNKNOWN_CHAR
;
10679 *s
++ = (char)(c
& 0xFF);
10682 if (maxlen
>= 0 && l
> maxlen
)
10683 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
10684 soap
->error
= SOAP_LENGTH
;
10692 soap
->labidx
= 0; /* use look-aside buffer */
10694 if (soap_new_block(soap
) == NULL
)
10701 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
10703 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
10704 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
10705 soap
->labidx
= soap
->lablen
; /* claim this space */
10707 register size_t k
= SOAP_BLKLEN
;
10708 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
10711 for (i
= 0; i
< k
; i
++)
10713 { *s
++ = *t
++; /* copy multibyte characters */
10717 if (soap
->mode
& SOAP_C_UTFSTRING
)
10718 { if (((c
= soap_get(soap
)) & 0x80000000) && c
>= -0x7FFFFF80 && c
< SOAP_AP
)
10722 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
10724 { if (c
< 0x010000)
10725 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
10727 { if (c
< 0x200000)
10728 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
10730 { if (c
< 0x04000000)
10731 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
10733 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
10734 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
10736 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
10738 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
10740 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
10742 *t
++ = (char)(0x80 | (c
& 0x3F));
10743 m
= (int)(t
- buf
) - 1;
10750 c
= soap_getutf8(soap
);
10778 { c
= soap_get(soap
);
10781 soap_unget(soap
, c
);
10785 case (soap_wchar
)('<' | 0x80000000):
10794 case (soap_wchar
)('>' | 0x80000000):
10803 case (soap_wchar
)('&' | 0x80000000):
10812 case (soap_wchar
)('"' | 0x80000000):
10817 t
= (char*)"quot;";
10821 case (soap_wchar
)('\'' | 0x80000000):
10826 t
= (char*)"apos;";
10833 #ifndef WITH_LEANER
10835 if (soap
->mode
& SOAP_C_MBSTRING
)
10836 { m
= wctomb(buf
, c
& 0x7FFFFFFF);
10837 if (m
>= 1 && m
<= (int)MB_CUR_MAX
)
10843 { *s
++ = SOAP_UNKNOWN_CHAR
;
10850 *s
++ = (char)(c
& 0xFF);
10853 if (maxlen
>= 0 && l
> maxlen
)
10854 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
10855 soap
->error
= SOAP_LENGTH
;
10861 soap_unget(soap
, c
);
10864 t
= soap_strdup(soap
, soap
->labbuf
);
10866 soap_size_block(soap
, NULL
, i
+1);
10867 t
= soap_save_block(soap
, NULL
, 0);
10870 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too short: %ld chars, minlen=%ld\n", l
, minlen
));
10871 soap
->error
= SOAP_LENGTH
;
10875 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10877 soap
->dom
->tail
= t
;
10879 soap
->dom
->data
= t
;
10883 if (soap_s2QName(soap
, t
, &t
, minlen
, maxlen
))
10889 /******************************************************************************/
10890 #ifndef WITH_LEANER
10895 soap_wstring_out(struct soap
*soap
, const wchar_t *s
, int flag
)
10898 register soap_wchar c
;
10900 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10901 { wchar_t *r
= (wchar_t*)s
;
10905 soap
->dom
->wide
= r
= (wchar_t*)soap_malloc(soap
, n
* sizeof(wchar_t));
10921 if (flag
|| !(soap
->mode
& SOAP_XML_CANONICAL
))
10948 if (c
>= 0x20 && c
< 0x80)
10950 if (soap_send_raw(soap
, &tmp
, 1))
10951 return soap
->error
;
10953 else /* check UTF16 encoding when wchar_t is too small to hold UCS */
10954 { if (sizeof(wchar_t) < 4 && (c
& 0xD800) == 0xD800)
10955 { /* http://unicode.org/faq/utf_bom.html#utf16-2 */
10956 if ((*s
& 0xD800) == 0xD800)
10957 c
= (c
<< 10) + *s
++ + 0x10000 - (0xD800 << 10) - 0xDC00;
10959 c
= 0xFFFD; /* Malformed */
10961 if (soap_pututf8(soap
, (unsigned long)c
))
10962 return soap
->error
;
10966 if (soap_send(soap
, t
))
10967 return soap
->error
;
10974 /******************************************************************************/
10975 #ifndef WITH_LEANER
10980 soap_wstring_in(struct soap
*soap
, int flag
, long minlen
, long maxlen
)
10982 register int i
, n
= 0, f
= 0;
10983 register long l
= 0;
10984 register soap_wchar c
;
10986 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Reading wide string content\n"));
10991 struct soap_attribute
*tp
;
10994 t
[sizeof(soap
->tmpbuf
)-1] = '\0';
10995 strncpy(t
+ 1, soap
->tag
, sizeof(soap
->tmpbuf
) - 2);
10997 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10999 { if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
11002 strcpy(t
, tp
->name
);
11004 if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
11009 strcpy(t
, tp
->value
);
11027 if (soap_new_block(soap
) == NULL
)
11030 { if (!(s
= (wchar_t*)soap_push_block(soap
, NULL
, sizeof(wchar_t)*SOAP_BLKLEN
)))
11032 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
11034 { *s
++ = (wchar_t)*t
++;
11039 c
= soap_getutf8(soap
);
11047 soap_unget(soap
, '/');
11066 { c
= soap_getutf8(soap
);
11069 soap_unget(soap
, c
);
11075 *s
++ = (soap_wchar
)'<';
11077 { *s
++ = (soap_wchar
)'&';
11083 *s
++ = (soap_wchar
)'>';
11085 { *s
++ = (soap_wchar
)'&';
11091 *s
++ = (soap_wchar
)'"';
11093 { *s
++ = (soap_wchar
)'&';
11094 t
= (char*)"quot;";
11100 if (sizeof(wchar_t) < 4 && c
> 0xFFFF)
11102 /* http://unicode.org/faq/utf_bom.html#utf16-2 */
11103 c1
= 0xD800 - (0x10000 >> 10) + (c
>> 10);
11104 c2
= 0xDC00 + (c
& 0x3FF);
11106 soap_unget(soap
, c2
);
11108 *s
++ = (wchar_t)c
& 0x7FFFFFFF;
11111 if (maxlen
>= 0 && l
> maxlen
)
11112 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
11113 soap
->error
= SOAP_LENGTH
;
11119 soap_unget(soap
, c
);
11121 soap_size_block(soap
, NULL
, sizeof(wchar_t) * (i
+ 1));
11123 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too short: %ld chars, minlen=%ld\n", l
, minlen
));
11124 soap
->error
= SOAP_LENGTH
;
11127 s
= (wchar_t*)soap_save_block(soap
, NULL
, NULL
, 0);
11129 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
11130 soap
->dom
->wide
= s
;
11137 /******************************************************************************/
11142 soap_int2s(struct soap
*soap
, int n
)
11143 { return soap_long2s(soap
, (long)n
);
11147 /******************************************************************************/
11152 soap_outint(struct soap
*soap
, const char *tag
, int id
, const int *p
, const char *type
, int n
)
11153 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11154 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
11155 return soap
->error
;
11156 return soap_element_end_out(soap
, tag
);
11160 /******************************************************************************/
11165 soap_s2int(struct soap
*soap
, const char *s
, int *p
)
11173 *p
= (int)soap_strtol(s
, &r
, 10);
11174 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11177 || soap_errno
== SOAP_ERANGE
11181 soap
->error
= SOAP_TYPE
;
11183 return soap
->error
;
11187 /******************************************************************************/
11192 soap_inint(struct soap
*soap
, const char *tag
, int *p
, const char *type
, int t
)
11193 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11197 && soap_match_tag(soap
, soap
->type
, type
)
11198 && soap_match_tag(soap
, soap
->type
, ":int")
11199 && soap_match_tag(soap
, soap
->type
, ":short")
11200 && soap_match_tag(soap
, soap
->type
, ":byte"))
11201 { soap
->error
= SOAP_TYPE
;
11206 p
= (int*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(int), 0, NULL
, NULL
, NULL
);
11208 p
= (int*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(int), 0, NULL
);
11210 { if (soap_s2int(soap
, soap_value(soap
), p
))
11213 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11219 /******************************************************************************/
11224 soap_long2s(struct soap
*soap
, long n
)
11225 { sprintf(soap
->tmpbuf
, "%ld", n
);
11226 return soap
->tmpbuf
;
11230 /******************************************************************************/
11235 soap_outlong(struct soap
*soap
, const char *tag
, int id
, const long *p
, const char *type
, int n
)
11236 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11237 || soap_string_out(soap
, soap_long2s(soap
, *p
), 0))
11238 return soap
->error
;
11239 return soap_element_end_out(soap
, tag
);
11243 /******************************************************************************/
11248 soap_s2long(struct soap
*soap
, const char *s
, long *p
)
11256 *p
= soap_strtol(s
, &r
, 10);
11257 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11260 || soap_errno
== SOAP_ERANGE
11264 soap
->error
= SOAP_TYPE
;
11266 return soap
->error
;
11270 /******************************************************************************/
11275 soap_inlong(struct soap
*soap
, const char *tag
, long *p
, const char *type
, int t
)
11276 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11280 && soap_match_tag(soap
, soap
->type
, type
)
11281 && soap_match_tag(soap
, soap
->type
, ":int")
11282 && soap_match_tag(soap
, soap
->type
, ":short")
11283 && soap_match_tag(soap
, soap
->type
, ":byte"))
11284 { soap
->error
= SOAP_TYPE
;
11289 p
= (long*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(long), 0, NULL
, NULL
, NULL
);
11291 p
= (long*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(long), 0, NULL
);
11293 { if (soap_s2long(soap
, soap_value(soap
), p
))
11296 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11302 /******************************************************************************/
11307 soap_LONG642s(struct soap
*soap
, LONG64 n
)
11308 { sprintf(soap
->tmpbuf
, SOAP_LONG_FORMAT
, n
);
11309 return soap
->tmpbuf
;
11313 /******************************************************************************/
11318 soap_outLONG64(struct soap
*soap
, const char *tag
, int id
, const LONG64
*p
, const char *type
, int n
)
11319 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11320 || soap_string_out(soap
, soap_LONG642s(soap
, *p
), 0))
11321 return soap
->error
;
11322 return soap_element_end_out(soap
, tag
);
11326 /******************************************************************************/
11331 soap_s2LONG64(struct soap
*soap
, const char *s
, LONG64
*p
)
11334 #ifdef HAVE_STRTOLL
11341 *p
= strtoll(s
, &r
, 10);
11342 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11345 || soap_errno
== SOAP_ERANGE
11350 # ifdef HAVE_SSCANF
11351 if (sscanf(s
, SOAP_LONG_FORMAT
, p
) != 1)
11354 soap
->error
= SOAP_TYPE
;
11356 return soap
->error
;
11360 /******************************************************************************/
11365 soap_inLONG64(struct soap
*soap
, const char *tag
, LONG64
*p
, const char *type
, int t
)
11366 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11370 && soap_match_tag(soap
, soap
->type
, type
)
11371 && soap_match_tag(soap
, soap
->type
, ":integer")
11372 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
11373 && soap_match_tag(soap
, soap
->type
, ":negativeInteger")
11374 && soap_match_tag(soap
, soap
->type
, ":nonPositiveInteger")
11375 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
11376 && soap_match_tag(soap
, soap
->type
, ":long")
11377 && soap_match_tag(soap
, soap
->type
, ":int")
11378 && soap_match_tag(soap
, soap
->type
, ":short")
11379 && soap_match_tag(soap
, soap
->type
, ":byte"))
11380 { soap
->error
= SOAP_TYPE
;
11385 p
= (LONG64
*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(LONG64
), 0, NULL
, NULL
, NULL
);
11387 p
= (LONG64
*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(LONG64
), 0, NULL
);
11389 { if (soap_s2LONG64(soap
, soap_value(soap
), p
))
11392 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11398 /******************************************************************************/
11403 soap_byte2s(struct soap
*soap
, char n
)
11404 { return soap_long2s(soap
, (long)n
);
11408 /******************************************************************************/
11413 soap_outbyte(struct soap
*soap
, const char *tag
, int id
, const char *p
, const char *type
, int n
)
11414 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11415 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
11416 return soap
->error
;
11417 return soap_element_end_out(soap
, tag
);
11421 /******************************************************************************/
11426 soap_s2byte(struct soap
*soap
, const char *s
, char *p
)
11430 n
= soap_strtol(s
, &r
, 10);
11431 if (s
== r
|| *r
|| n
< -128 || n
> 127)
11432 soap
->error
= SOAP_TYPE
;
11435 return soap
->error
;
11439 /******************************************************************************/
11444 soap_inbyte(struct soap
*soap
, const char *tag
, char *p
, const char *type
, int t
)
11445 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11449 && soap_match_tag(soap
, soap
->type
, type
)
11450 && soap_match_tag(soap
, soap
->type
, ":byte"))
11451 { soap
->error
= SOAP_TYPE
;
11456 p
= (char*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(char), 0, NULL
, NULL
, NULL
);
11458 p
= (char*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(char), 0, NULL
);
11460 { if (soap_s2byte(soap
, soap_value(soap
), p
))
11463 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11469 /******************************************************************************/
11474 soap_short2s(struct soap
*soap
, short n
)
11475 { return soap_long2s(soap
, (long)n
);
11479 /******************************************************************************/
11484 soap_outshort(struct soap
*soap
, const char *tag
, int id
, const short *p
, const char *type
, int n
)
11485 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11486 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
11487 return soap
->error
;
11488 return soap_element_end_out(soap
, tag
);
11492 /******************************************************************************/
11497 soap_s2short(struct soap
*soap
, const char *s
, short *p
)
11501 n
= soap_strtol(s
, &r
, 10);
11502 if (s
== r
|| *r
|| n
< -32768 || n
> 32767)
11503 soap
->error
= SOAP_TYPE
;
11506 return soap
->error
;
11510 /******************************************************************************/
11515 soap_inshort(struct soap
*soap
, const char *tag
, short *p
, const char *type
, int t
)
11516 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11520 && soap_match_tag(soap
, soap
->type
, type
)
11521 && soap_match_tag(soap
, soap
->type
, ":short")
11522 && soap_match_tag(soap
, soap
->type
, ":byte"))
11523 { soap
->error
= SOAP_TYPE
;
11528 p
= (short*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(short), 0, NULL
, NULL
, NULL
);
11530 p
= (short*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(short), 0, NULL
);
11532 { if (soap_s2short(soap
, soap_value(soap
), p
))
11535 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11541 /******************************************************************************/
11546 soap_float2s(struct soap
*soap
, float n
)
11548 if (soap_isnan((double)n
))
11550 if (soap_ispinff(n
))
11552 if (soap_isninff(n
))
11555 #if defined(HAVE_SPRINTF_L)
11556 sprintf_l(s
, soap
->c_locale
, soap
->float_format
, n
);
11558 sprintf(s
, soap
->float_format
, n
);
11559 s
= strchr(s
, ','); /* convert decimal comma to DP */
11563 return soap
->tmpbuf
;
11567 /******************************************************************************/
11572 soap_outfloat(struct soap
*soap
, const char *tag
, int id
, const float *p
, const char *type
, int n
)
11573 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11574 || soap_string_out(soap
, soap_float2s(soap
, *p
), 0))
11575 return soap
->error
;
11576 return soap_element_end_out(soap
, tag
);
11580 /******************************************************************************/
11585 soap_s2float(struct soap
*soap
, const char *s
, float *p
)
11588 return soap
->error
= SOAP_TYPE
;
11589 if (!soap_tag_cmp(s
, "INF"))
11591 else if (!soap_tag_cmp(s
, "+INF"))
11593 else if (!soap_tag_cmp(s
, "-INF"))
11595 else if (!soap_tag_cmp(s
, "NaN"))
11599 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
11600 #if defined(HAVE_STRTOD_L)
11602 *p
= (float)strtod_l(s
, &r
, soap
->c_locale
);
11604 #elif defined(HAVE_STRTOD)
11606 *p
= (float)strtod(s
, &r
);
11608 #elif defined(HAVE_STRTOF_L)
11610 *p
= strtof_l((char*)s
, &r
, soap
->c_locale
);
11612 #elif defined(HAVE_STRTOF)
11614 *p
= strtof((char*)s
, &r
);
11618 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11619 if (sscanf_l(s
, soap
->c_locale
, "%g", p
) != 1)
11620 soap
->error
= SOAP_TYPE
;
11621 #elif defined(HAVE_SSCANF)
11622 if (sscanf(s
, "%g", p
) != 1)
11623 soap
->error
= SOAP_TYPE
;
11625 soap
->error
= SOAP_TYPE
;
11630 return soap
->error
;
11634 /******************************************************************************/
11636 static int soap_isnumeric(struct soap
*soap
, const char *type
)
11637 { if (soap_match_tag(soap
, soap
->type
, type
)
11638 && soap_match_tag(soap
, soap
->type
, ":float")
11639 && soap_match_tag(soap
, soap
->type
, ":double")
11640 && soap_match_tag(soap
, soap
->type
, ":decimal")
11641 && soap_match_tag(soap
, soap
->type
, ":integer")
11642 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
11643 && soap_match_tag(soap
, soap
->type
, ":negativeInteger")
11644 && soap_match_tag(soap
, soap
->type
, ":nonPositiveInteger")
11645 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
11646 && soap_match_tag(soap
, soap
->type
, ":long")
11647 && soap_match_tag(soap
, soap
->type
, ":int")
11648 && soap_match_tag(soap
, soap
->type
, ":short")
11649 && soap_match_tag(soap
, soap
->type
, ":byte")
11650 && soap_match_tag(soap
, soap
->type
, ":unsignedLong")
11651 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
11652 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
11653 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11654 { soap
->error
= SOAP_TYPE
;
11662 /******************************************************************************/
11667 soap_infloat(struct soap
*soap
, const char *tag
, float *p
, const char *type
, int t
)
11668 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11671 if (*soap
->type
!= '\0' && soap_isnumeric(soap
, type
))
11674 p
= (float*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(float), 0, NULL
, NULL
, NULL
);
11676 p
= (float*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(float), 0, NULL
);
11678 { if (soap_s2float(soap
, soap_value(soap
), p
))
11681 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11687 /******************************************************************************/
11692 soap_double2s(struct soap
*soap
, double n
)
11696 if (soap_ispinfd(n
))
11698 if (soap_isninfd(n
))
11701 #if defined(HAVE_SPRINTF_L)
11702 sprintf_l(s
, soap
->c_locale
, soap
->double_format
, n
);
11704 sprintf(s
, soap
->double_format
, n
);
11705 s
= strchr(s
, ','); /* convert decimal comma to DP */
11709 return soap
->tmpbuf
;
11713 /******************************************************************************/
11718 soap_outdouble(struct soap
*soap
, const char *tag
, int id
, const double *p
, const char *type
, int n
)
11719 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11720 || soap_string_out(soap
, soap_double2s(soap
, *p
), 0))
11721 return soap
->error
;
11722 return soap_element_end_out(soap
, tag
);
11726 /******************************************************************************/
11731 soap_s2double(struct soap
*soap
, const char *s
, double *p
)
11734 return soap
->error
= SOAP_TYPE
;
11735 if (!soap_tag_cmp(s
, "INF"))
11737 else if (!soap_tag_cmp(s
, "+INF"))
11739 else if (!soap_tag_cmp(s
, "-INF"))
11741 else if (!soap_tag_cmp(s
, "NaN"))
11745 #if defined(HAVE_STRTOD_L)
11747 *p
= strtod_l(s
, &r
, soap
->c_locale
);
11749 #elif defined(HAVE_STRTOD)
11751 *p
= strtod(s
, &r
);
11755 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11756 if (sscanf_l(s
, soap
->c_locale
, "%lg", p
) != 1)
11757 soap
->error
= SOAP_TYPE
;
11758 #elif defined(HAVE_SSCANF)
11759 if (sscanf(s
, "%lg", p
) != 1)
11760 soap
->error
= SOAP_TYPE
;
11762 soap
->error
= SOAP_TYPE
;
11767 return soap
->error
;
11771 /******************************************************************************/
11776 soap_indouble(struct soap
*soap
, const char *tag
, double *p
, const char *type
, int t
)
11777 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11780 if (*soap
->type
!= '\0' && soap_isnumeric(soap
, type
))
11783 p
= (double*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(double), 0, NULL
, NULL
, NULL
);
11785 p
= (double*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(double), 0, NULL
);
11787 { if (soap_s2double(soap
, soap_value(soap
), p
))
11790 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11796 /******************************************************************************/
11801 soap_unsignedByte2s(struct soap
*soap
, unsigned char n
)
11802 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
11806 /******************************************************************************/
11811 soap_outunsignedByte(struct soap
*soap
, const char *tag
, int id
, const unsigned char *p
, const char *type
, int n
)
11812 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11813 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
11814 return soap
->error
;
11815 return soap_element_end_out(soap
, tag
);
11819 /******************************************************************************/
11824 soap_s2unsignedByte(struct soap
*soap
, const char *s
, unsigned char *p
)
11828 n
= soap_strtoul(s
, &r
, 10);
11829 if (s
== r
|| *r
|| n
> 255)
11830 soap
->error
= SOAP_TYPE
;
11831 *p
= (unsigned char)n
;
11833 return soap
->error
;
11837 /******************************************************************************/
11842 soap_inunsignedByte(struct soap
*soap
, const char *tag
, unsigned char *p
, const char *type
, int t
)
11843 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11847 && soap_match_tag(soap
, soap
->type
, type
)
11848 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11849 { soap
->error
= SOAP_TYPE
;
11854 p
= (unsigned char*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned char), 0, NULL
, NULL
, NULL
);
11856 p
= (unsigned char*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned char), 0, NULL
);
11858 { if (soap_s2unsignedByte(soap
, soap_value(soap
), p
))
11861 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11867 /******************************************************************************/
11872 soap_unsignedShort2s(struct soap
*soap
, unsigned short n
)
11873 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
11877 /******************************************************************************/
11882 soap_outunsignedShort(struct soap
*soap
, const char *tag
, int id
, const unsigned short *p
, const char *type
, int n
)
11883 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11884 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
11885 return soap
->error
;
11886 return soap_element_end_out(soap
, tag
);
11890 /******************************************************************************/
11895 soap_s2unsignedShort(struct soap
*soap
, const char *s
, unsigned short *p
)
11899 n
= soap_strtoul(s
, &r
, 10);
11900 if (s
== r
|| *r
|| n
> 65535)
11901 soap
->error
= SOAP_TYPE
;
11902 *p
= (unsigned short)n
;
11904 return soap
->error
;
11908 /******************************************************************************/
11913 soap_inunsignedShort(struct soap
*soap
, const char *tag
, unsigned short *p
, const char *type
, int t
)
11914 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11918 && soap_match_tag(soap
, soap
->type
, type
)
11919 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
11920 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11921 { soap
->error
= SOAP_TYPE
;
11926 p
= (unsigned short*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned short), 0, NULL
, NULL
, NULL
);
11928 p
= (unsigned short*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned short), 0, NULL
);
11930 { if (soap_s2unsignedShort(soap
, soap_value(soap
), p
))
11933 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11939 /******************************************************************************/
11944 soap_unsignedInt2s(struct soap
*soap
, unsigned int n
)
11945 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
11949 /******************************************************************************/
11954 soap_outunsignedInt(struct soap
*soap
, const char *tag
, int id
, const unsigned int *p
, const char *type
, int n
)
11955 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11956 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
11957 return soap
->error
;
11958 return soap_element_end_out(soap
, tag
);
11962 /******************************************************************************/
11967 soap_s2unsignedInt(struct soap
*soap
, const char *s
, unsigned int *p
)
11975 *p
= (unsigned int)soap_strtoul(s
, &r
, 10);
11976 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11979 || soap_errno
== SOAP_ERANGE
11983 soap
->error
= SOAP_TYPE
;
11985 return soap
->error
;
11989 /******************************************************************************/
11994 soap_inunsignedInt(struct soap
*soap
, const char *tag
, unsigned int *p
, const char *type
, int t
)
11995 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11999 && soap_match_tag(soap
, soap
->type
, type
)
12000 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
12001 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12002 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12003 { soap
->error
= SOAP_TYPE
;
12008 p
= (unsigned int*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned int), 0, NULL
, NULL
, NULL
);
12010 p
= (unsigned int*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned int), 0, NULL
);
12012 { if (soap_s2unsignedInt(soap
, soap_value(soap
), p
))
12015 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12021 /******************************************************************************/
12026 soap_unsignedLong2s(struct soap
*soap
, unsigned long n
)
12027 { sprintf(soap
->tmpbuf
, "%lu", n
);
12028 return soap
->tmpbuf
;
12032 /******************************************************************************/
12037 soap_outunsignedLong(struct soap
*soap
, const char *tag
, int id
, const unsigned 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_unsignedLong2s(soap
, *p
), 0))
12040 return soap
->error
;
12041 return soap_element_end_out(soap
, tag
);
12045 /******************************************************************************/
12050 soap_s2unsignedLong(struct soap
*soap
, const char *s
, unsigned long *p
)
12058 *p
= soap_strtoul(s
, &r
, 10);
12059 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
12062 || soap_errno
== SOAP_ERANGE
12066 soap
->error
= SOAP_TYPE
;
12068 return soap
->error
;
12072 /******************************************************************************/
12077 soap_inunsignedLong(struct soap
*soap
, const char *tag
, unsigned 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
, ":unsignedInt")
12084 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12085 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12086 { soap
->error
= SOAP_TYPE
;
12091 p
= (unsigned long*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned long), 0, NULL
, NULL
, NULL
);
12093 p
= (unsigned long*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned long), 0, NULL
);
12095 { if (soap_s2unsignedLong(soap
, soap_value(soap
), p
))
12098 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12104 /******************************************************************************/
12109 soap_ULONG642s(struct soap
*soap
, ULONG64 n
)
12110 { sprintf(soap
->tmpbuf
, SOAP_ULONG_FORMAT
, n
);
12111 return soap
->tmpbuf
;
12115 /******************************************************************************/
12120 soap_outULONG64(struct soap
*soap
, const char *tag
, int id
, const ULONG64
*p
, const char *type
, int n
)
12121 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12122 || soap_string_out(soap
, soap_ULONG642s(soap
, *p
), 0))
12123 return soap
->error
;
12124 return soap_element_end_out(soap
, tag
);
12128 /******************************************************************************/
12133 soap_s2ULONG64(struct soap
*soap
, const char *s
, ULONG64
*p
)
12136 #ifdef HAVE_STRTOULL
12143 *p
= strtoull(s
, &r
, 10);
12144 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
12147 || soap_errno
== SOAP_ERANGE
12153 if (sscanf(s
, SOAP_ULONG_FORMAT
, p
) != 1)
12156 soap
->error
= SOAP_TYPE
;
12158 return soap
->error
;
12162 /******************************************************************************/
12167 soap_inULONG64(struct soap
*soap
, const char *tag
, ULONG64
*p
, const char *type
, int t
)
12168 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12171 && soap_match_tag(soap
, soap
->type
, type
)
12172 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
12173 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
12174 && soap_match_tag(soap
, soap
->type
, ":unsignedLong")
12175 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
12176 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12177 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12178 { soap
->error
= SOAP_TYPE
;
12182 p
= (ULONG64
*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(ULONG64
), 0, NULL
, NULL
, NULL
);
12184 p
= (ULONG64
*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(ULONG64
), 0, NULL
);
12186 { if (soap_s2ULONG64(soap
, soap_value(soap
), p
))
12189 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12195 /******************************************************************************/
12200 soap_s2string(struct soap
*soap
, const char *s
, char **t
, long minlen
, long maxlen
)
12202 { long l
= (long)strlen(s
);
12203 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
12204 return soap
->error
= SOAP_LENGTH
;
12205 if (!(*t
= soap_strdup(soap
, s
)))
12206 return soap
->error
= SOAP_EOM
;
12207 if (!(soap
->mode
& (SOAP_ENC_LATIN
| SOAP_C_UTFSTRING
)))
12209 /* remove non-ASCII chars */
12210 for (s
= *t
; *s
; s
++)
12216 return soap
->error
;
12220 /******************************************************************************/
12225 soap_s2QName(struct soap
*soap
, const char *s
, char **t
, long minlen
, long maxlen
)
12227 { long l
= (long)strlen(s
);
12228 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
12229 return soap
->error
= SOAP_LENGTH
;
12231 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Normalized namespace(s) of QNames '%s'", s
));
12232 /* convert (by prefix normalize prefix) all QNames in s */
12235 struct soap_nlist
*np
;
12236 register const char *p
;
12238 while (*s
&& soap_blank((soap_wchar
)*s
))
12242 /* find next QName */
12244 while (s
[n
] && !soap_blank(s
[n
]))
12247 /* if there is no namespace stack, or prefix is "xml" then copy string */
12248 if (!np
|| !strncmp(s
, "xml:", 4))
12249 { soap_append_lab(soap
, s
, n
);
12251 else /* we normalize the QName by replacing its prefix */
12253 for (p
= s
; *p
&& p
< s
+ n
; p
++)
12257 { size_t k
= p
- s
;
12258 while (np
&& (strncmp(np
->id
, s
, k
) || np
->id
[k
]))
12263 { while (np
&& *np
->id
)
12267 /* replace prefix */
12269 { if (np
->index
>= 0 && soap
->local_namespaces
&& (q
= soap
->local_namespaces
[np
->index
].id
))
12270 { size_t k
= strlen(q
);
12272 soap_append_lab(soap
, q
, k
);
12274 { soap_append_lab(soap
, "\"", 1);
12275 soap_append_lab(soap
, soap
->local_namespaces
[np
->index
].ns
, strlen(soap
->local_namespaces
[np
->index
].ns
));
12276 soap_append_lab(soap
, "\"", 1);
12280 { soap_append_lab(soap
, "\"", 1);
12281 soap_append_lab(soap
, np
->ns
, strlen(np
->ns
));
12282 soap_append_lab(soap
, "\"", 1);
12285 { 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
));
12286 return soap
->error
= SOAP_NAMESPACE
;
12289 else if (s
[n
]) /* no namespace, part of string */
12290 { soap_append_lab(soap
, s
, n
);
12292 else /* no namespace: assume "" namespace */
12293 { soap_append_lab(soap
, "\"\"", 2);
12295 soap_append_lab(soap
, ":", 1);
12296 soap_append_lab(soap
, p
, n
- (p
-s
));
12298 /* advance to next and add spacing */
12301 soap_append_lab(soap
, " ", 1);
12303 soap_append_lab(soap
, SOAP_STR_EOS
, 1);
12304 *t
= soap_strdup(soap
, soap
->labbuf
);
12305 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, " into '%s'\n", *t
));
12307 return soap
->error
;
12311 /******************************************************************************/
12316 soap_QName2s(struct soap
*soap
, const char *s
)
12317 { const char *t
= NULL
;
12319 { soap
->labidx
= 0;
12323 while (*s
&& soap_blank((soap_wchar
)*s
))
12327 /* find next QName */
12329 while (s
[n
] && !soap_blank((soap_wchar
)s
[n
]))
12331 /* normal prefix: pass string as is */
12333 { soap_append_lab(soap
, s
, n
);
12335 if ((soap
->mode
& SOAP_XML_CANONICAL
))
12336 { const char *r
= strchr(s
, ':');
12338 soap_utilize_ns(soap
, s
, r
- s
);
12342 else /* URL-based string prefix */
12345 q
= strchr(s
, '"');
12347 { struct Namespace
*p
= soap
->local_namespaces
;
12349 { for (; p
->id
; p
++)
12351 if (!soap_tag_cmp(s
, p
->ns
))
12354 if (!soap_tag_cmp(s
, p
->in
))
12358 /* URL is in the namespace table? */
12360 { soap_append_lab(soap
, p
->id
, strlen(p
->id
));
12362 else /* not in namespace table: create xmlns binding */
12363 { char *r
= soap_strdup(soap
, s
);
12365 sprintf(soap
->tmpbuf
, "xmlns:_%d", soap
->idnum
++);
12366 soap_set_attr(soap
, soap
->tmpbuf
, r
, 1);
12367 soap_append_lab(soap
, soap
->tmpbuf
+ 6, strlen(soap
->tmpbuf
+ 6));
12369 soap_append_lab(soap
, q
+ 1, n
- (q
-s
) - 1);
12372 /* advance to next and add spacing */
12375 soap_append_lab(soap
, " ", 1);
12377 soap_append_lab(soap
, SOAP_STR_EOS
, 1);
12378 t
= soap_strdup(soap
, soap
->labbuf
);
12384 /******************************************************************************/
12389 soap_s2wchar(struct soap
*soap
, const char *s
, wchar_t **t
, long minlen
, long maxlen
)
12393 *t
= r
= (wchar_t*)soap_malloc(soap
, sizeof(wchar_t) * (strlen(s
) + 1));
12395 return soap
->error
= SOAP_EOM
;
12396 if (soap
->mode
& SOAP_ENC_LATIN
)
12398 *r
++ = (wchar_t)*s
++;
12401 { /* Convert UTF8 to wchar */
12403 { register soap_wchar c
, c1
, c2
, c3
, c4
;
12404 c
= (unsigned char)*s
++;
12408 { c1
= (soap_wchar
)*s
++ & 0x3F;
12410 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x1F) << 6) | c1
);
12412 { c2
= (soap_wchar
)*s
++ & 0x3F;
12414 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x0F) << 12) | (c1
<< 6) | c2
);
12416 { c3
= (soap_wchar
)*s
++ & 0x3F;
12418 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x07) << 18) | (c1
<< 12) | (c2
<< 6) | c3
);
12420 { c4
= (soap_wchar
)*s
++ & 0x3F;
12422 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x03) << 24) | (c1
<< 18) | (c2
<< 12) | (c3
<< 6) | c4
);
12424 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x01) << 30) | (c1
<< 24) | (c2
<< 18) | (c3
<< 12) | (c4
<< 6) | (soap_wchar
)(*s
++ & 0x3F));
12432 l
= (long)(r
- *t
);
12433 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
12434 return soap
->error
= SOAP_LENGTH
;
12436 return soap
->error
;
12440 /******************************************************************************/
12445 soap_wchar2s(struct soap
*soap
, const wchar_t *s
)
12446 { register soap_wchar c
;
12447 register char *r
, *t
;
12448 const wchar_t *q
= s
;
12451 { if (c
> 0 && c
< 0x80)
12456 r
= t
= (char*)soap_malloc(soap
, n
+ 1);
12458 { /* Convert wchar to UTF8 */
12460 { if (c
> 0 && c
< 0x80)
12464 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
12466 { if (c
< 0x010000)
12467 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
12469 { if (c
< 0x200000)
12470 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
12472 { if (c
< 0x04000000)
12473 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
12475 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
12476 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
12478 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
12480 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
12482 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
12484 *t
++ = (char)(0x80 | (c
& 0x3F));
12493 /******************************************************************************/
12498 soap_outstring(struct soap
*soap
, const char *tag
, int id
, char *const*p
, const char *type
, int n
)
12499 { id
= soap_element_id(soap
, tag
, id
, *p
, NULL
, 0, type
, n
);
12501 return soap
->error
;
12502 if (!**p
&& (soap
->mode
& SOAP_C_NILSTRING
))
12503 return soap_element_null(soap
, tag
, id
, type
);
12504 if (soap_element_begin_out(soap
, tag
, id
, type
)
12505 || soap_string_out(soap
, *p
, 0)
12506 || soap_element_end_out(soap
, tag
))
12507 return soap
->error
;
12512 /******************************************************************************/
12517 soap_instring(struct soap
*soap
, const char *tag
, char **p
, const char *type
, int t
, int flag
, long minlen
, long maxlen
)
12518 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12519 { if (!tag
|| *tag
!= '-' || soap
->error
!= SOAP_NO_TAG
)
12521 soap
->error
= SOAP_OK
;
12524 { if (!(p
= (char**)soap_malloc(soap
, sizeof(char*))))
12529 else if (soap
->body
)
12530 { *p
= soap_string_in(soap
, flag
, minlen
, maxlen
);
12531 if (!*p
|| !(char*)soap_id_enter(soap
, soap
->id
, *p
, t
, sizeof(char*), 0, NULL
, NULL
, NULL
))
12533 if (!**p
&& tag
&& *tag
== '-')
12534 { soap
->error
= SOAP_NO_TAG
;
12538 else if (tag
&& *tag
== '-')
12539 { soap
->error
= SOAP_NO_TAG
;
12542 else if (!*soap
->href
&& minlen
> 0)
12543 { soap
->error
= SOAP_LENGTH
;
12547 *p
= soap_strdup(soap
, SOAP_STR_EOS
);
12549 p
= (char**)soap_id_lookup(soap
, soap
->href
, (void**)p
, t
, sizeof(char**), 0);
12550 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12556 /******************************************************************************/
12557 #ifndef WITH_LEANER
12562 soap_outwstring(struct soap
*soap
, const char *tag
, int id
, wchar_t *const*p
, const char *type
, int n
)
12563 { id
= soap_element_id(soap
, tag
, id
, *p
, NULL
, 0, type
, n
);
12565 return soap
->error
;
12566 if (!**p
&& (soap
->mode
& SOAP_C_NILSTRING
))
12567 return soap_element_null(soap
, tag
, id
, type
);
12568 if (soap_element_begin_out(soap
, tag
, id
, type
)
12569 || soap_wstring_out(soap
, *p
, 0)
12570 || soap_element_end_out(soap
, tag
))
12571 return soap
->error
;
12577 /******************************************************************************/
12578 #ifndef WITH_LEANER
12583 soap_inwstring(struct soap
*soap
, const char *tag
, wchar_t **p
, const char *type
, int t
, long minlen
, long maxlen
)
12584 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12585 { if (!tag
|| *tag
!= '-' || soap
->error
!= SOAP_NO_TAG
)
12587 soap
->error
= SOAP_OK
;
12590 { if (!(p
= (wchar_t**)soap_malloc(soap
, sizeof(wchar_t*))))
12594 { *p
= soap_wstring_in(soap
, 1, minlen
, maxlen
);
12595 if (!*p
|| !(wchar_t*)soap_id_enter(soap
, soap
->id
, *p
, t
, sizeof(wchar_t*), 0, NULL
, NULL
, NULL
))
12597 if (!**p
&& tag
&& *tag
== '-')
12598 { soap
->error
= SOAP_NO_TAG
;
12602 else if (tag
&& *tag
== '-')
12603 { soap
->error
= SOAP_NO_TAG
;
12606 else if (soap
->null
)
12609 *p
= soap_wstrdup(soap
, (wchar_t*)SOAP_STR_EOS
);
12611 p
= (wchar_t**)soap_id_lookup(soap
, soap
->href
, (void**)p
, t
, sizeof(wchar_t**), 0);
12612 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12619 /******************************************************************************/
12624 soap_timegm(struct tm
*T
)
12626 #if defined(HAVE_TIMEGM)
12632 if (t
== (time_t)-1)
12634 #ifdef HAVE_GMTIME_R
12641 if (g
== (time_t)-1)
12649 /******************************************************************************/
12654 soap_dateTime2s(struct soap
*soap
, time_t n
)
12655 { struct tm T
, *pT
= &T
;
12656 #if defined(HAVE_GMTIME_R)
12657 if (gmtime_r(&n
, pT
))
12658 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%SZ", pT
);
12659 #elif defined(HAVE_GMTIME)
12660 if ((pT
= gmtime(&n
)))
12661 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%SZ", pT
);
12662 #elif defined(HAVE_GETTIMEOFDAY)
12663 struct timezone tz
;
12664 memset((void*)&tz
, 0, sizeof(tz
));
12665 #if defined(HAVE_LOCALTIME_R)
12666 if (localtime_r(&n
, pT
))
12667 { struct timeval tv
;
12668 gettimeofday(&tv
, &tz
);
12669 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12670 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
12673 if ((pT
= localtime(&n
)))
12674 { struct timeval tv
;
12675 gettimeofday(&tv
, &tz
);
12676 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12677 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
12680 #elif defined(HAVE_FTIME)
12682 memset((void*)&t
, 0, sizeof(t
));
12683 #if defined(HAVE_LOCALTIME_R)
12684 if (localtime_r(&n
, pT
))
12686 #ifdef __BORLANDC__
12691 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12692 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
12695 if ((pT
= localtime(&n
)))
12697 #ifdef __BORLANDC__
12702 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12703 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
12706 #elif defined(HAVE_LOCALTIME_R)
12707 if (localtime_r(&n
, pT
))
12708 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12710 if ((pT
= localtime(&n
)))
12711 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12714 strcpy(soap
->tmpbuf
, "1969-12-31T23:59:59Z");
12715 return soap
->tmpbuf
;
12719 /******************************************************************************/
12724 soap_outdateTime(struct soap
*soap
, const char *tag
, int id
, const time_t *p
, const char *type
, int n
)
12725 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12726 || soap_string_out(soap
, soap_dateTime2s(soap
, *p
), 0))
12727 return soap
->error
;
12728 return soap_element_end_out(soap
, tag
);
12732 /******************************************************************************/
12737 soap_s2dateTime(struct soap
*soap
, const char *s
, time_t *p
)
12743 memset((void*)&T
, 0, sizeof(T
));
12744 if (strchr(s
, '-'))
12745 t
= "%d-%d-%dT%d:%d:%d%31s";
12746 else if (strchr(s
, ':'))
12747 t
= "%4d%2d%2dT%d:%d:%d%31s";
12748 else /* parse non-XSD-standard alternative ISO 8601 format */
12749 t
= "%4d%2d%2dT%2d%2d%2d%31s";
12750 if (sscanf(s
, t
, &T
.tm_year
, &T
.tm_mon
, &T
.tm_mday
, &T
.tm_hour
, &T
.tm_min
, &T
.tm_sec
, zone
) < 6)
12751 return soap
->error
= SOAP_TYPE
;
12752 if (T
.tm_year
== 1)
12758 { for (s
= zone
+ 1; *s
; s
++)
12759 if (*s
< '0' || *s
> '9')
12766 #ifndef WITH_NOZONE
12767 if (*s
== '+' || *s
== '-')
12768 { int h
= 0, m
= 0;
12771 sscanf(s
, "%d:%d", &h
, &m
);
12776 { m
= (int)soap_strtol(s
, NULL
, 10);
12782 /* put hour and min in range */
12783 T
.tm_hour
+= T
.tm_min
/ 60;
12789 T
.tm_mday
+= T
.tm_hour
/ 24;
12795 /* note: day of the month may be out of range, timegm() handles it */
12798 *p
= soap_timegm(&T
);
12800 else /* no UTC or timezone, so assume we got a localtime */
12805 return soap
->error
;
12809 /******************************************************************************/
12814 soap_indateTime(struct soap
*soap
, const char *tag
, time_t *p
, const char *type
, int t
)
12815 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12818 && soap_match_tag(soap
, soap
->type
, type
)
12819 && soap_match_tag(soap
, soap
->type
, ":dateTime"))
12820 { soap
->error
= SOAP_TYPE
;
12824 p
= (time_t*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(time_t), 0, NULL
, NULL
, NULL
);
12826 p
= (time_t*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(time_t), 0, NULL
);
12828 { if (soap_s2dateTime(soap
, soap_value(soap
), p
))
12831 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12837 /******************************************************************************/
12842 soap_outliteral(struct soap
*soap
, const char *tag
, char *const*p
, const char *type
)
12844 const char *t
= NULL
;
12845 if (tag
&& *tag
!= '-')
12846 { if (soap
->local_namespaces
&& (t
= strchr(tag
, ':')))
12847 { strncpy(soap
->tmpbuf
, tag
, t
-tag
);
12848 soap
->tmpbuf
[t
-tag
] = '\0';
12849 for (i
= 0; soap
->local_namespaces
[i
].id
; i
++)
12850 if (!strcmp(soap
->tmpbuf
, soap
->local_namespaces
[i
].id
))
12853 if (soap_element(soap
, t
, 0, type
)
12854 || soap_attribute(soap
, "xmlns", soap
->local_namespaces
[i
].ns
? soap
->local_namespaces
[i
].ns
: SOAP_STR_EOS
)
12855 || soap_element_start_end_out(soap
, NULL
))
12856 return soap
->error
;
12860 if (soap_element_begin_out(soap
, t
, 0, type
))
12861 return soap
->error
;
12865 { if (soap_send(soap
, *p
))
12866 return soap
->error
;
12869 return soap_element_end_out(soap
, t
);
12874 /******************************************************************************/
12879 soap_inliteral(struct soap
*soap
, const char *tag
, char **p
)
12880 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12881 { if (soap
->error
!= SOAP_NO_TAG
|| soap_unget(soap
, soap_get(soap
)) == SOAP_TT
)
12883 soap
->error
= SOAP_OK
;
12886 { if (!(p
= (char**)soap_malloc(soap
, sizeof(char*))))
12889 if (soap
->body
|| (tag
&& *tag
== '-'))
12890 { *p
= soap_string_in(soap
, 0, -1, -1);
12893 if (!**p
&& tag
&& *tag
== '-')
12894 { soap
->error
= SOAP_NO_TAG
;
12898 else if (soap
->null
)
12901 *p
= soap_strdup(soap
, SOAP_STR_EOS
);
12902 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12908 /******************************************************************************/
12909 #ifndef WITH_LEANER
12914 soap_outwliteral(struct soap
*soap
, const char *tag
, wchar_t *const*p
, const char *type
)
12916 const char *t
= NULL
;
12917 if (tag
&& *tag
!= '-')
12918 { if (soap
->local_namespaces
&& (t
= strchr(tag
, ':')))
12919 { strncpy(soap
->tmpbuf
, tag
, t
-tag
);
12920 soap
->tmpbuf
[t
-tag
] = '\0';
12921 for (i
= 0; soap
->local_namespaces
[i
].id
; i
++)
12922 if (!strcmp(soap
->tmpbuf
, soap
->local_namespaces
[i
].id
))
12925 if (soap_element(soap
, t
, 0, type
)
12926 || soap_attribute(soap
, "xmlns", soap
->local_namespaces
[i
].ns
? soap
->local_namespaces
[i
].ns
: SOAP_STR_EOS
)
12927 || soap_element_start_end_out(soap
, NULL
))
12928 return soap
->error
;
12932 if (soap_element_begin_out(soap
, t
, 0, type
))
12933 return soap
->error
;
12935 if (soap_send(soap
, soap
->tmpbuf
))
12936 return soap
->error
;
12940 const wchar_t *s
= *p
;
12942 { if (soap_pututf8(soap
, (unsigned long)c
))
12943 return soap
->error
;
12947 return soap_element_end_out(soap
, t
);
12953 /******************************************************************************/
12954 #ifndef WITH_LEANER
12959 soap_inwliteral(struct soap
*soap
, const char *tag
, wchar_t **p
)
12960 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12961 { if (soap
->error
!= SOAP_NO_TAG
|| soap_unget(soap
, soap_get(soap
)) == SOAP_TT
)
12963 soap
->error
= SOAP_OK
;
12966 { if (!(p
= (wchar_t**)soap_malloc(soap
, sizeof(wchar_t*))))
12970 { *p
= soap_wstring_in(soap
, 0, -1, -1);
12973 if (!**p
&& tag
&& *tag
== '-')
12974 { soap
->error
= SOAP_NO_TAG
;
12978 else if (tag
&& *tag
== '-')
12979 { soap
->error
= SOAP_NO_TAG
;
12982 else if (soap
->null
)
12985 *p
= soap_wstrdup(soap
, (wchar_t*)SOAP_STR_EOS
);
12986 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12993 /******************************************************************************/
12998 soap_value(struct soap
*soap
)
12999 { register size_t i
;
13000 register soap_wchar c
= 0;
13001 register char *s
= soap
->tmpbuf
;
13003 return SOAP_STR_EOS
;
13004 do c
= soap_get(soap
);
13005 while (soap_blank(c
));
13006 for (i
= 0; i
< sizeof(soap
->tmpbuf
) - 1; i
++)
13007 { if (c
== SOAP_TT
|| c
== SOAP_LT
|| (int)c
== EOF
)
13010 c
= soap_get(soap
);
13012 for (s
--; i
> 0; i
--, s
--)
13013 { if (!soap_blank((soap_wchar
)*s
))
13017 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element content value='%s'\n", soap
->tmpbuf
));
13018 if (c
== SOAP_TT
|| c
== SOAP_LT
|| (int)c
== EOF
)
13019 soap_unget(soap
, c
);
13020 else if (soap
->mode
& SOAP_XML_STRICT
)
13021 { soap
->error
= SOAP_LENGTH
;
13025 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
13026 soap
->dom
->data
= soap_strdup(soap
, soap
->tmpbuf
);
13028 return soap
->tmpbuf
; /* return non-null pointer */
13032 /******************************************************************************/
13033 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
13038 soap_getline(struct soap
*soap
, char *s
, int len
)
13043 { c
= soap_getchar(soap
);
13044 if (c
== '\r' || c
== '\n')
13047 return soap
->error
= SOAP_EOF
;
13051 c
= soap_getchar(soap
); /* got \r or something else, now get \n */
13054 if (i
+1 == len
) /* empty line: end of HTTP/MIME header */
13056 c
= soap_get0(soap
);
13057 if (c
!= ' ' && c
!= '\t') /* HTTP line continuation? */
13060 else if ((int)c
== EOF
)
13061 return soap
->error
= SOAP_EOF
;
13063 return soap
->error
= SOAP_HDR
;
13070 /******************************************************************************/
13073 soap_count_attachments(struct soap
*soap
)
13075 #ifndef WITH_LEANER
13076 register struct soap_multipart
*content
;
13077 register size_t count
= soap
->count
;
13078 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count
));
13079 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
13080 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the size of DIME attachments\n"));
13081 for (content
= soap
->dime
.first
; content
; content
= content
->next
)
13082 { count
+= 12 + ((content
->size
+3)&(~3));
13084 count
+= ((strlen(content
->id
)+3)&(~3));
13086 count
+= ((strlen(content
->type
)+3)&(~3));
13087 if (content
->options
)
13088 count
+= ((((unsigned char)content
->options
[2] << 8) | ((unsigned char)content
->options
[3]))+7)&(~3);
13089 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content
->size
));
13092 if ((soap
->mode
& SOAP_ENC_MIME
) && soap
->mime
.boundary
)
13093 { register size_t n
= strlen(soap
->mime
.boundary
);
13094 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the size of MIME attachments\n"));
13095 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
13096 { register const char *s
;
13097 /* count \r\n--boundary\r\n */
13099 /* count Content-Type: ...\r\n */
13101 count
+= 16 + strlen(content
->type
);
13102 /* count Content-Transfer-Encoding: ...\r\n */
13103 s
= soap_code_str(mime_codes
, content
->encoding
);
13105 count
+= 29 + strlen(s
);
13106 /* count Content-ID: ...\r\n */
13108 count
+= 14 + strlen(content
->id
);
13109 /* count Content-Location: ...\r\n */
13110 if (content
->location
)
13111 count
+= 20 + strlen(content
->location
);
13112 /* count Content-Description: ...\r\n */
13113 if (content
->description
)
13114 count
+= 23 + strlen(content
->description
);
13115 /* count \r\n...content */
13116 count
+= 2 + content
->size
;
13117 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content
->size
));
13119 /* count \r\n--boundary-- */
13122 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "New count is %lu bytes\n", (unsigned long)count
));
13125 return soap
->count
;
13130 /******************************************************************************/
13131 #ifndef WITH_LEANER
13134 soap_putdimefield(struct soap
*soap
, const char *s
, size_t n
)
13135 { if (soap_send_raw(soap
, s
, n
))
13136 return soap
->error
;
13137 return soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)n
&3);
13142 /******************************************************************************/
13143 #ifndef WITH_LEANER
13148 soap_dime_option(struct soap
*soap
, unsigned short optype
, const char *option
)
13152 { n
= strlen(option
);
13153 s
= (char*)soap_malloc(soap
, n
+ 5);
13155 { s
[0] = (char)(optype
>> 8);
13156 s
[1] = (char)(optype
& 0xFF);
13157 s
[2] = (char)(n
>> 8);
13158 s
[3] = (char)(n
& 0xFF);
13159 strcpy(s
+ 4, option
);
13167 /******************************************************************************/
13168 #ifndef WITH_LEANER
13173 soap_putdimehdr(struct soap
*soap
)
13174 { unsigned char tmp
[12];
13175 size_t optlen
= 0, idlen
= 0, typelen
= 0;
13176 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Put DIME header id='%s'\n", soap
->dime
.id
?soap
->dime
.id
:SOAP_STR_EOS
));
13177 if (soap
->dime
.options
)
13178 optlen
= (((unsigned char)soap
->dime
.options
[2] << 8) | ((unsigned char)soap
->dime
.options
[3])) + 4;
13180 { idlen
= strlen(soap
->dime
.id
);
13181 if (idlen
> 0x0000FFFF)
13182 idlen
= 0x0000FFFF;
13184 if (soap
->dime
.type
)
13185 { typelen
= strlen(soap
->dime
.type
);
13186 if (typelen
> 0x0000FFFF)
13187 typelen
= 0x0000FFFF;
13189 tmp
[0] = SOAP_DIME_VERSION
| (soap
->dime
.flags
& 0x7);
13190 tmp
[1] = soap
->dime
.flags
& 0xF0;
13191 tmp
[2] = (char)(optlen
>> 8);
13192 tmp
[3] = (char)(optlen
& 0xFF);
13193 tmp
[4] = (char)(idlen
>> 8);
13194 tmp
[5] = (char)(idlen
& 0xFF);
13195 tmp
[6] = (char)(typelen
>> 8);
13196 tmp
[7] = (char)(typelen
& 0xFF);
13197 tmp
[8] = (char)(soap
->dime
.size
>> 24);
13198 tmp
[9] = (char)((soap
->dime
.size
>> 16) & 0xFF);
13199 tmp
[10] = (char)((soap
->dime
.size
>> 8) & 0xFF);
13200 tmp
[11] = (char)(soap
->dime
.size
& 0xFF);
13201 if (soap_send_raw(soap
, (char*)tmp
, 12)
13202 || soap_putdimefield(soap
, soap
->dime
.options
, optlen
)
13203 || soap_putdimefield(soap
, soap
->dime
.id
, idlen
)
13204 || soap_putdimefield(soap
, soap
->dime
.type
, typelen
))
13205 return soap
->error
;
13211 /******************************************************************************/
13212 #ifndef WITH_LEANER
13217 soap_putdime(struct soap
*soap
)
13218 { struct soap_multipart
*content
;
13219 if (!(soap
->mode
& SOAP_ENC_DIME
))
13221 for (content
= soap
->dime
.first
; content
; content
= content
->next
)
13223 soap
->dime
.size
= content
->size
;
13224 soap
->dime
.id
= content
->id
;
13225 soap
->dime
.type
= content
->type
;
13226 soap
->dime
.options
= content
->options
;
13227 soap
->dime
.flags
= SOAP_DIME_VERSION
| SOAP_DIME_MEDIA
;
13228 if (soap
->fdimereadopen
&& ((handle
= soap
->fdimereadopen(soap
, (void*)content
->ptr
, content
->id
, content
->type
, content
->options
)) || soap
->error
))
13229 { size_t size
= content
->size
;
13231 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadopen failed\n"));
13232 return soap
->error
;
13234 if (!size
&& ((soap
->mode
& SOAP_ENC_XML
) || (soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
))
13235 { size_t chunksize
= sizeof(soap
->tmpbuf
);
13236 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked streaming DIME\n"));
13238 { size
= soap
->fdimeread(soap
, handle
, soap
->tmpbuf
, chunksize
);
13239 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimeread returned %lu bytes\n", (unsigned long)size
));
13240 if (size
< chunksize
)
13241 { soap
->dime
.flags
&= ~SOAP_DIME_CF
;
13242 if (!content
->next
)
13243 soap
->dime
.flags
|= SOAP_DIME_ME
;
13246 soap
->dime
.flags
|= SOAP_DIME_CF
;
13247 soap
->dime
.size
= size
;
13248 if (soap_putdimehdr(soap
)
13249 || soap_putdimefield(soap
, soap
->tmpbuf
, size
))
13252 { soap
->dime
.flags
&= ~(SOAP_DIME_MB
| SOAP_DIME_MEDIA
);
13253 soap
->dime
.id
= NULL
;
13254 soap
->dime
.type
= NULL
;
13255 soap
->dime
.options
= NULL
;
13257 } while (size
>= chunksize
);
13260 { if (!content
->next
)
13261 soap
->dime
.flags
|= SOAP_DIME_ME
;
13262 if (soap_putdimehdr(soap
))
13263 return soap
->error
;
13266 if (size
< sizeof(soap
->tmpbuf
))
13269 bufsize
= sizeof(soap
->tmpbuf
);
13270 if (!(bufsize
= soap
->fdimeread(soap
, handle
, soap
->tmpbuf
, bufsize
)))
13271 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size
, (unsigned long)content
->size
));
13272 soap
->error
= SOAP_EOF
;
13275 if (soap_send_raw(soap
, soap
->tmpbuf
, bufsize
))
13279 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadclose\n"));
13280 soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)soap
->dime
.size
&3);
13282 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadclose\n"));
13283 if (soap
->fdimereadclose
)
13284 soap
->fdimereadclose(soap
, handle
);
13287 { if (!content
->next
)
13288 soap
->dime
.flags
|= SOAP_DIME_ME
;
13289 if (soap_putdimehdr(soap
)
13290 || soap_putdimefield(soap
, (char*)content
->ptr
, content
->size
))
13291 return soap
->error
;
13299 /******************************************************************************/
13300 #ifndef WITH_LEANER
13303 soap_getdimefield(struct soap
*soap
, size_t n
)
13304 { register soap_wchar c
;
13307 register char *p
= NULL
;
13309 { p
= (char*)soap_malloc(soap
, n
+ 1);
13312 for (i
= n
; i
> 0; i
--)
13313 { if ((int)(c
= soap_get1(soap
)) == EOF
)
13314 { soap
->error
= SOAP_EOF
;
13320 if ((soap
->error
= soap_move(soap
, -(long)n
&3)))
13324 soap
->error
= SOAP_EOM
;
13331 /******************************************************************************/
13332 #ifndef WITH_LEANER
13337 soap_getdimehdr(struct soap
*soap
)
13338 { register soap_wchar c
;
13341 unsigned char tmp
[12];
13342 size_t optlen
, idlen
, typelen
;
13343 if (!(soap
->mode
& SOAP_ENC_DIME
))
13344 return soap
->error
= SOAP_DIME_END
;
13345 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME header\n"));
13346 if (soap
->dime
.buflen
|| soap
->dime
.chunksize
)
13347 { if (soap_move(soap
, (long)(soap
->dime
.size
- soap_tell(soap
))))
13348 return soap
->error
= SOAP_EOF
;
13349 soap_unget(soap
, soap_getchar(soap
)); /* skip padding and get hdr */
13350 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "... From chunked\n"));
13354 for (i
= 12; i
> 0; i
--)
13355 { if ((int)(c
= soap_getchar(soap
)) == EOF
)
13356 return soap
->error
= SOAP_EOF
;
13359 if ((tmp
[0] & 0xF8) != SOAP_DIME_VERSION
)
13360 return soap
->error
= SOAP_DIME_MISMATCH
;
13361 soap
->dime
.flags
= (tmp
[0] & 0x7) | (tmp
[1] & 0xF0);
13362 optlen
= (tmp
[2] << 8) | tmp
[3];
13363 idlen
= (tmp
[4] << 8) | tmp
[5];
13364 typelen
= (tmp
[6] << 8) | tmp
[7];
13365 soap
->dime
.size
= (tmp
[8] << 24) | (tmp
[9] << 16) | (tmp
[10] << 8) | tmp
[11];
13366 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME size=%lu flags=0x%X\n", (unsigned long)soap
->dime
.size
, soap
->dime
.flags
));
13367 if (!(soap
->dime
.options
= soap_getdimefield(soap
, optlen
)) && soap
->error
)
13368 return soap
->error
;
13369 if (!(soap
->dime
.id
= soap_getdimefield(soap
, idlen
)) && soap
->error
)
13370 return soap
->error
;
13371 if (!(soap
->dime
.type
= soap_getdimefield(soap
, typelen
)) && soap
->error
)
13372 return soap
->error
;
13373 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
));
13374 if (soap
->dime
.flags
& SOAP_DIME_ME
)
13375 soap
->mode
&= ~SOAP_ENC_DIME
;
13381 /******************************************************************************/
13382 #ifndef WITH_LEANER
13387 soap_getdime(struct soap
*soap
)
13388 { while (soap
->dime
.flags
& SOAP_DIME_CF
)
13389 { if (soap_getdimehdr(soap
))
13390 return soap
->error
;
13391 if (soap_move(soap
, (long)soap
->dime
.size
))
13392 return soap
->error
= SOAP_EOF
;
13394 if (soap_move(soap
, (long)(((soap
->dime
.size
+3)&(~3))-soap_tell(soap
))))
13395 return soap
->error
= SOAP_EOF
;
13397 { register struct soap_multipart
*content
;
13398 if (soap_getdimehdr(soap
))
13400 if (soap
->fdimewriteopen
&& ((soap
->dime
.ptr
= (char*)soap
->fdimewriteopen(soap
, soap
->dime
.id
, soap
->dime
.type
, soap
->dime
.options
)) || soap
->error
))
13401 { const char *id
, *type
, *options
;
13403 if (!soap
->dime
.ptr
)
13404 return soap
->error
;
13405 id
= soap
->dime
.id
;
13406 type
= soap
->dime
.type
;
13407 options
= soap
->dime
.options
;
13409 { size
= soap
->dime
.size
;
13411 { n
= soap
->buflen
- soap
->bufidx
;
13414 if ((soap
->error
= soap
->fdimewrite(soap
, (void*)soap
->dime
.ptr
, soap
->buf
+ soap
->bufidx
, n
)))
13418 { soap
->bufidx
+= n
;
13421 if (soap_recv(soap
))
13422 { soap
->error
= SOAP_EOF
;
13426 if (soap_move(soap
, -(long)soap
->dime
.size
&3))
13427 { soap
->error
= SOAP_EOF
;
13430 if (!(soap
->dime
.flags
& SOAP_DIME_CF
))
13432 if (soap_getdimehdr(soap
))
13436 if (soap
->fdimewriteclose
)
13437 soap
->fdimewriteclose(soap
, (void*)soap
->dime
.ptr
);
13438 soap
->dime
.size
= 0;
13439 soap
->dime
.id
= id
;
13440 soap
->dime
.type
= type
;
13441 soap
->dime
.options
= options
;
13443 else if (soap
->dime
.flags
& SOAP_DIME_CF
)
13444 { const char *id
, *type
, *options
;
13445 id
= soap
->dime
.id
;
13446 type
= soap
->dime
.type
;
13447 options
= soap
->dime
.options
;
13448 if (soap_new_block(soap
) == NULL
)
13451 { register soap_wchar c
;
13454 s
= (char*)soap_push_block(soap
, NULL
, soap
->dime
.size
);
13456 return soap
->error
= SOAP_EOM
;
13457 for (i
= soap
->dime
.size
; i
> 0; i
--)
13458 { if ((int)(c
= soap_get1(soap
)) == EOF
)
13459 return soap
->error
= SOAP_EOF
;
13462 if (soap_move(soap
, -(long)soap
->dime
.size
&3))
13463 return soap
->error
= SOAP_EOF
;
13464 if (!(soap
->dime
.flags
& SOAP_DIME_CF
))
13466 if (soap_getdimehdr(soap
))
13467 return soap
->error
;
13469 soap
->dime
.size
= soap
->blist
->size
++; /* allocate one more for '\0' */
13470 if (!(soap
->dime
.ptr
= soap_save_block(soap
, NULL
, NULL
, 0)))
13471 return soap
->error
;
13472 soap
->dime
.ptr
[soap
->dime
.size
] = '\0'; /* force 0-terminated */
13473 soap
->dime
.id
= id
;
13474 soap
->dime
.type
= type
;
13475 soap
->dime
.options
= options
;
13478 soap
->dime
.ptr
= soap_getdimefield(soap
, soap
->dime
.size
);
13479 content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, soap
->dime
.ptr
, soap
->dime
.size
);
13481 return soap
->error
= SOAP_EOM
;
13482 content
->id
= soap
->dime
.id
;
13483 content
->type
= soap
->dime
.type
;
13484 content
->options
= soap
->dime
.options
;
13486 return soap
->error
;
13487 soap_resolve_attachment(soap
, content
);
13489 if (soap
->error
!= SOAP_DIME_END
)
13490 return soap
->error
;
13491 return soap
->error
= SOAP_OK
;
13496 /******************************************************************************/
13497 #ifndef WITH_LEANER
13502 soap_getmimehdr(struct soap
*soap
)
13503 { struct soap_multipart
*content
;
13505 { if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
13506 return soap
->error
;
13508 while (!*soap
->msgbuf
);
13509 if (soap
->msgbuf
[0] == '-' && soap
->msgbuf
[1] == '-')
13510 { char *s
= soap
->msgbuf
+ strlen(soap
->msgbuf
) - 1;
13511 /* remove white space */
13512 while (soap_blank((soap_wchar
)*s
))
13515 if (soap
->mime
.boundary
)
13516 { if (strcmp(soap
->msgbuf
+ 2, soap
->mime
.boundary
))
13517 return soap
->error
= SOAP_MIME_ERROR
;
13520 soap
->mime
.boundary
= soap_strdup(soap
, soap
->msgbuf
+ 2);
13521 if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
13522 return soap
->error
;
13524 if (soap_set_mime_attachment(soap
, NULL
, 0, SOAP_MIME_NONE
, NULL
, NULL
, NULL
, NULL
))
13525 return soap
->error
= SOAP_EOM
;
13526 content
= soap
->mime
.last
;
13528 { register char *key
= soap
->msgbuf
;
13529 register char *val
;
13532 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "MIME header: %s\n", key
));
13533 val
= strchr(soap
->msgbuf
, ':');
13537 while (*val
&& *val
<= 32);
13538 if (!soap_tag_cmp(key
, "Content-ID"))
13539 content
->id
= soap_strdup(soap
, val
);
13540 else if (!soap_tag_cmp(key
, "Content-Location"))
13541 content
->location
= soap_strdup(soap
, val
);
13542 else if (!soap_tag_cmp(key
, "Content-Disposition"))
13543 content
->id
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "name"));
13544 else if (!soap_tag_cmp(key
, "Content-Type"))
13545 content
->type
= soap_strdup(soap
, val
);
13546 else if (!soap_tag_cmp(key
, "Content-Description"))
13547 content
->description
= soap_strdup(soap
, val
);
13548 else if (!soap_tag_cmp(key
, "Content-Transfer-Encoding"))
13549 content
->encoding
= (enum soap_mime_encoding
)soap_code_int(mime_codes
, val
, (long)SOAP_MIME_NONE
);
13551 if (soap_getline(soap
, key
, sizeof(soap
->msgbuf
)))
13552 return soap
->error
;
13559 /******************************************************************************/
13560 #ifndef WITH_LEANER
13565 soap_getmime(struct soap
*soap
)
13566 { while (soap_get_mime_attachment(soap
, NULL
))
13568 return soap
->error
;
13573 /******************************************************************************/
13574 #ifndef WITH_LEANER
13579 soap_post_check_mime_attachments(struct soap
*soap
)
13580 { soap
->imode
|= SOAP_MIME_POSTCHECK
;
13585 /******************************************************************************/
13586 #ifndef WITH_LEANER
13591 soap_check_mime_attachments(struct soap
*soap
)
13592 { if (soap
->mode
& SOAP_MIME_POSTCHECK
)
13593 return soap_get_mime_attachment(soap
, NULL
) != NULL
;
13599 /******************************************************************************/
13600 #ifndef WITH_LEANER
13603 struct soap_multipart
*
13605 soap_get_mime_attachment(struct soap
*soap
, void *handle
)
13606 { register soap_wchar c
= 0;
13607 register size_t i
, m
= 0;
13608 register char *s
, *t
= NULL
;
13609 register struct soap_multipart
*content
;
13610 register short flag
= 0;
13611 if (!(soap
->mode
& SOAP_ENC_MIME
))
13613 content
= soap
->mime
.last
;
13615 { if (soap_getmimehdr(soap
))
13617 content
= soap
->mime
.last
;
13619 else if (content
!= soap
->mime
.first
)
13620 { if (soap
->fmimewriteopen
&& ((content
->ptr
= (char*)soap
->fmimewriteopen(soap
, (void*)handle
, content
->id
, content
->type
, content
->description
, content
->encoding
)) || soap
->error
))
13621 { if (!content
->ptr
)
13625 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
));
13626 if (!content
->ptr
&& soap_new_block(soap
) == NULL
)
13627 { soap
->error
= SOAP_EOM
;
13631 { if (content
->ptr
)
13633 else if (!(s
= (char*)soap_push_block(soap
, NULL
, sizeof(soap
->tmpbuf
))))
13634 { soap
->error
= SOAP_EOM
;
13637 for (i
= 0; i
< sizeof(soap
->tmpbuf
); i
++)
13644 { c
= soap_get1(soap
);
13646 { soap
->error
= SOAP_EOF
;
13650 if (flag
|| c
== '\r')
13651 { t
= soap
->msgbuf
;
13652 memset(t
, 0, sizeof(soap
->msgbuf
));
13654 if (soap
->mime
.boundary
)
13655 strncat(t
, soap
->mime
.boundary
, sizeof(soap
->msgbuf
)-4);
13656 do c
= soap_getchar(soap
);
13659 { soap
->error
= SOAP_EOF
;
13665 flag
= (c
== '\r');
13666 m
= t
- soap
->msgbuf
+ 1 - flag
;
13673 if (content
->ptr
&& soap
->fmimewrite
)
13674 { if ((soap
->error
= soap
->fmimewrite(soap
, (void*)content
->ptr
, soap
->tmpbuf
, i
)))
13679 *s
= '\0'; /* force 0-terminated */
13681 { if (!soap
->error
&& soap
->fmimewrite
)
13682 soap
->error
= soap
->fmimewrite(soap
, (void*)content
->ptr
, soap
->tmpbuf
, i
);
13683 if (soap
->fmimewriteclose
)
13684 soap
->fmimewriteclose(soap
, (void*)content
->ptr
);
13689 { content
->size
= soap_size_block(soap
, NULL
, i
+1)-1;
13690 content
->ptr
= soap_save_block(soap
, NULL
, NULL
, 0);
13692 soap_resolve_attachment(soap
, content
);
13693 if (c
== '-' && soap_getchar(soap
) == '-')
13694 { soap
->mode
&= ~SOAP_ENC_MIME
;
13695 if ((soap
->mode
& SOAP_MIME_POSTCHECK
) && soap_end_recv(soap
))
13696 { if (soap
->keep_alive
< 0)
13697 soap
->keep_alive
= 0;
13698 soap_closesock(soap
);
13703 { while (c
!= '\r' && (int)c
!= EOF
&& soap_blank(c
))
13704 c
= soap_getchar(soap
);
13705 if (c
!= '\r' || soap_getchar(soap
) != '\n')
13706 { soap
->error
= SOAP_MIME_ERROR
;
13709 if (soap_getmimehdr(soap
))
13717 /******************************************************************************/
13718 #ifndef WITH_LEANER
13723 soap_match_cid(struct soap
*soap
, const char *s
, const char *t
)
13724 { register size_t n
;
13729 if (!strncmp(s
, "cid:", 4))
13736 if (!strncmp(s
, t
, n
) && !s
[n
])
13738 soap_decode(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
, SOAP_STR_EOS
);
13739 if (!strncmp(soap
->tmpbuf
, t
, n
) && !soap
->tmpbuf
[n
])
13746 /******************************************************************************/
13747 #ifndef WITH_LEANER
13750 soap_resolve_attachment(struct soap
*soap
, struct soap_multipart
*content
)
13752 { register struct soap_xlist
**xp
= &soap
->xlist
;
13753 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving attachment data for id=%s\n", content
->id
));
13755 { register struct soap_xlist
*xq
= *xp
;
13756 if (!soap_match_cid(soap
, xq
->id
, content
->id
))
13757 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Found matching attachment %s for content id=%s\n", xq
->id
, content
->id
));
13759 *xq
->ptr
= (unsigned char*)content
->ptr
;
13760 *xq
->size
= (int)content
->size
;
13761 *xq
->type
= (char*)content
->type
;
13762 if (content
->options
)
13763 *xq
->options
= (char*)content
->options
;
13765 *xq
->options
= (char*)content
->description
;
13766 SOAP_FREE(soap
, xq
);
13776 /******************************************************************************/
13777 #ifndef WITH_LEANER
13782 soap_putmimehdr(struct soap
*soap
, struct soap_multipart
*content
)
13784 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "MIME attachment type=%s\n", content
->type
?content
->type
:SOAP_STR_EOS
));
13785 if (soap_send3(soap
, "\r\n--", soap
->mime
.boundary
, "\r\n"))
13786 return soap
->error
;
13787 if (content
->type
&& soap_send3(soap
, "Content-Type: ", content
->type
, "\r\n"))
13788 return soap
->error
;
13789 s
= soap_code_str(mime_codes
, content
->encoding
);
13790 if (s
&& soap_send3(soap
, "Content-Transfer-Encoding: ", s
, "\r\n"))
13791 return soap
->error
;
13792 if (content
->id
&& soap_send3(soap
, "Content-ID: ", content
->id
, "\r\n"))
13793 return soap
->error
;
13794 if (content
->location
&& soap_send3(soap
, "Content-Location: ", content
->location
, "\r\n"))
13795 return soap
->error
;
13796 if (content
->description
&& soap_send3(soap
, "Content-Description: ", content
->description
, "\r\n"))
13797 return soap
->error
;
13798 return soap_send_raw(soap
, "\r\n", 2);
13803 /******************************************************************************/
13804 #ifndef WITH_LEANER
13809 soap_putmime(struct soap
*soap
)
13810 { struct soap_multipart
*content
;
13811 if (!(soap
->mode
& SOAP_ENC_MIME
) || !soap
->mime
.boundary
)
13813 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending MIME attachments\n"));
13814 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
13816 if (soap
->fmimereadopen
&& ((handle
= soap
->fmimereadopen(soap
, (void*)content
->ptr
, content
->id
, content
->type
, content
->description
)) || soap
->error
))
13817 { size_t size
= content
->size
;
13819 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimereadopen failed\n"));
13820 return soap
->error
;
13822 if (soap_putmimehdr(soap
, content
))
13823 return soap
->error
;
13825 { if ((soap
->mode
& SOAP_ENC_XML
) || (soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
13826 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked streaming MIME\n"));
13828 { size
= soap
->fmimeread(soap
, handle
, soap
->tmpbuf
, sizeof(soap
->tmpbuf
));
13829 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimeread returned %lu bytes\n", (unsigned long)size
));
13830 if (soap_send_raw(soap
, soap
->tmpbuf
, size
))
13835 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
13841 if (size
< sizeof(soap
->tmpbuf
))
13844 bufsize
= sizeof(soap
->tmpbuf
);
13845 if (!(bufsize
= soap
->fmimeread(soap
, handle
, soap
->tmpbuf
, bufsize
)))
13846 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size
, (unsigned long)content
->size
));
13847 soap
->error
= SOAP_EOF
;
13850 if (soap_send_raw(soap
, soap
->tmpbuf
, bufsize
))
13855 if (soap
->fmimereadclose
)
13856 soap
->fmimereadclose(soap
, handle
);
13859 { if (soap_putmimehdr(soap
, content
)
13860 || soap_send_raw(soap
, content
->ptr
, content
->size
))
13861 return soap
->error
;
13864 return soap_send3(soap
, "\r\n--", soap
->mime
.boundary
, "--");
13869 /******************************************************************************/
13870 #ifndef WITH_LEANER
13875 soap_set_dime(struct soap
*soap
)
13876 { soap
->omode
|= SOAP_ENC_DIME
;
13877 soap
->dime
.first
= NULL
;
13878 soap
->dime
.last
= NULL
;
13883 /******************************************************************************/
13884 #ifndef WITH_LEANER
13889 soap_set_mime(struct soap
*soap
, const char *boundary
, const char *start
)
13890 { soap
->omode
|= SOAP_ENC_MIME
;
13891 soap
->mime
.first
= NULL
;
13892 soap
->mime
.last
= NULL
;
13893 soap
->mime
.boundary
= soap_strdup(soap
, boundary
);
13894 soap
->mime
.start
= soap_strdup(soap
, start
);
13899 /******************************************************************************/
13900 #ifndef WITH_LEANER
13905 soap_clr_dime(struct soap
*soap
)
13906 { soap
->omode
&= ~SOAP_ENC_DIME
;
13907 soap
->dime
.first
= NULL
;
13908 soap
->dime
.last
= NULL
;
13913 /******************************************************************************/
13914 #ifndef WITH_LEANER
13919 soap_clr_mime(struct soap
*soap
)
13920 { soap
->omode
&= ~SOAP_ENC_MIME
;
13921 soap
->mime
.first
= NULL
;
13922 soap
->mime
.last
= NULL
;
13923 soap
->mime
.boundary
= NULL
;
13924 soap
->mime
.start
= NULL
;
13929 /******************************************************************************/
13930 #ifndef WITH_LEANER
13932 static struct soap_multipart
*
13933 soap_new_multipart(struct soap
*soap
, struct soap_multipart
**first
, struct soap_multipart
**last
, char *ptr
, size_t size
)
13934 { struct soap_multipart
*content
;
13935 content
= (struct soap_multipart
*)soap_malloc(soap
, sizeof(struct soap_multipart
));
13937 { content
->next
= NULL
;
13938 content
->ptr
= ptr
;
13939 content
->size
= size
;
13940 content
->id
= NULL
;
13941 content
->type
= NULL
;
13942 content
->options
= NULL
;
13943 content
->encoding
= SOAP_MIME_NONE
;
13944 content
->location
= NULL
;
13945 content
->description
= NULL
;
13949 (*last
)->next
= content
;
13957 /******************************************************************************/
13958 #ifndef WITH_LEANER
13963 soap_set_dime_attachment(struct soap
*soap
, char *ptr
, size_t size
, const char *type
, const char *id
, unsigned short optype
, const char *option
)
13964 { struct soap_multipart
*content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, ptr
, size
);
13967 content
->id
= soap_strdup(soap
, id
);
13968 content
->type
= soap_strdup(soap
, type
);
13969 content
->options
= soap_dime_option(soap
, optype
, option
);
13975 /******************************************************************************/
13976 #ifndef WITH_LEANER
13981 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
)
13982 { struct soap_multipart
*content
= soap_new_multipart(soap
, &soap
->mime
.first
, &soap
->mime
.last
, ptr
, size
);
13985 content
->id
= soap_strdup(soap
, id
);
13986 content
->type
= soap_strdup(soap
, type
);
13987 content
->encoding
= encoding
;
13988 content
->location
= soap_strdup(soap
, location
);
13989 content
->description
= soap_strdup(soap
, description
);
13995 /******************************************************************************/
13996 #ifndef WITH_LEANER
13999 struct soap_multipart
*
14001 soap_next_multipart(struct soap_multipart
*content
)
14003 return content
->next
;
14009 /******************************************************************************/
14010 #ifndef WITH_LEANER
14013 soap_select_mime_boundary(struct soap
*soap
)
14014 { while (!soap
->mime
.boundary
|| soap_valid_mime_boundary(soap
))
14015 { register char *s
= soap
->mime
.boundary
;
14016 register size_t n
= 0;
14021 s
= soap
->mime
.boundary
= (char*)soap_malloc(soap
, n
+ 1);
14029 { *s
++ = soap_base64o
[soap_random
& 0x3F];
14034 if (!soap
->mime
.start
)
14035 soap
->mime
.start
= "<SOAP-ENV:Envelope>";
14040 /******************************************************************************/
14041 #ifndef WITH_LEANER
14044 soap_valid_mime_boundary(struct soap
*soap
)
14045 { register struct soap_multipart
*content
;
14047 if (soap
->fmimeread
)
14049 k
= strlen(soap
->mime
.boundary
);
14050 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
14051 { if (content
->ptr
&& content
->size
>= k
)
14052 { register const char *p
= (const char*)content
->ptr
;
14054 for (i
= 0; i
< content
->size
- k
; i
++, p
++)
14055 { if (!strncmp(p
, soap
->mime
.boundary
, k
))
14065 /******************************************************************************/
14069 soap_getgziphdr(struct soap
*soap
)
14071 soap_wchar c
= 0, f
= 0;
14072 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get gzip header\n"));
14073 for (i
= 0; i
< 9; i
++)
14074 { if ((int)(c
= soap_get1(soap
) == EOF
))
14075 return soap
->error
= SOAP_EOF
;
14076 if (i
== 1 && c
== 8)
14081 if (f
& 0x04) /* FEXTRA */
14082 { for (i
= soap_get1(soap
) | (soap_get1(soap
) << 8); i
; i
--)
14083 { if ((int)soap_get1(soap
) == EOF
)
14084 return soap
->error
= SOAP_EOF
;
14087 if (f
& 0x08) /* skip FNAME */
14089 c
= soap_get1(soap
);
14090 while (c
&& (int)c
!= EOF
);
14092 if ((int)c
!= EOF
&& (f
& 0x10)) /* skip FCOMMENT */
14094 c
= soap_get1(soap
);
14095 while (c
&& (int)c
!= EOF
);
14097 if ((int)c
!= EOF
&& (f
& 0x02)) /* skip FHCRC (CRC32 is used) */
14098 { if ((int)(c
= soap_get1(soap
)) != EOF
)
14099 c
= soap_get1(soap
);
14102 return soap
->error
= SOAP_EOF
;
14108 /******************************************************************************/
14113 soap_begin_recv(struct soap
*soap
)
14115 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Initializing for input\n"));
14116 soap
->error
= SOAP_OK
;
14117 soap_free_temp(soap
);
14118 soap_set_local_namespaces(soap
);
14119 soap
->version
= 0; /* don't assume we're parsing SOAP content by default */
14120 #ifndef WITH_NOIDREF
14121 soap_free_iht(soap
);
14123 if ((soap
->imode
& SOAP_IO
) == SOAP_IO_CHUNK
)
14124 soap
->omode
|= SOAP_IO_CHUNK
;
14125 soap
->imode
&= ~(SOAP_IO
| SOAP_ENC_MIME
);
14126 soap
->mode
= soap
->imode
;
14127 if (!soap
->keep_alive
)
14128 { soap
->buflen
= 0;
14131 if (!(soap
->mode
& SOAP_IO_KEEPALIVE
))
14132 soap
->keep_alive
= 0;
14136 soap
->part
= SOAP_BEGIN
;
14141 *soap
->endpoint
= '\0';
14142 soap
->action
= NULL
;
14143 soap
->header
= NULL
;
14144 soap
->fault
= NULL
;
14146 #ifndef WITH_LEANER
14148 soap
->dime
.chunksize
= 0;
14149 soap
->dime
.buflen
= 0;
14150 soap
->dime
.list
= NULL
;
14151 soap
->dime
.first
= NULL
;
14152 soap
->dime
.last
= NULL
;
14153 soap
->mime
.list
= NULL
;
14154 soap
->mime
.first
= NULL
;
14155 soap
->mime
.last
= NULL
;
14156 soap
->mime
.boundary
= NULL
;
14157 soap
->mime
.start
= NULL
;
14161 #ifndef WITH_FASTCGI
14162 if (!soap_valid_socket(soap
->socket
))
14163 #ifdef __BORLANDC__
14164 setmode(soap
->recvfd
, _O_BINARY
);
14166 _setmode(soap
->recvfd
, _O_BINARY
);
14172 soap
->mode
&= ~SOAP_ENC_ZLIB
;
14173 soap
->zlib_in
= SOAP_ZLIB_NONE
;
14174 soap
->zlib_out
= SOAP_ZLIB_NONE
;
14175 soap
->d_stream
->next_in
= Z_NULL
;
14176 soap
->d_stream
->avail_in
= 0;
14177 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
14178 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
14179 soap
->z_ratio_in
= 1.0;
14181 #ifdef WITH_OPENSSL
14185 #ifndef WITH_LEANER
14186 if (soap
->fprepareinitrecv
&& (soap
->error
= soap
->fprepareinitrecv(soap
)))
14187 return soap
->error
;
14189 c
= soap_getchar(soap
);
14192 { if (soap_getgziphdr(soap
))
14193 return soap
->error
;
14194 if (inflateInit2(soap
->d_stream
, -MAX_WBITS
) != Z_OK
)
14195 return soap
->error
= SOAP_ZLIB_ERROR
;
14197 { if (inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
14198 return soap
->error
= SOAP_ZLIB_ERROR
;
14200 soap
->zlib_state
= SOAP_ZLIB_INFLATE
;
14201 soap
->mode
|= SOAP_ENC_ZLIB
;
14202 soap
->zlib_in
= SOAP_ZLIB_GZIP
;
14203 soap
->z_crc
= crc32(0L, NULL
, 0);
14204 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip initialized\n"));
14206 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
14207 memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
14208 /* should not chunk over plain transport, so why bother to check? */
14209 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
14210 /* soap->z_buflen = soap->bufidx; */
14212 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
14213 soap
->d_stream
->avail_in
= soap
->buflen
- soap
->bufidx
;
14214 soap
->z_buflen
= soap
->buflen
;
14215 soap
->buflen
= soap
->bufidx
;
14219 while (soap_blank(c
))
14220 c
= soap_getchar(soap
);
14221 #ifndef WITH_LEANER
14222 if (c
== '-' && soap_get0(soap
) == '-')
14223 soap
->mode
|= SOAP_ENC_MIME
;
14224 else if ((c
& 0xFFFC) == (SOAP_DIME_VERSION
| SOAP_DIME_MB
) && (soap_get0(soap
) & 0xFFF0) == 0x20)
14225 soap
->mode
|= SOAP_ENC_DIME
;
14229 if (c
== 0xEF && (c
= soap_getchar(soap
)) == 0xBB && (c
= soap_getchar(soap
)) == 0xBF)
14230 c
= soap_getchar(soap
);
14232 while (soap_blank(c
))
14233 c
= soap_getchar(soap
);
14236 return soap
->error
= SOAP_EOF
;
14237 soap_unget(soap
, c
);
14238 #ifndef WITH_NOHTTP
14239 /* if not XML or MIME/DIME/ZLIB, assume HTTP header */
14240 if (c
!= '<' && !(soap
->mode
& (SOAP_ENC_MIME
| SOAP_ENC_DIME
| SOAP_ENC_ZLIB
)))
14241 { soap_mode m
= soap
->imode
;
14242 soap
->mode
&= ~SOAP_IO
;
14243 soap
->error
= soap
->fparse(soap
);
14244 if (soap
->error
&& soap
->error
< SOAP_STOP
)
14245 { soap
->keep_alive
= 0; /* force close later */
14246 return soap
->error
;
14248 if (soap
->error
== SOAP_STOP
)
14249 return soap
->error
;
14250 soap
->mode
= soap
->imode
; /* if imode is changed, effectuate */
14251 soap
->imode
= m
; /* restore imode */
14253 soap
->mode
&= ~SOAP_ENC_ZLIB
;
14255 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
14256 { soap
->chunkbuflen
= soap
->buflen
;
14257 soap
->buflen
= soap
->bufidx
;
14258 soap
->chunksize
= 0;
14260 /* Note: fparse should not use soap_unget to push back last char */
14261 if (soap_get0(soap
) == (int)EOF
)
14262 { if (soap
->status
== 200)
14263 return soap
->error
= SOAP_NO_DATA
; /* HTTP OK: always expect data */
14264 return soap
->error
= soap
->status
;
14267 if (soap
->zlib_in
!= SOAP_ZLIB_NONE
)
14270 if (soap
->zlib_in
!= SOAP_ZLIB_DEFLATE
)
14271 { c
= soap_get1(soap
);
14273 { if (soap_getgziphdr(soap
))
14274 return soap
->error
;
14275 if (inflateInit2(soap
->d_stream
, -MAX_WBITS
) != Z_OK
)
14276 return soap
->error
= SOAP_ZLIB_ERROR
;
14277 soap
->z_crc
= crc32(0L, NULL
, 0);
14278 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip initialized\n"));
14281 { soap_revget1(soap
);
14282 if (inflateInit(soap
->d_stream
) != Z_OK
)
14283 return soap
->error
= SOAP_ZLIB_ERROR
;
14284 soap
->zlib_in
= SOAP_ZLIB_DEFLATE
;
14289 if (inflateInit(soap
->d_stream
) != Z_OK
)
14290 return soap
->error
= SOAP_ZLIB_ERROR
;
14292 { if (inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
14293 return soap
->error
= SOAP_ZLIB_ERROR
;
14295 soap
->zlib_state
= SOAP_ZLIB_INFLATE
;
14296 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflate initialized\n"));
14297 soap
->mode
|= SOAP_ENC_ZLIB
;
14299 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
14300 memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
14301 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
14302 soap
->d_stream
->avail_in
= soap
->buflen
- soap
->bufidx
;
14303 soap
->z_buflen
= soap
->buflen
;
14304 soap
->buflen
= soap
->bufidx
;
14307 #ifndef WITH_LEANER
14308 if (soap
->fpreparerecv
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_CHUNK
&& soap
->buflen
> soap
->bufidx
)
14310 if ((r
= soap
->fpreparerecv(soap
, soap
->buf
+ soap
->bufidx
, soap
->buflen
- soap
->bufidx
)))
14311 return soap
->error
= r
;
14315 { if (soap
->error
== SOAP_FORM
&& soap
->fform
)
14316 { soap
->error
= soap
->fform(soap
);
14317 if (soap
->error
== SOAP_OK
)
14318 soap
->error
= SOAP_STOP
; /* prevents further processing */
14320 return soap
->error
;
14324 #ifndef WITH_LEANER
14325 if (soap
->mode
& SOAP_ENC_MIME
)
14326 { do /* skip preamble */
14327 { if ((int)(c
= soap_getchar(soap
)) == EOF
)
14328 return soap
->error
= SOAP_EOF
;
14329 } while (c
!= '-' || soap_get0(soap
) != '-');
14330 soap_unget(soap
, c
);
14331 if (soap_getmimehdr(soap
))
14332 return soap
->error
;
14333 if (soap
->mime
.start
)
14335 { if (!soap
->mime
.last
->id
)
14337 if (!soap_match_cid(soap
, soap
->mime
.start
, soap
->mime
.last
->id
))
14339 } while (soap_get_mime_attachment(soap
, NULL
));
14341 if (soap_get_header_attribute(soap
, soap
->mime
.first
->type
, "application/dime"))
14342 soap
->mode
|= SOAP_ENC_DIME
;
14344 if (soap
->mode
& SOAP_ENC_DIME
)
14345 { if (soap_getdimehdr(soap
))
14346 return soap
->error
;
14347 if (soap
->dime
.flags
& SOAP_DIME_CF
)
14348 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked DIME SOAP message\n"));
14349 soap
->dime
.chunksize
= soap
->dime
.size
;
14350 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.chunksize
)
14351 { soap
->dime
.buflen
= soap
->buflen
;
14352 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
14355 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
14357 soap
->count
= soap
->buflen
- soap
->bufidx
;
14364 /******************************************************************************/
14369 soap_envelope_begin_out(struct soap
*soap
)
14371 #ifndef WITH_LEANER
14373 if ((soap
->mode
& SOAP_ENC_MIME
) && soap
->mime
.boundary
&& soap
->mime
.start
&& strlen(soap
->mime
.boundary
) + strlen(soap
->mime
.start
) < sizeof(soap
->tmpbuf
) - 80 )
14375 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
14376 s
= "application/dime";
14377 else if (soap
->version
== 2)
14378 { if (soap
->mode
& SOAP_ENC_MTOM
)
14379 s
= "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
14381 s
= "application/soap+xml; charset=utf-8";
14383 else if (soap
->mode
& SOAP_ENC_MTOM
)
14384 s
= "application/xop+xml; charset=utf-8; type=\"text/xml\"";
14386 s
= "text/xml; charset=utf-8";
14387 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
);
14388 n
= strlen(soap
->tmpbuf
);
14389 if (soap_send_raw(soap
, soap
->tmpbuf
, n
))
14390 return soap
->error
;
14392 if (soap
->mode
& SOAP_IO_LENGTH
)
14393 soap
->dime
.size
= soap
->count
; /* DIME in MIME correction */
14394 if (!(soap
->mode
& SOAP_IO_LENGTH
) && (soap
->mode
& SOAP_ENC_DIME
))
14395 { if (soap_putdimehdr(soap
))
14396 return soap
->error
;
14399 soap
->part
= SOAP_IN_ENVELOPE
;
14400 return soap_element_begin_out(soap
, "SOAP-ENV:Envelope", 0, NULL
);
14404 /******************************************************************************/
14409 soap_envelope_end_out(struct soap
*soap
)
14410 { if (soap_element_end_out(soap
, "SOAP-ENV:Envelope") || ((soap
->mode
& SOAP_XML_INDENT
) && soap_send_raw(soap
, "\r\n", 2)))
14411 return soap
->error
;
14412 #ifndef WITH_LEANER
14413 if ((soap
->mode
& SOAP_IO_LENGTH
) && (soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
14414 { soap
->dime
.size
= soap
->count
- soap
->dime
.size
; /* DIME in MIME correction */
14415 sprintf(soap
->id
, soap
->dime_id_format
, 0);
14416 soap
->dime
.id
= soap
->id
;
14417 if (soap
->local_namespaces
)
14418 { if (soap
->local_namespaces
[0].out
)
14419 soap
->dime
.type
= (char*)soap
->local_namespaces
[0].out
;
14421 soap
->dime
.type
= (char*)soap
->local_namespaces
[0].ns
;
14423 soap
->dime
.options
= NULL
;
14424 soap
->dime
.flags
= SOAP_DIME_MB
| SOAP_DIME_ABSURI
;
14425 if (!soap
->dime
.first
)
14426 soap
->dime
.flags
|= SOAP_DIME_ME
;
14427 soap
->count
+= 12 + ((strlen(soap
->dime
.id
)+3)&(~3)) + (soap
->dime
.type
? ((strlen(soap
->dime
.type
)+3)&(~3)) : 0);
14429 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
14430 return soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)soap
->dime
.size
&3);
14432 soap
->part
= SOAP_END_ENVELOPE
;
14437 /******************************************************************************/
14443 soap_get_http_body(struct soap
*soap
)
14446 register size_t l
= 0, n
= 0;
14448 /* get HTML body of HTTP error content */
14449 if (!(soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) != SOAP_IO_CHUNK
)
14450 { n
= soap
->length
;
14455 soap
->labidx
= 0; /* use look-aside buffer */
14457 if (soap_new_block(soap
) == NULL
)
14463 register size_t i
, k
;
14464 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
14466 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
14467 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
14468 soap
->labidx
= soap
->lablen
; /* claim this space */
14470 register size_t i
, k
= SOAP_BLKLEN
;
14471 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
14474 for (i
= 0; i
< k
; i
++)
14475 { register soap_wchar c
= soap_getchar(soap
);
14478 *s
++ = (char)(c
& 0xFF);
14480 if (n
> 0 && l
>= n
)
14487 s
= soap_strdup(soap
, soap
->labbuf
);
14489 soap_size_block(soap
, NULL
, i
+1);
14490 s
= soap_save_block(soap
, NULL
, 0);
14500 /******************************************************************************/
14505 soap_envelope_begin_in(struct soap
*soap
)
14506 { register struct Namespace
*p
;
14507 soap
->part
= SOAP_IN_ENVELOPE
;
14508 if (soap_element_begin_in(soap
, "SOAP-ENV:Envelope", 0, NULL
))
14509 { if (soap
->error
== SOAP_TAG_MISMATCH
14510 && !soap_element_begin_in(soap
, "Envelope", 0, NULL
))
14511 soap
->error
= SOAP_VERSIONMISMATCH
;
14512 else if (soap
->status
)
14513 soap
->error
= soap
->status
;
14514 return soap
->error
;
14516 p
= soap
->local_namespaces
;
14518 { const char *ns
= p
[0].out
;
14521 if (!strcmp(ns
, soap_env1
))
14522 { soap
->version
= 1; /* make sure we use SOAP 1.1 */
14524 SOAP_FREE(soap
, p
[1].out
);
14525 if ((p
[1].out
= (char*)SOAP_MALLOC(soap
, sizeof(soap_enc1
))))
14526 strcpy(p
[1].out
, soap_enc1
);
14528 else if (!strcmp(ns
, soap_env2
))
14529 { soap
->version
= 2; /* make sure we use SOAP 1.2 */
14531 SOAP_FREE(soap
, p
[1].out
);
14532 if ((p
[1].out
= (char*)SOAP_MALLOC(soap
, sizeof(soap_enc2
))))
14533 strcpy(p
[1].out
, soap_enc2
);
14540 /******************************************************************************/
14545 soap_envelope_end_in(struct soap
*soap
)
14546 { soap
->part
= SOAP_END_ENVELOPE
;
14547 return soap_element_end_in(soap
, "SOAP-ENV:Envelope");
14551 /******************************************************************************/
14556 soap_body_begin_out(struct soap
*soap
)
14557 { soap
->part
= SOAP_IN_BODY
;
14558 if (soap
->version
== 1)
14559 soap
->encoding
= 1;
14561 if ((soap
->mode
& SOAP_XML_SEC
) && soap_set_attr(soap
, "wsu:Id", "Body", 1))
14562 return soap
->error
;
14564 if (soap_element(soap
, "SOAP-ENV:Body", 0, NULL
))
14565 return soap
->error
;
14566 return soap_element_start_end_out(soap
, NULL
);
14570 /******************************************************************************/
14575 soap_body_end_out(struct soap
*soap
)
14576 { if (soap_element_end_out(soap
, "SOAP-ENV:Body"))
14577 return soap
->error
;
14578 soap
->part
= SOAP_END_BODY
;
14583 /******************************************************************************/
14588 soap_body_begin_in(struct soap
*soap
)
14589 { soap
->part
= SOAP_IN_BODY
;
14590 if (soap_element_begin_in(soap
, "SOAP-ENV:Body", 0, NULL
))
14591 return soap
->error
;
14593 soap
->part
= SOAP_NO_BODY
;
14598 /******************************************************************************/
14603 soap_body_end_in(struct soap
*soap
)
14604 { if (soap
->part
== SOAP_NO_BODY
)
14605 return soap
->error
= SOAP_OK
;
14606 soap
->part
= SOAP_END_BODY
;
14607 return soap_element_end_in(soap
, "SOAP-ENV:Body");
14611 /******************************************************************************/
14616 soap_recv_header(struct soap
*soap
)
14617 { if (soap_getheader(soap
) && soap
->error
== SOAP_TAG_MISMATCH
)
14618 soap
->error
= SOAP_OK
;
14619 if (soap
->error
== SOAP_OK
&& soap
->fheader
)
14620 soap
->error
= soap
->fheader(soap
);
14621 return soap
->error
;
14625 /******************************************************************************/
14630 soap_set_endpoint(struct soap
*soap
, const char *endpoint
)
14631 { register const char *s
;
14632 register size_t i
, n
;
14633 soap
->endpoint
[0] = '\0';
14634 soap
->host
[0] = '\0';
14635 soap
->path
[0] = '/';
14636 soap
->path
[1] = '\0';
14638 if (!endpoint
|| !*endpoint
)
14640 #ifdef WITH_OPENSSL
14641 if (!soap_tag_cmp(endpoint
, "https:*"))
14644 strncpy(soap
->endpoint
, endpoint
, sizeof(soap
->endpoint
) - 1);
14645 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
14646 s
= strchr(endpoint
, ':');
14647 if (s
&& s
[1] == '/' && s
[2] == '/')
14652 if (n
>= sizeof(soap
->host
))
14653 n
= sizeof(soap
->host
) - 1;
14657 for (i
= 0; i
< n
; i
++)
14663 soap
->host
[i
] = s
[i
];
14667 { for (i
= 0; i
< n
; i
++)
14668 { soap
->host
[i
] = s
[i
];
14669 if (s
[i
] == '/' || s
[i
] == ':')
14674 for (i
= 0; i
< n
; i
++)
14675 { soap
->host
[i
] = s
[i
];
14676 if (s
[i
] == '/' || s
[i
] == ':')
14680 soap
->host
[i
] = '\0';
14682 { soap
->port
= (int)soap_strtol(s
+ i
+ 1, NULL
, 10);
14683 for (i
++; i
< n
; i
++)
14688 { strncpy(soap
->path
, s
+ i
, sizeof(soap
->path
));
14689 soap
->path
[sizeof(soap
->path
) - 1] = '\0';
14694 /******************************************************************************/
14699 soap_connect(struct soap
*soap
, const char *endpoint
, const char *action
)
14700 { return soap_connect_command(soap
, SOAP_POST
, endpoint
, action
);
14704 /******************************************************************************/
14709 soap_connect_command(struct soap
*soap
, int http_command
, const char *endpoints
, const char *action
)
14712 if (endpoints
&& (s
= strchr(endpoints
, ' ')))
14713 { endpoint
= (char*)SOAP_MALLOC(soap
, strlen(endpoints
) + 1);
14715 { strncpy(endpoint
, endpoints
, s
- endpoints
);
14716 endpoint
[s
- endpoints
] = '\0';
14717 if (soap_try_connect_command(soap
, http_command
, endpoint
, action
) != SOAP_TCP_ERROR
)
14721 soap
->error
= SOAP_OK
;
14725 s
= strchr(endpoints
, ' ');
14727 s
= endpoints
+ strlen(endpoints
);
14729 SOAP_FREE(soap
, endpoint
);
14732 soap_try_connect_command(soap
, http_command
, endpoints
, action
);
14733 return soap
->error
;
14737 /******************************************************************************/
14740 soap_try_connect_command(struct soap
*soap
, int http_command
, const char *endpoint
, const char *action
)
14741 { char host
[sizeof(soap
->host
)];
14744 soap
->error
= SOAP_OK
;
14745 strcpy(host
, soap
->host
); /* save previous host name: if != then reconnect */
14746 port
= soap
->port
; /* save previous port to compare */
14747 soap
->status
= http_command
;
14748 soap_set_endpoint(soap
, endpoint
);
14749 #ifndef WITH_LEANER
14750 if (soap
->fconnect
)
14751 { if ((soap
->error
= soap
->fconnect(soap
, endpoint
, soap
->host
, soap
->port
)))
14752 return soap
->error
;
14756 if (soap
->fopen
&& *soap
->host
)
14757 { if (!soap
->keep_alive
|| !soap_valid_socket(soap
->socket
) || strcmp(soap
->host
, host
) || soap
->port
!= port
|| !soap
->fpoll
|| soap
->fpoll(soap
))
14758 { soap
->keep_alive
= 0; /* to force close */
14759 soap
->omode
&= ~SOAP_IO_UDP
; /* to force close */
14760 soap_closesock(soap
);
14761 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap
->host
, soap
->path
, soap
->port
));
14763 if (!strncmp(endpoint
, "soap.udp:", 9))
14764 soap
->omode
|= SOAP_IO_UDP
;
14766 soap
->socket
= soap
->fopen(soap
, endpoint
, soap
->host
, soap
->port
);
14768 return soap
->error
;
14769 soap
->keep_alive
= ((soap
->omode
& SOAP_IO_KEEPALIVE
) != 0);
14772 count
= soap_count_attachments(soap
);
14773 if (soap_begin_send(soap
))
14774 return soap
->error
;
14775 if (http_command
== SOAP_GET
)
14776 { soap
->mode
&= ~SOAP_IO
;
14777 soap
->mode
|= SOAP_IO_BUFFER
;
14779 #ifndef WITH_NOHTTP
14780 soap
->action
= soap_strdup(soap
, action
);
14781 if ((soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& !(soap
->mode
& SOAP_ENC_XML
) && endpoint
)
14782 { unsigned int k
= soap
->mode
;
14783 soap
->mode
&= ~(SOAP_IO
| SOAP_ENC_ZLIB
);
14784 if ((k
& SOAP_IO
) != SOAP_IO_FLUSH
)
14785 soap
->mode
|= SOAP_IO_BUFFER
;
14786 if ((soap
->error
= soap
->fpost(soap
, endpoint
, soap
->host
, soap
->port
, soap
->path
, action
, count
)))
14787 return soap
->error
;
14788 #ifndef WITH_LEANER
14789 if ((k
& SOAP_IO
) == SOAP_IO_CHUNK
)
14790 { if (soap_flush(soap
))
14791 return soap
->error
;
14796 if (http_command
== SOAP_GET
)
14797 return soap_end_send(soap
);
14803 /******************************************************************************/
14808 soap_s2base64(struct soap
*soap
, const unsigned char *s
, char *t
, int n
)
14810 register unsigned long m
;
14813 t
= (char*)soap_malloc(soap
, (n
+ 2) / 3 * 4 + 1);
14820 for (; n
> 2; n
-= 3, s
+= 3)
14822 m
= (m
<< 8) | s
[1];
14823 m
= (m
<< 8) | s
[2];
14824 for (i
= 4; i
> 0; m
>>= 6)
14825 t
[--i
] = soap_base64o
[m
& 0x3F];
14831 for (i
= 0; i
< n
; i
++)
14832 m
= (m
<< 8) | *s
++;
14835 for (i
++; i
> 0; m
>>= 6)
14836 t
[--i
] = soap_base64o
[m
& 0x3F];
14837 for (i
= 3; i
> n
; i
--)
14845 /******************************************************************************/
14850 soap_base642s(struct soap
*soap
, const char *s
, char *t
, size_t l
, int *n
)
14851 { register int i
, j
, c
;
14852 register unsigned long m
;
14853 register const char *p
;
14859 return SOAP_NON_NULL
;
14862 { l
= (strlen(s
) + 3) / 4 * 3;
14863 t
= (char*)soap_malloc(soap
, l
);
14871 { for (i
= 0; i
< SOAP_BLKLEN
; i
++)
14876 if (c
== '=' || !c
)
14880 *t
++ = (char)((m
>> 4) & 0xFF);
14884 *t
++ = (char)((m
>> 10) & 0xFF);
14885 *t
++ = (char)((m
>> 2) & 0xFF);
14893 if (c
>= 0 && c
<= 79)
14894 { int b
= soap_base64i
[c
];
14896 { soap
->error
= SOAP_TYPE
;
14902 else if (!soap_blank(c
+ '+'))
14903 { soap
->error
= SOAP_TYPE
;
14907 *t
++ = (char)((m
>> 16) & 0xFF);
14908 *t
++ = (char)((m
>> 8) & 0xFF);
14909 *t
++ = (char)(m
& 0xFF);
14918 *n
+= 3 * SOAP_BLKLEN
;
14923 /******************************************************************************/
14928 soap_s2hex(struct soap
*soap
, const unsigned char *s
, char *t
, int n
)
14929 { register char *p
;
14931 t
= (char*)soap_malloc(soap
, 2 * n
+ 1);
14937 { for (; n
> 0; n
--)
14938 { register int m
= *s
++;
14939 *t
++ = (char)((m
>> 4) + (m
> 159 ? 'a' - 10 : '0'));
14941 *t
++ = (char)(m
+ (m
> 9 ? 'a' - 10 : '0'));
14949 /******************************************************************************/
14954 soap_hex2s(struct soap
*soap
, const char *s
, char *t
, size_t l
, int *n
)
14955 { register const char *p
;
14961 return SOAP_NON_NULL
;
14964 { l
= strlen(s
) / 2;
14965 t
= (char*)soap_malloc(soap
, l
);
14971 { register int d1
, d2
;
14978 *t
++ = ((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0');
14987 /******************************************************************************/
14988 #ifndef WITH_NOHTTP
14993 soap_puthttphdr(struct soap
*soap
, int status
, size_t count
)
14994 { if (soap
->status
!= SOAP_GET
)
14995 { register const char *s
= "text/xml; charset=utf-8";
14996 register int err
= SOAP_OK
;
14997 #ifndef WITH_LEANER
14998 register const char *r
= NULL
;
15000 if ((status
== SOAP_FILE
|| soap
->status
== SOAP_POST_FILE
) && soap
->http_content
)
15001 s
= soap
->http_content
;
15002 else if (status
== SOAP_HTML
)
15003 s
= "text/html; charset=utf-8";
15004 else if (count
|| ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
))
15005 { if (soap
->version
== 2)
15006 s
= "application/soap+xml; charset=utf-8";
15008 #ifndef WITH_LEANER
15009 if (soap
->mode
& (SOAP_ENC_DIME
| SOAP_ENC_MTOM
))
15010 { if (soap
->mode
& SOAP_ENC_MTOM
)
15011 { if (soap
->version
== 2)
15012 r
= "application/soap+xml";
15015 s
= "application/xop+xml";
15018 s
= "application/dime";
15020 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)
15021 { register const char *t
= strchr(s
, ';');
15022 sprintf(soap
->tmpbuf
, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap
->mime
.boundary
);
15024 { strncat(soap
->tmpbuf
, s
, t
- s
);
15025 soap
->tmpbuf
[sizeof(soap
->tmpbuf
)-1] = '\0';
15028 strcat(soap
->tmpbuf
, s
);
15029 if (soap
->mime
.start
)
15030 { strcat(soap
->tmpbuf
, "\"; start=\"");
15031 strcat(soap
->tmpbuf
, soap
->mime
.start
);
15033 strcat(soap
->tmpbuf
, "\"");
15035 { strcat(soap
->tmpbuf
, "; start-info=\"");
15036 strcat(soap
->tmpbuf
, r
);
15037 strcat(soap
->tmpbuf
, "\"");
15041 else if (status
== SOAP_OK
&& soap
->action
&& strlen(soap
->action
) < sizeof(soap
->tmpbuf
) - 80)
15042 { sprintf(soap
->tmpbuf
, "%s; action=\"%s\"", s
, soap
->action
);
15046 if (s
&& (err
= soap
->fposthdr(soap
, "Content-Type", s
)))
15049 if ((soap
->omode
& SOAP_ENC_ZLIB
))
15052 err
= soap
->fposthdr(soap
, "Content-Encoding", soap
->zlib_out
== SOAP_ZLIB_DEFLATE
? "deflate" : "gzip");
15054 err
= soap
->fposthdr(soap
, "Content-Encoding", "deflate");
15060 #ifndef WITH_LEANER
15061 if ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
)
15062 err
= soap
->fposthdr(soap
, "Transfer-Encoding", "chunked");
15066 { sprintf(soap
->tmpbuf
, "%lu", (unsigned long)count
);
15067 err
= soap
->fposthdr(soap
, "Content-Length", soap
->tmpbuf
);
15072 return soap
->fposthdr(soap
, "Connection", soap
->keep_alive
? "keep-alive" : "close");
15077 /******************************************************************************/
15080 soap_set_validation_fault(struct soap
*soap
, const char *s
, const char *t
)
15082 sprintf(soap
->msgbuf
, "Validation constraint violation: %s%s in element '%s'", s
, t
?t
:SOAP_STR_EOS
, soap
->tag
);
15084 sprintf(soap
->msgbuf
, "Validation constraint violation: %s%s", s
, t
?t
:SOAP_STR_EOS
);
15085 return soap
->msgbuf
;
15089 /******************************************************************************/
15094 soap_set_fault(struct soap
*soap
)
15095 { const char **c
= soap_faultcode(soap
);
15096 const char **s
= soap_faultstring(soap
);
15097 if (soap
->fseterror
)
15098 soap
->fseterror(soap
, c
, s
);
15100 { if (soap
->version
== 2)
15101 *c
= "SOAP-ENV:Sender";
15103 *c
= "SOAP-ENV:Client";
15107 switch (soap
->error
)
15110 case SOAP_CLI_FAULT
:
15111 *s
= "Client fault";
15113 case SOAP_SVR_FAULT
:
15114 *s
= "Server fault";
15116 case SOAP_TAG_MISMATCH
:
15117 *s
= soap_set_validation_fault(soap
, "tag name or namespace mismatch", NULL
);
15120 *s
= soap_set_validation_fault(soap
, "data type mismatch ", soap
->type
);
15122 case SOAP_SYNTAX_ERROR
:
15123 *s
= "Well-formedness violation";
15126 *s
= "No XML root element";
15128 case SOAP_MUSTUNDERSTAND
:
15129 *c
= "SOAP-ENV:MustUnderstand";
15130 sprintf(soap
->msgbuf
, "The data in element '%s' must be understood but cannot be handled", soap
->tag
);
15133 case SOAP_VERSIONMISMATCH
:
15134 *c
= "SOAP-ENV:VersionMismatch";
15135 *s
= "Invalid SOAP message or SOAP version mismatch";
15137 case SOAP_DATAENCODINGUNKNOWN
:
15138 *c
= "SOAP-ENV:DataEncodingUnknown";
15139 *s
= "Unsupported SOAP data encoding";
15141 case SOAP_NAMESPACE
:
15142 *s
= soap_set_validation_fault(soap
, "namespace error", NULL
);
15144 case SOAP_USER_ERROR
:
15147 case SOAP_FATAL_ERROR
:
15148 *s
= "Fatal error";
15150 case SOAP_NO_METHOD
:
15151 sprintf(soap
->msgbuf
, "Method '%s' not implemented: method name or namespace not recognized", soap
->tag
);
15155 *s
= "Data required for operation";
15157 case SOAP_GET_METHOD
:
15158 *s
= "HTTP GET method not implemented";
15160 case SOAP_PUT_METHOD
:
15161 *s
= "HTTP PUT method not implemented";
15163 case SOAP_HTTP_METHOD
:
15164 *s
= "HTTP method not implemented";
15167 *s
= "Out of memory";
15170 *s
= "Memory overflow or memory corruption error";
15173 *s
= "Header line too long";
15176 *s
= "Array index out of bounds";
15179 *s
= soap_set_validation_fault(soap
, "nil not allowed", NULL
);
15181 case SOAP_DUPLICATE_ID
:
15182 *s
= soap_set_validation_fault(soap
, "multiple definitions of id ", soap
->id
);
15183 if (soap
->version
== 2)
15184 *soap_faultsubcode(soap
) = "SOAP-ENC:DuplicateID";
15186 case SOAP_MISSING_ID
:
15187 *s
= soap_set_validation_fault(soap
, "missing id for ref ", soap
->id
);
15188 if (soap
->version
== 2)
15189 *soap_faultsubcode(soap
) = "SOAP-ENC:MissingID";
15192 *s
= soap_set_validation_fault(soap
, "incompatible object type ref/id pair ", soap
->id
);
15197 case SOAP_UDP_ERROR
:
15198 *s
= "Message too large for UDP packet";
15200 case SOAP_TCP_ERROR
:
15201 *s
= tcp_error(soap
);
15204 case SOAP_HTTP_ERROR
:
15205 *s
= "An HTTP processing error occurred";
15207 case SOAP_SSL_ERROR
:
15208 #ifdef WITH_OPENSSL
15209 *s
= "SSL/TLS error";
15211 *s
= "OpenSSL not installed: recompile with -DWITH_OPENSSL";
15214 case SOAP_PLUGIN_ERROR
:
15215 *s
= "Plugin registry error";
15217 case SOAP_DIME_ERROR
:
15218 *s
= "DIME format error";
15220 case SOAP_DIME_HREF
:
15221 *s
= "DIME href to missing attachment";
15223 case SOAP_DIME_MISMATCH
:
15224 *s
= "DIME version/transmission error";
15226 case SOAP_DIME_END
:
15227 *s
= "End of DIME error";
15229 case SOAP_MIME_ERROR
:
15230 *s
= "MIME format error";
15232 case SOAP_MIME_HREF
:
15233 *s
= "MIME href to missing attachment";
15235 case SOAP_MIME_END
:
15236 *s
= "End of MIME error";
15238 case SOAP_ZLIB_ERROR
:
15240 sprintf(soap
->msgbuf
, "Zlib/gzip error: '%s'", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
);
15243 *s
= "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
15246 case SOAP_REQUIRED
:
15247 *s
= soap_set_validation_fault(soap
, "missing required attribute", NULL
);
15249 case SOAP_PROHIBITED
:
15250 *s
= soap_set_validation_fault(soap
, "prohibited attribute present", NULL
);
15253 *s
= soap_set_validation_fault(soap
, "occurrence violation", NULL
);
15256 *s
= soap_set_validation_fault(soap
, "content range or length violation", NULL
);
15258 case SOAP_FD_EXCEEDED
:
15259 *s
= "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
15262 *s
= "Stopped: no response to be sent or received (informative)";
15267 strcpy(soap
->msgbuf
, soap_strerror(soap
));
15269 if (strlen(soap
->msgbuf
) + 25 < sizeof(soap
->msgbuf
))
15270 { memmove(soap
->msgbuf
+ 25, soap
->msgbuf
, strlen(soap
->msgbuf
) + 1);
15271 memcpy(soap
->msgbuf
, "End of file or no input: ", 25);
15277 *s
= "End of file or no input";
15281 #ifndef WITH_NOHTTP
15283 if (soap
->error
> 200 && soap
->error
< 600)
15284 { sprintf(soap
->msgbuf
, "HTTP Error: %d %s", soap
->error
, http_error(soap
, soap
->error
));
15290 { sprintf(soap
->msgbuf
, "Error %d", soap
->error
);
15297 /******************************************************************************/
15302 soap_send_fault(struct soap
*soap
)
15303 { register int status
= soap
->error
;
15304 if (status
== SOAP_STOP
)
15305 return soap_closesock(soap
);
15306 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Sending back fault struct for error code %d\n", soap
->error
));
15307 soap
->keep_alive
= 0; /* to terminate connection */
15308 soap_set_fault(soap
);
15309 if (soap
->error
< 200 && soap
->error
!= SOAP_FAULT
)
15310 soap
->header
= NULL
;
15311 if (status
!= SOAP_EOF
|| (!soap
->recv_timeout
&& !soap
->send_timeout
))
15314 if (soap
->fpoll
&& soap
->fpoll(soap
))
15317 else if (soap_valid_socket(soap
->socket
))
15318 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_SND
, 0);
15320 { if (!(r
& SOAP_TCP_SELECT_SND
)
15321 || ((r
& SOAP_TCP_SELECT_RCV
)
15322 && recv(soap
->socket
, soap
->tmpbuf
, 1, MSG_PEEK
) < 0))
15329 { soap
->error
= SOAP_OK
;
15330 soap_serializeheader(soap
);
15331 soap_serializefault(soap
);
15332 soap_begin_count(soap
);
15333 if (soap
->mode
& SOAP_IO_LENGTH
)
15334 { soap_envelope_begin_out(soap
);
15335 soap_putheader(soap
);
15336 soap_body_begin_out(soap
);
15337 soap_putfault(soap
);
15338 soap_body_end_out(soap
);
15339 soap_envelope_end_out(soap
);
15341 soap_end_count(soap
);
15342 if (soap_response(soap
, status
)
15343 || soap_envelope_begin_out(soap
)
15344 || soap_putheader(soap
)
15345 || soap_body_begin_out(soap
)
15346 || soap_putfault(soap
)
15347 || soap_body_end_out(soap
)
15348 || soap_envelope_end_out(soap
))
15349 return soap_closesock(soap
);
15350 soap_end_send(soap
);
15353 soap
->error
= status
;
15354 return soap_closesock(soap
);
15358 /******************************************************************************/
15363 soap_recv_fault(struct soap
*soap
, int check
)
15364 { register int status
= soap
->error
;
15365 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Check if receiving SOAP Fault\n"));
15367 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
15368 if (soap
->error
!= SOAP_NO_TAG
15369 && (soap
->error
!= SOAP_TAG_MISMATCH
|| soap
->level
!= 2))
15370 return soap
->error
;
15372 soap
->error
= SOAP_OK
;
15373 if (soap_getfault(soap
))
15374 { /* check flag set: check if SOAP Fault is present, if not just return */
15375 if (check
&& soap
->error
== SOAP_TAG_MISMATCH
&& soap
->level
== 2)
15376 return soap
->error
= SOAP_OK
;
15377 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
15378 *soap_faultcode(soap
) = (soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
15379 soap
->error
= status
;
15380 soap_set_fault(soap
);
15383 { register const char *s
= *soap_faultcode(soap
);
15384 if (!soap_match_tag(soap
, s
, "SOAP-ENV:Server") || !soap_match_tag(soap
, s
, "SOAP-ENV:Receiver"))
15385 status
= SOAP_SVR_FAULT
;
15386 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:Client") || !soap_match_tag(soap
, s
, "SOAP-ENV:Sender"))
15387 status
= SOAP_CLI_FAULT
;
15388 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:MustUnderstand"))
15389 status
= SOAP_MUSTUNDERSTAND
;
15390 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:VersionMismatch"))
15391 status
= SOAP_VERSIONMISMATCH
;
15393 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Received SOAP Fault code %s\n", s
));
15394 status
= SOAP_FAULT
;
15396 if (!soap_body_end_in(soap
))
15397 soap_envelope_end_in(soap
);
15399 soap_end_recv(soap
);
15400 soap
->error
= status
;
15401 return soap_closesock(soap
);
15405 /******************************************************************************/
15406 #ifndef WITH_NOHTTP
15411 soap_send_empty_response(struct soap
*soap
, int httpstatuscode
)
15412 { register soap_mode m
= soap
->omode
;
15414 if ((m
& SOAP_IO
) == SOAP_IO_CHUNK
)
15415 soap
->omode
= (m
& ~SOAP_IO
) | SOAP_IO_BUFFER
;
15416 if (soap_response(soap
, httpstatuscode
) || soap_end_send(soap
))
15418 return soap_closesock(soap
);
15421 return soap
->error
= SOAP_STOP
; /* stops the server's response */
15426 /******************************************************************************/
15427 #ifndef WITH_NOHTTP
15432 soap_recv_empty_response(struct soap
*soap
)
15433 { if (!soap_begin_recv(soap
))
15434 soap_end_recv(soap
);
15435 else if (soap
->error
== SOAP_NO_DATA
|| soap
->error
== 202)
15436 soap
->error
= SOAP_OK
;
15437 return soap_closesock(soap
);
15442 /******************************************************************************/
15446 soap_strerror(struct soap
*soap
)
15447 { register int err
= soap
->errnum
;
15451 # ifdef HAVE_STRERROR_R
15452 strerror_r(err
, soap
->msgbuf
, sizeof(soap
->msgbuf
));
15454 return strerror(err
);
15459 *soap
->msgbuf
= '\0';
15460 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
);
15463 *soap
->msgbuf
= '\0';
15464 len
= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, err
, 0, (LPTSTR
)soap
->msgbuf
, (DWORD
)(sizeof(soap
->msgbuf
)/sizeof(TCHAR
)), NULL
);
15465 for (i
= 0; i
<= len
; i
++)
15466 { if (((TCHAR
*)soap
->msgbuf
)[i
] < 0x80)
15467 soap
->msgbuf
[i
] = (char)((TCHAR
*)soap
->msgbuf
)[i
];
15469 soap
->msgbuf
[i
] = '?';
15475 { char *s
= soap
->msgbuf
;
15477 int rt
= soap
->recv_timeout
, st
= soap
->send_timeout
;
15478 int ru
= ' ', su
= ' ';
15480 strcpy(s
, "Operation interrupted or timed out");
15491 sprintf(s
+ strlen(s
), " (%d%cs receive delay)", rt
, ru
);
15493 sprintf(s
+ strlen(s
), " (%d%cs send delay)", st
, su
);
15496 return soap
->msgbuf
;
15501 /******************************************************************************/
15504 soap_set_error(struct soap
*soap
, const char *faultcode
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
15505 { *soap_faultcode(soap
) = faultcode
;
15506 if (faultsubcodeQName
)
15507 *soap_faultsubcode(soap
) = faultsubcodeQName
;
15508 *soap_faultstring(soap
) = faultstring
;
15509 if (faultdetailXML
&& *faultdetailXML
)
15510 { register const char **s
= soap_faultdetail(soap
);
15512 *s
= faultdetailXML
;
15514 return soap
->error
= soaperror
;
15518 /******************************************************************************/
15523 soap_set_sender_error(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
15524 { return soap_set_error(soap
, soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL
, faultstring
, faultdetailXML
, soaperror
);
15528 /******************************************************************************/
15533 soap_set_receiver_error(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
15534 { return soap_set_error(soap
, soap
->version
== 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL
, faultstring
, faultdetailXML
, soaperror
);
15538 /******************************************************************************/
15541 soap_copy_fault(struct soap
*soap
, const char *faultcode
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
15542 { char *r
= NULL
, *s
= NULL
, *t
= NULL
;
15543 if (faultsubcodeQName
)
15544 r
= soap_strdup(soap
, faultsubcodeQName
);
15546 s
= soap_strdup(soap
, faultstring
);
15547 if (faultdetailXML
)
15548 t
= soap_strdup(soap
, faultdetailXML
);
15549 return soap_set_error(soap
, faultcode
, r
, s
, t
, SOAP_FAULT
);
15553 /******************************************************************************/
15558 soap_sender_fault(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
)
15559 { return soap_sender_fault_subcode(soap
, NULL
, faultstring
, faultdetailXML
);
15563 /******************************************************************************/
15568 soap_sender_fault_subcode(struct soap
*soap
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
15569 { return soap_copy_fault(soap
, soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName
, faultstring
, faultdetailXML
);
15573 /******************************************************************************/
15578 soap_receiver_fault(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
)
15579 { return soap_receiver_fault_subcode(soap
, NULL
, faultstring
, faultdetailXML
);
15583 /******************************************************************************/
15588 soap_receiver_fault_subcode(struct soap
*soap
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
15589 { return soap_copy_fault(soap
, soap
->version
== 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName
, faultstring
, faultdetailXML
);
15593 /******************************************************************************/
15595 #ifndef WITH_NOSTDLIB
15599 soap_print_fault(struct soap
*soap
, FILE *fd
)
15600 { if (soap_check_state(soap
))
15601 fprintf(fd
, "Error: soap struct state not initialized\n");
15602 else if (soap
->error
)
15603 { const char *c
, *v
= NULL
, *s
, **d
;
15604 d
= soap_faultcode(soap
);
15606 soap_set_fault(soap
);
15608 if (soap
->version
== 2)
15609 v
= *soap_faultsubcode(soap
);
15610 s
= *soap_faultstring(soap
);
15611 d
= soap_faultdetail(soap
);
15612 fprintf(fd
, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap
->version
? "SOAP 1." : "Error ", soap
->version
? (int)soap
->version
: soap
->error
, c
, v
? v
: "no subcode", s
? s
: "[no reason]", d
&& *d
? *d
: "[no detail]");
15618 /******************************************************************************/
15621 #ifndef WITH_NOSTDLIB
15625 soap_stream_fault(struct soap
*soap
, std::ostream
& os
)
15626 { if (soap_check_state(soap
))
15627 os
<< "Error: soap struct state not initialized\n";
15628 else if (soap
->error
)
15629 { const char *c
, *v
= NULL
, *s
, **d
;
15630 d
= soap_faultcode(soap
);
15632 soap_set_fault(soap
);
15634 if (soap
->version
== 2)
15635 v
= *soap_faultsubcode(soap
);
15636 s
= *soap_faultstring(soap
);
15637 d
= soap_faultdetail(soap
);
15638 os
<< (soap
->version
? "SOAP 1." : "Error ")
15639 << (soap
->version
? (int)soap
->version
: soap
->error
)
15641 << "[" << (v
? v
: "no subcode") << "]"
15643 << "\"" << (s
? s
: "[no reason]") << "\""
15645 << "Detail: " << (d
&& *d
? *d
: "[no detail]")
15653 /******************************************************************************/
15655 #ifndef WITH_NOSTDLIB
15659 soap_sprint_fault(struct soap
*soap
, char *buf
, size_t len
)
15660 { if (soap_check_state(soap
))
15661 strncpy(buf
, "Error: soap struct not initialized", len
);
15662 else if (soap
->error
)
15663 { const char *c
, *v
= NULL
, *s
, **d
;
15664 d
= soap_faultcode(soap
);
15666 soap_set_fault(soap
);
15668 if (soap
->version
== 2)
15669 v
= *soap_faultsubcode(soap
);
15670 s
= *soap_faultstring(soap
);
15671 d
= soap_faultdetail(soap
);
15672 #ifdef HAVE_SNPRINTF
15678 (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
? *d
: "[no detail]");
15680 if (len
> 40 + (v
? strlen(v
) : 0) + (s
? strlen(s
) : 0) + (d
&& *d
? strlen(*d
) : 0))
15681 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
? *d
: "[no detail]");
15683 sprintf(buf
, "%s%d fault: %s\n", soap
->version
? "SOAP 1." : "Error ", soap
->version
? (int)soap
->version
: soap
->error
, c
);
15693 /******************************************************************************/
15695 #ifndef WITH_NOSTDLIB
15699 soap_print_fault_location(struct soap
*soap
, FILE *fd
)
15703 if (soap
->error
&& soap
->error
!= SOAP_STOP
&& soap
->bufidx
<= soap
->buflen
&& soap
->buflen
> 0 && soap
->buflen
<= SOAP_BUFLEN
)
15704 { i
= (int)soap
->bufidx
- 1;
15708 soap
->buf
[i
] = '\0';
15709 if ((int)soap
->buflen
>= i
+ 1024)
15712 j
= (int)soap
->buflen
- 1;
15714 soap
->buf
[j
] = '\0';
15715 fprintf(fd
, "%s%c\n<!-- ** HERE ** -->\n", soap
->buf
, c1
);
15716 if (soap
->bufidx
< soap
->buflen
)
15717 fprintf(fd
, "%s\n", soap
->buf
+ soap
->bufidx
);
15726 /******************************************************************************/
15731 soap_register_plugin_arg(struct soap
*soap
, int (*fcreate
)(struct soap
*, struct soap_plugin
*, void*), void *arg
)
15732 { register struct soap_plugin
*p
;
15734 if (!(p
= (struct soap_plugin
*)SOAP_MALLOC(soap
, sizeof(struct soap_plugin
))))
15735 return soap
->error
= SOAP_EOM
;
15740 r
= fcreate(soap
, p
, arg
);
15741 if (!r
&& p
->fdelete
)
15742 { p
->next
= soap
->plugins
;
15744 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Registered '%s' plugin\n", p
->id
));
15747 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
));
15748 SOAP_FREE(soap
, p
);
15753 /******************************************************************************/
15756 fplugin(struct soap
*soap
, const char *id
)
15757 { register struct soap_plugin
*p
;
15758 for (p
= soap
->plugins
; p
; p
= p
->next
)
15759 if (p
->id
== id
|| !strcmp(p
->id
, id
))
15765 /******************************************************************************/
15770 soap_lookup_plugin(struct soap
*soap
, const char *id
)
15771 { return soap
->fplugin(soap
, id
);
15775 /******************************************************************************/
15780 /******************************************************************************\
15782 * C++ soap struct methods
15784 \******************************************************************************/
15792 /******************************************************************************/
15794 soap::soap(soap_mode m
)
15795 { soap_init1(this, m
);
15799 /******************************************************************************/
15801 soap::soap(soap_mode im
, soap_mode om
)
15802 { soap_init2(this, im
, om
);
15806 /******************************************************************************/
15808 soap::soap(const struct soap
& soap
)
15809 { soap_copy_context(this, &soap
);
15813 /******************************************************************************/
15816 { soap_destroy(this);
15822 /******************************************************************************/