4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
30 gSOAP XML Web services tools
31 Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc., All Rights Reserved.
32 This part of the software is released under ONE of the following licenses:
33 GPL, or the gSOAP public license, or Genivia's license for commercial use.
34 --------------------------------------------------------------------------------
37 Oracle, Inc. - additions are noted in the code commented with
38 "Oracle customization"
39 - customization of the SSL accept timeout
40 - work around for SSL_Sleep reporting closed connection
41 - Function ssl_auth_init was static, but is now exported for external override
42 - redirection of gSoap debug logs when debug builds enabled
43 - added SSL_CTX_set_cipher_list call to restrict the cipher suite to RSA-2048/AES
44 TLS_RSA_WITH_AES_256_CBC_SHA is defined in RFC 3268
45 also see http://www.openssl.org/docs/apps/ciphers.html
46 - Added SSL_OP_NO_SSLv3 to force use of TLS
47 - bug fix: added call to close socket handle in various places noted in the code,
48 since the caller overwrites soap->socket with the return value
49 - compile warning cleanup
52 Wind River Systems Inc., for the following additions under gSOAP public license:
54 --------------------------------------------------------------------------------
57 The contents of this file are subject to the gSOAP Public License Version 1.3
58 (the "License"); you may not use this file except in compliance with the
59 License. You may obtain a copy of the License at
60 http://www.cs.fsu.edu/~engelen/soaplicense.html
61 Software distributed under the License is distributed on an "AS IS" basis,
62 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
63 for the specific language governing rights and limitations under the License.
65 The Initial Developer of the Original Code is Robert A. van Engelen.
66 Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc., All Rights Reserved.
67 --------------------------------------------------------------------------------
70 This program is free software; you can redistribute it and/or modify it under
71 the terms of the GNU General Public License as published by the Free Software
72 Foundation; either version 2 of the License, or (at your option) any later
75 This program is distributed in the hope that it will be useful, but WITHOUT ANY
76 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
77 PARTICULAR PURPOSE. See the GNU General Public License for more details.
79 You should have received a copy of the GNU General Public License along with
80 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
81 Place, Suite 330, Boston, MA 02111-1307 USA
83 Author contact information:
84 engelen@genivia.com / engelen@acm.org
86 This program is released under the GPL with the additional exemption that
87 compiling, linking, and/or using OpenSSL is allowed.
88 --------------------------------------------------------------------------------
89 A commercial use license is available from Genivia, Inc., contact@genivia.com
90 --------------------------------------------------------------------------------
94 Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
95 To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
96 tab (the project file needs to be selected in the file view) and add
97 "wsock32.lib" to the "Object/library modules" entry
99 On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
100 -fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
101 when locally allocated data exceeds 64K.
106 # pragma convert(819) /* EBCDIC to ASCII */
109 #include "stdsoap2.h"
112 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
115 #ifdef OPENSSL_NO_DEPRECATED
116 #include <openssl/rsa.h>
117 #include <openssl/bn.h>
118 #include <openssl/dh.h>
122 #ifdef SOAP_MEM_DEBUG
124 #include <ucontext.h> /* Oracle customization (for printstack(3C)) */
133 # pragma comment(lib, "winsock.lib")
135 # pragma comment(lib, "wsock32.lib")
137 # pragma warning(disable : 4996) /* disable deprecation warnings */
142 SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.17 2010-05-10 00:00:00 GMT")
145 SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.17 2010-05-10 00:00:00 GMT")
148 /* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
149 #ifndef SOAP_UNKNOWN_CHAR
150 #define SOAP_UNKNOWN_CHAR (127)
154 #define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
155 #define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
156 #define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
157 #define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
158 #define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
160 #define soap_blank(c) ((c) >= 0 && (c) <= 32)
161 #define soap_notblank(c) ((c) > 32)
163 #if defined(WIN32) && !defined(UNDER_CE)
164 #define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
166 #define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
169 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
170 static void soap_init_logs(struct soap
*);
173 static void soap_close_logfile(struct soap
*, int);
174 static void soap_set_logfile(struct soap
*, int, const char*);
177 #ifdef SOAP_MEM_DEBUG
178 static void soap_init_mht(struct soap
*);
179 static void soap_free_mht(struct soap
*);
180 static void soap_track_unlink(struct soap
*, const void*);
184 static int soap_set_error(struct soap
*, const char*, const char*, const char*, const char*, int);
185 static int soap_copy_fault(struct soap
*, const char*, const char*, const char*, const char*);
186 static int soap_getattrval(struct soap
*, char*, size_t, soap_wchar
);
190 static void soap_free_ns(struct soap
*soap
);
191 static soap_wchar
soap_char(struct soap
*);
192 static soap_wchar
soap_get_pi(struct soap
*);
193 static int soap_isxdigit(int);
194 static void *fplugin(struct soap
*, const char*);
195 static char *soap_get_http_body(struct soap
*);
196 static size_t soap_count_attachments(struct soap
*soap
);
197 static int soap_try_connect_command(struct soap
*, int http_command
, const char *endpoint
, const char *action
);
199 static void soap_update_ptrs(struct soap
*, char*, char*, char*, char*);
200 static int soap_has_copies(struct soap
*, const char*, const char*);
201 static void soap_init_iht(struct soap
*);
202 static void soap_free_iht(struct soap
*);
203 static void soap_init_pht(struct soap
*);
204 static void soap_free_pht(struct soap
*);
209 static const char *soap_set_validation_fault(struct soap
*, const char*, const char*);
210 static int soap_isnumeric(struct soap
*, const char*);
211 static struct soap_nlist
*soap_push_ns(struct soap
*soap
, const char *id
, const char *ns
, short utilized
);
212 static void soap_utilize_ns(struct soap
*soap
, const char *tag
, size_t n
);
217 static struct soap_multipart
*soap_new_multipart(struct soap
*, struct soap_multipart
**, struct soap_multipart
**, char*, size_t);
218 static int soap_putdimefield(struct soap
*, const char*, size_t);
219 static char *soap_getdimefield(struct soap
*, size_t);
220 static void soap_select_mime_boundary(struct soap
*);
221 static int soap_valid_mime_boundary(struct soap
*);
222 static void soap_resolve_attachment(struct soap
*, struct soap_multipart
*);
227 static int soap_getgziphdr(struct soap
*);
231 int soap_ssl_init_done
= 0;
234 // Oracle customization
236 // Function ssl_auth_init was static, but is now exported for external override
238 static int ssl_auth_init(struct soap*);
240 int ssl_auth_init(struct soap
*);
241 static int ssl_verify_callback(int, X509_STORE_CTX
*);
242 static int ssl_verify_callback_allow_expired_certificate(int, X509_STORE_CTX
*);
243 static int ssl_password(char*, int, int, void *);
246 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
248 static const char *soap_decode(char*, size_t, const char*, const char*);
254 static soap_wchar
soap_getchunkchar(struct soap
*);
255 static const char *http_error(struct soap
*, int);
256 static int http_get(struct soap
*);
257 static int http_405(struct soap
*);
258 static int http_post(struct soap
*, const char*, const char*, int, const char*, const char*, size_t);
259 static int http_send_header(struct soap
*, const char*);
260 static int http_post_header(struct soap
*, const char*, const char*);
261 static int http_response(struct soap
*, int, size_t);
262 static int http_parse(struct soap
*);
263 static int http_parse_header(struct soap
*, const char*, const char*);
270 static int fsend(struct soap
*, const char*, size_t);
271 static size_t frecv(struct soap
*, char*, size_t);
272 static int tcp_init(struct soap
*);
273 static const char *tcp_error(struct soap
*);
275 static int tcp_gethost(struct soap
*, const char *addr
, struct in_addr
*inaddr
);
277 static SOAP_SOCKET
tcp_connect(struct soap
*, const char *endpoint
, const char *host
, int port
);
278 static SOAP_SOCKET
tcp_accept(struct soap
*, SOAP_SOCKET
, struct sockaddr
*, int*);
279 static int tcp_select(struct soap
*, SOAP_SOCKET
, int, int);
280 static int tcp_disconnect(struct soap
*);
281 static int tcp_closesocket(struct soap
*, SOAP_SOCKET
);
282 static int tcp_shutdownsocket(struct soap
*, SOAP_SOCKET
, int);
283 static const char *soap_strerror(struct soap
*);
286 #define SOAP_TCP_SELECT_RCV 0x1
287 #define SOAP_TCP_SELECT_SND 0x2
288 #define SOAP_TCP_SELECT_ERR 0x4
289 #define SOAP_TCP_SELECT_ALL 0x7
292 #define SOAP_SOCKBLOCK(fd) \
293 { u_long blocking = 0; \
294 ioctlsocket(fd, FIONBIO, &blocking); \
296 #define SOAP_SOCKNONBLOCK(fd) \
297 { u_long nonblocking = 1; \
298 ioctlsocket(fd, FIONBIO, &nonblocking); \
300 #elif defined(VXWORKS)
301 #define SOAP_SOCKBLOCK(fd) \
302 { u_long blocking = 0; \
303 ioctl(fd, FIONBIO, (int)(&blocking)); \
305 #define SOAP_SOCKNONBLOCK(fd) \
306 { u_long nonblocking = 1; \
307 ioctl(fd, FIONBIO, (int)(&nonblocking)); \
310 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK);
311 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
312 #elif defined(SYMBIAN)
313 #define SOAP_SOCKBLOCK(fd) \
314 { long blocking = 0; \
315 ioctl(fd, 0/*FIONBIO*/, &blocking); \
317 #define SOAP_SOCKNONBLOCK(fd) \
318 { long nonblocking = 1; \
319 ioctl(fd, 0/*FIONBIO*/, &nonblocking); \
322 #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
323 #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
328 #if defined(PALM) && !defined(PALM_2)
329 unsigned short errno
;
333 static const char soap_env1
[42] = "http://schemas.xmlsoap.org/soap/envelope/";
334 static const char soap_enc1
[42] = "http://schemas.xmlsoap.org/soap/encoding/";
335 static const char soap_env2
[40] = "http://www.w3.org/2003/05/soap-envelope";
336 static const char soap_enc2
[40] = "http://www.w3.org/2003/05/soap-encoding";
337 static const char soap_rpc
[35] = "http://www.w3.org/2003/05/soap-rpc";
341 const struct soap_double_nan soap_double_nan
= {0xFFFFFFFF, 0xFFFFFFFF};
342 static const char soap_base64o
[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
343 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";
347 static const char soap_indent
[11] = "\n\t\t\t\t\t\t\t\t\t";
348 /* Alternative indentation form for SOAP_XML_INDENT:
349 static const char soap_indent[21] = "\n ";
354 # define SOAP_CANARY (0xC0DE)
357 static const char soap_padding
[4] = "\0\0\0";
358 #define SOAP_STR_PADDING (soap_padding)
359 #define SOAP_STR_EOS (soap_padding)
360 #define SOAP_NON_NULL (soap_padding)
363 static const struct soap_code_map html_entity_codes
[] = /* entities for XHTML parsing */
466 static const struct soap_code_map h_error_codes
[] =
468 #ifdef HOST_NOT_FOUND
469 { HOST_NOT_FOUND
, "Host not found" },
472 { TRY_AGAIN
, "Try Again" },
475 { NO_RECOVERY
, "No Recovery" },
478 { NO_DATA
, "No Data" },
481 { NO_ADDRESS
, "No Address" },
490 static const struct soap_code_map h_http_error_codes
[] =
494 { 203, "Non-Authoritative Information" },
495 { 204, "No Content" },
496 { 205, "Reset Content" },
497 { 206, "Partial Content" },
498 { 300, "Multiple Choices" },
499 { 301, "Moved Permanently" },
501 { 303, "See Other" },
502 { 304, "Not Modified" },
503 { 305, "Use Proxy" },
504 { 307, "Temporary Redirect" },
505 { 400, "Bad Request" },
506 { 401, "Unauthorized" },
507 { 402, "Payment Required" },
508 { 403, "Forbidden" },
509 { 404, "Not Found" },
510 { 405, "Method Not Allowed" },
511 { 406, "Not Acceptable" },
512 { 407, "Proxy Authentication Required" },
513 { 408, "Request Time-out" },
516 { 411, "Length Required" },
517 { 412, "Precondition Failed" },
518 { 413, "Request Entity Too Large" },
519 { 414, "Request-URI Too Large" },
520 { 415, "Unsupported Media Type" },
521 { 416, "Requested range not satisfiable" },
522 { 417, "Expectation Failed" },
523 { 500, "Internal Server Error" },
524 { 501, "Not Implemented" },
525 { 502, "Bad Gateway" },
526 { 503, "Service Unavailable" },
527 { 504, "Gateway Time-out" },
528 { 505, "HTTP Version not supported" },
535 static const struct soap_code_map h_ssl_error_codes
[] =
537 #define _SSL_ERROR(e) { e, #e }
538 _SSL_ERROR(SSL_ERROR_SSL
),
539 _SSL_ERROR(SSL_ERROR_ZERO_RETURN
),
540 _SSL_ERROR(SSL_ERROR_WANT_READ
),
541 _SSL_ERROR(SSL_ERROR_WANT_WRITE
),
542 _SSL_ERROR(SSL_ERROR_WANT_CONNECT
),
543 _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP
),
544 _SSL_ERROR(SSL_ERROR_SYSCALL
),
550 static const struct soap_code_map mime_codes
[] =
551 { { SOAP_MIME_7BIT
, "7bit" },
552 { SOAP_MIME_8BIT
, "8bit" },
553 { SOAP_MIME_BINARY
, "binary" },
554 { SOAP_MIME_QUOTED_PRINTABLE
, "quoted-printable" },
555 { SOAP_MIME_BASE64
, "base64" },
556 { SOAP_MIME_IETF_TOKEN
, "ietf-token" },
557 { SOAP_MIME_X_TOKEN
, "x-token" },
563 static int tcp_done
= 0;
566 #if defined(HP_UX) && defined(HAVE_GETHOSTBYNAME_R)
570 /******************************************************************************/
574 fsend(struct soap
*soap
, const char *s
, size_t n
)
575 { register int nwritten
, err
;
576 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
578 { soap
->os
->write(s
, (std::streamsize
)n
);
579 if (soap
->os
->good())
586 { if (soap_valid_socket(soap
->socket
))
588 if (soap
->send_timeout
)
593 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ALL
, soap
->send_timeout
);
596 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
);
604 if (err
!= SOAP_EINTR
&& err
!= SOAP_EAGAIN
&& err
!= SOAP_EWOULDBLOCK
)
610 nwritten
= SSL_write(soap
->ssl
, s
, (int)n
);
612 nwritten
= BIO_write(soap
->bio
, s
, (int)n
);
616 if ((soap
->omode
& SOAP_IO_UDP
))
618 nwritten
= sendto(soap
->socket
, (char*)s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, (SOAP_WINSOCKINT
)soap
->peerlen
);
620 nwritten
= send(soap
->socket
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
);
621 /* retry and back-off algorithm */
622 /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
626 if ((soap
->connect_flags
& SO_BROADCAST
))
627 udp_repeat
= 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
629 udp_repeat
= 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
630 udp_delay
= (soap_random
% 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
632 { tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ERR
, -1000 * udp_delay
);
634 nwritten
= sendto(soap
->socket
, (char*)s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
, (struct sockaddr
*)&soap
->peer
, (SOAP_WINSOCKINT
)soap
->peerlen
);
636 nwritten
= send(soap
->socket
, s
, (SOAP_WINSOCKINT
)n
, soap
->socket_flags
);
638 if (udp_delay
> 500) /* UDP_UPPER_DELAY */
641 while (nwritten
< 0 && --udp_repeat
> 0);
646 #if !defined(PALM) && !defined(AS400)
647 nwritten
= send(soap
->socket
, s
, (int)n
, soap
->socket_flags
);
649 nwritten
= send(soap
->socket
, (void*)s
, n
, soap
->socket_flags
);
654 err
= soap_socket_errno(soap
->socket
);
656 if (soap
->ssl
&& (r
= SSL_get_error(soap
->ssl
, nwritten
)) != SSL_ERROR_NONE
&& r
!= SSL_ERROR_WANT_READ
&& r
!= SSL_ERROR_WANT_WRITE
)
657 { soap
->errnum
= err
;
661 if (err
== SOAP_EWOULDBLOCK
|| err
== SOAP_EAGAIN
)
664 if (soap
->ssl
&& r
== SSL_ERROR_WANT_READ
)
665 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
667 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
669 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->send_timeout
? soap
->send_timeout
: -10000);
671 if (!r
&& soap
->send_timeout
)
673 if (r
< 0 && soap
->errnum
!= SOAP_EINTR
)
676 else if (err
&& err
!= SOAP_EINTR
)
677 { soap
->errnum
= err
;
680 nwritten
= 0; /* and call write() again */
686 nwritten
= fwrite((void*)s
, 1, n
, stdout
);
690 nwritten
= fwrite(s
, 1, n
, soap
->sendfd
);
695 nwritten
= (httpBlockPut(soap
->rpmreqid
, (char*)s
, n
) == 0) ? n
: -1;
698 nwritten
= fwrite(s
, sizeof(char), n
, fdopen(soap
->sendfd
, "w"));
701 nwritten
= _write(soap
->sendfd
, s
, (unsigned int)n
);
703 nwritten
= write(soap
->sendfd
, s
, (unsigned int)n
);
715 if (err
&& err
!= SOAP_EINTR
&& err
!= SOAP_EWOULDBLOCK
&& err
!= SOAP_EAGAIN
)
716 { soap
->errnum
= err
;
719 nwritten
= 0; /* and call write() again */
730 /******************************************************************************/
735 soap_send_raw(struct soap
*soap
, const char *s
, size_t n
)
738 if (soap
->mode
& SOAP_IO_LENGTH
)
741 if (soap
->fpreparesend
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
)
742 return soap
->error
= soap
->fpreparesend(soap
, s
, n
);
746 if (soap
->mode
& SOAP_IO
)
747 { register size_t i
= SOAP_BUFLEN
- soap
->bufidx
;
749 { memcpy(soap
->buf
+ soap
->bufidx
, s
, i
);
750 soap
->bufidx
= SOAP_BUFLEN
;
751 if (soap_flush(soap
))
757 memcpy(soap
->buf
+ soap
->bufidx
, s
, n
);
761 return soap_flush_raw(soap
, s
, n
);
765 /******************************************************************************/
770 soap_flush(struct soap
*soap
)
771 { register size_t n
= soap
->bufidx
;
775 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
777 if (soap
->fpreparesend
&& (r
= soap
->fpreparesend(soap
, soap
->buf
, n
)))
778 return soap
->error
= r
;
783 if (soap
->mode
& SOAP_ENC_ZLIB
)
784 { soap
->d_stream
->next_in
= (Byte
*)soap
->buf
;
785 soap
->d_stream
->avail_in
= (unsigned int)n
;
787 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)n
);
790 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflating %u bytes\n", soap
->d_stream
->avail_in
));
791 if (deflate(soap
->d_stream
, Z_NO_FLUSH
) != Z_OK
)
792 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to deflate: %s\n", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
793 return soap
->error
= SOAP_ZLIB_ERROR
;
795 if (!soap
->d_stream
->avail_out
)
796 { if (soap_flush_raw(soap
, soap
->z_buf
, SOAP_BUFLEN
))
798 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
799 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
801 } while (soap
->d_stream
->avail_in
);
805 return soap_flush_raw(soap
, soap
->buf
, n
);
811 /******************************************************************************/
816 soap_flush_raw(struct soap
*soap
, const char *s
, size_t n
)
817 { if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
819 if (!(t
= (char*)soap_push_block(soap
, NULL
, n
)))
820 return soap
->error
= SOAP_EOM
;
825 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
827 sprintf(t
, "\r\n%lX\r\n" + (soap
->chunksize
? 0 : 2), (unsigned long)n
);
828 DBGMSG(SENT
, t
, strlen(t
));
829 if ((soap
->error
= soap
->fsend(soap
, t
, strlen(t
))))
831 soap
->chunksize
+= n
;
835 return soap
->error
= soap
->fsend(soap
, s
, n
);
839 /******************************************************************************/
844 soap_send(struct soap
*soap
, const char *s
)
846 return soap_send_raw(soap
, s
, strlen(s
));
851 /******************************************************************************/
857 soap_send2(struct soap
*soap
, const char *s1
, const char *s2
)
858 { if (soap_send(soap
, s1
))
860 return soap_send(soap
, s2
);
865 /******************************************************************************/
871 soap_send3(struct soap
*soap
, const char *s1
, const char *s2
, const char *s3
)
872 { if (soap_send(soap
, s1
)
873 || soap_send(soap
, s2
))
875 return soap_send(soap
, s3
);
880 /******************************************************************************/
884 frecv(struct soap
*soap
, char *s
, size_t n
)
886 register int retries
= 100; /* max 100 retries with non-blocking sockets */
888 #if defined(__cplusplus) && !defined(WITH_LEAN) && !defined(WITH_COMPAT)
890 { if (soap
->is
->good())
891 return soap
->is
->read(s
, (std::streamsize
)n
).gcount();
895 if (soap_valid_socket(soap
->socket
))
899 register int err
= 0;
902 if (soap
->recv_timeout
&& !soap
->ssl
) /* SSL: sockets are nonblocking */
904 if (soap
->recv_timeout
)
907 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
);
913 if (r
!= SOAP_EINTR
&& r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
919 { r
= SSL_read(soap
->ssl
, s
, (int)n
);
922 err
= SSL_get_error(soap
->ssl
, r
);
923 if (err
!= SSL_ERROR_NONE
&& err
!= SSL_ERROR_WANT_READ
&& err
!= SSL_ERROR_WANT_WRITE
)
927 { r
= BIO_read(soap
->bio
, s
, (int)n
);
936 if ((soap
->omode
& SOAP_IO_UDP
))
937 { SOAP_SOCKLEN_T k
= (SOAP_SOCKLEN_T
)sizeof(soap
->peer
);
938 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
939 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 */
940 soap
->peerlen
= (size_t)k
;
942 soap
->ip
= ntohl(soap
->peer
.sin_addr
.s_addr
);
947 r
= recv(soap
->socket
, s
, (int)n
, soap
->socket_flags
);
949 /* CycleSyncDisplay(curStatusMsg); */
953 r
= soap_socket_errno(soap
->socket
);
954 if (r
!= SOAP_EINTR
&& r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
960 if (soap
->ssl
&& err
== SSL_ERROR_WANT_WRITE
)
961 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
963 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
965 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, soap
->recv_timeout
? soap
->recv_timeout
: 5);
967 if (!r
&& soap
->recv_timeout
)
971 if (r
!= SOAP_EINTR
&& r
!= SOAP_EAGAIN
&& r
!= SOAP_EWOULDBLOCK
)
977 r
= soap_socket_errno(soap
->socket
);
978 if (r
!= SOAP_EINTR
&& retries
-- <= 0)
986 return fread(s
, 1, n
, stdin
);
989 return fread(s
, 1, n
, soap
->recvfd
);
993 r
= httpBlockRead(soap
->rpmreqid
, s
, n
);
997 r
= _read(soap
->recvfd
, s
, (unsigned int)n
);
999 r
= read(soap
->recvfd
, s
, (unsigned int)n
);
1003 soap
->errnum
= soap_errno
;
1011 /******************************************************************************/
1015 soap_getchunkchar(struct soap
*soap
)
1016 { if (soap
->bufidx
< soap
->buflen
)
1017 return soap
->buf
[soap
->bufidx
++];
1019 soap
->buflen
= soap
->chunkbuflen
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1020 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes from socket %d\n", (unsigned int)soap
->buflen
, soap
->socket
));
1021 DBGMSG(RECV
, soap
->buf
, soap
->buflen
);
1023 return soap
->buf
[soap
->bufidx
++];
1029 /******************************************************************************/
1032 soap_isxdigit(int c
)
1033 { return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a' && c
<= 'f');
1037 /******************************************************************************/
1042 soap_recv_raw(struct soap
*soap
)
1043 { register size_t ret
;
1044 #if !defined(WITH_LEANER) || defined(WITH_ZLIB)
1048 if (soap
->mode
& SOAP_ENC_ZLIB
)
1049 { if (soap
->d_stream
->next_out
== Z_NULL
)
1051 if (soap
->d_stream
->avail_in
|| !soap
->d_stream
->avail_out
)
1052 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflating\n"));
1053 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
1054 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
1055 r
= inflate(soap
->d_stream
, Z_NO_FLUSH
);
1056 if (r
== Z_NEED_DICT
&& soap
->z_dict
)
1057 r
= inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
);
1058 if (r
== Z_OK
|| r
== Z_STREAM_END
)
1060 ret
= soap
->buflen
= SOAP_BUFLEN
- soap
->d_stream
->avail_out
;
1061 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
1062 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)ret
);
1063 if (r
== Z_STREAM_END
)
1064 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
1065 soap
->z_ratio_in
= (float)soap
->d_stream
->total_in
/ (float)soap
->d_stream
->total_out
;
1066 soap
->d_stream
->next_out
= Z_NULL
;
1069 { soap
->count
+= ret
;
1070 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- decompressed ----\n"));
1071 DBGMSG(RECV
, soap
->buf
, ret
);
1072 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n----\n"));
1074 if (soap
->fpreparerecv
&& (r
= soap
->fpreparerecv(soap
, soap
->buf
, ret
)))
1075 return soap
->error
= r
;
1080 else if (r
!= Z_BUF_ERROR
)
1081 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflate error: %s\n", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
1082 soap
->d_stream
->next_out
= Z_NULL
;
1083 soap
->error
= SOAP_ZLIB_ERROR
;
1088 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
&& !soap
->chunksize
)
1089 { memcpy(soap
->buf
, soap
->z_buf
, SOAP_BUFLEN
);
1090 soap
->buflen
= soap
->z_buflen
;
1092 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- compressed ----\n"));
1096 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
) /* read HTTP chunked transfer */
1098 { register soap_wchar c
;
1100 if (soap
->chunksize
)
1101 { soap
->buflen
= ret
= soap
->frecv(soap
, soap
->buf
, soap
->chunksize
> SOAP_BUFLEN
? SOAP_BUFLEN
: soap
->chunksize
);
1102 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Getting chunk: read %u bytes\n", (unsigned int)ret
));
1103 DBGMSG(RECV
, soap
->buf
, ret
);
1105 soap
->chunksize
-= ret
;
1109 if (!soap
->chunkbuflen
)
1110 { soap
->chunkbuflen
= ret
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1111 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret
, soap
->socket
));
1112 DBGMSG(RECV
, soap
->buf
, ret
);
1115 return soap
->ahead
= EOF
;
1118 soap
->bufidx
= soap
->buflen
;
1119 soap
->buflen
= soap
->chunkbuflen
;
1120 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap
->bufidx
, (unsigned int)soap
->buflen
));
1121 while (!soap_isxdigit((int)(c
= soap_getchunkchar(soap
))))
1122 { if ((int)c
== EOF
)
1123 return soap
->ahead
= EOF
;
1127 while (soap_isxdigit((int)(c
= soap_getchunkchar(soap
))) && t
- tmp
< 7);
1128 while ((int)c
!= EOF
&& c
!= '\n')
1129 c
= soap_getchunkchar(soap
);
1131 return soap
->ahead
= EOF
;
1133 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunk size = %s (hex)\n", tmp
));
1134 soap
->chunksize
= soap_strtoul(tmp
, &t
, 16);
1135 if (!soap
->chunksize
)
1136 { soap
->chunkbuflen
= 0;
1137 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of chunked message\n"));
1138 while ((int)c
!= EOF
&& c
!= '\n')
1139 c
= soap_getchunkchar(soap
);
1144 soap
->buflen
= soap
->bufidx
+ soap
->chunksize
;
1145 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap
->bufidx
, (unsigned int)soap
->buflen
, tmp
));
1146 if (soap
->buflen
> soap
->chunkbuflen
)
1147 { soap
->buflen
= soap
->chunkbuflen
;
1148 soap
->chunksize
-= soap
->buflen
- soap
->bufidx
;
1149 soap
->chunkbuflen
= 0;
1150 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap
->buflen
- soap
->bufidx
)));
1152 else if (soap
->chunkbuflen
)
1153 soap
->chunksize
= 0;
1154 ret
= soap
->buflen
- soap
->bufidx
;
1162 soap
->buflen
= ret
= soap
->frecv(soap
, soap
->buf
, SOAP_BUFLEN
);
1163 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Read %u bytes from socket %d\n", (unsigned int)ret
, soap
->socket
));
1164 DBGMSG(RECV
, soap
->buf
, ret
);
1167 if (soap
->mode
& SOAP_ENC_ZLIB
)
1168 { memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
1169 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
1170 soap
->d_stream
->avail_in
= (unsigned int)ret
;
1171 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
1172 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
1173 r
= inflate(soap
->d_stream
, Z_NO_FLUSH
);
1174 if (r
== Z_NEED_DICT
&& soap
->z_dict
)
1175 r
= inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
);
1176 if (r
== Z_OK
|| r
== Z_STREAM_END
)
1178 soap
->z_buflen
= soap
->buflen
;
1179 soap
->buflen
= SOAP_BUFLEN
- soap
->d_stream
->avail_out
;
1180 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
1181 soap
->z_crc
= crc32(soap
->z_crc
, (Byte
*)soap
->buf
, (unsigned int)soap
->buflen
);
1182 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated %u bytes\n", (unsigned int)soap
->buflen
));
1183 if (ret
&& !soap
->buflen
&& r
!= Z_STREAM_END
)
1186 if (r
== Z_STREAM_END
)
1187 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflated total %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
1188 soap
->z_ratio_in
= (float)soap
->d_stream
->total_in
/ (float)soap
->d_stream
->total_out
;
1189 soap
->d_stream
->next_out
= Z_NULL
;
1191 DBGLOG(RECV
, SOAP_MESSAGE(fdebug
, "\n---- decompressed ----\n"));
1192 DBGMSG(RECV
, soap
->buf
, ret
);
1194 if (soap
->fpreparerecv
&& (r
= soap
->fpreparerecv(soap
, soap
->buf
, ret
)))
1195 return soap
->error
= r
;
1199 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to inflate: (%d) %s\n", r
, soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
1200 soap
->d_stream
->next_out
= Z_NULL
;
1201 soap
->error
= SOAP_ZLIB_ERROR
;
1207 if (soap
->fpreparerecv
1209 && soap
->zlib_in
== SOAP_ZLIB_NONE
1211 && (r
= soap
->fpreparerecv(soap
, soap
->buf
+ soap
->bufidx
, ret
)))
1212 return soap
->error
= r
;
1219 /******************************************************************************/
1224 soap_recv(struct soap
*soap
)
1227 if (soap
->mode
& SOAP_ENC_DIME
)
1228 { if (soap
->dime
.buflen
)
1231 unsigned char tmp
[12];
1232 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME hdr for chunked DIME is in buffer\n"));
1233 soap
->count
+= soap
->dime
.buflen
- soap
->buflen
;
1234 soap
->buflen
= soap
->dime
.buflen
;
1235 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Skip padding (%ld bytes)\n", -(long)soap
->dime
.size
&3));
1236 for (i
= -(long)soap
->dime
.size
&3; i
> 0; i
--)
1238 if (soap
->bufidx
>= soap
->buflen
)
1239 if (soap_recv_raw(soap
))
1242 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME hdr for next chunk\n"));
1244 for (i
= 12; i
> 0; i
--)
1245 { *s
++ = soap
->buf
[soap
->bufidx
++];
1246 if (soap
->bufidx
>= soap
->buflen
)
1247 if (soap_recv_raw(soap
))
1250 soap
->dime
.flags
= tmp
[0] & 0x7;
1251 soap
->dime
.size
= ((size_t)tmp
[8] << 24) | ((size_t)tmp
[9] << 16) | ((size_t)tmp
[10] << 8) | ((size_t)tmp
[11]);
1252 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME chunk (%u bytes)\n", (unsigned int)soap
->dime
.size
));
1253 if (soap
->dime
.flags
& SOAP_DIME_CF
)
1254 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "More chunking\n"));
1255 soap
->dime
.chunksize
= soap
->dime
.size
;
1256 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.size
)
1257 { soap
->dime
.buflen
= soap
->buflen
;
1258 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
1261 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
1264 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Last chunk\n"));
1265 soap
->dime
.buflen
= 0;
1266 soap
->dime
.chunksize
= 0;
1268 soap
->count
= soap
->buflen
- soap
->bufidx
;
1269 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%u bytes remaining\n", (unsigned int)soap
->count
));
1272 if (soap
->dime
.chunksize
)
1273 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap
->dime
.chunksize
));
1274 if (soap_recv_raw(soap
))
1276 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.chunksize
)
1277 { soap
->dime
.buflen
= soap
->buflen
;
1278 soap
->count
-= soap
->buflen
- soap
->bufidx
- soap
->dime
.chunksize
;
1279 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
1282 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
1283 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%lu bytes remaining, count=%u\n", (unsigned long)(soap
->buflen
-soap
->bufidx
), (unsigned int)soap
->count
));
1288 return soap_recv_raw(soap
);
1292 /******************************************************************************/
1297 soap_getchar(struct soap
*soap
)
1298 { register soap_wchar c
;
1305 return soap_get1(soap
);
1309 /******************************************************************************/
1312 const struct soap_code_map
*
1314 soap_code(const struct soap_code_map
*code_map
, const char *str
)
1315 { if (code_map
&& str
)
1316 { while (code_map
->string
)
1317 { if (!strcmp(str
, code_map
->string
)) /* case sensitive */
1326 /******************************************************************************/
1331 soap_code_int(const struct soap_code_map
*code_map
, const char *str
, long other
)
1333 { while (code_map
->string
)
1334 { if (!soap_tag_cmp(str
, code_map
->string
)) /* case insensitive */
1335 return code_map
->code
;
1343 /******************************************************************************/
1348 soap_code_str(const struct soap_code_map
*code_map
, long code
)
1351 while (code_map
->code
!= code
&& code_map
->string
)
1353 return code_map
->string
;
1357 /******************************************************************************/
1362 soap_code_bits(const struct soap_code_map
*code_map
, const char *str
)
1363 { register long bits
= 0;
1365 { while (str
&& *str
)
1366 { const struct soap_code_map
*p
;
1367 for (p
= code_map
; p
->string
; p
++)
1368 { register size_t n
= strlen(p
->string
);
1369 if (!strncmp(p
->string
, str
, n
) && soap_blank(str
[n
]))
1372 while (*str
> 0 && *str
<= 32)
1385 /******************************************************************************/
1390 soap_code_list(struct soap
*soap
, const struct soap_code_map
*code_map
, long code
)
1391 { register char *t
= soap
->tmpbuf
;
1393 { while (code_map
->string
)
1394 { if (code_map
->code
& code
)
1395 { register const char *s
= code_map
->string
;
1396 if (t
!= soap
->tmpbuf
)
1398 while (*s
&& t
< soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 1)
1400 if (t
== soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 1)
1407 return soap
->tmpbuf
;
1411 /******************************************************************************/
1414 soap_char(struct soap
*soap
)
1417 register soap_wchar c
;
1418 register char *s
= tmp
;
1419 for (i
= 0; i
< 7; i
++)
1420 { c
= soap_get1(soap
);
1421 if (c
== ';' || (int)c
== EOF
)
1427 { if (tmp
[1] == 'x' || tmp
[1] == 'X')
1428 return (soap_wchar
)soap_strtol(tmp
+ 2, NULL
, 16);
1429 return (soap_wchar
)soap_strtol(tmp
+ 1, NULL
, 10);
1431 if (!strcmp(tmp
, "lt"))
1433 if (!strcmp(tmp
, "gt"))
1435 if (!strcmp(tmp
, "amp"))
1437 if (!strcmp(tmp
, "quot"))
1439 if (!strcmp(tmp
, "apos"))
1442 return (soap_wchar
)soap_code_int(html_entity_codes
, tmp
, SOAP_UNKNOWN_CHAR
);
1444 return SOAP_UNKNOWN_CHAR
; /* use this to represent unknown code */
1449 /******************************************************************************/
1453 soap_get0(struct soap
*soap
)
1454 { if (soap
->bufidx
>= soap
->buflen
&& soap_recv(soap
))
1456 return (unsigned char)soap
->buf
[soap
->bufidx
];
1461 /******************************************************************************/
1465 soap_get1(struct soap
*soap
)
1466 { if (soap
->bufidx
>= soap
->buflen
&& soap_recv(soap
))
1468 return (unsigned char)soap
->buf
[soap
->bufidx
++];
1473 /******************************************************************************/
1478 soap_get(struct soap
*soap
)
1479 { register soap_wchar c
;
1482 { if ((int)c
!= EOF
)
1486 c
= soap_get1(soap
);
1487 while ((int)c
!= EOF
)
1490 { c
= soap_get1(soap
);
1492 { c
= soap_get0(soap
);
1496 c
= soap_get1(soap
);
1499 { soap_unget(soap
, ']');
1504 { soap_revget1(soap
);
1513 do c
= soap_get1(soap
);
1514 while (soap_blank(c
));
1515 if (c
== '!' || c
== '?' || c
== '%')
1516 { register int k
= 1;
1518 { c
= soap_get1(soap
);
1520 { do c
= soap_get1(soap
);
1521 while ((int)c
!= EOF
&& c
!= '[');
1525 c
= soap_get1(soap
);
1528 if (c
== '-' && (c
= soap_get1(soap
)) == '-')
1530 { c
= soap_get1(soap
);
1531 if (c
== '-' && (c
= soap_get1(soap
)) == '-')
1533 } while ((int)c
!= EOF
);
1537 c
= soap_get_pi(soap
);
1538 while ((int)c
!= EOF
)
1545 c
= soap_get1(soap
);
1549 c
= soap_get1(soap
);
1563 return soap_char(soap
) | 0x80000000;
1571 /******************************************************************************/
1574 soap_get_pi(struct soap
*soap
)
1576 register char *s
= buf
;
1577 register int i
= sizeof(buf
);
1578 register soap_wchar c
= soap_getchar(soap
);
1579 /* This is a quick way to parse XML PI and we could use a callback instead to
1580 * enable applications to intercept processing instructions */
1581 while ((int)c
!= EOF
&& c
!= '?')
1583 { if (soap_blank(c
))
1587 c
= soap_getchar(soap
);
1590 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "XML PI <?%s?>\n", buf
));
1591 if (!strncmp(buf
, "xml ", 4))
1592 { s
= strstr(buf
, " encoding=");
1594 { if (!soap_tag_cmp(s
+ 11, "iso-8859-1*")
1595 || !soap_tag_cmp(s
+ 11, "latin1*"))
1596 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Switching to latin1 encoding\n"));
1597 soap
->mode
|= SOAP_ENC_LATIN
;
1599 else if (!soap_tag_cmp(s
+ 11, "utf-8*"))
1600 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Switching to utf-8 encoding\n"));
1601 soap
->mode
&= ~SOAP_ENC_LATIN
;
1606 c
= soap_getchar(soap
);
1611 /******************************************************************************/
1617 soap_move(struct soap
*soap
, long n
)
1618 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Moving %ld bytes forward\n", (long)n
));
1620 if ((int)soap_getchar(soap
) == EOF
)
1627 /******************************************************************************/
1633 soap_tell(struct soap
*soap
)
1634 { return soap
->count
- soap
->buflen
+ soap
->bufidx
- (soap
->ahead
!= 0);
1639 /******************************************************************************/
1644 soap_pututf8(struct soap
*soap
, register unsigned long c
)
1646 if (c
< 0x80 && c
> 0)
1648 return soap_send_raw(soap
, tmp
, 1);
1652 { register char *t
= tmp
;
1654 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
1657 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
1660 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
1662 { if (c
< 0x04000000)
1663 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
1665 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
1666 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
1668 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
1670 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
1672 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
1674 *t
++ = (char)(0x80 | (c
& 0x3F));
1678 sprintf(tmp
, "&#%lu;", c
);
1680 return soap_send(soap
, tmp
);
1684 /******************************************************************************/
1689 soap_getutf8(struct soap
*soap
)
1690 { register soap_wchar c
, c1
, c2
, c3
, c4
;
1697 if (c
< 0x80 || (soap
->mode
& SOAP_ENC_LATIN
))
1699 c1
= soap_get1(soap
);
1701 { soap_revget1(soap
); /* doesn't look like this is UTF8 */
1706 return ((soap_wchar
)(c
& 0x1F) << 6) | c1
;
1707 c2
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1709 return ((soap_wchar
)(c
& 0x0F) << 12) | (c1
<< 6) | c2
;
1710 c3
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1712 return ((soap_wchar
)(c
& 0x07) << 18) | (c1
<< 12) | (c2
<< 6) | c3
;
1713 c4
= (soap_wchar
)soap_get1(soap
) & 0x3F;
1715 return ((soap_wchar
)(c
& 0x03) << 24) | (c1
<< 18) | (c2
<< 12) | (c3
<< 6) | c4
;
1716 return ((soap_wchar
)(c
& 0x01) << 30) | (c1
<< 24) | (c2
<< 18) | (c3
<< 12) | (c4
<< 6) | (soap_wchar
)(soap_get1(soap
) & 0x3F);
1720 /******************************************************************************/
1725 soap_puthex(struct soap
*soap
, const unsigned char *s
, int n
)
1729 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1730 { if (!(soap
->dom
->data
= soap_s2hex(soap
, s
, NULL
, n
)))
1735 for (i
= 0; i
< n
; i
++)
1736 { register int m
= *s
++;
1737 d
[0] = (char)((m
>> 4) + (m
> 159 ? '7' : '0'));
1739 d
[1] = (char)(m
+ (m
> 9 ? '7' : '0'));
1740 if (soap_send_raw(soap
, d
, 2))
1747 /******************************************************************************/
1752 soap_gethex(struct soap
*soap
, int *n
)
1755 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1756 { soap
->dom
->data
= soap_string_in(soap
, 0, -1, -1);
1757 return (unsigned char*)soap_hex2s(soap
, soap
->dom
->data
, NULL
, 0, n
);
1764 register size_t i
, k
;
1765 if (soap_append_lab(soap
, NULL
, 0))
1767 s
= soap
->labbuf
+ soap
->labidx
;
1768 k
= soap
->lablen
- soap
->labidx
;
1769 soap
->labidx
= soap
->lablen
;
1770 for (i
= 0; i
< k
; i
++)
1771 { register char d1
, d2
;
1772 register soap_wchar c
;
1774 if (soap_isxdigit(c
))
1777 if (soap_isxdigit(c
))
1780 { soap
->error
= SOAP_TYPE
;
1786 soap_unget(soap
, c
);
1788 *n
= (int)(soap
->lablen
+ i
- k
);
1789 p
= (unsigned char*)soap_malloc(soap
, soap
->lablen
+ i
- k
);
1791 memcpy(p
, soap
->labbuf
, soap
->lablen
+ i
- k
);
1794 *s
++ = ((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0');
1798 if (soap_new_block(soap
) == NULL
)
1802 register char *s
= (char*)soap_push_block(soap
, NULL
, SOAP_BLKLEN
);
1804 { soap_end_block(soap
, NULL
);
1807 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
1808 { register char d1
, d2
;
1809 register soap_wchar c
= soap_get(soap
);
1810 if (soap_isxdigit(c
))
1813 if (soap_isxdigit(c
))
1816 { soap_end_block(soap
, NULL
);
1817 soap
->error
= SOAP_TYPE
;
1823 soap_unget(soap
, c
);
1825 *n
= (int)soap_size_block(soap
, NULL
, i
);
1826 p
= (unsigned char*)soap_save_block(soap
, NULL
, 0);
1829 *s
++ = ((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0');
1836 /******************************************************************************/
1841 soap_putbase64(struct soap
*soap
, const unsigned char *s
, int n
)
1843 register unsigned long m
;
1848 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1849 { if (!(soap
->dom
->data
= soap_s2base64(soap
, s
, NULL
, n
)))
1854 for (; n
> 2; n
-= 3, s
+= 3)
1856 m
= (m
<< 8) | s
[1];
1857 m
= (m
<< 8) | s
[2];
1858 for (i
= 4; i
> 0; m
>>= 6)
1859 d
[--i
] = soap_base64o
[m
& 0x3F];
1860 if (soap_send_raw(soap
, d
, 4))
1865 for (i
= 0; i
< n
; i
++)
1866 m
= (m
<< 8) | *s
++;
1869 for (i
++; i
> 0; m
>>= 6)
1870 d
[--i
] = soap_base64o
[m
& 0x3F];
1871 for (i
= 3; i
> n
; i
--)
1873 if (soap_send_raw(soap
, d
, 4))
1880 /******************************************************************************/
1885 soap_getbase64(struct soap
*soap
, int *n
, int malloc_flag
)
1888 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
1889 { soap
->dom
->data
= soap_string_in(soap
, 0, -1, -1);
1890 return (unsigned char*)soap_base642s(soap
, soap
->dom
->data
, NULL
, 0, n
);
1896 { register size_t i
, k
;
1898 if (soap_append_lab(soap
, NULL
, 2))
1900 s
= soap
->labbuf
+ soap
->labidx
;
1901 k
= soap
->lablen
- soap
->labidx
;
1902 soap
->labidx
= 3 * (soap
->lablen
/ 3);
1906 { for (i
= 0; i
< k
- 2; i
+= 3)
1907 { register unsigned long m
= 0;
1910 { register soap_wchar c
= soap_get(soap
);
1911 if (c
== '=' || c
< 0)
1915 *s
++ = (char)((m
>> 4) & 0xFF);
1919 *s
++ = (char)((m
>> 10) & 0xFF);
1920 *s
++ = (char)((m
>> 2) & 0xFF);
1924 *n
= (int)(soap
->lablen
+ i
- k
);
1925 p
= (unsigned char*)soap_malloc(soap
, soap
->lablen
+ i
- k
);
1927 memcpy(p
, soap
->labbuf
, soap
->lablen
+ i
- k
);
1929 { while ((int)((c
= soap_get(soap
)) != EOF
) && c
!= SOAP_LT
&& c
!= SOAP_TT
)
1932 soap_unget(soap
, c
);
1936 if (c
>= 0 && c
<= 79)
1937 { register int b
= soap_base64i
[c
];
1939 { soap
->error
= SOAP_TYPE
;
1945 else if (!soap_blank(c
+ '+'))
1946 { soap
->error
= SOAP_TYPE
;
1950 *s
++ = (char)((m
>> 16) & 0xFF);
1951 *s
++ = (char)((m
>> 8) & 0xFF);
1952 *s
++ = (char)(m
& 0xFF);
1957 if (soap_new_block(soap
) == NULL
)
1961 register char *s
= (char*)soap_push_block(soap
, NULL
, 3 * SOAP_BLKLEN
); /* must be multiple of 3 */
1963 { soap_end_block(soap
, NULL
);
1966 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
1967 { register unsigned long m
= 0;
1970 { register soap_wchar c
= soap_get(soap
);
1971 if (c
== '=' || c
< 0)
1976 *s
++ = (char)((m
>> 4) & 0xFF);
1980 *s
++ = (char)((m
>> 10) & 0xFF);
1981 *s
++ = (char)((m
>> 2) & 0xFF);
1985 *n
= (int)soap_size_block(soap
, NULL
, i
);
1986 p
= (unsigned char*)soap_save_block(soap
, NULL
, 0);
1988 { while ((int)((c
= soap_get(soap
)) != EOF
) && c
!= SOAP_LT
&& c
!= SOAP_TT
)
1991 soap_unget(soap
, c
);
1995 if (c
>= 0 && c
<= 79)
1996 { int b
= soap_base64i
[c
];
1998 { soap
->error
= SOAP_TYPE
;
2004 else if (!soap_blank(c
))
2005 { soap
->error
= SOAP_TYPE
;
2009 *s
++ = (char)((m
>> 16) & 0xFF);
2010 *s
++ = (char)((m
>> 8) & 0xFF);
2011 *s
++ = (char)(m
& 0xFF);
2018 /******************************************************************************/
2024 soap_xop_forward(struct soap
*soap
, unsigned char **ptr
, int *size
, char **id
, char **type
, char **options
)
2025 { /* Check MTOM xop:Include element (within hex/base64Binary) */
2026 /* TODO: this code to be obsoleted with new import/xop.h conventions */
2027 int body
= soap
->body
; /* should save type too? */
2028 if (!soap_peek_element(soap
))
2029 { if (!soap_element_begin_in(soap
, "xop:Include", 0, NULL
) && *soap
->href
)
2030 { if (soap_dime_forward(soap
, ptr
, size
, id
, type
, options
))
2033 if (soap
->body
&& soap_element_end_in(soap
, NULL
))
2042 /******************************************************************************/
2048 soap_dime_forward(struct soap
*soap
, unsigned char **ptr
, int *size
, char **id
, char **type
, char **options
)
2049 { struct soap_xlist
*xp
;
2057 *id
= soap_strdup(soap
, soap
->href
);
2058 xp
= (struct soap_xlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_xlist
));
2060 return soap
->error
= SOAP_EOM
;
2061 xp
->next
= soap
->xlist
;
2066 xp
->options
= options
;
2073 /******************************************************************************/
2078 soap_strdup(struct soap
*soap
, const char *s
)
2080 if (s
&& (t
= (char*)soap_malloc(soap
, strlen(s
) + 1)))
2086 /******************************************************************************/
2091 soap_wstrdup(struct soap
*soap
, const wchar_t *s
)
2092 { wchar_t *t
= NULL
;
2097 if ((t
= (wchar_t*)soap_malloc(soap
, sizeof(wchar_t)*(n
+1))))
2098 memcpy(t
, s
, sizeof(wchar_t)*(n
+1));
2104 /******************************************************************************/
2109 soap_new_block(struct soap
*soap
)
2110 { struct soap_blist
*p
;
2111 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "New block sequence (prev=%p)\n", soap
->blist
));
2112 if (!(p
= (struct soap_blist
*)SOAP_MALLOC(soap
, sizeof(struct soap_blist
))))
2113 { soap
->error
= SOAP_EOM
;
2116 p
->next
= soap
->blist
;
2124 /******************************************************************************/
2129 soap_push_block(struct soap
*soap
, struct soap_blist
*b
, size_t n
)
2133 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n
, (unsigned int)b
->size
+ (unsigned int)n
));
2134 if (!(p
= (char*)SOAP_MALLOC(soap
, n
+ sizeof(char*) + sizeof(size_t))))
2135 { soap
->error
= SOAP_EOM
;
2138 *(char**)p
= b
->ptr
;
2139 *(size_t*)(p
+ sizeof(char*)) = n
;
2142 return p
+ sizeof(char*) + sizeof(size_t);
2146 /******************************************************************************/
2151 soap_pop_block(struct soap
*soap
, struct soap_blist
*b
)
2157 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Pop block\n"));
2159 b
->size
-= *(size_t*)(p
+ sizeof(char*));
2160 b
->ptr
= *(char**)p
;
2165 /******************************************************************************/
2166 #ifndef WITH_NOIDREF
2169 soap_update_ptrs(struct soap
*soap
, char *start
, char *end
, char *p1
, char *p2
)
2171 register struct soap_ilist
*ip
= NULL
;
2172 register struct soap_flist
*fp
= NULL
;
2174 register struct soap_xlist
*xp
= NULL
;
2176 register void *p
, **q
;
2177 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2178 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2179 { if (ip
->ptr
&& (char*)ip
->ptr
>= start
&& (char*)ip
->ptr
< end
)
2180 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Update id='%s' %p -> %p\n", ip
->id
, ip
->ptr
, (char*)ip
->ptr
+ (p1
-p2
)));
2181 ip
->ptr
= (char*)ip
->ptr
+ (p1
-p2
);
2183 for (q
= &ip
->link
; q
; q
= (void**)p
)
2185 if (p
&& (char*)p
>= start
&& (char*)p
< end
)
2186 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Link update id='%s' %p\n", ip
->id
, p
));
2187 *q
= (char*)p
+ (p1
-p2
);
2190 for (q
= &ip
->copy
; q
; q
= (void**)p
)
2192 if (p
&& (char*)p
>= start
&& (char*)p
< end
)
2193 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy chain update id='%s' %p\n", ip
->id
, p
));
2194 *q
= (char*)p
+ (p1
-p2
);
2197 for (fp
= ip
->flist
; fp
; fp
= fp
->next
)
2198 { if ((char*)fp
->ptr
>= start
&& (char*)fp
->ptr
< end
)
2199 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy list update id='%s' %p\n", ip
->id
, fp
));
2200 fp
->ptr
= (char*)fp
->ptr
+ (p1
-p2
);
2206 for (xp
= soap
->xlist
; xp
; xp
= xp
->next
)
2207 { if (xp
->ptr
&& (char*)xp
->ptr
>= start
&& (char*)xp
->ptr
< end
)
2208 { 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
)));
2209 xp
->ptr
= (unsigned char**)((char*)xp
->ptr
+ (p1
-p2
));
2210 xp
->size
= (int*)((char*)xp
->size
+ (p1
-p2
));
2211 xp
->type
= (char**)((char*)xp
->type
+ (p1
-p2
));
2212 xp
->options
= (char**)((char*)xp
->options
+ (p1
-p2
));
2220 /******************************************************************************/
2221 #ifndef WITH_NOIDREF
2224 soap_has_copies(struct soap
*soap
, register const char *start
, register const char *end
)
2226 register struct soap_ilist
*ip
= NULL
;
2227 register struct soap_flist
*fp
= NULL
;
2228 register const char *p
;
2229 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2230 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2231 { for (p
= (const char*)ip
->copy
; p
; p
= *(const char**)p
)
2232 if (p
>= start
&& p
< end
)
2234 for (fp
= ip
->flist
; fp
; fp
= fp
->next
)
2235 if ((const char*)fp
->ptr
>= start
&& (const char*)fp
->ptr
< end
)
2244 /******************************************************************************/
2245 #ifndef WITH_NOIDREF
2250 soap_resolve(struct soap
*soap
)
2252 register struct soap_ilist
*ip
= NULL
;
2253 register struct soap_flist
*fp
= NULL
;
2255 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving forwarded data\n"));
2256 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2257 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2259 { register void *p
, **q
, *r
;
2260 q
= (void**)ip
->link
;
2263 DBGLOG(TEST
, if (q
) SOAP_MESSAGE(fdebug
, "Traversing link chain to resolve id='%s'\n", ip
->id
));
2267 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "... link %p -> %p\n", q
, r
));
2271 else if (*ip
->id
== '#')
2272 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Missing data for id='%s'\n", ip
->id
));
2273 /* Oracle customization */
2274 strncpy(soap
->id
, ip
->id
+ 1, sizeof(soap
->id
) - 1);
2275 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
2276 return soap
->error
= SOAP_MISSING_ID
;
2282 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolution phase\n"));
2283 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2284 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2285 { if (ip
->ptr
&& !soap_has_copies(soap
, (const char*)ip
->ptr
, (const char*)ip
->ptr
+ ip
->size
))
2287 { register void *p
, **q
= (void**)ip
->copy
;
2288 DBGLOG(TEST
, if (q
) SOAP_MESSAGE(fdebug
, "Traversing copy chain to resolve id='%s'\n", ip
->id
));
2291 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "... copy %p -> %p (%u bytes)\n", ip
->ptr
, q
, (unsigned int)ip
->size
));
2293 memcpy(q
, ip
->ptr
, ip
->size
);
2298 for (fp
= ip
->flist
; fp
; fp
= ip
->flist
)
2299 { register unsigned int k
= fp
->level
;
2300 register void *p
= ip
->ptr
;
2301 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
));
2302 while (ip
->level
< k
)
2303 { register void **q
= (void**)soap_malloc(soap
, sizeof(void*));
2307 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level, new location=%p holds=%p...\n", q
, *q
));
2312 fp
->fcopy(soap
, ip
->type
, fp
->type
, fp
->ptr
, fp
->len
, p
, ip
->size
);
2314 soap_fcopy(soap
, ip
->type
, fp
->type
, fp
->ptr
, fp
->len
, p
, ip
->size
);
2315 ip
->flist
= fp
->next
;
2316 SOAP_FREE(soap
, fp
);
2324 for (i
= 0; i
< SOAP_IDHASH
; i
++)
2325 { for (ip
= soap
->iht
[i
]; ip
; ip
= ip
->next
)
2326 { if (ip
->copy
|| ip
->flist
)
2327 { 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
));
2332 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolution done\n"));
2338 /******************************************************************************/
2343 soap_size_block(struct soap
*soap
, struct soap_blist
*b
, size_t n
)
2347 { b
->size
-= *(size_t*)(b
->ptr
+ sizeof(char*)) - n
;
2348 *(size_t*)(b
->ptr
+ sizeof(char*)) = n
;
2354 /******************************************************************************/
2359 soap_first_block(struct soap
*soap
, struct soap_blist
*b
)
2366 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "First block\n"));
2375 return r
+ sizeof(char*) + sizeof(size_t);
2379 /******************************************************************************/
2384 soap_next_block(struct soap
*soap
, struct soap_blist
*b
)
2390 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Next block\n"));
2391 b
->ptr
= *(char**)p
;
2394 return b
->ptr
+ sizeof(char*) + sizeof(size_t);
2400 /******************************************************************************/
2405 soap_block_size(struct soap
*soap
, struct soap_blist
*b
)
2408 return *(size_t*)(b
->ptr
+ sizeof(char*));
2412 /******************************************************************************/
2417 soap_end_block(struct soap
*soap
, struct soap_blist
*b
)
2422 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of block sequence, free all remaining blocks\n"));
2423 for (p
= b
->ptr
; p
; p
= q
)
2427 if (soap
->blist
== b
)
2428 soap
->blist
= b
->next
;
2430 { struct soap_blist
*bp
;
2431 for (bp
= soap
->blist
; bp
; bp
= bp
->next
)
2432 { if (bp
->next
== b
)
2433 { bp
->next
= b
->next
;
2440 DBGLOG(TEST
, if (soap
->blist
) SOAP_MESSAGE(fdebug
, "Restore previous block sequence\n"));
2444 /******************************************************************************/
2449 soap_save_block(struct soap
*soap
, struct soap_blist
*b
, char *p
, int flag
)
2450 { register size_t n
;
2451 register char *q
, *s
;
2454 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
));
2457 p
= (char*)soap_malloc(soap
, b
->size
);
2459 { for (s
= p
, q
= soap_first_block(soap
, b
); q
; q
= soap_next_block(soap
, b
))
2460 { n
= soap_block_size(soap
, b
);
2461 #ifndef WITH_NOIDREF
2463 soap_update_ptrs(soap
, q
, q
+ n
, s
, q
);
2465 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copy %u bytes from %p to %p\n", (unsigned int)n
, q
, s
));
2471 soap
->error
= SOAP_EOM
;
2473 soap_end_block(soap
, b
);
2478 /******************************************************************************/
2483 soap_putsize(struct soap
*soap
, const char *type
, int size
)
2484 { return soap_putsizes(soap
, type
, &size
, 1);
2488 /******************************************************************************/
2493 soap_putsizes(struct soap
*soap
, const char *type
, const int *size
, int dim
)
2494 { return soap_putsizesoffsets(soap
, type
, size
, NULL
, dim
);
2498 /******************************************************************************/
2503 soap_putsizesoffsets(struct soap
*soap
, const char *type
, const int *size
, const int *offset
, int dim
)
2507 if (soap
->version
== 2)
2508 { sprintf(soap
->type
, "%s[%d", type
, size
[0]);
2509 for (i
= 1; i
< dim
; i
++)
2510 sprintf(soap
->type
+ strlen(soap
->type
), " %d", size
[i
]);
2514 { sprintf(soap
->type
, "%s[%d", type
, size
[0] + offset
[0]);
2515 for (i
= 1; i
< dim
; i
++)
2516 sprintf(soap
->type
+ strlen(soap
->type
), ",%d", size
[i
] + offset
[i
]);
2519 { sprintf(soap
->type
, "%s[%d", type
, size
[0]);
2520 for (i
= 1; i
< dim
; i
++)
2521 sprintf(soap
->type
+ strlen(soap
->type
), ",%d", size
[i
]);
2523 strcat(soap
->type
, "]");
2529 /******************************************************************************/
2534 soap_putoffset(struct soap
*soap
, int offset
)
2535 { return soap_putoffsets(soap
, &offset
, 1);
2539 /******************************************************************************/
2544 soap_putoffsets(struct soap
*soap
, const int *offset
, int dim
)
2546 sprintf(soap
->arrayOffset
, "[%d", offset
[0]);
2547 for (i
= 1; i
< dim
; i
++)
2548 sprintf(soap
->arrayOffset
+ strlen(soap
->arrayOffset
), ",%d", offset
[i
]);
2549 strcat(soap
->arrayOffset
, "]");
2550 return soap
->arrayOffset
;
2554 /******************************************************************************/
2559 soap_size(const int *size
, int dim
)
2560 { register int i
, n
= size
[0];
2561 for (i
= 1; i
< dim
; i
++)
2567 /******************************************************************************/
2572 soap_getoffsets(const char *attr
, const int *size
, int *offset
, int dim
)
2573 { register int i
, j
= 0;
2575 for (i
= 0; i
< dim
&& attr
&& *attr
; i
++)
2578 j
+= offset
[i
] = (int)soap_strtol(attr
, NULL
, 10);
2579 attr
= strchr(attr
, ',');
2582 for (i
= 0; i
< dim
&& attr
&& *attr
; i
++)
2585 j
+= (int)soap_strtol(attr
, NULL
, 10);
2586 attr
= strchr(attr
, ',');
2592 /******************************************************************************/
2597 soap_getsize(const char *attr1
, const char *attr2
, int *j
)
2598 { register int n
, k
;
2607 { k
= (int)soap_strtol(attr1
, &s
, 10);
2609 if (k
< 0 || n
> SOAP_MAXARRAYSIZE
|| s
== attr1
)
2611 attr1
= strchr(s
, ',');
2613 attr1
= strchr(s
, ' ');
2614 if (attr2
&& *attr2
)
2617 k
= (int)soap_strtol(attr2
, &s
, 10);
2631 /******************************************************************************/
2636 soap_getsizes(const char *attr
, int *size
, int dim
)
2637 { register int i
, k
, n
;
2640 i
= (int)strlen(attr
);
2643 { for (i
= i
-1; i
>= 0; i
--)
2644 if (attr
[i
] == '[' || attr
[i
] == ',' || attr
[i
] == ' ')
2646 k
= (int)soap_strtol(attr
+ i
+ 1, NULL
, 10);
2647 n
*= size
[--dim
] = k
;
2648 if (k
< 0 || n
> SOAP_MAXARRAYSIZE
)
2650 } while (i
>= 0 && attr
[i
] != '[');
2655 /******************************************************************************/
2660 soap_getposition(const char *attr
, int *pos
)
2661 { register int i
, n
;
2667 { pos
[n
++] = (int)soap_strtol(attr
+ i
, NULL
, 10);
2668 while (attr
[i
] && attr
[i
] != ',' && attr
[i
] != ']')
2672 } while (n
< SOAP_MAXDIMS
&& attr
[i
] && attr
[i
] != ']');
2677 /******************************************************************************/
2682 soap_push_namespace(struct soap
*soap
, const char *id
, const char *ns
)
2683 { register struct soap_nlist
*np
;
2684 register struct Namespace
*p
;
2685 register short i
= -1;
2686 register size_t n
, k
;
2689 p
= soap
->local_namespaces
;
2691 { for (i
= 0; p
->id
; p
++, i
++)
2692 { if (p
->ns
&& !strcmp(ns
, p
->ns
))
2694 { SOAP_FREE(soap
, p
->out
);
2700 { if (!strcmp(ns
, p
->out
))
2704 { if (!soap_tag_cmp(ns
, p
->in
))
2705 { if ((p
->out
= (char*)SOAP_MALLOC(soap
, k
)))
2716 np
= (struct soap_nlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_nlist
) + n
+ k
);
2718 { soap
->error
= SOAP_EOM
;
2721 np
->next
= soap
->nlist
;
2723 np
->level
= soap
->level
;
2726 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push namespace binding (level=%u) '%s' '%s'\n", soap
->level
, id
, ns
));
2728 { np
->ns
= strcpy(np
->id
+ n
+ 1, ns
);
2729 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns
));
2733 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Push OK ('%s' matches '%s' in namespace table)\n", id
, p
->id
));
2739 /******************************************************************************/
2744 soap_pop_namespace(struct soap
*soap
)
2745 { register struct soap_nlist
*np
, *nq
;
2746 for (np
= soap
->nlist
; np
&& np
->level
>= soap
->level
; np
= nq
)
2748 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Pop namespace binding (level=%u) '%s'\n", soap
->level
, np
->id
));
2749 SOAP_FREE(soap
, np
);
2755 /******************************************************************************/
2760 soap_match_namespace(struct soap
*soap
, const char *id1
, const char *id2
, size_t n1
, size_t n2
)
2761 { register struct soap_nlist
*np
= soap
->nlist
;
2762 while (np
&& (strncmp(np
->id
, id1
, n1
) || np
->id
[n1
]))
2765 { if (!(soap
->mode
& SOAP_XML_IGNORENS
))
2767 || (soap
->local_namespaces
[np
->index
].id
2768 && (strncmp(soap
->local_namespaces
[np
->index
].id
, id2
, n2
)
2769 || soap
->local_namespaces
[np
->index
].id
[n2
])))
2770 return SOAP_NAMESPACE
;
2774 return SOAP_NAMESPACE
;
2775 if ((n1
== 3 && n1
== n2
&& !strncmp(id1
, "xml", 3) && !strncmp(id1
, id2
, 3))
2776 || (soap
->mode
& SOAP_XML_IGNORENS
))
2778 return soap
->error
= SOAP_SYNTAX_ERROR
;
2782 /******************************************************************************/
2787 soap_current_namespace(struct soap
*soap
, const char *tag
)
2788 { register struct soap_nlist
*np
;
2789 register const char *s
;
2790 if (!tag
|| !strncmp(tag
, "xml", 3))
2793 if (!(s
= strchr(tag
, ':')))
2794 { while (np
&& *np
->id
) /* find default namespace, if present */
2798 { while (np
&& (strncmp(np
->id
, tag
, s
- tag
) || np
->id
[s
- tag
]))
2801 soap
->error
= SOAP_NAMESPACE
;
2804 { if (np
->index
>= 0)
2805 return soap
->namespaces
[np
->index
].ns
;
2807 return soap_strdup(soap
, np
->ns
);
2813 /******************************************************************************/
2818 soap_tag_cmp(const char *s
, const char *t
)
2820 { register int c1
= *s
;
2821 register int c2
= *t
;
2822 if (!c1
|| c1
== '"')
2826 { if (c1
>= 'A' && c1
<= 'Z')
2828 if (c2
>= 'A' && c2
<= 'Z')
2837 if (c2
>= 'A' && c2
<= 'Z')
2841 if (!c1
|| c1
== '"')
2843 if (c1
>= 'A' && c1
<= 'Z')
2845 if (c1
== c2
&& !soap_tag_cmp(s
+ 1, t
+ 1))
2855 if (*t
== '*' && !t
[1])
2861 /******************************************************************************/
2866 soap_match_tag(struct soap
*soap
, const char *tag1
, const char *tag2
)
2867 { register const char *s
, *t
;
2869 if (!tag1
|| !tag2
|| !*tag2
)
2871 s
= strchr(tag1
, ':');
2872 t
= strchr(tag2
, ':');
2875 { if (t
[1] && SOAP_STRCMP(s
+ 1, t
+ 1))
2876 return SOAP_TAG_MISMATCH
;
2877 if (t
!= tag2
&& (err
= soap_match_namespace(soap
, tag1
, tag2
, s
- tag1
, t
- tag2
)))
2878 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags '%s' and '%s' match but namespaces differ\n", tag1
, tag2
));
2879 if (err
== SOAP_NAMESPACE
)
2880 return SOAP_TAG_MISMATCH
;
2884 else if (SOAP_STRCMP(tag1
, t
+ 1))
2885 { return SOAP_TAG_MISMATCH
;
2887 else if (t
!= tag2
&& (err
= soap_match_namespace(soap
, tag1
, tag2
, 0, t
- tag2
)))
2888 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags '%s' and '%s' match but namespaces differ\n", tag1
, tag2
));
2889 if (err
== SOAP_NAMESPACE
)
2890 return SOAP_TAG_MISMATCH
;
2893 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags and (default) namespaces match: '%s' '%s'\n", tag1
, tag2
));
2897 { if (SOAP_STRCMP(s
+ 1, tag2
))
2898 return SOAP_TAG_MISMATCH
;
2900 else if (SOAP_STRCMP(tag1
, tag2
))
2901 return SOAP_TAG_MISMATCH
;
2902 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Tags match: '%s' '%s'\n", tag1
, tag2
));
2907 /******************************************************************************/
2912 soap_match_array(struct soap
*soap
, const char *type
)
2913 { if (*soap
->arrayType
)
2914 if (soap_match_tag(soap
, soap
->arrayType
, type
)
2915 && soap_match_tag(soap
, soap
->arrayType
, "xsd:anyType")
2916 && soap_match_tag(soap
, soap
->arrayType
, "xsd:ur-type")
2918 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array type mismatch: '%s' '%s'\n", soap
->arrayType
, type
));
2919 return SOAP_TAG_MISMATCH
;
2925 /******************************************************************************\
2929 \******************************************************************************/
2931 /******************************************************************************/
2938 { unsigned char buf
[4];
2939 if (!soap_ssl_init_done
)
2941 RAND_pseudo_bytes(buf
, 4);
2947 /******************************************************************************/
2953 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
)
2955 soap
->keyfile
= keyfile
;
2956 soap
->password
= password
;
2957 soap
->cafile
= cafile
;
2958 soap
->capath
= capath
;
2959 soap
->crlfile
= NULL
;
2960 soap
->dhfile
= dhfile
;
2961 soap
->randfile
= randfile
;
2962 soap
->ssl_flags
= flags
| (dhfile
== NULL
? SOAP_SSL_RSA
: 0);
2963 if (!(err
= soap
->fsslauth(soap
)))
2965 SSL_CTX_set_session_id_context(soap
->ctx
, (unsigned char*)sid
, (unsigned int)strlen(sid
));
2967 SSL_CTX_set_session_cache_mode(soap
->ctx
, SSL_SESS_CACHE_OFF
);
2974 /******************************************************************************/
2980 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
)
2981 { soap
->keyfile
= keyfile
;
2982 soap
->password
= password
;
2983 soap
->cafile
= cafile
;
2984 soap
->capath
= capath
;
2985 soap
->dhfile
= NULL
;
2986 soap
->ssl_flags
= flags
;
2987 soap
->randfile
= randfile
;
2988 soap
->fsslverify
= (flags
& SOAP_SSL_ALLOW_EXPIRED_CERTIFICATE
) == 0 ? ssl_verify_callback
: ssl_verify_callback_allow_expired_certificate
;
2989 return soap
->fsslauth(soap
);
2994 /******************************************************************************/
3001 { /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
3002 if (!soap_ssl_init_done
)
3003 { soap_ssl_init_done
= 1;
3006 SSL_load_error_strings();
3008 if (!RAND_load_file("/dev/urandom", 1024))
3010 RAND_seed(buf
, sizeof(buf
));
3011 while (!RAND_status())
3013 RAND_seed(&r
, sizeof(int));
3021 /******************************************************************************/
3027 soap_ssl_error(struct soap
*soap
, int ret
)
3028 { int err
= SSL_get_error(soap
->ssl
, ret
);
3029 const char *msg
= soap_code_str(h_ssl_error_codes
, err
);
3030 size_t msgbufsize
= sizeof(soap
->msgbuf
);
3032 { /* Oracle customization */
3033 strncpy(soap
->msgbuf
, msg
, msgbufsize
- 1);
3034 soap
->msgbuf
[msgbufsize
- 1] = '\0';
3037 return ERR_error_string(err
, soap
->msgbuf
);
3038 if (ERR_peek_error())
3040 /* Oracle customization */
3041 if (strlen(soap
->msgbuf
) < (msgbufsize
-1))
3042 strcat(soap
->msgbuf
, "\n");
3044 soap
->msgbuf
[msgbufsize
- 2] = '\n';
3045 while ((r
= ERR_get_error()))
3046 ERR_error_string_n(r
, soap
->msgbuf
+ strlen(soap
->msgbuf
), sizeof(soap
->msgbuf
) - strlen(soap
->msgbuf
));
3052 /* Oracle customization -- display SSL error code and string at the end */
3053 int myerrno
= errno
;
3054 unsigned long ec
= ERR_get_error();
3055 sprintf(soap
->msgbuf
,
3056 "EOF was observed that violates the protocol. The client probably provided invalid authentication information. SSL error code is %s. ",
3060 /* display the next error string in the error queue */
3061 ERR_error_string_n(ec
, soap
->msgbuf
+ strlen(soap
->msgbuf
),
3062 sizeof(soap
->msgbuf
) - strlen(soap
->msgbuf
));
3063 if (sizeof(soap
->msgbuf
) - strlen(soap
->msgbuf
) > 2)
3065 strcat(soap
->msgbuf
, ". ");
3070 /* display system error too */
3071 char *mystrerror
= strerror(myerrno
);
3072 if (strlen(mystrerror
)
3073 < (sizeof(soap
->msgbuf
) - strlen(soap
->msgbuf
)))
3075 strncat(soap
->msgbuf
+ strlen(soap
->msgbuf
), mystrerror
,
3076 strlen(mystrerror
));
3080 strncat(soap
->msgbuf
+ strlen(soap
->msgbuf
), mystrerror
,
3081 (sizeof(soap
->msgbuf
) - strlen(soap
->msgbuf
)));
3083 soap
->msgbuf
[sizeof(soap
->msgbuf
) - 1] = '\0';
3088 sprintf(soap
->msgbuf
, "Error observed by underlying BIO: %s", strerror(errno
));
3092 return soap
->msgbuf
;
3097 /******************************************************************************/
3101 ssl_password(char *buf
, int num
, int rwflag
, void *userdata
)
3102 { if (num
< (int)strlen((char*)userdata
) + 1)
3104 return (int)strlen(strcpy(buf
, (char*)userdata
));
3109 /******************************************************************************/
3116 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 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 // Oracle customization
3133 // added SSL_CTX_set_cipher_list call to restrict the cipher suite to RSA-2048/AES
3134 // TLS_RSA_WITH_AES_256_CBC_SHA is defined in RFC 3268
3135 // also see http://www.openssl.org/docs/apps/ciphers.html
3137 if (!SSL_CTX_set_cipher_list(soap
->ctx
, "AES256-SHA"))
3138 return soap_set_receiver_error(soap
, "SSL error", "Cannot set cipher suite", SOAP_SSL_ERROR
);
3140 { if (!RAND_load_file(soap
->randfile
, -1))
3141 return soap_set_receiver_error(soap
, "SSL error", "Can't load randomness", SOAP_SSL_ERROR
);
3143 if (soap
->cafile
|| soap
->capath
)
3144 { if (!SSL_CTX_load_verify_locations(soap
->ctx
, soap
->cafile
, soap
->capath
))
3145 return soap_set_receiver_error(soap
, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR
);
3146 if (soap
->cafile
&& (soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3147 SSL_CTX_set_client_CA_list(soap
->ctx
, SSL_load_client_CA_file(soap
->cafile
));
3149 if (!(soap
->ssl_flags
& SOAP_SSL_NO_DEFAULT_CA_PATH
))
3150 { if (!SSL_CTX_set_default_verify_paths(soap
->ctx
))
3151 return soap_set_receiver_error(soap
, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR
);
3153 /* This code assumes a typical scenario, see alternative code below */
3155 { if (!SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->keyfile
))
3156 return soap_set_receiver_error(soap
, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR
);
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 (!SSL_CTX_use_PrivateKey_file(soap
->ctx
, soap
->keyfile
, SSL_FILETYPE_PEM
))
3162 return soap_set_receiver_error(soap
, "SSL error", "Can't read key file", SOAP_SSL_ERROR
);
3164 /* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
3167 { SSL_CTX_set_default_passwd_cb_userdata(soap
->ctx
, (void*)soap
->password
);
3168 SSL_CTX_set_default_passwd_cb(soap
->ctx
, ssl_password
);
3170 if (!soap
->cafile
|| !SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->cafile
))
3171 { if (soap
->keyfile
)
3172 { if (!SSL_CTX_use_certificate_chain_file(soap
->ctx
, soap
->keyfile
))
3173 return soap_set_receiver_error(soap
, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR
);
3174 if (!SSL_CTX_use_PrivateKey_file(soap
->ctx
, soap
->keyfile
, SSL_FILETYPE_PEM
))
3175 return soap_set_receiver_error(soap
, "SSL error", "Can't read key file", SOAP_SSL_ERROR
);
3179 if ((soap
->ssl_flags
& SOAP_SSL_RSA
))
3182 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3184 #ifdef OPENSSL_NO_DEPRECATED
3185 RSA
*rsa
= RSA_new();
3188 return soap_set_receiver_error(soap
, "SSL error", "Can't allocate RSA struct", SOAP_SSL_ERROR
);
3191 BIGNUM
*e
= BN_new();
3195 return soap_set_receiver_error(soap
, "SSL error", "Can't allocate BIGNUM", SOAP_SSL_ERROR
);
3197 if (!BN_set_word(e
, RSA_F4
))
3201 return soap_set_receiver_error(soap
, "SSL error", "Can't set BIGNUM value", SOAP_SSL_ERROR
);
3204 #if OPENSSL_VERSION_NUMBER > 0x00908000L
3205 if (!RSA_generate_key_ex(rsa
, 1024, e
, NULL
))
3207 if (( rsa
= RSA_generate_key(1024, RSA_F4
, NULL
, NULL
)) == NULL
)
3212 return soap_set_receiver_error(soap
, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR
);
3216 RSA
*rsa
= RSA_generate_key(1024, RSA_F4
, NULL
, NULL
);
3218 if (!SSL_CTX_set_tmp_rsa(soap
->ctx
, rsa
))
3222 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3224 #ifdef OPENSSL_NO_DEPRECATED
3227 return soap_set_receiver_error(soap
, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR
);
3231 Oracle customization for OpenSSL 0.9.8 removal of deprecated function usage: RSA_generate_key
3233 #ifdef OPENSSL_NO_DEPRECATED
3237 else if (soap
->dhfile
)
3240 #ifdef OPENSSL_NO_DEPRECATED
3244 int n
= (int)soap_strtoul(soap
->dhfile
, &s
, 10);
3245 /* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
3246 if (n
>= 512 && s
&& *s
== '\0') {
3247 #if !defined(OPENSSL_NO_DEPRECATED) || OPENSSL_VERSION_NUMBER < 0x00908000L
3248 dh
= DH_generate_parameters(n
, 2/*or 5*/, NULL
, NULL
);
3250 if (DH_generate_parameters_ex(&dhrec
, n
, 2/*or 5*/, NULL
) == 0)
3253 return soap_set_receiver_error(soap
, "SSL error", "Can't compute DH params", SOAP_SSL_ERROR
);
3258 bio
= BIO_new_file(soap
->dhfile
, "r");
3260 return soap_set_receiver_error(soap
, "SSL error", "Can't read DH file", SOAP_SSL_ERROR
);
3261 dh
= PEM_read_bio_DHparams(bio
, NULL
, NULL
, NULL
);
3264 if (!dh
|| DH_check(dh
, &n
) != 1 || SSL_CTX_set_tmp_dh(soap
->ctx
, dh
) < 0)
3266 #ifndef OPENSSL_NO_DEPRECATED
3270 return soap_set_receiver_error(soap
, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR
);
3272 #ifndef OPENSSL_NO_DEPRECATED
3278 // Oracle customization
3280 // Added SSL_OP_NO_SSLv3 to force use of TLS
3281 // Added SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG to prevent forced downgrade
3282 // of security level
3284 flags
= ((SSL_OP_ALL
& ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
) | SSL_OP_NO_SSLv2
| SSL_OP_NO_SSLv3
);
3286 flags
= (SSL_OP_ALL
| SSL_OP_NO_SSLv2
);
3287 if ((soap
->ssl_flags
& SOAP_SSLv3
))
3288 flags
|= SSL_OP_NO_TLSv1
;
3289 if ((soap
->ssl_flags
& SOAP_TLSv1
))
3290 flags
|= SSL_OP_NO_SSLv3
;
3291 #ifdef SSL_OP_NO_TICKET
3292 /* TLS extension is enabled by default in OPENSSL v0.9.8k
3293 Disable it by adding SSL_OP_NO_TICKET */
3294 flags
|= SSL_OP_NO_TICKET
;
3296 SSL_CTX_set_options(soap
->ctx
, flags
);
3297 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3298 mode
= (SSL_VERIFY_PEER
| SSL_VERIFY_FAIL_IF_NO_PEER_CERT
);
3299 else if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
3300 mode
= SSL_VERIFY_PEER
;
3302 mode
= SSL_VERIFY_NONE
;
3303 SSL_CTX_set_verify(soap
->ctx
, mode
, soap
->fsslverify
);
3304 #if (OPENSSL_VERSION_NUMBER < 0x00905100L)
3305 SSL_CTX_set_verify_depth(soap
->ctx
, 1);
3307 SSL_CTX_set_verify_depth(soap
->ctx
, 9);
3314 /******************************************************************************/
3318 ssl_verify_callback(int ok
, X509_STORE_CTX
*store
)
3323 X509
*cert
= X509_STORE_CTX_get_current_cert(store
);
3324 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
)));
3325 X509_NAME_oneline(X509_get_issuer_name(cert
), data
, sizeof(data
));
3326 fprintf(stderr
, "certificate issuer %s\n", data
);
3327 X509_NAME_oneline(X509_get_subject_name(cert
), data
, sizeof(data
));
3328 fprintf(stderr
, "certificate subject %s\n", data
);
3331 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3337 /******************************************************************************/
3341 ssl_verify_callback_allow_expired_certificate(int ok
, X509_STORE_CTX
*store
)
3342 { ok
= ssl_verify_callback(ok
, store
);
3343 if (ok
== 0 && X509_STORE_CTX_get_error(store
) == X509_V_ERR_CERT_HAS_EXPIRED
)
3346 fprintf(stderr
, "ignoring certificate expiration\n");
3348 X509_STORE_CTX_set_error(store
, X509_V_OK
);
3351 /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3357 /******************************************************************************/
3364 soap_ssl_accept(struct soap
*soap
)
3367 if (!soap_valid_socket(soap
->socket
))
3368 return soap_set_receiver_error(soap
, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR
);
3369 if (!soap
->ctx
&& (soap
->error
= soap
->fsslauth(soap
)))
3370 return SOAP_SSL_ERROR
;
3372 { soap
->ssl
= SSL_new(soap
->ctx
);
3374 return soap_set_receiver_error(soap
, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR
);
3377 SSL_clear(soap
->ssl
);
3378 soap
->imode
|= SOAP_ENC_SSL
;
3379 soap
->omode
|= SOAP_ENC_SSL
;
3380 /* Set SSL sockets to non-blocking */
3381 SOAP_SOCKNONBLOCK(soap
->socket
)
3382 bio
= BIO_new_socket((int)soap
->socket
, BIO_NOCLOSE
);
3383 SSL_set_bio(soap
->ssl
, bio
, bio
);
3384 retries
= 100; /* SSL_accept timeout: 10 sec retries, 100 times 0.1 sec */
3385 #if defined(WITH_OPENSSL) && defined(KMS_SERVER)
3386 /* Oracle customization for Ultra 2 KMS Server */
3387 if (soap
->ssl_accept_timeout
> 0 )
3389 retries
= 10 * soap
->ssl_accept_timeout
;
3393 while ((r
= SSL_accept(soap
->ssl
)) <= 0)
3394 { int err
= SSL_get_error(soap
->ssl
, r
);
3395 if (err
== SSL_ERROR_WANT_ACCEPT
|| err
== SSL_ERROR_WANT_READ
|| err
== SSL_ERROR_WANT_WRITE
)
3396 { if (err
== SSL_ERROR_WANT_READ
)
3397 s
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
3399 s
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
3400 if (s
< 0 && soap
->errnum
!= SOAP_EINTR
)
3404 { soap
->errnum
= soap_socket_errno(soap
->socket
);
3411 { soap_set_receiver_error(soap
, soap_ssl_error(soap
, r
), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR
);
3412 soap_closesock(soap
);
3413 return SOAP_SSL_ERROR
;
3415 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION
))
3418 if ((err
= SSL_get_verify_result(soap
->ssl
)) != X509_V_OK
)
3419 { soap_closesock(soap
);
3420 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
);
3422 peer
= SSL_get_peer_certificate(soap
->ssl
);
3424 { soap_closesock(soap
);
3425 return soap_set_sender_error(soap
, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR
);
3435 /******************************************************************************\
3437 * TCP/UDP [SSL/TLS] IPv4 and IPv6
3439 \******************************************************************************/
3441 /******************************************************************************/
3445 tcp_init(struct soap
*soap
)
3446 { soap
->errmode
= 1;
3452 if (WSAStartup(MAKEWORD(1, 1), &w
))
3462 /******************************************************************************/
3466 tcp_error(struct soap
*soap
)
3467 { register const char *msg
= NULL
;
3468 switch (soap
->errmode
)
3470 msg
= soap_strerror(soap
);
3473 msg
= "WSAStartup failed";
3478 msg
= soap_code_str(h_error_codes
, soap
->errnum
);
3481 { sprintf(soap
->msgbuf
, "TCP/UDP IP error %d", soap
->errnum
);
3491 /******************************************************************************/
3496 tcp_gethost(struct soap
*soap
, const char *addr
, struct in_addr
*inaddr
)
3497 { soap_int32 iadd
= -1;
3498 struct hostent hostent
, *host
= &hostent
;
3501 /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3502 iadd
= inet_addr((char*)addr
);
3504 #if defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3505 struct hostent_data ht_data
;
3508 iadd
= inet_addr((void*)addr
);
3510 iadd
= inet_addr(addr
);
3514 { memcpy(inaddr
, &iadd
, sizeof(iadd
));
3517 #if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
3518 if (gethostbyname_r(addr
, &hostent
, soap
->buf
, SOAP_BUFLEN
, &host
, &soap
->errnum
) < 0)
3520 #elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
3521 memset((void*)&ht_data
, 0, sizeof(ht_data
));
3522 if (gethostbyname_r(addr
, &hostent
, &ht_data
) < 0)
3524 soap
->errnum
= h_errno
;
3526 #elif defined(HAVE_GETHOSTBYNAME_R)
3527 host
= gethostbyname_r(addr
, &hostent
, soap
->buf
, SOAP_BUFLEN
, &soap
->errnum
);
3528 #elif defined(VXWORKS)
3529 /* If the DNS resolver library resolvLib has been configured in the vxWorks
3530 * image, a query for the host IP address is sent to the DNS server, if the
3531 * name was not found in the local host table. */
3532 hostint
= hostGetByName((char*)addr
);
3533 if (hostint
== ERROR
)
3535 soap
->errnum
= soap_errno
;
3539 if (!(host
= gethostbyname((void*)addr
)))
3540 soap
->errnum
= h_errno
;
3542 if (!(host
= gethostbyname(addr
)))
3543 soap
->errnum
= h_errno
;
3547 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Host name not found\n"));
3551 inaddr
->s_addr
= hostint
;
3553 memcpy(inaddr
, host
->h_addr
, host
->h_length
);
3561 /******************************************************************************/
3565 tcp_connect(struct soap
*soap
, const char *endpoint
, const char *host
, int port
)
3568 struct addrinfo hints
, *res
, *ressave
;
3573 int len
= SOAP_BUFLEN
;
3576 #if !defined(WITH_LEAN) || defined(WITH_OPENSSL)
3579 if (soap_valid_socket(soap
->socket
))
3580 soap
->fclosesocket(soap
, soap
->socket
);
3581 soap
->socket
= SOAP_INVALID_SOCKET
;
3584 soap_set_sender_error(soap
, tcp_error(soap
), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR
);
3585 return SOAP_INVALID_SOCKET
;
3589 memset((void*)&hints
, 0, sizeof(hints
));
3590 hints
.ai_family
= PF_UNSPEC
;
3592 if ((soap
->omode
& SOAP_IO_UDP
))
3593 hints
.ai_socktype
= SOCK_DGRAM
;
3596 hints
.ai_socktype
= SOCK_STREAM
;
3599 if (soap
->proxy_host
)
3600 err
= getaddrinfo(soap
->proxy_host
, soap_int2s(soap
, soap
->proxy_port
), &hints
, &res
);
3602 err
= getaddrinfo(host
, soap_int2s(soap
, port
), &hints
, &res
);
3603 /* Oracle customization: check err before using res */
3604 if (err
|| (res
==NULL
))
3605 { soap_set_sender_error(soap
, SOAP_GAI_STRERROR(err
), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR
);
3610 return SOAP_INVALID_SOCKET
;
3614 fd
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
3621 if ((soap
->omode
& SOAP_IO_UDP
))
3622 fd
= socket(AF_INET
, SOCK_DGRAM
, 0);
3625 fd
= socket(AF_INET
, SOCK_STREAM
, 0);
3627 if (!soap_valid_socket(fd
))
3631 { res
= res
->ai_next
;
3635 soap
->errnum
= soap_socket_errno(fd
);
3636 soap_set_sender_error(soap
, tcp_error(soap
), "socket failed in tcp_connect()", SOAP_TCP_ERROR
);
3638 freeaddrinfo(ressave
);
3640 return SOAP_INVALID_SOCKET
;
3642 #ifdef SOCKET_CLOSE_ON_EXEC
3645 SetHandleInformation((HANDLE
)fd
, HANDLE_FLAG_INHERIT
, 0);
3648 fcntl(fd
, F_SETFD
, 1);
3652 if (soap
->connect_flags
== SO_LINGER
)
3653 { struct linger linger
;
3654 memset((void*)&linger
, 0, sizeof(linger
));
3656 linger
.l_linger
= soap
->linger_time
;
3657 if (setsockopt(fd
, SOL_SOCKET
, SO_LINGER
, (char*)&linger
, sizeof(struct linger
)))
3658 { soap
->errnum
= soap_socket_errno(fd
);
3659 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR
);
3660 soap
->fclosesocket(soap
, fd
);
3662 freeaddrinfo(ressave
);
3664 return SOAP_INVALID_SOCKET
;
3667 else if (soap
->connect_flags
&& setsockopt(fd
, SOL_SOCKET
, soap
->connect_flags
, (char*)&set
, sizeof(int)))
3668 { soap
->errnum
= soap_socket_errno(fd
);
3669 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR
);
3670 soap
->fclosesocket(soap
, fd
);
3672 freeaddrinfo(ressave
);
3674 return SOAP_INVALID_SOCKET
;
3676 if ((soap
->keep_alive
|| soap
->tcp_keep_alive
) && setsockopt(fd
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
3677 { soap
->errnum
= soap_socket_errno(fd
);
3678 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR
);
3679 soap
->fclosesocket(soap
, fd
);
3681 freeaddrinfo(ressave
);
3683 return SOAP_INVALID_SOCKET
;
3685 if (setsockopt(fd
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
3686 { soap
->errnum
= soap_socket_errno(fd
);
3687 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR
);
3688 soap
->fclosesocket(soap
, fd
);
3690 freeaddrinfo(ressave
);
3692 return SOAP_INVALID_SOCKET
;
3694 if (setsockopt(fd
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
3695 { soap
->errnum
= soap_socket_errno(fd
);
3696 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR
);
3697 soap
->fclosesocket(soap
, fd
);
3699 freeaddrinfo(ressave
);
3701 return SOAP_INVALID_SOCKET
;
3704 if (soap
->tcp_keep_idle
&& setsockopt((SOAP_SOCKET
)fd
, IPPROTO_TCP
, TCP_KEEPIDLE
, (char*)&(soap
->tcp_keep_idle
), sizeof(int)))
3705 { soap
->errnum
= soap_socket_errno(fd
);
3706 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR
);
3707 soap
->fclosesocket(soap
, (SOAP_SOCKET
)fd
);
3709 freeaddrinfo(ressave
);
3711 return SOAP_INVALID_SOCKET
;
3714 #ifdef TCP_KEEPINTVL
3715 if (soap
->tcp_keep_intvl
&& setsockopt((SOAP_SOCKET
)fd
, IPPROTO_TCP
, TCP_KEEPINTVL
, (char*)&(soap
->tcp_keep_intvl
), sizeof(int)))
3716 { soap
->errnum
= soap_socket_errno(fd
);
3717 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR
);
3718 soap
->fclosesocket(soap
, (SOAP_SOCKET
)fd
);
3720 freeaddrinfo(ressave
);
3722 return SOAP_INVALID_SOCKET
;
3726 if (soap
->tcp_keep_cnt
&& setsockopt((SOAP_SOCKET
)fd
, IPPROTO_TCP
, TCP_KEEPCNT
, (char*)&(soap
->tcp_keep_cnt
), sizeof(int)))
3727 { soap
->errnum
= soap_socket_errno(fd
);
3728 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR
);
3729 soap
->fclosesocket(soap
, (SOAP_SOCKET
)fd
);
3731 freeaddrinfo(ressave
);
3733 return SOAP_INVALID_SOCKET
;
3737 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(fd
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
3738 { soap
->errnum
= soap_socket_errno(fd
);
3739 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR
);
3740 soap
->fclosesocket(soap
, fd
);
3742 freeaddrinfo(ressave
);
3744 return SOAP_INVALID_SOCKET
;
3748 if ((soap
->omode
& SOAP_IO_UDP
) && soap
->ipv6_multicast_if
)
3749 { struct sockaddr_in6
*in6addr
= (struct sockaddr_in6
*)res
->ai_addr
;
3750 in6addr
->sin6_scope_id
= soap
->ipv6_multicast_if
;
3753 #ifdef IP_MULTICAST_TTL
3754 if ((soap
->omode
& SOAP_IO_UDP
) && soap
->ipv4_multicast_if
&& !soap
->ipv6_multicast_if
)
3755 { if (soap
->ipv4_multicast_ttl
> 0)
3756 { char ttl
= (char)(soap
->ipv4_multicast_ttl
);
3757 if (setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_TTL
, (char*)&ttl
, sizeof(ttl
)))
3758 { soap
->errnum
= soap_socket_errno(fd
);
3759 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_TTL failed in tcp_connect()", SOAP_TCP_ERROR
);
3760 soap
->fclosesocket(soap
, fd
);
3761 return SOAP_INVALID_SOCKET
;
3765 if (setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_IF
, (char*)soap
->ipv4_multicast_if
, sizeof(struct in_addr
)))
3766 { soap
->errnum
= soap_socket_errno(fd
);
3767 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR
);
3768 soap
->fclosesocket(soap
, fd
);
3769 return SOAP_INVALID_SOCKET
;
3772 #ifndef IP_MULTICAST_IF
3773 #define IP_MULTICAST_IF 2
3775 if (setsockopt(fd
, IPPROTO_IP
, IP_MULTICAST_IF
, (char*)soap
->ipv4_multicast_if
, sizeof(struct in_addr
)))
3776 { soap
->errnum
= soap_socket_errno(fd
);
3777 soap_set_sender_error(soap
, tcp_error(soap
), "setsockopt IP_MULTICAST_IF failed in tcp_connect()", SOAP_TCP_ERROR
);
3778 soap
->fclosesocket(soap
, fd
);
3779 return SOAP_INVALID_SOCKET
;
3785 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Opening socket %d to host='%s' port=%d\n", fd
, host
, port
));
3787 soap
->peerlen
= sizeof(soap
->peer
);
3788 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
3789 soap
->peer
.sin_family
= AF_INET
;
3791 if (soap
->proxy_host
)
3792 { if (soap
->fresolve(soap
, soap
->proxy_host
, &soap
->peer
.sin_addr
))
3793 { soap_set_sender_error(soap
, tcp_error(soap
), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR
);
3794 soap
->fclosesocket(soap
, fd
);
3795 return SOAP_INVALID_SOCKET
;
3797 soap
->peer
.sin_port
= htons((short)soap
->proxy_port
);
3800 { if (soap
->fresolve(soap
, host
, &soap
->peer
.sin_addr
))
3801 { soap_set_sender_error(soap
, tcp_error(soap
), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR
);
3802 soap
->fclosesocket(soap
, fd
);
3803 return SOAP_INVALID_SOCKET
;
3805 soap
->peer
.sin_port
= htons((short)port
);
3809 if ((soap
->omode
& SOAP_IO_UDP
))
3813 if ((soap
->omode
& SOAP_IO_UDP
))
3814 { memcpy(&soap
->peer
, res
->ai_addr
, res
->ai_addrlen
);
3815 soap
->peerlen
= res
->ai_addrlen
;
3816 freeaddrinfo(ressave
);
3821 if (soap
->connect_timeout
)
3822 SOAP_SOCKNONBLOCK(fd
)
3830 if (connect(fd
, res
->ai_addr
, (int)res
->ai_addrlen
))
3832 if (connect(fd
, (struct sockaddr
*)&soap
->peer
, sizeof(soap
->peer
)))
3834 { err
= soap_socket_errno(fd
);
3836 if (err
== SOAP_EADDRINUSE
)
3837 { soap
->fclosesocket(soap
, fd
);
3841 else if (soap
->connect_timeout
&& (err
== SOAP_EINPROGRESS
|| err
== SOAP_EAGAIN
|| err
== SOAP_EWOULDBLOCK
))
3846 r
= tcp_select(soap
, fd
, SOAP_TCP_SELECT_SND
, soap
->connect_timeout
);
3850 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connect timeout\n"));
3851 soap_set_sender_error(soap
, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3852 soap
->fclosesocket(soap
, fd
);
3853 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3855 freeaddrinfo(ressave
);
3857 return SOAP_INVALID_SOCKET
;
3860 if (r
!= SOAP_EINTR
)
3861 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
3862 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3863 soap
->fclosesocket(soap
, fd
);
3864 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3866 freeaddrinfo(ressave
);
3868 return SOAP_INVALID_SOCKET
;
3871 k
= (SOAP_SOCKLEN_T
)sizeof(soap
->errnum
);
3872 if (!getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, (char*)&soap
->errnum
, &k
) && !soap
->errnum
) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
3874 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
3876 soap
->errnum
= soap_socket_errno(fd
);
3877 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3878 soap
->fclosesocket(soap
, fd
);
3880 freeaddrinfo(ressave
);
3882 return SOAP_INVALID_SOCKET
;
3887 { res
= res
->ai_next
;
3888 soap
->fclosesocket(soap
, fd
);
3892 if (err
&& err
!= SOAP_EINTR
)
3893 { soap
->errnum
= err
;
3894 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not connect to host\n"));
3895 soap_set_sender_error(soap
, tcp_error(soap
), "connect failed in tcp_connect()", SOAP_TCP_ERROR
);
3896 soap
->fclosesocket(soap
, fd
);
3898 freeaddrinfo(ressave
);
3900 return SOAP_INVALID_SOCKET
;
3907 soap
->peerlen
= 0; /* IPv6: already connected so use send() */
3908 freeaddrinfo(ressave
);
3910 if (soap
->recv_timeout
|| soap
->send_timeout
)
3911 SOAP_SOCKNONBLOCK(fd
)
3915 soap
->imode
&= ~SOAP_ENC_SSL
;
3916 soap
->omode
&= ~SOAP_ENC_SSL
;
3917 if (!soap_tag_cmp(endpoint
, "https:*"))
3922 if (soap
->proxy_host
)
3923 { soap_mode m
= soap
->mode
; /* preserve settings */
3924 soap_mode om
= soap
->omode
; /* make sure we only parse HTTP */
3925 size_t n
= soap
->count
; /* save the content length */
3926 const char *userid
, *passwd
;
3927 soap
->omode
&= ~SOAP_ENC
; /* mask IO and ENC */
3928 soap
->omode
|= SOAP_IO_BUFFER
;
3929 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connecting to %s proxy server\n", soap
->proxy_http_version
));
3930 sprintf(soap
->tmpbuf
, "CONNECT %s:%d HTTP/%s", host
, port
, soap
->proxy_http_version
);
3931 if (soap_begin_send(soap
)
3932 || (soap
->error
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
3933 { soap
->fclosesocket(soap
, fd
);
3934 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3935 return SOAP_INVALID_SOCKET
;
3938 if (soap
->proxy_userid
&& soap
->proxy_passwd
&& strlen(soap
->proxy_userid
) + strlen(soap
->proxy_passwd
) < 761)
3939 { sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->proxy_userid
, soap
->proxy_passwd
);
3940 strcpy(soap
->tmpbuf
, "Basic ");
3941 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
3942 if ((soap
->error
= soap
->fposthdr(soap
, "Proxy-Authorization", soap
->tmpbuf
)))
3943 { soap
->fclosesocket(soap
, fd
);
3944 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3946 // Oracle customization
3947 // TODO: returning soap->error may also be a bug
3953 if ((soap
->error
= soap
->fposthdr(soap
, NULL
, NULL
))
3954 || soap_flush(soap
))
3955 { soap
->fclosesocket(soap
, fd
);
3956 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3957 return SOAP_INVALID_SOCKET
;
3961 soap
->imode
&= ~SOAP_ENC
; /* mask IO and ENC */
3962 userid
= soap
->userid
; /* preserve */
3963 passwd
= soap
->passwd
; /* preserve */
3964 if ((soap
->error
= soap
->fparse(soap
)))
3965 { soap
->fclosesocket(soap
, fd
);
3966 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3967 return SOAP_INVALID_SOCKET
;
3969 soap
->userid
= userid
; /* restore */
3970 soap
->passwd
= passwd
; /* restore */
3971 soap
->imode
= om
; /* restore */
3972 soap
->count
= n
; /* restore */
3973 if (soap_begin_send(soap
))
3974 { soap
->fclosesocket(soap
, fd
);
3975 return SOAP_INVALID_SOCKET
;
3978 strncpy(soap
->endpoint
, endpoint
, sizeof(soap
->endpoint
)-1); /* restore */
3981 if (!soap
->ctx
&& (soap
->error
= soap
->fsslauth(soap
)))
3982 { soap_set_sender_error(soap
, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR
);
3983 soap
->fclosesocket(soap
, fd
);
3984 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3985 return SOAP_INVALID_SOCKET
;
3988 { soap
->ssl
= SSL_new(soap
->ctx
);
3990 { soap
->fclosesocket(soap
, fd
);
3991 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
3992 soap
->error
= SOAP_SSL_ERROR
;
3993 return SOAP_INVALID_SOCKET
;
3997 SSL_clear(soap
->ssl
);
3999 { if (!strcmp(soap
->session_host
, host
) && soap
->session_port
== port
)
4000 SSL_set_session(soap
->ssl
, soap
->session
);
4001 SSL_SESSION_free(soap
->session
);
4002 soap
->session
= NULL
;
4004 soap
->imode
|= SOAP_ENC_SSL
;
4005 soap
->omode
|= SOAP_ENC_SSL
;
4006 bio
= BIO_new_socket((int)fd
, BIO_NOCLOSE
);
4007 SSL_set_bio(soap
->ssl
, bio
, bio
);
4010 /* Connect timeout: set SSL sockets to non-blocking */
4011 if (soap
->connect_timeout
)
4012 { SOAP_SOCKNONBLOCK(fd
)
4013 retries
= 10*soap
->connect_timeout
;
4019 // Oracle customization
4021 // Clear error queue of any errors remaining from a previous operation
4025 retries
= 100; /* SSL connect timeout: 10 sec retries, 100 x 0.1 sec */
4026 /* Try connecting until success or timeout (when nonblocking) */
4028 { if ((r
= SSL_connect(soap
->ssl
)) <= 0)
4029 { int err
= SSL_get_error(soap
->ssl
, r
);
4030 if (err
== SSL_ERROR_WANT_CONNECT
|| err
== SSL_ERROR_WANT_READ
|| err
== SSL_ERROR_WANT_WRITE
)
4032 if (err
== SSL_ERROR_WANT_READ
)
4033 s
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, -100000);
4035 s
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_SND
| SOAP_TCP_SELECT_ERR
, -100000);
4036 if (s
< 0 && soap
->errnum
!= SOAP_EINTR
)
4037 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL_connect/select error in tcp_connect\n"));
4038 soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4039 soap
->fclosesocket(soap
, fd
);
4040 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
4041 return SOAP_INVALID_SOCKET
;
4043 if (s
== 0 && retries
-- <= 0)
4044 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL connect timeout\n"));
4045 soap_set_sender_error(soap
, "Timeout", "SSL connect failed in tcp_connect()", SOAP_TCP_ERROR
);
4046 soap
->fclosesocket(soap
, fd
);
4047 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
4048 return SOAP_INVALID_SOCKET
;
4052 { soap_set_sender_error(soap
, soap_ssl_error(soap
, r
), "SSL_connect error in tcp_connect()", SOAP_SSL_ERROR
);
4053 soap
->fclosesocket(soap
, fd
);
4054 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
4055 return SOAP_INVALID_SOCKET
;
4058 } while (!SSL_is_init_finished(soap
->ssl
));
4059 /* Set SSL sockets to nonblocking */
4060 SOAP_SOCKNONBLOCK(fd
)
4061 /* Check server credentials when required */
4062 if ((soap
->ssl_flags
& SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION
))
4064 if ((err
= SSL_get_verify_result(soap
->ssl
)) != X509_V_OK
)
4065 { soap_set_sender_error(soap
, X509_verify_cert_error_string(err
), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR
);
4066 soap
->fclosesocket(soap
, fd
);
4067 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
4068 return SOAP_INVALID_SOCKET
;
4070 if (!(soap
->ssl_flags
& SOAP_SSL_SKIP_HOST_CHECK
))
4071 { /* Oracle customization: X509_NAME *subj; */
4075 peer
= SSL_get_peer_certificate(soap
->ssl
);
4077 { soap_set_sender_error(soap
, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR
);
4078 soap
->fclosesocket(soap
, fd
);
4079 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
4080 return SOAP_INVALID_SOCKET
;
4082 ext_count
= X509_get_ext_count(peer
);
4085 for (i
= 0; i
< ext_count
; i
++)
4086 { X509_EXTENSION
*ext
= X509_get_ext(peer
, i
);
4087 const char *ext_str
= OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext
)));
4088 if (ext_str
&& !strcmp(ext_str
, "subjectAltName"))
4089 { X509V3_EXT_METHOD
*meth
= (X509V3_EXT_METHOD
*)X509V3_EXT_get(ext
);
4091 #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
4092 const unsigned char *data
;
4094 unsigned char *data
;
4096 STACK_OF(CONF_VALUE
) *val
;
4100 data
= ext
->value
->data
;
4101 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4103 ext_data
= ASN1_item_d2i(NULL
, &data
, ext
->value
->length
, ASN1_ITEM_ptr(meth
->it
));
4105 { /* OpenSSL not perfectly portable at this point (?):
4106 Some compilers appear to prefer
4107 meth->d2i(NULL, (const unsigned char**)&data, ...
4109 meth->d2i(NULL, &data, ext->value->length);
4111 ext_data
= meth
->d2i(NULL
, &data
, ext
->value
->length
);
4114 ext_data
= meth
->d2i(NULL
, &data
, ext
->value
->length
);
4117 { val
= meth
->i2v(meth
, ext_data
, NULL
);
4119 { for (j
= 0; j
< sk_CONF_VALUE_num(val
); j
++)
4120 { CONF_VALUE
*nval
= sk_CONF_VALUE_value(val
, j
);
4121 if (nval
&& !strcmp(nval
->name
, "DNS") && !strcmp(nval
->value
, host
))
4126 sk_CONF_VALUE_pop_free(val
, X509V3_conf_free
);
4128 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4130 ASN1_item_free((ASN1_VALUE
*)ext_data
, ASN1_ITEM_ptr(meth
->it
));
4132 meth
->ext_free(ext_data
);
4134 meth
->ext_free(ext_data
);
4143 // Oracle customization
4145 // the certificate subject name is an entity name, not a DNS name
4148 if (!ok && (subj = X509_get_subject_name(peer)))
4151 { ASN1_STRING *name;
4152 i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
4155 name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
4157 { if (!soap_tag_cmp(host, (const char*)M_ASN1_STRING_data(name)))
4160 { unsigned char *tmp = NULL;
4161 ASN1_STRING_to_UTF8(&tmp, name);
4163 { if (!soap_tag_cmp(host, (const char*)tmp))
4175 { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
4176 soap->fclosesocket(soap, fd);
4177 return SOAP_INVALID_SOCKET;
4184 // Oracle customization for debug
4186 if ( SSL_session_reused( soap
->ssl
) == 1)
4188 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL session reused\n"));
4192 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "SSL session negotiated\n"));
4196 soap
->fclosesocket(soap
, fd
);
4197 soap
->socket
= SOAP_INVALID_SOCKET
; /* Oracle customization */
4198 soap
->error
= SOAP_SSL_ERROR
;
4199 return SOAP_INVALID_SOCKET
;
4207 /******************************************************************************/
4211 tcp_select(struct soap
*soap
, SOAP_SOCKET s
, int flags
, int timeout
)
4214 fd_set fd
[3], *rfd
, *sfd
, *efd
;
4217 /* if fd max set size exceeded, use poll() when available */
4218 #if defined(__QNX__) || defined(QNX) /* select() is not MT safe on some QNX */
4221 if ((int)s
>= (int)FD_SETSIZE
)
4224 { struct pollfd pollfd
;
4228 if (flags
& SOAP_TCP_SELECT_RCV
)
4229 pollfd
.events
|= POLLIN
;
4230 if (flags
& SOAP_TCP_SELECT_SND
)
4231 pollfd
.events
|= POLLOUT
;
4232 if (flags
& SOAP_TCP_SELECT_ERR
)
4233 pollfd
.events
|= POLLERR
;
4235 timeout
/= -1000; /* -usec -> ms */
4236 else if (timeout
<= 1000000) /* avoid overflow */
4237 timeout
*= 1000; /* sec -> ms */
4239 { retries
= timeout
/ 1000000;
4240 timeout
= 1000000000;
4242 do r
= poll(&pollfd
, 1, timeout
);
4243 while (r
== 0 && retries
--);
4246 if ((flags
& SOAP_TCP_SELECT_RCV
) && (pollfd
.revents
& POLLIN
))
4247 r
|= SOAP_TCP_SELECT_RCV
;
4248 if ((flags
& SOAP_TCP_SELECT_SND
) && (pollfd
.revents
& POLLOUT
))
4249 r
|= SOAP_TCP_SELECT_SND
;
4250 if ((flags
& SOAP_TCP_SELECT_ERR
) && (pollfd
.revents
& POLLERR
))
4251 r
|= SOAP_TCP_SELECT_ERR
;
4254 soap
->errnum
= soap_socket_errno(s
);
4258 { soap
->error
= SOAP_FD_EXCEEDED
;
4263 rfd
= sfd
= efd
= NULL
;
4264 if (flags
& SOAP_TCP_SELECT_RCV
)
4269 if (flags
& SOAP_TCP_SELECT_SND
)
4274 if (flags
& SOAP_TCP_SELECT_ERR
)
4280 { tv
.tv_sec
= timeout
;
4284 { tv
.tv_sec
= -timeout
/ 1000000;
4285 tv
.tv_usec
= -timeout
% 1000000;
4287 r
= select((int)s
+ 1, rfd
, sfd
, efd
, &tv
);
4290 if ((flags
& SOAP_TCP_SELECT_RCV
) && FD_ISSET(s
, rfd
))
4291 r
|= SOAP_TCP_SELECT_RCV
;
4292 if ((flags
& SOAP_TCP_SELECT_SND
) && FD_ISSET(s
, sfd
))
4293 r
|= SOAP_TCP_SELECT_SND
;
4294 if ((flags
& SOAP_TCP_SELECT_ERR
) && FD_ISSET(s
, efd
))
4295 r
|= SOAP_TCP_SELECT_ERR
;
4298 soap
->errnum
= soap_socket_errno(s
);
4304 /******************************************************************************/
4308 tcp_accept(struct soap
*soap
, SOAP_SOCKET s
, struct sockaddr
*a
, int *n
)
4310 fd
= accept(s
, a
, (SOAP_SOCKLEN_T
*)n
); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4311 #ifdef SOCKET_CLOSE_ON_EXEC
4314 SetHandleInformation((HANDLE
)fd
, HANDLE_FLAG_INHERIT
, 0);
4317 fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
4325 /******************************************************************************/
4329 tcp_disconnect(struct soap
*soap
)
4335 { SSL_SESSION_free(soap
->session
);
4336 soap
->session
= NULL
;
4339 { soap
->session
= SSL_get1_session(soap
->ssl
);
4341 { strcpy(soap
->session_host
, soap
->host
);
4342 soap
->session_port
= soap
->port
;
4345 r
= SSL_shutdown(soap
->ssl
);
4346 /* SSL shutdown does not work when reads are pending */
4347 while (SSL_want_read(soap
->ssl
))
4348 { SSL_read(soap
->ssl
, NULL
, 0);
4349 if (soap_socket_errno(soap
->socket
) != SOAP_EAGAIN
)
4350 { r
= SSL_shutdown(soap
->ssl
);
4355 { if (soap_valid_socket(soap
->socket
))
4356 { if (!soap
->fshutdownsocket(soap
, soap
->socket
, 1))
4360 wait up to 10 seconds for close_notify to be sent by peer (if peer not
4361 present, this avoids calling SSL_shutdown() which has a lengthy return
4364 r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_ERR
, 10);
4365 if (r
<= 0 && soap
->errnum
!= SOAP_EINTR
)
4367 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Connection lost...\n"));
4368 soap
->fclosesocket(soap
, soap
->socket
);
4369 soap
->socket
= SOAP_INVALID_SOCKET
;
4370 ERR_remove_state(0);
4374 r
= SSL_shutdown(soap
->ssl
);
4380 { s
= ERR_get_error();
4382 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Shutdown failed: %d\n", SSL_get_error(soap
->ssl
, r
)));
4383 if (soap_valid_socket(soap
->socket
) && !(soap
->omode
& SOAP_IO_UDP
))
4384 { soap
->fclosesocket(soap
, soap
->socket
);
4385 soap
->socket
= SOAP_INVALID_SOCKET
;
4389 SSL_free(soap
->ssl
);
4392 return SOAP_SSL_ERROR
;
4393 ERR_remove_state(0);
4396 if (soap_valid_socket(soap
->socket
) && !(soap
->omode
& SOAP_IO_UDP
))
4397 { soap
->fshutdownsocket(soap
, soap
->socket
, 2);
4398 soap
->fclosesocket(soap
, soap
->socket
);
4399 soap
->socket
= SOAP_INVALID_SOCKET
;
4406 /******************************************************************************/
4410 tcp_closesocket(struct soap
*soap
, SOAP_SOCKET fd
)
4411 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Close socket %d\n", (int)fd
));
4412 return soap_closesocket(fd
);
4417 /******************************************************************************/
4421 tcp_shutdownsocket(struct soap
*soap
, SOAP_SOCKET fd
, int how
)
4422 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Shutdown socket %d how=%d\n", (int)fd
, how
));
4423 return shutdown(fd
, how
);
4428 /******************************************************************************/
4434 soap_bind(struct soap
*soap
, const char *host
, int port
, int backlog
)
4437 struct addrinfo
*addrinfo
= NULL
;
4438 struct addrinfo hints
;
4439 struct addrinfo res
;
4446 int level
= IPPROTO_IPV6
;
4451 int len
= SOAP_BUFLEN
;
4454 if (soap_valid_socket(soap
->master
))
4455 { soap
->fclosesocket(soap
, soap
->master
);
4456 soap
->master
= SOAP_INVALID_SOCKET
;
4458 soap
->socket
= SOAP_INVALID_SOCKET
;
4461 { soap_set_receiver_error(soap
, tcp_error(soap
), "TCP init failed in soap_bind()", SOAP_TCP_ERROR
);
4462 return SOAP_INVALID_SOCKET
;
4465 memset((void*)&hints
, 0, sizeof(hints
));
4466 hints
.ai_family
= PF_UNSPEC
;
4468 if ((soap
->omode
& SOAP_IO_UDP
))
4469 hints
.ai_socktype
= SOCK_DGRAM
;
4472 hints
.ai_socktype
= SOCK_STREAM
;
4473 hints
.ai_flags
= AI_PASSIVE
;
4475 /* Oracle customization: check err before using addrinfo */
4476 err
= getaddrinfo(host
, soap_int2s(soap
, port
), &hints
, &addrinfo
);
4477 if (err
|| !addrinfo
)
4478 { soap_set_receiver_error(soap
, SOAP_GAI_STRERROR(err
), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR
);
4481 freeaddrinfo(addrinfo
);
4483 return SOAP_INVALID_SOCKET
;
4486 memcpy(&soap
->peer
, addrinfo
->ai_addr
, addrinfo
->ai_addrlen
);
4487 soap
->peerlen
= addrinfo
->ai_addrlen
;
4488 res
.ai_addr
= (struct sockaddr
*)&soap
->peer
;
4489 res
.ai_addrlen
= soap
->peerlen
;
4490 freeaddrinfo(addrinfo
);
4491 soap
->master
= (int)socket(res
.ai_family
, res
.ai_socktype
, res
.ai_protocol
);
4494 if ((soap
->omode
& SOAP_IO_UDP
))
4495 soap
->master
= (int)socket(AF_INET
, SOCK_DGRAM
, 0);
4498 soap
->master
= (int)socket(AF_INET
, SOCK_STREAM
, 0);
4501 if (!soap_valid_socket(soap
->master
))
4502 { soap
->errnum
= soap_socket_errno(soap
->master
);
4503 soap_set_receiver_error(soap
, tcp_error(soap
), "socket failed in soap_bind()", SOAP_TCP_ERROR
);
4504 return SOAP_INVALID_SOCKET
;
4507 if ((soap
->omode
& SOAP_IO_UDP
))
4508 soap
->socket
= soap
->master
;
4510 #ifdef SOCKET_CLOSE_ON_EXEC
4513 SetHandleInformation((HANDLE
)soap
->master
, HANDLE_FLAG_INHERIT
, 0);
4516 fcntl(soap
->master
, F_SETFD
, 1);
4520 if (soap
->bind_flags
&& setsockopt(soap
->master
, SOL_SOCKET
, soap
->bind_flags
, (char*)&set
, sizeof(int)))
4521 { soap
->errnum
= soap_socket_errno(soap
->master
);
4522 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR
);
4523 return SOAP_INVALID_SOCKET
;
4525 if (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) && setsockopt(soap
->master
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
4526 { soap
->errnum
= soap_socket_errno(soap
->master
);
4527 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR
);
4528 return SOAP_INVALID_SOCKET
;
4530 if (setsockopt(soap
->master
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
4531 { soap
->errnum
= soap_socket_errno(soap
->master
);
4532 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR
);
4533 return SOAP_INVALID_SOCKET
;
4535 if (setsockopt(soap
->master
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
4536 { soap
->errnum
= soap_socket_errno(soap
->master
);
4537 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR
);
4538 return SOAP_INVALID_SOCKET
;
4541 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(soap
->master
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
4542 { soap
->errnum
= soap_socket_errno(soap
->master
);
4543 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR
);
4544 return SOAP_INVALID_SOCKET
;
4550 if (setsockopt(soap
->master
, level
, IPV6_V6ONLY
, (char*)&unset
, sizeof(int)))
4551 { soap
->errnum
= soap_socket_errno(soap
->master
);
4552 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt IPV6_V6ONLY failed in soap_bind()", SOAP_TCP_ERROR
);
4553 return SOAP_INVALID_SOCKET
;
4557 if (bind(soap
->master
, res
.ai_addr
, (int)res
.ai_addrlen
))
4558 { soap
->errnum
= soap_socket_errno(soap
->master
);
4559 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4560 soap_closesock(soap
);
4561 soap_set_receiver_error(soap
, tcp_error(soap
), "bind failed in soap_bind()", SOAP_TCP_ERROR
);
4562 return SOAP_INVALID_SOCKET
;
4565 soap
->peerlen
= sizeof(soap
->peer
);
4566 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
4567 soap
->peer
.sin_family
= AF_INET
;
4570 { if (soap
->fresolve(soap
, host
, &soap
->peer
.sin_addr
))
4571 { soap_set_receiver_error(soap
, tcp_error(soap
), "get host by name failed in soap_bind()", SOAP_TCP_ERROR
);
4572 return SOAP_INVALID_SOCKET
;
4576 soap
->peer
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
4577 soap
->peer
.sin_port
= htons((short)port
);
4579 if (bind(soap
->master
, (struct sockaddr
*)&soap
->peer
, (int)soap
->peerlen
))
4580 { soap
->errnum
= soap_socket_errno(soap
->master
);
4581 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4582 soap_closesock(soap
);
4583 soap_set_receiver_error(soap
, tcp_error(soap
), "bind failed in soap_bind()", SOAP_TCP_ERROR
);
4584 return SOAP_INVALID_SOCKET
;
4587 if (!(soap
->omode
& SOAP_IO_UDP
) && listen(soap
->master
, backlog
))
4588 { soap
->errnum
= soap_socket_errno(soap
->master
);
4589 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not bind to host\n"));
4590 soap_closesock(soap
);
4591 soap_set_receiver_error(soap
, tcp_error(soap
), "listen failed in soap_bind()", SOAP_TCP_ERROR
);
4592 return SOAP_INVALID_SOCKET
;
4594 return soap
->master
;
4599 /******************************************************************************/
4605 soap_poll(struct soap
*soap
)
4609 if (soap_valid_socket(soap
->socket
))
4610 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_ALL
, 0);
4611 if (r
> 0 && (r
& SOAP_TCP_SELECT_ERR
))
4614 else if (soap_valid_socket(soap
->master
))
4615 r
= tcp_select(soap
, soap
->master
, SOAP_TCP_SELECT_SND
, 0);
4621 if (soap
->imode
& SOAP_ENC_SSL
)
4623 if (soap_valid_socket(soap
->socket
)
4624 && (r
& SOAP_TCP_SELECT_SND
)
4625 && (!(r
& SOAP_TCP_SELECT_RCV
)
4626 || SSL_peek(soap
->ssl
, soap
->tmpbuf
, 1) > 0))
4631 if (soap_valid_socket(soap
->socket
)
4632 && (r
& SOAP_TCP_SELECT_SND
)
4633 && (!(r
& SOAP_TCP_SELECT_RCV
)
4634 || recv(soap
->socket
, soap
->tmpbuf
, 1, MSG_PEEK
) > 0))
4638 { if ((soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) && soap_socket_errno(soap
->master
) != SOAP_EINTR
)
4639 { soap_set_receiver_error(soap
, tcp_error(soap
), "select failed in soap_poll()", SOAP_TCP_ERROR
);
4640 return soap
->error
= SOAP_TCP_ERROR
;
4643 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Polling: other end down on socket=%d select=%d\n", soap
->socket
, r
));
4652 /******************************************************************************/
4658 soap_accept(struct soap
*soap
)
4659 { int n
= (int)sizeof(soap
->peer
);
4661 int len
= SOAP_BUFLEN
;
4664 soap
->error
= SOAP_OK
;
4666 if ((soap
->omode
& SOAP_IO_UDP
))
4667 return soap
->socket
= soap
->master
;
4669 memset((void*)&soap
->peer
, 0, sizeof(soap
->peer
));
4670 soap
->socket
= SOAP_INVALID_SOCKET
;
4672 soap
->keep_alive
= 0;
4673 if (soap_valid_socket(soap
->master
))
4676 { if (soap
->accept_timeout
|| soap
->send_timeout
|| soap
->recv_timeout
)
4679 r
= tcp_select(soap
, soap
->master
, SOAP_TCP_SELECT_ALL
, soap
->accept_timeout
? soap
->accept_timeout
: 60);
4682 if (!r
&& soap
->accept_timeout
)
4683 { soap_set_receiver_error(soap
, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR
);
4684 return SOAP_INVALID_SOCKET
;
4688 if (r
!= SOAP_EINTR
)
4689 { soap_closesock(soap
);
4690 soap_set_sender_error(soap
, tcp_error(soap
), "accept failed in soap_accept()", SOAP_TCP_ERROR
);
4691 return SOAP_INVALID_SOCKET
;
4696 if (soap
->accept_timeout
|| soap
->send_timeout
|| soap
->recv_timeout
)
4697 SOAP_SOCKNONBLOCK(soap
->master
)
4699 SOAP_SOCKBLOCK(soap
->master
)
4700 soap
->socket
= soap
->faccept(soap
, soap
->master
, (struct sockaddr
*)&soap
->peer
, &n
);
4701 soap
->peerlen
= (size_t)n
;
4702 if (soap_valid_socket(soap
->socket
))
4705 /* Use soap->host to store the numeric form of the remote host */
4706 getnameinfo((struct sockaddr
*)&soap
->peer
, n
, soap
->host
, sizeof(soap
->host
), NULL
, 0, NI_NUMERICHOST
| NI_NUMERICSERV
);
4707 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Accept socket %d from %s\n", soap
->socket
, soap
->host
));
4709 // Oracle customization
4711 // bug fix: save off the remote host
4712 strcpy(soap
->session_host
, soap
->host
);
4713 soap
->ip
= 0; /* info stored in soap->peer and soap->host */
4714 soap
->port
= 0; /* info stored in soap->peer and soap->host */
4716 soap
->ip
= ntohl(soap
->peer
.sin_addr
.s_addr
);
4717 soap
->port
= (int)ntohs(soap
->peer
.sin_port
); /* does not return port number on some systems */
4718 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));
4721 if (soap
->accept_flags
== SO_LINGER
)
4722 { struct linger linger
;
4723 memset((void*)&linger
, 0, sizeof(linger
));
4725 linger
.l_linger
= soap
->linger_time
;
4726 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_LINGER
, (char*)&linger
, sizeof(struct linger
)))
4727 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4728 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR
);
4729 soap_closesock(soap
);
4730 return SOAP_INVALID_SOCKET
;
4733 else if (soap
->accept_flags
&& setsockopt(soap
->socket
, SOL_SOCKET
, soap
->accept_flags
, (char*)&set
, sizeof(int)))
4734 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4735 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR
);
4736 soap_closesock(soap
);
4737 return SOAP_INVALID_SOCKET
;
4739 if (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) && setsockopt(soap
->socket
, SOL_SOCKET
, SO_KEEPALIVE
, (char*)&set
, sizeof(int)))
4740 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4741 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR
);
4742 soap_closesock(soap
);
4743 return SOAP_INVALID_SOCKET
;
4745 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_SNDBUF
, (char*)&len
, sizeof(int)))
4746 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4747 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR
);
4748 soap_closesock(soap
);
4749 return SOAP_INVALID_SOCKET
;
4751 if (setsockopt(soap
->socket
, SOL_SOCKET
, SO_RCVBUF
, (char*)&len
, sizeof(int)))
4752 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4753 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR
);
4754 soap_closesock(soap
);
4755 return SOAP_INVALID_SOCKET
;
4758 if (!(soap
->omode
& SOAP_IO_UDP
) && setsockopt(soap
->socket
, IPPROTO_TCP
, TCP_NODELAY
, (char*)&set
, sizeof(int)))
4759 { soap
->errnum
= soap_socket_errno(soap
->socket
);
4760 soap_set_receiver_error(soap
, tcp_error(soap
), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR
);
4761 soap_closesock(soap
);
4762 return SOAP_INVALID_SOCKET
;
4766 soap
->keep_alive
= (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) != 0);
4767 return soap
->socket
;
4769 err
= soap_socket_errno(soap
->socket
);
4770 if (err
!= 0 && err
!= SOAP_EINTR
&& err
!= SOAP_EAGAIN
&& err
!= SOAP_EWOULDBLOCK
)
4771 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Accept failed from %s\n", soap
->host
));
4773 soap_set_receiver_error(soap
, tcp_error(soap
), "accept failed in soap_accept()", SOAP_TCP_ERROR
);
4774 soap_closesock(soap
);
4775 return SOAP_INVALID_SOCKET
;
4781 soap_set_receiver_error(soap
, tcp_error(soap
), "no master socket in soap_accept()", SOAP_TCP_ERROR
);
4782 return SOAP_INVALID_SOCKET
;
4788 /******************************************************************************/
4793 soap_closesock(struct soap
*soap
)
4794 { register int status
= soap
->error
;
4796 soap
->mime
.first
= NULL
;
4797 soap
->mime
.last
= NULL
;
4798 soap
->dime
.first
= NULL
;
4799 soap
->dime
.last
= NULL
;
4801 if (soap
->fdisconnect
&& (soap
->error
= soap
->fdisconnect(soap
)))
4803 if (status
== SOAP_EOF
|| status
== SOAP_TCP_ERROR
|| status
== SOAP_SSL_ERROR
|| !soap
->keep_alive
)
4804 { if (soap
->fclose
&& (soap
->error
= soap
->fclose(soap
)))
4806 soap
->keep_alive
= 0;
4809 if (soap
->zlib_state
== SOAP_ZLIB_DEFLATE
)
4810 deflateEnd(soap
->d_stream
);
4811 else if (soap
->zlib_state
== SOAP_ZLIB_INFLATE
)
4812 inflateEnd(soap
->d_stream
);
4813 soap
->zlib_state
= SOAP_ZLIB_NONE
;
4815 return soap
->error
= status
;
4819 /******************************************************************************/
4825 soap_cleanup(struct soap
*soap
)
4837 /******************************************************************************/
4842 soap_done(struct soap
*soap
)
4847 if (soap_check_state(soap
))
4849 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Done with context\n"));
4850 soap_free_temp(soap
);
4852 { struct soap_clist
*p
= soap
->clist
->next
;
4853 SOAP_FREE(soap
, soap
->clist
);
4856 if (soap
->state
== SOAP_INIT
)
4857 soap
->omode
&= ~SOAP_IO_UDP
; /* to force close the socket */
4858 soap
->keep_alive
= 0; /* to force close the socket */
4859 soap_closesock(soap
);
4861 soap_free_cookies(soap
);
4863 while (soap
->plugins
)
4864 { register struct soap_plugin
*p
= soap
->plugins
->next
;
4865 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Removing plugin '%s'\n", soap
->plugins
->id
));
4866 if (soap
->plugins
->fcopy
|| soap
->state
== SOAP_INIT
)
4867 soap
->plugins
->fdelete(soap
, soap
->plugins
);
4868 SOAP_FREE(soap
, soap
->plugins
);
4871 soap
->fplugin
= fplugin
;
4872 soap
->fmalloc
= NULL
;
4874 soap
->fpost
= http_post
;
4875 soap
->fget
= http_get
;
4876 soap
->fput
= http_405
;
4877 soap
->fdel
= http_405
;
4878 soap
->fhead
= http_405
;
4880 soap
->fposthdr
= http_post_header
;
4881 soap
->fresponse
= http_response
;
4882 soap
->fparse
= http_parse
;
4883 soap
->fparsehdr
= http_parse_header
;
4885 soap
->fheader
= NULL
;
4888 soap
->fresolve
= tcp_gethost
;
4890 soap
->fresolve
= NULL
;
4892 soap
->faccept
= tcp_accept
;
4893 soap
->fopen
= tcp_connect
;
4894 soap
->fclose
= tcp_disconnect
;
4895 soap
->fclosesocket
= tcp_closesocket
;
4896 soap
->fshutdownsocket
= tcp_shutdownsocket
;
4897 soap
->fsend
= fsend
;
4898 soap
->frecv
= frecv
;
4899 soap
->fpoll
= soap_poll
;
4902 soap
->fclose
= NULL
;
4906 soap
->fprepareinitsend
= NULL
;
4907 soap
->fprepareinitrecv
= NULL
;
4908 soap
->fpreparesend
= NULL
;
4909 soap
->fpreparerecv
= NULL
;
4910 soap
->fpreparefinalsend
= NULL
;
4911 soap
->fpreparefinalrecv
= NULL
;
4913 soap
->fseterror
= NULL
;
4914 soap
->fignore
= NULL
;
4915 soap
->fserveloop
= NULL
;
4918 { SSL_SESSION_free(soap
->session
);
4919 soap
->session
= NULL
;
4922 if (soap
->state
== SOAP_INIT
)
4923 { if (soap_valid_socket(soap
->master
))
4924 { soap
->fclosesocket(soap
, soap
->master
);
4925 soap
->master
= SOAP_INVALID_SOCKET
;
4930 { SSL_free(soap
->ssl
);
4933 if (soap
->state
== SOAP_INIT
)
4935 { SSL_CTX_free(soap
->ctx
);
4941 ERR_remove_state(0);
4943 #ifdef WITH_C_LOCALE
4944 freelocale(soap
->c_locale
);
4948 { SOAP_FREE(soap
, (void*)soap
->d_stream
);
4949 soap
->d_stream
= NULL
;
4952 { SOAP_FREE(soap
, (void*)soap
->z_buf
);
4957 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free logfiles\n"));
4958 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
4959 { if (soap
->logfile
[i
])
4960 { SOAP_FREE(soap
, (void*)soap
->logfile
[i
]);
4961 soap
->logfile
[i
] = NULL
;
4963 soap_close_logfile(soap
, i
);
4965 soap
->state
= SOAP_NONE
;
4967 #ifdef SOAP_MEM_DEBUG
4968 soap_free_mht(soap
);
4973 /******************************************************************************\
4977 \******************************************************************************/
4979 /******************************************************************************/
4983 http_parse(struct soap
*soap
)
4984 { char header
[SOAP_HDRLEN
], *s
;
4985 unsigned short httpcmd
= 0, status
= 0;
4986 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Waiting for HTTP request/response...\n"));
4987 *soap
->endpoint
= '\0';
4989 soap
->userid
= NULL
;
4990 soap
->passwd
= NULL
;
4991 soap
->action
= NULL
;
4992 soap
->authrealm
= NULL
;
4993 soap
->proxy_from
= NULL
;
4994 soap
->http_content
= NULL
;
4997 { if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
4998 { if (soap
->error
== SOAP_EOF
)
5000 return soap
->error
= 414;
5002 if ((s
= strchr(soap
->msgbuf
, ' ')))
5003 { soap
->status
= (unsigned short)soap_strtoul(s
, &s
, 10);
5004 if (!soap_blank(*s
))
5009 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP status: %s\n", soap
->msgbuf
));
5011 { if (soap_getline(soap
, header
, SOAP_HDRLEN
))
5012 { if (soap
->error
== SOAP_EOF
)
5013 { soap
->error
= SOAP_OK
;
5014 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "EOF in HTTP header, continue anyway\n"));
5021 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP header: %s\n", header
));
5022 s
= strchr(header
, ':');
5027 while (*s
&& *s
<= 32);
5030 t
= s
+ strlen(s
) - 1;
5031 while (t
> s
&& *t
<= 32)
5033 if (t
>= s
&& *t
== '"')
5036 if ((soap
->error
= soap
->fparsehdr(soap
, header
, s
)))
5037 { if (soap
->error
< SOAP_STOP
)
5039 status
= soap
->error
;
5040 soap
->error
= SOAP_OK
;
5044 } while (soap
->status
== 100);
5045 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Finished HTTP header parsing, status = %d\n", soap
->status
));
5046 s
= strstr(soap
->msgbuf
, "HTTP/");
5047 if (s
&& s
[7] != '1')
5048 { if (soap
->keep_alive
== 1)
5049 soap
->keep_alive
= 0;
5050 if (soap
->status
== 0 && (soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
) /* soap->status == 0 for HTTP request */
5051 { soap
->imode
|= SOAP_IO_CHUNK
;
5052 soap
->omode
= (soap
->omode
& ~SOAP_IO
) | SOAP_IO_STORE
;
5055 if (soap
->keep_alive
< 0)
5056 soap
->keep_alive
= 1;
5057 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Keep alive connection = %d\n", soap
->keep_alive
));
5058 if (soap
->status
== 0)
5061 { if (!strncmp(soap
->msgbuf
, "POST ", l
= 5))
5063 else if (!strncmp(soap
->msgbuf
, "GET ", l
= 4))
5065 else if (!strncmp(soap
->msgbuf
, "PUT ", l
= 4))
5067 else if (!strncmp(soap
->msgbuf
, "DELETE ", l
= 7))
5069 else if (!strncmp(soap
->msgbuf
, "HEAD ", l
= 5))
5073 { size_t m
= strlen(soap
->endpoint
);
5074 size_t n
= m
+ (s
- soap
->msgbuf
) - l
- 1;
5077 if (n
>= sizeof(soap
->endpoint
))
5078 n
= sizeof(soap
->endpoint
) - 1;
5079 strncpy(soap
->path
, soap
->msgbuf
+ l
, n
- m
);
5080 soap
->path
[n
- m
] = '\0';
5081 strcat(soap
->endpoint
, soap
->path
);
5082 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Target endpoint='%s'\n", soap
->endpoint
));
5085 { case 2: soap
->error
= soap
->fget(soap
); break;
5086 case 3: soap
->error
= soap
->fput(soap
); break;
5087 case 4: soap
->error
= soap
->fdel(soap
); break;
5088 case 5: soap
->error
= soap
->fhead(soap
); break;
5089 default: soap
->error
= 405; break;
5091 if (soap
->error
== SOAP_OK
)
5092 soap
->error
= SOAP_STOP
; /* prevents further processing */
5096 return soap
->error
= status
;
5099 return soap
->error
= status
;
5101 return soap
->error
= 405;
5103 /* Status OK (HTTP 200) */
5104 if (soap
->status
== 0 || soap
->status
== 200)
5106 /* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors
5107 may not have a body. When content length, content type, or chunking is
5108 used assume there is a message to parse, either XML or HTTP.
5109 This version allows parsing of content when length=0:
5110 if (soap->length > 0 || soap->http_content || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
5112 if (soap
->length
> 0 || (soap
->imode
& SOAP_IO
) == SOAP_IO_CHUNK
)
5113 { if (((soap
->status
> 200 && soap
->status
<= 299) || soap
->status
== 400 || soap
->status
== 500))
5115 /* force close afterwards in soap_closesock() */
5116 soap
->keep_alive
= 0;
5117 /* read HTTP body for error details */
5118 s
= soap_get_http_body(soap
);
5120 return soap_set_receiver_error(soap
, soap
->msgbuf
, s
, soap
->status
);
5122 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "HTTP error %d\n", soap
->status
));
5123 return soap_set_receiver_error(soap
, "HTTP Error", soap
->msgbuf
, soap
->status
);
5128 /******************************************************************************/
5132 http_parse_header(struct soap
*soap
, const char *key
, const char *val
)
5133 { if (!soap_tag_cmp(key
, "Host"))
5136 if (soap
->imode
& SOAP_ENC_SSL
)
5137 strcpy(soap
->endpoint
, "https://");
5140 strcpy(soap
->endpoint
, "http://");
5141 strncat(soap
->endpoint
, val
, sizeof(soap
->endpoint
) - 8);
5142 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
5145 else if (!soap_tag_cmp(key
, "Content-Type"))
5146 { const char *action
;
5147 soap
->http_content
= soap_strdup(soap
, val
);
5148 if (soap_get_header_attribute(soap
, val
, "application/dime"))
5149 soap
->imode
|= SOAP_ENC_DIME
;
5150 else if (soap_get_header_attribute(soap
, val
, "multipart/related")
5151 || soap_get_header_attribute(soap
, val
, "multipart/form-data"))
5152 { soap
->mime
.boundary
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "boundary"));
5153 soap
->mime
.start
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "start"));
5154 soap
->imode
|= SOAP_ENC_MIME
;
5156 action
= soap_get_header_attribute(soap
, val
, "action");
5158 { if (*action
== '"')
5159 { soap
->action
= soap_strdup(soap
, action
+ 1);
5160 soap
->action
[strlen(soap
->action
) - 1] = '\0';
5163 soap
->action
= soap_strdup(soap
, action
);
5167 else if (!soap_tag_cmp(key
, "Content-Length"))
5168 { soap
->length
= soap_strtoul(val
, NULL
, 10);
5170 else if (!soap_tag_cmp(key
, "Content-Encoding"))
5171 { if (!soap_tag_cmp(val
, "deflate"))
5173 soap
->zlib_in
= SOAP_ZLIB_DEFLATE
;
5175 return SOAP_ZLIB_ERROR
;
5177 else if (!soap_tag_cmp(val
, "gzip"))
5179 soap
->zlib_in
= SOAP_ZLIB_GZIP
;
5181 return SOAP_ZLIB_ERROR
;
5185 else if (!soap_tag_cmp(key
, "Accept-Encoding"))
5188 if (strchr(val
, '*') || soap_get_header_attribute(soap
, val
, "gzip"))
5189 soap
->zlib_out
= SOAP_ZLIB_GZIP
;
5192 if (strchr(val
, '*') || soap_get_header_attribute(soap
, val
, "deflate"))
5193 soap
->zlib_out
= SOAP_ZLIB_DEFLATE
;
5195 soap
->zlib_out
= SOAP_ZLIB_NONE
;
5198 else if (!soap_tag_cmp(key
, "Transfer-Encoding"))
5199 { soap
->imode
&= ~SOAP_IO
;
5200 if (!soap_tag_cmp(val
, "chunked"))
5201 soap
->imode
|= SOAP_IO_CHUNK
;
5203 else if (!soap_tag_cmp(key
, "Connection"))
5204 { if (!soap_tag_cmp(val
, "keep-alive"))
5205 soap
->keep_alive
= -soap
->keep_alive
;
5206 else if (!soap_tag_cmp(val
, "close"))
5207 soap
->keep_alive
= 0;
5210 else if (!soap_tag_cmp(key
, "Authorization"))
5211 { if (!soap_tag_cmp(val
, "Basic *"))
5214 soap_base642s(soap
, val
+ 6, soap
->tmpbuf
, sizeof(soap
->tmpbuf
) - 1, &n
);
5215 soap
->tmpbuf
[n
] = '\0';
5216 if ((s
= strchr(soap
->tmpbuf
, ':')))
5218 soap
->userid
= soap_strdup(soap
, soap
->tmpbuf
);
5219 soap
->passwd
= soap_strdup(soap
, s
+ 1);
5223 else if (!soap_tag_cmp(key
, "WWW-Authenticate"))
5224 { soap
->authrealm
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
+ 6, "realm"));
5226 else if (!soap_tag_cmp(key
, "Expect"))
5227 { if (!soap_tag_cmp(val
, "100-continue"))
5228 { if ((soap
->error
= soap
->fposthdr(soap
, "HTTP/1.1 100 Continue", NULL
))
5229 || (soap
->error
= soap
->fposthdr(soap
, NULL
, NULL
)))
5234 else if (!soap_tag_cmp(key
, "SOAPAction"))
5236 { soap
->action
= soap_strdup(soap
, val
+ 1);
5237 soap
->action
[strlen(soap
->action
) - 1] = '\0';
5240 soap
->action
= soap_strdup(soap
, val
);
5242 else if (!soap_tag_cmp(key
, "Location"))
5243 { strncpy(soap
->endpoint
, val
, sizeof(soap
->endpoint
));
5244 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
5246 else if (!soap_tag_cmp(key
, "X-Forwarded-For"))
5247 { soap
->proxy_from
= soap_strdup(soap
, val
);
5250 else if (!soap_tag_cmp(key
, "Cookie")
5251 || !soap_tag_cmp(key
, "Cookie2")
5252 || !soap_tag_cmp(key
, "Set-Cookie")
5253 || !soap_tag_cmp(key
, "Set-Cookie2"))
5254 { soap_getcookies(soap
, val
);
5262 /******************************************************************************/
5263 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5268 soap_get_header_attribute(struct soap
*soap
, const char *line
, const char *key
)
5269 { register const char *s
= line
;
5272 { register short flag
;
5273 s
= soap_decode_key(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
);
5274 flag
= soap_tag_cmp(soap
->tmpbuf
, key
);
5275 s
= soap_decode_val(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
);
5277 return soap
->tmpbuf
;
5285 /******************************************************************************/
5286 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5291 soap_decode_key(char *buf
, size_t len
, const char *val
)
5292 { return soap_decode(buf
, len
, val
, "=,;");
5297 /******************************************************************************/
5298 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5303 soap_decode_val(char *buf
, size_t len
, const char *val
)
5308 return soap_decode(buf
, len
, val
+ 1, ",;");
5313 /******************************************************************************/
5314 #if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
5317 soap_decode(char *buf
, size_t len
, const char *val
, const char *sep
)
5320 for (s
= val
; *s
; s
++)
5321 if (*s
!= ' ' && *s
!= '\t' && !strchr(sep
, *s
))
5325 while (*s
&& *s
!= '"' && --len
)
5329 { while (*s
&& !soap_blank(*s
) && !strchr(sep
, *s
) && --len
)
5331 { *t
++ = ((s
[1] >= 'A' ? (s
[1] & 0x7) + 9 : s
[1] - '0') << 4)
5332 + (s
[2] >= 'A' ? (s
[2] & 0x7) + 9 : s
[2] - '0');
5340 while (*s
&& !strchr(sep
, *s
))
5347 /******************************************************************************/
5351 http_error(struct soap
*soap
, int status
)
5352 { register const char *msg
= SOAP_STR_EOS
;
5354 msg
= soap_code_str(h_http_error_codes
, status
);
5363 /******************************************************************************/
5367 http_get(struct soap
*soap
)
5368 { return SOAP_GET_METHOD
;
5373 /******************************************************************************/
5377 http_405(struct soap
*soap
)
5383 /******************************************************************************/
5387 http_post(struct soap
*soap
, const char *endpoint
, const char *host
, int port
, const char *path
, const char *action
, size_t count
)
5388 { register const char *s
;
5390 if (soap
->status
== SOAP_GET
)
5395 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))
5397 if (!endpoint
|| (soap_tag_cmp(endpoint
, "http:*") && soap_tag_cmp(endpoint
, "https:*") && strncmp(endpoint
, "httpg:", 6)))
5400 if (strlen(endpoint
) + strlen(soap
->http_version
) > sizeof(soap
->tmpbuf
) - 80)
5401 return soap
->error
= SOAP_EOM
;
5402 if (soap
->proxy_host
&& soap_tag_cmp(endpoint
, "https:*"))
5403 sprintf(soap
->tmpbuf
, "%s %s HTTP/%s", s
, endpoint
, soap
->http_version
);
5405 sprintf(soap
->tmpbuf
, "%s /%s HTTP/%s", s
, (*path
== '/' ? path
+ 1 : path
), soap
->http_version
);
5406 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5409 if ((soap
->ssl
&& soap
->port
!= 443) || (!soap
->ssl
&& soap
->port
!= 80))
5410 sprintf(soap
->tmpbuf
, "%s:%d", host
, port
);
5412 strcpy(soap
->tmpbuf
, host
);
5415 sprintf(soap
->tmpbuf
, "%s:%d", host
, port
);
5417 { /* Oracle customization */
5418 strncpy(soap
->tmpbuf
, host
, sizeof(soap
->tmpbuf
) - 1);
5419 soap
->tmpbuf
[sizeof(soap
->tmpbuf
) - 1] = '\0';
5422 // Oracle customization
5423 if ((err
= soap
->fposthdr(soap
, "Host", soap
->tmpbuf
))
5424 || (err
= soap
->fposthdr(soap
, "User-Agent", "SunKMS gSOAP/2.7.17"))
5425 || (err
= soap_puthttphdr(soap
, SOAP_OK
, count
)))
5429 if ((err
= soap
->fposthdr(soap
, "Accept-Encoding", "gzip, deflate")))
5431 if ((err
= soap
->fposthdr(soap
, "Accept-Encoding", "deflate")))
5436 if (soap
->userid
&& soap
->passwd
&& strlen(soap
->userid
) + strlen(soap
->passwd
) < 761)
5437 { sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->userid
, soap
->passwd
);
5438 strcpy(soap
->tmpbuf
, "Basic ");
5439 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
5440 if ((err
= soap
->fposthdr(soap
, "Authorization", soap
->tmpbuf
)))
5443 if (soap
->proxy_userid
&& soap
->proxy_passwd
&& strlen(soap
->proxy_userid
) + strlen(soap
->proxy_passwd
) < 761)
5444 { sprintf(soap
->tmpbuf
+ 262, "%s:%s", soap
->proxy_userid
, soap
->proxy_passwd
);
5445 strcpy(soap
->tmpbuf
, "Basic ");
5446 soap_s2base64(soap
, (const unsigned char*)(soap
->tmpbuf
+ 262), soap
->tmpbuf
+ 6, (int)strlen(soap
->tmpbuf
+ 262));
5447 if ((err
= soap
->fposthdr(soap
, "Proxy-Authorization", soap
->tmpbuf
)))
5453 if (soap_putcookies(soap
, host
, path
, soap
->ssl
!= NULL
))
5456 if (soap_putcookies(soap
, host
, path
, 0))
5460 if (soap
->status
!= SOAP_GET
&& (soap
->version
== 1 || (action
&& *action
)))
5461 { sprintf(soap
->tmpbuf
, "\"%s\"", action
&& strlen(action
) < sizeof(soap
->tmpbuf
) - 3 ? action
: SOAP_STR_EOS
);
5462 if ((err
= soap
->fposthdr(soap
, "SOAPAction", soap
->tmpbuf
)))
5465 return soap
->fposthdr(soap
, NULL
, NULL
);
5470 /******************************************************************************/
5474 http_send_header(struct soap
*soap
, const char *s
)
5475 { register const char *t
;
5477 { t
= strchr(s
, '\n'); /* disallow \n in HTTP headers */
5480 if (soap_send_raw(soap
, s
, t
- s
))
5489 /******************************************************************************/
5493 http_post_header(struct soap
*soap
, const char *key
, const char *val
)
5495 { if (http_send_header(soap
, key
))
5497 if (val
&& (soap_send_raw(soap
, ": ", 2) || http_send_header(soap
, val
)))
5500 return soap_send_raw(soap
, "\r\n", 2);
5505 /******************************************************************************/
5509 http_response(struct soap
*soap
, int status
, size_t count
)
5513 httpOutputEnable(soap
->rpmreqid
);
5515 if (strlen(soap
->http_version
) > 4)
5516 return soap
->error
= SOAP_EOM
;
5517 if (!status
|| status
== SOAP_HTML
|| status
== SOAP_FILE
)
5519 if (count
|| ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
))
5523 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Status = %s\n", s
));
5525 if (soap
->rpmreqid
|| soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* RPM behaves as if standalone */
5527 if (soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* standalone application (socket) or CGI (stdin/out)? */
5529 { sprintf(soap
->tmpbuf
, "HTTP/%s %s", soap
->http_version
, s
);
5530 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5533 else if ((err
= soap
->fposthdr(soap
, "Status", s
))) /* CGI header */
5536 else if (status
>= 200 && status
< 600)
5537 { sprintf(soap
->tmpbuf
, "HTTP/%s %d %s", soap
->http_version
, status
, http_error(soap
, status
));
5538 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5542 { sprintf(soap
->tmpbuf
, "Basic realm=\"%s\"", (soap
->authrealm
&& strlen(soap
->authrealm
) < sizeof(soap
->tmpbuf
) - 14) ? soap
->authrealm
: "gSOAP Web Service");
5543 if ((err
= soap
->fposthdr(soap
, "WWW-Authenticate", soap
->tmpbuf
)))
5546 else if ((status
>= 301 && status
<= 303) || status
== 307)
5547 { if ((err
= soap
->fposthdr(soap
, "Location", soap
->endpoint
)))
5553 { const char *s
= *soap_faultcode(soap
);
5554 if (status
>= SOAP_GET_METHOD
&& status
<= SOAP_HTTP_METHOD
)
5555 s
= "405 Method Not Allowed";
5556 else if (soap
->version
== 2 && (!s
|| !strcmp(s
, "SOAP-ENV:Sender")))
5557 s
= "400 Bad Request";
5559 s
= "500 Internal Server Error";
5560 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error %s (status=%d)\n", s
, status
));
5562 if (soap
->rpmreqid
|| soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* RPM behaves as if standalone */
5564 if (soap_valid_socket(soap
->master
) || soap_valid_socket(soap
->socket
)) /* standalone application */
5566 { sprintf(soap
->tmpbuf
, "HTTP/%s %s", soap
->http_version
, s
);
5567 if ((err
= soap
->fposthdr(soap
, soap
->tmpbuf
, NULL
)))
5570 else if ((err
= soap
->fposthdr(soap
, "Status", s
))) /* CGI */
5573 if ((err
= soap
->fposthdr(soap
, "Server", "gSOAP/2.7"))
5574 || (err
= soap_puthttphdr(soap
, status
, count
)))
5577 if (soap_putsetcookies(soap
))
5580 return soap
->fposthdr(soap
, NULL
, NULL
);
5585 /******************************************************************************/
5590 soap_response(struct soap
*soap
, int status
)
5591 { register size_t count
;
5592 if (!(soap
->omode
& (SOAP_ENC_XML
| SOAP_IO_STORE
/* this tests for chunking too */))
5593 && (status
== SOAP_HTML
|| status
== SOAP_FILE
))
5594 soap
->omode
= (soap
->omode
& ~SOAP_IO
) | SOAP_IO_STORE
;
5595 soap
->status
= status
;
5596 count
= soap_count_attachments(soap
);
5597 if (soap_begin_send(soap
))
5600 if ((soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& !(soap
->mode
& SOAP_ENC_XML
))
5601 { register int n
= soap
->mode
;
5602 soap
->mode
&= ~(SOAP_IO
| SOAP_ENC_ZLIB
);
5603 if ((n
& SOAP_IO
) != SOAP_IO_FLUSH
)
5604 soap
->mode
|= SOAP_IO_BUFFER
;
5605 if ((soap
->error
= soap
->fresponse(soap
, status
, count
)))
5608 if ((n
& SOAP_IO
) == SOAP_IO_CHUNK
)
5609 { if (soap_flush(soap
))
5620 /******************************************************************************\
5624 \******************************************************************************/
5627 /******************************************************************************/
5631 soap_encode_cookie(const char *s
, char *t
, size_t len
)
5633 register size_t n
= len
;
5634 while ((c
= *s
++) && --n
> 0)
5635 { if (c
> ' ' && c
< 128 && !strchr("()<>@,;:\\\"/[]?={}#!$&'*+", c
))
5639 *t
++ = (c
>> 4) + (c
> 159 ? '7' : '0');
5641 *t
++ = c
+ (c
> 9 ? '7' : '0');
5651 /******************************************************************************/
5655 soap_cookie(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5656 { struct soap_cookie
*p
;
5658 domain
= soap
->cookie_domain
;
5660 path
= soap
->cookie_path
;
5662 path
= SOAP_STR_EOS
;
5663 else if (*path
== '/')
5665 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Search cookie %s domain=%s path=%s\n", name
, domain
?domain
:"(null)", path
?path
:"(null)"));
5666 for (p
= soap
->cookies
; p
; p
= p
->next
)
5667 { 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
));
5668 if (!strcmp(p
->name
, name
)
5671 && !strcmp(p
->domain
, domain
)
5672 && (!*p
->path
|| !strncmp(p
->path
, path
, strlen(p
->path
))))
5678 /******************************************************************************/
5682 soap_set_cookie(struct soap
*soap
, const char *name
, const char *value
, const char *domain
, const char *path
)
5683 { struct soap_cookie
**p
, *q
;
5686 domain
= soap
->cookie_domain
;
5688 path
= soap
->cookie_path
;
5690 path
= SOAP_STR_EOS
;
5691 else if (*path
== '/')
5693 q
= soap_cookie(soap
, name
, domain
, path
);
5694 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)"));
5696 { if ((q
= (struct soap_cookie
*)SOAP_MALLOC(soap
, sizeof(struct soap_cookie
))))
5697 { if ((q
->name
= (char*)SOAP_MALLOC(soap
, strlen(name
)+1)))
5698 strcpy(q
->name
, name
);
5707 for (p
= &soap
->cookies
, n
= soap
->cookie_max
; *p
&& n
; p
= &(*p
)->next
, n
--)
5708 if (!strcmp((*p
)->name
, name
) && (*p
)->path
&& path
&& strcmp((*p
)->path
, path
) < 0)
5715 { SOAP_FREE(soap
, q
->name
);
5725 { if (!value
|| strcmp(value
, q
->value
))
5726 { SOAP_FREE(soap
, q
->value
);
5730 if (value
&& *value
&& !q
->value
&& (q
->value
= (char*)SOAP_MALLOC(soap
, strlen(value
)+1)))
5731 strcpy(q
->value
, value
);
5733 { if (!domain
|| strcmp(domain
, q
->domain
))
5734 { SOAP_FREE(soap
, q
->domain
);
5738 if (domain
&& !q
->domain
&& (q
->domain
= (char*)SOAP_MALLOC(soap
, strlen(domain
)+1)))
5739 strcpy(q
->domain
, domain
);
5741 { if (!path
|| strncmp(path
, q
->path
, strlen(q
->path
)))
5742 { SOAP_FREE(soap
, q
->path
);
5746 if (path
&& !q
->path
&& (q
->path
= (char*)SOAP_MALLOC(soap
, strlen(path
)+1)))
5747 strcpy(q
->path
, path
);
5754 /******************************************************************************/
5758 soap_clr_cookie(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5759 { struct soap_cookie
**p
, *q
;
5761 domain
= soap
->cookie_domain
;
5763 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error in clear cookie %s: cookie domain not set\n", name
?name
:"(null)"));
5767 path
= soap
->cookie_path
;
5769 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error in clear cookie %s: cookie path not set\n", name
?name
:"(null)"));
5774 for (p
= &soap
->cookies
, q
= *p
; q
; q
= *p
)
5775 { if (!strcmp(q
->name
, name
) && !strcmp(q
->domain
, domain
) && !strncmp(q
->path
, path
, strlen(q
->path
)))
5777 SOAP_FREE(soap
, q
->value
);
5779 SOAP_FREE(soap
, q
->domain
);
5781 SOAP_FREE(soap
, q
->path
);
5790 /******************************************************************************/
5794 soap_cookie_value(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5795 { struct soap_cookie
*p
;
5796 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5801 /******************************************************************************/
5805 soap_env_cookie_value(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5806 { struct soap_cookie
*p
;
5807 if ((p
= soap_cookie(soap
, name
, domain
, path
)) && p
->env
)
5812 /******************************************************************************/
5816 soap_cookie_expire(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5817 { struct soap_cookie
*p
;
5818 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5823 /******************************************************************************/
5827 soap_set_cookie_expire(struct soap
*soap
, const char *name
, long expire
, const char *domain
, const char *path
)
5828 { struct soap_cookie
*p
;
5829 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)"));
5830 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5831 { p
->maxage
= expire
;
5838 /******************************************************************************/
5842 soap_set_cookie_session(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5843 { struct soap_cookie
*p
;
5844 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5852 /******************************************************************************/
5856 soap_clr_cookie_session(struct soap
*soap
, const char *name
, const char *domain
, const char *path
)
5857 { struct soap_cookie
*p
;
5858 if ((p
= soap_cookie(soap
, name
, domain
, path
)))
5866 /******************************************************************************/
5870 soap_putsetcookies(struct soap
*soap
)
5871 { struct soap_cookie
*p
;
5874 for (p
= soap
->cookies
; p
; p
= p
->next
)
5878 || (!p
->env
&& !soap
->ssl
== !p
->secure
)
5883 s
+= soap_encode_cookie(p
->name
, s
, tmp
-s
+4064);
5884 if (p
->value
&& *p
->value
)
5886 s
+= soap_encode_cookie(p
->value
, s
, tmp
-s
+4064);
5888 if (p
->domain
&& (int)strlen(p
->domain
) < tmp
-s
+4064)
5889 { strcpy(s
, ";Domain=");
5890 strcat(s
, p
->domain
);
5892 else if (soap
->cookie_domain
&& (int)strlen(soap
->cookie_domain
) < tmp
-s
+4064)
5893 { strcpy(s
, ";Domain=");
5894 strcat(s
, soap
->cookie_domain
);
5896 strcat(s
, ";Path=/");
5901 t
= soap
->cookie_path
;
5905 if ((int)strlen(t
) < tmp
-s
+4064)
5906 { if (strchr(t
, '%')) /* already URL encoded? */
5911 s
+= soap_encode_cookie(t
, s
, tmp
-s
+4064);
5914 if (p
->version
> 0 && s
-tmp
< 4060)
5915 { sprintf(s
, ";Version=%u", p
->version
);
5918 if (p
->maxage
>= 0 && s
-tmp
< 4060)
5919 { sprintf(s
, ";Max-Age=%ld", p
->maxage
);
5928 strcpy(s
, ";Secure");
5929 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set-Cookie: %s\n", tmp
));
5930 if ((soap
->error
= soap
->fposthdr(soap
, "Set-Cookie", tmp
)))
5937 /******************************************************************************/
5941 soap_putcookies(struct soap
*soap
, const char *domain
, const char *path
, int secure
)
5942 { struct soap_cookie
**p
, *q
;
5943 unsigned int version
= 0;
5944 time_t now
= time(NULL
);
5947 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending cookies for domain=%s path=%s\n", domain
, path
));
5951 { if (q
->expire
&& now
> q
->expire
)
5952 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Cookie %s expired\n", q
->name
));
5953 SOAP_FREE(soap
, q
->name
);
5955 SOAP_FREE(soap
, q
->value
);
5957 SOAP_FREE(soap
, q
->domain
);
5959 SOAP_FREE(soap
, q
->path
);
5965 char *t
= q
->domain
;
5970 { const char *r
= strchr(t
, ':');
5975 flag
= !strncmp(t
, domain
, n
);
5977 /* domain-level cookies, cannot compile when WITH_NOIO set */
5980 { struct hostent
*hostent
= gethostbyname((char*)domain
);
5982 { const char *r
= strchr(hostent
->h_name
, '.');
5984 r
= hostent
->h_name
;
5985 flag
= !strncmp(t
, r
, n
);
5990 && (!q
->path
|| !strncmp(q
->path
, path
, strlen(q
->path
)))
5991 && (!q
->secure
|| secure
))
5993 if (q
->version
!= version
)
5994 { sprintf(s
, "$Version=%u;", q
->version
);
5995 version
= q
->version
;
5998 s
+= soap_encode_cookie(q
->name
, s
, tmp
-s
+4080);
5999 if (q
->value
&& *q
->value
)
6001 s
+= soap_encode_cookie(q
->value
, s
, tmp
-s
+4080);
6003 if (q
->path
&& *q
->path
&& (int)strlen(q
->path
) < tmp
-s
+4080)
6004 { sprintf(s
, ";$Path=\"/%s\"", (*q
->path
== '/' ? q
->path
+ 1 : q
->path
));
6007 if (q
->domain
&& (int)strlen(q
->domain
) < tmp
-s
+4080)
6008 sprintf(s
, ";$Domain=\"%s\"", q
->domain
);
6009 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Cookie: %s\n", tmp
));
6010 if ((soap
->error
= soap
->fposthdr(soap
, "Cookie", tmp
)))
6019 /******************************************************************************/
6023 soap_getcookies(struct soap
*soap
, const char *val
)
6024 { struct soap_cookie
*p
= NULL
, *q
;
6026 char *t
, tmp
[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6027 char *domain
= NULL
;
6029 unsigned int version
= 0;
6030 time_t now
= time(NULL
);
6035 { s
= soap_decode_key(tmp
, sizeof(tmp
), s
);
6036 if (!soap_tag_cmp(tmp
, "$Version"))
6037 { if ((s
= soap_decode_val(tmp
, sizeof(tmp
), s
)))
6039 p
->version
= (int)soap_strtol(tmp
, NULL
, 10);
6041 version
= (int)soap_strtol(tmp
, NULL
, 10);
6044 else if (!soap_tag_cmp(tmp
, "$Path"))
6045 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6047 { if ((t
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6054 SOAP_FREE(soap
, p
->path
);
6059 SOAP_FREE(soap
, path
);
6063 else if (!soap_tag_cmp(tmp
, "$Domain"))
6064 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6066 { if ((t
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6073 SOAP_FREE(soap
, p
->domain
);
6078 SOAP_FREE(soap
, domain
);
6082 else if (p
&& !soap_tag_cmp(tmp
, "Path"))
6084 SOAP_FREE(soap
, p
->path
);
6085 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6087 { if ((p
->path
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6088 strcpy(p
->path
, tmp
);
6093 else if (p
&& !soap_tag_cmp(tmp
, "Domain"))
6095 SOAP_FREE(soap
, p
->domain
);
6096 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6098 { if ((p
->domain
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1)))
6099 strcpy(p
->domain
, tmp
);
6104 else if (p
&& !soap_tag_cmp(tmp
, "Version"))
6105 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6106 p
->version
= (unsigned int)soap_strtoul(tmp
, NULL
, 10);
6108 else if (p
&& !soap_tag_cmp(tmp
, "Max-Age"))
6109 { s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6110 p
->expire
= now
+ soap_strtol(tmp
, NULL
, 10);
6112 else if (p
&& !soap_tag_cmp(tmp
, "Expires"))
6115 static const char mns
[] = "anebarprayunulugepctovec";
6116 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6117 if (strlen(tmp
) > 20)
6118 { memset((void*)&T
, 0, sizeof(T
));
6122 T
.tm_mday
= (int)soap_strtol(a
, NULL
, 10);
6125 T
.tm_mon
= (int)(strstr(mns
, a
) - mns
) / 2;
6128 T
.tm_year
= 100 + (int)soap_strtol(a
, NULL
, 10);
6131 T
.tm_hour
= (int)soap_strtol(a
, NULL
, 10);
6134 T
.tm_min
= (int)soap_strtol(a
, NULL
, 10);
6137 T
.tm_sec
= (int)soap_strtol(a
, NULL
, 10);
6138 p
->expire
= soap_timegm(&T
);
6141 else if (p
&& !soap_tag_cmp(tmp
, "Secure"))
6145 { 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
));
6146 if ((q
= soap_set_cookie(soap
, p
->name
, p
->value
, p
->domain
, p
->path
)))
6147 { q
->version
= p
->version
;
6148 q
->expire
= p
->expire
;
6149 q
->secure
= p
->secure
;
6153 SOAP_FREE(soap
, p
->name
);
6155 SOAP_FREE(soap
, p
->value
);
6157 SOAP_FREE(soap
, p
->domain
);
6159 SOAP_FREE(soap
, p
->path
);
6162 if ((p
= (struct soap_cookie
*)SOAP_MALLOC(soap
, sizeof(struct soap_cookie
))))
6163 { p
->name
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1);
6164 strcpy(p
->name
, tmp
);
6165 s
= soap_decode_val(tmp
, sizeof(tmp
), s
);
6167 { p
->value
= (char*)SOAP_MALLOC(soap
, strlen(tmp
)+1);
6168 strcpy(p
->value
, tmp
);
6174 else if (*soap
->host
)
6175 { p
->domain
= (char*)SOAP_MALLOC(soap
, strlen(soap
->host
)+1);
6176 strcpy(p
->domain
, soap
->host
);
6182 else if (soap
->path
&& *soap
->path
)
6183 { p
->path
= (char*)SOAP_MALLOC(soap
, strlen(soap
->path
)+1);
6184 strcpy(p
->path
, soap
->path
);
6187 { p
->path
= (char*)SOAP_MALLOC(soap
, 2);
6188 strcpy(p
->path
, "/");
6192 p
->version
= version
;
6197 { 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
));
6198 if ((q
= soap_set_cookie(soap
, p
->name
, p
->value
, p
->domain
, p
->path
)))
6199 { q
->version
= p
->version
;
6200 q
->expire
= p
->expire
;
6201 q
->secure
= p
->secure
;
6205 SOAP_FREE(soap
, p
->name
);
6207 SOAP_FREE(soap
, p
->value
);
6209 SOAP_FREE(soap
, p
->domain
);
6211 SOAP_FREE(soap
, p
->path
);
6215 SOAP_FREE(soap
, domain
);
6217 SOAP_FREE(soap
, path
);
6220 /******************************************************************************/
6224 soap_getenv_cookies(struct soap
*soap
)
6225 { struct soap_cookie
*p
;
6227 char key
[4096], val
[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
6228 if (!(s
= getenv("HTTP_COOKIE")))
6231 { s
= soap_decode_key(key
, sizeof(key
), s
);
6232 s
= soap_decode_val(val
, sizeof(val
), s
);
6233 p
= soap_set_cookie(soap
, key
, val
, NULL
, NULL
);
6240 /******************************************************************************/
6244 soap_copy_cookies(struct soap
*copy
, const struct soap
*soap
)
6245 { struct soap_cookie
*p
, **q
, *r
;
6247 for (p
= soap
->cookies
; p
; p
= p
->next
)
6248 { if (!(*q
= (struct soap_cookie
*)SOAP_MALLOC(copy
, sizeof(struct soap_cookie
))))
6252 { if (((*q
)->name
= (char*)SOAP_MALLOC(copy
, strlen(p
->name
)+1)))
6253 strcpy((*q
)->name
, p
->name
);
6256 { if (((*q
)->value
= (char*)SOAP_MALLOC(copy
, strlen(p
->value
)+1)))
6257 strcpy((*q
)->value
, p
->value
);
6260 { if (((*q
)->domain
= (char*)SOAP_MALLOC(copy
, strlen(p
->domain
)+1)))
6261 strcpy((*q
)->domain
, p
->domain
);
6264 { if (((*q
)->path
= (char*)SOAP_MALLOC(copy
, strlen(p
->path
)+1)))
6265 strcpy((*q
)->path
, p
->path
);
6273 /******************************************************************************/
6277 soap_free_cookies(struct soap
*soap
)
6278 { struct soap_cookie
*p
;
6279 for (p
= soap
->cookies
; p
; p
= soap
->cookies
)
6280 { soap
->cookies
= p
->next
;
6281 SOAP_FREE(soap
, p
->name
);
6283 SOAP_FREE(soap
, p
->value
);
6285 SOAP_FREE(soap
, p
->domain
);
6287 SOAP_FREE(soap
, p
->path
);
6292 /******************************************************************************/
6293 #endif /* WITH_COOKIES */
6295 /******************************************************************************/
6296 #ifndef WITH_NOIDREF
6301 soap_hash(register const char *s
)
6302 { register size_t h
= 0;
6305 return h
% SOAP_IDHASH
;
6310 /******************************************************************************/
6311 #ifndef WITH_NOIDREF
6314 soap_init_pht(struct soap
*soap
)
6318 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
6319 soap
->pht
[i
] = NULL
;
6324 /******************************************************************************/
6329 soap_new1(soap_mode mode
)
6330 { return soap_new2(mode
, mode
);
6334 /******************************************************************************/
6340 { return soap_new2(SOAP_IO_DEFAULT
, SOAP_IO_DEFAULT
);
6344 /******************************************************************************/
6349 soap_new2(soap_mode imode
, soap_mode omode
)
6350 { struct soap
*soap
= (struct soap
*)malloc(sizeof(struct soap
));
6352 soap_init2(soap
, imode
, omode
);
6357 /******************************************************************************/
6362 soap_free(struct soap
*soap
)
6368 /******************************************************************************/
6373 soap_del(struct soap
*soap
)
6378 /******************************************************************************/
6379 #ifndef WITH_NOIDREF
6382 soap_free_pht(struct soap
*soap
)
6383 { register struct soap_pblk
*pb
, *next
;
6385 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free pointer hashtable\n"));
6386 for (pb
= soap
->pblk
; pb
; pb
= next
)
6388 SOAP_FREE(soap
, pb
);
6392 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
6393 soap
->pht
[i
] = NULL
;
6398 /******************************************************************************/
6399 #ifndef WITH_NOIDREF
6404 soap_embed(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, const char *tag
, int type
)
6406 struct soap_plist
*pp
;
6407 if (soap
->version
== 2)
6410 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, type
, &pp
);
6412 i
= soap_pointer_lookup(soap
, p
, type
, &pp
);
6414 { if (soap_is_embedded(soap
, pp
)
6415 || soap_is_single(soap
, pp
))
6417 soap_set_embedded(soap
, pp
);
6424 /******************************************************************************/
6425 #ifndef WITH_NOIDREF
6430 soap_pointer_lookup(struct soap
*soap
, const void *p
, int type
, struct soap_plist
**ppp
)
6431 { register struct soap_plist
*pp
;
6434 { for (pp
= soap
->pht
[soap_hash_ptr(p
)]; pp
; pp
= pp
->next
)
6435 { if (pp
->ptr
== p
&& pp
->type
== type
)
6437 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup location=%p type=%d id=%d\n", p
, type
, pp
->id
));
6442 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup location=%p type=%d: not found\n", p
, type
));
6448 /******************************************************************************/
6449 #ifndef WITH_NOIDREF
6454 soap_pointer_enter(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int type
, struct soap_plist
**ppp
)
6455 { register size_t h
;
6456 register struct soap_plist
*pp
;
6457 if (!soap
->pblk
|| soap
->pidx
>= SOAP_PTRBLK
)
6458 { register struct soap_pblk
*pb
= (struct soap_pblk
*)SOAP_MALLOC(soap
, sizeof(struct soap_pblk
));
6460 { soap
->error
= SOAP_EOM
;
6463 pb
->next
= soap
->pblk
;
6467 *ppp
= pp
= &soap
->pblk
->plist
[soap
->pidx
++];
6469 h
= soap_hash_ptr(a
->__ptr
);
6471 h
= soap_hash_ptr(p
);
6472 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));
6473 pp
->next
= soap
->pht
[h
];
6480 pp
->id
= ++soap
->idnum
;
6486 /******************************************************************************/
6487 #ifndef WITH_NOIDREF
6492 soap_array_pointer_lookup(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int type
, struct soap_plist
**ppp
)
6493 { register struct soap_plist
*pp
;
6495 if (!p
|| !a
->__ptr
)
6497 for (pp
= soap
->pht
[soap_hash_ptr(a
->__ptr
)]; pp
; pp
= pp
->next
)
6498 { if (pp
->type
== type
&& pp
->array
&& pp
->array
->__ptr
== a
->__ptr
)
6500 for (i
= 0; i
< n
; i
++)
6501 if (((const int*)&pp
->array
->__size
)[i
] != ((const int*)&a
->__size
)[i
])
6505 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array lookup location=%p type=%d id=%d\n", a
->__ptr
, type
, pp
->id
));
6510 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Array lookup location=%p type=%d: not found\n", a
->__ptr
, type
));
6516 /******************************************************************************/
6521 soap_begin_count(struct soap
*soap
)
6522 { soap_free_ns(soap
);
6524 if ((soap
->mode
& SOAP_ENC_DIME
) || (soap
->omode
& SOAP_ENC_DIME
))
6525 soap
->mode
= soap
->omode
| SOAP_IO_LENGTH
| SOAP_ENC_DIME
;
6528 { soap
->mode
= soap
->omode
;
6529 if ((soap
->mode
& SOAP_IO_UDP
))
6530 soap
->mode
|= SOAP_ENC_XML
;
6531 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
6532 || (((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_ENC_XML
))
6534 && !soap
->fpreparesend
6537 soap
->mode
&= ~SOAP_IO_LENGTH
;
6539 soap
->mode
|= SOAP_IO_LENGTH
;
6542 if ((soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
)
6543 { if (!(soap
->mode
& SOAP_ENC_DIME
))
6544 soap
->mode
&= ~SOAP_IO_LENGTH
;
6545 if (soap
->mode
& SOAP_ENC_XML
)
6546 soap
->mode
|= SOAP_IO_BUFFER
;
6548 soap
->mode
|= SOAP_IO_STORE
;
6551 if (!soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
))
6552 soap
->mode
|= SOAP_XML_TREE
;
6554 if ((soap
->mode
& SOAP_ENC_MTOM
) && (soap
->mode
& SOAP_ENC_DIME
))
6555 soap
->mode
|= SOAP_ENC_MIME
;
6556 else if (!(soap
->mode
& SOAP_ENC_MIME
))
6557 soap
->mode
&= ~SOAP_ENC_MTOM
;
6558 if (soap
->mode
& SOAP_ENC_MIME
)
6559 soap_select_mime_boundary(soap
);
6560 soap
->dime
.list
= soap
->dime
.last
; /* keep track of last DIME attachment */
6566 soap
->mustUnderstand
= 0;
6568 soap
->part
= SOAP_BEGIN
;
6570 soap_clr_attr(soap
);
6571 soap_set_local_namespaces(soap
);
6572 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
));
6574 soap
->dime
.count
= 0; /* count # of attachments */
6575 soap
->dime
.size
= 0; /* accumulate total size of attachments */
6576 if (soap
->fprepareinitsend
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
)
6577 return soap
->error
= soap
->fprepareinitsend(soap
);
6583 /******************************************************************************/
6588 soap_end_count(struct soap
*soap
)
6589 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of count phase\n"));
6591 if (soap
->fpreparefinalsend
&& (soap
->mode
& SOAP_IO_LENGTH
))
6592 return soap
->error
= soap
->fpreparefinalsend(soap
);
6598 /******************************************************************************/
6603 soap_begin_send(struct soap
*soap
)
6604 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Initializing for output\n"));
6606 soap
->error
= SOAP_OK
;
6607 soap
->mode
= soap
->omode
| (soap
->mode
& (SOAP_IO_LENGTH
| SOAP_ENC_DIME
));
6609 if ((soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
)
6610 { if (soap
->mode
& SOAP_ENC_XML
)
6611 soap
->mode
|= SOAP_IO_BUFFER
;
6613 soap
->mode
|= SOAP_IO_STORE
;
6617 if ((soap
->mode
& SOAP_IO_UDP
))
6618 { soap
->mode
|= SOAP_ENC_XML
;
6619 if (soap
->count
> SOAP_BUFLEN
)
6620 return soap
->error
= SOAP_UDP_ERROR
;
6623 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_FLUSH
&& soap_valid_socket(soap
->socket
))
6624 { if (soap
->count
|| (soap
->mode
& SOAP_IO_LENGTH
) || (soap
->mode
& SOAP_ENC_XML
))
6625 soap
->mode
|= SOAP_IO_BUFFER
;
6627 soap
->mode
|= SOAP_IO_STORE
;
6629 soap
->mode
&= ~SOAP_IO_LENGTH
;
6630 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
6631 if (soap_new_block(soap
) == NULL
)
6633 if (!(soap
->mode
& SOAP_IO_KEEPALIVE
))
6634 soap
->keep_alive
= 0;
6635 if (!soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
))
6636 soap
->mode
|= SOAP_XML_TREE
;
6638 if ((soap
->mode
& SOAP_ENC_MTOM
) && (soap
->mode
& SOAP_ENC_DIME
))
6639 { soap
->mode
|= SOAP_ENC_MIME
;
6640 soap
->mode
&= ~SOAP_ENC_DIME
;
6642 else if (!(soap
->mode
& SOAP_ENC_MIME
))
6643 soap
->mode
&= ~SOAP_ENC_MTOM
;
6644 if (soap
->mode
& SOAP_ENC_MIME
)
6645 soap_select_mime_boundary(soap
);
6648 #ifndef WITH_FASTCGI
6649 if (!soap_valid_socket(soap
->socket
)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
6651 setmode(soap
->sendfd
, _O_BINARY
);
6653 _setmode(soap
->sendfd
, _O_BINARY
);
6659 if (soap
->mode
& SOAP_IO
)
6663 soap
->chunksize
= 0;
6667 soap
->mustUnderstand
= 0;
6671 soap_clr_attr(soap
);
6672 soap_set_local_namespaces(soap
);
6674 soap
->z_ratio_out
= 1.0;
6675 if ((soap
->mode
& SOAP_ENC_ZLIB
) && soap
->zlib_state
!= SOAP_ZLIB_DEFLATE
)
6677 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
6678 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
6679 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
6681 if (soap
->zlib_out
!= SOAP_ZLIB_DEFLATE
)
6682 { memcpy(soap
->z_buf
, "\37\213\10\0\0\0\0\0\0\377", 10);
6683 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
+ 10;
6684 soap
->d_stream
->avail_out
= SOAP_BUFLEN
- 10;
6685 soap
->z_crc
= crc32(0L, NULL
, 0);
6686 soap
->zlib_out
= SOAP_ZLIB_GZIP
;
6688 *((Byte
*)soap
->z_buf
+ 2) = 0xff;
6689 if (deflateInit2(soap
->d_stream
, soap
->z_level
, Z_DEFLATED
, -MAX_WBITS
, 8, Z_DEFAULT_STRATEGY
) != Z_OK
)
6690 return soap
->error
= SOAP_ZLIB_ERROR
;
6694 if (deflateInit(soap
->d_stream
, soap
->z_level
) != Z_OK
)
6695 return soap
->error
= SOAP_ZLIB_ERROR
;
6697 { if (deflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
6698 return soap
->error
= SOAP_ZLIB_ERROR
;
6700 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflate initialized\n"));
6701 soap
->zlib_state
= SOAP_ZLIB_DEFLATE
;
6708 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap
->socket
, soap
->mode
, (unsigned long)soap
->count
));
6709 soap
->part
= SOAP_BEGIN
;
6711 if (soap
->fprepareinitsend
&& (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
6712 soap
->fprepareinitsend(soap
);
6718 /******************************************************************************/
6719 #ifndef WITH_NOIDREF
6724 soap_embedded(struct soap
*soap
, const void *p
, int t
)
6725 { struct soap_plist
*pp
;
6726 if (soap_pointer_lookup(soap
, p
, t
, &pp
))
6729 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded %p type=%d mark set to 1\n", p
, t
));
6735 /******************************************************************************/
6736 #ifndef WITH_NOIDREF
6741 soap_reference(struct soap
*soap
, const void *p
, int t
)
6742 { struct soap_plist
*pp
;
6743 if (!p
|| (soap
->mode
& SOAP_XML_TREE
))
6745 if (soap_pointer_lookup(soap
, p
, t
, &pp
))
6746 { if (pp
->mark1
== 0)
6751 else if (soap_pointer_enter(soap
, p
, NULL
, 0, t
, &pp
))
6757 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reference %p type=%d (%d %d)\n", p
, t
, (int)pp
->mark1
, (int)pp
->mark2
));
6763 /******************************************************************************/
6764 #ifndef WITH_NOIDREF
6769 soap_array_reference(struct soap
*soap
, const void *p
, const struct soap_array
*a
, int n
, int t
)
6771 struct soap_plist
*pp
;
6772 if (!p
|| !a
->__ptr
)
6774 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
6776 { if (pp
->mark1
== 0)
6781 else if (!soap_pointer_enter(soap
, p
, a
, n
, t
, &pp
))
6787 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
));
6793 /******************************************************************************/
6794 #ifndef WITH_NOIDREF
6799 soap_embedded_id(struct soap
*soap
, int id
, const void *p
, int t
)
6800 { struct soap_plist
*pp
= NULL
;
6801 if (soap
->mode
& SOAP_XML_TREE
)
6803 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Embedded_id %p type=%d id=%d\n", p
, t
, id
));
6804 if (soap
->version
== 1 && soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
) && soap
->part
!= SOAP_IN_HEADER
)
6806 { id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
6808 { if (soap
->mode
& SOAP_IO_LENGTH
)
6812 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
));
6819 id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
6820 else if (id
&& !soap_pointer_lookup(soap
, p
, t
, &pp
))
6823 { if (soap
->mode
& SOAP_IO_LENGTH
)
6827 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
));
6834 /******************************************************************************/
6835 #ifndef WITH_NOIDREF
6840 soap_is_embedded(struct soap
*soap
, struct soap_plist
*pp
)
6843 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Is embedded? %d %d\n", (int)pp
->mark1
, (int)pp
->mark2
));
6844 if (soap
->version
== 1 && soap
->encodingStyle
&& !(soap
->mode
& SOAP_XML_GRAPH
) && soap
->part
!= SOAP_IN_HEADER
)
6845 { if (soap
->mode
& SOAP_IO_LENGTH
)
6846 return pp
->mark1
!= 0;
6847 return pp
->mark2
!= 0;
6849 if (soap
->mode
& SOAP_IO_LENGTH
)
6850 return pp
->mark1
== 1;
6851 return pp
->mark2
== 1;
6856 /******************************************************************************/
6857 #ifndef WITH_NOIDREF
6862 soap_is_single(struct soap
*soap
, struct soap_plist
*pp
)
6863 { if (soap
->part
== SOAP_IN_HEADER
)
6867 if (soap
->mode
& SOAP_IO_LENGTH
)
6868 return pp
->mark1
== 0;
6869 return pp
->mark2
== 0;
6874 /******************************************************************************/
6875 #ifndef WITH_NOIDREF
6880 soap_set_embedded(struct soap
*soap
, struct soap_plist
*pp
)
6883 if (soap
->mode
& SOAP_IO_LENGTH
)
6891 /******************************************************************************/
6897 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
)
6899 #ifndef WITH_NOIDREF
6900 struct soap_plist
*pp
= NULL
; /* Oracle customization */
6902 if (!p
|| !a
->__ptr
|| (!aid
&& !atype
))
6903 return soap_element_id(soap
, tag
, id
, p
, a
, n
, type
, t
);
6904 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
));
6905 i
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
6907 { i
= soap_pointer_enter(soap
, p
, a
, n
, t
, &pp
);
6909 { soap
->error
= SOAP_EOM
;
6916 { sprintf(soap
->tmpbuf
, soap
->dime_id_format
, id
);
6917 aid
= soap_strdup(soap
, soap
->tmpbuf
);
6919 /* Add MTOM xop:Include element when necessary */
6920 /* TODO: this code to be obsoleted with new import/xop.h conventions */
6921 if ((soap
->mode
& SOAP_ENC_MTOM
) && strcmp(tag
, "xop:Include"))
6922 { if (soap_element_begin_out(soap
, tag
, 0, type
)
6923 || soap_element_href(soap
, "xop:Include", 0, "xmlns:xop=\"http://www.w3.org/2004/08/xop/include\" href", aid
)
6924 || soap_element_end_out(soap
, tag
))
6927 else if (soap_element_href(soap
, tag
, 0, "href", aid
))
6929 if (soap
->mode
& SOAP_IO_LENGTH
)
6930 { if (pp
&& (pp
->mark1
!= 3)) /* Oracle customization */
6931 { struct soap_multipart
*content
;
6932 if (soap
->mode
& SOAP_ENC_MTOM
)
6933 content
= soap_new_multipart(soap
, &soap
->mime
.first
, &soap
->mime
.last
, (char*)a
->__ptr
, a
->__size
);
6935 content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, (char*)a
->__ptr
, a
->__size
);
6937 { soap
->error
= SOAP_EOM
;
6940 if (!strncmp(aid
, "cid:", 4)) /* RFC 2111 */
6941 { if (soap
->mode
& SOAP_ENC_MTOM
)
6942 { char *s
= (char*)soap_malloc(soap
, strlen(aid
) - 1);
6945 strcpy(s
+ 1, aid
+ 4);
6951 content
->id
= aid
+ 4;
6955 content
->type
= atype
;
6956 content
->options
= aoptions
;
6957 content
->encoding
= SOAP_MIME_BINARY
;
6961 else if (pp
) /* Oracle customization */
6969 /******************************************************************************/
6970 #ifndef WITH_NOIDREF
6973 soap_init_iht(struct soap
*soap
)
6975 for (i
= 0; i
< SOAP_IDHASH
; i
++)
6976 soap
->iht
[i
] = NULL
;
6981 /******************************************************************************/
6982 #ifndef WITH_NOIDREF
6985 soap_free_iht(struct soap
*soap
)
6987 register struct soap_ilist
*ip
= NULL
, *p
= NULL
;
6988 register struct soap_flist
*fp
= NULL
, *fq
= NULL
;
6989 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free ID hashtable\n"));
6990 for (i
= 0; i
< SOAP_IDHASH
; i
++)
6991 { for (ip
= soap
->iht
[i
]; ip
; ip
= p
)
6992 { for (fp
= ip
->flist
; fp
; fp
= fq
)
6994 SOAP_FREE(soap
, fp
);
6997 SOAP_FREE(soap
, ip
);
6999 soap
->iht
[i
] = NULL
;
7005 /******************************************************************************/
7006 #ifndef WITH_NOIDREF
7011 soap_lookup(struct soap
*soap
, const char *id
)
7012 { register struct soap_ilist
*ip
= NULL
;
7013 for (ip
= soap
->iht
[soap_hash(id
)]; ip
; ip
= ip
->next
)
7014 if (!strcmp(ip
->id
, id
))
7021 /******************************************************************************/
7022 #ifndef WITH_NOIDREF
7027 soap_enter(struct soap
*soap
, const char *id
)
7028 { register size_t h
;
7029 register struct soap_ilist
*ip
;
7030 ip
= (struct soap_ilist
*)SOAP_MALLOC(soap
, sizeof(struct soap_ilist
) + strlen(id
));
7032 { h
= soap_hash(id
);
7034 ip
->next
= soap
->iht
[h
];
7042 /******************************************************************************/
7047 soap_malloc(struct soap
*soap
, size_t n
)
7050 return (void*)SOAP_NON_NULL
;
7052 return SOAP_MALLOC(soap
, n
);
7054 p
= (char*)soap
->fmalloc(soap
, n
);
7056 { n
+= sizeof(short);
7057 n
+= (-(long)n
) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
7058 if (!(p
= (char*)SOAP_MALLOC(soap
, n
+ sizeof(void*) + sizeof(size_t))))
7059 { soap
->error
= SOAP_EOM
;
7062 /* set the canary to detect corruption */
7063 *(unsigned short*)(p
+ n
- sizeof(unsigned short)) = (unsigned short)SOAP_CANARY
;
7064 /* keep chain of alloced cells for destruction */
7065 *(void**)(p
+ n
) = soap
->alist
;
7066 *(size_t*)(p
+ n
+ sizeof(void*)) = n
;
7067 soap
->alist
= p
+ n
;
7074 /******************************************************************************/
7075 #ifdef SOAP_MEM_DEBUG
7077 soap_init_mht(struct soap
*soap
)
7079 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
7080 soap
->mht
[i
] = NULL
;
7084 /******************************************************************************/
7085 #ifdef SOAP_MEM_DEBUG
7087 soap_free_mht(struct soap
*soap
)
7089 register struct soap_mlist
*mp
, *mq
;
7090 for (i
= 0; i
< (int)SOAP_PTRHASH
; i
++)
7091 { for (mp
= soap
->mht
[i
]; mp
; mp
= mq
)
7095 fprintf(stderr
, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp
->file
, mp
->line
, mp
->ptr
);
7097 (void) printstack( 2 ); /* Oracle customization */
7102 soap
->mht
[i
] = NULL
;
7107 /******************************************************************************/
7108 #ifdef SOAP_MEM_DEBUG
7112 soap_track_malloc(struct soap
*soap
, const char *file
, int line
, size_t size
)
7113 { register void *p
= malloc(size
);
7115 { register size_t h
= soap_hash_ptr(p
);
7116 register struct soap_mlist
*mp
= (struct soap_mlist
*)malloc(sizeof(struct soap_mlist
));
7117 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%s(%d): malloc(%lu) = %p\n", file
, line
, (unsigned long)size
, p
));
7118 mp
->next
= soap
->mht
[h
];
7129 /******************************************************************************/
7130 #ifdef SOAP_MEM_DEBUG
7134 soap_track_free(struct soap
*soap
, const char *file
, int line
, void *p
)
7135 { register size_t h
= soap_hash_ptr(p
);
7136 register struct soap_mlist
*mp
;
7137 for (mp
= soap
->mht
[h
]; mp
; mp
= mp
->next
)
7143 if (soap
->fdebug
[SOAP_INDEX_TEST
])
7144 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "%s(%d): free(%p)\n", file
, line
, p
));
7149 fprintf(stderr
, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file
, line
, p
, mp
->file
, mp
->line
);
7152 fprintf(stderr
, "%s(%d): free(%p) pointer not malloced\n", file
, line
, p
);
7156 /******************************************************************************/
7157 #ifdef SOAP_MEM_DEBUG
7159 soap_track_unlink(struct soap
*soap
, const void *p
)
7160 { register size_t h
= soap_hash_ptr(p
);
7161 register struct soap_mlist
*mp
;
7162 for (mp
= soap
->mht
[h
]; mp
; mp
= mp
->next
)
7170 /******************************************************************************/
7175 soap_dealloc(struct soap
*soap
, void *p
)
7176 { if (soap_check_state(soap
))
7179 { register char **q
;
7180 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7182 if (*(unsigned short*)(char*)(*q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7184 #ifdef SOAP_MEM_DEBUG
7185 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7187 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7188 DBGHEX(TEST
, *q
- 200, 200);
7189 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7190 soap
->error
= SOAP_MOE
;
7193 if (p
== (void*)(*q
- *(size_t*)(*q
+ sizeof(void*))))
7194 { *q
= **(char***)q
;
7195 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Freed data at %p\n", p
));
7200 soap_delete(soap
, p
);
7204 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free all soap_malloc() data\n"));
7206 { q
= (char*)soap
->alist
;
7207 if (*(unsigned short*)(char*)(q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7209 #ifdef SOAP_MEM_DEBUG
7210 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7212 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7213 DBGHEX(TEST
, q
- 200, 200);
7214 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7215 soap
->error
= SOAP_MOE
;
7218 soap
->alist
= *(void**)q
;
7219 q
-= *(size_t*)(q
+ sizeof(void*));
7222 /* we must assume these were deallocated: */
7223 soap
->action
= NULL
;
7225 soap
->header
= NULL
;
7226 soap
->userid
= NULL
;
7227 soap
->passwd
= NULL
;
7228 soap
->authrealm
= NULL
;
7229 soap
->http_content
= NULL
;
7231 soap_clr_mime(soap
);
7237 /******************************************************************************/
7242 soap_delete(struct soap
*soap
, void *p
)
7243 { register struct soap_clist
**cp
;
7244 if (soap_check_state(soap
))
7249 { if (p
== (*cp
)->ptr
)
7250 { register struct soap_clist
*q
= *cp
;
7253 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: deletion callback failed for object type %d\n", q
->ptr
, q
->type
));
7254 #ifdef SOAP_MEM_DEBUG
7255 fprintf(stderr
, "new(object type = %d) = %p not freed: deletion callback failed\n", q
->type
, q
->ptr
);
7263 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: address not in list\n", p
));
7267 { register struct soap_clist
*q
= *cp
;
7270 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not dealloc data %p: deletion callback failed for object type %d\n", q
->ptr
, q
->type
));
7271 #ifdef SOAP_MEM_DEBUG
7272 fprintf(stderr
, "new(object type = %d) = %p not freed: deletion callback failed\n", q
->type
, q
->ptr
);
7278 soap
->fault
= NULL
; /* this was possibly deallocated */
7279 soap
->header
= NULL
; /* this was possibly deallocated */
7283 /******************************************************************************/
7288 soap_delegate_deletion(struct soap
*soap
, struct soap
*soap_to
)
7289 { register struct soap_clist
*cp
;
7291 #ifdef SOAP_MEM_DEBUG
7293 register struct soap_mlist
**mp
, *mq
;
7296 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7298 if (*(unsigned short*)(char*)(*q
- sizeof(unsigned short)) != (unsigned short)SOAP_CANARY
)
7300 #ifdef SOAP_MEM_DEBUG
7301 fprintf(stderr
, "Data corruption in dynamic allocation (see logs)\n");
7303 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Data corruption:\n"));
7304 DBGHEX(TEST
, *q
- 200, 200);
7305 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "\n"));
7306 soap
->error
= SOAP_MOE
;
7309 #ifdef SOAP_MEM_DEBUG
7310 p
= (void*)(*q
- *(size_t*)(*q
+ sizeof(void*)));
7311 h
= soap_hash_ptr(p
);
7312 for (mp
= &soap
->mht
[h
]; *mp
; mp
= &(*mp
)->next
)
7313 { if ((*mp
)->ptr
== p
)
7316 mq
->next
= soap_to
->mht
[h
];
7317 soap_to
->mht
[h
] = mq
;
7323 *q
= (char*)soap_to
->alist
;
7324 soap_to
->alist
= soap
->alist
;
7326 cp
= soap_to
->clist
;
7330 cp
->next
= soap
->clist
;
7333 soap_to
->clist
= soap
->clist
;
7338 /******************************************************************************/
7343 soap_link(struct soap
*soap
, void *p
, int t
, int n
, int (*fdelete
)(struct soap_clist
*))
7344 { register struct soap_clist
*cp
;
7345 if ((cp
= (struct soap_clist
*)SOAP_MALLOC(soap
, sizeof(struct soap_clist
))))
7346 { cp
->next
= soap
->clist
;
7350 cp
->fdelete
= fdelete
;
7357 /******************************************************************************/
7362 soap_unlink(struct soap
*soap
, const void *p
)
7363 { register char **q
;
7364 register struct soap_clist
**cp
;
7367 for (q
= (char**)&soap
->alist
; *q
; q
= *(char***)q
)
7368 { if (p
== (void*)(*q
- *(size_t*)(*q
+ sizeof(void*))))
7369 { *q
= **(char***)q
;
7370 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unlinked data %p\n", p
));
7371 #ifdef SOAP_MEM_DEBUG
7372 soap_track_unlink(soap
, p
);
7377 for (cp
= &soap
->clist
; *cp
; cp
= &(*cp
)->next
)
7378 { if (p
== (*cp
)->ptr
)
7379 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unlinked class instance %p\n", p
));
7389 /******************************************************************************/
7390 #ifndef WITH_NOIDREF
7395 soap_lookup_type(struct soap
*soap
, const char *id
)
7396 { register struct soap_ilist
*ip
;
7398 { ip
= soap_lookup(soap
, id
);
7400 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Lookup id='%s' type=%d\n", id
, ip
->type
));
7404 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id
));
7410 /******************************************************************************/
7411 #ifndef WITH_NOIDREF
7416 soap_id_lookup(struct soap
*soap
, const char *id
, void **p
, int t
, size_t n
, unsigned int k
)
7417 { struct soap_ilist
*ip
;
7419 if (!p
|| !id
|| !*id
)
7421 ip
= soap_lookup(soap
, id
); /* lookup pointer to hash table entry for string id */
7423 { if (!(ip
= soap_enter(soap
, id
))) /* new hash table entry for string id */
7425 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id
, t
, p
, (unsigned int)n
));
7436 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id
, t
, ip
->ptr
, (unsigned int)n
));
7439 /* Oracle customization */
7440 strncpy(soap
->id
, id
, sizeof(soap
->id
) - 1);
7441 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
7442 soap
->error
= SOAP_HREF
;
7443 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id
, ip
->type
, t
));
7446 while (ip
->level
< k
)
7447 { q
= (void**)soap_malloc(soap
, sizeof(void*));
7453 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
7457 else if (ip
->level
> k
)
7458 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving level %u pointers to href='%s'\n", ip
->level
, id
));
7459 while (ip
->level
> k
)
7460 { void *s
, **r
= &ip
->link
;
7461 q
= (void**)ip
->link
;
7463 { *r
= (void*)soap_malloc(soap
, sizeof(void*));
7474 ip
->level
= ip
->level
- 1;
7475 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
7477 q
= (void**)ip
->link
;
7482 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id
, t
, p
, (unsigned int)n
));
7483 while (ip
->level
< k
)
7484 { q
= (void**)soap_malloc(soap
, sizeof(void*));
7490 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Descending one level...\n"));
7492 q
= (void**)ip
->link
;
7501 /******************************************************************************/
7502 #ifndef WITH_NOIDREF
7507 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))
7508 { struct soap_ilist
*ip
;
7509 if (!p
|| !href
|| !*href
)
7511 ip
= soap_lookup(soap
, href
); /* lookup pointer to hash table entry for string id */
7513 { if (!(ip
= soap_enter(soap
, href
))) /* new hash table entry for string id */
7522 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
));
7524 else if (ip
->type
!= st
|| (ip
->level
== k
&& ip
->size
!= n
))
7525 { 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
));
7526 /* Oracle customization */
7527 strncpy(soap
->id
, href
, sizeof(soap
->id
) - 1);
7528 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
7529 soap
->error
= SOAP_HREF
;
7532 if (fcopy
|| n
< sizeof(void*) || *href
!= '#')
7533 { register struct soap_flist
*fp
= (struct soap_flist
*)SOAP_MALLOC(soap
, sizeof(struct soap_flist
));
7535 { soap
->error
= SOAP_EOM
;
7538 fp
->next
= ip
->flist
;
7546 fp
->fcopy
= soap_fcopy
;
7548 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
));
7551 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Forwarding copying address %p for type=%d href='%s'\n", p
, st
, href
));
7552 *(void**)p
= ip
->copy
;
7560 /******************************************************************************/
7565 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*))
7567 #ifndef WITH_NOIDREF
7568 struct soap_ilist
*ip
;
7570 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id
, t
, p
, (unsigned long)n
, k
));
7574 p
= finstantiate(soap
, t
, type
, arrayType
, &n
);
7576 p
= soap_malloc(soap
, n
);
7580 #ifndef WITH_NOIDREF
7584 #ifndef WITH_NOIDREF
7585 ip
= soap_lookup(soap
, id
); /* lookup pointer to hash table entry for string id */
7586 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Lookup entry id='%s for location=%p'\n", id
, p
));
7588 { if (!(ip
= soap_enter(soap
, id
))) /* new hash table entry for string id */
7597 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
));
7599 else if ((ip
->type
!= t
|| (ip
->level
== k
&& ip
->size
!= n
)) && (ip
->copy
|| ip
->flist
))
7600 { 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
));
7601 /* Oracle customization */
7602 strncpy(soap
->id
, id
, sizeof(soap
->id
) - 1);
7603 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
7604 soap
->error
= SOAP_HREF
;
7608 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Multiply defined id='%s'\n", id
));
7609 /* Oracle customization */
7610 strncpy(soap
->id
, id
, sizeof(soap
->id
) - 1);
7611 soap
->id
[sizeof(soap
->id
) - 1] = '\0';
7612 soap
->error
= SOAP_DUPLICATE_ID
;
7619 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
));
7626 /******************************************************************************/
7631 soap_fcopy(struct soap
*soap
, int st
, int tt
, void *p
, size_t len
, const void *q
, size_t n
)
7632 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st
, tt
, q
, p
, (unsigned long)n
));
7637 /******************************************************************************/
7642 soap_end_send(struct soap
*soap
)
7646 if (soap
->dime
.list
)
7647 { /* SOAP body referenced attachments must appear first */
7648 soap
->dime
.last
->next
= soap
->dime
.first
;
7649 soap
->dime
.first
= soap
->dime
.list
->next
;
7650 soap
->dime
.list
->next
= NULL
;
7651 soap
->dime
.last
= soap
->dime
.list
;
7653 if (!(err
= soap_putdime(soap
)))
7654 err
= soap_putmime(soap
);
7655 soap
->mime
.list
= NULL
;
7656 soap
->mime
.first
= NULL
;
7657 soap
->mime
.last
= NULL
;
7658 soap
->dime
.list
= NULL
;
7659 soap
->dime
.first
= NULL
;
7660 soap
->dime
.last
= NULL
;
7664 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End send\n"));
7665 if (soap
->mode
& SOAP_IO
) /* need to flush the remaining data in buffer */
7666 { if (soap_flush(soap
))
7668 { if (soap
->mode
& SOAP_ENC_ZLIB
&& soap
->zlib_state
== SOAP_ZLIB_DEFLATE
)
7669 { soap
->zlib_state
= SOAP_ZLIB_NONE
;
7670 deflateEnd(soap
->d_stream
);
7678 if (soap
->mode
& SOAP_ENC_ZLIB
)
7680 soap
->d_stream
->avail_in
= 0;
7682 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflating remainder\n"));
7683 r
= deflate(soap
->d_stream
, Z_FINISH
);
7684 if (soap
->d_stream
->avail_out
!= SOAP_BUFLEN
)
7685 { if (soap_flush_raw(soap
, soap
->z_buf
, SOAP_BUFLEN
- soap
->d_stream
->avail_out
))
7686 { soap
->zlib_state
= SOAP_ZLIB_NONE
;
7687 deflateEnd(soap
->d_stream
);
7690 soap
->d_stream
->next_out
= (Byte
*)soap
->z_buf
;
7691 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
7693 } while (r
== Z_OK
);
7694 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Deflated total %lu->%lu bytes\n", soap
->d_stream
->total_in
, soap
->d_stream
->total_out
));
7695 soap
->z_ratio_out
= (float)soap
->d_stream
->total_out
/ (float)soap
->d_stream
->total_in
;
7696 soap
->mode
&= ~SOAP_ENC_ZLIB
;
7697 soap
->zlib_state
= SOAP_ZLIB_NONE
;
7698 if (deflateEnd(soap
->d_stream
) != Z_OK
|| r
!= Z_STREAM_END
)
7699 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Unable to end deflate: %s\n", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
));
7700 return soap
->error
= SOAP_ZLIB_ERROR
;
7703 if (soap
->zlib_out
!= SOAP_ZLIB_DEFLATE
)
7704 { soap
->z_buf
[0] = soap
->z_crc
& 0xFF;
7705 soap
->z_buf
[1] = (soap
->z_crc
>> 8) & 0xFF;
7706 soap
->z_buf
[2] = (soap
->z_crc
>> 16) & 0xFF;
7707 soap
->z_buf
[3] = (soap
->z_crc
>> 24) & 0xFF;
7708 soap
->z_buf
[4] = soap
->d_stream
->total_in
& 0xFF;
7709 soap
->z_buf
[5] = (soap
->d_stream
->total_in
>> 8) & 0xFF;
7710 soap
->z_buf
[6] = (soap
->d_stream
->total_in
>> 16) & 0xFF;
7711 soap
->z_buf
[7] = (soap
->d_stream
->total_in
>> 24) & 0xFF;
7712 if (soap_flush_raw(soap
, soap
->z_buf
, 8))
7714 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip crc32=%lu\n", (unsigned long)soap
->z_crc
));
7719 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
7722 if (!(soap
->mode
& SOAP_ENC_XML
))
7724 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending buffered message of length %u\n", (unsigned int)soap
->blist
->size
));
7725 if (soap
->status
>= SOAP_POST
)
7726 soap
->error
= soap
->fpost(soap
, soap
->endpoint
, soap
->host
, soap
->port
, soap
->path
, soap
->action
, soap
->blist
->size
);
7727 else if (soap
->status
!= SOAP_STOP
)
7728 soap
->error
= soap
->fresponse(soap
, soap
->status
, soap
->blist
->size
);
7729 if (soap
->error
|| soap_flush(soap
))
7734 for (p
= soap_first_block(soap
, NULL
); p
; p
= soap_next_block(soap
, NULL
))
7735 { DBGMSG(SENT
, p
, soap_block_size(soap
, NULL
));
7736 if ((soap
->error
= soap
->fsend(soap
, p
, soap_block_size(soap
, NULL
))))
7737 { soap_end_block(soap
, NULL
);
7741 soap_end_block(soap
, NULL
);
7744 else if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
7745 { DBGMSG(SENT
, "\r\n0\r\n\r\n", 7);
7746 if ((soap
->error
= soap
->fsend(soap
, "\r\n0\r\n\r\n", 7)))
7753 if (!soap
->ssl
&& soap_valid_socket(soap
->socket
) && !soap
->keep_alive
&& !(soap
->omode
& SOAP_IO_UDP
))
7754 soap
->fshutdownsocket(soap
, soap
->socket
, 1); /* Send TCP FIN */
7756 if (soap_valid_socket(soap
->socket
) && !soap
->keep_alive
&& !(soap
->omode
& SOAP_IO_UDP
))
7757 soap
->fshutdownsocket(soap
, soap
->socket
, 1); /* Send TCP FIN */
7760 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End of send phase\n"));
7761 soap
->omode
&= ~SOAP_XML_SEC
;
7763 soap
->part
= SOAP_END
;
7768 /******************************************************************************/
7773 soap_end_recv(struct soap
*soap
)
7774 { soap
->part
= SOAP_END
;
7776 soap
->wsuid
= NULL
; /* reset before next send */
7777 soap
->c14nexclude
= NULL
; /* reset before next send */
7780 if ((soap
->mode
& SOAP_ENC_DIME
) && soap_getdime(soap
))
7781 { soap
->dime
.first
= NULL
;
7782 soap
->dime
.last
= NULL
;
7785 soap
->dime
.list
= soap
->dime
.first
;
7786 soap
->dime
.first
= NULL
;
7787 soap
->dime
.last
= NULL
;
7788 /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */
7789 if (soap
->mode
& SOAP_ENC_MIME
)
7791 #ifndef WITH_NOIDREF
7792 if (soap
->mode
& SOAP_MIME_POSTCHECK
)
7793 { soap_resolve(soap
);
7797 if (soap_getmime(soap
))
7800 soap
->mime
.list
= soap
->mime
.first
;
7801 soap
->mime
.first
= NULL
;
7802 soap
->mime
.last
= NULL
;
7803 soap
->mime
.boundary
= NULL
;
7805 { struct soap_multipart
*content
;
7806 for (content
= soap
->mime
.list
; content
; content
= content
->next
)
7807 soap_resolve_attachment(soap
, content
);
7810 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "End of receive message ok\n"));
7812 if (soap
->mode
& SOAP_ENC_ZLIB
)
7813 { /* Make sure end of compressed content is reached */
7814 while (soap
->d_stream
->next_out
!= Z_NULL
)
7815 if ((int)soap_get1(soap
) == EOF
)
7817 soap
->mode
&= ~SOAP_ENC_ZLIB
;
7818 memcpy(soap
->buf
, soap
->z_buf
, SOAP_BUFLEN
);
7819 soap
->bufidx
= (char*)soap
->d_stream
->next_in
- soap
->z_buf
;
7820 soap
->buflen
= soap
->z_buflen
;
7821 soap
->zlib_state
= SOAP_ZLIB_NONE
;
7822 if (inflateEnd(soap
->d_stream
) != Z_OK
)
7823 return soap
->error
= SOAP_ZLIB_ERROR
;
7824 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Inflate end ok\n"));
7826 if (soap
->zlib_in
== SOAP_ZLIB_GZIP
)
7829 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Inflate gzip crc check\n"));
7830 for (i
= 0; i
< 8; i
++)
7831 { if ((int)(c
= soap_get1(soap
)) == EOF
)
7832 return soap
->error
= SOAP_EOF
;
7833 soap
->z_buf
[i
] = (char)c
;
7835 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)))
7836 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap
->z_crc
));
7837 return soap
->error
= SOAP_ZLIB_ERROR
;
7839 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)))
7840 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Gzip error: incorrect message length\n"));
7841 return soap
->error
= SOAP_ZLIB_ERROR
;
7844 soap
->zlib_in
= SOAP_ZLIB_NONE
;
7848 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
7849 while ((int)soap_getchar(soap
) != EOF
) /* advance to last chunk */
7851 #ifndef WITH_NOIDREF
7852 if (soap_resolve(soap
))
7857 { if (soap
->mode
& SOAP_ENC_MTOM
)
7858 return soap
->error
= SOAP_MIME_HREF
;
7859 return soap
->error
= SOAP_DIME_HREF
;
7864 if (soap
->fpreparefinalrecv
)
7865 return soap
->error
= soap
->fpreparefinalrecv(soap
);
7871 /******************************************************************************/
7876 soap_free_temp(struct soap
*soap
)
7877 { register struct soap_attribute
*tp
, *tq
;
7878 register struct Namespace
*ns
;
7880 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free any remaining temp blocks\n"));
7882 soap_end_block(soap
, NULL
);
7883 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free attribute storage\n"));
7884 for (tp
= soap
->attributes
; tp
; tp
= tq
)
7887 SOAP_FREE(soap
, tp
->value
);
7888 SOAP_FREE(soap
, tp
);
7890 soap
->attributes
= NULL
;
7893 SOAP_FREE(soap
, soap
->labbuf
);
7894 soap
->labbuf
= NULL
;
7898 ns
= soap
->local_namespaces
;
7900 { for (; ns
->id
; ns
++)
7902 { if (soap
->encodingStyle
== ns
->out
)
7903 soap
->encodingStyle
= SOAP_STR_EOS
;
7904 SOAP_FREE(soap
, ns
->out
);
7907 if (soap
->encodingStyle
== ns
->ns
)
7908 soap
->encodingStyle
= SOAP_STR_EOS
;
7910 SOAP_FREE(soap
, soap
->local_namespaces
);
7911 soap
->local_namespaces
= NULL
;
7915 { struct soap_xlist
*xp
= soap
->xlist
->next
;
7916 SOAP_FREE(soap
, soap
->xlist
);
7920 #ifndef WITH_NOIDREF
7921 soap_free_pht(soap
);
7922 soap_free_iht(soap
);
7927 /******************************************************************************/
7930 soap_free_ns(struct soap
*soap
)
7931 { register struct soap_nlist
*np
, *nq
;
7932 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free namespace stack\n"));
7933 for (np
= soap
->nlist
; np
; np
= nq
)
7935 SOAP_FREE(soap
, np
);
7941 /******************************************************************************/
7943 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
7945 soap_init_logs(struct soap
*soap
)
7947 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
7948 { soap
->logfile
[i
] = NULL
;
7949 soap
->fdebug
[i
] = NULL
;
7955 /******************************************************************************/
7956 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
7960 soap_open_logfile(struct soap
*soap
, int i
)
7961 { if (soap
->logfile
[i
])
7962 soap
->fdebug
[i
] = fopen(soap
->logfile
[i
], i
< 2 ? "ab" : "a");
7966 /******************************************************************************/
7969 soap_close_logfile(struct soap
*soap
, int i
)
7970 { if (soap
->fdebug
[i
])
7971 { fclose(soap
->fdebug
[i
]);
7972 soap
->fdebug
[i
] = NULL
;
7977 /******************************************************************************/
7982 soap_close_logfiles(struct soap
*soap
)
7984 for (i
= 0; i
< SOAP_MAXLOGS
; i
++)
7985 soap_close_logfile(soap
, i
);
7989 /******************************************************************************/
7992 soap_set_logfile(struct soap
*soap
, int i
, const char *logfile
)
7995 soap_close_logfile(soap
, i
);
7996 s
= soap
->logfile
[i
];
7997 soap
->logfile
[i
] = logfile
;
7999 SOAP_FREE(soap
, (void*)s
);
8001 if ((t
= (char*)SOAP_MALLOC(soap
, strlen(logfile
) + 1)))
8003 soap
->logfile
[i
] = t
;
8007 /******************************************************************************/
8012 soap_set_recv_logfile(struct soap
*soap
, const char *logfile
)
8013 { soap_set_logfile(soap
, SOAP_INDEX_RECV
, logfile
);
8017 /******************************************************************************/
8022 soap_set_sent_logfile(struct soap
*soap
, const char *logfile
)
8023 { soap_set_logfile(soap
, SOAP_INDEX_SENT
, logfile
);
8027 /******************************************************************************/
8032 soap_set_test_logfile(struct soap
*soap
, const char *logfile
)
8033 { soap_set_logfile(soap
, SOAP_INDEX_TEST
, logfile
);
8037 /******************************************************************************/
8042 soap_copy(const struct soap
*soap
)
8043 { return soap_copy_context((struct soap
*)malloc(sizeof(struct soap
)), soap
);
8047 /******************************************************************************/
8052 soap_copy_context(struct soap
*copy
, const struct soap
*soap
)
8053 { if (soap_check_state(soap
))
8056 { register struct soap_plugin
*p
= NULL
;
8060 memcpy(copy
, soap
, sizeof(struct soap
));
8062 copy
->state
= SOAP_COPY
;
8063 copy
->error
= SOAP_OK
;
8064 copy
->userid
= NULL
;
8065 copy
->passwd
= NULL
;
8070 copy
->attributes
= NULL
;
8071 copy
->labbuf
= NULL
;
8074 #ifdef SOAP_MEM_DEBUG
8075 soap_init_mht(copy
);
8077 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8078 soap_init_logs(copy
);
8081 soap_set_test_logfile(copy
, soap
->logfile
[SOAP_INDEX_TEST
]);
8082 soap_set_sent_logfile(copy
, soap
->logfile
[SOAP_INDEX_SENT
]);
8083 soap_set_recv_logfile(copy
, soap
->logfile
[SOAP_INDEX_RECV
]);
8085 #ifdef WITH_C_LOCALE
8086 copy
->c_locale
= duplocale(soap
->c_locale
);
8088 copy
->c_locale
= NULL
;
8093 copy
->session
= NULL
;
8096 copy
->d_stream
= (z_stream
*)SOAP_MALLOC(copy
, sizeof(z_stream
));
8097 copy
->d_stream
->zalloc
= Z_NULL
;
8098 copy
->d_stream
->zfree
= Z_NULL
;
8099 copy
->d_stream
->opaque
= Z_NULL
;
8102 copy
->local_namespaces
= NULL
;
8103 #ifndef WITH_NOIDREF
8104 soap_init_iht(copy
);
8105 soap_init_pht(copy
);
8107 copy
->header
= NULL
;
8109 copy
->action
= NULL
;
8112 copy
->cookies
= soap_copy_cookies(copy
, soap
);
8114 copy
->cookies
= NULL
;
8117 copy
->plugins
= NULL
;
8118 for (p
= soap
->plugins
; p
; p
= p
->next
)
8119 { register struct soap_plugin
*q
= (struct soap_plugin
*)SOAP_MALLOC(copy
, sizeof(struct soap_plugin
));
8122 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Copying plugin '%s'\n", p
->id
));
8124 if (p
->fcopy
&& p
->fcopy(copy
, q
, p
))
8125 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Could not copy plugin '%s'\n", p
->id
));
8129 q
->next
= copy
->plugins
;
8137 /******************************************************************************/
8142 soap_copy_stream(struct soap
*copy
, struct soap
*soap
)
8143 { copy
->mode
= soap
->mode
;
8144 copy
->imode
= soap
->imode
;
8145 copy
->omode
= soap
->omode
;
8146 copy
->socket
= soap
->socket
;
8147 copy
->recv_timeout
= soap
->recv_timeout
;
8148 copy
->send_timeout
= soap
->send_timeout
;
8149 #if defined(__cplusplus) && !defined(WITH_LEAN)
8150 copy
->os
= soap
->os
;
8151 copy
->is
= soap
->is
;
8153 copy
->sendfd
= soap
->sendfd
;
8154 copy
->recvfd
= soap
->recvfd
;
8155 copy
->bufidx
= soap
->bufidx
;
8156 copy
->buflen
= soap
->buflen
;
8157 copy
->ahead
= soap
->ahead
;
8158 copy
->cdata
= soap
->cdata
;
8159 copy
->chunksize
= soap
->chunksize
;
8160 copy
->chunkbuflen
= soap
->chunkbuflen
;
8161 copy
->keep_alive
= soap
->keep_alive
;
8162 copy
->tcp_keep_alive
= soap
->tcp_keep_alive
;
8163 copy
->tcp_keep_idle
= soap
->tcp_keep_idle
;
8164 copy
->tcp_keep_intvl
= soap
->tcp_keep_intvl
;
8165 copy
->tcp_keep_cnt
= soap
->tcp_keep_cnt
;
8166 copy
->max_keep_alive
= soap
->max_keep_alive
;
8168 copy
->peer
= soap
->peer
;
8169 copy
->peerlen
= soap
->peerlen
;
8172 copy
->bio
= soap
->bio
;
8173 copy
->ssl
= soap
->ssl
;
8174 copy
->ctx
= soap
->ctx
;
8177 copy
->zlib_state
= soap
->zlib_state
;
8178 copy
->zlib_in
= soap
->zlib_in
;
8179 copy
->zlib_out
= soap
->zlib_out
;
8180 copy
->d_stream
= (z_stream
*)SOAP_MALLOC(copy
, sizeof(z_stream
));
8181 memcpy(copy
->d_stream
, soap
->d_stream
, sizeof(z_stream
));
8182 copy
->z_crc
= soap
->z_crc
;
8183 copy
->z_ratio_in
= soap
->z_ratio_in
;
8184 copy
->z_ratio_out
= soap
->z_ratio_out
;
8186 copy
->z_buflen
= soap
->z_buflen
;
8187 copy
->z_level
= soap
->z_level
;
8188 if (soap
->z_buf
&& soap
->zlib_state
!= SOAP_ZLIB_NONE
)
8189 { copy
->z_buf
= (char*)SOAP_MALLOC(copy
, SOAP_BUFLEN
);
8190 memcpy(copy
->z_buf
, soap
->z_buf
, sizeof(soap
->z_buf
));
8192 copy
->z_dict
= soap
->z_dict
;
8193 copy
->z_dict_len
= soap
->z_dict_len
;
8195 memcpy(copy
->buf
, soap
->buf
, sizeof(soap
->buf
));
8199 /******************************************************************************/
8204 soap_free_stream(struct soap
*soap
)
8205 { soap
->socket
= SOAP_INVALID_SOCKET
;
8212 SOAP_FREE(soap
, soap
->d_stream
);
8213 soap
->d_stream
= NULL
;
8215 SOAP_FREE(soap
, soap
->z_buf
);
8221 /******************************************************************************/
8226 soap_init(struct soap
*soap
)
8227 { soap
->state
= SOAP_INIT
;
8228 #ifdef SOAP_MEM_DEBUG
8229 soap_init_mht(soap
);
8231 #if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
8232 soap_init_logs(soap
);
8236 Oracle customization for KMS server debug
8238 #ifdef SOAP_DEBUG_SERVER
8239 soap_set_test_logfile(soap
, "/var/log/SUNWkms2/TEST.log");
8240 soap_set_sent_logfile(soap
, "/var/log/SUNWkms2/SENT.log");
8241 soap_set_recv_logfile(soap
, "/var/log/SUNWkms2/RECV.log");
8243 soap_set_test_logfile(soap
, "TEST.log");
8244 soap_set_sent_logfile(soap
, "SENT.log");
8245 soap_set_recv_logfile(soap
, "RECV.log");
8247 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Initializing context\n"));
8250 soap_imode(soap
, SOAP_IO_DEFAULT
);
8251 soap_omode(soap
, SOAP_IO_DEFAULT
);
8252 soap
->plugins
= NULL
;
8254 soap
->userid
= NULL
;
8255 soap
->passwd
= NULL
;
8257 soap
->fpost
= http_post
;
8258 soap
->fget
= http_get
;
8259 soap
->fput
= http_405
;
8260 soap
->fdel
= http_405
;
8261 soap
->fhead
= http_405
;
8263 soap
->fposthdr
= http_post_header
;
8264 soap
->fresponse
= http_response
;
8265 soap
->fparse
= http_parse
;
8266 soap
->fparsehdr
= http_parse_header
;
8268 soap
->fheader
= NULL
;
8269 soap
->fconnect
= NULL
;
8270 soap
->fdisconnect
= NULL
;
8272 soap
->ipv6_multicast_if
= 0;
8273 soap
->ipv4_multicast_if
= NULL
;
8275 soap
->fresolve
= tcp_gethost
;
8277 soap
->fresolve
= NULL
;
8279 soap
->faccept
= tcp_accept
;
8280 soap
->fopen
= tcp_connect
;
8281 soap
->fclose
= tcp_disconnect
;
8282 soap
->fclosesocket
= tcp_closesocket
;
8283 soap
->fshutdownsocket
= tcp_shutdownsocket
;
8284 soap
->fsend
= fsend
;
8285 soap
->frecv
= frecv
;
8286 soap
->fpoll
= soap_poll
;
8289 soap
->fclose
= NULL
;
8292 soap
->fseterror
= NULL
;
8293 soap
->fignore
= NULL
;
8294 soap
->fserveloop
= NULL
;
8295 soap
->fplugin
= fplugin
;
8296 soap
->fmalloc
= NULL
;
8298 soap
->fprepareinitsend
= NULL
;
8299 soap
->fprepareinitrecv
= NULL
;
8300 soap
->fpreparesend
= NULL
;
8301 soap
->fpreparerecv
= NULL
;
8302 soap
->fpreparefinalsend
= NULL
;
8303 soap
->fpreparefinalrecv
= NULL
;
8304 soap
->fdimereadopen
= NULL
;
8305 soap
->fdimewriteopen
= NULL
;
8306 soap
->fdimereadclose
= NULL
;
8307 soap
->fdimewriteclose
= NULL
;
8308 soap
->fdimeread
= NULL
;
8309 soap
->fdimewrite
= NULL
;
8310 soap
->fmimereadopen
= NULL
;
8311 soap
->fmimewriteopen
= NULL
;
8312 soap
->fmimereadclose
= NULL
;
8313 soap
->fmimewriteclose
= NULL
;
8314 soap
->fmimeread
= NULL
;
8315 soap
->fmimewrite
= NULL
;
8317 soap
->float_format
= "%.9G"; /* Alternative: use "%G" */
8318 soap
->double_format
= "%.17lG"; /* Alternative: use "%lG" */
8319 soap
->dime_id_format
= "cid:id%d"; /* default DIME id format */
8320 soap
->http_version
= "1.1";
8321 soap
->proxy_http_version
= "1.0";
8322 soap
->http_content
= NULL
;
8325 soap
->keep_alive
= 0;
8326 soap
->tcp_keep_alive
= 0;
8327 soap
->tcp_keep_idle
= 0;
8328 soap
->tcp_keep_intvl
= 0;
8329 soap
->tcp_keep_cnt
= 0;
8330 soap
->max_keep_alive
= SOAP_MAXKEEPALIVE
;
8331 soap
->recv_timeout
= 0;
8332 soap
->send_timeout
= 0;
8333 soap
->connect_timeout
= 0;
8334 soap
->accept_timeout
= 0;
8335 #if defined(WITH_OPENSSL) && defined(KMS_SERVER)
8336 /* Oracle customization for Ultra 2 KMS Server */
8337 soap
->ssl_accept_timeout
= 0;
8339 soap
->socket_flags
= 0;
8340 soap
->connect_flags
= 0;
8341 soap
->bind_flags
= 0;
8342 soap
->accept_flags
= 0;
8343 soap
->linger_time
= 0;
8345 soap
->labbuf
= NULL
;
8348 soap
->encodingStyle
= SOAP_STR_EOS
;
8349 #ifndef WITH_NONAMESPACES
8350 soap
->namespaces
= namespaces
;
8352 soap
->namespaces
= NULL
;
8354 soap
->local_namespaces
= NULL
;
8359 soap
->attributes
= NULL
;
8360 soap
->header
= NULL
;
8362 soap
->master
= SOAP_INVALID_SOCKET
;
8363 soap
->socket
= SOAP_INVALID_SOCKET
;
8368 soap
->dime
.list
= NULL
;
8369 soap
->dime
.first
= NULL
;
8370 soap
->dime
.last
= NULL
;
8371 soap
->mime
.list
= NULL
;
8372 soap
->mime
.first
= NULL
;
8373 soap
->mime
.last
= NULL
;
8374 soap
->mime
.boundary
= NULL
;
8375 soap
->mime
.start
= NULL
;
8382 soap
->recvfd
= stdin
;
8383 soap
->sendfd
= stdout
;
8385 soap
->host
[0] = '\0';
8386 soap
->session_host
[0] = '\0'; /* Oracle customization */
8387 soap
->session_port
= 0; /* Oracle customization */
8389 soap
->action
= NULL
;
8390 soap
->proxy_host
= NULL
;
8391 soap
->proxy_port
= 8080;
8392 soap
->proxy_userid
= NULL
;
8393 soap
->proxy_passwd
= NULL
;
8394 soap
->authrealm
= NULL
;
8395 soap
->prolog
= NULL
;
8397 soap
->zlib_state
= SOAP_ZLIB_NONE
;
8398 soap
->zlib_in
= SOAP_ZLIB_NONE
;
8399 soap
->zlib_out
= SOAP_ZLIB_NONE
;
8400 soap
->d_stream
= (z_stream
*)SOAP_MALLOC(soap
, sizeof(z_stream
));
8401 soap
->d_stream
->zalloc
= Z_NULL
;
8402 soap
->d_stream
->zfree
= Z_NULL
;
8403 soap
->d_stream
->opaque
= Z_NULL
;
8406 soap
->z_dict
= NULL
;
8407 soap
->z_dict_len
= 0;
8411 soap
->c14nexclude
= NULL
;
8412 soap
->cookies
= NULL
;
8413 soap
->cookie_domain
= NULL
;
8414 soap
->cookie_path
= NULL
;
8415 soap
->cookie_max
= 32;
8418 soap
->rpmreqid
= NULL
;
8423 #ifndef WITH_NOIDREF
8424 soap_init_iht(soap
);
8425 soap_init_pht(soap
);
8428 if (!soap_ssl_init_done
)
8430 soap
->fsslauth
= ssl_auth_init
;
8431 soap
->fsslverify
= ssl_verify_callback
;
8435 soap
->ssl_flags
= SOAP_SSL_DEFAULT
;
8436 soap
->keyfile
= NULL
;
8437 soap
->password
= NULL
;
8438 soap
->dhfile
= NULL
;
8439 soap
->cafile
= NULL
;
8440 soap
->capath
= NULL
;
8441 soap
->crlfile
= NULL
;
8442 soap
->randfile
= NULL
;
8443 soap
->session
= NULL
;
8445 #ifdef WITH_C_LOCALE
8446 soap
->c_locale
= newlocale(LC_ALL_MASK
, "C", NULL
);
8448 soap
->c_locale
= NULL
;
8453 soap
->dime
.chunksize
= 0;
8454 soap
->dime
.buflen
= 0;
8459 soap
->mustUnderstand
= 0;
8461 soap
->part
= SOAP_END
;
8470 soap
->endpoint
[0] = '\0';
8471 soap
->error
= SOAP_OK
;
8475 /******************************************************************************/
8480 soap_init1(struct soap
*soap
, soap_mode mode
)
8481 { soap_init2(soap
, mode
, mode
);
8485 /******************************************************************************/
8490 soap_init2(struct soap
*soap
, soap_mode imode
, soap_mode omode
)
8492 soap_imode(soap
, imode
);
8493 soap_omode(soap
, omode
);
8497 /******************************************************************************/
8502 soap_begin(struct soap
*soap
)
8503 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reinitializing context\n"));
8504 if (!soap
->keep_alive
)
8508 soap
->keep_alive
= (((soap
->imode
| soap
->omode
) & SOAP_IO_KEEPALIVE
) != 0);
8512 soap
->mustUnderstand
= 0;
8515 soap
->part
= SOAP_END
;
8520 soap
->error
= SOAP_OK
;
8525 soap
->endpoint
[0] = '\0';
8527 soap
->dime
.chunksize
= 0;
8528 soap
->dime
.buflen
= 0;
8530 soap_free_temp(soap
);
8534 /******************************************************************************/
8539 soap_end(struct soap
*soap
)
8540 { if (soap_check_state(soap
))
8542 soap_free_temp(soap
);
8543 soap_dealloc(soap
, NULL
);
8545 { register struct soap_clist
*cp
= soap
->clist
->next
;
8546 SOAP_FREE(soap
, soap
->clist
);
8549 soap_closesock(soap
);
8551 soap_close_logfiles(soap
);
8559 /******************************************************************************/
8564 soap_set_namespaces(struct soap
*soap
, const struct Namespace
*p
)
8565 { register struct Namespace
*ns
= soap
->local_namespaces
;
8566 register struct soap_nlist
*np
, *nq
, *nr
;
8567 register unsigned int level
= soap
->level
;
8568 soap
->namespaces
= p
;
8569 soap
->local_namespaces
= NULL
;
8570 soap_set_local_namespaces(soap
);
8571 /* reverse the namespace list */
8584 /* then push on new stack */
8586 { register const char *s
;
8587 soap
->level
= np
->level
; /* preserve element nesting level */
8589 if (!s
&& np
->index
>= 0 && ns
)
8590 { s
= ns
[np
->index
].out
;
8592 s
= ns
[np
->index
].ns
;
8594 if (s
&& soap_push_namespace(soap
, np
->id
, s
) == NULL
)
8598 SOAP_FREE(soap
, nq
);
8602 for (i
= 0; ns
[i
].id
; i
++)
8604 { SOAP_FREE(soap
, ns
[i
].out
);
8608 SOAP_FREE(soap
, ns
);
8610 soap
->level
= level
; /* restore level */
8615 /******************************************************************************/
8620 soap_set_local_namespaces(struct soap
*soap
)
8621 { if (soap
->namespaces
&& !soap
->local_namespaces
)
8622 { register const struct Namespace
*ns1
;
8623 register struct Namespace
*ns2
;
8624 register size_t n
= 1;
8625 for (ns1
= soap
->namespaces
; ns1
->id
; ns1
++)
8627 n
*= sizeof(struct Namespace
);
8628 ns2
= (struct Namespace
*)SOAP_MALLOC(soap
, n
);
8630 { memcpy(ns2
, soap
->namespaces
, n
);
8632 { if (!strcmp(ns2
[0].ns
, soap_env1
))
8637 soap
->local_namespaces
= ns2
;
8643 /******************************************************************************/
8649 soap_tagsearch(const char *big
, const char *little
)
8651 { register size_t n
= strlen(little
);
8652 register const char *s
= big
;
8654 { register const char *t
= s
;
8656 for (i
= 0; i
< n
; i
++, t
++)
8657 { if (*t
!= little
[i
])
8660 if (*t
== '\0' || *t
== ' ')
8661 { if (i
== n
|| (i
&& little
[i
-1] == ':'))
8674 /******************************************************************************/
8680 soap_lookup_ns(struct soap
*soap
, const char *tag
, size_t n
)
8681 { register struct soap_nlist
*np
;
8682 for (np
= soap
->nlist
; np
; np
= np
->next
)
8683 { if (!strncmp(np
->id
, tag
, n
) && !np
->id
[n
])
8691 /******************************************************************************/
8693 static struct soap_nlist
*
8694 soap_push_ns(struct soap
*soap
, const char *id
, const char *ns
, short utilized
)
8695 { register struct soap_nlist
*np
;
8697 if (soap_tagsearch(soap
->c14nexclude
, id
))
8700 { for (np
= soap
->nlist
; np
; np
= np
->next
)
8701 { if (!strcmp(np
->id
, id
) && (!np
->ns
|| !strcmp(np
->ns
, ns
)))
8705 { if ((np
->level
< soap
->level
|| !np
->ns
) && np
->index
== 1)
8711 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap
->level
, id
, ns
?ns
:"(null)", utilized
));
8717 np
= (struct soap_nlist
*)SOAP_MALLOC(soap
, sizeof(struct soap_nlist
) + n
+ k
+ 1);
8719 { soap
->error
= SOAP_EOM
;
8722 np
->next
= soap
->nlist
;
8726 np
->ns
= strcpy(np
->id
+ n
+ 1, ns
);
8729 np
->level
= soap
->level
;
8730 np
->index
= utilized
;
8735 /******************************************************************************/
8738 soap_utilize_ns(struct soap
*soap
, const char *tag
, size_t n
)
8739 { register struct soap_nlist
*np
= soap_lookup_ns(soap
, tag
, n
);
8740 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Utilizing namespace of '%s'\n", tag
));
8742 { if (np
->index
== 0)
8743 soap_push_ns(soap
, np
->id
, np
->ns
, 1);
8745 else if (strncmp(tag
, "xml", 3))
8746 { strncpy(soap
->tmpbuf
, tag
, n
);
8747 soap
->tmpbuf
[n
] = '\0';
8748 soap_push_ns(soap
, soap
->tmpbuf
, NULL
, 1);
8753 /******************************************************************************/
8758 soap_element(struct soap
*soap
, const char *tag
, int id
, const char *type
)
8761 register const char *s
;
8763 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element begin tag='%s' id='%d' type='%s'\n", tag
, id
, type
?type
:SOAP_STR_EOS
));
8766 if (soap
->wsuid
&& soap_tagsearch(soap
->wsuid
, tag
))
8768 for (s
= tag
, i
= 0; *s
&& i
< sizeof(soap
->tag
); s
++, i
++)
8769 soap
->tag
[i
] = *s
== ':' ? '-' : *s
;
8770 soap
->tag
[sizeof(soap
->tag
) - 1] = '\0';
8771 if (soap_set_attr(soap
, "wsu:Id", soap
->tag
, 1))
8775 if (soap
->part
== SOAP_BEGIN_SECURITY
&& (soap
->mode
& SOAP_XML_CANONICAL
) && !(soap
->mode
& SOAP_DOM_ASIS
))
8776 { register struct soap_nlist
*np
;
8777 /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */
8778 for (np
= soap
->nlist
; np
; np
= np
->next
)
8779 { if (np
->index
== 2)
8783 if (soap
->mode
& SOAP_XML_DOM
)
8784 { register struct soap_dom_element
*elt
= (struct soap_dom_element
*)soap_malloc(soap
, sizeof(struct soap_dom_element
));
8789 elt
->prnt
= soap
->dom
;
8790 elt
->name
= soap_strdup(soap
, tag
);
8801 { struct soap_dom_element
*p
= soap
->dom
->elts
;
8808 soap
->dom
->elts
= elt
;
8818 { if (!(soap
->mode
& SOAP_XML_CANONICAL
)
8819 && soap_send(soap
, soap
->prolog
? soap
->prolog
: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
8822 else if (soap
->mode
& SOAP_XML_INDENT
)
8823 { if (soap
->ns
== 1 && soap_send_raw(soap
, soap_indent
, soap
->level
< sizeof(soap_indent
) ? soap
->level
: sizeof(soap_indent
) - 1))
8827 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tag
, ':')))
8828 { struct Namespace
*ns
= soap
->local_namespaces
;
8830 if (soap_send_raw(soap
, "<", 1)
8831 || soap_send(soap
, s
+ 1))
8833 if (soap
->nlist
&& !strncmp(soap
->nlist
->id
, tag
, n
) && !soap
->nlist
->id
[n
])
8835 for (; ns
&& ns
->id
; ns
++)
8836 { if (*ns
->id
&& (ns
->out
|| ns
->ns
) && !strncmp(ns
->id
, tag
, n
) && !ns
->id
[n
])
8837 { soap_push_ns(soap
, ns
->id
, ns
->out
? ns
->out
: ns
->ns
, 0);
8838 if (soap_attribute(soap
, "xmlns", ns
->out
? ns
->out
: ns
->ns
))
8846 if (soap_send_raw(soap
, "<", 1)
8847 || soap_send(soap
, tag
))
8853 { struct Namespace
*ns
;
8856 if ((soap
->mode
& SOAP_XML_DEFAULTNS
))
8857 k
= 4; /* only produce the first four required entries */
8859 for (ns
= soap
->local_namespaces
; ns
&& ns
->id
&& k
; ns
++, k
--)
8860 { if (*ns
->id
&& (ns
->out
|| ns
->ns
))
8861 { sprintf(soap
->tmpbuf
, "xmlns:%s", ns
->id
);
8862 if (soap_attribute(soap
, soap
->tmpbuf
, ns
->out
? ns
->out
: ns
->ns
))
8867 soap
->ns
= 1; /* namespace table control: ns = 0 or 2 to start, then 1 to stop dumping the table */
8869 if (soap
->mode
& SOAP_XML_CANONICAL
)
8870 { const char *t
= strchr(tag
, ':');
8872 soap_utilize_ns(soap
, tag
, t
- tag
);
8876 { sprintf(soap
->tmpbuf
, "_%d", id
);
8877 if (soap_attribute(soap
, "id", soap
->tmpbuf
))
8880 if (type
&& *type
&& (!(soap
->mode
& SOAP_XML_SEC
) || soap
->part
== SOAP_IN_BODY
))
8881 { if (soap_attribute(soap
, "xsi:type", type
))
8884 if (soap
->mode
& SOAP_XML_CANONICAL
)
8885 { const char *t
= strchr(type
, ':');
8887 soap_utilize_ns(soap
, type
, t
- type
);
8891 if (soap
->null
&& soap
->position
> 0)
8893 sprintf(soap
->tmpbuf
, "[%d", soap
->positions
[0]);
8894 for (i
= 1; i
< soap
->position
; i
++)
8895 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), ",%d", soap
->positions
[i
]);
8896 strcat(soap
->tmpbuf
, "]");
8897 if (soap_attribute(soap
, "SOAP-ENC:position", soap
->tmpbuf
))
8900 if (soap
->mustUnderstand
)
8901 { if (soap
->actor
&& *soap
->actor
)
8902 { if (soap_attribute(soap
, soap
->version
== 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap
->actor
))
8905 if (soap_attribute(soap
, "SOAP-ENV:mustUnderstand", soap
->version
== 2 ? "true" : "1"))
8907 soap
->mustUnderstand
= 0;
8910 { if (soap
->encodingStyle
&& soap
->local_namespaces
)
8911 { if (!*soap
->encodingStyle
)
8912 { if (soap
->local_namespaces
[1].out
)
8913 soap
->encodingStyle
= soap
->local_namespaces
[1].out
;
8915 soap
->encodingStyle
= soap
->local_namespaces
[1].ns
;
8917 if (soap
->encodingStyle
&& soap_attribute(soap
, "SOAP-ENV:encodingStyle", soap
->encodingStyle
))
8924 if (soap
->part
== SOAP_BEGIN_SECURITY
&& (soap
->mode
& SOAP_XML_CANONICAL
))
8925 soap
->part
= SOAP_IN_SECURITY
;
8930 /******************************************************************************/
8935 soap_element_begin_out(struct soap
*soap
, const char *tag
, int id
, const char *type
)
8938 if (soap_element(soap
, tag
, id
, type
))
8940 return soap_element_start_end_out(soap
, NULL
);
8944 /******************************************************************************/
8946 #ifndef HAVE_STRRCHR
8950 soap_strrchr(const char *s
, int t
)
8951 { register char *r
= NULL
;
8960 /******************************************************************************/
8966 soap_strtol(const char *s
, char **t
, int b
)
8967 { register long n
= 0;
8969 while (*s
> 0 && *s
<= 32)
8979 while ((c
= *s
) && c
>= '0' && c
<= '9')
8980 { if (n
>= 214748364 && (n
> 214748364 || c
>= '8'))
8989 else /* assume b == 16 and value is always positive */
8991 { if (c
>= '0' && c
<= '9')
8993 else if (c
>= 'A' && c
<= 'F')
8995 else if (c
>= 'a' && c
<= 'f')
9011 /******************************************************************************/
9013 #ifndef HAVE_STRTOUL
9017 soap_strtoul(const char *s
, char **t
, int b
)
9018 { unsigned long n
= 0;
9020 while (*s
> 0 && *s
<= 32)
9025 while ((c
= *s
) && c
>= '0' && c
<= '9')
9026 { if (n
>= 429496729 && (n
> 429496729 || c
>= '6'))
9035 { if (c
>= '0' && c
<= '9')
9037 else if (c
>= 'A' && c
<= 'F')
9039 else if (c
>= 'a' && c
<= 'f')
9055 /******************************************************************************/
9060 soap_array_begin_out(struct soap
*soap
, const char *tag
, int id
, const char *type
, const char *offset
)
9061 { if (!type
|| !*type
)
9062 return soap_element_begin_out(soap
, tag
, id
, NULL
);
9063 if (soap_element(soap
, tag
, id
, "SOAP-ENC:Array"))
9065 if (soap
->version
== 2)
9067 s
= soap_strrchr(type
, '[');
9068 if ((size_t)(s
- type
) < sizeof(soap
->tmpbuf
))
9069 { strncpy(soap
->tmpbuf
, type
, s
- type
);
9070 soap
->tmpbuf
[s
- type
] = '\0';
9071 if (soap_attribute(soap
, "SOAP-ENC:itemType", soap
->tmpbuf
))
9073 if (s
&& (soap_attribute(soap
, "SOAP-ENC:arraySize", s
+ 1)))
9078 { if (offset
&& soap_attribute(soap
, "SOAP-ENC:offset", offset
))
9080 if (soap_attribute(soap
, "SOAP-ENC:arrayType", type
))
9084 if ((soap
->mode
& SOAP_XML_CANONICAL
))
9085 { const char *s
= strchr(type
, ':');
9087 soap_utilize_ns(soap
, type
, s
- type
);
9090 return soap_element_start_end_out(soap
, NULL
);
9094 /******************************************************************************/
9099 soap_element_start_end_out(struct soap
*soap
, const char *tag
)
9100 { register struct soap_attribute
*tp
;
9102 if (soap
->mode
& SOAP_XML_CANONICAL
)
9103 { struct soap_nlist
*np
;
9104 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9105 { if (tp
->visible
&& tp
->name
)
9106 { const char *s
= strchr(tp
->name
, ':');
9108 soap_utilize_ns(soap
, tp
->name
, s
- tp
->name
);
9111 for (np
= soap
->nlist
; np
; np
= np
->next
)
9112 { if (np
->index
== 1 && np
->ns
)
9113 { sprintf(soap
->tmpbuf
, "xmlns:%s", np
->id
);
9114 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Enabling utilized binding (level=%u) %s='%s'\n", np
->level
, soap
->tmpbuf
, np
->ns
));
9115 soap_set_attr(soap
, soap
->tmpbuf
, np
->ns
, 1);
9122 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9123 { register struct soap_dom_attribute
**att
;
9124 att
= &soap
->dom
->atts
;
9125 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9127 { *att
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
9130 (*att
)->next
= NULL
;
9131 (*att
)->nstr
= NULL
;
9132 (*att
)->name
= soap_strdup(soap
, tp
->name
);
9133 (*att
)->data
= soap_strdup(soap
, tp
->value
);
9134 (*att
)->wide
= NULL
;
9135 (*att
)->soap
= soap
;
9136 att
= &(*att
)->next
;
9143 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9148 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tp
->name
, ':')))
9149 { size_t n
= s
- tp
->name
;
9150 if (soap
->nlist
&& !strncmp(soap
->nlist
->id
, tp
->name
, n
) && !soap
->nlist
->id
[n
])
9154 if (soap_send(soap
, " ") || soap_send(soap
, s
))
9159 if (soap_send(soap
, " ") || soap_send(soap
, tp
->name
))
9161 if (tp
->visible
== 2 && tp
->value
)
9162 if (soap_send_raw(soap
, "=\"", 2)
9163 || soap_string_out(soap
, tp
->value
, tp
->flag
)
9164 || soap_send_raw(soap
, "\"", 1))
9172 if (soap
->mode
& SOAP_XML_CANONICAL
)
9173 { if (soap_send_raw(soap
, ">", 1)
9174 || soap_element_end_out(soap
, tag
))
9179 soap
->level
--; /* decrement level just before /> */
9180 if (soap_send_raw(soap
, "/>", 2))
9184 return soap_send_raw(soap
, ">", 1);
9188 /******************************************************************************/
9193 soap_element_end_out(struct soap
*soap
, const char *tag
)
9200 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element ending tag='%s'\n", tag
));
9202 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9203 { if (soap
->dom
->prnt
)
9204 soap
->dom
= soap
->dom
->prnt
;
9209 if (soap
->mode
& SOAP_XML_CANONICAL
)
9210 soap_pop_namespace(soap
);
9211 if (soap
->mode
& SOAP_XML_INDENT
)
9213 { if (soap_send_raw(soap
, soap_indent
, soap
->level
< sizeof(soap_indent
) ? soap
->level
: sizeof(soap_indent
) - 1))
9218 if ((soap
->mode
& SOAP_XML_DEFAULTNS
) && (s
= strchr(tag
, ':')))
9219 { soap_pop_namespace(soap
);
9223 if (soap_send_raw(soap
, "</", 2)
9224 || soap_send(soap
, tag
))
9226 soap
->level
--; /* decrement level just before > */
9227 return soap_send_raw(soap
, ">", 1);
9231 /******************************************************************************/
9236 soap_element_ref(struct soap
*soap
, const char *tag
, int id
, int href
)
9237 { register int n
= 0;
9238 const char *s
= "href";
9239 if (soap
->version
== 2)
9240 { s
= "SOAP-ENC:ref";
9243 sprintf(soap
->href
, "#_%d", href
);
9244 return soap_element_href(soap
, tag
, id
, s
, soap
->href
+ n
);
9248 /******************************************************************************/
9253 soap_element_href(struct soap
*soap
, const char *tag
, int id
, const char *ref
, const char *val
)
9254 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element '%s' reference %s='%s'\n", tag
, ref
, val
));
9255 if (soap_element(soap
, tag
, id
, NULL
)
9256 || soap_attribute(soap
, ref
, val
)
9257 || soap_element_start_end_out(soap
, tag
))
9263 /******************************************************************************/
9268 soap_element_null(struct soap
*soap
, const char *tag
, int id
, const char *type
)
9269 { struct soap_attribute
*tp
;
9270 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9273 if (tp
|| (soap
->version
== 2 && soap
->position
> 0) || id
> 0 || (soap
->mode
& SOAP_XML_NIL
))
9274 { if (soap_element(soap
, tag
, id
, type
))
9276 if (!tp
&& soap_attribute(soap
, "xsi:nil", "true"))
9278 return soap_element_start_end_out(soap
, tag
);
9282 soap
->mustUnderstand
= 0;
9287 /******************************************************************************/
9292 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
)
9294 { soap_element_null(soap
, tag
, id
, type
);
9297 #ifndef WITH_NOIDREF
9298 if (soap
->mode
& SOAP_XML_TREE
)
9301 { struct soap_plist
*pp
;
9303 id
= soap_array_pointer_lookup(soap
, p
, a
, n
, t
, &pp
);
9305 id
= soap_pointer_lookup(soap
, p
, t
, &pp
);
9307 { if (soap_is_embedded(soap
, pp
))
9308 { soap_element_ref(soap
, tag
, 0, id
);
9311 if (soap_is_single(soap
, pp
))
9313 soap_set_embedded(soap
, pp
);
9323 /******************************************************************************/
9328 soap_element_result(struct soap
*soap
, const char *tag
)
9329 { if (soap
->version
== 2 && soap
->encodingStyle
)
9330 { if (soap_element(soap
, "SOAP-RPC:result", 0, NULL
)
9331 || soap_attribute(soap
, "xmlns:SOAP-RPC", soap_rpc
)
9332 || soap_element_start_end_out(soap
, NULL
)
9333 || soap_string_out(soap
, tag
, 0)
9334 || soap_element_end_out(soap
, "SOAP-RPC:result"))
9341 /******************************************************************************/
9346 soap_check_result(struct soap
*soap
, const char *tag
)
9347 { if (soap
->version
== 2 && soap
->encodingStyle
)
9348 { soap_instring(soap
, ":result", NULL
, NULL
, 0, 2, -1, -1);
9349 /* just ignore content for compliance reasons, but should compare tag to element's QName value? */
9354 /******************************************************************************/
9359 soap_attribute(struct soap
*soap
, const char *name
, const char *value
)
9361 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Attribute '%s'='%s'\n", name
, value
));
9363 if ((soap
->mode
& SOAP_XML_DOM
) && !(soap
->mode
& SOAP_XML_CANONICAL
) && soap
->dom
)
9364 { register struct soap_dom_attribute
*a
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
9367 a
->next
= soap
->dom
->atts
;
9369 a
->name
= soap_strdup(soap
, name
);
9370 a
->data
= soap_strdup(soap
, value
);
9373 soap
->dom
->atts
= a
;
9378 if (soap
->mode
& SOAP_XML_CANONICAL
)
9379 { /* TODO: consider using this code to handle default namespace bindings
9380 if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
9381 { if (name[5] == ':')
9382 soap_push_ns(soap, name + 6, value, 0);
9384 soap_push_ns(soap, "", value, 0);
9387 if (!strncmp(name
, "xmlns:", 6))
9388 soap_push_ns(soap
, name
+ 6, value
, 0);
9389 else if (soap_set_attr(soap
, name
, value
, 1))
9394 { if (soap_send(soap
, " ") || soap_send(soap
, name
))
9397 if (soap_send_raw(soap
, "=\"", 2)
9398 || soap_string_out(soap
, value
, 1)
9399 || soap_send_raw(soap
, "\"", 1))
9406 /******************************************************************************/
9411 soap_element_begin_in(struct soap
*soap
, const char *tag
, int nillable
, const char *type
)
9412 { if (!soap_peek_element(soap
))
9414 return soap
->error
= SOAP_TAG_MISMATCH
;
9415 if (tag
&& *tag
== '-')
9417 if (!(soap
->error
= soap_match_tag(soap
, soap
->tag
, tag
)))
9419 if (type
&& *soap
->type
&& soap_match_tag(soap
, soap
->type
, type
))
9420 return soap
->error
= SOAP_TYPE
;
9421 if (!nillable
&& soap
->null
&& (soap
->mode
& SOAP_XML_STRICT
))
9422 return soap
->error
= SOAP_NULL
;
9425 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Begin element found (level=%u) '%s'='%s'\n", soap
->level
, soap
->tag
, tag
?tag
:SOAP_STR_EOS
));
9428 else if (soap
->error
== SOAP_NO_TAG
&& tag
&& *tag
== '-')
9429 soap
->error
= SOAP_OK
;
9434 /******************************************************************************/
9439 soap_element_end_in(struct soap
*soap
, const char *tag
)
9440 { register soap_wchar c
;
9443 if (tag
&& *tag
== '-')
9445 if (soap
->error
== SOAP_NO_TAG
)
9446 soap
->error
= SOAP_OK
;
9448 /* this whitespace or mixed content is not insignificant for DOM */
9449 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9450 { if (!soap
->peeked
&& !soap_string_in(soap
, 3, -1, -1))
9452 if (soap
->dom
->prnt
)
9453 soap
->dom
= soap
->dom
->prnt
;
9462 { while (((c
= soap_get(soap
)) != SOAP_TT
))
9463 { if ((int)c
== EOF
)
9464 return soap
->error
= SOAP_EOF
;
9468 { c
= soap_get(soap
);
9472 soap_unget(soap
, c
);
9477 n
= sizeof(soap
->tag
);
9478 while (soap_notblank(c
= soap_get(soap
)))
9484 return soap
->error
= SOAP_EOF
;
9485 while (soap_blank(c
))
9488 return soap
->error
= SOAP_SYNTAX_ERROR
;
9489 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End element found (level=%u) '%s'='%s'\n", soap
->level
, soap
->tag
, tag
?tag
:SOAP_STR_EOS
));
9491 if (tag
&& (soap
->mode
& SOAP_XML_STRICT
))
9492 { soap_pop_namespace(soap
);
9493 if (soap_match_tag(soap
, soap
->tag
, tag
))
9494 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "End element tag name does not match\n"));
9495 return soap
->error
= SOAP_SYNTAX_ERROR
;
9504 /******************************************************************************/
9509 soap_attr_value(struct soap
*soap
, const char *name
, int flag
)
9510 { register struct soap_attribute
*tp
;
9512 return SOAP_STR_EOS
;
9513 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9514 { if (tp
->visible
&& !soap_match_tag(soap
, tp
->name
, name
))
9518 { if (flag
== 2 && (soap
->mode
& SOAP_XML_STRICT
))
9519 soap
->error
= SOAP_PROHIBITED
;
9523 else if (flag
== 1 && (soap
->mode
& SOAP_XML_STRICT
))
9524 soap
->error
= SOAP_REQUIRED
;
9526 soap
->error
= SOAP_OK
;
9531 /******************************************************************************/
9536 soap_set_attr(struct soap
*soap
, const char *name
, const char *value
, int flag
)
9537 { register struct soap_attribute
*tp
;
9540 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Set attribute %s='%s'\n", name
, value
?value
:SOAP_STR_EOS
));
9541 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9542 { if (!strcmp(tp
->name
, name
))
9546 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Allocate attribute %s\n", name
));
9547 if (!(tp
= (struct soap_attribute
*)SOAP_MALLOC(soap
, sizeof(struct soap_attribute
) + strlen(name
))))
9548 return soap
->error
= SOAP_EOM
;
9551 if ((soap
->mode
& SOAP_XML_CANONICAL
))
9552 { struct soap_attribute
**tpp
= &soap
->attributes
;
9553 const char *s
= strchr(name
, ':');
9554 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inserting attribute %s for c14n\n", name
))
9555 if (!strncmp(name
, "xmlns", 5))
9556 { for (; *tpp
; tpp
= &(*tpp
)->next
)
9557 if (strncmp((*tpp
)->name
, "xmlns", 5) || strcmp((*tpp
)->name
+ 5, name
+ 5) > 0)
9561 { for (; *tpp
; tpp
= &(*tpp
)->next
)
9562 if (strncmp((*tpp
)->name
, "xmlns", 5) && ((*tpp
)->ns
|| strcmp((*tpp
)->name
, name
) > 0))
9567 for (; *tpp
; tpp
= &(*tpp
)->next
)
9568 { if (!strncmp((*tpp
)->name
, "xmlns:", 6) && !strncmp((*tpp
)->name
+ 6, name
, s
- name
) && !(*tpp
)->name
[6 + s
- name
])
9570 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Canonicalization: prefix %s=%p (%s)\n", name
, (*tpp
)->ns
, (*tpp
)->ns
));
9571 tp
->ns
= (*tpp
)->ns
;
9574 else if (strncmp((*tpp
)->name
, "xmlns", 5) && (*tpp
)->ns
&& tp
->ns
&& ((k
= strcmp((*tpp
)->ns
, tp
->ns
)) > 0 || (!k
&& strcmp((*tpp
)->name
, name
) > 0)))
9583 { tp
->next
= soap
->attributes
;
9584 soap
->attributes
= tp
;
9586 strcpy(tp
->name
, name
);
9589 else if (tp
->visible
)
9592 else if (value
&& tp
->value
&& tp
->size
<= strlen(value
))
9593 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Free attribute value of %s (free %p)\n", name
, tp
->value
));
9594 SOAP_FREE(soap
, tp
->value
);
9600 { tp
->size
= strlen(value
) + 1;
9601 if (!(tp
->value
= (char*)SOAP_MALLOC(soap
, tp
->size
)))
9602 return soap
->error
= SOAP_EOM
;
9603 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Allocate attribute value for %s (%p)\n", tp
->name
, tp
->value
));
9605 strcpy(tp
->value
, value
);
9606 if (!strncmp(tp
->name
, "xmlns:", 6))
9611 if (soap
->part
!= SOAP_IN_SECURITY
&& !strcmp(name
, "wsu:Id"))
9612 { soap
->part
= SOAP_BEGIN_SECURITY
;
9613 strncpy(soap
->id
, value
, sizeof(soap
->id
));
9614 soap
->id
[sizeof(soap
->id
)-1] = '\0';
9624 /******************************************************************************/
9629 soap_clr_attr(struct soap
*soap
)
9630 { register struct soap_attribute
*tp
;
9632 if ((soap
->mode
& SOAP_XML_CANONICAL
))
9633 { while (soap
->attributes
)
9634 { tp
= soap
->attributes
->next
;
9635 if (soap
->attributes
->value
)
9636 SOAP_FREE(soap
, soap
->attributes
->value
);
9637 SOAP_FREE(soap
, soap
->attributes
);
9638 soap
->attributes
= tp
;
9643 { for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9649 /******************************************************************************/
9652 soap_getattrval(struct soap
*soap
, char *s
, size_t n
, soap_wchar d
)
9653 { register size_t i
;
9654 for (i
= 0; i
< n
; i
++)
9655 { register soap_wchar c
= soap_get(soap
);
9660 soap_unget(soap
, '/');
9667 { soap_unget(soap
, c
);
9693 { soap_unget(soap
, c
);
9699 return soap
->error
= SOAP_EOF
;
9703 return soap
->error
= SOAP_EOM
;
9707 /******************************************************************************/
9713 soap_store_lab(struct soap
*soap
, const char *s
, size_t n
)
9715 return soap_append_lab(soap
, s
, n
);
9720 /******************************************************************************/
9726 soap_append_lab(struct soap
*soap
, const char *s
, size_t n
)
9727 { if (soap
->labidx
+ n
>= soap
->lablen
)
9728 { register char *t
= soap
->labbuf
;
9729 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap
->lablen
));
9730 if (soap
->lablen
== 0)
9731 soap
->lablen
= SOAP_LABLEN
;
9732 while (soap
->labidx
+ n
>= soap
->lablen
)
9734 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, ", new size=%lu\n", (unsigned long)soap
->lablen
));
9735 soap
->labbuf
= (char*)SOAP_MALLOC(soap
, soap
->lablen
);
9739 return soap
->error
= SOAP_EOM
;
9742 { memcpy(soap
->labbuf
, t
, soap
->labidx
);
9747 { memcpy(soap
->labbuf
+ soap
->labidx
, s
, n
);
9755 /******************************************************************************/
9760 soap_peek_element(struct soap
*soap
)
9763 register struct soap_dom_attribute
**att
= NULL
;
9764 register char *lead
= NULL
;
9766 register struct soap_attribute
*tp
, *tq
= NULL
;
9767 register const char *t
;
9769 register soap_wchar c
;
9773 return soap
->error
= SOAP_NO_TAG
;
9778 soap
->href
[0] = '\0';
9779 soap
->type
[0] = '\0';
9780 soap
->arrayType
[0] = '\0';
9781 soap
->arraySize
[0] = '\0';
9782 soap
->arrayOffset
[0] = '\0';
9787 soap
->mustUnderstand
= 0;
9789 if ((c
= soap_getchar(soap
)) != 0xEF || (c
= soap_get1(soap
)) != 0xBB || (c
= soap_get1(soap
)) != 0xBF)
9790 soap_unget(soap
, c
);
9793 /* whitespace leading to start tag is not insignificant for DOM */
9797 { if (soap_append_lab(soap
, NULL
, 0))
9799 s
= soap
->labbuf
+ soap
->labidx
;
9800 i
= soap
->lablen
- soap
->labidx
;
9801 soap
->labidx
= soap
->lablen
;
9802 while (soap_blank(c
) && i
--)
9807 while (soap_blank(c
));
9810 lead
= soap
->labbuf
;
9814 while (soap_blank(c
))
9818 { *soap
->tag
= '\0';
9820 return soap
->error
= SOAP_EOF
;
9821 soap_unget(soap
, c
);
9823 /* whitespace leading to end tag is not insignificant for DOM */
9824 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
9825 soap
->dom
->tail
= soap_strdup(soap
, lead
);
9827 return soap
->error
= SOAP_NO_TAG
;
9830 do c
= soap_get1(soap
);
9831 while (soap_blank(c
));
9832 i
= sizeof(soap
->tag
);
9833 while (c
!= '>' && c
!= '/' && soap_notblank(c
) && (int)c
!= EOF
)
9836 c
= soap_get1(soap
);
9838 while (soap_blank(c
))
9839 c
= soap_get1(soap
);
9842 if (soap
->mode
& SOAP_XML_DOM
)
9843 { register struct soap_dom_element
*elt
;
9844 elt
= (struct soap_dom_element
*)soap_malloc(soap
, sizeof(struct soap_dom_element
));
9849 elt
->name
= soap_strdup(soap
, soap
->tag
);
9850 elt
->prnt
= soap
->dom
;
9857 elt
->head
= soap_strdup(soap
, lead
);
9861 { struct soap_dom_element
*p
= soap
->dom
->elts
;
9868 soap
->dom
->elts
= elt
;
9874 soap_pop_namespace(soap
);
9875 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
9877 while ((int)c
!= EOF
&& c
!= '>' && c
!= '/')
9879 i
= sizeof(soap
->tmpbuf
);
9880 while (c
!= '=' && c
!= '>' && c
!= '/' && soap_notblank(c
) && (int)c
!= EOF
)
9883 c
= soap_get1(soap
);
9886 if (i
== sizeof(soap
->tmpbuf
))
9887 return soap
->error
= SOAP_SYNTAX_ERROR
;
9889 /* add attribute name to dom */
9891 { *att
= (struct soap_dom_attribute
*)soap_malloc(soap
, sizeof(struct soap_dom_attribute
));
9894 (*att
)->next
= NULL
;
9895 (*att
)->nstr
= NULL
;
9896 (*att
)->name
= soap_strdup(soap
, soap
->tmpbuf
);
9897 (*att
)->data
= NULL
;
9898 (*att
)->wide
= NULL
;
9899 (*att
)->soap
= soap
;
9902 if (!strncmp(soap
->tmpbuf
, "xmlns", 5))
9903 { if (soap
->tmpbuf
[5] == ':')
9904 t
= soap
->tmpbuf
+ 6;
9905 else if (soap
->tmpbuf
[5])
9913 for (tp
= soap
->attributes
; tp
; tq
= tp
, tp
= tp
->next
)
9914 { if (!SOAP_STRCMP(tp
->name
, soap
->tmpbuf
))
9918 { tp
= (struct soap_attribute
*)SOAP_MALLOC(soap
, sizeof(struct soap_attribute
) + strlen(soap
->tmpbuf
));
9920 return soap
->error
= SOAP_EOM
;
9921 strcpy(tp
->name
, soap
->tmpbuf
);
9924 /* if attribute name is qualified, append it to the end of the list */
9925 if (tq
&& strchr(soap
->tmpbuf
, ':'))
9930 { tp
->next
= soap
->attributes
;
9931 soap
->attributes
= tp
;
9934 while (soap_blank(c
))
9935 c
= soap_get1(soap
);
9937 { do c
= soap_getutf8(soap
);
9938 while (soap_blank(c
));
9939 if (c
!= SOAP_QT
&& c
!= SOAP_AP
)
9940 { soap_unget(soap
, c
);
9941 c
= ' '; /* blank delimiter */
9943 if (soap_getattrval(soap
, tp
->value
, tp
->size
, c
))
9946 if (soap
->error
!= SOAP_EOM
)
9948 soap
->error
= SOAP_OK
;
9949 if (soap_store_lab(soap
, tp
->value
, tp
->size
))
9952 SOAP_FREE(soap
, tp
->value
);
9954 { if (soap_getattrval(soap
, soap
->labbuf
+ soap
->labidx
, soap
->lablen
- soap
->labidx
, c
))
9955 { if (soap
->error
!= SOAP_EOM
)
9957 soap
->error
= SOAP_OK
;
9958 soap
->labidx
= soap
->lablen
;
9959 if (soap_append_lab(soap
, NULL
, 0))
9966 tp
->size
= soap
->lablen
;
9968 { tp
->size
= strlen(soap
->labbuf
) + 1;
9969 if (tp
->size
< SOAP_LABLEN
)
9970 tp
->size
= SOAP_LABLEN
;
9972 if (!(tp
->value
= (char*)SOAP_MALLOC(soap
, tp
->size
)))
9973 return soap
->error
= SOAP_EOM
;
9974 strcpy(tp
->value
, soap
->labbuf
);
9977 if (soap
->error
!= SOAP_EOM
)
9979 soap
->error
= SOAP_OK
;
9980 if (soap_new_block(soap
) == NULL
)
9983 { if (!(s
= (char*)soap_push_block(soap
, NULL
, SOAP_BLKLEN
)))
9985 if (soap_getattrval(soap
, s
, SOAP_BLKLEN
, c
))
9986 { if (soap
->error
!= SOAP_EOM
)
9988 soap
->error
= SOAP_OK
;
9993 n
= tp
->size
+ soap
->blist
->size
;
9994 if (!(s
= (char*)SOAP_MALLOC(soap
, n
)))
9995 return soap
->error
= SOAP_EOM
;
9997 { memcpy(s
, tp
->value
, tp
->size
);
9998 SOAP_FREE(soap
, tp
->value
);
10000 soap_save_block(soap
, NULL
, s
+ tp
->size
, 0);
10005 do c
= soap_get1(soap
);
10006 while (soap_blank(c
));
10007 tp
->visible
= 2; /* seen this attribute w/ value */
10010 (*att
)->data
= soap_strdup(soap
, tp
->value
);
10014 tp
->visible
= 1; /* seen this attribute w/o value */
10017 att
= &(*att
)->next
;
10019 if (t
&& tp
->value
)
10020 { if (soap_push_namespace(soap
, t
, tp
->value
) == NULL
)
10021 return soap
->error
;
10026 { soap
->dom
->nstr
= soap_current_namespace(soap
, soap
->tag
);
10027 for (att
= &soap
->dom
->atts
; *att
; att
= &(*att
)->next
)
10028 (*att
)->nstr
= soap_current_namespace(soap
, (*att
)->name
);
10032 return soap
->error
= SOAP_EOF
;
10033 if (!(soap
->body
= (c
!= '/')))
10034 do c
= soap_get1(soap
);
10035 while (soap_blank(c
));
10037 if (soap
->mode
& SOAP_XML_DOM
)
10038 { if (!soap
->body
&& soap
->dom
->prnt
)
10039 soap
->dom
= soap
->dom
->prnt
;
10042 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10043 { if (tp
->visible
&& tp
->value
)
10045 #ifndef WITH_NOIDREF
10046 if (!strcmp(tp
->name
, "id"))
10047 { if ((soap
->version
> 0 && !(soap
->mode
& SOAP_XML_TREE
))
10048 || (soap
->mode
& SOAP_XML_GRAPH
))
10050 strncpy(soap
->id
+ 1, tp
->value
, sizeof(soap
->id
) - 2);
10051 soap
->id
[sizeof(soap
->id
)-1] = '\0';
10054 else if (!strcmp(tp
->name
, "href"))
10055 { if (soap
->version
== 1
10056 || (soap
->mode
& SOAP_XML_GRAPH
)
10057 || (soap
->mode
& SOAP_ENC_MTOM
)
10058 || (soap
->mode
& SOAP_ENC_DIME
))
10059 { strncpy(soap
->href
, tp
->value
, sizeof(soap
->href
) - 1);
10060 soap
->href
[sizeof(soap
->href
)-1] = '\0';
10065 if (!soap_match_tag(soap
, tp
->name
, "xsi:type"))
10066 { strncpy(soap
->type
, tp
->value
, sizeof(soap
->type
) - 1);
10067 soap
->type
[sizeof(soap
->type
)-1] = '\0';
10069 else if ((!soap_match_tag(soap
, tp
->name
, "xsi:null")
10070 || !soap_match_tag(soap
, tp
->name
, "xsi:nil"))
10071 && (!strcmp(tp
->value
, "1")
10072 || !strcmp(tp
->value
, "true")))
10075 else if (soap
->version
== 1)
10076 { if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:arrayType"))
10077 { s
= soap_strrchr(tp
->value
, '[');
10078 if (s
&& (size_t)(s
- tp
->value
) < sizeof(soap
->arrayType
))
10079 { strncpy(soap
->arrayType
, tp
->value
, s
- tp
->value
);
10080 soap
->arrayType
[s
- tp
->value
] = '\0';
10081 strncpy(soap
->arraySize
, s
, sizeof(soap
->arraySize
) - 1);
10084 strncpy(soap
->arrayType
, tp
->value
, sizeof(soap
->arrayType
) - 1);
10085 soap
->arraySize
[sizeof(soap
->arrayType
)-1] = '\0';
10086 soap
->arrayType
[sizeof(soap
->arrayType
)-1] = '\0';
10088 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:offset"))
10089 strncpy(soap
->arrayOffset
, tp
->value
, sizeof(soap
->arrayOffset
));
10090 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:position"))
10091 soap
->position
= soap_getposition(tp
->value
, soap
->positions
);
10092 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:root"))
10093 soap
->root
= ((!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")));
10094 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:mustUnderstand")
10095 && (!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")))
10096 soap
->mustUnderstand
= 1;
10097 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:actor"))
10098 { if ((!soap
->actor
|| strcmp(soap
->actor
, tp
->value
))
10099 && strcmp(tp
->value
, "http://schemas.xmlsoap.org/soap/actor/next"))
10103 else if (soap
->version
== 2)
10105 #ifndef WITH_NOIDREF
10106 if (!strcmp(tp
->name
, "ref")
10107 || !soap_match_tag(soap
, tp
->name
, "SOAP-ENC:ref"))
10108 { *soap
->href
= '#';
10109 strncpy(soap
->href
+ 1, tp
->value
, sizeof(soap
->href
) - 2);
10110 soap
->href
[sizeof(soap
->href
)-1] = '\0';
10114 if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:itemType"))
10115 strncpy(soap
->arrayType
, tp
->value
, sizeof(soap
->arrayType
) - 1);
10116 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENC:arraySize"))
10117 strncpy(soap
->arraySize
, tp
->value
, sizeof(soap
->arraySize
) - 1);
10118 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:mustUnderstand")
10119 && (!strcmp(tp
->value
, "1") || !strcmp(tp
->value
, "true")))
10120 soap
->mustUnderstand
= 1;
10121 else if (!soap_match_tag(soap
, tp
->name
, "SOAP-ENV:role"))
10122 { if ((!soap
->actor
|| strcmp(soap
->actor
, tp
->value
))
10123 && strcmp(tp
->value
, "http://www.w3.org/2003/05/soap-envelope/role/next"))
10128 { if (!soap_match_tag(soap
, tp
->name
, "wsdl:required") && !strcmp(tp
->value
, "true"))
10129 soap
->mustUnderstand
= 1;
10133 return soap
->error
= SOAP_OK
;
10137 /******************************************************************************/
10142 soap_retry(struct soap
*soap
)
10143 { soap
->error
= SOAP_OK
;
10148 /******************************************************************************/
10153 soap_revert(struct soap
*soap
)
10154 { if (!soap
->peeked
)
10155 { soap
->peeked
= 1;
10159 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Reverting last element (level=%u)\n", soap
->level
));
10163 /******************************************************************************/
10168 soap_string_out(struct soap
*soap
, const char *s
, int flag
)
10169 { register const char *t
;
10170 register soap_wchar c
;
10171 register soap_wchar mask
= (soap_wchar
)0xFFFFFF80UL
;
10173 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10174 { soap
->dom
->data
= soap_strdup(soap
, s
);
10178 if (flag
== 2 || soap
->mode
& SOAP_C_UTFSTRING
)
10186 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "	", 5))
10187 return soap
->error
;
10192 if (flag
|| !(soap
->mode
& SOAP_XML_CANONICAL
))
10193 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "
", 5))
10194 return soap
->error
;
10199 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "
", 5))
10200 return soap
->error
;
10204 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "&", 5))
10205 return soap
->error
;
10209 if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, "<", 4))
10210 return soap
->error
;
10215 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, ">", 4))
10216 return soap
->error
;
10222 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_send_raw(soap
, """, 6))
10223 return soap
->error
;
10228 #ifndef WITH_LEANER
10230 if (soap
->mode
& SOAP_C_MBSTRING
)
10232 register int m
= mbtowc(&wc
, t
- 1, MB_CUR_MAX
);
10233 if (m
> 0 && wc
!= c
)
10234 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_pututf8(soap
, wc
))
10235 return soap
->error
;
10242 #ifndef WITH_NOSTRINGTOUTF8
10243 if ((c
& mask
) || !(c
& 0xFFFFFFE0UL
))
10244 { if (soap_send_raw(soap
, s
, t
- s
- 1) || soap_pututf8(soap
, (unsigned char)c
))
10245 return soap
->error
;
10251 return soap_send_raw(soap
, s
, t
- s
- 1);
10255 /******************************************************************************/
10260 soap_string_in(struct soap
*soap
, int flag
, long minlen
, long maxlen
)
10261 { register char *s
;
10264 register long l
= 0;
10265 register int n
= 0, f
= 0, m
= 0;
10266 register soap_wchar c
;
10267 #if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
10268 char buf
[MB_LEN_MAX
> 8 ? MB_LEN_MAX
: 8];
10272 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Reading string content, flag=%d\n", flag
));
10273 if (soap
->peeked
&& *soap
->tag
)
10276 struct soap_attribute
*tp
;
10277 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String content includes tag '%s' and attributes\n", soap
->tag
));
10280 t
[sizeof(soap
->tmpbuf
)-1] = '\0';
10281 strncpy(t
+ 1, soap
->tag
, sizeof(soap
->tmpbuf
) - 2);
10283 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10285 { if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
10288 strcpy(t
, tp
->name
);
10290 if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
10291 break; /* too many or large attribute values */
10295 strcpy(t
, tp
->value
);
10306 m
= (int)strlen(soap
->tmpbuf
);
10315 { register int state
= 0;
10317 soap
->labidx
= 0; /* use look-aside buffer */
10319 if (soap_new_block(soap
) == NULL
)
10326 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
10328 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
10329 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
10330 soap
->labidx
= soap
->lablen
; /* claim this space */
10332 register size_t k
= SOAP_BLKLEN
;
10333 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
10336 for (i
= 0; i
< k
; i
++)
10338 { *s
++ = *t
++; /* copy multibyte characters */
10342 c
= soap_getchar(soap
);
10345 if (c
>= 0x80 && state
!= 1 && !(soap
->mode
& SOAP_ENC_LATIN
))
10346 { soap_unget(soap
, c
);
10347 c
= soap_getutf8(soap
);
10348 if (soap
->mode
& SOAP_C_UTFSTRING
)
10352 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
10354 { if (c
< 0x010000)
10355 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
10357 { if (c
< 0x200000)
10358 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
10360 { if (c
< 0x04000000)
10361 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
10363 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
10364 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
10366 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
10368 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
10370 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
10372 *t
++ = (char)(0x80 | (c
& 0x3F));
10373 m
= (int)(t
- buf
) - 1;
10452 { c
= soap_getchar(soap
);
10455 soap_unget(soap
, c
);
10460 c
= soap_getchar(soap
);
10469 { c
= soap_getchar(soap
);
10471 { do c
= soap_getchar(soap
);
10472 while ((int)c
!= EOF
&& c
!= '[');
10475 t
= (char*)"![CDATA[";
10480 { if ((c
= soap_getchar(soap
)) == '-')
10484 soap_unget(soap
, c
);
10489 soap_unget(soap
, c
);
10496 else if (f
&& n
== 0)
10497 { soap_revget1(soap
);
10503 soap_unget(soap
, c
);
10513 #ifndef WITH_LEANER
10515 if (soap
->mode
& SOAP_C_MBSTRING
)
10516 { m
= wctomb(buf
, c
& 0x7FFFFFFF);
10517 if (m
>= 1 && m
<= (int)MB_CUR_MAX
)
10523 { *s
++ = SOAP_UNKNOWN_CHAR
;
10530 *s
++ = (char)(c
& 0xFF);
10533 if (maxlen
>= 0 && l
> maxlen
)
10534 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
10535 soap
->error
= SOAP_LENGTH
;
10543 soap
->labidx
= 0; /* use look-aside buffer */
10545 if (soap_new_block(soap
) == NULL
)
10552 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
10554 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
10555 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
10556 soap
->labidx
= soap
->lablen
; /* claim this space */
10558 register size_t k
= SOAP_BLKLEN
;
10559 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
10562 for (i
= 0; i
< k
; i
++)
10564 { *s
++ = *t
++; /* copy multibyte characters */
10568 if (soap
->mode
& SOAP_C_UTFSTRING
)
10569 { if (((c
= soap_get(soap
)) & 0x80000000) && c
>= -0x7FFFFF80 && c
< SOAP_AP
)
10573 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
10575 { if (c
< 0x010000)
10576 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
10578 { if (c
< 0x200000)
10579 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
10581 { if (c
< 0x04000000)
10582 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
10584 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
10585 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
10587 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
10589 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
10591 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
10593 *t
++ = (char)(0x80 | (c
& 0x3F));
10594 m
= (int)(t
- buf
) - 1;
10601 c
= soap_getutf8(soap
);
10629 { c
= soap_get(soap
);
10632 soap_unget(soap
, c
);
10636 case (soap_wchar
)('<' | 0x80000000):
10645 case (soap_wchar
)('>' | 0x80000000):
10654 case (soap_wchar
)('&' | 0x80000000):
10663 case (soap_wchar
)('"' | 0x80000000):
10668 t
= (char*)"quot;";
10672 case (soap_wchar
)('\'' | 0x80000000):
10677 t
= (char*)"apos;";
10684 #ifndef WITH_LEANER
10686 if (soap
->mode
& SOAP_C_MBSTRING
)
10687 { m
= wctomb(buf
, c
& 0x7FFFFFFF);
10688 if (m
>= 1 && m
<= (int)MB_CUR_MAX
)
10694 { *s
++ = SOAP_UNKNOWN_CHAR
;
10701 *s
++ = (char)(c
& 0xFF);
10704 if (maxlen
>= 0 && l
> maxlen
)
10705 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
10706 soap
->error
= SOAP_LENGTH
;
10712 soap_unget(soap
, c
);
10715 t
= soap_strdup(soap
, soap
->labbuf
);
10717 soap_size_block(soap
, NULL
, i
+1);
10718 t
= soap_save_block(soap
, NULL
, 0);
10721 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too short: %ld chars, minlen=%ld\n", l
, minlen
));
10722 soap
->error
= SOAP_LENGTH
;
10726 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10728 soap
->dom
->tail
= t
;
10730 soap
->dom
->data
= t
;
10734 if (soap_s2QName(soap
, t
, &t
, minlen
, maxlen
))
10740 /******************************************************************************/
10741 #ifndef WITH_LEANER
10746 soap_wstring_out(struct soap
*soap
, const wchar_t *s
, int flag
)
10749 register soap_wchar c
;
10751 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10752 { wchar_t *r
= (wchar_t*)s
;
10756 soap
->dom
->wide
= r
= (wchar_t*)soap_malloc(soap
, n
* sizeof(wchar_t));
10772 if (flag
|| !(soap
->mode
& SOAP_XML_CANONICAL
))
10799 if (c
>= 0x20 && c
< 0x80)
10801 if (soap_send_raw(soap
, &tmp
, 1))
10802 return soap
->error
;
10804 else if (soap_pututf8(soap
, (unsigned long)c
))
10805 return soap
->error
;
10808 if (soap_send(soap
, t
))
10809 return soap
->error
;
10816 /******************************************************************************/
10817 #ifndef WITH_LEANER
10822 soap_wstring_in(struct soap
*soap
, int flag
, long minlen
, long maxlen
)
10824 register int i
, n
= 0, f
= 0;
10825 register long l
= 0;
10826 register soap_wchar c
;
10828 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Reading wide string content\n"));
10833 struct soap_attribute
*tp
;
10836 t
[sizeof(soap
->tmpbuf
)-1] = '\0';
10837 strncpy(t
+ 1, soap
->tag
, sizeof(soap
->tmpbuf
) - 2);
10839 for (tp
= soap
->attributes
; tp
; tp
= tp
->next
)
10841 { if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
10844 strcpy(t
, tp
->name
);
10846 if (t
>= soap
->tmpbuf
+ sizeof(soap
->tmpbuf
) - 2)
10851 strcpy(t
, tp
->value
);
10869 if (soap_new_block(soap
) == NULL
)
10872 { if (!(s
= (wchar_t*)soap_push_block(soap
, NULL
, sizeof(wchar_t)*SOAP_BLKLEN
)))
10874 for (i
= 0; i
< SOAP_BLKLEN
; i
++)
10876 { *s
++ = (wchar_t)*t
++;
10881 c
= soap_getutf8(soap
);
10889 soap_unget(soap
, '/');
10908 { c
= soap_getutf8(soap
);
10911 soap_unget(soap
, c
);
10917 *s
++ = (soap_wchar
)'<';
10919 { *s
++ = (soap_wchar
)'&';
10925 *s
++ = (soap_wchar
)'>';
10927 { *s
++ = (soap_wchar
)'&';
10933 *s
++ = (soap_wchar
)'"';
10935 { *s
++ = (soap_wchar
)'&';
10936 t
= (char*)"quot;";
10942 *s
++ = (wchar_t)c
& 0x7FFFFFFF;
10945 if (maxlen
>= 0 && l
> maxlen
)
10946 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too long: maxlen=%ld\n", maxlen
));
10947 soap
->error
= SOAP_LENGTH
;
10953 soap_unget(soap
, c
);
10955 soap_size_block(soap
, NULL
, sizeof(wchar_t) * (i
+ 1));
10957 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "String too short: %ld chars, minlen=%ld\n", l
, minlen
));
10958 soap
->error
= SOAP_LENGTH
;
10961 s
= (wchar_t*)soap_save_block(soap
, NULL
, NULL
, 0);
10963 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
10964 soap
->dom
->wide
= s
;
10971 /******************************************************************************/
10976 soap_int2s(struct soap
*soap
, int n
)
10977 { return soap_long2s(soap
, (long)n
);
10981 /******************************************************************************/
10986 soap_outint(struct soap
*soap
, const char *tag
, int id
, const int *p
, const char *type
, int n
)
10987 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
10988 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
10989 return soap
->error
;
10990 return soap_element_end_out(soap
, tag
);
10994 /******************************************************************************/
10999 soap_s2int(struct soap
*soap
, const char *s
, int *p
)
11007 *p
= (int)soap_strtol(s
, &r
, 10);
11008 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11011 || soap_errno
== SOAP_ERANGE
11015 soap
->error
= SOAP_TYPE
;
11017 return soap
->error
;
11021 /******************************************************************************/
11026 soap_inint(struct soap
*soap
, const char *tag
, int *p
, const char *type
, int t
)
11027 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11031 && soap_match_tag(soap
, soap
->type
, type
)
11032 && soap_match_tag(soap
, soap
->type
, ":int")
11033 && soap_match_tag(soap
, soap
->type
, ":short")
11034 && soap_match_tag(soap
, soap
->type
, ":byte"))
11035 { soap
->error
= SOAP_TYPE
;
11040 p
= (int*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(int), 0, NULL
, NULL
, NULL
);
11042 p
= (int*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(int), 0, NULL
);
11044 { if (soap_s2int(soap
, soap_value(soap
), p
))
11047 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11053 /******************************************************************************/
11058 soap_long2s(struct soap
*soap
, long n
)
11059 { sprintf(soap
->tmpbuf
, "%ld", n
);
11060 return soap
->tmpbuf
;
11064 /******************************************************************************/
11069 soap_outlong(struct soap
*soap
, const char *tag
, int id
, const long *p
, const char *type
, int n
)
11070 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11071 || soap_string_out(soap
, soap_long2s(soap
, *p
), 0))
11072 return soap
->error
;
11073 return soap_element_end_out(soap
, tag
);
11077 /******************************************************************************/
11082 soap_s2long(struct soap
*soap
, const char *s
, long *p
)
11090 *p
= soap_strtol(s
, &r
, 10);
11091 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11094 || soap_errno
== SOAP_ERANGE
11098 soap
->error
= SOAP_TYPE
;
11100 return soap
->error
;
11104 /******************************************************************************/
11109 soap_inlong(struct soap
*soap
, const char *tag
, long *p
, const char *type
, int t
)
11110 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11114 && soap_match_tag(soap
, soap
->type
, type
)
11115 && soap_match_tag(soap
, soap
->type
, ":int")
11116 && soap_match_tag(soap
, soap
->type
, ":short")
11117 && soap_match_tag(soap
, soap
->type
, ":byte"))
11118 { soap
->error
= SOAP_TYPE
;
11123 p
= (long*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(long), 0, NULL
, NULL
, NULL
);
11125 p
= (long*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(long), 0, NULL
);
11127 { if (soap_s2long(soap
, soap_value(soap
), p
))
11130 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11136 /******************************************************************************/
11141 soap_LONG642s(struct soap
*soap
, LONG64 n
)
11142 { sprintf(soap
->tmpbuf
, SOAP_LONG_FORMAT
, n
);
11143 return soap
->tmpbuf
;
11147 /******************************************************************************/
11152 soap_outLONG64(struct soap
*soap
, const char *tag
, int id
, const LONG64
*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_LONG642s(soap
, *p
), 0))
11155 return soap
->error
;
11156 return soap_element_end_out(soap
, tag
);
11160 /******************************************************************************/
11165 soap_s2LONG64(struct soap
*soap
, const char *s
, LONG64
*p
)
11168 #ifdef HAVE_STRTOLL
11175 *p
= strtoll(s
, &r
, 10);
11176 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11179 || soap_errno
== SOAP_ERANGE
11184 # ifdef HAVE_SSCANF
11185 if (sscanf(s
, SOAP_LONG_FORMAT
, p
) != 1)
11188 soap
->error
= SOAP_TYPE
;
11190 return soap
->error
;
11194 /******************************************************************************/
11199 soap_inLONG64(struct soap
*soap
, const char *tag
, LONG64
*p
, const char *type
, int t
)
11200 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11204 && soap_match_tag(soap
, soap
->type
, type
)
11205 && soap_match_tag(soap
, soap
->type
, ":integer")
11206 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
11207 && soap_match_tag(soap
, soap
->type
, ":negativeInteger")
11208 && soap_match_tag(soap
, soap
->type
, ":nonPositiveInteger")
11209 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
11210 && soap_match_tag(soap
, soap
->type
, ":long")
11211 && soap_match_tag(soap
, soap
->type
, ":int")
11212 && soap_match_tag(soap
, soap
->type
, ":short")
11213 && soap_match_tag(soap
, soap
->type
, ":byte"))
11214 { soap
->error
= SOAP_TYPE
;
11219 p
= (LONG64
*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(LONG64
), 0, NULL
, NULL
, NULL
);
11221 p
= (LONG64
*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(LONG64
), 0, NULL
);
11223 { if (soap_s2LONG64(soap
, soap_value(soap
), p
))
11226 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11232 /******************************************************************************/
11237 soap_byte2s(struct soap
*soap
, char n
)
11238 { return soap_long2s(soap
, (long)n
);
11242 /******************************************************************************/
11247 soap_outbyte(struct soap
*soap
, const char *tag
, int id
, const char *p
, const char *type
, int n
)
11248 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11249 || soap_string_out(soap
, soap_long2s(soap
, (long)*p
), 0))
11250 return soap
->error
;
11251 return soap_element_end_out(soap
, tag
);
11255 /******************************************************************************/
11260 soap_s2byte(struct soap
*soap
, const char *s
, char *p
)
11264 n
= soap_strtol(s
, &r
, 10);
11265 if (s
== r
|| *r
|| n
< -128 || n
> 127)
11266 soap
->error
= SOAP_TYPE
;
11269 return soap
->error
;
11273 /******************************************************************************/
11278 soap_inbyte(struct soap
*soap
, const char *tag
, char *p
, const char *type
, int t
)
11279 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11283 && soap_match_tag(soap
, soap
->type
, type
)
11284 && soap_match_tag(soap
, soap
->type
, ":byte"))
11285 { soap
->error
= SOAP_TYPE
;
11290 p
= (char*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(char), 0, NULL
, NULL
, NULL
);
11292 p
= (char*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(char), 0, NULL
);
11294 { if (soap_s2byte(soap
, soap_value(soap
), p
))
11297 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11303 /******************************************************************************/
11308 soap_short2s(struct soap
*soap
, short n
)
11309 { return soap_long2s(soap
, (long)n
);
11313 /******************************************************************************/
11318 soap_outshort(struct soap
*soap
, const char *tag
, int id
, const short *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_long2s(soap
, (long)*p
), 0))
11321 return soap
->error
;
11322 return soap_element_end_out(soap
, tag
);
11326 /******************************************************************************/
11331 soap_s2short(struct soap
*soap
, const char *s
, short *p
)
11335 n
= soap_strtol(s
, &r
, 10);
11336 if (s
== r
|| *r
|| n
< -32768 || n
> 32767)
11337 soap
->error
= SOAP_TYPE
;
11340 return soap
->error
;
11344 /******************************************************************************/
11349 soap_inshort(struct soap
*soap
, const char *tag
, short *p
, const char *type
, int t
)
11350 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11354 && soap_match_tag(soap
, soap
->type
, type
)
11355 && soap_match_tag(soap
, soap
->type
, ":short")
11356 && soap_match_tag(soap
, soap
->type
, ":byte"))
11357 { soap
->error
= SOAP_TYPE
;
11362 p
= (short*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(short), 0, NULL
, NULL
, NULL
);
11364 p
= (short*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(short), 0, NULL
);
11366 { if (soap_s2short(soap
, soap_value(soap
), p
))
11369 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11375 /******************************************************************************/
11380 soap_float2s(struct soap
*soap
, float n
)
11382 if (soap_isnan((double)n
))
11384 if (soap_ispinff(n
))
11386 if (soap_isninff(n
))
11389 #if defined(HAVE_SPRINTF_L)
11390 sprintf_l(s
, soap
->c_locale
, soap
->float_format
, n
);
11392 sprintf(s
, soap
->float_format
, n
);
11393 s
= strchr(s
, ','); /* convert decimal comma to DP */
11397 return soap
->tmpbuf
;
11401 /******************************************************************************/
11406 soap_outfloat(struct soap
*soap
, const char *tag
, int id
, const float *p
, const char *type
, int n
)
11407 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11408 || soap_string_out(soap
, soap_float2s(soap
, *p
), 0))
11409 return soap
->error
;
11410 return soap_element_end_out(soap
, tag
);
11414 /******************************************************************************/
11419 soap_s2float(struct soap
*soap
, const char *s
, float *p
)
11422 return soap
->error
= SOAP_TYPE
;
11423 if (!soap_tag_cmp(s
, "INF"))
11425 else if (!soap_tag_cmp(s
, "+INF"))
11427 else if (!soap_tag_cmp(s
, "-INF"))
11429 else if (!soap_tag_cmp(s
, "NaN"))
11433 /* On some systems strtof requires -std=c99 or does not even link: so we try to use strtod first */
11434 #if defined(HAVE_STRTOD_L)
11436 *p
= (float)strtod_l(s
, &r
, soap
->c_locale
);
11438 #elif defined(HAVE_STRTOD)
11440 *p
= (float)strtod(s
, &r
);
11442 #elif defined(HAVE_STRTOF_L)
11444 *p
= strtof_l((char*)s
, &r
, soap
->c_locale
);
11446 #elif defined(HAVE_STRTOF)
11448 *p
= strtof((char*)s
, &r
);
11452 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11453 if (sscanf_l(s
, soap
->c_locale
, "%g", p
) != 1)
11454 soap
->error
= SOAP_TYPE
;
11455 #elif defined(HAVE_SSCANF)
11456 if (sscanf(s
, "%g", p
) != 1)
11457 soap
->error
= SOAP_TYPE
;
11459 soap
->error
= SOAP_TYPE
;
11464 return soap
->error
;
11468 /******************************************************************************/
11470 static int soap_isnumeric(struct soap
*soap
, const char *type
)
11471 { if (soap_match_tag(soap
, soap
->type
, type
)
11472 && soap_match_tag(soap
, soap
->type
, ":float")
11473 && soap_match_tag(soap
, soap
->type
, ":double")
11474 && soap_match_tag(soap
, soap
->type
, ":decimal")
11475 && soap_match_tag(soap
, soap
->type
, ":integer")
11476 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
11477 && soap_match_tag(soap
, soap
->type
, ":negativeInteger")
11478 && soap_match_tag(soap
, soap
->type
, ":nonPositiveInteger")
11479 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
11480 && soap_match_tag(soap
, soap
->type
, ":long")
11481 && soap_match_tag(soap
, soap
->type
, ":int")
11482 && soap_match_tag(soap
, soap
->type
, ":short")
11483 && soap_match_tag(soap
, soap
->type
, ":byte")
11484 && soap_match_tag(soap
, soap
->type
, ":unsignedLong")
11485 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
11486 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
11487 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11488 { soap
->error
= SOAP_TYPE
;
11496 /******************************************************************************/
11501 soap_infloat(struct soap
*soap
, const char *tag
, float *p
, const char *type
, int t
)
11502 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11505 if (*soap
->type
!= '\0' && soap_isnumeric(soap
, type
))
11508 p
= (float*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(float), 0, NULL
, NULL
, NULL
);
11510 p
= (float*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(float), 0, NULL
);
11512 { if (soap_s2float(soap
, soap_value(soap
), p
))
11515 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11521 /******************************************************************************/
11526 soap_double2s(struct soap
*soap
, double n
)
11530 if (soap_ispinfd(n
))
11532 if (soap_isninfd(n
))
11535 #if defined(HAVE_SPRINTF_L)
11536 sprintf_l(s
, soap
->c_locale
, soap
->double_format
, n
);
11538 sprintf(s
, soap
->double_format
, n
);
11539 s
= strchr(s
, ','); /* convert decimal comma to DP */
11543 return soap
->tmpbuf
;
11547 /******************************************************************************/
11552 soap_outdouble(struct soap
*soap
, const char *tag
, int id
, const double *p
, const char *type
, int n
)
11553 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11554 || soap_string_out(soap
, soap_double2s(soap
, *p
), 0))
11555 return soap
->error
;
11556 return soap_element_end_out(soap
, tag
);
11560 /******************************************************************************/
11565 soap_s2double(struct soap
*soap
, const char *s
, double *p
)
11568 return soap
->error
= SOAP_TYPE
;
11569 if (!soap_tag_cmp(s
, "INF"))
11571 else if (!soap_tag_cmp(s
, "+INF"))
11573 else if (!soap_tag_cmp(s
, "-INF"))
11575 else if (!soap_tag_cmp(s
, "NaN"))
11579 #if defined(HAVE_STRTOD_L)
11581 *p
= strtod_l(s
, &r
, soap
->c_locale
);
11583 #elif defined(HAVE_STRTOD)
11585 *p
= strtod(s
, &r
);
11589 #if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
11590 if (sscanf_l(s
, soap
->c_locale
, "%lg", p
) != 1)
11591 soap
->error
= SOAP_TYPE
;
11592 #elif defined(HAVE_SSCANF)
11593 if (sscanf(s
, "%lg", p
) != 1)
11594 soap
->error
= SOAP_TYPE
;
11596 soap
->error
= SOAP_TYPE
;
11601 return soap
->error
;
11605 /******************************************************************************/
11610 soap_indouble(struct soap
*soap
, const char *tag
, double *p
, const char *type
, int t
)
11611 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11614 if (*soap
->type
!= '\0' && soap_isnumeric(soap
, type
))
11617 p
= (double*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(double), 0, NULL
, NULL
, NULL
);
11619 p
= (double*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(double), 0, NULL
);
11621 { if (soap_s2double(soap
, soap_value(soap
), p
))
11624 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11630 /******************************************************************************/
11635 soap_unsignedByte2s(struct soap
*soap
, unsigned char n
)
11636 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
11640 /******************************************************************************/
11645 soap_outunsignedByte(struct soap
*soap
, const char *tag
, int id
, const unsigned char *p
, const char *type
, int n
)
11646 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11647 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
11648 return soap
->error
;
11649 return soap_element_end_out(soap
, tag
);
11653 /******************************************************************************/
11658 soap_s2unsignedByte(struct soap
*soap
, const char *s
, unsigned char *p
)
11662 n
= soap_strtoul(s
, &r
, 10);
11663 if (s
== r
|| *r
|| n
> 255)
11664 soap
->error
= SOAP_TYPE
;
11665 *p
= (unsigned char)n
;
11667 return soap
->error
;
11671 /******************************************************************************/
11676 soap_inunsignedByte(struct soap
*soap
, const char *tag
, unsigned char *p
, const char *type
, int t
)
11677 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11681 && soap_match_tag(soap
, soap
->type
, type
)
11682 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11683 { soap
->error
= SOAP_TYPE
;
11688 p
= (unsigned char*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned char), 0, NULL
, NULL
, NULL
);
11690 p
= (unsigned char*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned char), 0, NULL
);
11692 { if (soap_s2unsignedByte(soap
, soap_value(soap
), p
))
11695 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11701 /******************************************************************************/
11706 soap_unsignedShort2s(struct soap
*soap
, unsigned short n
)
11707 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
11711 /******************************************************************************/
11716 soap_outunsignedShort(struct soap
*soap
, const char *tag
, int id
, const unsigned short *p
, const char *type
, int n
)
11717 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11718 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
11719 return soap
->error
;
11720 return soap_element_end_out(soap
, tag
);
11724 /******************************************************************************/
11729 soap_s2unsignedShort(struct soap
*soap
, const char *s
, unsigned short *p
)
11733 n
= soap_strtoul(s
, &r
, 10);
11734 if (s
== r
|| *r
|| n
> 65535)
11735 soap
->error
= SOAP_TYPE
;
11736 *p
= (unsigned short)n
;
11738 return soap
->error
;
11742 /******************************************************************************/
11747 soap_inunsignedShort(struct soap
*soap
, const char *tag
, unsigned short *p
, const char *type
, int t
)
11748 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11752 && soap_match_tag(soap
, soap
->type
, type
)
11753 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
11754 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11755 { soap
->error
= SOAP_TYPE
;
11760 p
= (unsigned short*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned short), 0, NULL
, NULL
, NULL
);
11762 p
= (unsigned short*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned short), 0, NULL
);
11764 { if (soap_s2unsignedShort(soap
, soap_value(soap
), p
))
11767 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11773 /******************************************************************************/
11778 soap_unsignedInt2s(struct soap
*soap
, unsigned int n
)
11779 { return soap_unsignedLong2s(soap
, (unsigned long)n
);
11783 /******************************************************************************/
11788 soap_outunsignedInt(struct soap
*soap
, const char *tag
, int id
, const unsigned int *p
, const char *type
, int n
)
11789 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11790 || soap_string_out(soap
, soap_unsignedLong2s(soap
, (unsigned long)*p
), 0))
11791 return soap
->error
;
11792 return soap_element_end_out(soap
, tag
);
11796 /******************************************************************************/
11801 soap_s2unsignedInt(struct soap
*soap
, const char *s
, unsigned int *p
)
11809 *p
= (unsigned int)soap_strtoul(s
, &r
, 10);
11810 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11813 || soap_errno
== SOAP_ERANGE
11817 soap
->error
= SOAP_TYPE
;
11819 return soap
->error
;
11823 /******************************************************************************/
11828 soap_inunsignedInt(struct soap
*soap
, const char *tag
, unsigned int *p
, const char *type
, int t
)
11829 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11833 && soap_match_tag(soap
, soap
->type
, type
)
11834 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
11835 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
11836 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11837 { soap
->error
= SOAP_TYPE
;
11842 p
= (unsigned int*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned int), 0, NULL
, NULL
, NULL
);
11844 p
= (unsigned int*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned int), 0, NULL
);
11846 { if (soap_s2unsignedInt(soap
, soap_value(soap
), p
))
11849 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11855 /******************************************************************************/
11860 soap_unsignedLong2s(struct soap
*soap
, unsigned long n
)
11861 { sprintf(soap
->tmpbuf
, "%lu", n
);
11862 return soap
->tmpbuf
;
11866 /******************************************************************************/
11871 soap_outunsignedLong(struct soap
*soap
, const char *tag
, int id
, const unsigned long *p
, const char *type
, int n
)
11872 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
11873 || soap_string_out(soap
, soap_unsignedLong2s(soap
, *p
), 0))
11874 return soap
->error
;
11875 return soap_element_end_out(soap
, tag
);
11879 /******************************************************************************/
11884 soap_s2unsignedLong(struct soap
*soap
, const char *s
, unsigned long *p
)
11892 *p
= soap_strtoul(s
, &r
, 10);
11893 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11896 || soap_errno
== SOAP_ERANGE
11900 soap
->error
= SOAP_TYPE
;
11902 return soap
->error
;
11906 /******************************************************************************/
11911 soap_inunsignedLong(struct soap
*soap
, const char *tag
, unsigned long *p
, const char *type
, int t
)
11912 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
11916 && soap_match_tag(soap
, soap
->type
, type
)
11917 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
11918 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
11919 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
11920 { soap
->error
= SOAP_TYPE
;
11925 p
= (unsigned long*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(unsigned long), 0, NULL
, NULL
, NULL
);
11927 p
= (unsigned long*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(unsigned long), 0, NULL
);
11929 { if (soap_s2unsignedLong(soap
, soap_value(soap
), p
))
11932 if (soap
->body
&& soap_element_end_in(soap
, tag
))
11938 /******************************************************************************/
11943 soap_ULONG642s(struct soap
*soap
, ULONG64 n
)
11944 { sprintf(soap
->tmpbuf
, SOAP_ULONG_FORMAT
, n
);
11945 return soap
->tmpbuf
;
11949 /******************************************************************************/
11954 soap_outULONG64(struct soap
*soap
, const char *tag
, int id
, const ULONG64
*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_ULONG642s(soap
, *p
), 0))
11957 return soap
->error
;
11958 return soap_element_end_out(soap
, tag
);
11962 /******************************************************************************/
11967 soap_s2ULONG64(struct soap
*soap
, const char *s
, ULONG64
*p
)
11970 #ifdef HAVE_STRTOULL
11977 *p
= strtoull(s
, &r
, 10);
11978 if ((s
== r
&& (soap
->mode
& SOAP_XML_STRICT
)) || *r
11981 || soap_errno
== SOAP_ERANGE
11987 if (sscanf(s
, SOAP_ULONG_FORMAT
, p
) != 1)
11990 soap
->error
= SOAP_TYPE
;
11992 return soap
->error
;
11996 /******************************************************************************/
12001 soap_inULONG64(struct soap
*soap
, const char *tag
, ULONG64
*p
, const char *type
, int t
)
12002 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12005 && soap_match_tag(soap
, soap
->type
, type
)
12006 && soap_match_tag(soap
, soap
->type
, ":positiveInteger")
12007 && soap_match_tag(soap
, soap
->type
, ":nonNegativeInteger")
12008 && soap_match_tag(soap
, soap
->type
, ":unsignedLong")
12009 && soap_match_tag(soap
, soap
->type
, ":unsignedInt")
12010 && soap_match_tag(soap
, soap
->type
, ":unsignedShort")
12011 && soap_match_tag(soap
, soap
->type
, ":unsignedByte"))
12012 { soap
->error
= SOAP_TYPE
;
12016 p
= (ULONG64
*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(ULONG64
), 0, NULL
, NULL
, NULL
);
12018 p
= (ULONG64
*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(ULONG64
), 0, NULL
);
12020 { if (soap_s2ULONG64(soap
, soap_value(soap
), p
))
12023 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12029 /******************************************************************************/
12034 soap_s2string(struct soap
*soap
, const char *s
, char **t
, long minlen
, long maxlen
)
12036 { long l
= (long)strlen(s
);
12037 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
12038 return soap
->error
= SOAP_LENGTH
;
12039 if (!(*t
= soap_strdup(soap
, s
)))
12040 return soap
->error
= SOAP_EOM
;
12041 if (!(soap
->mode
& (SOAP_ENC_LATIN
| SOAP_C_UTFSTRING
)))
12043 /* remove non-ASCII chars */
12044 for (s
= *t
; *s
; s
++)
12050 return soap
->error
;
12054 /******************************************************************************/
12059 soap_s2QName(struct soap
*soap
, const char *s
, char **t
, long minlen
, long maxlen
)
12061 { long l
= (long)strlen(s
);
12062 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
12063 return soap
->error
= SOAP_LENGTH
;
12065 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Normalized namespace(s) of QNames '%s'", s
));
12066 /* convert (by prefix normalize prefix) all QNames in s */
12069 struct soap_nlist
*np
;
12070 register const char *p
;
12072 while (*s
&& soap_blank(*s
))
12076 /* find next QName */
12078 while (s
[n
] && !soap_blank(s
[n
]))
12081 /* if there is no namespace stack, or prefix is "xml" then copy string */
12082 if (!np
|| !strncmp(s
, "xml:", 4))
12083 { soap_append_lab(soap
, s
, n
);
12085 else /* we normalize the QName by replacing its prefix */
12086 { for (p
= s
; *p
&& p
< s
+ n
; p
++)
12090 { size_t k
= p
- s
;
12091 while (np
&& (strncmp(np
->id
, s
, k
) || np
->id
[k
]))
12096 { while (np
&& *np
->id
)
12100 /* replace prefix */
12102 { if (np
->index
>= 0 && soap
->local_namespaces
)
12103 { const char *q
= soap
->local_namespaces
[np
->index
].id
;
12105 soap_append_lab(soap
, q
, strlen(q
));
12108 { soap_append_lab(soap
, "\"", 1);
12109 soap_append_lab(soap
, np
->ns
, strlen(np
->ns
));
12110 soap_append_lab(soap
, "\"", 1);
12113 { 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
));
12114 return soap
->error
= SOAP_NAMESPACE
;
12117 else if (s
[n
]) /* no namespace, part of string */
12118 { soap_append_lab(soap
, s
, n
);
12120 else /* no namespace: assume "" namespace */
12121 { soap_append_lab(soap
, "\"\"", 2);
12123 soap_append_lab(soap
, ":", 1);
12124 soap_append_lab(soap
, p
, n
- (p
-s
));
12126 /* advance to next and add spacing */
12129 soap_append_lab(soap
, " ", 1);
12131 soap_append_lab(soap
, SOAP_STR_EOS
, 1);
12132 *t
= soap_strdup(soap
, soap
->labbuf
);
12133 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, " into '%s'\n", *t
));
12135 return soap
->error
;
12139 /******************************************************************************/
12144 soap_QName2s(struct soap
*soap
, const char *s
)
12145 { const char *t
= NULL
;
12147 { soap
->labidx
= 0;
12151 while (*s
&& soap_blank(*s
))
12155 /* find next QName */
12157 while (s
[n
] && !soap_blank(s
[n
]))
12159 /* normal prefix: pass string as is */
12161 { soap_append_lab(soap
, s
, n
);
12163 if ((soap
->mode
& SOAP_XML_CANONICAL
))
12164 { const char *r
= strchr(s
, ':');
12166 soap_utilize_ns(soap
, s
, r
- s
);
12170 else /* URL-based string prefix */
12173 q
= strchr(s
, '"');
12175 { struct Namespace
*p
= soap
->local_namespaces
;
12177 { for (; p
->id
; p
++)
12179 if (!soap_tag_cmp(s
, p
->ns
))
12182 if (!soap_tag_cmp(s
, p
->in
))
12186 /* URL is in the namespace table? */
12188 { soap_append_lab(soap
, p
->id
, strlen(p
->id
));
12190 else /* not in namespace table: create xmlns binding */
12191 { char *r
= soap_strdup(soap
, s
);
12193 sprintf(soap
->tmpbuf
, "xmlns:_%d", soap
->idnum
++);
12194 soap_set_attr(soap
, soap
->tmpbuf
, r
, 1);
12195 soap_append_lab(soap
, soap
->tmpbuf
+ 6, strlen(soap
->tmpbuf
+ 6));
12197 soap_append_lab(soap
, q
+ 1, n
- (q
-s
) - 1);
12200 /* advance to next and add spacing */
12203 soap_append_lab(soap
, " ", 1);
12205 soap_append_lab(soap
, SOAP_STR_EOS
, 1);
12206 t
= soap_strdup(soap
, soap
->labbuf
);
12212 /******************************************************************************/
12217 soap_s2wchar(struct soap
*soap
, const char *s
, wchar_t **t
, long minlen
, long maxlen
)
12221 *t
= r
= (wchar_t*)soap_malloc(soap
, sizeof(wchar_t) * (strlen(s
) + 1));
12223 return soap
->error
= SOAP_EOM
;
12224 if (soap
->mode
& SOAP_ENC_LATIN
)
12226 *r
++ = (wchar_t)*s
++;
12229 { /* Convert UTF8 to wchar */
12231 { register soap_wchar c
, c1
, c2
, c3
, c4
;
12232 c
= (unsigned char)*s
++;
12236 { c1
= (soap_wchar
)*s
++ & 0x3F;
12238 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x1F) << 6) | c1
);
12240 { c2
= (soap_wchar
)*s
++ & 0x3F;
12242 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x0F) << 12) | (c1
<< 6) | c2
);
12244 { c3
= (soap_wchar
)*s
++ & 0x3F;
12246 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x07) << 18) | (c1
<< 12) | (c2
<< 6) | c3
);
12248 { c4
= (soap_wchar
)*s
++ & 0x3F;
12250 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x03) << 24) | (c1
<< 18) | (c2
<< 12) | (c3
<< 6) | c4
);
12252 *r
++ = (wchar_t)(((soap_wchar
)(c
& 0x01) << 30) | (c1
<< 24) | (c2
<< 18) | (c3
<< 12) | (c4
<< 6) | (soap_wchar
)(*s
++ & 0x3F));
12260 l
= (long)(r
- *t
);
12261 if ((maxlen
>= 0 && l
> maxlen
) || l
< minlen
)
12262 return soap
->error
= SOAP_LENGTH
;
12264 return soap
->error
;
12268 /******************************************************************************/
12273 soap_wchar2s(struct soap
*soap
, const wchar_t *s
)
12274 { register soap_wchar c
;
12275 register char *r
, *t
;
12276 const wchar_t *q
= s
;
12279 { if (c
> 0 && c
< 0x80)
12284 r
= t
= (char*)soap_malloc(soap
, n
+ 1);
12286 { /* Convert wchar to UTF8 */
12288 { if (c
> 0 && c
< 0x80)
12292 *t
++ = (char)(0xC0 | ((c
>> 6) & 0x1F));
12294 { if (c
< 0x010000)
12295 *t
++ = (char)(0xE0 | ((c
>> 12) & 0x0F));
12297 { if (c
< 0x200000)
12298 *t
++ = (char)(0xF0 | ((c
>> 18) & 0x07));
12300 { if (c
< 0x04000000)
12301 *t
++ = (char)(0xF8 | ((c
>> 24) & 0x03));
12303 { *t
++ = (char)(0xFC | ((c
>> 30) & 0x01));
12304 *t
++ = (char)(0x80 | ((c
>> 24) & 0x3F));
12306 *t
++ = (char)(0x80 | ((c
>> 18) & 0x3F));
12308 *t
++ = (char)(0x80 | ((c
>> 12) & 0x3F));
12310 *t
++ = (char)(0x80 | ((c
>> 6) & 0x3F));
12312 *t
++ = (char)(0x80 | (c
& 0x3F));
12321 /******************************************************************************/
12326 soap_outstring(struct soap
*soap
, const char *tag
, int id
, char *const*p
, const char *type
, int n
)
12327 { id
= soap_element_id(soap
, tag
, id
, *p
, NULL
, 0, type
, n
);
12329 return soap
->error
;
12330 if (!**p
&& (soap
->mode
& SOAP_C_NILSTRING
))
12331 return soap_element_null(soap
, tag
, id
, type
);
12332 if (soap_element_begin_out(soap
, tag
, id
, type
)
12333 || soap_string_out(soap
, *p
, 0)
12334 || soap_element_end_out(soap
, tag
))
12335 return soap
->error
;
12340 /******************************************************************************/
12345 soap_instring(struct soap
*soap
, const char *tag
, char **p
, const char *type
, int t
, int flag
, long minlen
, long maxlen
)
12346 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12347 { if (!tag
|| *tag
!= '-' || soap
->error
!= SOAP_NO_TAG
)
12349 soap
->error
= SOAP_OK
;
12352 { if (!(p
= (char**)soap_malloc(soap
, sizeof(char*))))
12357 else if (soap
->body
)
12358 { *p
= soap_string_in(soap
, flag
, minlen
, maxlen
);
12359 if (!*p
|| !(char*)soap_id_enter(soap
, soap
->id
, *p
, t
, sizeof(char*), 0, NULL
, NULL
, NULL
))
12361 if (!**p
&& tag
&& *tag
== '-')
12362 { soap
->error
= SOAP_NO_TAG
;
12366 else if (tag
&& *tag
== '-')
12367 { soap
->error
= SOAP_NO_TAG
;
12370 else if (!*soap
->href
&& minlen
> 0)
12371 { soap
->error
= SOAP_LENGTH
;
12375 *p
= soap_strdup(soap
, SOAP_STR_EOS
);
12377 p
= (char**)soap_id_lookup(soap
, soap
->href
, (void**)p
, t
, sizeof(char**), 0);
12378 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12384 /******************************************************************************/
12385 #ifndef WITH_LEANER
12390 soap_outwstring(struct soap
*soap
, const char *tag
, int id
, wchar_t *const*p
, const char *type
, int n
)
12391 { id
= soap_element_id(soap
, tag
, id
, *p
, NULL
, 0, type
, n
);
12393 return soap
->error
;
12394 if (!**p
&& (soap
->mode
& SOAP_C_NILSTRING
))
12395 return soap_element_null(soap
, tag
, id
, type
);
12396 if (soap_element_begin_out(soap
, tag
, id
, type
)
12397 || soap_wstring_out(soap
, *p
, 0)
12398 || soap_element_end_out(soap
, tag
))
12399 return soap
->error
;
12405 /******************************************************************************/
12406 #ifndef WITH_LEANER
12411 soap_inwstring(struct soap
*soap
, const char *tag
, wchar_t **p
, const char *type
, int t
, long minlen
, long maxlen
)
12412 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12413 { if (!tag
|| *tag
!= '-' || soap
->error
!= SOAP_NO_TAG
)
12415 soap
->error
= SOAP_OK
;
12418 { if (!(p
= (wchar_t**)soap_malloc(soap
, sizeof(wchar_t*))))
12422 { *p
= soap_wstring_in(soap
, 1, minlen
, maxlen
);
12423 if (!*p
|| !(wchar_t*)soap_id_enter(soap
, soap
->id
, *p
, t
, sizeof(wchar_t*), 0, NULL
, NULL
, NULL
))
12425 if (!**p
&& tag
&& *tag
== '-')
12426 { soap
->error
= SOAP_NO_TAG
;
12430 else if (tag
&& *tag
== '-')
12431 { soap
->error
= SOAP_NO_TAG
;
12434 else if (soap
->null
)
12437 *p
= soap_wstrdup(soap
, (wchar_t*)SOAP_STR_EOS
);
12439 p
= (wchar_t**)soap_id_lookup(soap
, soap
->href
, (void**)p
, t
, sizeof(wchar_t**), 0);
12440 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12447 /******************************************************************************/
12452 soap_timegm(struct tm
*T
)
12454 #if defined(HAVE_TIMEGM)
12460 if (t
== (time_t)-1)
12462 #ifdef HAVE_GMTIME_R
12469 if (g
== (time_t)-1)
12477 /******************************************************************************/
12482 soap_dateTime2s(struct soap
*soap
, time_t n
)
12483 { struct tm T
, *pT
= &T
;
12484 #if defined(HAVE_GMTIME_R)
12485 if (gmtime_r(&n
, pT
))
12486 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%SZ", pT
);
12487 #elif defined(HAVE_GMTIME)
12488 if ((pT
= gmtime(&n
)))
12489 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%SZ", pT
);
12490 #elif defined(HAVE_GETTIMEOFDAY)
12491 struct timezone tz
;
12492 memset((void*)&tz
, 0, sizeof(tz
));
12493 #if defined(HAVE_LOCALTIME_R)
12494 if (localtime_r(&n
, pT
))
12495 { struct timeval tv
;
12496 gettimeofday(&tv
, &tz
);
12497 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12498 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
12501 if ((pT
= localtime(&n
)))
12502 { struct timeval tv
;
12503 gettimeofday(&tv
, &tz
);
12504 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12505 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -tz
.tz_minuteswest
/60+(pT
->tm_isdst
!=0), abs(tz
.tz_minuteswest
)%60);
12508 #elif defined(HAVE_FTIME)
12510 memset((void*)&t
, 0, sizeof(t
));
12511 #if defined(HAVE_LOCALTIME_R)
12512 if (localtime_r(&n
, pT
))
12514 #ifdef __BORLANDC__
12519 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12520 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
12523 if ((pT
= localtime(&n
)))
12525 #ifdef __BORLANDC__
12530 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12531 sprintf(soap
->tmpbuf
+ strlen(soap
->tmpbuf
), "%+03d:%02d", -t
.timezone
/60+(pT
->tm_isdst
!=0), abs(t
.timezone
)%60);
12534 #elif defined(HAVE_LOCALTIME_R)
12535 if (localtime_r(&n
, pT
))
12536 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12538 if ((pT
= localtime(&n
)))
12539 strftime(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), "%Y-%m-%dT%H:%M:%S", pT
);
12542 strcpy(soap
->tmpbuf
, "1969-12-31T23:59:59Z");
12543 return soap
->tmpbuf
;
12547 /******************************************************************************/
12552 soap_outdateTime(struct soap
*soap
, const char *tag
, int id
, const time_t *p
, const char *type
, int n
)
12553 { if (soap_element_begin_out(soap
, tag
, soap_embedded_id(soap
, id
, p
, n
), type
)
12554 || soap_string_out(soap
, soap_dateTime2s(soap
, *p
), 0))
12555 return soap
->error
;
12556 return soap_element_end_out(soap
, tag
);
12560 /******************************************************************************/
12565 soap_s2dateTime(struct soap
*soap
, const char *s
, time_t *p
)
12571 memset((void*)&T
, 0, sizeof(T
));
12572 if (strchr(s
, '-'))
12573 t
= "%d-%d-%dT%d:%d:%d%31s";
12574 else if (strchr(s
, ':'))
12575 t
= "%4d%2d%2dT%d:%d:%d%31s";
12576 else /* parse non-XSD-standard alternative ISO 8601 format */
12577 t
= "%4d%2d%2dT%2d%2d%2d%31s";
12578 if (sscanf(s
, t
, &T
.tm_year
, &T
.tm_mon
, &T
.tm_mday
, &T
.tm_hour
, &T
.tm_min
, &T
.tm_sec
, zone
) < 6)
12579 return soap
->error
= SOAP_TYPE
;
12580 if (T
.tm_year
== 1)
12586 { for (s
= zone
+ 1; *s
; s
++)
12587 if (*s
< '0' || *s
> '9')
12594 #ifndef WITH_NOZONE
12595 if (*s
== '+' || *s
== '-')
12596 { int h
= 0, m
= 0;
12599 sscanf(s
, "%d:%d", &h
, &m
);
12604 { m
= (int)soap_strtol(s
, NULL
, 10);
12610 /* put hour and min in range */
12611 T
.tm_hour
+= T
.tm_min
/ 60;
12617 T
.tm_mday
+= T
.tm_hour
/ 24;
12623 /* note: day of the month may be out of range, timegm() handles it */
12626 *p
= soap_timegm(&T
);
12628 else /* no UTC or timezone, so assume we got a localtime */
12633 return soap
->error
;
12637 /******************************************************************************/
12642 soap_indateTime(struct soap
*soap
, const char *tag
, time_t *p
, const char *type
, int t
)
12643 { if (soap_element_begin_in(soap
, tag
, 0, NULL
))
12646 && soap_match_tag(soap
, soap
->type
, type
)
12647 && soap_match_tag(soap
, soap
->type
, ":dateTime"))
12648 { soap
->error
= SOAP_TYPE
;
12652 p
= (time_t*)soap_id_enter(soap
, soap
->id
, p
, t
, sizeof(time_t), 0, NULL
, NULL
, NULL
);
12654 p
= (time_t*)soap_id_forward(soap
, soap
->href
, p
, 0, t
, 0, sizeof(time_t), 0, NULL
);
12656 { if (soap_s2dateTime(soap
, soap_value(soap
), p
))
12659 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12665 /******************************************************************************/
12670 soap_outliteral(struct soap
*soap
, const char *tag
, char *const*p
, const char *type
)
12672 const char *t
= NULL
;
12673 if (tag
&& *tag
!= '-')
12674 { if (soap
->local_namespaces
&& (t
= strchr(tag
, ':')))
12675 { strncpy(soap
->tmpbuf
, tag
, t
-tag
);
12676 soap
->tmpbuf
[t
-tag
] = '\0';
12677 for (i
= 0; soap
->local_namespaces
[i
].id
; i
++)
12678 if (!strcmp(soap
->tmpbuf
, soap
->local_namespaces
[i
].id
))
12681 if (soap_element(soap
, t
, 0, type
)
12682 || soap_attribute(soap
, "xmlns", soap
->local_namespaces
[i
].ns
? soap
->local_namespaces
[i
].ns
: SOAP_STR_EOS
)
12683 || soap_element_start_end_out(soap
, NULL
))
12684 return soap
->error
;
12688 if (soap_element_begin_out(soap
, t
, 0, type
))
12689 return soap
->error
;
12693 { if (soap_send(soap
, *p
))
12694 return soap
->error
;
12697 return soap_element_end_out(soap
, t
);
12702 /******************************************************************************/
12707 soap_inliteral(struct soap
*soap
, const char *tag
, char **p
)
12708 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12709 { if (soap
->error
!= SOAP_NO_TAG
|| soap_unget(soap
, soap_get(soap
)) == SOAP_TT
)
12711 soap
->error
= SOAP_OK
;
12714 { if (!(p
= (char**)soap_malloc(soap
, sizeof(char*))))
12717 if (soap
->body
|| (tag
&& *tag
== '-'))
12718 { *p
= soap_string_in(soap
, 0, -1, -1);
12721 if (!**p
&& tag
&& *tag
== '-')
12722 { soap
->error
= SOAP_NO_TAG
;
12726 else if (soap
->null
)
12729 *p
= soap_strdup(soap
, SOAP_STR_EOS
);
12730 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12736 /******************************************************************************/
12737 #ifndef WITH_LEANER
12742 soap_outwliteral(struct soap
*soap
, const char *tag
, wchar_t *const*p
, const char *type
)
12744 const char *t
= NULL
;
12745 if (tag
&& *tag
!= '-')
12746 { if (soap
->local_namespaces
&& (t
= strchr(tag
, ':')))
12747 { strncpy(soap
->tmpbuf
, tag
, t
-tag
);
12748 soap
->tmpbuf
[t
-tag
] = '\0';
12749 for (i
= 0; soap
->local_namespaces
[i
].id
; i
++)
12750 if (!strcmp(soap
->tmpbuf
, soap
->local_namespaces
[i
].id
))
12753 if (soap_element(soap
, t
, 0, type
)
12754 || soap_attribute(soap
, "xmlns", soap
->local_namespaces
[i
].ns
? soap
->local_namespaces
[i
].ns
: SOAP_STR_EOS
)
12755 || soap_element_start_end_out(soap
, NULL
))
12756 return soap
->error
;
12760 if (soap_element_begin_out(soap
, t
, 0, type
))
12761 return soap
->error
;
12763 if (soap_send(soap
, soap
->tmpbuf
))
12764 return soap
->error
;
12768 const wchar_t *s
= *p
;
12770 { if (soap_pututf8(soap
, (unsigned long)c
))
12771 return soap
->error
;
12775 return soap_element_end_out(soap
, t
);
12781 /******************************************************************************/
12782 #ifndef WITH_LEANER
12787 soap_inwliteral(struct soap
*soap
, const char *tag
, wchar_t **p
)
12788 { if (soap_element_begin_in(soap
, tag
, 1, NULL
))
12789 { if (soap
->error
!= SOAP_NO_TAG
|| soap_unget(soap
, soap_get(soap
)) == SOAP_TT
)
12791 soap
->error
= SOAP_OK
;
12794 { if (!(p
= (wchar_t**)soap_malloc(soap
, sizeof(wchar_t*))))
12798 { *p
= soap_wstring_in(soap
, 0, -1, -1);
12801 if (!**p
&& tag
&& *tag
== '-')
12802 { soap
->error
= SOAP_NO_TAG
;
12806 else if (tag
&& *tag
== '-')
12807 { soap
->error
= SOAP_NO_TAG
;
12810 else if (soap
->null
)
12813 *p
= soap_wstrdup(soap
, (wchar_t*)SOAP_STR_EOS
);
12814 if (soap
->body
&& soap_element_end_in(soap
, tag
))
12821 /******************************************************************************/
12826 soap_value(struct soap
*soap
)
12827 { register size_t i
;
12828 register soap_wchar c
= 0;
12829 register char *s
= soap
->tmpbuf
;
12831 return SOAP_STR_EOS
;
12832 do c
= soap_get(soap
);
12833 while (soap_blank(c
));
12834 for (i
= 0; i
< sizeof(soap
->tmpbuf
) - 1; i
++)
12835 { if (c
== SOAP_TT
|| c
== SOAP_LT
|| (int)c
== EOF
)
12838 c
= soap_get(soap
);
12840 for (s
--; i
> 0; i
--, s
--)
12841 { if (!soap_blank(*s
))
12845 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Element content value='%s'\n", soap
->tmpbuf
));
12846 if (c
== SOAP_TT
|| c
== SOAP_LT
|| (int)c
== EOF
)
12847 soap_unget(soap
, c
);
12848 else if (soap
->mode
& SOAP_XML_STRICT
)
12849 { soap
->error
= SOAP_LENGTH
;
12853 if ((soap
->mode
& SOAP_XML_DOM
) && soap
->dom
)
12854 soap
->dom
->data
= soap_strdup(soap
, soap
->tmpbuf
);
12856 return soap
->tmpbuf
; /* return non-null pointer */
12860 /******************************************************************************/
12861 #if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
12866 soap_getline(struct soap
*soap
, char *s
, int len
)
12871 { c
= soap_getchar(soap
);
12872 if (c
== '\r' || c
== '\n')
12875 return soap
->error
= SOAP_EOF
;
12879 c
= soap_getchar(soap
); /* got \r or something else, now get \n */
12882 if (i
+1 == len
) /* empty line: end of HTTP/MIME header */
12884 c
= soap_get0(soap
);
12885 if (c
!= ' ' && c
!= '\t') /* HTTP line continuation? */
12888 else if ((int)c
== EOF
)
12889 return soap
->error
= SOAP_EOF
;
12891 return soap
->error
= SOAP_HDR
;
12898 /******************************************************************************/
12901 soap_count_attachments(struct soap
*soap
)
12903 #ifndef WITH_LEANER
12904 register struct soap_multipart
*content
;
12905 register size_t count
= soap
->count
;
12906 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count
));
12907 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
12908 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the size of DIME attachments\n"));
12909 for (content
= soap
->dime
.first
; content
; content
= content
->next
)
12910 { count
+= 12 + ((content
->size
+3)&(~3));
12912 count
+= ((strlen(content
->id
)+3)&(~3));
12914 count
+= ((strlen(content
->type
)+3)&(~3));
12915 if (content
->options
)
12916 count
+= ((((unsigned char)content
->options
[2] << 8) | ((unsigned char)content
->options
[3]))+7)&(~3);
12917 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content
->size
));
12920 if ((soap
->mode
& SOAP_ENC_MIME
) && soap
->mime
.boundary
)
12921 { register size_t n
= strlen(soap
->mime
.boundary
);
12922 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Calculating the size of MIME attachments\n"));
12923 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
12924 { register const char *s
;
12925 /* count \r\n--boundary\r\n */
12927 /* count Content-Type: ...\r\n */
12929 count
+= 16 + strlen(content
->type
);
12930 /* count Content-Transfer-Encoding: ...\r\n */
12931 s
= soap_code_str(mime_codes
, content
->encoding
);
12933 count
+= 29 + strlen(s
);
12934 /* count Content-ID: ...\r\n */
12936 count
+= 14 + strlen(content
->id
);
12937 /* count Content-Location: ...\r\n */
12938 if (content
->location
)
12939 count
+= 20 + strlen(content
->location
);
12940 /* count Content-Description: ...\r\n */
12941 if (content
->description
)
12942 count
+= 23 + strlen(content
->description
);
12943 /* count \r\n...content */
12944 count
+= 2 + content
->size
;
12945 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content
->size
));
12947 /* count \r\n--boundary-- */
12950 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "New count is %lu bytes\n", (unsigned long)count
));
12953 return soap
->count
;
12958 /******************************************************************************/
12959 #ifndef WITH_LEANER
12962 soap_putdimefield(struct soap
*soap
, const char *s
, size_t n
)
12963 { if (soap_send_raw(soap
, s
, n
))
12964 return soap
->error
;
12965 return soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)n
&3);
12970 /******************************************************************************/
12971 #ifndef WITH_LEANER
12976 soap_dime_option(struct soap
*soap
, unsigned short optype
, const char *option
)
12980 { n
= strlen(option
);
12981 s
= (char*)soap_malloc(soap
, n
+ 5);
12983 { s
[0] = (char)(optype
>> 8);
12984 s
[1] = (char)(optype
& 0xFF);
12985 s
[2] = (char)(n
>> 8);
12986 s
[3] = (char)(n
& 0xFF);
12987 strcpy(s
+ 4, option
);
12995 /******************************************************************************/
12996 #ifndef WITH_LEANER
13001 soap_putdimehdr(struct soap
*soap
)
13002 { unsigned char tmp
[12];
13003 size_t optlen
= 0, idlen
= 0, typelen
= 0;
13004 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Put DIME header id='%s'\n", soap
->dime
.id
?soap
->dime
.id
:SOAP_STR_EOS
));
13005 if (soap
->dime
.options
)
13006 optlen
= (((unsigned char)soap
->dime
.options
[2] << 8) | ((unsigned char)soap
->dime
.options
[3])) + 4;
13008 { idlen
= strlen(soap
->dime
.id
);
13009 if (idlen
> 0x0000FFFF)
13010 idlen
= 0x0000FFFF;
13012 if (soap
->dime
.type
)
13013 { typelen
= strlen(soap
->dime
.type
);
13014 if (typelen
> 0x0000FFFF)
13015 typelen
= 0x0000FFFF;
13017 tmp
[0] = SOAP_DIME_VERSION
| (soap
->dime
.flags
& 0x7);
13018 tmp
[1] = soap
->dime
.flags
& 0xF0;
13019 tmp
[2] = (char)(optlen
>> 8);
13020 tmp
[3] = (char)(optlen
& 0xFF);
13021 tmp
[4] = (char)(idlen
>> 8);
13022 tmp
[5] = (char)(idlen
& 0xFF);
13023 tmp
[6] = (char)(typelen
>> 8);
13024 tmp
[7] = (char)(typelen
& 0xFF);
13025 tmp
[8] = (char)(soap
->dime
.size
>> 24);
13026 tmp
[9] = (char)((soap
->dime
.size
>> 16) & 0xFF);
13027 tmp
[10] = (char)((soap
->dime
.size
>> 8) & 0xFF);
13028 tmp
[11] = (char)(soap
->dime
.size
& 0xFF);
13029 if (soap_send_raw(soap
, (char*)tmp
, 12)
13030 || soap_putdimefield(soap
, soap
->dime
.options
, optlen
)
13031 || soap_putdimefield(soap
, soap
->dime
.id
, idlen
)
13032 || soap_putdimefield(soap
, soap
->dime
.type
, typelen
))
13033 return soap
->error
;
13039 /******************************************************************************/
13040 #ifndef WITH_LEANER
13045 soap_putdime(struct soap
*soap
)
13046 { struct soap_multipart
*content
;
13047 if (!(soap
->mode
& SOAP_ENC_DIME
))
13049 for (content
= soap
->dime
.first
; content
; content
= content
->next
)
13051 soap
->dime
.size
= content
->size
;
13052 soap
->dime
.id
= content
->id
;
13053 soap
->dime
.type
= content
->type
;
13054 soap
->dime
.options
= content
->options
;
13055 soap
->dime
.flags
= SOAP_DIME_VERSION
| SOAP_DIME_MEDIA
;
13056 if (soap
->fdimereadopen
&& ((handle
= soap
->fdimereadopen(soap
, (void*)content
->ptr
, content
->id
, content
->type
, content
->options
)) || soap
->error
))
13057 { size_t size
= content
->size
;
13059 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadopen failed\n"));
13060 return soap
->error
;
13062 if (!size
&& ((soap
->mode
& SOAP_ENC_XML
) || (soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
))
13063 { size_t chunksize
= sizeof(soap
->tmpbuf
);
13064 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked streaming DIME\n"));
13066 { size
= soap
->fdimeread(soap
, handle
, soap
->tmpbuf
, chunksize
);
13067 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimeread returned %lu bytes\n", (unsigned long)size
));
13068 if (size
< chunksize
)
13069 { soap
->dime
.flags
&= ~SOAP_DIME_CF
;
13070 if (!content
->next
)
13071 soap
->dime
.flags
|= SOAP_DIME_ME
;
13074 soap
->dime
.flags
|= SOAP_DIME_CF
;
13075 soap
->dime
.size
= size
;
13076 if (soap_putdimehdr(soap
)
13077 || soap_putdimefield(soap
, soap
->tmpbuf
, size
))
13080 { soap
->dime
.flags
&= ~(SOAP_DIME_MB
| SOAP_DIME_MEDIA
);
13081 soap
->dime
.id
= NULL
;
13082 soap
->dime
.type
= NULL
;
13083 soap
->dime
.options
= NULL
;
13085 } while (size
>= chunksize
);
13088 { if (!content
->next
)
13089 soap
->dime
.flags
|= SOAP_DIME_ME
;
13090 if (soap_putdimehdr(soap
))
13091 return soap
->error
;
13094 if (size
< sizeof(soap
->tmpbuf
))
13097 bufsize
= sizeof(soap
->tmpbuf
);
13098 if (!(bufsize
= soap
->fdimeread(soap
, handle
, soap
->tmpbuf
, bufsize
)))
13099 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size
, (unsigned long)content
->size
));
13100 soap
->error
= SOAP_EOF
;
13103 if (soap_send_raw(soap
, soap
->tmpbuf
, bufsize
))
13107 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadclose\n"));
13108 soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)soap
->dime
.size
&3);
13110 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fdimereadclose\n"));
13111 if (soap
->fdimereadclose
)
13112 soap
->fdimereadclose(soap
, handle
);
13115 { if (!content
->next
)
13116 soap
->dime
.flags
|= SOAP_DIME_ME
;
13117 if (soap_putdimehdr(soap
)
13118 || soap_putdimefield(soap
, (char*)content
->ptr
, content
->size
))
13119 return soap
->error
;
13127 /******************************************************************************/
13128 #ifndef WITH_LEANER
13131 soap_getdimefield(struct soap
*soap
, size_t n
)
13132 { register soap_wchar c
;
13135 register char *p
= NULL
;
13137 { p
= (char*)soap_malloc(soap
, n
+ 1);
13140 for (i
= n
; i
> 0; i
--)
13141 { if ((int)(c
= soap_get1(soap
)) == EOF
)
13142 { soap
->error
= SOAP_EOF
;
13148 if ((soap
->error
= soap_move(soap
, -(long)n
&3)))
13152 soap
->error
= SOAP_EOM
;
13159 /******************************************************************************/
13160 #ifndef WITH_LEANER
13165 soap_getdimehdr(struct soap
*soap
)
13166 { register soap_wchar c
;
13169 unsigned char tmp
[12];
13170 size_t optlen
, idlen
, typelen
;
13171 if (!(soap
->mode
& SOAP_ENC_DIME
))
13172 return soap
->error
= SOAP_DIME_END
;
13173 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get DIME header\n"));
13174 if (soap
->dime
.buflen
|| soap
->dime
.chunksize
)
13175 { if (soap_move(soap
, (long)(soap
->dime
.size
- soap_tell(soap
))))
13176 return soap
->error
= SOAP_EOF
;
13177 soap_unget(soap
, soap_getchar(soap
)); /* skip padding and get hdr */
13178 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "... From chunked\n"));
13182 for (i
= 12; i
> 0; i
--)
13183 { if ((int)(c
= soap_getchar(soap
)) == EOF
)
13184 return soap
->error
= SOAP_EOF
;
13187 if ((tmp
[0] & 0xF8) != SOAP_DIME_VERSION
)
13188 return soap
->error
= SOAP_DIME_MISMATCH
;
13189 soap
->dime
.flags
= (tmp
[0] & 0x7) | (tmp
[1] & 0xF0);
13190 optlen
= (tmp
[2] << 8) | tmp
[3];
13191 idlen
= (tmp
[4] << 8) | tmp
[5];
13192 typelen
= (tmp
[6] << 8) | tmp
[7];
13193 soap
->dime
.size
= (tmp
[8] << 24) | (tmp
[9] << 16) | (tmp
[10] << 8) | tmp
[11];
13194 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "DIME size=%lu flags=0x%X\n", (unsigned long)soap
->dime
.size
, soap
->dime
.flags
));
13195 if (!(soap
->dime
.options
= soap_getdimefield(soap
, optlen
)) && soap
->error
)
13196 return soap
->error
;
13197 if (!(soap
->dime
.id
= soap_getdimefield(soap
, idlen
)) && soap
->error
)
13198 return soap
->error
;
13199 if (!(soap
->dime
.type
= soap_getdimefield(soap
, typelen
)) && soap
->error
)
13200 return soap
->error
;
13201 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
));
13202 if (soap
->dime
.flags
& SOAP_DIME_ME
)
13203 soap
->mode
&= ~SOAP_ENC_DIME
;
13209 /******************************************************************************/
13210 #ifndef WITH_LEANER
13215 soap_getdime(struct soap
*soap
)
13216 { while (soap
->dime
.flags
& SOAP_DIME_CF
)
13217 { if (soap_getdimehdr(soap
))
13218 return soap
->error
;
13219 if (soap_move(soap
, (long)soap
->dime
.size
))
13220 return soap
->error
= SOAP_EOF
;
13222 if (soap_move(soap
, (long)(((soap
->dime
.size
+3)&(~3))-soap_tell(soap
))))
13223 return soap
->error
= SOAP_EOF
;
13225 { register struct soap_multipart
*content
;
13226 if (soap_getdimehdr(soap
))
13228 if (soap
->fdimewriteopen
&& ((soap
->dime
.ptr
= (char*)soap
->fdimewriteopen(soap
, soap
->dime
.id
, soap
->dime
.type
, soap
->dime
.options
)) || soap
->error
))
13229 { const char *id
, *type
, *options
;
13231 if (!soap
->dime
.ptr
)
13232 return soap
->error
;
13233 id
= soap
->dime
.id
;
13234 type
= soap
->dime
.type
;
13235 options
= soap
->dime
.options
;
13237 { size
= soap
->dime
.size
;
13239 { n
= soap
->buflen
- soap
->bufidx
;
13242 if ((soap
->error
= soap
->fdimewrite(soap
, (void*)soap
->dime
.ptr
, soap
->buf
+ soap
->bufidx
, n
)))
13246 { soap
->bufidx
+= n
;
13249 if (soap_recv(soap
))
13250 { soap
->error
= SOAP_EOF
;
13254 if (soap_move(soap
, -(long)soap
->dime
.size
&3))
13255 { soap
->error
= SOAP_EOF
;
13258 if (!(soap
->dime
.flags
& SOAP_DIME_CF
))
13260 if (soap_getdimehdr(soap
))
13264 if (soap
->fdimewriteclose
)
13265 soap
->fdimewriteclose(soap
, (void*)soap
->dime
.ptr
);
13266 soap
->dime
.size
= 0;
13267 soap
->dime
.id
= id
;
13268 soap
->dime
.type
= type
;
13269 soap
->dime
.options
= options
;
13271 else if (soap
->dime
.flags
& SOAP_DIME_CF
)
13272 { const char *id
, *type
, *options
;
13273 id
= soap
->dime
.id
;
13274 type
= soap
->dime
.type
;
13275 options
= soap
->dime
.options
;
13276 if (soap_new_block(soap
) == NULL
)
13279 { register soap_wchar c
;
13282 s
= (char*)soap_push_block(soap
, NULL
, soap
->dime
.size
);
13284 return soap
->error
= SOAP_EOM
;
13285 for (i
= soap
->dime
.size
; i
> 0; i
--)
13286 { if ((int)(c
= soap_get1(soap
)) == EOF
)
13287 return soap
->error
= SOAP_EOF
;
13290 if (soap_move(soap
, -(long)soap
->dime
.size
&3))
13291 return soap
->error
= SOAP_EOF
;
13292 if (!(soap
->dime
.flags
& SOAP_DIME_CF
))
13294 if (soap_getdimehdr(soap
))
13295 return soap
->error
;
13297 soap
->dime
.size
= soap
->blist
->size
++; /* allocate one more for '\0' */
13298 if (!(soap
->dime
.ptr
= soap_save_block(soap
, NULL
, NULL
, 0)))
13299 return soap
->error
;
13300 soap
->dime
.ptr
[soap
->dime
.size
] = '\0'; /* force 0-terminated */
13301 soap
->dime
.id
= id
;
13302 soap
->dime
.type
= type
;
13303 soap
->dime
.options
= options
;
13306 soap
->dime
.ptr
= soap_getdimefield(soap
, soap
->dime
.size
);
13307 content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, soap
->dime
.ptr
, soap
->dime
.size
);
13309 return soap
->error
= SOAP_EOM
;
13310 content
->id
= soap
->dime
.id
;
13311 content
->type
= soap
->dime
.type
;
13312 content
->options
= soap
->dime
.options
;
13314 return soap
->error
;
13315 soap_resolve_attachment(soap
, content
);
13317 if (soap
->error
!= SOAP_DIME_END
)
13318 return soap
->error
;
13319 return soap
->error
= SOAP_OK
;
13324 /******************************************************************************/
13325 #ifndef WITH_LEANER
13330 soap_getmimehdr(struct soap
*soap
)
13331 { struct soap_multipart
*content
;
13333 { if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
13334 return soap
->error
;
13336 while (!*soap
->msgbuf
);
13337 if (soap
->msgbuf
[0] == '-' && soap
->msgbuf
[1] == '-')
13338 { char *s
= soap
->msgbuf
+ strlen(soap
->msgbuf
) - 1;
13339 /* remove white space */
13340 while (soap_blank(*s
))
13343 if (soap
->mime
.boundary
)
13344 { if (strcmp(soap
->msgbuf
+ 2, soap
->mime
.boundary
))
13345 return soap
->error
= SOAP_MIME_ERROR
;
13348 soap
->mime
.boundary
= soap_strdup(soap
, soap
->msgbuf
+ 2);
13349 if (soap_getline(soap
, soap
->msgbuf
, sizeof(soap
->msgbuf
)))
13350 return soap
->error
;
13352 if (soap_set_mime_attachment(soap
, NULL
, 0, SOAP_MIME_NONE
, NULL
, NULL
, NULL
, NULL
))
13353 return soap
->error
= SOAP_EOM
;
13354 content
= soap
->mime
.last
;
13356 { register char *key
= soap
->msgbuf
;
13357 register char *val
;
13360 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "MIME header: %s\n", key
));
13361 val
= strchr(soap
->msgbuf
, ':');
13365 while (*val
&& *val
<= 32);
13366 if (!soap_tag_cmp(key
, "Content-ID"))
13367 content
->id
= soap_strdup(soap
, val
);
13368 else if (!soap_tag_cmp(key
, "Content-Location"))
13369 content
->location
= soap_strdup(soap
, val
);
13370 else if (!soap_tag_cmp(key
, "Content-Disposition"))
13371 content
->id
= soap_strdup(soap
, soap_get_header_attribute(soap
, val
, "name"));
13372 else if (!soap_tag_cmp(key
, "Content-Type"))
13373 content
->type
= soap_strdup(soap
, val
);
13374 else if (!soap_tag_cmp(key
, "Content-Description"))
13375 content
->description
= soap_strdup(soap
, val
);
13376 else if (!soap_tag_cmp(key
, "Content-Transfer-Encoding"))
13377 content
->encoding
= (enum soap_mime_encoding
)soap_code_int(mime_codes
, val
, (long)SOAP_MIME_NONE
);
13379 if (soap_getline(soap
, key
, sizeof(soap
->msgbuf
)))
13380 return soap
->error
;
13387 /******************************************************************************/
13388 #ifndef WITH_LEANER
13393 soap_getmime(struct soap
*soap
)
13394 { while (soap_get_mime_attachment(soap
, NULL
))
13396 return soap
->error
;
13401 /******************************************************************************/
13402 #ifndef WITH_LEANER
13407 soap_post_check_mime_attachments(struct soap
*soap
)
13408 { soap
->imode
|= SOAP_MIME_POSTCHECK
;
13413 /******************************************************************************/
13414 #ifndef WITH_LEANER
13419 soap_check_mime_attachments(struct soap
*soap
)
13420 { if (soap
->mode
& SOAP_MIME_POSTCHECK
)
13421 return soap_get_mime_attachment(soap
, NULL
) != NULL
;
13427 /******************************************************************************/
13428 #ifndef WITH_LEANER
13431 struct soap_multipart
*
13433 soap_get_mime_attachment(struct soap
*soap
, void *handle
)
13434 { register soap_wchar c
= 0;
13435 register size_t i
, m
= 0;
13436 register char *s
, *t
= NULL
;
13437 register struct soap_multipart
*content
;
13438 register short flag
= 0;
13439 if (!(soap
->mode
& SOAP_ENC_MIME
))
13441 content
= soap
->mime
.last
;
13443 { if (soap_getmimehdr(soap
))
13445 content
= soap
->mime
.last
;
13447 else if (content
!= soap
->mime
.first
)
13448 { if (soap
->fmimewriteopen
&& ((content
->ptr
= (char*)soap
->fmimewriteopen(soap
, (void*)handle
, content
->id
, content
->type
, content
->description
, content
->encoding
)) || soap
->error
))
13449 { if (!content
->ptr
)
13453 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
));
13454 if (!content
->ptr
&& soap_new_block(soap
) == NULL
)
13455 { soap
->error
= SOAP_EOM
;
13459 { if (content
->ptr
)
13461 else if (!(s
= (char*)soap_push_block(soap
, NULL
, sizeof(soap
->tmpbuf
))))
13462 { soap
->error
= SOAP_EOM
;
13465 for (i
= 0; i
< sizeof(soap
->tmpbuf
); i
++)
13472 { c
= soap_get1(soap
);
13474 { soap
->error
= SOAP_EOF
;
13478 if (flag
|| c
== '\r')
13479 { t
= soap
->msgbuf
;
13480 memset(t
, 0, sizeof(soap
->msgbuf
));
13482 if (soap
->mime
.boundary
)
13483 strncat(t
, soap
->mime
.boundary
, sizeof(soap
->msgbuf
)-4);
13484 do c
= soap_getchar(soap
);
13487 { soap
->error
= SOAP_EOF
;
13493 flag
= (c
== '\r');
13494 m
= t
- soap
->msgbuf
+ 1 - flag
;
13501 if (content
->ptr
&& soap
->fmimewrite
)
13502 { if ((soap
->error
= soap
->fmimewrite(soap
, (void*)content
->ptr
, soap
->tmpbuf
, i
)))
13507 *s
= '\0'; /* force 0-terminated */
13509 { if (!soap
->error
&& soap
->fmimewrite
)
13510 soap
->error
= soap
->fmimewrite(soap
, (void*)content
->ptr
, soap
->tmpbuf
, i
);
13511 if (soap
->fmimewriteclose
)
13512 soap
->fmimewriteclose(soap
, (void*)content
->ptr
);
13517 { content
->size
= soap_size_block(soap
, NULL
, i
+1)-1;
13518 content
->ptr
= soap_save_block(soap
, NULL
, NULL
, 0);
13520 soap_resolve_attachment(soap
, content
);
13521 if (c
== '-' && soap_getchar(soap
) == '-')
13522 { soap
->mode
&= ~SOAP_ENC_MIME
;
13523 if ((soap
->mode
& SOAP_MIME_POSTCHECK
) && soap_end_recv(soap
))
13527 { while (c
!= '\r' && (int)c
!= EOF
&& soap_blank(c
))
13528 c
= soap_getchar(soap
);
13529 if (c
!= '\r' || soap_getchar(soap
) != '\n')
13530 { soap
->error
= SOAP_MIME_ERROR
;
13533 if (soap_getmimehdr(soap
))
13541 /******************************************************************************/
13542 #ifndef WITH_LEANER
13547 soap_match_cid(struct soap
*soap
, const char *s
, const char *t
)
13548 { register size_t n
;
13553 if (!strncmp(s
, "cid:", 4))
13560 if (!strncmp(s
, t
, n
) && !s
[n
])
13562 soap_decode(soap
->tmpbuf
, sizeof(soap
->tmpbuf
), s
, SOAP_STR_EOS
);
13563 if (!strncmp(soap
->tmpbuf
, t
, n
) && !soap
->tmpbuf
[n
])
13570 /******************************************************************************/
13571 #ifndef WITH_LEANER
13574 soap_resolve_attachment(struct soap
*soap
, struct soap_multipart
*content
)
13576 { register struct soap_xlist
**xp
= &soap
->xlist
;
13577 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Resolving attachment data for id=%s\n", content
->id
));
13579 { register struct soap_xlist
*xq
= *xp
;
13580 if (!soap_match_cid(soap
, xq
->id
, content
->id
))
13581 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Found matching attachment %s for content id=%s\n", xq
->id
, content
->id
));
13583 *xq
->ptr
= (unsigned char*)content
->ptr
;
13584 *xq
->size
= (int)content
->size
;
13585 *xq
->type
= (char*)content
->type
;
13586 if (content
->options
)
13587 *xq
->options
= (char*)content
->options
;
13589 *xq
->options
= (char*)content
->description
;
13590 SOAP_FREE(soap
, xq
);
13600 /******************************************************************************/
13601 #ifndef WITH_LEANER
13606 soap_putmimehdr(struct soap
*soap
, struct soap_multipart
*content
)
13608 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "MIME attachment type=%s\n", content
->type
?content
->type
:SOAP_STR_EOS
));
13609 if (soap_send3(soap
, "\r\n--", soap
->mime
.boundary
, "\r\n"))
13610 return soap
->error
;
13611 if (content
->type
&& soap_send3(soap
, "Content-Type: ", content
->type
, "\r\n"))
13612 return soap
->error
;
13613 s
= soap_code_str(mime_codes
, content
->encoding
);
13614 if (s
&& soap_send3(soap
, "Content-Transfer-Encoding: ", s
, "\r\n"))
13615 return soap
->error
;
13616 if (content
->id
&& soap_send3(soap
, "Content-ID: ", content
->id
, "\r\n"))
13617 return soap
->error
;
13618 if (content
->location
&& soap_send3(soap
, "Content-Location: ", content
->location
, "\r\n"))
13619 return soap
->error
;
13620 if (content
->description
&& soap_send3(soap
, "Content-Description: ", content
->description
, "\r\n"))
13621 return soap
->error
;
13622 return soap_send_raw(soap
, "\r\n", 2);
13627 /******************************************************************************/
13628 #ifndef WITH_LEANER
13633 soap_putmime(struct soap
*soap
)
13634 { struct soap_multipart
*content
;
13635 if (!(soap
->mode
& SOAP_ENC_MIME
) || !soap
->mime
.boundary
)
13637 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Sending MIME attachments\n"));
13638 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
13640 if (soap
->fmimereadopen
&& ((handle
= soap
->fmimereadopen(soap
, (void*)content
->ptr
, content
->id
, content
->type
, content
->description
)) || soap
->error
))
13641 { size_t size
= content
->size
;
13643 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimereadopen failed\n"));
13644 return soap
->error
;
13646 if (soap_putmimehdr(soap
, content
))
13647 return soap
->error
;
13649 { if ((soap
->mode
& SOAP_ENC_XML
) || (soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
|| (soap
->mode
& SOAP_IO
) == SOAP_IO_STORE
)
13650 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked streaming MIME\n"));
13652 { size
= soap
->fmimeread(soap
, handle
, soap
->tmpbuf
, sizeof(soap
->tmpbuf
));
13653 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimeread returned %lu bytes\n", (unsigned long)size
));
13654 if (soap_send_raw(soap
, soap
->tmpbuf
, size
))
13659 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
13665 if (size
< sizeof(soap
->tmpbuf
))
13668 bufsize
= sizeof(soap
->tmpbuf
);
13669 if (!(bufsize
= soap
->fmimeread(soap
, handle
, soap
->tmpbuf
, bufsize
)))
13670 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size
, (unsigned long)content
->size
));
13671 soap
->error
= SOAP_EOF
;
13674 if (soap_send_raw(soap
, soap
->tmpbuf
, bufsize
))
13679 if (soap
->fmimereadclose
)
13680 soap
->fmimereadclose(soap
, handle
);
13683 { if (soap_putmimehdr(soap
, content
)
13684 || soap_send_raw(soap
, content
->ptr
, content
->size
))
13685 return soap
->error
;
13688 return soap_send3(soap
, "\r\n--", soap
->mime
.boundary
, "--");
13693 /******************************************************************************/
13694 #ifndef WITH_LEANER
13699 soap_set_dime(struct soap
*soap
)
13700 { soap
->omode
|= SOAP_ENC_DIME
;
13701 soap
->dime
.first
= NULL
;
13702 soap
->dime
.last
= NULL
;
13707 /******************************************************************************/
13708 #ifndef WITH_LEANER
13713 soap_set_mime(struct soap
*soap
, const char *boundary
, const char *start
)
13714 { soap
->omode
|= SOAP_ENC_MIME
;
13715 soap
->mime
.first
= NULL
;
13716 soap
->mime
.last
= NULL
;
13717 soap
->mime
.boundary
= soap_strdup(soap
, boundary
);
13718 soap
->mime
.start
= soap_strdup(soap
, start
);
13723 /******************************************************************************/
13724 #ifndef WITH_LEANER
13729 soap_clr_dime(struct soap
*soap
)
13730 { soap
->omode
&= ~SOAP_ENC_DIME
;
13731 soap
->dime
.first
= NULL
;
13732 soap
->dime
.last
= NULL
;
13737 /******************************************************************************/
13738 #ifndef WITH_LEANER
13743 soap_clr_mime(struct soap
*soap
)
13744 { soap
->omode
&= ~SOAP_ENC_MIME
;
13745 soap
->mime
.first
= NULL
;
13746 soap
->mime
.last
= NULL
;
13747 soap
->mime
.boundary
= NULL
;
13748 soap
->mime
.start
= NULL
;
13753 /******************************************************************************/
13754 #ifndef WITH_LEANER
13756 static struct soap_multipart
*
13757 soap_new_multipart(struct soap
*soap
, struct soap_multipart
**first
, struct soap_multipart
**last
, char *ptr
, size_t size
)
13758 { struct soap_multipart
*content
;
13759 content
= (struct soap_multipart
*)soap_malloc(soap
, sizeof(struct soap_multipart
));
13761 { content
->next
= NULL
;
13762 content
->ptr
= ptr
;
13763 content
->size
= size
;
13764 content
->id
= NULL
;
13765 content
->type
= NULL
;
13766 content
->options
= NULL
;
13767 content
->encoding
= SOAP_MIME_NONE
;
13768 content
->location
= NULL
;
13769 content
->description
= NULL
;
13773 (*last
)->next
= content
;
13781 /******************************************************************************/
13782 #ifndef WITH_LEANER
13787 soap_set_dime_attachment(struct soap
*soap
, char *ptr
, size_t size
, const char *type
, const char *id
, unsigned short optype
, const char *option
)
13788 { struct soap_multipart
*content
= soap_new_multipart(soap
, &soap
->dime
.first
, &soap
->dime
.last
, ptr
, size
);
13791 content
->id
= soap_strdup(soap
, id
);
13792 content
->type
= soap_strdup(soap
, type
);
13793 content
->options
= soap_dime_option(soap
, optype
, option
);
13799 /******************************************************************************/
13800 #ifndef WITH_LEANER
13805 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
)
13806 { struct soap_multipart
*content
= soap_new_multipart(soap
, &soap
->mime
.first
, &soap
->mime
.last
, ptr
, size
);
13809 content
->id
= soap_strdup(soap
, id
);
13810 content
->type
= soap_strdup(soap
, type
);
13811 content
->encoding
= encoding
;
13812 content
->location
= soap_strdup(soap
, location
);
13813 content
->description
= soap_strdup(soap
, description
);
13819 /******************************************************************************/
13820 #ifndef WITH_LEANER
13823 struct soap_multipart
*
13825 soap_next_multipart(struct soap_multipart
*content
)
13827 return content
->next
;
13833 /******************************************************************************/
13834 #ifndef WITH_LEANER
13837 soap_select_mime_boundary(struct soap
*soap
)
13838 { while (!soap
->mime
.boundary
|| soap_valid_mime_boundary(soap
))
13839 { register char *s
= soap
->mime
.boundary
;
13840 register size_t n
= 0;
13845 s
= soap
->mime
.boundary
= (char*)soap_malloc(soap
, n
+ 1);
13853 { *s
++ = soap_base64o
[soap_random
& 0x3F];
13858 if (!soap
->mime
.start
)
13859 soap
->mime
.start
= "<SOAP-ENV:Envelope>";
13864 /******************************************************************************/
13865 #ifndef WITH_LEANER
13868 soap_valid_mime_boundary(struct soap
*soap
)
13869 { register struct soap_multipart
*content
;
13871 if (soap
->fmimeread
)
13873 k
= strlen(soap
->mime
.boundary
);
13874 for (content
= soap
->mime
.first
; content
; content
= content
->next
)
13875 { if (content
->ptr
&& content
->size
>= k
)
13876 { register const char *p
= (const char*)content
->ptr
;
13878 for (i
= 0; i
< content
->size
- k
; i
++, p
++)
13879 { if (!strncmp(p
, soap
->mime
.boundary
, k
))
13889 /******************************************************************************/
13893 soap_getgziphdr(struct soap
*soap
)
13895 soap_wchar c
= 0, f
= 0;
13896 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Get gzip header\n"));
13897 for (i
= 0; i
< 9; i
++)
13898 { if ((int)(c
= soap_get1(soap
) == EOF
))
13899 return soap
->error
= SOAP_EOF
;
13900 if (i
== 1 && c
== 8)
13905 if (f
& 0x04) /* FEXTRA */
13906 { for (i
= soap_get1(soap
) | (soap_get1(soap
) << 8); i
; i
--)
13907 { if ((int)soap_get1(soap
) == EOF
)
13908 return soap
->error
= SOAP_EOF
;
13911 if (f
& 0x08) /* skip FNAME */
13913 c
= soap_get1(soap
);
13914 while (c
&& (int)c
!= EOF
);
13916 if ((int)c
!= EOF
&& (f
& 0x10)) /* skip FCOMMENT */
13918 c
= soap_get1(soap
);
13919 while (c
&& (int)c
!= EOF
);
13921 if ((int)c
!= EOF
&& (f
& 0x02)) /* skip FHCRC (CRC32 is used) */
13922 { if ((int)(c
= soap_get1(soap
)) != EOF
)
13923 c
= soap_get1(soap
);
13926 return soap
->error
= SOAP_EOF
;
13932 /******************************************************************************/
13937 soap_begin_recv(struct soap
*soap
)
13939 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Initializing for input\n"));
13940 soap
->error
= SOAP_OK
;
13941 soap_free_temp(soap
);
13942 soap_set_local_namespaces(soap
);
13943 soap
->version
= 0; /* don't assume we're parsing SOAP content by default */
13944 #ifndef WITH_NOIDREF
13945 soap_free_iht(soap
);
13947 if ((soap
->imode
& SOAP_IO
) == SOAP_IO_CHUNK
)
13948 soap
->omode
|= SOAP_IO_CHUNK
;
13949 soap
->imode
&= ~(SOAP_IO
| SOAP_ENC_MIME
);
13950 soap
->mode
= soap
->imode
;
13951 if (!soap
->keep_alive
)
13952 { soap
->buflen
= 0;
13955 if (!(soap
->mode
& SOAP_IO_KEEPALIVE
))
13956 soap
->keep_alive
= 0;
13960 soap
->part
= SOAP_BEGIN
;
13965 *soap
->endpoint
= '\0';
13966 soap
->action
= NULL
;
13967 soap
->header
= NULL
;
13968 soap
->fault
= NULL
;
13970 #ifndef WITH_LEANER
13972 soap
->dime
.chunksize
= 0;
13973 soap
->dime
.buflen
= 0;
13974 soap
->dime
.list
= NULL
;
13975 soap
->dime
.first
= NULL
;
13976 soap
->dime
.last
= NULL
;
13977 soap
->mime
.list
= NULL
;
13978 soap
->mime
.first
= NULL
;
13979 soap
->mime
.last
= NULL
;
13980 soap
->mime
.boundary
= NULL
;
13981 soap
->mime
.start
= NULL
;
13985 #ifndef WITH_FASTCGI
13986 if (!soap_valid_socket(soap
->socket
))
13987 #ifdef __BORLANDC__
13988 setmode(soap
->recvfd
, _O_BINARY
);
13990 _setmode(soap
->recvfd
, _O_BINARY
);
13996 soap
->mode
&= ~SOAP_ENC_ZLIB
;
13997 soap
->zlib_in
= SOAP_ZLIB_NONE
;
13998 soap
->zlib_out
= SOAP_ZLIB_NONE
;
13999 soap
->d_stream
->next_in
= Z_NULL
;
14000 soap
->d_stream
->avail_in
= 0;
14001 soap
->d_stream
->next_out
= (Byte
*)soap
->buf
;
14002 soap
->d_stream
->avail_out
= SOAP_BUFLEN
;
14003 soap
->z_ratio_in
= 1.0;
14005 #ifdef WITH_OPENSSL
14009 #ifndef WITH_LEANER
14010 if (soap
->fprepareinitrecv
&& (soap
->error
= soap
->fprepareinitrecv(soap
)))
14011 return soap
->error
;
14013 c
= soap_getchar(soap
);
14016 { if (soap_getgziphdr(soap
))
14017 return soap
->error
;
14018 if (inflateInit2(soap
->d_stream
, -MAX_WBITS
) != Z_OK
)
14019 return soap
->error
= SOAP_ZLIB_ERROR
;
14021 { if (inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
14022 return soap
->error
= SOAP_ZLIB_ERROR
;
14024 soap
->zlib_state
= SOAP_ZLIB_INFLATE
;
14025 soap
->mode
|= SOAP_ENC_ZLIB
;
14026 soap
->zlib_in
= SOAP_ZLIB_GZIP
;
14027 soap
->z_crc
= crc32(0L, NULL
, 0);
14028 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip initialized\n"));
14030 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
14031 memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
14032 /* should not chunk over plain transport, so why bother to check? */
14033 /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
14034 /* soap->z_buflen = soap->bufidx; */
14036 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
14037 soap
->d_stream
->avail_in
= soap
->buflen
- soap
->bufidx
;
14038 soap
->z_buflen
= soap
->buflen
;
14039 soap
->buflen
= soap
->bufidx
;
14043 while (soap_blank(c
))
14044 c
= soap_getchar(soap
);
14045 #ifndef WITH_LEANER
14046 if (c
== '-' && soap_get0(soap
) == '-')
14047 soap
->mode
|= SOAP_ENC_MIME
;
14048 else if ((c
& 0xFFFC) == (SOAP_DIME_VERSION
| SOAP_DIME_MB
) && (soap_get0(soap
) & 0xFFF0) == 0x20)
14049 soap
->mode
|= SOAP_ENC_DIME
;
14053 if (c
== 0xEF && (c
= soap_getchar(soap
)) == 0xBB && (c
= soap_getchar(soap
)) == 0xBF)
14054 c
= soap_getchar(soap
);
14056 while (soap_blank(c
))
14057 c
= soap_getchar(soap
);
14060 return soap
->error
= SOAP_EOF
;
14061 soap_unget(soap
, c
);
14062 #ifndef WITH_NOHTTP
14063 /* if not XML or MIME/DIME/ZLIB, assume HTTP header */
14064 if (c
!= '<' && !(soap
->mode
& (SOAP_ENC_MIME
| SOAP_ENC_DIME
| SOAP_ENC_ZLIB
)))
14065 { soap_mode m
= soap
->imode
;
14066 soap
->mode
&= ~SOAP_IO
;
14067 soap
->error
= soap
->fparse(soap
);
14068 if (soap
->error
&& soap
->error
< SOAP_STOP
)
14069 { soap
->keep_alive
= 0; /* force close later */
14070 return soap
->error
;
14072 if (soap
->error
== SOAP_STOP
)
14073 return soap
->error
;
14074 soap
->mode
= soap
->imode
; /* if imode is changed, effectuate */
14075 soap
->imode
= m
; /* restore imode */
14077 soap
->mode
&= ~SOAP_ENC_ZLIB
;
14079 if ((soap
->mode
& SOAP_IO
) == SOAP_IO_CHUNK
)
14080 { soap
->chunkbuflen
= soap
->buflen
;
14081 soap
->buflen
= soap
->bufidx
;
14082 soap
->chunksize
= 0;
14084 /* Note: fparse should not use soap_unget to push back last char */
14085 if (soap_get0(soap
) == (int)EOF
)
14086 { if (soap
->status
== 200)
14087 return soap
->error
= SOAP_NO_DATA
; /* HTTP OK: always expect data */
14088 return soap
->error
= soap
->status
;
14091 if (soap
->zlib_in
!= SOAP_ZLIB_NONE
)
14094 if (soap
->zlib_in
!= SOAP_ZLIB_DEFLATE
)
14095 { c
= soap_get1(soap
);
14097 { if (soap_getgziphdr(soap
))
14098 return soap
->error
;
14099 if (inflateInit2(soap
->d_stream
, -MAX_WBITS
) != Z_OK
)
14100 return soap
->error
= SOAP_ZLIB_ERROR
;
14101 soap
->z_crc
= crc32(0L, NULL
, 0);
14102 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "gzip initialized\n"));
14105 { soap_revget1(soap
);
14106 if (inflateInit(soap
->d_stream
) != Z_OK
)
14107 return soap
->error
= SOAP_ZLIB_ERROR
;
14108 soap
->zlib_in
= SOAP_ZLIB_DEFLATE
;
14113 if (inflateInit(soap
->d_stream
) != Z_OK
)
14114 return soap
->error
= SOAP_ZLIB_ERROR
;
14116 { if (inflateSetDictionary(soap
->d_stream
, (const Bytef
*)soap
->z_dict
, soap
->z_dict_len
) != Z_OK
)
14117 return soap
->error
= SOAP_ZLIB_ERROR
;
14119 soap
->zlib_state
= SOAP_ZLIB_INFLATE
;
14120 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Inflate initialized\n"));
14121 soap
->mode
|= SOAP_ENC_ZLIB
;
14123 soap
->z_buf
= (char*)SOAP_MALLOC(soap
, SOAP_BUFLEN
);
14124 memcpy(soap
->z_buf
, soap
->buf
, SOAP_BUFLEN
);
14125 soap
->d_stream
->next_in
= (Byte
*)(soap
->z_buf
+ soap
->bufidx
);
14126 soap
->d_stream
->avail_in
= soap
->buflen
- soap
->bufidx
;
14127 soap
->z_buflen
= soap
->buflen
;
14128 soap
->buflen
= soap
->bufidx
;
14131 #ifndef WITH_LEANER
14132 if (soap
->fpreparerecv
&& (soap
->mode
& SOAP_IO
) != SOAP_IO_CHUNK
&& soap
->buflen
> soap
->bufidx
)
14134 if ((r
= soap
->fpreparerecv(soap
, soap
->buf
+ soap
->bufidx
, soap
->buflen
- soap
->bufidx
)))
14135 return soap
->error
= r
;
14139 { if (soap
->error
== SOAP_FORM
&& soap
->fform
)
14140 { soap
->error
= soap
->fform(soap
);
14141 if (soap
->error
== SOAP_OK
)
14142 soap
->error
= SOAP_STOP
; /* prevents further processing */
14144 return soap
->error
;
14148 #ifndef WITH_LEANER
14149 if (soap
->mode
& SOAP_ENC_MIME
)
14150 { if (soap_getmimehdr(soap
))
14151 return soap
->error
;
14152 if (soap
->mime
.start
)
14154 { if (!soap
->mime
.last
->id
)
14156 if (!soap_match_cid(soap
, soap
->mime
.start
, soap
->mime
.last
->id
))
14158 } while (soap_get_mime_attachment(soap
, NULL
));
14160 if (soap_get_header_attribute(soap
, soap
->mime
.first
->type
, "application/dime"))
14161 soap
->mode
|= SOAP_ENC_DIME
;
14163 if (soap
->mode
& SOAP_ENC_DIME
)
14164 { if (soap_getdimehdr(soap
))
14165 return soap
->error
;
14166 if (soap
->dime
.flags
& SOAP_DIME_CF
)
14167 { DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Chunked DIME SOAP message\n"));
14168 soap
->dime
.chunksize
= soap
->dime
.size
;
14169 if (soap
->buflen
- soap
->bufidx
>= soap
->dime
.chunksize
)
14170 { soap
->dime
.buflen
= soap
->buflen
;
14171 soap
->buflen
= soap
->bufidx
+ soap
->dime
.chunksize
;
14174 soap
->dime
.chunksize
-= soap
->buflen
- soap
->bufidx
;
14176 soap
->count
= soap
->buflen
- soap
->bufidx
;
14183 /******************************************************************************/
14188 soap_envelope_begin_out(struct soap
*soap
)
14190 #ifndef WITH_LEANER
14192 if ((soap
->mode
& SOAP_ENC_MIME
) && soap
->mime
.boundary
&& soap
->mime
.start
&& strlen(soap
->mime
.boundary
) + strlen(soap
->mime
.start
) < sizeof(soap
->tmpbuf
) - 80 )
14194 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
14195 s
= "application/dime";
14196 else if (soap
->version
== 2)
14197 { if (soap
->mode
& SOAP_ENC_MTOM
)
14198 s
= "application/xop+xml; charset=utf-8; type=\"application/soap+xml\"";
14200 s
= "application/soap+xml; charset=utf-8";
14202 else if (soap
->mode
& SOAP_ENC_MTOM
)
14203 s
= "application/xop+xml; charset=utf-8; type=\"text/xml\"";
14205 s
= "text/xml; charset=utf-8";
14206 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
);
14207 n
= strlen(soap
->tmpbuf
);
14208 if (soap_send_raw(soap
, soap
->tmpbuf
, n
))
14209 return soap
->error
;
14211 if (soap
->mode
& SOAP_IO_LENGTH
)
14212 soap
->dime
.size
= soap
->count
; /* DIME in MIME correction */
14213 if (!(soap
->mode
& SOAP_IO_LENGTH
) && (soap
->mode
& SOAP_ENC_DIME
))
14214 { if (soap_putdimehdr(soap
))
14215 return soap
->error
;
14218 soap
->part
= SOAP_IN_ENVELOPE
;
14219 return soap_element_begin_out(soap
, "SOAP-ENV:Envelope", 0, NULL
);
14223 /******************************************************************************/
14228 soap_envelope_end_out(struct soap
*soap
)
14229 { if (soap_element_end_out(soap
, "SOAP-ENV:Envelope") || ((soap
->mode
& SOAP_XML_INDENT
) && soap_send_raw(soap
, "\r\n", 2)))
14230 return soap
->error
;
14231 #ifndef WITH_LEANER
14232 if ((soap
->mode
& SOAP_IO_LENGTH
) && (soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
14233 { soap
->dime
.size
= soap
->count
- soap
->dime
.size
; /* DIME in MIME correction */
14234 sprintf(soap
->id
, soap
->dime_id_format
, 0);
14235 soap
->dime
.id
= soap
->id
;
14236 if (soap
->local_namespaces
)
14237 { if (soap
->local_namespaces
[0].out
)
14238 soap
->dime
.type
= (char*)soap
->local_namespaces
[0].out
;
14240 soap
->dime
.type
= (char*)soap
->local_namespaces
[0].ns
;
14242 soap
->dime
.options
= NULL
;
14243 soap
->dime
.flags
= SOAP_DIME_MB
| SOAP_DIME_ABSURI
;
14244 if (!soap
->dime
.first
)
14245 soap
->dime
.flags
|= SOAP_DIME_ME
;
14246 soap
->count
+= 12 + ((strlen(soap
->dime
.id
)+3)&(~3)) + (soap
->dime
.type
? ((strlen(soap
->dime
.type
)+3)&(~3)) : 0);
14248 if ((soap
->mode
& SOAP_ENC_DIME
) && !(soap
->mode
& SOAP_ENC_MTOM
))
14249 return soap_send_raw(soap
, SOAP_STR_PADDING
, -(long)soap
->dime
.size
&3);
14251 soap
->part
= SOAP_END_ENVELOPE
;
14256 /******************************************************************************/
14259 soap_get_http_body(struct soap
*soap
)
14262 register size_t l
= 0, n
= 0;
14264 /* get HTML body of HTTP error content */
14265 if (!(soap
->mode
& SOAP_ENC_ZLIB
) && (soap
->mode
& SOAP_IO
) != SOAP_IO_CHUNK
)
14266 { n
= soap
->length
;
14271 soap
->labidx
= 0; /* use look-aside buffer */
14273 if (soap_new_block(soap
) == NULL
)
14279 register size_t i
, k
;
14280 if (soap_append_lab(soap
, NULL
, 0)) /* allocate more space in look-aside buffer if necessary */
14282 s
= soap
->labbuf
+ soap
->labidx
; /* space to populate */
14283 k
= soap
->lablen
- soap
->labidx
; /* number of bytes available */
14284 soap
->labidx
= soap
->lablen
; /* claim this space */
14286 register size_t i
, k
= SOAP_BLKLEN
;
14287 if (!(s
= (char*)soap_push_block(soap
, NULL
, k
)))
14290 for (i
= 0; i
< k
; i
++)
14291 { register soap_wchar c
= soap_getchar(soap
);
14294 *s
++ = (char)(c
& 0xFF);
14296 if (n
> 0 && l
>= n
)
14303 s
= soap_strdup(soap
, soap
->labbuf
);
14305 soap_size_block(soap
, NULL
, i
+1);
14306 s
= soap_save_block(soap
, NULL
, 0);
14315 /******************************************************************************/
14320 soap_envelope_begin_in(struct soap
*soap
)
14321 { register struct Namespace
*p
;
14322 soap
->part
= SOAP_IN_ENVELOPE
;
14323 if (soap_element_begin_in(soap
, "SOAP-ENV:Envelope", 0, NULL
))
14324 { if (soap
->error
== SOAP_TAG_MISMATCH
14325 && !soap_element_begin_in(soap
, "Envelope", 0, NULL
))
14326 soap
->error
= SOAP_VERSIONMISMATCH
;
14327 else if (soap
->status
)
14328 soap
->error
= soap
->status
;
14329 return soap
->error
;
14331 p
= soap
->local_namespaces
;
14333 { const char *ns
= p
[0].out
;
14336 if (!strcmp(ns
, soap_env1
))
14337 { soap
->version
= 1; /* make sure we use SOAP 1.1 */
14339 SOAP_FREE(soap
, p
[1].out
);
14340 if ((p
[1].out
= (char*)SOAP_MALLOC(soap
, sizeof(soap_enc1
))))
14341 strcpy(p
[1].out
, soap_enc1
);
14343 else if (!strcmp(ns
, soap_env2
))
14344 { soap
->version
= 2; /* make sure we use SOAP 1.2 */
14346 SOAP_FREE(soap
, p
[1].out
);
14347 if ((p
[1].out
= (char*)SOAP_MALLOC(soap
, sizeof(soap_enc2
))))
14348 strcpy(p
[1].out
, soap_enc2
);
14355 /******************************************************************************/
14360 soap_envelope_end_in(struct soap
*soap
)
14361 { soap
->part
= SOAP_END_ENVELOPE
;
14362 return soap_element_end_in(soap
, "SOAP-ENV:Envelope");
14366 /******************************************************************************/
14371 soap_body_begin_out(struct soap
*soap
)
14372 { soap
->part
= SOAP_IN_BODY
;
14373 if (soap
->version
== 1)
14374 soap
->encoding
= 1;
14376 if ((soap
->mode
& SOAP_XML_SEC
) && soap_set_attr(soap
, "wsu:Id", "Body", 1))
14377 return soap
->error
;
14379 if (soap_element(soap
, "SOAP-ENV:Body", 0, NULL
))
14380 return soap
->error
;
14381 return soap_element_start_end_out(soap
, NULL
);
14385 /******************************************************************************/
14390 soap_body_end_out(struct soap
*soap
)
14391 { if (soap_element_end_out(soap
, "SOAP-ENV:Body"))
14392 return soap
->error
;
14393 soap
->part
= SOAP_END_BODY
;
14398 /******************************************************************************/
14403 soap_body_begin_in(struct soap
*soap
)
14404 { soap
->part
= SOAP_IN_BODY
;
14405 if (soap_element_begin_in(soap
, "SOAP-ENV:Body", 0, NULL
))
14406 return soap
->error
;
14408 soap
->part
= SOAP_NO_BODY
;
14413 /******************************************************************************/
14418 soap_body_end_in(struct soap
*soap
)
14419 { if (soap
->part
== SOAP_NO_BODY
)
14420 return soap
->error
= SOAP_OK
;
14421 soap
->part
= SOAP_END_BODY
;
14422 return soap_element_end_in(soap
, "SOAP-ENV:Body");
14426 /******************************************************************************/
14431 soap_recv_header(struct soap
*soap
)
14432 { if (soap_getheader(soap
) && soap
->error
== SOAP_TAG_MISMATCH
)
14433 soap
->error
= SOAP_OK
;
14434 if (soap
->error
== SOAP_OK
&& soap
->fheader
)
14435 soap
->error
= soap
->fheader(soap
);
14436 return soap
->error
;
14440 /******************************************************************************/
14445 soap_set_endpoint(struct soap
*soap
, const char *endpoint
)
14446 { register const char *s
;
14447 register size_t i
, n
;
14448 soap
->endpoint
[0] = '\0';
14449 soap
->host
[0] = '\0';
14450 soap
->path
[0] = '/';
14451 soap
->path
[1] = '\0';
14453 if (!endpoint
|| !*endpoint
)
14455 #ifdef WITH_OPENSSL
14456 if (!soap_tag_cmp(endpoint
, "https:*"))
14459 strncpy(soap
->endpoint
, endpoint
, sizeof(soap
->endpoint
) - 1);
14460 soap
->endpoint
[sizeof(soap
->endpoint
) - 1] = '\0';
14461 s
= strchr(endpoint
, ':');
14462 if (s
&& s
[1] == '/' && s
[2] == '/')
14467 if (n
>= sizeof(soap
->host
))
14468 n
= sizeof(soap
->host
) - 1;
14472 for (i
= 0; i
< n
; i
++)
14478 soap
->host
[i
] = s
[i
];
14482 { for (i
= 0; i
< n
; i
++)
14483 { soap
->host
[i
] = s
[i
];
14484 if (s
[i
] == '/' || s
[i
] == ':')
14489 for (i
= 0; i
< n
; i
++)
14490 { soap
->host
[i
] = s
[i
];
14491 if (s
[i
] == '/' || s
[i
] == ':')
14495 soap
->host
[i
] = '\0';
14497 { soap
->port
= (int)soap_strtol(s
+ i
+ 1, NULL
, 10);
14498 for (i
++; i
< n
; i
++)
14503 { strncpy(soap
->path
, s
+ i
, sizeof(soap
->path
));
14504 soap
->path
[sizeof(soap
->path
) - 1] = '\0';
14509 /******************************************************************************/
14514 soap_connect(struct soap
*soap
, const char *endpoint
, const char *action
)
14515 { return soap_connect_command(soap
, SOAP_POST
, endpoint
, action
);
14519 /******************************************************************************/
14524 soap_connect_command(struct soap
*soap
, int http_command
, const char *endpoints
, const char *action
)
14527 if (endpoints
&& (s
= strchr(endpoints
, ' ')))
14528 { endpoint
= (char*)SOAP_MALLOC(soap
, strlen(endpoints
) + 1);
14530 { strncpy(endpoint
, endpoints
, s
- endpoints
);
14531 endpoint
[s
- endpoints
] = '\0';
14532 if (soap_try_connect_command(soap
, http_command
, endpoint
, action
) != SOAP_TCP_ERROR
)
14536 soap
->error
= SOAP_OK
;
14540 s
= strchr(endpoints
, ' ');
14542 s
= endpoints
+ strlen(endpoints
);
14544 SOAP_FREE(soap
, endpoint
);
14547 soap_try_connect_command(soap
, http_command
, endpoints
, action
);
14548 return soap
->error
;
14552 /******************************************************************************/
14555 soap_try_connect_command(struct soap
*soap
, int http_command
, const char *endpoint
, const char *action
)
14556 { char host
[sizeof(soap
->host
)];
14559 soap
->error
= SOAP_OK
;
14560 strcpy(host
, soap
->host
); /* save previous host name: if != then reconnect */
14561 port
= soap
->port
; /* save previous port to compare */
14562 soap
->status
= http_command
;
14563 soap_set_endpoint(soap
, endpoint
);
14564 #ifndef WITH_LEANER
14565 if (soap
->fconnect
)
14566 { if ((soap
->error
= soap
->fconnect(soap
, endpoint
, soap
->host
, soap
->port
)))
14567 return soap
->error
;
14571 if (soap
->fopen
&& *soap
->host
)
14572 { if (!soap
->keep_alive
|| !soap_valid_socket(soap
->socket
) || strcmp(soap
->host
, host
) || soap
->port
!= port
|| !soap
->fpoll
|| soap
->fpoll(soap
))
14573 { soap
->keep_alive
= 0; /* to force close */
14574 soap
->omode
&= ~SOAP_IO_UDP
; /* to force close */
14575 soap_closesock(soap
);
14576 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap
->host
, soap
->path
, soap
->port
));
14578 if (!strncmp(endpoint
, "soap.udp:", 9))
14579 soap
->omode
|= SOAP_IO_UDP
;
14581 soap
->socket
= soap
->fopen(soap
, endpoint
, soap
->host
, soap
->port
);
14583 return soap
->error
;
14584 soap
->keep_alive
= ((soap
->omode
& SOAP_IO_KEEPALIVE
) != 0);
14587 count
= soap_count_attachments(soap
);
14588 if (soap_begin_send(soap
))
14589 return soap
->error
;
14590 if (http_command
== SOAP_GET
)
14591 { soap
->mode
&= ~SOAP_IO
;
14592 soap
->mode
|= SOAP_IO_BUFFER
;
14594 #ifndef WITH_NOHTTP
14595 soap
->action
= soap_strdup(soap
, action
);
14596 if ((soap
->mode
& SOAP_IO
) != SOAP_IO_STORE
&& !(soap
->mode
& SOAP_ENC_XML
) && endpoint
)
14597 { unsigned int k
= soap
->mode
;
14598 soap
->mode
&= ~(SOAP_IO
| SOAP_ENC_ZLIB
);
14599 if ((k
& SOAP_IO
) != SOAP_IO_FLUSH
)
14600 soap
->mode
|= SOAP_IO_BUFFER
;
14601 if ((soap
->error
= soap
->fpost(soap
, endpoint
, soap
->host
, soap
->port
, soap
->path
, action
, count
)))
14602 return soap
->error
;
14603 #ifndef WITH_LEANER
14604 if ((k
& SOAP_IO
) == SOAP_IO_CHUNK
)
14605 { if (soap_flush(soap
))
14606 return soap
->error
;
14611 if (http_command
== SOAP_GET
)
14612 return soap_end_send(soap
);
14618 /******************************************************************************/
14623 soap_s2base64(struct soap
*soap
, const unsigned char *s
, char *t
, int n
)
14625 register unsigned long m
;
14628 t
= (char*)soap_malloc(soap
, (n
+ 2) / 3 * 4 + 1);
14635 for (; n
> 2; n
-= 3, s
+= 3)
14637 m
= (m
<< 8) | s
[1];
14638 m
= (m
<< 8) | s
[2];
14639 for (i
= 4; i
> 0; m
>>= 6)
14640 t
[--i
] = soap_base64o
[m
& 0x3F];
14646 for (i
= 0; i
< n
; i
++)
14647 m
= (m
<< 8) | *s
++;
14650 for (i
++; i
> 0; m
>>= 6)
14651 t
[--i
] = soap_base64o
[m
& 0x3F];
14652 for (i
= 3; i
> n
; i
--)
14660 /******************************************************************************/
14665 soap_base642s(struct soap
*soap
, const char *s
, char *t
, size_t l
, int *n
)
14666 { register int i
, j
, c
;
14667 register unsigned long m
;
14668 register const char *p
;
14674 return SOAP_NON_NULL
;
14677 { l
= (strlen(s
) + 3) / 4 * 3;
14678 t
= (char*)soap_malloc(soap
, l
);
14686 { for (i
= 0; i
< SOAP_BLKLEN
; i
++)
14691 if (c
== '=' || !c
)
14695 *t
++ = (char)((m
>> 4) & 0xFF);
14699 *t
++ = (char)((m
>> 10) & 0xFF);
14700 *t
++ = (char)((m
>> 2) & 0xFF);
14708 if (c
>= 0 && c
<= 79)
14709 { int b
= soap_base64i
[c
];
14711 { soap
->error
= SOAP_TYPE
;
14717 else if (!soap_blank(c
+ '+'))
14718 { soap
->error
= SOAP_TYPE
;
14722 *t
++ = (char)((m
>> 16) & 0xFF);
14723 *t
++ = (char)((m
>> 8) & 0xFF);
14724 *t
++ = (char)(m
& 0xFF);
14733 *n
+= 3 * SOAP_BLKLEN
;
14738 /******************************************************************************/
14743 soap_s2hex(struct soap
*soap
, const unsigned char *s
, char *t
, int n
)
14744 { register char *p
;
14746 t
= (char*)soap_malloc(soap
, 2 * n
+ 1);
14752 { for (; n
> 0; n
--)
14753 { register int m
= *s
++;
14754 *t
++ = (char)((m
>> 4) + (m
> 159 ? 'a' - 10 : '0'));
14756 *t
++ = (char)(m
+ (m
> 9 ? 'a' - 10 : '0'));
14764 /******************************************************************************/
14769 soap_hex2s(struct soap
*soap
, const char *s
, char *t
, size_t l
, int *n
)
14770 { register const char *p
;
14776 return SOAP_NON_NULL
;
14779 { l
= strlen(s
) / 2;
14780 t
= (char*)soap_malloc(soap
, l
);
14786 { register int d1
, d2
;
14793 *t
++ = ((d1
>= 'A' ? (d1
& 0x7) + 9 : d1
- '0') << 4) + (d2
>= 'A' ? (d2
& 0x7) + 9 : d2
- '0');
14802 /******************************************************************************/
14803 #ifndef WITH_NOHTTP
14808 soap_puthttphdr(struct soap
*soap
, int status
, size_t count
)
14809 { if (soap
->status
!= SOAP_GET
)
14810 { register const char *s
= "text/xml; charset=utf-8";
14811 register int err
= SOAP_OK
;
14812 #ifndef WITH_LEANER
14813 register const char *r
= NULL
;
14815 if ((status
== SOAP_FILE
|| soap
->status
== SOAP_POST_FILE
) && soap
->http_content
)
14816 s
= soap
->http_content
;
14817 else if (status
== SOAP_HTML
)
14818 s
= "text/html; charset=utf-8";
14819 else if (count
|| ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
))
14820 { if (soap
->version
== 2)
14821 s
= "application/soap+xml; charset=utf-8";
14823 #ifndef WITH_LEANER
14824 if (soap
->mode
& (SOAP_ENC_DIME
| SOAP_ENC_MTOM
))
14825 { if (soap
->mode
& SOAP_ENC_MTOM
)
14826 { if (soap
->version
== 2)
14827 r
= "application/soap+xml";
14830 s
= "application/xop+xml";
14833 s
= "application/dime";
14835 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)
14836 { register const char *t
= strchr(s
, ';');
14837 sprintf(soap
->tmpbuf
, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap
->mime
.boundary
);
14839 { strncat(soap
->tmpbuf
, s
, t
- s
);
14840 soap
->tmpbuf
[sizeof(soap
->tmpbuf
)-1] = '\0';
14843 strcat(soap
->tmpbuf
, s
);
14844 if (soap
->mime
.start
)
14845 { strcat(soap
->tmpbuf
, "\"; start=\"");
14846 strcat(soap
->tmpbuf
, soap
->mime
.start
);
14848 strcat(soap
->tmpbuf
, "\"");
14850 { strcat(soap
->tmpbuf
, "; start-info=\"");
14851 strcat(soap
->tmpbuf
, r
);
14852 strcat(soap
->tmpbuf
, "\"");
14857 if (s
&& (err
= soap
->fposthdr(soap
, "Content-Type", s
)))
14860 if ((soap
->omode
& SOAP_ENC_ZLIB
))
14863 err
= soap
->fposthdr(soap
, "Content-Encoding", soap
->zlib_out
== SOAP_ZLIB_DEFLATE
? "deflate" : "gzip");
14865 err
= soap
->fposthdr(soap
, "Content-Encoding", "deflate");
14871 #ifndef WITH_LEANER
14872 if ((soap
->omode
& SOAP_IO
) == SOAP_IO_CHUNK
)
14873 err
= soap
->fposthdr(soap
, "Transfer-Encoding", "chunked");
14877 { sprintf(soap
->tmpbuf
, "%lu", (unsigned long)count
);
14878 err
= soap
->fposthdr(soap
, "Content-Length", soap
->tmpbuf
);
14883 return soap
->fposthdr(soap
, "Connection", soap
->keep_alive
? "keep-alive" : "close");
14888 /******************************************************************************/
14891 soap_set_validation_fault(struct soap
*soap
, const char *s
, const char *t
)
14893 sprintf(soap
->msgbuf
, "Validation constraint violation: %s%s in element '%s'", s
, t
?t
:SOAP_STR_EOS
, soap
->tag
);
14895 sprintf(soap
->msgbuf
, "Validation constraint violation: %s%s", s
, t
?t
:SOAP_STR_EOS
);
14896 return soap
->msgbuf
;
14900 /******************************************************************************/
14905 soap_set_fault(struct soap
*soap
)
14906 { const char **c
= soap_faultcode(soap
);
14907 const char **s
= soap_faultstring(soap
);
14908 if (soap
->fseterror
)
14909 soap
->fseterror(soap
, c
, s
);
14911 { if (soap
->version
== 2)
14912 *c
= "SOAP-ENV:Sender";
14914 *c
= "SOAP-ENV:Client";
14918 switch (soap
->error
)
14921 case SOAP_CLI_FAULT
:
14922 *s
= "Client fault";
14924 case SOAP_SVR_FAULT
:
14925 *s
= "Server fault";
14927 case SOAP_TAG_MISMATCH
:
14928 *s
= soap_set_validation_fault(soap
, "tag name or namespace mismatch", NULL
);
14931 *s
= soap_set_validation_fault(soap
, "data type mismatch ", soap
->type
);
14933 case SOAP_SYNTAX_ERROR
:
14934 *s
= "Well-formedness violation";
14937 *s
= "No XML root element";
14939 case SOAP_MUSTUNDERSTAND
:
14940 *c
= "SOAP-ENV:MustUnderstand";
14941 sprintf(soap
->msgbuf
, "The data in element '%s' must be understood but cannot be handled", soap
->tag
);
14944 case SOAP_VERSIONMISMATCH
:
14945 *c
= "SOAP-ENV:VersionMismatch";
14946 *s
= "Invalid SOAP message or SOAP version mismatch";
14948 case SOAP_DATAENCODINGUNKNOWN
:
14949 *c
= "SOAP-ENV:DataEncodingUnknown";
14950 *s
= "Unsupported SOAP data encoding";
14952 case SOAP_NAMESPACE
:
14953 *s
= soap_set_validation_fault(soap
, "namespace error", NULL
);
14955 case SOAP_USER_ERROR
:
14958 case SOAP_FATAL_ERROR
:
14959 *s
= "Fatal error";
14961 case SOAP_NO_METHOD
:
14962 sprintf(soap
->msgbuf
, "Method '%s' not implemented: method name or namespace not recognized", soap
->tag
);
14966 *s
= "Data required for operation";
14968 case SOAP_GET_METHOD
:
14969 *s
= "HTTP GET method not implemented";
14971 case SOAP_PUT_METHOD
:
14972 *s
= "HTTP PUT method not implemented";
14974 case SOAP_HEAD_METHOD
:
14975 *s
= "HTTP HEAD method not implemented";
14977 case SOAP_HTTP_METHOD
:
14978 *s
= "HTTP method not implemented";
14981 *s
= "Out of memory";
14984 *s
= "Memory overflow or memory corruption error";
14987 *s
= "Header line too long";
14990 *s
= "Array index out of bounds";
14993 *s
= soap_set_validation_fault(soap
, "nil not allowed", NULL
);
14995 case SOAP_DUPLICATE_ID
:
14996 *s
= soap_set_validation_fault(soap
, "multiple definitions of id ", soap
->id
);
14997 if (soap
->version
== 2)
14998 *soap_faultsubcode(soap
) = "SOAP-ENC:DuplicateID";
15000 case SOAP_MISSING_ID
:
15001 *s
= soap_set_validation_fault(soap
, "missing id for ref ", soap
->id
);
15002 if (soap
->version
== 2)
15003 *soap_faultsubcode(soap
) = "SOAP-ENC:MissingID";
15006 *s
= soap_set_validation_fault(soap
, "incompatible object type ref/id pair ", soap
->id
);
15011 case SOAP_UDP_ERROR
:
15012 *s
= "Message too large for UDP packet";
15014 case SOAP_TCP_ERROR
:
15015 *s
= tcp_error(soap
);
15018 case SOAP_HTTP_ERROR
:
15019 *s
= "An HTTP processing error occurred";
15021 case SOAP_SSL_ERROR
:
15022 #ifdef WITH_OPENSSL
15025 *s
= "OpenSSL not installed: recompile with -DWITH_OPENSSL";
15028 case SOAP_PLUGIN_ERROR
:
15029 *s
= "Plugin registry error";
15031 case SOAP_DIME_ERROR
:
15032 *s
= "DIME format error";
15034 case SOAP_DIME_HREF
:
15035 *s
= "DIME href to missing attachment";
15037 case SOAP_DIME_MISMATCH
:
15038 *s
= "DIME version/transmission error";
15040 case SOAP_DIME_END
:
15041 *s
= "End of DIME error";
15043 case SOAP_MIME_ERROR
:
15044 *s
= "MIME format error";
15046 case SOAP_MIME_HREF
:
15047 *s
= "MIME href to missing attachment";
15049 case SOAP_MIME_END
:
15050 *s
= "End of MIME error";
15052 case SOAP_ZLIB_ERROR
:
15054 sprintf(soap
->msgbuf
, "Zlib/gzip error: '%s'", soap
->d_stream
->msg
?soap
->d_stream
->msg
:SOAP_STR_EOS
);
15057 *s
= "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
15060 case SOAP_REQUIRED
:
15061 *s
= soap_set_validation_fault(soap
, "missing required attribute", NULL
);
15063 case SOAP_PROHIBITED
:
15064 *s
= soap_set_validation_fault(soap
, "prohibited attribute present", NULL
);
15067 *s
= soap_set_validation_fault(soap
, "occurrence violation", NULL
);
15070 *s
= soap_set_validation_fault(soap
, "content range or length violation", NULL
);
15072 case SOAP_FD_EXCEEDED
:
15073 *s
= "Maximum number of open connections was reached (no define HAVE_POLL): increase FD_SETSIZE";
15076 *s
= "Stopped: no response to be sent or received (informative)";
15081 strcpy(soap
->msgbuf
, soap_strerror(soap
));
15083 if (strlen(soap
->msgbuf
) + 25 < sizeof(soap
->msgbuf
))
15084 { memmove(soap
->msgbuf
+ 25, soap
->msgbuf
, strlen(soap
->msgbuf
) + 1);
15085 memcpy(soap
->msgbuf
, "End of file or no input: ", 25);
15091 *s
= "End of file or no input";
15095 #ifndef WITH_NOHTTP
15097 if (soap
->error
> 200 && soap
->error
< 600)
15098 { sprintf(soap
->msgbuf
, "HTTP Error: %d %s", soap
->error
, http_error(soap
, soap
->error
));
15104 { sprintf(soap
->msgbuf
, "Error %d", soap
->error
);
15111 /******************************************************************************/
15116 soap_send_fault(struct soap
*soap
)
15117 { register int status
= soap
->error
;
15118 if (status
== SOAP_STOP
)
15119 return soap_closesock(soap
);
15120 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Sending back fault struct for error code %d\n", soap
->error
));
15121 soap
->keep_alive
= 0; /* to terminate connection */
15122 soap_set_fault(soap
);
15123 if (soap
->error
< 200 && soap
->error
!= SOAP_FAULT
)
15124 soap
->header
= NULL
;
15125 if (status
!= SOAP_EOF
|| (!soap
->recv_timeout
&& !soap
->send_timeout
))
15128 if (soap
->fpoll
&& soap
->fpoll(soap
))
15131 else if (soap_valid_socket(soap
->socket
))
15132 { r
= tcp_select(soap
, soap
->socket
, SOAP_TCP_SELECT_RCV
| SOAP_TCP_SELECT_SND
, 0);
15134 { if (!(r
& SOAP_TCP_SELECT_SND
)
15135 || ((r
& SOAP_TCP_SELECT_RCV
)
15136 && recv(soap
->socket
, soap
->tmpbuf
, 1, MSG_PEEK
) < 0))
15143 { soap
->error
= SOAP_OK
;
15144 soap_serializeheader(soap
);
15145 soap_serializefault(soap
);
15146 soap_begin_count(soap
);
15147 if (soap
->mode
& SOAP_IO_LENGTH
)
15148 { soap_envelope_begin_out(soap
);
15149 soap_putheader(soap
);
15150 soap_body_begin_out(soap
);
15151 soap_putfault(soap
);
15152 soap_body_end_out(soap
);
15153 soap_envelope_end_out(soap
);
15155 soap_end_count(soap
);
15156 if (soap_response(soap
, status
)
15157 || soap_envelope_begin_out(soap
)
15158 || soap_putheader(soap
)
15159 || soap_body_begin_out(soap
)
15160 || soap_putfault(soap
)
15161 || soap_body_end_out(soap
)
15162 || soap_envelope_end_out(soap
))
15163 return soap_closesock(soap
);
15164 soap_end_send(soap
);
15167 soap
->error
= status
;
15168 return soap_closesock(soap
);
15172 /******************************************************************************/
15177 soap_recv_fault(struct soap
*soap
, int check
)
15178 { register int status
= soap
->error
;
15179 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Check if receiving SOAP Fault\n"));
15181 { /* try getfault when no tag or tag mismatched at level 2, otherwise ret */
15182 if (soap
->error
!= SOAP_NO_TAG
15183 && (soap
->error
!= SOAP_TAG_MISMATCH
|| soap
->level
!= 2))
15184 return soap
->error
;
15186 soap
->error
= SOAP_OK
;
15187 if (soap_getfault(soap
))
15188 { /* check flag set: check if SOAP Fault is present, if not just return */
15189 if (check
&& soap
->error
== SOAP_TAG_MISMATCH
&& soap
->level
== 2)
15190 return soap
->error
= SOAP_OK
;
15191 DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
15192 *soap_faultcode(soap
) = (soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
15193 soap
->error
= status
;
15194 soap_set_fault(soap
);
15197 { register const char *s
= *soap_faultcode(soap
);
15198 if (!soap_match_tag(soap
, s
, "SOAP-ENV:Server") || !soap_match_tag(soap
, s
, "SOAP-ENV:Receiver"))
15199 status
= SOAP_SVR_FAULT
;
15200 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:Client") || !soap_match_tag(soap
, s
, "SOAP-ENV:Sender"))
15201 status
= SOAP_CLI_FAULT
;
15202 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:MustUnderstand"))
15203 status
= SOAP_MUSTUNDERSTAND
;
15204 else if (!soap_match_tag(soap
, s
, "SOAP-ENV:VersionMismatch"))
15205 status
= SOAP_VERSIONMISMATCH
;
15207 { DBGLOG(TEST
,SOAP_MESSAGE(fdebug
, "Received SOAP Fault code %s\n", s
));
15208 status
= SOAP_FAULT
;
15210 if (!soap_body_end_in(soap
))
15211 soap_envelope_end_in(soap
);
15213 soap_end_recv(soap
);
15214 soap
->error
= status
;
15215 return soap_closesock(soap
);
15219 /******************************************************************************/
15220 #ifndef WITH_NOHTTP
15225 soap_send_empty_response(struct soap
*soap
, int httpstatuscode
)
15226 { register soap_mode m
= soap
->omode
;
15228 if ((m
& SOAP_IO
) == SOAP_IO_CHUNK
)
15229 soap
->omode
= (m
& ~SOAP_IO
) | SOAP_IO_BUFFER
;
15230 if (soap_response(soap
, httpstatuscode
) || soap_end_send(soap
))
15232 return soap_closesock(soap
);
15235 return soap
->error
= SOAP_STOP
; /* stops the server's response */
15240 /******************************************************************************/
15241 #ifndef WITH_NOHTTP
15246 soap_recv_empty_response(struct soap
*soap
)
15247 { if (!soap_begin_recv(soap
))
15248 soap_end_recv(soap
);
15249 else if (soap
->error
== SOAP_NO_DATA
|| soap
->error
== 202)
15250 soap
->error
= SOAP_OK
;
15251 return soap_closesock(soap
);
15256 /******************************************************************************/
15260 soap_strerror(struct soap
*soap
)
15261 { register int err
= soap
->errnum
;
15265 return strerror(err
);
15269 *soap
->msgbuf
= '\0';
15270 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
);
15273 *soap
->msgbuf
= '\0';
15274 len
= FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, err
, 0, (LPTSTR
)soap
->msgbuf
, (DWORD
)(sizeof(soap
->msgbuf
)/sizeof(TCHAR
)), NULL
);
15275 for (i
= 0; i
<= len
; i
++)
15276 { if (((TCHAR
*)soap
->msgbuf
)[i
] < 0x80)
15277 soap
->msgbuf
[i
] = (char)((TCHAR
*)soap
->msgbuf
)[i
];
15279 soap
->msgbuf
[i
] = '?';
15285 { char *s
= soap
->msgbuf
;
15287 int rt
= soap
->recv_timeout
, st
= soap
->send_timeout
;
15288 int ru
= ' ', su
= ' ';
15290 strcpy(s
, "Operation interrupted or timed out");
15301 sprintf(s
+ strlen(s
), " (%d%cs receive delay)", rt
, ru
);
15303 sprintf(s
+ strlen(s
), " (%d%cs send delay)", st
, su
);
15306 return soap
->msgbuf
;
15311 /******************************************************************************/
15314 soap_set_error(struct soap
*soap
, const char *faultcode
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
15315 { *soap_faultcode(soap
) = faultcode
;
15316 if (faultsubcodeQName
)
15317 *soap_faultsubcode(soap
) = faultsubcodeQName
;
15318 *soap_faultstring(soap
) = faultstring
;
15319 if (faultdetailXML
&& *faultdetailXML
)
15320 { register const char **s
= soap_faultdetail(soap
);
15322 *s
= faultdetailXML
;
15324 return soap
->error
= soaperror
;
15328 /******************************************************************************/
15333 soap_set_sender_error(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
15334 { return soap_set_error(soap
, soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL
, faultstring
, faultdetailXML
, soaperror
);
15338 /******************************************************************************/
15343 soap_set_receiver_error(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
, int soaperror
)
15344 { return soap_set_error(soap
, soap
->version
== 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL
, faultstring
, faultdetailXML
, soaperror
);
15348 /******************************************************************************/
15351 soap_copy_fault(struct soap
*soap
, const char *faultcode
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
15352 { char *r
= NULL
, *s
= NULL
, *t
= NULL
;
15353 if (faultsubcodeQName
)
15354 r
= soap_strdup(soap
, faultsubcodeQName
);
15356 s
= soap_strdup(soap
, faultstring
);
15357 if (faultdetailXML
)
15358 t
= soap_strdup(soap
, faultdetailXML
);
15359 return soap_set_error(soap
, faultcode
, r
, s
, t
, SOAP_FAULT
);
15363 /******************************************************************************/
15368 soap_sender_fault(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
)
15369 { return soap_sender_fault_subcode(soap
, NULL
, faultstring
, faultdetailXML
);
15373 /******************************************************************************/
15378 soap_sender_fault_subcode(struct soap
*soap
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
15379 { return soap_copy_fault(soap
, soap
->version
== 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName
, faultstring
, faultdetailXML
);
15383 /******************************************************************************/
15388 soap_receiver_fault(struct soap
*soap
, const char *faultstring
, const char *faultdetailXML
)
15389 { return soap_receiver_fault_subcode(soap
, NULL
, faultstring
, faultdetailXML
);
15393 /******************************************************************************/
15398 soap_receiver_fault_subcode(struct soap
*soap
, const char *faultsubcodeQName
, const char *faultstring
, const char *faultdetailXML
)
15399 { return soap_copy_fault(soap
, soap
->version
== 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName
, faultstring
, faultdetailXML
);
15403 /******************************************************************************/
15405 #ifndef WITH_NOSTDLIB
15409 soap_print_fault(struct soap
*soap
, FILE *fd
)
15410 { if (soap_check_state(soap
))
15411 fprintf(fd
, "Error: soap struct state not initialized\n");
15412 else if (soap
->error
)
15413 { const char *c
, *v
= NULL
, *s
, **d
;
15414 d
= soap_faultcode(soap
);
15416 soap_set_fault(soap
);
15418 if (soap
->version
== 2)
15419 v
= *soap_faultsubcode(soap
);
15420 s
= *soap_faultstring(soap
);
15421 d
= soap_faultdetail(soap
);
15422 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]");
15428 /******************************************************************************/
15431 #ifndef WITH_NOSTDLIB
15435 soap_stream_fault(struct soap
*soap
, std::ostream
& os
)
15436 { if (soap_check_state(soap
))
15437 os
<< "Error: soap struct state not initialized\n";
15438 else if (soap
->error
)
15439 { const char *c
, *v
= NULL
, *s
, **d
;
15440 d
= soap_faultcode(soap
);
15442 soap_set_fault(soap
);
15444 if (soap
->version
== 2)
15445 v
= *soap_faultsubcode(soap
);
15446 s
= *soap_faultstring(soap
);
15447 d
= soap_faultdetail(soap
);
15448 os
<< (soap
->version
? "SOAP 1." : "Error ")
15449 << (soap
->version
? (int)soap
->version
: soap
->error
)
15451 << "[" << (v
? v
: "no subcode") << "]"
15453 << "\"" << (s
? s
: "[no reason]") << "\""
15455 << "Detail: " << (d
&& *d
? *d
: "[no detail]")
15463 /******************************************************************************/
15465 #ifndef WITH_NOSTDLIB
15469 soap_sprint_fault(struct soap
*soap
, char *buf
, size_t len
)
15470 { if (soap_check_state(soap
))
15471 strncpy(buf
, "Error: soap struct not initialized", len
);
15472 else if (soap
->error
)
15473 { const char *c
, *v
= NULL
, *s
, **d
;
15474 d
= soap_faultcode(soap
);
15476 soap_set_fault(soap
);
15478 if (soap
->version
== 2)
15479 v
= *soap_faultsubcode(soap
);
15480 s
= *soap_faultstring(soap
);
15481 d
= soap_faultdetail(soap
);
15482 #ifdef HAVE_SNPRINTF
15488 (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]");
15490 if (len
> 40 + (v
? strlen(v
) : 0) + (s
? strlen(s
) : 0) + (d
&& *d
? strlen(*d
) : 0))
15491 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]");
15493 sprintf(buf
, "%s%d fault: %s\n", soap
->version
? "SOAP 1." : "Error ", soap
->version
? (int)soap
->version
: soap
->error
, c
);
15503 /******************************************************************************/
15505 #ifndef WITH_NOSTDLIB
15509 soap_print_fault_location(struct soap
*soap
, FILE *fd
)
15513 if (soap
->error
&& soap
->error
!= SOAP_STOP
&& soap
->bufidx
<= soap
->buflen
&& soap
->buflen
> 0 && soap
->buflen
<= SOAP_BUFLEN
)
15514 { i
= (int)soap
->bufidx
- 1;
15518 soap
->buf
[i
] = '\0';
15519 if ((int)soap
->buflen
>= i
+ 1024)
15522 j
= (int)soap
->buflen
- 1;
15524 soap
->buf
[j
] = '\0';
15525 fprintf(fd
, "%s%c\n<!-- ** HERE ** -->\n", soap
->buf
, c1
);
15526 if (soap
->bufidx
< soap
->buflen
)
15527 fprintf(fd
, "%s\n", soap
->buf
+ soap
->bufidx
);
15536 /******************************************************************************/
15541 soap_register_plugin_arg(struct soap
*soap
, int (*fcreate
)(struct soap
*, struct soap_plugin
*, void*), void *arg
)
15542 { register struct soap_plugin
*p
;
15544 if (!(p
= (struct soap_plugin
*)SOAP_MALLOC(soap
, sizeof(struct soap_plugin
))))
15545 return soap
->error
= SOAP_EOM
;
15550 r
= fcreate(soap
, p
, arg
);
15551 if (!r
&& p
->fdelete
)
15552 { p
->next
= soap
->plugins
;
15554 DBGLOG(TEST
, SOAP_MESSAGE(fdebug
, "Registered '%s' plugin\n", p
->id
));
15557 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
));
15558 SOAP_FREE(soap
, p
);
15563 /******************************************************************************/
15566 fplugin(struct soap
*soap
, const char *id
)
15567 { register struct soap_plugin
*p
;
15568 for (p
= soap
->plugins
; p
; p
= p
->next
)
15569 if (p
->id
== id
|| !strcmp(p
->id
, id
))
15575 /******************************************************************************/
15580 soap_lookup_plugin(struct soap
*soap
, const char *id
)
15581 { return soap
->fplugin(soap
, id
);
15585 /******************************************************************************/
15590 /******************************************************************************\
15592 * C++ soap struct methods
15594 \******************************************************************************/
15602 /******************************************************************************/
15604 soap::soap(soap_mode m
)
15605 { soap_init1(this, m
);
15609 /******************************************************************************/
15611 soap::soap(soap_mode im
, soap_mode om
)
15612 { soap_init2(this, im
, om
);
15616 /******************************************************************************/
15618 soap::soap(const struct soap
& soap
)
15619 { soap_copy_context(this, &soap
);
15623 /******************************************************************************/
15626 { soap_destroy(this);
15632 /******************************************************************************/