7
gSOAP XML Web services tools
8
Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved.
9
This part of the software is released under one of the following licenses:
10
GPL, the gSOAP public license, or Genivia's license for commercial use.
11
--------------------------------------------------------------------------------
14
Wind River Systems Inc., for the following additions under gSOAP public license:
15
- vxWorks compatible (#define VXWORKS)
16
--------------------------------------------------------------------------------
19
The contents of this file are subject to the gSOAP Public License Version 1.3
20
(the "License"); you may not use this file except in compliance with the
21
License. You may obtain a copy of the License at
22
http://www.cs.fsu.edu/~engelen/soaplicense.html
23
Software distributed under the License is distributed on an "AS IS" basis,
24
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
25
for the specific language governing rights and limitations under the License.
27
The Initial Developer of the Original Code is Robert A. van Engelen.
28
Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved.
29
--------------------------------------------------------------------------------
32
This program is free software; you can redistribute it and/or modify it under
33
the terms of the GNU General Public License as published by the Free Software
34
Foundation; either version 2 of the License, or (at your option) any later
37
This program is distributed in the hope that it will be useful, but WITHOUT ANY
38
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
39
PARTICULAR PURPOSE. See the GNU General Public License for more details.
41
You should have received a copy of the GNU General Public License along with
42
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
43
Place, Suite 330, Boston, MA 02111-1307 USA
45
Author contact information:
46
engelen@genivia.com / engelen@acm.org
47
--------------------------------------------------------------------------------
48
A commercial use license is available from Genivia, Inc., contact@genivia.com
49
--------------------------------------------------------------------------------
53
Win32 build needs winsock.dll (Visual C++ "wsock32.lib")
54
To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link"
55
tab (the project file needs to be selected in the file view) and add
56
"wsock32.lib" to the "Object/library modules" entry
58
On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with
59
-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack
60
when locally allocated data exceeds 64K.
65
# pragma convert(819) /* EBCDIC to ASCII */
75
# pragma comment(lib, "winsock.lib")
77
# pragma comment(lib, "wsock32.lib")
79
# pragma warning(disable : 4996) // disable deprecation warnings
84
SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.9k 2007-08-21 00:00:00 GMT")
87
SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.9k 2007-08-21 00:00:00 GMT")
90
/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
91
#ifndef SOAP_UNKNOWN_CHAR
92
#define SOAP_UNKNOWN_CHAR (127)
96
#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */
97
#define SOAP_TT (soap_wchar)(-3) /* XML character '</' */
98
#define SOAP_GT (soap_wchar)(-4) /* XML character '>' */
99
#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */
100
#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */
102
#define soap_blank(c) ((c) >= 0 && (c) <= 32)
103
#define soap_notblank(c) ((c) > 32)
105
#if defined(WIN32) && !defined(UNDER_CE)
106
#define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1))
108
#define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1)))
112
static void soap_init_logs(struct soap*);
113
static void soap_close_logfile(struct soap*, int);
114
static void soap_set_logfile(struct soap*, int, const char*);
117
#ifdef SOAP_MEM_DEBUG
118
static void soap_init_mht(struct soap*);
119
static void soap_free_mht(struct soap*);
120
static void soap_track_unlink(struct soap*, const void*);
124
static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int);
125
static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*);
126
static int soap_getattrval(struct soap*, char*, size_t, soap_wchar);
130
static soap_wchar soap_char(struct soap*);
131
static soap_wchar soap_get_pi(struct soap*);
132
static int soap_isxdigit(int);
133
static void *fplugin(struct soap*, const char*);
135
static void soap_update_ptrs(struct soap*, char*, char*, char*, char*);
136
static int soap_has_copies(struct soap*, const char*, const char*);
137
static void soap_init_iht(struct soap*);
138
static void soap_free_iht(struct soap*);
139
static void soap_init_pht(struct soap*);
140
static void soap_free_pht(struct soap*);
145
static const char *soap_set_validation_fault(struct soap*, const char*, const char*);
146
static int soap_isnumeric(struct soap*, const char*);
147
static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized);
148
static void soap_pop_ns(struct soap *soap);
149
static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n);
154
static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t);
155
static int soap_putdimefield(struct soap*, const char*, size_t);
156
static char *soap_getdimefield(struct soap*, size_t);
157
static void soap_select_mime_boundary(struct soap*);
158
static int soap_valid_mime_boundary(struct soap*);
159
static void soap_resolve_attachment(struct soap*, struct soap_multipart*);
164
static int soap_getgziphdr(struct soap*);
168
static int ssl_init_done = 0;
169
static int ssl_auth_init(struct soap*);
170
static int ssl_verify_callback(int, X509_STORE_CTX*);
171
static int ssl_password(char*, int, int, void *);
172
/* This callback is included for future references. It should not be deleted
173
static DH *ssl_tmp_dh(SSL*, int, int);
177
#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
179
static const char *soap_decode(char*, size_t, const char*, const char*);
185
static soap_wchar soap_getchunkchar(struct soap*);
186
static const char *http_error(struct soap*, int);
187
static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t);
188
static int http_get(struct soap*);
189
static int http_send_header(struct soap*, const char*);
190
static int http_post_header(struct soap*, const char*, const char*);
191
static int http_response(struct soap*, int, size_t);
192
static int http_parse(struct soap*);
193
static int http_parse_header(struct soap*, const char*, const char*);
199
static int fsend(struct soap*, const char*, size_t);
200
static size_t frecv(struct soap*, char*, size_t);
201
static int tcp_init(struct soap*);
202
static const char *tcp_error(struct soap*);
204
static size_t frecv_stop(struct soap*, char*, size_t);
207
static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr);
209
static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port);
210
static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*);
211
static int tcp_disconnect(struct soap*);
212
static int tcp_closesocket(struct soap*, SOAP_SOCKET);
213
static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int);
214
static const char *soap_strerror(struct soap*);
218
#if defined(PALM) && !defined(PALM_2)
219
unsigned short errno;
223
static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/";
224
static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/";
225
static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope";
226
static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding";
227
static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc";
231
const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF};
232
static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
233
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";
237
static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t";
238
/* Alternative indentation form for SOAP_XML_INDENT:
239
static const char soap_indent[21] = "\n ";
244
# define SOAP_CANARY (0xC0DE)
247
static const char soap_padding[4] = "\0\0\0";
248
#define SOAP_STR_PADDING (soap_padding)
249
#define SOAP_STR_EOS (soap_padding)
250
#define SOAP_NON_NULL (soap_padding)
253
static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */
356
static const struct soap_code_map h_error_codes[] =
358
#ifdef HOST_NOT_FOUND
359
{ HOST_NOT_FOUND, "Host not found" },
362
{ TRY_AGAIN, "Try Again" },
365
{ NO_RECOVERY, "No Recovery" },
368
{ NO_DATA, "No Data" },
371
{ NO_ADDRESS, "No Address" },
380
static const struct soap_code_map h_http_error_codes[] =
384
{ 203, "Non-Authoritative Information" },
385
{ 204, "No Content" },
386
{ 205, "Reset Content" },
387
{ 206, "Partial Content" },
388
{ 300, "Multiple Choices" },
389
{ 301, "Moved Permanently" },
391
{ 303, "See Other" },
392
{ 304, "Not Modified" },
393
{ 305, "Use Proxy" },
394
{ 307, "Temporary Redirect" },
395
{ 400, "Bad Request" },
396
{ 401, "Unauthorized" },
397
{ 402, "Payment Required" },
398
{ 403, "Forbidden" },
399
{ 404, "Not Found" },
400
{ 405, "Method Not Allowed" },
401
{ 406, "Not Acceptable" },
402
{ 407, "Proxy Authentication Required" },
403
{ 408, "Request Time-out" },
406
{ 411, "Length Required" },
407
{ 412, "Precondition Failed" },
408
{ 413, "Request Entity Too Large" },
409
{ 414, "Request-URI Too Large" },
410
{ 415, "Unsupported Media Type" },
411
{ 416, "Requested range not satisfiable" },
412
{ 417, "Expectation Failed" },
413
{ 500, "Internal Server Error" },
414
{ 501, "Not Implemented" },
415
{ 502, "Bad Gateway" },
416
{ 503, "Service Unavailable" },
417
{ 504, "Gateway Time-out" },
418
{ 505, "HTTP Version not supported" },
425
static const struct soap_code_map h_ssl_error_codes[] =
427
#define _SSL_ERROR(e) { e, #e }
428
_SSL_ERROR(SSL_ERROR_SSL),
429
_SSL_ERROR(SSL_ERROR_ZERO_RETURN),
430
_SSL_ERROR(SSL_ERROR_WANT_READ),
431
_SSL_ERROR(SSL_ERROR_WANT_WRITE),
432
_SSL_ERROR(SSL_ERROR_WANT_CONNECT),
433
_SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP),
434
_SSL_ERROR(SSL_ERROR_SYSCALL),
440
static const struct soap_code_map mime_codes[] =
441
{ { SOAP_MIME_7BIT, "7bit" },
442
{ SOAP_MIME_8BIT, "8bit" },
443
{ SOAP_MIME_BINARY, "binary" },
444
{ SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" },
445
{ SOAP_MIME_BASE64, "base64" },
446
{ SOAP_MIME_IETF_TOKEN, "ietf-token" },
447
{ SOAP_MIME_X_TOKEN, "x-token" },
453
static int tcp_done = 0;
456
/******************************************************************************/
460
fsend(struct soap *soap, const char *s, size_t n)
461
{ register int nwritten, err;
462
#if defined(__cplusplus) && !defined(WITH_LEAN)
464
{ soap->os->write(s, (std::streamsize)n);
465
if (soap->os->good())
471
{ if (soap_valid_socket(soap->socket))
474
if (soap->send_timeout)
477
if ((int)soap->socket >= (int)FD_SETSIZE)
478
return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
481
{ struct timeval timeout;
484
if (soap->send_timeout > 0)
485
{ timeout.tv_sec = soap->send_timeout;
489
{ timeout.tv_sec = -soap->send_timeout/1000000;
490
timeout.tv_usec = -soap->send_timeout%1000000;
493
FD_SET(soap->socket, &fd);
496
r = select((int)soap->socket + 1, &fd, &fd, &fd, &timeout);
499
r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
506
err = soap_socket_errno(soap->socket);
507
if (err != SOAP_EINTR && err != SOAP_EAGAIN)
508
{ soap->errnum = err;
516
nwritten = SSL_write(soap->ssl, s, (int)n);
518
nwritten = BIO_write(soap->bio, s, (int)n);
522
if ((soap->omode & SOAP_IO_UDP))
524
nwritten = sendto(soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
526
nwritten = send(soap->socket, s, n, soap->socket_flags);
527
/* retry and back-off algorithm */
528
/* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */
530
{ struct timeval timeout;
535
if ((int)soap->socket >= (int)FD_SETSIZE)
536
return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
538
if ((soap->connect_flags & SO_BROADCAST))
539
udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */
541
udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */
542
udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */
544
{ timeout.tv_sec = 0;
545
timeout.tv_usec = 1000 * udp_delay; /* ms */
547
FD_SET(soap->socket, &fd);
548
select((int)soap->socket + 1, NULL, NULL, &fd, &timeout);
550
nwritten = sendto(soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen);
552
nwritten = send(soap->socket, s, n, soap->socket_flags);
554
if (udp_delay > 500) /* UDP_UPPER_DELAY */
557
while (nwritten < 0 && --udp_repeat > 0);
562
#if !defined(PALM) && !defined(AS400)
563
nwritten = send(soap->socket, s, (int)n, soap->socket_flags);
565
nwritten = send(soap->socket, (void*)s, n, soap->socket_flags);
568
{ register int r = 0;
570
if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE)
573
err = soap_socket_errno(soap->socket);
574
if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN)
577
struct timeval timeout;
580
if ((int)soap->socket >= (int)FD_SETSIZE)
581
return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
583
if (soap->send_timeout > 0)
584
{ timeout.tv_sec = soap->send_timeout;
587
else if (soap->send_timeout < 0)
588
{ timeout.tv_sec = -soap->send_timeout/1000000;
589
timeout.tv_usec = -soap->send_timeout%1000000;
592
{ timeout.tv_sec = 0;
593
timeout.tv_usec = 10000;
596
FD_SET(soap->socket, &fd);
598
if (soap->ssl && r == SSL_ERROR_WANT_READ)
599
r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
601
r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
603
r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
605
if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR)
611
else if (err && err != SOAP_EINTR)
612
{ soap->errnum = err;
615
nwritten = 0; /* and call write() again */
621
nwritten = fwrite((void*)s, 1, n, stdout);
625
nwritten = fwrite(s, 1, n, soap->sendfd);
630
nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1;
633
nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w"));
635
nwritten = write(soap->sendfd, s, (unsigned int)n);
641
if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN)
642
{ soap->errnum = err;
645
nwritten = 0; /* and call write() again */
656
/******************************************************************************/
661
soap_send_raw(struct soap *soap, const char *s, size_t n)
664
if (soap->mode & SOAP_IO_LENGTH)
667
if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
668
return soap->error = soap->fpreparesend(soap, s, n);
672
if (soap->mode & SOAP_IO)
673
{ register size_t i = SOAP_BUFLEN - soap->bufidx;
675
{ memcpy(soap->buf + soap->bufidx, s, i);
676
soap->bufidx = SOAP_BUFLEN;
677
if (soap_flush(soap))
683
memcpy(soap->buf + soap->bufidx, s, n);
687
return soap_flush_raw(soap, s, n);
691
/******************************************************************************/
696
soap_flush(struct soap *soap)
697
{ register size_t n = soap->bufidx;
701
if (soap->mode & SOAP_ENC_ZLIB)
702
{ soap->d_stream.next_in = (Byte*)soap->buf;
703
soap->d_stream.avail_in = (unsigned int)n;
705
soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n);
708
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in));
709
if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK)
710
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
711
return soap->error = SOAP_ZLIB_ERROR;
713
if (!soap->d_stream.avail_out)
714
{ if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN))
716
soap->d_stream.next_out = (Byte*)soap->z_buf;
717
soap->d_stream.avail_out = SOAP_BUFLEN;
719
} while (soap->d_stream.avail_in);
723
return soap_flush_raw(soap, soap->buf, n);
729
/******************************************************************************/
734
soap_flush_raw(struct soap *soap, const char *s, size_t n)
735
{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
737
if (!(t = (char*)soap_push_block(soap, n)))
738
return soap->error = SOAP_EOM;
741
if (soap->fpreparesend)
742
return soap->error = soap->fpreparesend(soap, s, n);
747
if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
749
sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
750
DBGMSG(SENT, t, strlen(t));
751
if ((soap->error = soap->fsend(soap, t, strlen(t))))
753
soap->chunksize += n;
757
return soap->error = soap->fsend(soap, s, n);
761
/******************************************************************************/
766
soap_send(struct soap *soap, const char *s)
768
return soap_send_raw(soap, s, strlen(s));
773
/******************************************************************************/
779
soap_send2(struct soap *soap, const char *s1, const char *s2)
780
{ if (soap_send(soap, s1))
782
return soap_send(soap, s2);
787
/******************************************************************************/
793
soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3)
794
{ if (soap_send(soap, s1)
795
|| soap_send(soap, s2))
797
return soap_send(soap, s3);
802
/******************************************************************************/
806
frecv(struct soap *soap, char *s, size_t n)
809
register int timeouts = 6000; /* Palm: 1 min timeout for SSL */
812
#if defined(__cplusplus) && !defined(WITH_LEAN)
814
{ if (soap->is->good())
815
return soap->is->read(s, (std::streamsize)n).gcount();
819
if (soap_valid_socket(soap->socket))
823
register int err = 0;
827
if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */
829
if (soap->recv_timeout)
833
if ((int)soap->socket >= (int)FD_SETSIZE)
834
{ soap->error = SOAP_FD_EXCEEDED;
835
return 0; /* Hint: MUST increase FD_SETSIZE */
839
{ struct timeval timeout;
841
if (soap->recv_timeout > 0)
842
{ timeout.tv_sec = soap->recv_timeout;
846
{ timeout.tv_sec = -soap->recv_timeout/1000000;
847
timeout.tv_usec = -soap->recv_timeout%1000000;
850
FD_SET(soap->socket, &fd);
851
r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
858
r = soap_socket_errno(soap->socket);
859
if (r != SOAP_EINTR && r != SOAP_EAGAIN)
868
{ r = SSL_read(soap->ssl, s, (int)n);
871
err = SSL_get_error(soap->ssl, r);
872
if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
876
{ r = BIO_read(soap->bio, s, (int)n);
885
if ((soap->omode & SOAP_IO_UDP))
886
{ SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer);
887
memset((void*)&soap->peer, 0, sizeof(soap->peer));
888
r = recvfrom(soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
889
soap->peerlen = (size_t)k;
891
soap->ip = ntohl(soap->peer.sin_addr.s_addr);
896
r = recv(soap->socket, s, (int)n, soap->socket_flags);
898
/* CycleSyncDisplay(curStatusMsg); */
902
r = soap_socket_errno(soap->socket);
903
if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
909
{ struct timeval timeout;
911
if (soap->recv_timeout > 0)
912
{ timeout.tv_sec = soap->recv_timeout;
915
else if (soap->recv_timeout < 0)
916
{ timeout.tv_sec = -soap->recv_timeout/1000000;
917
timeout.tv_usec = -soap->recv_timeout%1000000;
920
{ timeout.tv_sec = 0;
921
timeout.tv_usec = 10000;
924
if ((int)soap->socket >= (int)FD_SETSIZE)
925
{ soap->error = SOAP_FD_EXCEEDED;
926
return 0; /* Hint: MUST increase FD_SETSIZE */
930
FD_SET(soap->socket, &fd);
932
if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
933
r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
935
r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
937
r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
939
if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR)
943
if (!r && soap->recv_timeout)
950
r = soap_socket_errno(soap->socket);
951
if (r != SOAP_EINTR && timeouts-- <= 0)
959
return fread(s, 1, n, stdin);
962
return fread(s, 1, n, soap->recvfd);
966
r = httpBlockRead(soap->rpmreqid, s, n);
969
r = read(soap->recvfd, s, (unsigned int)n);
972
soap->errnum = soap_errno;
980
/******************************************************************************/
985
frecv_stop(struct soap *soap, char *s, size_t n)
992
/******************************************************************************/
996
soap_getchunkchar(struct soap *soap)
997
{ if (soap->bufidx < soap->buflen)
998
return soap->buf[soap->bufidx++];
1000
soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1001
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket));
1002
DBGMSG(RECV, soap->buf, soap->buflen);
1004
return soap->buf[soap->bufidx++];
1010
/******************************************************************************/
1013
soap_isxdigit(int c)
1014
{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
1018
/******************************************************************************/
1023
soap_recv_raw(struct soap *soap)
1024
{ register size_t ret;
1026
if (soap->mode & SOAP_ENC_ZLIB)
1027
{ if (soap->d_stream.next_out == Z_NULL)
1029
if (soap->d_stream.avail_in || !soap->d_stream.avail_out)
1031
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n"));
1032
soap->d_stream.next_out = (Byte*)soap->buf;
1033
soap->d_stream.avail_out = SOAP_BUFLEN;
1034
r = inflate(&soap->d_stream, Z_NO_FLUSH);
1035
if (r == Z_OK || r == Z_STREAM_END)
1037
ret = soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out;
1038
if (soap->zlib_in == SOAP_ZLIB_GZIP)
1039
soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret);
1040
if (r == Z_STREAM_END)
1041
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
1042
soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
1043
soap->d_stream.next_out = Z_NULL;
1046
{ soap->count += ret;
1047
DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1048
DBGMSG(RECV, soap->buf, ret);
1049
DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n"));
1053
else if (r != Z_BUF_ERROR)
1054
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
1055
soap->d_stream.next_out = Z_NULL;
1056
soap->error = SOAP_ZLIB_ERROR;
1061
if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize)
1062
{ memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
1063
soap->buflen = soap->z_buflen;
1065
DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n"));
1069
if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */
1072
if (soap->chunksize)
1073
{ soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize);
1074
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret));
1075
DBGMSG(RECV, soap->buf, ret);
1077
soap->chunksize -= ret;
1080
{ register soap_wchar c;
1083
if (!soap->chunkbuflen)
1084
{ soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1085
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
1086
DBGMSG(RECV, soap->buf, ret);
1089
return soap->ahead = EOF;
1092
soap->bufidx = soap->buflen;
1093
soap->buflen = soap->chunkbuflen;
1094
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen));
1095
while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
1096
{ if ((int)c == EOF)
1097
return soap->ahead = EOF;
1101
while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7);
1102
while ((int)c != EOF && c != '\n')
1103
c = soap_getchunkchar(soap);
1105
return soap->ahead = EOF;
1107
soap->chunksize = soap_strtoul(tmp, &t, 16);
1108
if (!soap->chunksize)
1109
{ soap->chunkbuflen = 0;
1110
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n"));
1111
while ((int)c != EOF && c != '\n')
1112
c = soap_getchunkchar(soap);
1113
return soap->ahead = EOF;
1115
soap->buflen = soap->bufidx + soap->chunksize;
1116
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp));
1117
if (soap->buflen > soap->chunkbuflen)
1118
{ soap->buflen = soap->chunkbuflen;
1119
soap->chunksize -= soap->buflen - soap->bufidx;
1120
soap->chunkbuflen = 0;
1121
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx)));
1123
else if (soap->chunkbuflen)
1124
soap->chunksize = 0;
1125
ret = soap->buflen - soap->bufidx;
1133
soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
1134
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket));
1135
DBGMSG(RECV, soap->buf, ret);
1138
if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret)))
1142
if (soap->mode & SOAP_ENC_ZLIB)
1144
memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
1145
soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
1146
soap->d_stream.avail_in = (unsigned int)ret;
1147
soap->d_stream.next_out = (Byte*)soap->buf;
1148
soap->d_stream.avail_out = SOAP_BUFLEN;
1149
r = inflate(&soap->d_stream, Z_NO_FLUSH);
1150
if (r == Z_OK || r == Z_STREAM_END)
1152
soap->z_buflen = soap->buflen;
1153
soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out;
1154
if (soap->zlib_in == SOAP_ZLIB_GZIP)
1155
soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen);
1156
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret));
1159
if (r == Z_STREAM_END)
1160
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
1161
soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out;
1162
soap->d_stream.next_out = Z_NULL;
1164
DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n"));
1165
DBGMSG(RECV, soap->buf, ret);
1168
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:""));
1169
soap->d_stream.next_out = Z_NULL;
1170
soap->error = SOAP_ZLIB_ERROR;
1180
/******************************************************************************/
1185
soap_recv(struct soap *soap)
1188
if (soap->mode & SOAP_ENC_DIME)
1189
{ if (soap->dime.buflen)
1192
unsigned char tmp[12];
1193
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n"));
1194
soap->count += soap->dime.buflen - soap->buflen;
1195
soap->buflen = soap->dime.buflen;
1196
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3));
1197
for (i = -(long)soap->dime.size&3; i > 0; i--)
1199
if (soap->bufidx >= soap->buflen)
1200
if (soap_recv_raw(soap))
1203
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n"));
1205
for (i = 12; i > 0; i--)
1206
{ *s++ = soap->buf[soap->bufidx++];
1207
if (soap->bufidx >= soap->buflen)
1208
if (soap_recv_raw(soap))
1211
soap->dime.flags = tmp[0] & 0x7;
1212
soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
1213
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size));
1214
if (soap->dime.flags & SOAP_DIME_CF)
1215
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n"));
1216
soap->dime.chunksize = soap->dime.size;
1217
if (soap->buflen - soap->bufidx >= soap->dime.size)
1218
{ soap->dime.buflen = soap->buflen;
1219
soap->buflen = soap->bufidx + soap->dime.chunksize;
1222
soap->dime.chunksize -= soap->buflen - soap->bufidx;
1225
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n"));
1226
soap->dime.buflen = 0;
1227
soap->dime.chunksize = 0;
1229
soap->count = soap->buflen - soap->bufidx;
1230
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count));
1233
if (soap->dime.chunksize)
1234
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize));
1235
if (soap_recv_raw(soap))
1237
if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
1238
{ soap->dime.buflen = soap->buflen;
1239
soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize;
1240
soap->buflen = soap->bufidx + soap->dime.chunksize;
1243
soap->dime.chunksize -= soap->buflen - soap->bufidx;
1244
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count));
1249
return soap_recv_raw(soap);
1253
/******************************************************************************/
1258
soap_getchar(struct soap *soap)
1259
{ register soap_wchar c;
1266
return soap_get1(soap);
1270
/******************************************************************************/
1273
const struct soap_code_map*
1275
soap_code(const struct soap_code_map *code_map, const char *str)
1276
{ if (code_map && str)
1277
{ while (code_map->string)
1278
{ if (!strcmp(str, code_map->string)) /* case sensitive */
1287
/******************************************************************************/
1292
soap_code_int(const struct soap_code_map *code_map, const char *str, long other)
1294
{ while (code_map->string)
1295
{ if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */
1296
return code_map->code;
1304
/******************************************************************************/
1309
soap_code_str(const struct soap_code_map *code_map, long code)
1312
while (code_map->code != code && code_map->string)
1314
return code_map->string;
1318
/******************************************************************************/
1323
soap_code_bits(const struct soap_code_map *code_map, const char *str)
1324
{ register long bits = 0;
1326
{ while (str && *str)
1327
{ const struct soap_code_map *p;
1328
for (p = code_map; p->string; p++)
1329
{ register size_t n = strlen(p->string);
1330
if (!strncmp(p->string, str, n) && soap_blank(str[n]))
1333
while (*str > 0 && *str <= 32)
1346
/******************************************************************************/
1351
soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code)
1352
{ register char *t = soap->tmpbuf;
1354
{ while (code_map->string)
1355
{ if (code_map->code & code)
1356
{ register const char *s = code_map->string;
1357
if (t != soap->tmpbuf)
1359
while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1361
if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1)
1368
return soap->tmpbuf;
1372
/******************************************************************************/
1375
soap_char(struct soap *soap)
1378
register soap_wchar c;
1379
register char *s = tmp;
1380
for (i = 0; i < 7; i++)
1381
{ c = soap_get1(soap);
1382
if (c == ';' || (int)c == EOF)
1388
{ if (tmp[1] == 'x' || tmp[1] == 'X')
1389
return soap_strtol(tmp + 2, NULL, 16);
1390
return atol(tmp + 1);
1392
if (!strcmp(tmp, "lt"))
1394
if (!strcmp(tmp, "gt"))
1396
if (!strcmp(tmp, "amp"))
1398
if (!strcmp(tmp, "quot"))
1400
if (!strcmp(tmp, "apos"))
1403
return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR);
1405
return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */
1410
/******************************************************************************/
1414
soap_get0(struct soap *soap)
1415
{ if (soap->bufidx >= soap->buflen && soap_recv(soap))
1417
return (unsigned char)soap->buf[soap->bufidx];
1422
/******************************************************************************/
1426
soap_get1(struct soap *soap)
1427
{ if (soap->bufidx >= soap->buflen && soap_recv(soap))
1429
return (unsigned char)soap->buf[soap->bufidx++];
1434
/******************************************************************************/
1439
soap_get(struct soap *soap)
1440
{ register soap_wchar c;
1443
{ if ((int)c != EOF)
1447
c = soap_get1(soap);
1448
while ((int)c != EOF)
1451
{ c = soap_get1(soap);
1453
{ c = soap_get0(soap);
1457
c = soap_get1(soap);
1460
{ soap_unget(soap, ']');
1465
{ soap_revget1(soap);
1474
do c = soap_get1(soap);
1475
while (soap_blank(c));
1476
if (c == '!' || c == '?' || c == '%')
1477
{ register int k = 1;
1479
{ c = soap_get1(soap);
1481
{ do c = soap_get1(soap);
1482
while ((int)c != EOF && c != '[');
1486
c = soap_get1(soap);
1489
if (c == '-' && (c = soap_get1(soap)) == '-')
1491
{ c = soap_get1(soap);
1492
if (c == '-' && (c = soap_get1(soap)) == '-')
1494
} while ((int)c != EOF);
1498
c = soap_get_pi(soap);
1499
while ((int)c != EOF)
1506
c = soap_get1(soap);
1510
c = soap_get1(soap);
1524
return soap_char(soap) | 0x80000000;
1532
/******************************************************************************/
1535
soap_get_pi(struct soap *soap)
1537
register char *s = buf;
1538
register int i = sizeof(buf);
1539
register soap_wchar c = soap_getchar(soap);
1540
/* This is a quick way to parse XML PI and we could use a callback instead to
1541
* enable applications to intercept processing instructions */
1542
while ((int)c != EOF && c != '?')
1544
{ if (soap_blank(c))
1548
c = soap_getchar(soap);
1551
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <?%s?>\n", buf));
1552
if (!strncmp(buf, "xml ", 4))
1553
{ s = strstr(buf, " encoding=");
1555
{ if (!soap_tag_cmp(s + 11, "iso-8859-1*")
1556
|| !soap_tag_cmp(s + 11, "latin1*"))
1557
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n"));
1558
soap->mode |= SOAP_ENC_LATIN;
1560
else if (!soap_tag_cmp(s + 11, "utf-8*"))
1561
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n"));
1562
soap->mode &= ~SOAP_ENC_LATIN;
1567
c = soap_getchar(soap);
1572
/******************************************************************************/
1578
soap_move(struct soap *soap, long n)
1579
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
1581
if ((int)soap_getchar(soap) == EOF)
1588
/******************************************************************************/
1594
soap_tell(struct soap *soap)
1595
{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0);
1600
/******************************************************************************/
1605
soap_pututf8(struct soap *soap, register unsigned long c)
1607
if (c < 0x80 && c >= 0x20)
1609
return soap_send_raw(soap, tmp, 1);
1612
if (c >= 0x80 && (soap->mode & SOAP_XML_CANONICAL))
1613
{ register char *t = tmp;
1615
*t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
1618
*t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
1621
*t++ = (char)(0xF0 | ((c >> 18) & 0x07));
1623
{ if (c < 0x04000000)
1624
*t++ = (char)(0xF8 | ((c >> 24) & 0x03));
1626
{ *t++ = (char)(0xFC | ((c >> 30) & 0x01));
1627
*t++ = (char)(0x80 | ((c >> 24) & 0x3F));
1629
*t++ = (char)(0x80 | ((c >> 18) & 0x3F));
1631
*t++ = (char)(0x80 | ((c >> 12) & 0x3F));
1633
*t++ = (char)(0x80 | ((c >> 6) & 0x3F));
1635
*t++ = (char)(0x80 | (c & 0x3F));
1640
sprintf(tmp, "&#%lu;", c);
1641
return soap_send(soap, tmp);
1645
/******************************************************************************/
1650
soap_getutf8(struct soap *soap)
1651
{ register soap_wchar c, c1, c2, c3, c4;
1659
if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN))
1661
c1 = soap_get1(soap);
1663
{ soap_revget1(soap); /* doesn't look like this is UTF8 */
1668
return ((soap_wchar)(c & 0x1F) << 6) | c1;
1669
c2 = (soap_wchar)soap_get1(soap) & 0x3F;
1670
if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */
1673
return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2;
1674
c3 = (soap_wchar)soap_get1(soap) & 0x3F;
1676
return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
1677
c4 = (soap_wchar)soap_get1(soap) & 0x3F;
1679
return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
1680
return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F);
1684
/******************************************************************************/
1689
soap_puthex(struct soap *soap, const unsigned char *s, int n)
1693
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1694
{ if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n)))
1699
for (i = 0; i < n; i++)
1700
{ register int m = *s++;
1701
d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0'));
1703
d[1] = (char)(m + (m > 9 ? '7' : '0'));
1704
if (soap_send_raw(soap, d, 2))
1711
/******************************************************************************/
1716
soap_gethex(struct soap *soap, int *n)
1719
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1720
{ soap->dom->data = soap_string_in(soap, 0, -1, -1);
1721
return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n);
1728
register size_t i, k;
1729
if (soap_append_lab(soap, NULL, 0))
1731
s = soap->labbuf + soap->labidx;
1732
k = soap->lablen - soap->labidx;
1733
soap->labidx = soap->lablen;
1734
for (i = 0; i < k; i++)
1735
{ register char d1, d2;
1736
register soap_wchar c;
1738
if (soap_isxdigit(c))
1741
if (soap_isxdigit(c))
1744
{ soap->error = SOAP_TYPE;
1750
soap_unget(soap, c);
1752
*n = (int)(soap->lablen + i - k);
1753
p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
1755
memcpy(p, soap->labbuf, soap->lablen + i - k);
1758
*s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1762
if (soap_new_block(soap))
1766
register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN);
1768
{ soap_end_block(soap);
1771
for (i = 0; i < SOAP_BLKLEN; i++)
1772
{ register char d1, d2;
1773
register soap_wchar c = soap_get(soap);
1774
if (soap_isxdigit(c))
1777
if (soap_isxdigit(c))
1780
{ soap_end_block(soap);
1781
soap->error = SOAP_TYPE;
1787
soap_unget(soap, c);
1789
*n = (int)soap_size_block(soap, i);
1790
p = (unsigned char*)soap_save_block(soap, NULL, 0);
1793
*s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
1800
/******************************************************************************/
1805
soap_putbase64(struct soap *soap, const unsigned char *s, int n)
1807
register unsigned long m;
1812
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1813
{ if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n)))
1818
for (; n > 2; n -= 3, s += 3)
1820
m = (m << 8) | s[1];
1821
m = (m << 8) | s[2];
1822
for (i = 4; i > 0; m >>= 6)
1823
d[--i] = soap_base64o[m & 0x3F];
1824
if (soap_send_raw(soap, d, 4))
1829
for (i = 0; i < n; i++)
1830
m = (m << 8) | *s++;
1833
for (i++; i > 0; m >>= 6)
1834
d[--i] = soap_base64o[m & 0x3F];
1835
for (i = 3; i > n; i--)
1837
if (soap_send_raw(soap, d, 4))
1844
/******************************************************************************/
1849
soap_getbase64(struct soap *soap, int *n, int malloc_flag)
1852
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
1853
{ soap->dom->data = soap_string_in(soap, 0, -1, -1);
1854
return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n);
1860
{ register size_t i, k;
1862
if (soap_append_lab(soap, NULL, 2))
1864
s = soap->labbuf + soap->labidx;
1865
k = soap->lablen - soap->labidx;
1866
soap->labidx = 3 * (soap->lablen / 3);
1870
{ for (i = 0; i < k - 2; i += 3)
1871
{ register unsigned long m = 0;
1874
{ register soap_wchar c = soap_get(soap);
1875
if (c == '=' || c < 0)
1879
*s++ = (char)((m >> 4) & 0xFF);
1883
*s++ = (char)((m >> 10) & 0xFF);
1884
*s++ = (char)((m >> 2) & 0xFF);
1888
*n = (int)(soap->lablen + i - k);
1889
p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k);
1891
memcpy(p, soap->labbuf, soap->lablen + i - k);
1893
{ while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1896
soap_unget(soap, c);
1900
if (c >= 0 && c <= 79)
1901
{ register int b = soap_base64i[c];
1903
{ soap->error = SOAP_TYPE;
1909
else if (!soap_blank(c + '+'))
1910
{ soap->error = SOAP_TYPE;
1914
*s++ = (char)((m >> 16) & 0xFF);
1915
*s++ = (char)((m >> 8) & 0xFF);
1916
*s++ = (char)(m & 0xFF);
1921
if (soap_new_block(soap))
1925
register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */
1927
{ soap_end_block(soap);
1930
for (i = 0; i < SOAP_BLKLEN; i++)
1931
{ register unsigned long m = 0;
1934
{ register soap_wchar c = soap_get(soap);
1935
if (c == '=' || c < 0)
1940
*s++ = (char)((m >> 4) & 0xFF);
1944
*s++ = (char)((m >> 10) & 0xFF);
1945
*s++ = (char)((m >> 2) & 0xFF);
1949
*n = (int)soap_size_block(soap, i);
1950
p = (unsigned char*)soap_save_block(soap, NULL, 0);
1952
{ while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT)
1955
soap_unget(soap, c);
1959
if (c >= 0 && c <= 79)
1960
{ int b = soap_base64i[c];
1962
{ soap->error = SOAP_TYPE;
1968
else if (!soap_blank(c))
1969
{ soap->error = SOAP_TYPE;
1973
*s++ = (char)((m >> 16) & 0xFF);
1974
*s++ = (char)((m >> 8) & 0xFF);
1975
*s++ = (char)(m & 0xFF);
1982
/******************************************************************************/
1988
soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
1989
{ /* Check MTOM xop:Include element (within hex/base64Binary) */
1990
/* TODO: this code to be obsoleted with new import/xop.h conventions */
1991
int body = soap->body; /* should save type too? */
1992
if (!soap_peek_element(soap))
1993
{ if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href)
1994
{ if (soap_dime_forward(soap, ptr, size, id, type, options))
1997
if (soap->body && soap_element_end_in(soap, NULL))
2006
/******************************************************************************/
2012
soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options)
2013
{ struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist));
2016
*id = soap_strdup(soap, soap->href);
2020
return soap->error = SOAP_EOM;
2021
xp->next = soap->xlist;
2026
xp->options = options;
2033
/******************************************************************************/
2038
soap_strdup(struct soap *soap, const char *s)
2040
if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1)))
2046
/******************************************************************************/
2051
soap_new_block(struct soap *soap)
2052
{ struct soap_blist *p;
2053
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist));
2054
if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist))))
2056
p->next = soap->blist;
2064
/******************************************************************************/
2069
soap_push_block(struct soap *soap, size_t n)
2071
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n));
2072
if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t))))
2073
{ soap->error = SOAP_EOM;
2076
*(char**)p = soap->blist->ptr;
2077
*(size_t*)(p + sizeof(char*)) = n;
2078
soap->blist->ptr = p;
2079
soap->blist->size += n;
2080
return p + sizeof(char*) + sizeof(size_t);
2084
/******************************************************************************/
2089
soap_pop_block(struct soap *soap)
2091
if (!soap->blist->ptr)
2093
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n"));
2094
p = soap->blist->ptr;
2095
soap->blist->size -= *(size_t*)(p + sizeof(char*));
2096
soap->blist->ptr = *(char**)p;
2101
/******************************************************************************/
2102
#ifndef WITH_NOIDREF
2105
soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2)
2107
register struct soap_ilist *ip = NULL;
2108
register struct soap_flist *fp = NULL;
2110
register struct soap_xlist *xp = NULL;
2112
register void *p, **q;
2113
for (i = 0; i < SOAP_IDHASH; i++)
2114
{ for (ip = soap->iht[i]; ip; ip = ip->next)
2115
{ if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end)
2116
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2)));
2117
ip->ptr = (char*)ip->ptr + (p1-p2);
2119
for (q = &ip->link; q; q = (void**)p)
2121
if (p && (char*)p >= start && (char*)p < end)
2122
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p));
2123
*q = (char*)p + (p1-p2);
2126
for (q = &ip->copy; q; q = (void**)p)
2128
if (p && (char*)p >= start && (char*)p < end)
2129
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p));
2130
*q = (char*)p + (p1-p2);
2133
for (fp = ip->flist; fp; fp = fp->next)
2134
{ if ((char*)fp->ptr >= start && (char*)fp->ptr < end)
2135
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp));
2136
fp->ptr = (char*)fp->ptr + (p1-p2);
2142
for (xp = soap->xlist; xp; xp = xp->next)
2143
{ if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end)
2144
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2)));
2145
xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2));
2146
xp->size = (int*)((char*)xp->size + (p1-p2));
2147
xp->type = (char**)((char*)xp->type + (p1-p2));
2148
xp->options = (char**)((char*)xp->options + (p1-p2));
2156
/******************************************************************************/
2157
#ifndef WITH_NOIDREF
2160
soap_has_copies(struct soap *soap, register const char *start, register const char *end)
2162
register struct soap_ilist *ip = NULL;
2163
register struct soap_flist *fp = NULL;
2164
register const char *p;
2165
for (i = 0; i < SOAP_IDHASH; i++)
2166
{ for (ip = soap->iht[i]; ip; ip = ip->next)
2167
{ for (p = (const char*)ip->copy; p; p = *(const char**)p)
2168
if (p >= start && p < end)
2170
for (fp = ip->flist; fp; fp = fp->next)
2171
if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end)
2180
/******************************************************************************/
2181
#ifndef WITH_NOIDREF
2186
soap_resolve(struct soap *soap)
2188
register struct soap_ilist *ip = NULL;
2189
register struct soap_flist *fp = NULL;
2191
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n"));
2192
for (i = 0; i < SOAP_IDHASH; i++)
2193
{ for (ip = soap->iht[i]; ip; ip = ip->next)
2195
{ register void *p, **q, *r;
2196
q = (void**)ip->link;
2199
DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id));
2203
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r));
2207
else if (*ip->id == '#')
2208
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id));
2209
strcpy(soap->id, ip->id + 1);
2210
return soap->error = SOAP_MISSING_ID;
2216
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n"));
2217
for (i = 0; i < SOAP_IDHASH; i++)
2218
{ for (ip = soap->iht[i]; ip; ip = ip->next)
2219
{ if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size))
2221
{ register void *p, **q = (void**)ip->copy;
2222
DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id));
2225
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size));
2227
memcpy(q, ip->ptr, ip->size);
2232
for (fp = ip->flist; fp; fp = ip->flist)
2233
{ register unsigned int k = fp->level;
2234
register void *p = ip->ptr;
2235
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));
2236
while (ip->level < k)
2237
{ register void **q = (void**)soap_malloc(soap, sizeof(void*));
2241
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q));
2246
fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2248
soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size);
2249
ip->flist = fp->next;
2250
SOAP_FREE(soap, fp);
2258
for (i = 0; i < SOAP_IDHASH; i++)
2259
{ for (ip = soap->iht[i]; ip; ip = ip->next)
2260
{ if (ip->copy || ip->flist)
2261
{ 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));
2266
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n"));
2272
/******************************************************************************/
2277
soap_size_block(struct soap *soap, size_t n)
2278
{ if (soap->blist->ptr)
2279
{ soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n;
2280
*(size_t*)(soap->blist->ptr + sizeof(char*)) = n;
2282
return soap->blist->size;
2286
/******************************************************************************/
2291
soap_first_block(struct soap *soap)
2293
p = soap->blist->ptr;
2296
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n"));
2304
soap->blist->ptr = r;
2305
return r + sizeof(char*) + sizeof(size_t);
2309
/******************************************************************************/
2314
soap_next_block(struct soap *soap)
2316
p = soap->blist->ptr;
2318
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n"));
2319
soap->blist->ptr = *(char**)p;
2321
if (soap->blist->ptr)
2322
return soap->blist->ptr + sizeof(char*) + sizeof(size_t);
2328
/******************************************************************************/
2333
soap_block_size(struct soap *soap)
2334
{ return *(size_t*)(soap->blist->ptr + sizeof(char*));
2338
/******************************************************************************/
2343
soap_end_block(struct soap *soap)
2344
{ struct soap_blist *bp;
2348
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n"));
2349
for (p = bp->ptr; p; p = q)
2353
soap->blist = bp->next;
2354
SOAP_FREE(soap, bp);
2356
DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n"));
2360
/******************************************************************************/
2365
soap_save_block(struct soap *soap, char *p, int flag)
2366
{ register size_t n;
2367
register char *q, *s;
2368
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p));
2369
if (soap->blist->size)
2371
p = (char*)soap_malloc(soap, soap->blist->size);
2373
{ for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap))
2374
{ n = soap_block_size(soap);
2375
#ifndef WITH_NOIDREF
2377
soap_update_ptrs(soap, q, q + n, s, q);
2379
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s));
2385
soap->error = SOAP_EOM;
2387
soap_end_block(soap);
2392
/******************************************************************************/
2397
soap_putsize(struct soap *soap, const char *type, int size)
2398
{ return soap_putsizes(soap, type, &size, 1);
2402
/******************************************************************************/
2407
soap_putsizes(struct soap *soap, const char *type, const int *size, int dim)
2408
{ return soap_putsizesoffsets(soap, type, size, NULL, dim);
2412
/******************************************************************************/
2417
soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
2421
if (soap->version == 2)
2422
{ sprintf(soap->type, "%s[%d", type, size[0]);
2423
for (i = 1; i < dim; i++)
2424
sprintf(soap->type + strlen(soap->type), " %d", size[i]);
2428
{ sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
2429
for (i = 1; i < dim; i++)
2430
sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
2433
{ sprintf(soap->type, "%s[%d", type, size[0]);
2434
for (i = 1; i < dim; i++)
2435
sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
2437
strcat(soap->type, "]");
2443
/******************************************************************************/
2448
soap_putoffset(struct soap *soap, int offset)
2449
{ return soap_putoffsets(soap, &offset, 1);
2453
/******************************************************************************/
2458
soap_putoffsets(struct soap *soap, const int *offset, int dim)
2460
sprintf(soap->arrayOffset, "[%d", offset[0]);
2461
for (i = 1; i < dim; i++)
2462
sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
2463
strcat(soap->arrayOffset, "]");
2464
return soap->arrayOffset;
2468
/******************************************************************************/
2473
soap_size(const int *size, int dim)
2474
{ register int i, n = size[0];
2475
for (i = 1; i < dim; i++)
2481
/******************************************************************************/
2486
soap_getoffsets(const char *attr, const int *size, int *offset, int dim)
2487
{ register int i, j = 0;
2489
for (i = 0; i < dim && attr && *attr; i++)
2492
j += offset[i] = (int)atol(attr);
2493
attr = strchr(attr, ',');
2496
for (i = 0; i < dim && attr && *attr; i++)
2499
j += (int)atol(attr);
2500
attr = strchr(attr, ',');
2506
/******************************************************************************/
2511
soap_getsize(const char *attr1, const char *attr2, int *j)
2512
{ register int n, k;
2521
{ k = (int)soap_strtol(attr1, &s, 10);
2523
if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1)
2525
attr1 = strchr(s, ',');
2527
attr1 = strchr(s, ' ');
2528
if (attr2 && *attr2)
2531
k = (int)soap_strtol(attr2, &s, 10);
2545
/******************************************************************************/
2550
soap_getsizes(const char *attr, int *size, int dim)
2551
{ register int i, k, n;
2554
i = (int)strlen(attr);
2557
{ for (i = i-1; i >= 0; i--)
2558
if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ')
2560
k = (int)atol(attr + i + 1);
2561
n *= size[--dim] = k;
2562
if (k < 0 || n > SOAP_MAXARRAYSIZE)
2564
} while (i >= 0 && attr[i] != '[');
2569
/******************************************************************************/
2574
soap_getposition(const char *attr, int *pos)
2575
{ register int i, n;
2581
{ pos[n++] = (int)atol(attr + i);
2582
while (attr[i] && attr[i] != ',' && attr[i] != ']')
2586
} while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']');
2591
/******************************************************************************/
2596
soap_push_namespace(struct soap *soap, const char *id, const char *ns)
2597
{ register struct soap_nlist *np;
2598
register struct Namespace *p;
2599
register short i = -1;
2600
register size_t n, k;
2603
p = soap->local_namespaces;
2605
{ for (i = 0; p->id; p++, i++)
2606
{ if (p->ns && !strcmp(ns, p->ns))
2608
{ SOAP_FREE(soap, p->out);
2614
{ if (!strcmp(ns, p->out))
2618
{ if (!soap_tag_cmp(ns, p->in))
2619
{ if ((p->out = (char*)SOAP_MALLOC(soap, k)))
2630
np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k);
2632
return soap->error = SOAP_EOM;
2633
np->next = soap->nlist;
2635
np->level = soap->level;
2638
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns));
2640
{ np->ns = np->id + n + 1;
2642
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns));
2646
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id));
2652
/******************************************************************************/
2657
soap_pop_namespace(struct soap *soap)
2658
{ register struct soap_nlist *np, *nq;
2659
for (np = soap->nlist; np && np->level >= soap->level; np = nq)
2661
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id));
2662
SOAP_FREE(soap, np);
2668
/******************************************************************************/
2673
soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2)
2674
{ register struct soap_nlist *np = soap->nlist;
2675
while (np && (strncmp(np->id, id1, n1) || np->id[n1]))
2679
|| (soap->local_namespaces[np->index].id
2680
&& (strncmp(soap->local_namespaces[np->index].id, id2, n2)
2681
|| soap->local_namespaces[np->index].id[n2])))
2682
return SOAP_NAMESPACE;
2685
if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2))
2687
return soap->error = SOAP_SYNTAX_ERROR;
2691
/******************************************************************************/
2696
soap_current_namespace(struct soap *soap, const char *tag)
2697
{ register struct soap_nlist *np;
2698
register const char *s;
2700
if (!(s = strchr(tag, ':')))
2701
{ while (np && *np->id) /* find default namespace, if present */
2705
{ while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag]))
2708
soap->error = SOAP_NAMESPACE;
2711
{ if (np->index >= 0)
2712
return soap->namespaces[np->index].ns;
2714
return soap_strdup(soap, np->ns);
2720
/******************************************************************************/
2725
soap_tag_cmp(const char *s, const char *t)
2727
{ register int c1 = *s;
2728
register int c2 = *t;
2729
if (!c1 || c1 == '"')
2733
{ if (c1 >= 'A' && c1 <= 'Z')
2735
if (c2 >= 'A' && c2 <= 'Z')
2744
if (c2 >= 'A' && c2 <= 'Z')
2748
if (!c1 || c1 == '"')
2750
if (c1 >= 'A' && c1 <= 'Z')
2752
if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1))
2762
if (*t == '*' && !t[1])
2768
/******************************************************************************/
2773
soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
2774
{ register const char *s, *t;
2776
if (!tag1 || !tag2 || !*tag2)
2778
s = strchr(tag1, ':');
2779
t = strchr(tag2, ':');
2782
{ if (t[1] && SOAP_STRCMP(s + 1, t + 1))
2783
return SOAP_TAG_MISMATCH;
2784
if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)))
2785
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2786
if (err == SOAP_NAMESPACE)
2787
return SOAP_TAG_MISMATCH;
2791
else if (SOAP_STRCMP(tag1, t + 1))
2792
{ return SOAP_TAG_MISMATCH;
2794
else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2)))
2795
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2));
2796
if (err == SOAP_NAMESPACE)
2797
return SOAP_TAG_MISMATCH;
2800
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2));
2804
{ if (SOAP_STRCMP(s + 1, tag2))
2805
return SOAP_TAG_MISMATCH;
2807
else if (SOAP_STRCMP(tag1, tag2))
2808
return SOAP_TAG_MISMATCH;
2809
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2));
2814
/******************************************************************************/
2819
soap_match_array(struct soap *soap, const char *type)
2820
{ if (*soap->arrayType)
2821
if (soap_match_tag(soap, soap->arrayType, type)
2822
&& soap_match_tag(soap, soap->arrayType, "xsd:anyType")
2823
&& soap_match_tag(soap, soap->arrayType, "xsd:ur-type")
2825
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type));
2826
return SOAP_TAG_MISMATCH;
2832
/******************************************************************************\
2836
\******************************************************************************/
2839
/******************************************************************************/
2845
{ unsigned char buf[4];
2848
RAND_pseudo_bytes(buf, 4);
2853
/******************************************************************************/
2858
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)
2860
soap->keyfile = keyfile;
2861
soap->password = password;
2862
soap->cafile = cafile;
2863
soap->capath = capath;
2864
soap->dhfile = dhfile;
2865
soap->randfile = randfile;
2866
soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0);
2867
if (!(err = soap->fsslauth(soap)))
2869
SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid));
2875
/******************************************************************************/
2880
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)
2881
{ soap->keyfile = keyfile;
2882
soap->password = password;
2883
soap->cafile = cafile;
2884
soap->capath = capath;
2885
soap->dhfile = NULL;
2886
soap->ssl_flags = flags;
2887
soap->randfile = randfile;
2888
return soap->fsslauth(soap);
2892
/******************************************************************************/
2898
{ /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */
2900
{ ssl_init_done = 1;
2903
SSL_load_error_strings();
2905
if (!RAND_load_file("/dev/urandom", 1024))
2907
RAND_seed(buf, sizeof(buf));
2908
while (!RAND_status())
2910
RAND_seed(&r, sizeof(int));
2917
/******************************************************************************/
2922
soap_ssl_error(struct soap *soap, int ret)
2923
{ int err = SSL_get_error(soap->ssl, ret);
2924
const char *msg = soap_code_str(h_ssl_error_codes, err);
2926
strcpy(soap->msgbuf, msg);
2928
return ERR_error_string(err, soap->msgbuf);
2929
if (ERR_peek_error())
2931
strcat(soap->msgbuf, "\n");
2932
while ((r = ERR_get_error()))
2933
ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf));
2938
strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
2941
sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
2945
return soap->msgbuf;
2949
/******************************************************************************/
2952
ssl_password(char *buf, int num, int rwflag, void *userdata)
2953
{ if (num < (int)strlen((char*)userdata) + 1)
2955
return (int)strlen(strcpy(buf, (char*)userdata));
2959
/******************************************************************************/
2960
/* This callback is included for future references. It should not be deleted
2963
ssl_tmp_dh(SSL *ssl, int is_export, int keylength)
2964
{ static DH *dh512 = NULL;
2965
static DH *dh1024 = NULL;
2970
{ BIO *bio = BIO_new_file("dh512.pem", "r");
2972
{ dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2981
{ BIO *bio = BIO_new_file("dh1024.pem", "r");
2983
{ dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
2994
/******************************************************************************/
2997
ssl_auth_init(struct soap *soap)
3003
{ if (!(soap->ctx = SSL_CTX_new(SSLv23_method())))
3004
return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR);
3005
/* Alters the behavior of SSL read/write:
3006
SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY);
3010
{ if (!RAND_load_file(soap->randfile, -1))
3011
return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR);
3013
if (soap->cafile || soap->capath)
3014
{ if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath))
3015
return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR);
3016
if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3017
SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile));
3019
if (!SSL_CTX_set_default_verify_paths(soap->ctx))
3020
return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR);
3021
/* This code assumes a typical scenario, see alternative code below */
3023
{ if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
3024
return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR);
3026
{ SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
3027
SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
3029
if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
3030
return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
3032
/* Suggested alternative approach to check the key file for certs (cafile=NULL):
3034
{ SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password);
3035
SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password);
3037
if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile))
3038
{ if (soap->keyfile)
3039
{ if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile))
3040
return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR);
3041
if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
3042
return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR);
3046
if ((soap->ssl_flags & SOAP_SSL_RSA))
3047
{ RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL);
3048
if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa))
3051
return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR);
3055
else if (soap->dhfile)
3058
bio = BIO_new_file(soap->dhfile, "r");
3060
return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR);
3061
dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
3063
if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0)
3066
return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR);
3070
flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2);
3071
if ((soap->ssl_flags & SOAP_SSLv3))
3072
flags |= SSL_OP_NO_TLSv1;
3073
if ((soap->ssl_flags & SOAP_TLSv1))
3074
flags |= SSL_OP_NO_SSLv3;
3075
SSL_CTX_set_options(soap->ctx, flags);
3076
if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3077
mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
3078
else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
3079
mode = SSL_VERIFY_PEER;
3081
mode = SSL_VERIFY_NONE;
3082
SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify);
3083
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
3084
SSL_CTX_set_verify_depth(soap->ctx, 1);
3086
SSL_CTX_set_verify_depth(soap->ctx, 9);
3092
/******************************************************************************/
3095
ssl_verify_callback(int ok, X509_STORE_CTX *store)
3100
X509 *cert = X509_STORE_CTX_get_current_cert(store);
3101
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)));
3102
X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data));
3103
fprintf(stderr, "certificate issuer %s\n", data);
3104
X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data));
3105
fprintf(stderr, "certificate subject %s\n", data);
3108
/* Note: return 1 to continue, but unsafe progress will be terminated by SSL */
3113
/******************************************************************************/
3118
soap_ssl_accept(struct soap *soap)
3121
if (!soap_valid_socket(soap->socket))
3122
return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR);
3123
if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
3124
return SOAP_INVALID_SOCKET;
3126
{ soap->ssl = SSL_new(soap->ctx);
3128
return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3131
SSL_clear(soap->ssl);
3132
soap->imode |= SOAP_ENC_SSL;
3133
soap->omode |= SOAP_ENC_SSL;
3134
/* Set SSL sockets to non-blocking */
3136
{ u_long nonblocking = 1;
3137
ioctlsocket(soap->socket, FIONBIO, &nonblocking);
3139
#elif defined(VXWORKS)
3140
{ u_long nonblocking = 1;
3141
ioctl(soap->socket, FIONBIO, (int)&nonblocking);
3144
fcntl(soap->socket, F_SETFL, fcntl(soap->socket, F_GETFL)|O_NONBLOCK);
3146
bio = BIO_new_socket(soap->socket, BIO_NOCLOSE);
3147
SSL_set_bio(soap->ssl, bio, bio);
3148
timeouts = 100; /* 10 sec retries, 100 times 0.1 sec */
3149
while ((r = SSL_accept(soap->ssl)) <= 0)
3150
{ int err = SSL_get_error(soap->ssl, r);
3151
if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE)
3152
{ struct timeval timeout;
3155
if ((int)soap->socket >= (int)FD_SETSIZE)
3156
return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
3159
timeout.tv_usec = 100000;
3161
FD_SET(soap->socket, &fd);
3162
if (err == SSL_ERROR_WANT_READ)
3163
s = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
3165
s = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout);
3166
if (s < 0 && (s = soap_socket_errno(soap->socket)) != SOAP_EINTR)
3172
{ soap->errnum = err;
3175
if (timeouts-- <= 0)
3179
{ soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR);
3180
soap_closesock(soap);
3181
return SOAP_SSL_ERROR;
3183
if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION))
3186
if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3187
{ soap_closesock(soap);
3188
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);
3190
peer = SSL_get_peer_certificate(soap->ssl);
3192
{ soap_closesock(soap);
3193
return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR);
3201
/******************************************************************************/
3202
#endif /* WITH_OPENSSL */
3204
/******************************************************************************/
3208
tcp_init(struct soap *soap)
3209
{ soap->errmode = 1;
3215
if (WSAStartup(MAKEWORD(1, 1), &w))
3225
/******************************************************************************/
3230
soap_done(struct soap *soap)
3235
if (soap_check_state(soap))
3237
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n"));
3238
soap_free_temp(soap);
3240
{ struct soap_clist *p = soap->clist->next;
3241
SOAP_FREE(soap, soap->clist);
3244
soap->keep_alive = 0; /* to force close the socket */
3245
soap_closesock(soap);
3247
soap_free_cookies(soap);
3249
while (soap->plugins)
3250
{ register struct soap_plugin *p = soap->plugins->next;
3251
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id));
3252
if (soap->plugins->fcopy || soap->state == SOAP_INIT)
3253
soap->plugins->fdelete(soap, soap->plugins);
3254
SOAP_FREE(soap, soap->plugins);
3257
soap->fplugin = fplugin;
3258
soap->fmalloc = NULL;
3260
soap->fpost = http_post;
3261
soap->fget = http_get;
3263
soap->fposthdr = http_post_header;
3264
soap->fresponse = http_response;
3265
soap->fparse = http_parse;
3266
soap->fparsehdr = http_parse_header;
3268
soap->fheader = NULL;
3271
soap->fresolve = tcp_gethost;
3273
soap->fresolve = NULL;
3275
soap->faccept = tcp_accept;
3276
soap->fopen = tcp_connect;
3277
soap->fclose = tcp_disconnect;
3278
soap->fclosesocket = tcp_closesocket;
3279
soap->fshutdownsocket = tcp_shutdownsocket;
3280
soap->fsend = fsend;
3281
soap->frecv = frecv;
3282
soap->fpoll = soap_poll;
3285
soap->fclose = NULL;
3289
soap->fprepareinit = NULL;
3290
soap->fpreparesend = NULL;
3291
soap->fpreparerecv = NULL;
3292
soap->fpreparefinal = NULL;
3294
soap->fseterror = NULL;
3295
soap->fignore = NULL;
3296
soap->fserveloop = NULL;
3299
{ SSL_SESSION_free(soap->session);
3300
soap->session = NULL;
3303
if (soap->state == SOAP_INIT)
3304
{ if (soap_valid_socket(soap->master))
3305
{ soap->fclosesocket(soap, soap->master);
3306
soap->master = SOAP_INVALID_SOCKET;
3310
{ SSL_CTX_free(soap->ctx);
3316
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n"));
3317
for (i = 0; i < SOAP_MAXLOGS; i++)
3318
{ if (soap->logfile[i])
3319
{ SOAP_FREE(soap, (void*)soap->logfile[i]);
3320
soap->logfile[i] = NULL;
3322
soap_close_logfile(soap, i);
3326
#ifdef SOAP_MEM_DEBUG
3327
soap_free_mht(soap);
3332
/******************************************************************************/
3338
soap_cleanup(struct soap *soap)
3350
/******************************************************************************/
3354
tcp_error(struct soap *soap)
3355
{ register const char *msg = NULL;
3356
switch (soap->errmode)
3358
msg = soap_strerror(soap);
3361
msg = "WSAStartup failed";
3366
msg = soap_code_str(h_error_codes, soap->errnum);
3369
{ sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
3379
/******************************************************************************/
3383
http_error(struct soap *soap, int status)
3384
{ register const char *msg = SOAP_STR_EOS;
3386
msg = soap_code_str(h_http_error_codes, status);
3395
/******************************************************************************/
3400
tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
3401
{ soap_int32 iadd = -1;
3402
struct hostent hostent, *host = &hostent;
3405
/* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */
3406
iadd = inet_addr((char*)addr);
3408
#if defined(_AIX43) || defined(TRU64)
3409
struct hostent_data ht_data;
3412
iadd = inet_addr((void*)addr);
3414
iadd = inet_addr(addr);
3418
{ memcpy(inaddr, &iadd, sizeof(iadd));
3421
#if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
3422
if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
3424
#elif defined(_AIX43) || defined(TRU64)
3425
memset((void*)&ht_data, 0, sizeof(ht_data));
3426
if (gethostbyname_r(addr, &hostent, &ht_data) < 0)
3428
soap->errnum = h_errno;
3430
#elif defined(HAVE_GETHOSTBYNAME_R)
3431
host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum);
3432
#elif defined(VXWORKS)
3433
/* If the DNS resolver library resolvLib has been configured in the vxWorks
3434
* image, a query for the host IP address is sent to the DNS server, if the
3435
* name was not found in the local host table. */
3436
hostint = hostGetByName((char*)addr);
3437
if (hostint == ERROR)
3439
soap->errnum = soap_errno;
3443
if (!(host = gethostbyname((void*)addr)))
3444
soap->errnum = h_errno;
3446
if (!(host = gethostbyname(addr)))
3447
soap->errnum = h_errno;
3451
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n"));
3455
inaddr->s_addr = hostint;
3457
memcpy(inaddr, host->h_addr, host->h_length);
3465
/******************************************************************************/
3469
tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port)
3472
struct addrinfo hints, *res, *ressave;
3478
int len = SOAP_BUFLEN;
3481
if (soap_valid_socket(soap->socket))
3482
soap->fclosesocket(soap, soap->socket);
3483
soap->socket = SOAP_INVALID_SOCKET;
3486
soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR);
3487
return SOAP_INVALID_SOCKET;
3491
memset((void*)&hints, 0, sizeof(hints));
3492
hints.ai_family = PF_UNSPEC;
3494
if ((soap->omode & SOAP_IO_UDP))
3495
hints.ai_socktype = SOCK_DGRAM;
3498
hints.ai_socktype = SOCK_STREAM;
3500
if (soap->proxy_host)
3501
err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res);
3503
err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res);
3505
{ soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR);
3506
return SOAP_INVALID_SOCKET;
3510
fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
3517
if ((soap->omode & SOAP_IO_UDP))
3518
fd = socket(AF_INET, SOCK_DGRAM, 0);
3521
fd = socket(AF_INET, SOCK_STREAM, 0);
3523
if (!soap_valid_socket(fd))
3524
{ soap->errnum = soap_socket_errno(fd);
3525
soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR);
3527
freeaddrinfo(ressave);
3529
return SOAP_INVALID_SOCKET;
3531
#ifdef SOCKET_CLOSE_ON_EXEC
3534
SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
3537
fcntl(fd, F_SETFD, 1);
3541
if (soap->connect_flags == SO_LINGER)
3542
{ struct linger linger;
3543
memset((void*)&linger, 0, sizeof(linger));
3545
linger.l_linger = 0;
3546
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
3547
{ soap->errnum = soap_socket_errno(fd);
3548
soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR);
3549
soap->fclosesocket(soap, fd);
3551
freeaddrinfo(ressave);
3553
return SOAP_INVALID_SOCKET;
3556
else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int)))
3557
{ soap->errnum = soap_socket_errno(fd);
3558
soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR);
3559
soap->fclosesocket(soap, fd);
3561
freeaddrinfo(ressave);
3563
return SOAP_INVALID_SOCKET;
3565
if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
3566
{ soap->errnum = soap_socket_errno(fd);
3567
soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR);
3568
soap->fclosesocket(soap, fd);
3570
freeaddrinfo(ressave);
3572
return SOAP_INVALID_SOCKET;
3574
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
3575
{ soap->errnum = soap_socket_errno(fd);
3576
soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3577
soap->fclosesocket(soap, fd);
3579
freeaddrinfo(ressave);
3581
return SOAP_INVALID_SOCKET;
3583
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
3584
{ soap->errnum = soap_socket_errno(fd);
3585
soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR);
3586
soap->fclosesocket(soap, fd);
3588
freeaddrinfo(ressave);
3590
return SOAP_INVALID_SOCKET;
3593
if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (unsigned int*)&(soap->tcp_keep_idle), sizeof(int)))
3594
{ soap->errnum = soap_socket_errno(fd);
3595
soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR);
3596
soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3598
freeaddrinfo(ressave);
3600
return SOAP_INVALID_SOCKET;
3603
#ifdef TCP_KEEPINTVL
3604
if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (unsigned int*)&(soap->tcp_keep_intvl), sizeof(int)))
3605
{ soap->errnum = soap_socket_errno(fd);
3606
soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR);
3607
soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3609
freeaddrinfo(ressave);
3611
return SOAP_INVALID_SOCKET;
3615
if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (unsigned int*)&(soap->tcp_keep_cnt), sizeof(int)))
3616
{ soap->errnum = soap_socket_errno(fd);
3617
soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR);
3618
soap->fclosesocket(soap, (SOAP_SOCKET)fd);
3620
freeaddrinfo(ressave);
3622
return SOAP_INVALID_SOCKET;
3626
if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
3627
{ soap->errnum = soap_socket_errno(fd);
3628
soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR);
3629
soap->fclosesocket(soap, fd);
3631
freeaddrinfo(ressave);
3633
return SOAP_INVALID_SOCKET;
3637
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port));
3639
soap->peerlen = sizeof(soap->peer);
3640
memset((void*)&soap->peer, 0, sizeof(soap->peer));
3641
soap->peer.sin_family = AF_INET;
3643
if (soap->proxy_host)
3644
{ if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr))
3645
{ soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3646
soap->fclosesocket(soap, fd);
3648
freeaddrinfo(ressave);
3650
return SOAP_INVALID_SOCKET;
3652
soap->peer.sin_port = htons((short)soap->proxy_port);
3655
{ if (soap->fresolve(soap, host, &soap->peer.sin_addr))
3656
{ soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR);
3657
soap->fclosesocket(soap, fd);
3659
freeaddrinfo(ressave);
3661
return SOAP_INVALID_SOCKET;
3663
soap->peer.sin_port = htons((short)port);
3666
if ((soap->omode & SOAP_IO_UDP))
3669
freeaddrinfo(ressave);
3675
if (soap->connect_timeout)
3677
{ u_long nonblocking = 1;
3678
ioctlsocket(fd, FIONBIO, &nonblocking);
3680
#elif defined(VXWORKS)
3681
{ u_long nonblocking = 1;
3682
ioctl(fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */
3685
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
3689
{ u_long blocking = 0;
3690
ioctlsocket(fd, FIONBIO, &blocking);
3692
#elif defined(VXWORKS)
3693
{ u_long blocking = 0;
3694
ioctl(fd, FIONBIO, (int)(&blocking));
3697
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
3703
if (connect(fd, res->ai_addr, (int)res->ai_addrlen))
3705
if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer)))
3707
{ err = soap_socket_errno(fd);
3709
if (err == SOAP_EADDRINUSE)
3710
{ soap->fclosesocket(soap, fd);
3714
else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EWOULDBLOCK))
3718
if ((int)soap->socket >= (int)FD_SETSIZE)
3719
{ soap->error = SOAP_FD_EXCEEDED;
3721
freeaddrinfo(ressave);
3723
return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
3727
{ struct timeval timeout;
3730
if (soap->connect_timeout > 0)
3731
{ timeout.tv_sec = soap->connect_timeout;
3732
timeout.tv_usec = 0;
3735
{ timeout.tv_sec = -soap->connect_timeout/1000000;
3736
timeout.tv_usec = -soap->connect_timeout%1000000;
3740
r = select((int)fd + 1, NULL, &fds, NULL, &timeout);
3745
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
3746
soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3747
soap->fclosesocket(soap, fd);
3749
freeaddrinfo(ressave);
3751
return SOAP_INVALID_SOCKET;
3753
r = soap_socket_errno(fd);
3754
if (r != SOAP_EINTR)
3756
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3757
soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3758
soap->fclosesocket(soap, fd);
3760
freeaddrinfo(ressave);
3762
return SOAP_INVALID_SOCKET;
3765
k = (SOAP_SOCKLEN_T)sizeof(soap->errnum);
3766
if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
3768
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3770
soap->errnum = soap_socket_errno(fd);
3771
soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3772
soap->fclosesocket(soap, fd);
3774
freeaddrinfo(ressave);
3776
return SOAP_INVALID_SOCKET;
3781
{ res = res->ai_next;
3782
soap->fclosesocket(soap, fd);
3786
if (err && err != SOAP_EINTR)
3787
{ soap->errnum = err;
3788
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
3789
soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3790
soap->fclosesocket(soap, fd);
3792
freeaddrinfo(ressave);
3794
return SOAP_INVALID_SOCKET;
3801
soap->peerlen = 0; /* IPv6: already connected so use send() */
3802
freeaddrinfo(ressave);
3805
if (soap->connect_timeout)
3807
{ u_long blocking = 0;
3808
ioctlsocket(fd, FIONBIO, &blocking);
3810
#elif defined(VXWORKS)
3811
{ u_long blocking = 0;
3812
ioctl(fd, FIONBIO, (int)(&blocking));
3815
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK);
3819
soap->imode &= ~SOAP_ENC_SSL;
3820
soap->omode &= ~SOAP_ENC_SSL;
3821
if (!soap_tag_cmp(endpoint, "https:*"))
3826
if (soap->proxy_host)
3827
{ unsigned int k = soap->omode; /* make sure we only parse HTTP */
3828
size_t n = soap->count; /* save the content length */
3829
char *userid, *passwd;
3830
soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
3831
soap->omode |= SOAP_IO_BUFFER;
3832
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version));
3833
sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version);
3834
if (soap_begin_send(soap)
3835
|| (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL)))
3836
{ soap->fclosesocket(soap, fd);
3837
return SOAP_INVALID_SOCKET;
3840
if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
3841
{ sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
3842
strcpy(soap->tmpbuf, "Basic ");
3843
soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
3844
if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
3845
{ soap->fclosesocket(soap, fd);
3850
if ((soap->error = soap->fposthdr(soap, NULL, NULL))
3851
|| soap_flush(soap))
3852
{ soap->fclosesocket(soap, fd);
3853
return SOAP_INVALID_SOCKET;
3857
soap->imode &= ~SOAP_ENC; /* mask IO and ENC */
3858
userid = soap->userid; /* preserve */
3859
passwd = soap->passwd; /* preserve */
3860
if ((soap->error = soap->fparse(soap)))
3861
{ soap->fclosesocket(soap, fd);
3862
return SOAP_INVALID_SOCKET;
3864
soap->userid = userid; /* restore */
3865
soap->passwd = passwd; /* restore */
3866
soap->imode = k; /* restore */
3867
soap->count = n; /* restore */
3868
if (soap_begin_send(soap))
3869
{ soap->fclosesocket(soap, fd);
3870
return SOAP_INVALID_SOCKET;
3873
strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */
3875
if (!soap->ctx && (soap->error = soap->fsslauth(soap)))
3876
{ soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR);
3877
soap->fclosesocket(soap, fd);
3878
return SOAP_INVALID_SOCKET;
3880
soap->ssl = SSL_new(soap->ctx);
3882
{ soap->fclosesocket(soap, fd);
3883
soap->error = SOAP_SSL_ERROR;
3884
return SOAP_INVALID_SOCKET;
3887
{ if (!strcmp(soap->session_host, host) && soap->session_port == port)
3888
SSL_set_session(soap->ssl, soap->session);
3889
SSL_SESSION_free(soap->session);
3890
soap->session = NULL;
3892
soap->imode |= SOAP_ENC_SSL;
3893
soap->omode |= SOAP_ENC_SSL;
3894
bio = BIO_new_socket(fd, BIO_NOCLOSE);
3895
SSL_set_bio(soap->ssl, bio, bio);
3896
/* Connect timeout: set SSL sockets to non-blocking */
3898
if (soap->connect_timeout)
3900
{ u_long nonblocking = 1;
3901
ioctlsocket(fd, FIONBIO, &nonblocking);
3903
#elif defined(VXWORKS)
3904
{ u_long nonblocking = 1;
3905
ioctl(fd, FIONBIO, (int)(&nonblocking));
3908
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
3911
/* Try connecting until success or timeout */
3913
{ if ((r = SSL_connect(soap->ssl)) <= 0)
3914
{ int err = SSL_get_error(soap->ssl, r);
3915
if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3916
{ soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR);
3917
soap->fclosesocket(soap, fd);
3918
return SOAP_INVALID_SOCKET;
3920
if (soap->connect_timeout)
3923
if ((int)soap->socket >= (int)FD_SETSIZE)
3924
{ soap->error = SOAP_FD_EXCEEDED;
3925
return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
3929
{ struct timeval timeout;
3932
if (soap->connect_timeout > 0)
3933
{ timeout.tv_sec = soap->connect_timeout;
3934
timeout.tv_usec = 0;
3937
{ timeout.tv_sec = -soap->connect_timeout/1000000;
3938
timeout.tv_usec = -soap->connect_timeout%1000000;
3942
r = select((int)fd + 1, &fds, NULL, &fds, &timeout);
3947
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n"));
3948
soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR);
3949
soap->fclosesocket(soap, fd);
3950
return SOAP_INVALID_SOCKET;
3958
/* Set SSL sockets to non-blocking */
3961
{ u_long nonblocking = 1;
3962
ioctlsocket(fd, FIONBIO, &nonblocking);
3964
#elif defined(VXWORKS)
3965
{ u_long nonblocking = 1;
3966
ioctl(fd, FIONBIO, (int)(&nonblocking));
3969
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
3972
/* Check server credentials when required */
3973
if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION))
3975
if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK)
3976
{ 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);
3977
soap->fclosesocket(soap, fd);
3978
return SOAP_INVALID_SOCKET;
3980
if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
3985
peer = SSL_get_peer_certificate(soap->ssl);
3987
{ soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
3988
soap->fclosesocket(soap, fd);
3989
return SOAP_INVALID_SOCKET;
3991
ext_count = X509_get_ext_count(peer);
3994
for (i = 0; i < ext_count; i++)
3995
{ X509_EXTENSION *ext = X509_get_ext(peer, i);
3996
const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
3997
if (ext_str && !strcmp(ext_str, "subjectAltName"))
3998
{ X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext);
4000
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
4001
const unsigned char *data;
4003
unsigned char *data;
4005
STACK_OF(CONF_VALUE) *val;
4009
data = ext->value->data;
4010
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
4012
ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
4014
{ /* OpenSSL not perfectly portable at this point (?):
4015
Some compilers appear to prefer
4016
meth->d2i(NULL, (const unsigned char**)&data, ...
4018
meth->d2i(NULL, &data, ext->value->length);
4020
ext_data = meth->d2i(NULL, &data, ext->value->length);
4023
ext_data = meth->d2i(NULL, &data, ext->value->length);
4025
val = meth->i2v(meth, ext_data, NULL);
4026
for (j = 0; j < sk_CONF_VALUE_num(val); j++)
4027
{ CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
4028
if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
4038
if (!ok && (subj = X509_get_subject_name(peer)))
4041
{ ASN1_STRING *name;
4042
i = X509_NAME_get_index_by_NID(subj, NID_commonName, i);
4045
name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i));
4047
{ if (!soap_tag_cmp(host, (const char*)name))
4050
{ unsigned char *tmp = NULL;
4051
ASN1_STRING_to_UTF8(&tmp, name);
4053
{ if (!soap_tag_cmp(host, (const char*)tmp))
4063
{ soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR);
4064
soap->fclosesocket(soap, fd);
4065
return SOAP_INVALID_SOCKET;
4070
soap->fclosesocket(soap, fd);
4071
soap->error = SOAP_SSL_ERROR;
4072
return SOAP_INVALID_SOCKET;
4080
/******************************************************************************/
4086
soap_bind(struct soap *soap, const char *host, int port, int backlog)
4089
struct addrinfo *addrinfo = NULL;
4090
struct addrinfo hints;
4091
struct addrinfo res;
4095
int len = SOAP_BUFLEN;
4098
if (soap_valid_socket(soap->master))
4099
{ soap->fclosesocket(soap, soap->master);
4100
soap->master = SOAP_INVALID_SOCKET;
4102
soap->socket = SOAP_INVALID_SOCKET;
4105
{ soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR);
4106
return SOAP_INVALID_SOCKET;
4109
memset((void*)&hints, 0, sizeof(hints));
4110
hints.ai_family = PF_UNSPEC;
4112
if ((soap->omode & SOAP_IO_UDP))
4113
hints.ai_socktype = SOCK_DGRAM;
4116
hints.ai_socktype = SOCK_STREAM;
4117
hints.ai_flags = AI_PASSIVE;
4119
err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo);
4122
memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen);
4123
soap->peerlen = addrinfo->ai_addrlen;
4124
res.ai_addr = (struct sockaddr*)&soap->peer;
4125
res.ai_addrlen = soap->peerlen;
4126
freeaddrinfo(addrinfo);
4128
if (err || !addrinfo)
4129
{ soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR);
4130
return SOAP_INVALID_SOCKET;
4132
soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol);
4135
if ((soap->omode & SOAP_IO_UDP))
4136
soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0);
4139
soap->master = (int)socket(AF_INET, SOCK_STREAM, 0);
4142
if (!soap_valid_socket(soap->master))
4143
{ soap->errnum = soap_socket_errno(soap->master);
4144
soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR);
4145
return SOAP_INVALID_SOCKET;
4148
if ((soap->omode & SOAP_IO_UDP))
4149
soap->socket = soap->master;
4151
#ifdef SOCKET_CLOSE_ON_EXEC
4154
SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0);
4157
fcntl(soap->master, F_SETFD, 1);
4161
if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int)))
4162
{ soap->errnum = soap_socket_errno(soap->master);
4163
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR);
4164
return SOAP_INVALID_SOCKET;
4166
if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4167
{ soap->errnum = soap_socket_errno(soap->master);
4168
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR);
4169
return SOAP_INVALID_SOCKET;
4171
if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4172
{ soap->errnum = soap_socket_errno(soap->master);
4173
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR);
4174
return SOAP_INVALID_SOCKET;
4176
if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4177
{ soap->errnum = soap_socket_errno(soap->master);
4178
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR);
4179
return SOAP_INVALID_SOCKET;
4182
if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4183
{ soap->errnum = soap_socket_errno(soap->master);
4184
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR);
4185
return SOAP_INVALID_SOCKET;
4191
if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen))
4192
{ soap->errnum = soap_socket_errno(soap->master);
4193
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4194
soap_closesock(soap);
4195
soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
4196
return SOAP_INVALID_SOCKET;
4199
soap->peerlen = sizeof(soap->peer);
4200
memset((void*)&soap->peer, 0, sizeof(soap->peer));
4201
soap->peer.sin_family = AF_INET;
4204
{ if (soap->fresolve(soap, host, &soap->peer.sin_addr))
4205
{ soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR);
4206
return SOAP_INVALID_SOCKET;
4210
soap->peer.sin_addr.s_addr = htonl(INADDR_ANY);
4211
soap->peer.sin_port = htons((short)port);
4213
if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen))
4214
{ soap->errnum = soap_socket_errno(soap->master);
4215
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4216
soap_closesock(soap);
4217
soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR);
4218
return SOAP_INVALID_SOCKET;
4221
if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog))
4222
{ soap->errnum = soap_socket_errno(soap->master);
4223
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n"));
4224
soap_closesock(soap);
4225
soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR);
4226
return SOAP_INVALID_SOCKET;
4228
return soap->master;
4233
/******************************************************************************/
4239
soap_poll(struct soap *soap)
4242
struct timeval timeout;
4243
fd_set rfd, sfd, xfd;
4246
if ((int)soap->socket >= (int)FD_SETSIZE)
4247
return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */
4250
timeout.tv_usec = 0;
4254
if (soap_valid_socket(soap->socket))
4255
{ FD_SET(soap->socket, &rfd);
4256
FD_SET(soap->socket, &sfd);
4257
FD_SET(soap->socket, &xfd);
4258
r = select((int)soap->socket + 1, &rfd, &sfd, &xfd, &timeout);
4259
if (r > 0 && FD_ISSET(soap->socket, &xfd))
4262
else if (soap_valid_socket(soap->master))
4263
{ FD_SET(soap->master, &sfd);
4264
r = select((int)soap->master + 1, NULL, &sfd, NULL, &timeout);
4271
if (soap->imode & SOAP_ENC_SSL)
4273
if (soap_valid_socket(soap->socket)
4274
&& FD_ISSET(soap->socket, &sfd)
4275
&& (!FD_ISSET(soap->socket, &rfd)
4276
|| SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0))
4281
if (soap_valid_socket(soap->socket)
4282
&& FD_ISSET(soap->socket, &sfd)
4283
&& (!FD_ISSET(soap->socket, &rfd)
4284
|| recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
4288
{ soap->errnum = soap_socket_errno(soap->master);
4289
if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
4290
{ soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR);
4291
return soap->error = SOAP_TCP_ERROR;
4296
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r));
4305
/******************************************************************************/
4309
tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n)
4311
fd = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */
4312
#ifdef SOCKET_CLOSE_ON_EXEC
4315
SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0);
4318
fcntl(fd, F_SETFD, FD_CLOEXEC);
4326
/******************************************************************************/
4332
soap_accept(struct soap *soap)
4333
{ int n = (int)sizeof(soap->peer);
4335
int len = SOAP_BUFLEN;
4338
soap->error = SOAP_OK;
4340
if ((soap->omode & SOAP_IO_UDP))
4341
return soap->socket = soap->master;
4343
memset((void*)&soap->peer, 0, sizeof(soap->peer));
4344
soap->socket = SOAP_INVALID_SOCKET;
4346
soap->keep_alive = 0;
4347
if (soap_valid_socket(soap->master))
4352
if (soap->accept_timeout)
4355
if ((int)soap->socket >= (int)FD_SETSIZE)
4356
{ soap->error = SOAP_FD_EXCEEDED;
4357
return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */
4361
{ struct timeval timeout;
4364
if (soap->accept_timeout > 0)
4365
{ timeout.tv_sec = soap->accept_timeout;
4366
timeout.tv_usec = 0;
4369
{ timeout.tv_sec = -soap->accept_timeout/1000000;
4370
timeout.tv_usec = -soap->accept_timeout%1000000;
4373
FD_SET(soap->master, &fd);
4374
r = select((int)soap->master + 1, &fd, &fd, &fd, &timeout);
4379
soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR);
4380
return SOAP_INVALID_SOCKET;
4382
r = soap_socket_errno(soap->master);
4383
if (r != SOAP_EINTR)
4385
soap_closesock(soap);
4386
soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4387
return SOAP_INVALID_SOCKET;
4391
{ u_long nonblocking = 1;
4392
ioctlsocket(soap->master, FIONBIO, &nonblocking);
4394
#elif defined(VXWORKS)
4395
{ u_long nonblocking = 1;
4396
ioctl(soap->master, FIONBIO, (int)(&nonblocking));
4399
fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL)|O_NONBLOCK);
4404
{ u_long blocking = 0;
4405
ioctlsocket(soap->master, FIONBIO, &blocking);
4407
#elif defined(VXWORKS)
4408
{ u_long blocking = 0;
4409
ioctl(soap->master, FIONBIO, (int)(&blocking));
4412
fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL)&~O_NONBLOCK);
4415
soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n);
4416
soap->peerlen = (size_t)n;
4417
if (soap_valid_socket(soap->socket))
4420
/* Use soap->host to store the numeric form of the remote host */
4421
getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
4422
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host));
4423
soap->ip = 0; /* info stored in soap->peer and soap->host */
4424
soap->port = 0; /* info stored in soap->peer and soap->host */
4426
soap->ip = ntohl(soap->peer.sin_addr.s_addr);
4427
soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
4428
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));
4431
if (soap->accept_flags == SO_LINGER)
4432
{ struct linger linger;
4433
memset((void*)&linger, 0, sizeof(linger));
4435
linger.l_linger = 0;
4436
if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger)))
4437
{ soap->errnum = soap_socket_errno(soap->socket);
4438
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR);
4439
soap_closesock(soap);
4440
return SOAP_INVALID_SOCKET;
4443
else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int)))
4444
{ soap->errnum = soap_socket_errno(soap->socket);
4445
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR);
4446
soap_closesock(soap);
4447
return SOAP_INVALID_SOCKET;
4449
if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int)))
4450
{ soap->errnum = soap_socket_errno(soap->socket);
4451
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR);
4452
soap_closesock(soap);
4453
return SOAP_INVALID_SOCKET;
4455
if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int)))
4456
{ soap->errnum = soap_socket_errno(soap->socket);
4457
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR);
4458
soap_closesock(soap);
4459
return SOAP_INVALID_SOCKET;
4461
if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int)))
4462
{ soap->errnum = soap_socket_errno(soap->socket);
4463
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR);
4464
soap_closesock(soap);
4465
return SOAP_INVALID_SOCKET;
4468
if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int)))
4469
{ soap->errnum = soap_socket_errno(soap->socket);
4470
soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR);
4471
soap_closesock(soap);
4472
return SOAP_INVALID_SOCKET;
4476
if (soap->accept_timeout)
4479
u_long blocking = 0;
4480
ioctlsocket(soap->master, FIONBIO, &blocking);
4481
ioctlsocket(soap->socket, FIONBIO, &blocking);
4482
#elif defined(VXWORKS)
4483
u_long blocking = 0;
4484
ioctl(soap->master, FIONBIO, (int)(&blocking));
4485
ioctl(soap->socket, FIONBIO, (int)(&blocking));
4487
fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL,0)&~O_NONBLOCK);
4488
fcntl(soap->socket, F_SETFL, fcntl(soap->socket, F_GETFL,0)&~O_NONBLOCK);
4489
#elif defined(SYMBIAN)
4491
ioctl(soap->master, 0/*FIONBIO*/, &blocking);
4493
fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL)&~O_NONBLOCK);
4494
fcntl(soap->socket, F_SETFL, fcntl(soap->socket, F_GETFL)&~O_NONBLOCK);
4497
soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
4498
return soap->socket;
4500
err = soap_socket_errno(soap->socket);
4501
if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN)
4502
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host));
4504
soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR);
4505
soap_closesock(soap);
4506
return SOAP_INVALID_SOCKET;
4512
soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR);
4513
return SOAP_INVALID_SOCKET;
4519
/******************************************************************************/
4523
tcp_disconnect(struct soap *soap)
4529
{ SSL_SESSION_free(soap->session);
4530
soap->session = NULL;
4533
{ soap->session = SSL_get1_session(soap->ssl);
4535
{ strcpy(soap->session_host, soap->host);
4536
soap->session_port = soap->port;
4539
r = SSL_shutdown(soap->ssl);
4541
{ if (soap_valid_socket(soap->socket))
4542
{ struct timeval timeout;
4544
if (soap->fshutdownsocket(soap, soap->socket, 1))
4546
wait up to 10 seconds for close_notify to be sent by peer (if peer not
4547
present, this avoids calling SSL_shutdown() which has a lengthy return
4551
if ((int)soap->socket < (int)FD_SETSIZE)
4554
timeout.tv_sec = 10;
4555
timeout.tv_usec = 0;
4557
FD_SET(soap->socket, &fd);
4558
r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout);
4559
if (r <= 0 && soap_socket_errno(soap->socket) != SOAP_EINTR)
4561
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
4562
soap->fclosesocket(soap, soap->socket);
4563
soap->socket = SOAP_INVALID_SOCKET;
4564
SSL_free(soap->ssl);
4566
ERR_remove_state(0);
4574
r = SSL_shutdown(soap->ssl);
4577
{ s = ERR_get_error();
4579
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r)));
4580
if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4581
{ soap->fclosesocket(soap, soap->socket);
4582
soap->socket = SOAP_INVALID_SOCKET;
4584
SSL_free(soap->ssl);
4586
ERR_remove_state(0);
4587
return SOAP_SSL_ERROR;
4590
SSL_free(soap->ssl);
4592
ERR_remove_state(0);
4595
if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP))
4596
{ soap->fshutdownsocket(soap, soap->socket, 2);
4597
soap->fclosesocket(soap, soap->socket);
4598
soap->socket = SOAP_INVALID_SOCKET;
4605
/******************************************************************************/
4609
tcp_closesocket(struct soap *soap, SOAP_SOCKET fd)
4610
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd));
4611
return soap_closesocket(fd);
4616
/******************************************************************************/
4620
tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how)
4621
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how));
4622
return shutdown(fd, how);
4627
/******************************************************************************/
4632
soap_closesock(struct soap *soap)
4633
{ register int status = soap->error;
4634
if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive)
4635
{ if (soap->fclose && (soap->error = soap->fclose(soap)))
4637
soap->keep_alive = 0;
4640
if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
4641
deflateEnd(&soap->d_stream);
4642
else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
4643
inflateEnd(&soap->d_stream);
4644
soap->zlib_state = SOAP_ZLIB_NONE;
4646
return soap->error = status;
4650
/******************************************************************************/
4651
#ifndef WITH_NOIDREF
4656
soap_hash(register const char *s)
4657
{ register size_t h = 0;
4660
return h % SOAP_IDHASH;
4665
/******************************************************************************/
4666
#ifndef WITH_NOIDREF
4669
soap_init_pht(struct soap *soap)
4671
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n"));
4674
for (i = 0; i < (int)SOAP_PTRHASH; i++)
4675
soap->pht[i] = NULL;
4680
/******************************************************************************/
4685
soap_new1(soap_mode mode)
4686
{ return soap_new2(mode, mode);
4690
/******************************************************************************/
4696
{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
4700
/******************************************************************************/
4705
soap_new2(soap_mode imode, soap_mode omode)
4706
{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap));
4708
soap_init2(soap, imode, omode);
4713
/******************************************************************************/
4718
soap_free(struct soap *soap)
4724
/******************************************************************************/
4729
soap_del(struct soap *soap)
4734
/******************************************************************************/
4735
#ifndef WITH_NOIDREF
4738
soap_free_pht(struct soap *soap)
4739
{ register struct soap_pblk *pb, *next;
4741
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n"));
4742
for (pb = soap->pblk; pb; pb = next)
4744
SOAP_FREE(soap, pb);
4748
for (i = 0; i < (int)SOAP_PTRHASH; i++)
4749
soap->pht[i] = NULL;
4754
/******************************************************************************/
4755
#ifndef WITH_NOIDREF
4760
soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
4762
struct soap_plist *pp;
4763
if (soap->version != 1)
4766
i = soap_array_pointer_lookup(soap, p, a, n, type, &pp);
4768
i = soap_pointer_lookup(soap, p, type, &pp);
4770
{ if (soap_is_embedded(soap, pp)
4771
|| soap_is_single(soap, pp))
4773
soap_set_embedded(soap, pp);
4780
/******************************************************************************/
4781
#ifndef WITH_NOIDREF
4786
soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp)
4787
{ register struct soap_plist *pp;
4790
{ for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next)
4791
{ if (pp->ptr == p && pp->type == type)
4793
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id));
4798
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type));
4804
/******************************************************************************/
4805
#ifndef WITH_NOIDREF
4810
soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
4811
{ register size_t h;
4812
register struct soap_plist *pp;
4813
if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
4814
{ register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
4816
{ soap->error = SOAP_EOM;
4819
pb->next = soap->pblk;
4823
*ppp = pp = &soap->pblk->plist[soap->pidx++];
4825
h = soap_hash_ptr(a->__ptr);
4827
h = soap_hash_ptr(p);
4828
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));
4829
pp->next = soap->pht[h];
4836
pp->id = ++soap->idnum;
4842
/******************************************************************************/
4843
#ifndef WITH_NOIDREF
4848
soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
4849
{ register struct soap_plist *pp;
4851
if (!p || !a->__ptr)
4853
for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next)
4854
{ if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr)
4856
for (i = 0; i < n; i++)
4857
if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i])
4861
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id));
4866
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type));
4872
/******************************************************************************/
4877
soap_begin_count(struct soap *soap)
4880
if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME))
4881
soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME;
4884
{ soap->mode = soap->omode;
4885
if ((soap->mode & SOAP_IO) == SOAP_IO_STORE
4886
|| (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML))
4888
&& !soap->fpreparesend
4891
soap->mode &= ~SOAP_IO_LENGTH;
4893
soap->mode |= SOAP_IO_LENGTH;
4896
if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
4897
{ if (!(soap->mode & SOAP_ENC_DIME))
4898
soap->mode &= ~SOAP_IO_LENGTH;
4899
if (soap->mode & SOAP_ENC_XML)
4900
soap->mode |= SOAP_IO_BUFFER;
4902
soap->mode |= SOAP_IO_STORE;
4905
if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
4906
soap->mode |= SOAP_XML_TREE;
4908
if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
4909
soap->mode |= SOAP_ENC_MIME;
4911
soap->mode &= ~SOAP_ENC_MTOM;
4912
if (soap->mode & SOAP_ENC_MIME)
4913
soap_select_mime_boundary(soap);
4914
soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */
4920
soap->mustUnderstand = 0;
4922
soap->part = SOAP_BEGIN;
4924
soap_clr_attr(soap);
4925
soap_set_local_namespaces(soap);
4926
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
4928
soap->dime.count = 0; /* count # of attachments */
4929
soap->dime.size = 0; /* accumulate total size of attachments */
4930
if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE)
4931
return soap->error = soap->fprepareinit(soap);
4937
/******************************************************************************/
4942
soap_end_count(struct soap *soap)
4945
if (soap->fpreparefinal)
4946
return soap->error = soap->fpreparefinal(soap);
4948
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n"));
4953
/******************************************************************************/
4958
soap_begin_send(struct soap *soap)
4959
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n"));
4960
soap->error = SOAP_OK;
4961
soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
4963
if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH)
4964
{ if (soap->mode & SOAP_ENC_XML)
4965
soap->mode |= SOAP_IO_BUFFER;
4967
soap->mode |= SOAP_IO_STORE;
4971
if ((soap->mode & SOAP_IO_UDP))
4972
{ soap->mode |= SOAP_ENC_XML;
4973
if (soap->count > SOAP_BUFLEN)
4974
return soap->error = SOAP_UDP_ERROR;
4977
if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket))
4978
{ if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML))
4979
soap->mode |= SOAP_IO_BUFFER;
4981
soap->mode |= SOAP_IO_STORE;
4983
soap->mode &= ~SOAP_IO_LENGTH;
4984
if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
4985
soap_new_block(soap);
4986
if (!(soap->mode & SOAP_IO_KEEPALIVE))
4987
soap->keep_alive = 0;
4988
if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
4989
soap->mode |= SOAP_XML_TREE;
4991
if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
4992
{ soap->mode |= SOAP_ENC_MIME;
4993
soap->mode &= ~SOAP_ENC_DIME;
4996
soap->mode &= ~SOAP_ENC_MTOM;
4997
if (soap->mode & SOAP_ENC_MIME)
4998
soap_select_mime_boundary(soap);
5001
#ifndef WITH_FASTCGI
5002
if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */
5004
setmode(soap->sendfd, O_BINARY);
5006
_setmode(soap->sendfd, _O_BINARY);
5012
if (soap->mode & SOAP_IO)
5016
soap->chunksize = 0;
5020
soap->mustUnderstand = 0;
5024
soap_clr_attr(soap);
5025
soap_set_local_namespaces(soap);
5027
soap->z_ratio_out = 1.0;
5028
if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE)
5029
{ soap->d_stream.next_out = (Byte*)soap->z_buf;
5030
soap->d_stream.avail_out = SOAP_BUFLEN;
5032
if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
5033
{ memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10);
5034
soap->d_stream.next_out = (Byte*)soap->z_buf + 10;
5035
soap->d_stream.avail_out = SOAP_BUFLEN - 10;
5036
soap->z_crc = crc32(0L, NULL, 0);
5037
soap->zlib_out = SOAP_ZLIB_GZIP;
5038
if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK)
5039
return soap->error = SOAP_ZLIB_ERROR;
5043
if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK)
5044
return soap->error = SOAP_ZLIB_ERROR;
5045
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n"));
5046
soap->zlib_state = SOAP_ZLIB_DEFLATE;
5049
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count));
5050
soap->part = SOAP_BEGIN;
5052
if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE)
5053
soap->fprepareinit(soap);
5059
/******************************************************************************/
5060
#ifndef WITH_NOIDREF
5065
soap_embedded(struct soap *soap, const void *p, int t)
5066
{ struct soap_plist *pp;
5067
if (soap_pointer_lookup(soap, p, t, &pp))
5070
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t));
5076
/******************************************************************************/
5077
#ifndef WITH_NOIDREF
5082
soap_reference(struct soap *soap, const void *p, int t)
5083
{ struct soap_plist *pp;
5084
if (!p || (soap->mode & SOAP_XML_TREE))
5086
if (soap_pointer_lookup(soap, p, t, &pp))
5087
{ if (pp->mark1 == 0)
5092
else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
5098
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
5104
/******************************************************************************/
5105
#ifndef WITH_NOIDREF
5110
soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
5112
struct soap_plist *pp;
5113
if (!p || !a->__ptr)
5115
i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
5117
{ if (pp->mark1 == 0)
5122
else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
5128
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));
5134
/******************************************************************************/
5135
#ifndef WITH_NOIDREF
5140
soap_embedded_id(struct soap *soap, int id, const void *p, int t)
5141
{ struct soap_plist *pp = NULL;
5142
if (soap->mode & SOAP_XML_TREE)
5144
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
5145
if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
5147
{ id = soap_pointer_lookup(soap, p, t, &pp);
5149
{ if (soap->mode & SOAP_IO_LENGTH)
5153
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));
5160
id = soap_pointer_lookup(soap, p, t, &pp);
5161
else if (id && !soap_pointer_lookup(soap, p, t, &pp))
5164
{ if (soap->mode & SOAP_IO_LENGTH)
5168
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));
5175
/******************************************************************************/
5176
#ifndef WITH_NOIDREF
5181
soap_is_embedded(struct soap *soap, struct soap_plist *pp)
5184
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2));
5185
if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
5186
{ if (soap->mode & SOAP_IO_LENGTH)
5187
return pp->mark1 != 0;
5188
return pp->mark2 != 0;
5190
if (soap->mode & SOAP_IO_LENGTH)
5191
return pp->mark1 == 1;
5192
return pp->mark2 == 1;
5197
/******************************************************************************/
5198
#ifndef WITH_NOIDREF
5203
soap_is_single(struct soap *soap, struct soap_plist *pp)
5204
{ if (soap->part == SOAP_IN_HEADER)
5208
if (soap->mode & SOAP_IO_LENGTH)
5209
return pp->mark1 == 0;
5210
return pp->mark2 == 0;
5215
/******************************************************************************/
5216
#ifndef WITH_NOIDREF
5221
soap_set_embedded(struct soap *soap, struct soap_plist *pp)
5224
if (soap->mode & SOAP_IO_LENGTH)
5232
/******************************************************************************/
5238
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)
5240
#ifndef WITH_NOIDREF
5241
struct soap_plist *pp;
5243
if (!p || !a->__ptr || (!aid && !atype))
5244
return soap_element_id(soap, tag, id, p, a, n, type, t);
5245
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:""));
5246
i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
5248
{ i = soap_pointer_enter(soap, p, a, n, t, &pp);
5250
{ soap->error = SOAP_EOM;
5257
{ sprintf(soap->tmpbuf, soap->dime_id_format, id);
5258
aid = soap_strdup(soap, soap->tmpbuf);
5260
/* Add MTOM xop:Include element when necessary */
5261
/* TODO: this code to be obsoleted with new import/xop.h conventions */
5262
if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include"))
5263
{ if (soap_element_begin_out(soap, tag, 0, type)
5264
|| soap_element_href(soap, "xop:Include", 0, "href", aid)
5265
|| soap_element_end_out(soap, tag))
5268
else if (soap_element_href(soap, tag, 0, "href", aid))
5270
if (soap->mode & SOAP_IO_LENGTH)
5271
{ if (pp->mark1 != 3)
5272
{ struct soap_multipart *content;
5273
if (soap->mode & SOAP_ENC_MTOM)
5274
content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size);
5276
content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size);
5278
{ soap->error = SOAP_EOM;
5281
if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */
5282
{ if (soap->mode & SOAP_ENC_MTOM)
5283
{ char *s = (char*)soap_malloc(soap, strlen(aid) - 1);
5286
strcpy(s + 1, aid + 4);
5292
content->id = aid + 4;
5296
content->type = atype;
5297
content->options = aoptions;
5298
content->encoding = SOAP_MIME_BINARY;
5310
/******************************************************************************/
5311
#ifndef WITH_NOIDREF
5314
soap_init_iht(struct soap *soap)
5316
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n"));
5317
for (i = 0; i < SOAP_IDHASH; i++)
5318
soap->iht[i] = NULL;
5323
/******************************************************************************/
5324
#ifndef WITH_NOIDREF
5327
soap_free_iht(struct soap *soap)
5329
register struct soap_ilist *ip = NULL, *p = NULL;
5330
register struct soap_flist *fp = NULL, *fq = NULL;
5331
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n"));
5332
for (i = 0; i < SOAP_IDHASH; i++)
5333
{ for (ip = soap->iht[i]; ip; ip = p)
5334
{ for (fp = ip->flist; fp; fp = fq)
5336
SOAP_FREE(soap, fp);
5339
SOAP_FREE(soap, ip);
5341
soap->iht[i] = NULL;
5347
/******************************************************************************/
5348
#ifndef WITH_NOIDREF
5353
soap_lookup(struct soap *soap, const char *id)
5354
{ register struct soap_ilist *ip = NULL;
5355
for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next)
5356
if (!strcmp(ip->id, id))
5363
/******************************************************************************/
5364
#ifndef WITH_NOIDREF
5369
soap_enter(struct soap *soap, const char *id)
5370
{ register size_t h;
5371
register struct soap_ilist *ip;
5372
ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
5374
{ h = soap_hash(id);
5376
ip->next = soap->iht[h];
5385
/******************************************************************************/
5390
soap_malloc(struct soap *soap, size_t n)
5393
return (void*)SOAP_NON_NULL;
5395
return SOAP_MALLOC(soap, n);
5397
p = (char*)soap->fmalloc(soap, n);
5399
{ n += sizeof(short);
5400
n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */
5401
if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t))))
5402
{ soap->error = SOAP_EOM;
5405
/* set the canary to detect corruption */
5406
*(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY;
5407
/* keep chain of alloced cells for destruction */
5408
*(void**)(p + n) = soap->alist;
5409
*(size_t*)(p + n + sizeof(void*)) = n;
5410
soap->alist = p + n;
5417
/******************************************************************************/
5418
#ifdef SOAP_MEM_DEBUG
5420
soap_init_mht(struct soap *soap)
5422
for (i = 0; i < (int)SOAP_PTRHASH; i++)
5423
soap->mht[i] = NULL;
5427
/******************************************************************************/
5428
#ifdef SOAP_MEM_DEBUG
5430
soap_free_mht(struct soap *soap)
5432
register struct soap_mlist *mp, *mq;
5433
for (i = 0; i < (int)SOAP_PTRHASH; i++)
5434
{ for (mp = soap->mht[i]; mp; mp = mq)
5437
fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr);
5440
soap->mht[i] = NULL;
5445
/******************************************************************************/
5446
#ifdef SOAP_MEM_DEBUG
5450
soap_track_malloc(struct soap *soap, const char *file, int line, size_t size)
5451
{ register void *p = malloc(size);
5453
{ register size_t h = soap_hash_ptr(p);
5454
register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist));
5455
if (soap->fdebug[SOAP_INDEX_TEST])
5456
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p));
5458
mp->next = soap->mht[h];
5469
/******************************************************************************/
5470
#ifdef SOAP_MEM_DEBUG
5474
soap_track_free(struct soap *soap, const char *file, int line, void *p)
5475
{ register size_t h = soap_hash_ptr(p);
5476
register struct soap_mlist *mp;
5477
for (mp = soap->mht[h]; mp; mp = mp->next)
5483
if (soap->fdebug[SOAP_INDEX_TEST])
5484
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p));
5489
fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line);
5492
fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p);
5496
/******************************************************************************/
5497
#ifdef SOAP_MEM_DEBUG
5499
soap_track_unlink(struct soap *soap, const void *p)
5500
{ register size_t h = soap_hash_ptr(p);
5501
register struct soap_mlist *mp;
5502
for (mp = soap->mht[h]; mp; mp = mp->next)
5510
/******************************************************************************/
5515
soap_dealloc(struct soap *soap, void *p)
5516
{ if (soap_check_state(soap))
5519
{ register char **q;
5520
for (q = (char**)&soap->alist; *q; q = *(char***)q)
5522
if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY)
5524
#ifdef SOAP_MEM_DEBUG
5525
fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
5527
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
5528
DBGHEX(TEST, *q - 200, 200);
5529
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
5530
soap->error = SOAP_MOE;
5533
if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
5534
{ *q = **(char***)q;
5535
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p));
5540
soap_delete(soap, p);
5544
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n"));
5546
{ q = (char*)soap->alist;
5547
if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY)
5549
#ifdef SOAP_MEM_DEBUG
5550
fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n");
5552
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n"));
5553
DBGHEX(TEST, q - 200, 200);
5554
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n"));
5555
soap->error = SOAP_MOE;
5558
soap->alist = *(void**)q;
5559
q -= *(size_t*)(q + sizeof(void*));
5562
/* we must assume these were deallocated: */
5563
soap->action = NULL;
5565
soap->header = NULL;
5566
soap->userid = NULL;
5567
soap->passwd = NULL;
5568
soap->authrealm = NULL;
5569
soap->http_content = NULL;
5571
soap_clr_mime(soap);
5577
/******************************************************************************/
5582
soap_delete(struct soap *soap, void *p)
5583
{ register struct soap_clist **cp;
5584
if (soap_check_state(soap))
5589
{ if (p == (*cp)->ptr)
5590
{ register struct soap_clist *q = *cp;
5593
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
5594
#ifdef SOAP_MEM_DEBUG
5595
fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
5603
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p));
5607
{ register struct soap_clist *q = *cp;
5610
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type));
5611
#ifdef SOAP_MEM_DEBUG
5612
fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr);
5618
soap->fault = NULL; /* this was possibly deallocated */
5619
soap->header = NULL; /* this was possibly deallocated */
5623
/******************************************************************************/
5628
soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*))
5629
{ register struct soap_clist *cp;
5630
if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist))))
5631
{ cp->next = soap->clist;
5635
cp->fdelete = fdelete;
5642
/******************************************************************************/
5647
soap_unlink(struct soap *soap, const void *p)
5648
{ register char **q;
5649
register struct soap_clist **cp;
5652
for (q = (char**)&soap->alist; *q; q = *(char***)q)
5653
{ if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*))))
5654
{ *q = **(char***)q;
5655
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p));
5656
#ifdef SOAP_MEM_DEBUG
5657
soap_track_unlink(soap, p);
5662
for (cp = &soap->clist; *cp; cp = &(*cp)->next)
5663
{ if (p == (*cp)->ptr)
5664
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p));
5674
/******************************************************************************/
5675
#ifndef WITH_NOIDREF
5680
soap_lookup_type(struct soap *soap, const char *id)
5681
{ register struct soap_ilist *ip;
5683
{ ip = soap_lookup(soap, id);
5685
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type));
5689
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id));
5695
/******************************************************************************/
5696
#ifndef WITH_NOIDREF
5701
soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k)
5702
{ struct soap_ilist *ip;
5704
if (!p || !id || !*id)
5706
ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
5708
{ ip = soap_enter(soap, id); /* new hash table entry for string id */
5709
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n));
5720
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n));
5722
{ strcpy(soap->id, id);
5723
soap->error = SOAP_HREF;
5724
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t));
5727
while (ip->level < k)
5728
{ q = (void**)soap_malloc(soap, sizeof(void*));
5734
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5738
else if (ip->level > k)
5739
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id));
5740
while (ip->level > k)
5741
{ void *s, **r = &ip->link;
5742
q = (void**)ip->link;
5744
{ *r = (void*)soap_malloc(soap, sizeof(void*));
5753
ip->level = ip->level - 1;
5754
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5756
q = (void**)ip->link;
5761
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n));
5762
while (ip->level < k)
5763
{ q = (void**)soap_malloc(soap, sizeof(void*));
5767
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n"));
5769
q = (void**)ip->link;
5778
/******************************************************************************/
5779
#ifndef WITH_NOIDREF
5784
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))
5785
{ struct soap_ilist *ip;
5786
if (!p || !href || !*href)
5788
ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */
5790
{ ip = soap_enter(soap, href); /* new hash table entry for string id */
5798
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));
5800
else if (ip->type != st || (ip->level == k && ip->size != n))
5801
{ 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));
5802
strcpy(soap->id, href);
5803
soap->error = SOAP_HREF;
5806
if (fcopy || n < sizeof(void*) || *href != '#')
5807
{ register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist));
5809
{ soap->error = SOAP_EOM;
5812
fp->next = ip->flist;
5820
fp->fcopy = soap_fcopy;
5822
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));
5825
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href));
5826
*(void**)p = ip->copy;
5834
/******************************************************************************/
5839
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*))
5841
#ifndef WITH_NOIDREF
5842
struct soap_ilist *ip;
5844
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k));
5848
p = finstantiate(soap, t, type, arrayType, &n);
5850
p = soap_malloc(soap, n);
5854
#ifndef WITH_NOIDREF
5858
#ifndef WITH_NOIDREF
5859
ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */
5860
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p));
5862
{ ip = soap_enter(soap, id); /* new hash table entry for string id */
5870
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));
5872
else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist))
5873
{ 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));
5874
strcpy(soap->id, id);
5875
soap->error = SOAP_HREF;
5879
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id));
5880
strcpy(soap->id, id);
5881
soap->error = SOAP_DUPLICATE_ID;
5888
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));
5895
/******************************************************************************/
5900
soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n)
5901
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n));
5906
/******************************************************************************/
5911
soap_end_send(struct soap *soap)
5914
if (soap->dime.list)
5915
{ /* SOAP body referenced attachments must appear first */
5916
soap->dime.last->next = soap->dime.first;
5917
soap->dime.first = soap->dime.list->next;
5918
soap->dime.list->next = NULL;
5919
soap->dime.last = soap->dime.list;
5921
if (soap_putdime(soap) || soap_putmime(soap))
5923
soap->mime.list = NULL;
5924
soap->mime.first = NULL;
5925
soap->mime.last = NULL;
5926
soap->dime.list = NULL;
5927
soap->dime.first = NULL;
5928
soap->dime.last = NULL;
5930
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n"));
5931
if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
5932
{ if (soap_flush(soap))
5934
{ if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE)
5935
{ soap->zlib_state = SOAP_ZLIB_NONE;
5936
deflateEnd(&soap->d_stream);
5944
if (soap->mode & SOAP_ENC_ZLIB)
5946
soap->d_stream.avail_in = 0;
5948
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n"));
5949
r = deflate(&soap->d_stream, Z_FINISH);
5950
if (soap->d_stream.avail_out != SOAP_BUFLEN)
5951
{ if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out))
5952
{ soap->zlib_state = SOAP_ZLIB_NONE;
5953
deflateEnd(&soap->d_stream);
5956
soap->d_stream.next_out = (Byte*)soap->z_buf;
5957
soap->d_stream.avail_out = SOAP_BUFLEN;
5959
} while (r == Z_OK);
5960
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out));
5961
soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in;
5962
soap->mode &= ~SOAP_ENC_ZLIB;
5963
soap->zlib_state = SOAP_ZLIB_NONE;
5964
if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END)
5965
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:""));
5966
return soap->error = SOAP_ZLIB_ERROR;
5969
if (soap->zlib_out != SOAP_ZLIB_DEFLATE)
5970
{ soap->z_buf[0] = soap->z_crc & 0xFF;
5971
soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF;
5972
soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF;
5973
soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF;
5974
soap->z_buf[4] = soap->d_stream.total_in & 0xFF;
5975
soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF;
5976
soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF;
5977
soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF;
5978
if (soap_flush_raw(soap, soap->z_buf, 8))
5980
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc));
5985
if ((soap->mode & SOAP_IO) == SOAP_IO_STORE)
5988
if (!(soap->mode & SOAP_ENC_XML))
5990
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size));
5991
if (soap->status >= SOAP_POST)
5992
soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size);
5993
else if (soap->status != SOAP_STOP)
5994
soap->error = soap->fresponse(soap, soap->status, soap->blist->size);
5995
if (soap->error || soap_flush(soap))
6000
for (p = soap_first_block(soap); p; p = soap_next_block(soap))
6001
{ DBGMSG(SENT, p, soap_block_size(soap));
6002
if ((soap->error = soap->fsend(soap, p, soap_block_size(soap))))
6003
{ soap_end_block(soap);
6007
soap_end_block(soap);
6010
else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
6011
{ DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
6012
if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
6019
if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
6020
soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */
6022
if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP))
6023
soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */
6026
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n"));
6027
soap->omode &= ~SOAP_XML_SEC;
6029
soap->part = SOAP_END;
6034
/******************************************************************************/
6039
soap_end_recv(struct soap *soap)
6040
{ soap->part = SOAP_END;
6042
if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap))
6043
{ soap->dime.first = NULL;
6044
soap->dime.last = NULL;
6047
soap->dime.list = soap->dime.first;
6048
soap->dime.first = NULL;
6049
soap->dime.last = NULL;
6050
/* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */
6051
if (soap->mode & SOAP_ENC_MIME)
6053
#ifndef WITH_NOIDREF
6054
if (soap->mode & SOAP_MIME_POSTCHECK)
6055
{ soap_resolve(soap);
6059
if (soap_getmime(soap))
6062
soap->mime.list = soap->mime.first;
6063
soap->mime.first = NULL;
6064
soap->mime.last = NULL;
6065
soap->mime.boundary = NULL;
6067
{ struct soap_multipart *content;
6068
for (content = soap->mime.list; content; content = content->next)
6069
soap_resolve_attachment(soap, content);
6072
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n"));
6074
if (soap->mode & SOAP_ENC_ZLIB)
6075
{ /* Make sure end of compressed content is reached */
6076
while (soap->d_stream.next_out != Z_NULL)
6077
if ((int)soap_get1(soap) == EOF)
6079
soap->mode &= ~SOAP_ENC_ZLIB;
6080
memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN);
6081
soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf;
6082
soap->buflen = soap->z_buflen;
6083
soap->zlib_state = SOAP_ZLIB_NONE;
6084
if (inflateEnd(&soap->d_stream) != Z_OK)
6085
return soap->error = SOAP_ZLIB_ERROR;
6086
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n"));
6088
if (soap->zlib_in == SOAP_ZLIB_GZIP)
6091
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n"));
6092
for (i = 0; i < 8; i++)
6093
{ if ((int)(c = soap_get1(soap)) == EOF)
6094
return soap->error = SOAP_EOF;
6095
soap->z_buf[i] = (char)c;
6097
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)))
6098
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc));
6099
return soap->error = SOAP_ZLIB_ERROR;
6101
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)))
6102
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n"));
6103
return soap->error = SOAP_ZLIB_ERROR;
6106
soap->zlib_in = SOAP_ZLIB_NONE;
6110
if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
6111
while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */
6113
if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap)))
6115
#ifndef WITH_NOIDREF
6116
if (soap_resolve(soap))
6121
{ if (soap->mode & SOAP_ENC_MTOM)
6122
return soap->error = SOAP_MIME_HREF;
6123
return soap->error = SOAP_DIME_HREF;
6126
soap_free_temp(soap);
6131
/******************************************************************************/
6136
soap_free_temp(struct soap *soap)
6137
{ register struct soap_nlist *np, *nq;
6138
register struct soap_attribute *tp, *tq;
6139
register struct Namespace *ns;
6140
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n"));
6141
for (np = soap->nlist; np; np = nq)
6143
SOAP_FREE(soap, np);
6146
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n"));
6148
soap_end_block(soap);
6149
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n"));
6150
for (tp = soap->attributes; tp; tp = tq)
6153
SOAP_FREE(soap, tp->value);
6154
SOAP_FREE(soap, tp);
6156
soap->attributes = NULL;
6159
SOAP_FREE(soap, soap->labbuf);
6160
soap->labbuf = NULL;
6164
ns = soap->local_namespaces;
6166
{ for (; ns->id; ns++)
6168
{ if (soap->encodingStyle == ns->out)
6169
soap->encodingStyle = SOAP_STR_EOS;
6170
SOAP_FREE(soap, ns->out);
6173
if (soap->encodingStyle == ns->ns)
6174
soap->encodingStyle = SOAP_STR_EOS;
6176
SOAP_FREE(soap, soap->local_namespaces);
6177
soap->local_namespaces = NULL;
6181
{ struct soap_xlist *xp = soap->xlist->next;
6182
SOAP_FREE(soap, soap->xlist);
6186
#ifndef WITH_NOIDREF
6187
soap_free_pht(soap);
6188
soap_free_iht(soap);
6193
/******************************************************************************/
6196
soap_init_logs(struct soap *soap)
6198
for (i = 0; i < SOAP_MAXLOGS; i++)
6199
{ soap->logfile[i] = NULL;
6200
soap->fdebug[i] = NULL;
6205
/******************************************************************************/
6206
#if !defined(WITH_LEAN) || defined(SOAP_DEBUG)
6210
soap_open_logfile(struct soap *soap, int i)
6211
{ if (soap->logfile[i])
6212
soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a");
6216
/******************************************************************************/
6219
soap_close_logfile(struct soap *soap, int i)
6220
{ if (soap->fdebug[i])
6221
{ fclose(soap->fdebug[i]);
6222
soap->fdebug[i] = NULL;
6227
/******************************************************************************/
6232
soap_close_logfiles(struct soap *soap)
6234
for (i = 0; i < SOAP_MAXLOGS; i++)
6235
soap_close_logfile(soap, i);
6239
/******************************************************************************/
6242
soap_set_logfile(struct soap *soap, int i, const char *logfile)
6245
soap_close_logfile(soap, i);
6246
s = soap->logfile[i];
6247
soap->logfile[i] = logfile;
6249
SOAP_FREE(soap, (void*)s);
6251
if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1)))
6253
soap->logfile[i] = t;
6257
/******************************************************************************/
6262
soap_set_recv_logfile(struct soap *soap, const char *logfile)
6263
{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
6267
/******************************************************************************/
6272
soap_set_sent_logfile(struct soap *soap, const char *logfile)
6273
{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
6277
/******************************************************************************/
6282
soap_set_test_logfile(struct soap *soap, const char *logfile)
6283
{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
6287
/******************************************************************************/
6292
soap_copy(struct soap *soap)
6293
{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap);
6297
/******************************************************************************/
6302
soap_copy_context(struct soap *copy, struct soap *soap)
6303
{ if (soap_check_state(soap))
6306
{ register struct soap_plugin *p = NULL;
6307
memcpy(copy, soap, sizeof(struct soap));
6308
copy->state = SOAP_COPY;
6309
copy->error = SOAP_OK;
6310
copy->userid = NULL;
6311
copy->passwd = NULL;
6316
copy->attributes = NULL;
6317
copy->labbuf = NULL;
6320
#ifdef SOAP_MEM_DEBUG
6321
soap_init_mht(copy);
6324
soap_init_logs(copy);
6325
soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
6326
soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
6327
soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]);
6329
copy->local_namespaces = NULL;
6330
#ifndef WITH_NOIDREF
6331
soap_init_iht(copy);
6332
soap_init_pht(copy);
6334
copy->header = NULL;
6336
copy->action = NULL;
6339
copy->cookies = soap_copy_cookies(copy, soap);
6341
copy->cookies = NULL;
6344
copy->plugins = NULL;
6345
for (p = soap->plugins; p; p = p->next)
6346
{ register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin));
6349
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id));
6351
if (p->fcopy && (soap->error = p->fcopy(copy, q, p)))
6352
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id));
6356
q->next = copy->plugins;
6361
soap->error = SOAP_EOM;
6366
/******************************************************************************/
6371
soap_copy_stream(struct soap *copy, struct soap *soap)
6372
{ copy->mode = soap->mode;
6373
copy->imode = soap->imode;
6374
copy->omode = soap->omode;
6375
copy->socket = soap->socket;
6376
copy->recv_timeout = soap->recv_timeout;
6377
copy->send_timeout = soap->send_timeout;
6378
#if defined(__cplusplus) && !defined(WITH_LEAN)
6379
copy->os = soap->os;
6380
copy->is = soap->is;
6382
copy->sendfd = soap->sendfd;
6383
copy->recvfd = soap->recvfd;
6384
copy->bufidx = soap->bufidx;
6385
copy->buflen = soap->buflen;
6386
copy->ahead = soap->ahead;
6387
copy->cdata = soap->cdata;
6388
copy->chunksize = soap->chunksize;
6389
copy->chunkbuflen = soap->chunkbuflen;
6390
copy->keep_alive = soap->keep_alive;
6391
copy->tcp_keep_alive = soap->tcp_keep_alive;
6392
copy->tcp_keep_idle = soap->tcp_keep_idle;
6393
copy->tcp_keep_intvl = soap->tcp_keep_intvl;
6394
copy->tcp_keep_cnt = soap->tcp_keep_cnt;
6395
copy->max_keep_alive = soap->max_keep_alive;
6397
copy->peer = soap->peer;
6398
copy->peerlen = soap->peerlen;
6401
copy->bio = soap->bio;
6402
copy->ssl = soap->ssl;
6403
copy->ctx = soap->ctx;
6406
copy->zlib_state = soap->zlib_state;
6407
copy->zlib_in = soap->zlib_in;
6408
copy->zlib_out = soap->zlib_out;
6409
copy->d_stream = soap->d_stream;
6410
copy->z_buflen = soap->z_buflen;
6411
copy->z_level = soap->z_level;
6412
copy->z_crc = soap->z_crc;
6413
copy->z_ratio_in = soap->z_ratio_in;
6414
copy->z_ratio_out = soap->z_ratio_out;
6415
memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf));
6417
memcpy(copy->buf, soap->buf, sizeof(soap->buf));
6421
/******************************************************************************/
6426
soap_init(struct soap *soap)
6427
{ soap->state = SOAP_INIT;
6429
soap_imode(soap, SOAP_IO_DEFAULT);
6430
soap_omode(soap, SOAP_IO_DEFAULT);
6431
soap->plugins = NULL;
6433
soap->userid = NULL;
6434
soap->passwd = NULL;
6436
soap->fpost = http_post;
6437
soap->fget = http_get;
6439
soap->fposthdr = http_post_header;
6440
soap->fresponse = http_response;
6441
soap->fparse = http_parse;
6442
soap->fparsehdr = http_parse_header;
6444
soap->fheader = NULL;
6445
soap->fconnect = NULL;
6446
soap->fdisconnect = NULL;
6449
soap->fresolve = tcp_gethost;
6451
soap->fresolve = NULL;
6453
soap->faccept = tcp_accept;
6454
soap->fopen = tcp_connect;
6455
soap->fclose = tcp_disconnect;
6456
soap->fclosesocket = tcp_closesocket;
6457
soap->fshutdownsocket = tcp_shutdownsocket;
6458
soap->fsend = fsend;
6459
soap->frecv = frecv;
6460
soap->fpoll = soap_poll;
6463
soap->fclose = NULL;
6466
soap->fseterror = NULL;
6467
soap->fignore = NULL;
6468
soap->fserveloop = NULL;
6469
soap->fplugin = fplugin;
6470
soap->fmalloc = NULL;
6472
soap->fprepareinit = NULL;
6473
soap->fpreparesend = NULL;
6474
soap->fpreparerecv = NULL;
6475
soap->fpreparefinal = NULL;
6476
soap->fdimereadopen = NULL;
6477
soap->fdimewriteopen = NULL;
6478
soap->fdimereadclose = NULL;
6479
soap->fdimewriteclose = NULL;
6480
soap->fdimeread = NULL;
6481
soap->fdimewrite = NULL;
6482
soap->fmimereadopen = NULL;
6483
soap->fmimewriteopen = NULL;
6484
soap->fmimereadclose = NULL;
6485
soap->fmimewriteclose = NULL;
6486
soap->fmimeread = NULL;
6487
soap->fmimewrite = NULL;
6489
soap->float_format = "%.9G"; /* Alternative: use "%G" */
6490
soap->double_format = "%.17lG"; /* Alternative: use "%lG" */
6491
soap->dime_id_format = "cid:id%d"; /* default DIME id format */
6492
soap->http_version = "1.1";
6493
soap->proxy_http_version = "1.0";
6494
soap->http_content = NULL;
6496
soap->keep_alive = 0;
6497
soap->tcp_keep_alive = 0;
6498
soap->tcp_keep_idle = 0;
6499
soap->tcp_keep_intvl = 0;
6500
soap->tcp_keep_cnt = 0;
6501
soap->max_keep_alive = SOAP_MAXKEEPALIVE;
6502
soap->recv_timeout = 0;
6503
soap->send_timeout = 0;
6504
soap->connect_timeout = 0;
6505
soap->accept_timeout = 0;
6506
soap->socket_flags = 0;
6507
soap->connect_flags = 0;
6508
soap->bind_flags = 0;
6509
soap->accept_flags = 0;
6511
soap->labbuf = NULL;
6514
soap->encodingStyle = SOAP_STR_EOS;
6515
#ifndef WITH_NONAMESPACES
6516
soap->namespaces = namespaces;
6518
soap->namespaces = NULL;
6520
soap->local_namespaces = NULL;
6525
soap->attributes = NULL;
6526
soap->header = NULL;
6528
soap->master = SOAP_INVALID_SOCKET;
6529
soap->socket = SOAP_INVALID_SOCKET;
6534
soap->dime.list = NULL;
6535
soap->dime.first = NULL;
6536
soap->dime.last = NULL;
6537
soap->mime.list = NULL;
6538
soap->mime.first = NULL;
6539
soap->mime.last = NULL;
6540
soap->mime.boundary = NULL;
6541
soap->mime.start = NULL;
6548
soap->recvfd = stdin;
6549
soap->sendfd = stdout;
6551
soap->host[0] = '\0';
6553
soap->action = NULL;
6554
soap->proxy_host = NULL;
6555
soap->proxy_port = 8080;
6556
soap->proxy_userid = NULL;
6557
soap->proxy_passwd = NULL;
6558
soap->authrealm = NULL;
6559
soap->prolog = NULL;
6561
soap->zlib_state = SOAP_ZLIB_NONE;
6562
soap->zlib_in = SOAP_ZLIB_NONE;
6563
soap->zlib_out = SOAP_ZLIB_NONE;
6564
soap->d_stream.zalloc = NULL;
6565
soap->d_stream.zfree = NULL;
6566
soap->d_stream.opaque = NULL;
6570
soap->c14ninclude = NULL;
6571
soap->c14nexclude = NULL;
6572
soap->cookies = NULL;
6573
soap->cookie_domain = NULL;
6574
soap->cookie_path = NULL;
6575
soap->cookie_max = 32;
6577
#ifdef SOAP_MEM_DEBUG
6578
soap_init_mht(soap);
6581
soap_init_logs(soap);
6584
soap->rpmreqid = NULL;
6589
#ifndef WITH_NOIDREF
6590
soap_init_iht(soap);
6591
soap_init_pht(soap);
6594
soap_set_recv_logfile(soap, "RECV.log");
6595
soap_set_sent_logfile(soap, "SENT.log");
6596
soap_set_test_logfile(soap, "TEST.log");
6597
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n"));
6602
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing OpenSSL, version=%ld\n", (long)OPENSSL_VERSION_NUMBER));
6604
soap->fsslauth = ssl_auth_init;
6605
soap->fsslverify = ssl_verify_callback;
6609
soap->ssl_flags = SOAP_SSL_DEFAULT;
6610
soap->keyfile = NULL;
6611
soap->password = NULL;
6612
soap->dhfile = NULL;
6613
soap->cafile = NULL;
6614
soap->capath = NULL;
6615
soap->crlfile = NULL;
6616
soap->randfile = NULL;
6617
soap->session = NULL;
6623
/******************************************************************************/
6628
soap_init1(struct soap *soap, soap_mode mode)
6629
{ soap_init2(soap, mode, mode);
6633
/******************************************************************************/
6638
soap_init2(struct soap *soap, soap_mode imode, soap_mode omode)
6640
soap_imode(soap, imode);
6641
soap_omode(soap, omode);
6645
/******************************************************************************/
6650
soap_begin(struct soap *soap)
6651
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n"));
6652
if (!soap->keep_alive)
6656
soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0);
6660
soap->mustUnderstand = 0;
6663
soap->part = SOAP_END;
6668
soap->error = SOAP_OK;
6673
soap->endpoint[0] = '\0';
6675
soap->dime.chunksize = 0;
6676
soap->dime.buflen = 0;
6678
soap_free_temp(soap);
6682
/******************************************************************************/
6687
soap_end(struct soap *soap)
6688
{ if (soap_check_state(soap))
6690
soap_free_temp(soap);
6691
soap_dealloc(soap, NULL);
6693
{ register struct soap_clist *cp = soap->clist->next;
6694
SOAP_FREE(soap, soap->clist);
6697
soap_closesock(soap);
6699
soap_close_logfiles(soap);
6707
/******************************************************************************/
6712
soap_set_namespaces(struct soap *soap, const struct Namespace *p)
6713
{ register struct Namespace *ns = soap->local_namespaces;
6714
register struct soap_nlist *np, *nq, *nr;
6715
register unsigned int level = soap->level;
6716
soap->namespaces = p;
6717
soap->local_namespaces = NULL;
6718
soap_set_local_namespaces(soap);
6719
/* reverse the namespace list */
6732
/* then push on new stack */
6734
{ register const char *s;
6735
soap->level = np->level; /* preserve element nesting level */
6737
if (!s && np->index >= 0 && ns)
6738
{ s = ns[np->index].out;
6740
s = ns[np->index].ns;
6742
if (s && soap_push_namespace(soap, np->id, s))
6746
SOAP_FREE(soap, nq);
6750
for (i = 0; ns[i].id; i++)
6752
{ SOAP_FREE(soap, ns[i].out);
6756
SOAP_FREE(soap, ns);
6758
soap->level = level; /* restore level */
6763
/******************************************************************************/
6768
soap_set_local_namespaces(struct soap *soap)
6769
{ if (soap->namespaces && !soap->local_namespaces)
6770
{ register const struct Namespace *ns1;
6771
register struct Namespace *ns2;
6772
register size_t n = 1;
6773
for (ns1 = soap->namespaces; ns1->id; ns1++)
6775
n *= sizeof(struct Namespace);
6776
ns2 = (struct Namespace*)SOAP_MALLOC(soap, n);
6778
{ memcpy(ns2, soap->namespaces, n);
6780
{ if (!strcmp(ns2[0].ns, soap_env1))
6785
soap->local_namespaces = ns2;
6791
/******************************************************************************/
6797
soap_strsearch(const char *big, const char *little)
6798
{ size_t n = strlen(little);
6799
const char *s = big;
6801
{ if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' '))
6812
/******************************************************************************/
6818
soap_lookup_ns(struct soap *soap, const char *tag, size_t n)
6819
{ register struct soap_nlist *np;
6820
for (np = soap->nlist; np; np = np->next)
6821
{ if (!strncmp(np->id, tag, n) && !np->id[n])
6829
/******************************************************************************/
6831
static struct soap_nlist *
6832
soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized)
6833
{ register struct soap_nlist *np;
6835
if (soap_strsearch(soap->c14nexclude, id))
6838
{ for (np = soap->nlist; np; np = np->next)
6839
{ if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns)))
6843
{ if ((np->level < soap->level || !np->ns) && np->index == 1)
6849
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized));
6855
np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1);
6857
{ soap->error = SOAP_EOM;
6860
np->next = soap->nlist;
6864
{ np->ns = np->id + n + 1;
6869
np->level = soap->level;
6870
np->index = utilized;
6875
/******************************************************************************/
6878
soap_utilize_ns(struct soap *soap, const char *tag, size_t n)
6879
{ register struct soap_nlist *np = soap_lookup_ns(soap, tag, n);
6880
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
6882
{ if (np->index == 0)
6883
soap_push_ns(soap, np->id, np->ns, 1);
6885
else if (strncmp(tag, "xml", 3))
6886
{ strncpy(soap->tmpbuf, tag, n);
6887
soap->tmpbuf[n] = '\0';
6888
soap_push_ns(soap, soap->tmpbuf, NULL, 1);
6893
/******************************************************************************/
6896
soap_pop_ns(struct soap *soap)
6897
{ soap_pop_namespace(soap);
6901
/******************************************************************************/
6906
soap_element(struct soap *soap, const char *tag, int id, const char *type)
6909
register const char *s;
6911
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:""));
6913
if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS))
6914
{ register struct soap_nlist *np;
6915
/* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */
6916
for (np = soap->nlist; np; np = np->next)
6917
{ if (np->index == 2)
6921
if (soap->mode & SOAP_XML_DOM)
6922
{ register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
6924
return soap->error = SOAP_EOM;
6927
elt->prnt = soap->dom;
6928
elt->name = soap_strdup(soap, tag);
6939
{ struct soap_dom_element *p = soap->dom->elts;
6946
soap->dom->elts = elt;
6956
{ if (!(soap->mode & SOAP_XML_CANONICAL)
6957
&& soap_send(soap, soap->prolog ? soap->prolog : "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"))
6960
else if (soap->mode & SOAP_XML_INDENT)
6961
{ if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
6967
s = strchr(tag, ':');
6968
if (s && strncmp(tag, "SOAP-ENV", s - tag))
6969
{ struct Namespace *ns = soap->local_namespaces;
6971
if (soap_send_raw(soap, "<", 1)
6972
|| soap_send(soap, s + 1))
6974
if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n])
6976
for (; ns && ns->id; ns++)
6977
{ if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n])
6978
{ soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0);
6979
if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns))
6987
if (soap_send_raw(soap, "<", 1)
6988
|| soap_send(soap, tag))
6994
{ struct Namespace *ns;
6995
for (ns = soap->local_namespaces; ns && ns->id; ns++)
6996
{ if (*ns->id && (ns->out || ns->ns))
6997
{ sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
6998
if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
7003
soap->ns = 1; /* start with 0 or 2, but should be one to continue */
7005
if (soap->mode & SOAP_XML_CANONICAL)
7006
{ const char *t = strchr(tag, ':');
7008
soap_utilize_ns(soap, tag, t - tag);
7012
{ sprintf(soap->tmpbuf, "_%d", id);
7013
if (soap_attribute(soap, "id", soap->tmpbuf))
7016
if (type && *type && (!(soap->mode & SOAP_XML_SEC) || soap->part == SOAP_IN_BODY))
7017
{ if (soap_attribute(soap, "xsi:type", type))
7020
if (soap->mode & SOAP_XML_CANONICAL)
7021
{ const char *t = strchr(type, ':');
7023
soap_utilize_ns(soap, type, t - type);
7027
if (soap->null && soap->position > 0)
7029
sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
7030
for (i = 1; i < soap->position; i++)
7031
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
7032
strcat(soap->tmpbuf, "]");
7033
if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
7036
if (soap->mustUnderstand)
7037
{ if (soap->actor && *soap->actor)
7038
{ if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor))
7041
if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1"))
7043
soap->mustUnderstand = 0;
7046
{ if (soap->encodingStyle && soap->local_namespaces)
7047
{ if (!*soap->encodingStyle)
7048
{ if (soap->local_namespaces[1].out)
7049
soap->encodingStyle = soap->local_namespaces[1].out;
7051
soap->encodingStyle = soap->local_namespaces[1].ns;
7053
if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
7060
if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL))
7061
soap->part = SOAP_IN_SECURITY;
7066
/******************************************************************************/
7071
soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type)
7074
if (soap_element(soap, tag, id, type))
7076
return soap_element_start_end_out(soap, NULL);
7080
/******************************************************************************/
7082
#ifndef HAVE_STRRCHR
7086
soap_strrchr(const char *s, int t)
7087
{ register char *r = NULL;
7096
/******************************************************************************/
7102
soap_strtol(const char *s, char **t, int b)
7103
{ register long n = 0;
7105
while (*s > 0 && *s <= 32)
7115
while ((c = *s) && c >= '0' && c <= '9')
7116
{ if (n >= 214748364 && (n > 214748364 || c >= '8'))
7125
else /* b == 16 and value is always positive */
7127
{ if (c >= '0' && c <= '9')
7129
else if (c >= 'A' && c <= 'F')
7131
else if (c >= 'a' && c <= 'f')
7147
/******************************************************************************/
7149
#ifndef HAVE_STRTOUL
7153
soap_strtoul(const char *s, char **t, int b)
7154
{ unsigned long n = 0;
7156
while (*s > 0 && *s <= 32)
7161
while ((c = *s) && c >= '0' && c <= '9')
7162
{ if (n >= 429496729 && (n > 429496729 || c >= '6'))
7171
{ if (c >= '0' && c <= '9')
7173
else if (c >= 'A' && c <= 'F')
7175
else if (c >= 'a' && c <= 'f')
7191
/******************************************************************************/
7196
soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset)
7197
{ if (soap_element(soap, tag, id, "SOAP-ENC:Array"))
7199
if (soap->version == 2)
7201
s = soap_strrchr(type, '[');
7202
if ((size_t)(s - type) < sizeof(soap->tmpbuf))
7203
{ strncpy(soap->tmpbuf, type, s - type);
7204
soap->tmpbuf[s - type] = '\0';
7205
if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf)))
7207
if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
7212
{ if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset)))
7214
if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type)))
7218
if (type && *type && (soap->mode & SOAP_XML_CANONICAL))
7219
{ const char *s = strchr(type, ':');
7221
soap_utilize_ns(soap, type, s - type);
7224
return soap_element_start_end_out(soap, NULL);
7228
/******************************************************************************/
7233
soap_element_start_end_out(struct soap *soap, const char *tag)
7234
{ register struct soap_attribute *tp;
7236
if (soap->mode & SOAP_XML_CANONICAL)
7237
{ struct soap_nlist *np;
7238
for (tp = soap->attributes; tp; tp = tp->next)
7239
{ if (tp->visible && tp->name)
7240
{ const char *s = strchr(tp->name, ':');
7242
soap_utilize_ns(soap, tp->name, s - tp->name);
7245
for (np = soap->nlist; np; np = np->next)
7246
{ if (np->index == 1 && np->ns)
7247
{ sprintf(soap->tmpbuf, "xmlns:%s", np->id);
7248
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
7249
soap_set_attr(soap, soap->tmpbuf, np->ns);
7256
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7257
{ register struct soap_dom_attribute **att;
7258
att = &soap->dom->atts;
7259
for (tp = soap->attributes; tp; tp = tp->next)
7261
{ *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
7263
return soap->error = SOAP_EOM;
7264
(*att)->next = NULL;
7265
(*att)->nstr = NULL;
7266
(*att)->name = soap_strdup(soap, tp->name);
7267
(*att)->data = soap_strdup(soap, tp->value);
7268
(*att)->wide = NULL;
7269
(*att)->soap = soap;
7270
att = &(*att)->next;
7277
for (tp = soap->attributes; tp; tp = tp->next)
7281
const char *s = strchr(tp->name, ':');
7283
{ size_t n = s - tp->name;
7284
if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n])
7288
if (soap_send(soap, " ") || soap_send(soap, s))
7293
if (soap_send(soap, " ") || soap_send(soap, tp->name))
7295
if (tp->visible == 2 && tp->value)
7296
if (soap_send_raw(soap, "=\"", 2)
7297
|| soap_string_out(soap, tp->value, 1)
7298
|| soap_send_raw(soap, "\"", 1))
7306
if (soap->mode & SOAP_XML_CANONICAL)
7307
{ if (soap_send_raw(soap, ">", 1)
7308
|| soap_element_end_out(soap, tag))
7313
soap->level--; /* decrement level just before /> */
7314
if (soap_send_raw(soap, "/>", 2))
7318
return soap_send_raw(soap, ">", 1);
7322
/******************************************************************************/
7327
soap_element_end_out(struct soap *soap, const char *tag)
7330
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag));
7332
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7333
{ if (soap->dom->prnt)
7334
soap->dom = soap->dom->prnt;
7339
if (soap->mode & SOAP_XML_CANONICAL)
7341
if (soap->mode & SOAP_XML_INDENT)
7343
{ if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1))
7350
{ const char *s = strchr(tag, ':');
7351
if (s && strncmp(tag, "SOAP-ENV", s - tag))
7352
{ soap_pop_ns(soap);
7357
if (soap_send_raw(soap, "</", 2)
7358
|| soap_send(soap, tag))
7360
soap->level--; /* decrement level just before > */
7361
return soap_send_raw(soap, ">", 1);
7365
/******************************************************************************/
7370
soap_element_ref(struct soap *soap, const char *tag, int id, int href)
7371
{ register int n = 0;
7372
const char *s = "href";
7373
if (soap->version == 2)
7374
{ s = "SOAP-ENC:ref";
7377
sprintf(soap->href, "#_%d", href);
7378
return soap_element_href(soap, tag, id, s, soap->href + n);
7382
/******************************************************************************/
7387
soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val)
7388
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val));
7389
if (soap_element(soap, tag, id, NULL)
7390
|| soap_attribute(soap, ref, val)
7391
|| soap_element_start_end_out(soap, tag))
7397
/******************************************************************************/
7402
soap_element_null(struct soap *soap, const char *tag, int id, const char *type)
7403
{ struct soap_attribute *tp;
7404
for (tp = soap->attributes; tp; tp = tp->next)
7407
if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL))
7408
{ if (soap_element(soap, tag, id, type))
7410
if (soap->part != SOAP_IN_HEADER && soap->encodingStyle)
7411
if (soap_attribute(soap, "xsi:nil", "true"))
7413
return soap_element_start_end_out(soap, tag);
7417
soap->mustUnderstand = 0;
7422
/******************************************************************************/
7427
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)
7428
{ if (!p || (a && !a->__ptr))
7429
{ soap_element_null(soap, tag, id, type);
7432
#ifndef WITH_NOIDREF
7433
if (soap->mode & SOAP_XML_TREE)
7436
{ struct soap_plist *pp;
7438
id = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
7440
id = soap_pointer_lookup(soap, p, t, &pp);
7442
{ if (soap_is_embedded(soap, pp))
7443
{ soap_element_ref(soap, tag, 0, id);
7446
if (soap_is_single(soap, pp))
7448
soap_set_embedded(soap, pp);
7458
/******************************************************************************/
7463
soap_element_result(struct soap *soap, const char *tag)
7464
{ if (soap->version == 2 && soap->encodingStyle)
7465
{ if (soap_element(soap, "SOAP-RPC:result", 0, NULL)
7466
|| soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc)
7467
|| soap_element_start_end_out(soap, NULL)
7468
|| soap_string_out(soap, tag, 0)
7469
|| soap_element_end_out(soap, "SOAP-RPC:result"))
7476
/******************************************************************************/
7481
soap_check_result(struct soap *soap, const char *tag)
7482
{ if (soap->version == 2 && soap->encodingStyle)
7483
{ soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1);
7484
/* just ignore content for compliance reasons, but should compare tag to element's QName value? */
7489
/******************************************************************************/
7494
soap_attribute(struct soap *soap, const char *name, const char *value)
7497
if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom)
7498
{ register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
7499
a->next = soap->dom->atts;
7501
a->name = soap_strdup(soap, name);
7502
a->data = soap_strdup(soap, value);
7505
soap->dom->atts = a;
7510
if (soap->mode & SOAP_XML_CANONICAL)
7511
{ /* TODO: consider using this code to handle default namespace bindings
7512
if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0'))
7513
{ if (name[5] == ':')
7514
soap_push_ns(soap, name + 6, value, 0);
7516
soap_push_ns(soap, "", value, 0);
7519
if (!strncmp(name, "xmlns:", 6))
7520
soap_push_ns(soap, name + 6, value, 0);
7521
else if (soap_set_attr(soap, name, value))
7526
{ if (soap_send(soap, " ") || soap_send(soap, name))
7529
if (soap_send_raw(soap, "=\"", 2)
7530
|| soap_string_out(soap, value, 1)
7531
|| soap_send_raw(soap, "\"", 1))
7538
/******************************************************************************/
7543
soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type)
7544
{ if (!soap_peek_element(soap))
7546
return soap->error = SOAP_TAG_MISMATCH;
7547
if (tag && *tag == '-')
7549
if (!(soap->error = soap_match_tag(soap, soap->tag, tag)))
7551
if (type && *soap->type && soap_match_tag(soap, soap->type, type))
7552
return soap->error = SOAP_TYPE;
7553
if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT))
7554
return soap->error = SOAP_NULL;
7557
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" ));
7560
else if (soap->error == SOAP_NO_TAG && tag && *tag == '-')
7561
soap->error = SOAP_OK;
7566
/******************************************************************************/
7571
soap_element_end_in(struct soap *soap, const char *tag)
7572
{ register soap_wchar c;
7575
if (tag && *tag == '-')
7577
if (soap->error == SOAP_NO_TAG)
7578
soap->error = SOAP_OK;
7580
/* this whitespace or mixed content is not insignificant for DOM */
7581
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7582
{ if (!soap->peeked && !soap_string_in(soap, 3, -1, -1))
7584
if (soap->dom->prnt)
7585
soap->dom = soap->dom->prnt;
7594
{ while (((c = soap_get(soap)) != SOAP_TT))
7595
{ if ((int)c == EOF)
7596
return soap->error = SOAP_EOF;
7600
{ c = soap_get(soap);
7604
soap_unget(soap, c);
7609
n = sizeof(soap->tag);
7610
while (soap_notblank(c = soap_get(soap)))
7616
return soap->error = SOAP_EOF;
7617
while (soap_blank(c))
7620
return soap->error = SOAP_SYNTAX_ERROR;
7621
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:""));
7623
if (tag && (soap->mode & SOAP_XML_STRICT))
7624
{ soap_pop_namespace(soap);
7625
if (soap_match_tag(soap, soap->tag, tag))
7626
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n"));
7627
return soap->error = SOAP_SYNTAX_ERROR;
7636
/******************************************************************************/
7641
soap_attr_value(struct soap *soap, const char *name, int flag)
7642
{ register struct soap_attribute *tp;
7644
return SOAP_STR_EOS;
7645
for (tp = soap->attributes; tp; tp = tp->next)
7646
{ if (tp->visible && !soap_match_tag(soap, tp->name, name))
7650
{ if (flag == 2 && (soap->mode & SOAP_XML_STRICT))
7651
soap->error = SOAP_PROHIBITED;
7655
else if (flag == 1 && (soap->mode & SOAP_XML_STRICT))
7656
soap->error = SOAP_REQUIRED;
7661
/******************************************************************************/
7666
soap_set_attr(struct soap *soap, const char *name, const char *value)
7667
{ register struct soap_attribute *tp;
7670
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:""));
7671
for (tp = soap->attributes; tp; tp = tp->next)
7672
{ if (!strcmp(tp->name, name))
7676
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name));
7677
if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name))))
7678
return soap->error = SOAP_EOM;
7681
if (soap->mode & SOAP_XML_CANONICAL)
7682
{ struct soap_attribute **tpp = &soap->attributes;
7683
const char *s = strchr(name, ':');
7684
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
7685
if (!strncmp(name, "xmlns", 5))
7686
{ for (; *tpp; tpp = &(*tpp)->next)
7687
if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
7691
{ for (; *tpp; tpp = &(*tpp)->next)
7692
if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0))
7697
for (; *tpp; tpp = &(*tpp)->next)
7698
{ if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name])
7700
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns));
7701
tp->ns = (*tpp)->ns;
7704
else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0)))
7713
{ tp->next = soap->attributes;
7714
soap->attributes = tp;
7716
strcpy(tp->name, name);
7719
else if (tp->visible)
7722
else if (value && tp->value && tp->size <= strlen(value))
7723
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value));
7724
SOAP_FREE(soap, tp->value);
7730
{ tp->size = strlen(value) + 1;
7731
if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
7732
return soap->error = SOAP_EOM;
7733
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value));
7735
strcpy(tp->value, value);
7736
if (!strncmp(tp->name, "xmlns:", 6))
7740
if (!strcmp(name, "wsu:Id"))
7741
{ soap->part = SOAP_BEGIN_SECURITY;
7742
strncpy(soap->id, value, sizeof(soap->id));
7743
soap->id[sizeof(soap->id)-1] = '\0';
7753
/******************************************************************************/
7758
soap_clr_attr(struct soap *soap)
7759
{ register struct soap_attribute *tp;
7761
if ((soap->mode & SOAP_XML_CANONICAL))
7762
{ while (soap->attributes)
7763
{ tp = soap->attributes->next;
7764
if (soap->attributes->value)
7765
SOAP_FREE(soap, soap->attributes->value);
7766
SOAP_FREE(soap, soap->attributes);
7767
soap->attributes = tp;
7772
{ for (tp = soap->attributes; tp; tp = tp->next)
7778
/******************************************************************************/
7781
soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
7782
{ register size_t i;
7783
for (i = 0; i < n; i++)
7784
{ register soap_wchar c = soap_get(soap);
7789
soap_unget(soap, '/');
7796
{ soap_unget(soap, c);
7822
{ soap_unget(soap, c);
7828
return soap->error = SOAP_EOF;
7832
return soap->error = SOAP_EOM;
7836
/******************************************************************************/
7842
soap_store_lab(struct soap *soap, const char *s, size_t n)
7844
return soap_append_lab(soap, s, n);
7849
/******************************************************************************/
7855
soap_append_lab(struct soap *soap, const char *s, size_t n)
7856
{ if (soap->labidx + n >= soap->lablen)
7857
{ register char *t = soap->labbuf;
7858
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
7859
if (soap->lablen == 0)
7860
soap->lablen = SOAP_LABLEN;
7861
while (soap->labidx + n >= soap->lablen)
7863
DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
7864
soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
7868
return soap->error = SOAP_EOM;
7871
{ memcpy(soap->labbuf, t, soap->labidx);
7876
{ memcpy(soap->labbuf + soap->labidx, s, n);
7884
/******************************************************************************/
7889
soap_peek_element(struct soap *soap)
7892
register struct soap_dom_attribute **att = NULL;
7893
register char *lead = NULL;
7895
register struct soap_attribute *tp, *tq = NULL;
7898
register soap_wchar c;
7902
return soap->error = SOAP_NO_TAG;
7907
soap->href[0] = '\0';
7908
soap->type[0] = '\0';
7909
soap->arrayType[0] = '\0';
7910
soap->arraySize[0] = '\0';
7911
soap->arrayOffset[0] = '\0';
7916
soap->mustUnderstand = 0;
7917
c = soap_getutf8(soap);
7919
/* whitespace leading to start tag is not insignificant for DOM */
7923
{ if (soap_append_lab(soap, NULL, 0))
7925
s = soap->labbuf + soap->labidx;
7926
i = soap->lablen - soap->labidx;
7927
soap->labidx = soap->lablen;
7928
while (soap_blank(c) && i--)
7930
c = soap_getutf8(soap);
7933
while (soap_blank(c));
7935
lead = soap_strdup(soap, soap->labbuf);
7938
while (soap_blank(c))
7939
c = soap_getutf8(soap);
7942
{ *soap->tag = '\0';
7944
return soap->error = SOAP_EOF;
7945
soap_unget(soap, c);
7947
/* whitespace leading to end tag is not insignificant for DOM */
7948
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
7949
soap->dom->tail = soap_strdup(soap, lead);
7951
return soap->error = SOAP_NO_TAG;
7954
do c = soap_get1(soap);
7955
while (soap_blank(c));
7956
i = sizeof(soap->tag);
7957
while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
7960
c = soap_get1(soap);
7962
while (soap_blank(c))
7963
c = soap_get1(soap);
7966
if (soap->mode & SOAP_XML_DOM)
7967
{ register struct soap_dom_element *elt;
7968
elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element));
7970
return soap->error = SOAP_EOM;
7973
elt->name = soap_strdup(soap, soap->tag);
7974
elt->prnt = soap->dom;
7985
{ struct soap_dom_element *p = soap->dom->elts;
7992
soap->dom->elts = elt;
7998
soap_pop_namespace(soap);
7999
for (tp = soap->attributes; tp; tp = tp->next)
8001
while ((int)c != EOF && c != '>' && c != '/')
8003
i = sizeof(soap->tmpbuf);
8004
while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
8007
c = soap_get1(soap);
8010
if (i == sizeof(soap->tmpbuf))
8011
return soap->error = SOAP_SYNTAX_ERROR;
8013
/* add attribute name to dom */
8015
{ *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute));
8017
return soap->error = SOAP_EOM;
8018
(*att)->next = NULL;
8019
(*att)->nstr = NULL;
8020
(*att)->name = soap_strdup(soap, soap->tmpbuf);
8021
(*att)->data = NULL;
8022
(*att)->wide = NULL;
8023
(*att)->soap = soap;
8026
if (!strncmp(soap->tmpbuf, "xmlns", 5))
8027
{ if (soap->tmpbuf[5] == ':')
8028
{ soap->tmpbuf[5] = '\0';
8029
t = soap->tmpbuf + 6;
8031
else if (soap->tmpbuf[5])
8039
for (tp = soap->attributes; tp; tq = tp, tp = tp->next)
8040
{ if (!SOAP_STRCMP(tp->name, soap->tmpbuf))
8044
{ tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf));
8046
return soap->error = SOAP_EOM;
8047
strcpy(tp->name, soap->tmpbuf);
8050
/* if attribute name is qualified, append it to the list */
8051
if (tq && strchr(soap->tmpbuf, ':'))
8056
{ tp->next = soap->attributes;
8057
soap->attributes = tp;
8060
while (soap_blank(c))
8061
c = soap_get1(soap);
8063
{ do c = soap_getutf8(soap);
8064
while (soap_blank(c));
8065
if (c != SOAP_QT && c != SOAP_AP)
8066
{ soap_unget(soap, c);
8067
c = ' '; /* blank delimiter */
8069
if (soap_getattrval(soap, tp->value, tp->size, c))
8072
if (soap->error != SOAP_EOM)
8074
soap->error = SOAP_OK;
8075
if (soap_store_lab(soap, tp->value, tp->size))
8078
SOAP_FREE(soap, tp->value);
8080
{ if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c))
8081
{ if (soap->error != SOAP_EOM)
8083
soap->error = SOAP_OK;
8084
soap->labidx = soap->lablen;
8085
if (soap_append_lab(soap, NULL, 0))
8092
tp->size = soap->lablen;
8094
{ tp->size = strlen(soap->labbuf) + 1;
8095
if (tp->size < SOAP_LABLEN)
8096
tp->size = SOAP_LABLEN;
8098
if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size)))
8099
return soap->error = SOAP_EOM;
8100
strcpy(tp->value, soap->labbuf);
8103
if (soap->error != SOAP_EOM)
8105
soap->error = SOAP_OK;
8106
if (soap_new_block(soap))
8109
{ if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN)))
8111
if (soap_getattrval(soap, s, SOAP_BLKLEN, c))
8112
{ if (soap->error != SOAP_EOM)
8114
soap->error = SOAP_OK;
8119
n = tp->size + soap->blist->size;
8120
if (!(s = (char*)SOAP_MALLOC(soap, n)))
8121
return soap->error = SOAP_EOM;
8123
{ memcpy(s, tp->value, tp->size);
8124
SOAP_FREE(soap, tp->value);
8126
soap_save_block(soap, s + tp->size, 0);
8131
do c = soap_get1(soap);
8132
while (soap_blank(c));
8133
tp->visible = 2; /* seen this attribute w/ value */
8136
(*att)->data = soap_strdup(soap, tp->value);
8140
tp->visible = 1; /* seen this attribute w/o value */
8143
att = &(*att)->next;
8146
{ if (soap_push_namespace(soap, t, tp->value))
8153
{ soap->dom->nstr = soap_current_namespace(soap, soap->tag);
8154
for (att = &soap->dom->atts; *att; att = &(*att)->next)
8155
(*att)->nstr = soap_current_namespace(soap, (*att)->name);
8159
return soap->error = SOAP_EOF;
8160
if (!(soap->body = (c != '/')))
8161
do c = soap_get1(soap);
8162
while (soap_blank(c));
8164
if (soap->mode & SOAP_XML_DOM)
8165
{ if (!soap->body && soap->dom->prnt)
8166
soap->dom = soap->dom->prnt;
8169
for (tp = soap->attributes; tp; tp = tp->next)
8170
{ if (tp->visible && tp->value)
8172
#ifndef WITH_NOIDREF
8173
if (!strcmp(tp->name, "id"))
8174
{ if (soap->version > 0
8175
|| (soap->mode & SOAP_XML_GRAPH))
8177
strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
8178
soap->id[sizeof(soap->id)-1] = '\0';
8181
else if (!strcmp(tp->name, "href"))
8182
{ if (soap->version == 1
8183
|| (soap->mode & SOAP_XML_GRAPH)
8184
|| (soap->mode & SOAP_ENC_MTOM))
8185
{ strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
8186
soap->href[sizeof(soap->href)-1] = '\0';
8191
if (!soap_match_tag(soap, tp->name, "xsi:type"))
8192
{ strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
8193
soap->type[sizeof(soap->type)-1] = '\0';
8195
else if ((!soap_match_tag(soap, tp->name, "xsi:null")
8196
|| !soap_match_tag(soap, tp->name, "xsi:nil"))
8197
&& (!strcmp(tp->value, "1")
8198
|| !strcmp(tp->value, "true")))
8201
else if (soap->version == 1)
8202
{ if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType"))
8203
{ s = soap_strrchr(tp->value, '[');
8204
if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
8205
{ strncpy(soap->arrayType, tp->value, s - tp->value);
8206
soap->arrayType[s - tp->value] = '\0';
8207
strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
8210
strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
8211
soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
8212
soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
8214
else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
8215
strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
8216
else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position"))
8217
soap->position = soap_getposition(tp->value, soap->positions);
8218
else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root"))
8219
soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true")));
8220
else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
8221
&& (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
8222
soap->mustUnderstand = 1;
8223
else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor"))
8224
{ if ((!soap->actor || strcmp(soap->actor, tp->value))
8225
&& strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next"))
8229
else if (soap->version == 2)
8230
{ if (!strcmp(tp->name, "ref")
8231
|| !soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
8232
{ *soap->href = '#';
8233
strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
8234
soap->href[sizeof(soap->href)-1] = '\0';
8236
else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType"))
8237
strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
8238
else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize"))
8239
strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1);
8240
else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand")
8241
&& (!strcmp(tp->value, "1") || !strcmp(tp->value, "true")))
8242
soap->mustUnderstand = 1;
8243
else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role"))
8244
{ if ((!soap->actor || strcmp(soap->actor, tp->value))
8245
&& strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next"))
8251
return soap->error = SOAP_OK;
8255
/******************************************************************************/
8260
soap_retry(struct soap *soap)
8261
{ soap->error = SOAP_OK;
8266
/******************************************************************************/
8271
soap_revert(struct soap *soap)
8272
{ if (!soap->peeked)
8277
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level));
8281
/******************************************************************************/
8286
soap_string_out(struct soap *soap, const char *s, int flag)
8287
{ register const char *t;
8288
register soap_wchar c;
8289
register soap_wchar mask = 0xFFFFFF80UL;
8291
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8292
{ soap->dom->data = soap_strdup(soap, s);
8296
if (soap->mode & SOAP_C_UTFSTRING)
8304
{ if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "	", 5))
8310
if (flag || !(soap->mode & SOAP_XML_CANONICAL))
8311
{ if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
8317
if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "
", 5))
8322
if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5))
8327
if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4))
8333
{ if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4))
8340
{ if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6))
8348
if (soap->mode & SOAP_C_MBSTRING)
8350
register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
8351
if (m > 0 && wc != c)
8352
{ if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
8360
if ((c & mask) || !(c & 0xFFFFFFE0UL))
8361
{ if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c))
8367
return soap_send_raw(soap, s, t - s - 1);
8371
/******************************************************************************/
8376
soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
8380
register long l = 0;
8383
register soap_wchar c;
8384
#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB)
8385
char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8];
8389
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n"));
8396
struct soap_attribute *tp;
8399
t[sizeof(soap->tmpbuf)-1] = '\0';
8400
strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
8402
for (tp = soap->attributes; tp; tp = tp->next)
8404
{ if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
8407
strcpy(t, tp->name);
8409
if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
8414
strcpy(t, tp->value);
8423
m = (int)strlen(soap->tmpbuf);
8431
{ register int state = 0;
8433
soap->labidx = 0; /* use look-aside buffer */
8435
if (soap_new_block(soap))
8442
if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
8444
s = soap->labbuf + soap->labidx; /* space to populate */
8445
k = soap->lablen - soap->labidx; /* number of bytes available */
8446
soap->labidx = soap->lablen; /* claim this space */
8448
register size_t k = SOAP_BLKLEN;
8449
if (!(s = (char*)soap_push_block(soap, k)))
8452
for (i = 0; i < k; i++)
8454
{ *s++ = *t++; /* copy multibyte characters */
8458
c = soap_getchar(soap);
8461
if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN))
8462
{ soap_unget(soap, c);
8463
c = soap_getutf8(soap);
8464
if (soap->mode & SOAP_C_UTFSTRING)
8465
{ if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
8469
*t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
8472
*t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
8475
*t++ = (char)(0xF0 | ((c >> 18) & 0x07));
8477
{ if (c < 0x04000000)
8478
*t++ = (char)(0xF8 | ((c >> 24) & 0x03));
8480
{ *t++ = (char)(0xFC | ((c >> 30) & 0x01));
8481
*t++ = (char)(0x80 | ((c >> 24) & 0x3F));
8483
*t++ = (char)(0x80 | ((c >> 18) & 0x3F));
8485
*t++ = (char)(0x80 | ((c >> 12) & 0x3F));
8487
*t++ = (char)(0x80 | ((c >> 6) & 0x3F));
8489
*t++ = (char)(0x80 | (c & 0x3F));
8490
m = (int)(t - buf) - 1;
8556
{ c = soap_getchar(soap);
8559
soap_unget(soap, c);
8564
c = soap_getchar(soap);
8573
{ c = soap_getchar(soap);
8575
{ do c = soap_getchar(soap);
8576
while ((int)c != EOF && c != '[');
8579
t = (char*)"![CDATA[";
8584
{ if ((c = soap_getchar(soap)) == '-')
8588
soap_unget(soap, c);
8593
soap_unget(soap, c);
8602
soap_unget(soap, c);
8614
if (soap->mode & SOAP_C_MBSTRING)
8615
{ m = wctomb(buf, c & 0x7FFFFFFF);
8616
if (m >= 1 && m <= (int)MB_CUR_MAX)
8622
{ *s++ = SOAP_UNKNOWN_CHAR;
8629
*s++ = (char)(c & 0xFF);
8632
if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8633
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8634
soap->error = SOAP_LENGTH;
8642
soap->labidx = 0; /* use look-aside buffer */
8644
if (soap_new_block(soap))
8651
if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */
8653
s = soap->labbuf + soap->labidx; /* space to populate */
8654
k = soap->lablen - soap->labidx; /* number of bytes available */
8655
soap->labidx = soap->lablen; /* claim this space */
8657
register size_t k = SOAP_BLKLEN;
8658
if (!(s = (char*)soap_push_block(soap, k)))
8661
for (i = 0; i < k; i++)
8663
{ *s++ = *t++; /* copy multibyte characters */
8667
if (soap->mode & SOAP_C_UTFSTRING)
8668
{ if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
8672
*t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
8675
*t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
8678
*t++ = (char)(0xF0 | ((c >> 18) & 0x07));
8680
{ if (c < 0x04000000)
8681
*t++ = (char)(0xF8 | ((c >> 24) & 0x03));
8683
{ *t++ = (char)(0xFC | ((c >> 30) & 0x01));
8684
*t++ = (char)(0x80 | ((c >> 24) & 0x3F));
8686
*t++ = (char)(0x80 | ((c >> 18) & 0x3F));
8688
*t++ = (char)(0x80 | ((c >> 12) & 0x3F));
8690
*t++ = (char)(0x80 | ((c >> 6) & 0x3F));
8692
*t++ = (char)(0x80 | (c & 0x3F));
8693
m = (int)(t - buf) - 1;
8700
c = soap_getutf8(soap);
8726
{ c = soap_get(soap);
8729
soap_unget(soap, c);
8733
case (soap_wchar)('<' | 0x80000000):
8742
case (soap_wchar)('>' | 0x80000000):
8751
case (soap_wchar)('&' | 0x80000000):
8760
case (soap_wchar)('"' | 0x80000000):
8769
case (soap_wchar)('\'' | 0x80000000):
8783
if (soap->mode & SOAP_C_MBSTRING)
8784
{ m = wctomb(buf, c & 0x7FFFFFFF);
8785
if (m >= 1 && m <= (int)MB_CUR_MAX)
8791
{ *s++ = SOAP_UNKNOWN_CHAR;
8798
*s++ = (char)(c & 0xFF);
8801
if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
8802
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
8803
soap->error = SOAP_LENGTH;
8809
soap_unget(soap, c);
8812
t = soap_strdup(soap, soap->labbuf);
8814
soap_size_block(soap, i+1);
8815
t = soap_save_block(soap, NULL, 0);
8817
if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
8818
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
8819
soap->error = SOAP_LENGTH;
8823
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8825
soap->dom->tail = t;
8827
soap->dom->data = t;
8831
if (soap_s2QName(soap, t, &t))
8837
/******************************************************************************/
8843
soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
8846
register soap_wchar c;
8848
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
8849
{ wchar_t *r = (wchar_t*)s;
8853
soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t));
8869
if (flag || !(soap->mode & SOAP_XML_CANONICAL))
8896
if (c >= 0x20 && c < 0x80)
8898
if (soap_send_raw(soap, &tmp, 1))
8901
else if (soap_pututf8(soap, (unsigned long)c))
8905
if (soap_send(soap, t))
8913
/******************************************************************************/
8919
soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
8921
register int i, n = 0;
8922
register long l = 0;
8923
register soap_wchar c;
8925
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n"));
8932
struct soap_attribute *tp;
8935
t[sizeof(soap->tmpbuf)-1] = '\0';
8936
strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
8938
for (tp = soap->attributes; tp; tp = tp->next)
8940
{ if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
8943
strcpy(t, tp->name);
8945
if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2)
8950
strcpy(t, tp->value);
8964
if (soap_new_block(soap))
8967
{ if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN)))
8969
for (i = 0; i < SOAP_BLKLEN; i++)
8971
{ *s++ = (wchar_t)*t++;
8976
c = soap_getutf8(soap);
8984
soap_unget(soap, '/');
9001
{ c = soap_getutf8(soap);
9004
soap_unget(soap, c);
9010
*s++ = (soap_wchar)'<';
9012
{ *s++ = (soap_wchar)'&';
9018
*s++ = (soap_wchar)'>';
9020
{ *s++ = (soap_wchar)'&';
9026
*s++ = (soap_wchar)'"';
9028
{ *s++ = (soap_wchar)'&';
9035
*s++ = (wchar_t)c & 0x7FFFFFFF;
9038
if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen)
9039
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen));
9040
soap->error = SOAP_LENGTH;
9046
soap_unget(soap, c);
9048
soap_size_block(soap, sizeof(wchar_t) * (i + 1));
9049
if ((soap->mode & SOAP_XML_STRICT) && l < minlen)
9050
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen));
9051
soap->error = SOAP_LENGTH;
9054
s = (wchar_t*)soap_save_block(soap, NULL, 0);
9056
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
9057
soap->dom->wide = s;
9064
/******************************************************************************/
9069
soap_int2s(struct soap *soap, int n)
9070
{ return soap_long2s(soap, (long)n);
9074
/******************************************************************************/
9079
soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n)
9080
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9081
|| soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
9083
return soap_element_end_out(soap, tag);
9087
/******************************************************************************/
9092
soap_s2int(struct soap *soap, const char *s, int *p)
9100
*p = (int)soap_strtol(s, &r, 10);
9101
if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9104
|| soap_errno == SOAP_ERANGE
9108
soap->error = SOAP_TYPE;
9114
/******************************************************************************/
9119
soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t)
9120
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9124
&& soap_match_tag(soap, soap->type, type)
9125
&& soap_match_tag(soap, soap->type, ":int")
9126
&& soap_match_tag(soap, soap->type, ":short")
9127
&& soap_match_tag(soap, soap->type, ":byte"))
9128
{ soap->error = SOAP_TYPE;
9133
p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL);
9135
p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL);
9137
{ if (soap_s2int(soap, soap_value(soap), p))
9140
if (soap->body && soap_element_end_in(soap, tag))
9146
/******************************************************************************/
9151
soap_long2s(struct soap *soap, long n)
9152
{ sprintf(soap->tmpbuf, "%ld", n);
9153
return soap->tmpbuf;
9157
/******************************************************************************/
9162
soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n)
9163
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9164
|| soap_string_out(soap, soap_long2s(soap, *p), 0))
9166
return soap_element_end_out(soap, tag);
9170
/******************************************************************************/
9175
soap_s2long(struct soap *soap, const char *s, long *p)
9183
*p = soap_strtol(s, &r, 10);
9184
if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9187
|| soap_errno == SOAP_ERANGE
9191
soap->error = SOAP_TYPE;
9197
/******************************************************************************/
9202
soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t)
9203
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9207
&& soap_match_tag(soap, soap->type, type)
9208
&& soap_match_tag(soap, soap->type, ":int")
9209
&& soap_match_tag(soap, soap->type, ":short")
9210
&& soap_match_tag(soap, soap->type, ":byte"))
9211
{ soap->error = SOAP_TYPE;
9216
p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL);
9218
p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL);
9220
{ if (soap_s2long(soap, soap_value(soap), p))
9223
if (soap->body && soap_element_end_in(soap, tag))
9229
/******************************************************************************/
9234
soap_LONG642s(struct soap *soap, LONG64 n)
9235
{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
9236
return soap->tmpbuf;
9240
/******************************************************************************/
9245
soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n)
9246
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9247
|| soap_string_out(soap, soap_LONG642s(soap, *p), 0))
9249
return soap_element_end_out(soap, tag);
9253
/******************************************************************************/
9258
soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p)
9268
*p = strtoll(s, &r, 10);
9269
if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9272
|| soap_errno == SOAP_ERANGE
9278
if (sscanf(s, SOAP_LONG_FORMAT, p) != 1)
9281
soap->error = SOAP_TYPE;
9287
/******************************************************************************/
9292
soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t)
9293
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9297
&& soap_match_tag(soap, soap->type, type)
9298
&& soap_match_tag(soap, soap->type, ":integer")
9299
&& soap_match_tag(soap, soap->type, ":positiveInteger")
9300
&& soap_match_tag(soap, soap->type, ":negativeInteger")
9301
&& soap_match_tag(soap, soap->type, ":nonPositiveInteger")
9302
&& soap_match_tag(soap, soap->type, ":nonNegativeInteger")
9303
&& soap_match_tag(soap, soap->type, ":long")
9304
&& soap_match_tag(soap, soap->type, ":int")
9305
&& soap_match_tag(soap, soap->type, ":short")
9306
&& soap_match_tag(soap, soap->type, ":byte"))
9307
{ soap->error = SOAP_TYPE;
9312
p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL);
9314
p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL);
9316
{ if (soap_s2LONG64(soap, soap_value(soap), p))
9319
if (soap->body && soap_element_end_in(soap, tag))
9325
/******************************************************************************/
9330
soap_byte2s(struct soap *soap, char n)
9331
{ return soap_long2s(soap, (long)n);
9335
/******************************************************************************/
9340
soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n)
9341
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9342
|| soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
9344
return soap_element_end_out(soap, tag);
9348
/******************************************************************************/
9353
soap_s2byte(struct soap *soap, const char *s, char *p)
9357
n = soap_strtol(s, &r, 10);
9358
if (s == r || *r || n < -128 || n > 127)
9359
soap->error = SOAP_TYPE;
9366
/******************************************************************************/
9371
soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t)
9372
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9376
&& soap_match_tag(soap, soap->type, type)
9377
&& soap_match_tag(soap, soap->type, ":byte"))
9378
{ soap->error = SOAP_TYPE;
9383
p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL);
9385
p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL);
9387
{ if (soap_s2byte(soap, soap_value(soap), p))
9390
if (soap->body && soap_element_end_in(soap, tag))
9396
/******************************************************************************/
9401
soap_short2s(struct soap *soap, short n)
9402
{ return soap_long2s(soap, (long)n);
9406
/******************************************************************************/
9411
soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n)
9412
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9413
|| soap_string_out(soap, soap_long2s(soap, (long)*p), 0))
9415
return soap_element_end_out(soap, tag);
9419
/******************************************************************************/
9424
soap_s2short(struct soap *soap, const char *s, short *p)
9428
n = soap_strtol(s, &r, 10);
9429
if (s == r || *r || n < -32768 || n > 32767)
9430
soap->error = SOAP_TYPE;
9437
/******************************************************************************/
9442
soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t)
9443
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9447
&& soap_match_tag(soap, soap->type, type)
9448
&& soap_match_tag(soap, soap->type, ":short")
9449
&& soap_match_tag(soap, soap->type, ":byte"))
9450
{ soap->error = SOAP_TYPE;
9455
p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL);
9457
p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL);
9459
{ if (soap_s2short(soap, soap_value(soap), p))
9462
if (soap->body && soap_element_end_in(soap, tag))
9468
/******************************************************************************/
9473
soap_float2s(struct soap *soap, float n)
9475
if (soap_isnan((double)n))
9477
if (soap_ispinff(n))
9479
if (soap_isninff(n))
9482
sprintf(soap->tmpbuf, soap->float_format, n);
9483
t = strchr(s, ','); /* convert decimal comma to DP */
9490
/******************************************************************************/
9495
soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n)
9496
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9497
|| soap_string_out(soap, soap_float2s(soap, *p), 0))
9499
return soap_element_end_out(soap, tag);
9503
/******************************************************************************/
9508
soap_s2float(struct soap *soap, const char *s, float *p)
9511
return soap->error = SOAP_TYPE;
9512
if (!soap_tag_cmp(s, "INF"))
9514
else if (!soap_tag_cmp(s, "+INF"))
9516
else if (!soap_tag_cmp(s, "-INF"))
9518
else if (!soap_tag_cmp(s, "NaN"))
9522
/* On some systems, strtof appears to be broken or doesn't link: use with caution */
9523
#if defined(HAVE_STRTOF)
9525
*p = strtof((char*)s, &r);
9527
#elif defined(HAVE_STRTOD)
9529
*p = (float)strtod(s, &r);
9533
if (sscanf(s, "%g", p) != 1)
9534
soap->error = SOAP_TYPE;
9536
soap->error = SOAP_TYPE;
9544
/******************************************************************************/
9546
static int soap_isnumeric(struct soap *soap, const char *type)
9547
{ if (soap_match_tag(soap, soap->type, type)
9548
&& soap_match_tag(soap, soap->type, ":float")
9549
&& soap_match_tag(soap, soap->type, ":double")
9550
&& soap_match_tag(soap, soap->type, ":decimal")
9551
&& soap_match_tag(soap, soap->type, ":integer")
9552
&& soap_match_tag(soap, soap->type, ":positiveInteger")
9553
&& soap_match_tag(soap, soap->type, ":negativeInteger")
9554
&& soap_match_tag(soap, soap->type, ":nonPositiveInteger")
9555
&& soap_match_tag(soap, soap->type, ":nonNegativeInteger")
9556
&& soap_match_tag(soap, soap->type, ":long")
9557
&& soap_match_tag(soap, soap->type, ":int")
9558
&& soap_match_tag(soap, soap->type, ":short")
9559
&& soap_match_tag(soap, soap->type, ":byte")
9560
&& soap_match_tag(soap, soap->type, ":unsignedLong")
9561
&& soap_match_tag(soap, soap->type, ":unsignedInt")
9562
&& soap_match_tag(soap, soap->type, ":unsignedShort")
9563
&& soap_match_tag(soap, soap->type, ":unsignedByte"))
9564
{ soap->error = SOAP_TYPE;
9572
/******************************************************************************/
9577
soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t)
9578
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9581
if (*soap->type != '\0' && soap_isnumeric(soap, type))
9584
p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL);
9586
p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL);
9588
{ if (soap_s2float(soap, soap_value(soap), p))
9591
if (soap->body && soap_element_end_in(soap, tag))
9597
/******************************************************************************/
9602
soap_double2s(struct soap *soap, double n)
9606
if (soap_ispinfd(n))
9608
if (soap_isninfd(n))
9611
sprintf(soap->tmpbuf, soap->double_format, n);
9612
t = strchr(s, ','); /* convert decimal comma to DP */
9619
/******************************************************************************/
9624
soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n)
9625
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9626
|| soap_string_out(soap, soap_double2s(soap, *p), 0))
9628
return soap_element_end_out(soap, tag);
9632
/******************************************************************************/
9637
soap_s2double(struct soap *soap, const char *s, double *p)
9640
return soap->error = SOAP_TYPE;
9641
if (!soap_tag_cmp(s, "INF"))
9643
else if (!soap_tag_cmp(s, "+INF"))
9645
else if (!soap_tag_cmp(s, "-INF"))
9647
else if (!soap_tag_cmp(s, "NaN"))
9657
if (sscanf(s, "%lg", p) != 1)
9658
soap->error = SOAP_TYPE;
9660
soap->error = SOAP_TYPE;
9668
/******************************************************************************/
9673
soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t)
9674
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9677
if (*soap->type != '\0' && soap_isnumeric(soap, type))
9680
p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL);
9682
p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL);
9684
{ if (soap_s2double(soap, soap_value(soap), p))
9687
if (soap->body && soap_element_end_in(soap, tag))
9693
/******************************************************************************/
9698
soap_unsignedByte2s(struct soap *soap, unsigned char n)
9699
{ return soap_unsignedLong2s(soap, (unsigned long)n);
9703
/******************************************************************************/
9708
soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n)
9709
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9710
|| soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9712
return soap_element_end_out(soap, tag);
9716
/******************************************************************************/
9721
soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p)
9725
n = soap_strtoul(s, &r, 10);
9726
if (s == r || *r || n > 255)
9727
soap->error = SOAP_TYPE;
9728
*p = (unsigned char)n;
9734
/******************************************************************************/
9739
soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t)
9740
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9744
&& soap_match_tag(soap, soap->type, type)
9745
&& soap_match_tag(soap, soap->type, ":unsignedByte"))
9746
{ soap->error = SOAP_TYPE;
9751
p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL);
9753
p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL);
9755
{ if (soap_s2unsignedByte(soap, soap_value(soap), p))
9758
if (soap->body && soap_element_end_in(soap, tag))
9764
/******************************************************************************/
9769
soap_unsignedShort2s(struct soap *soap, unsigned short n)
9770
{ return soap_unsignedLong2s(soap, (unsigned long)n);
9774
/******************************************************************************/
9779
soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n)
9780
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9781
|| soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9783
return soap_element_end_out(soap, tag);
9787
/******************************************************************************/
9792
soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p)
9796
n = soap_strtoul(s, &r, 10);
9797
if (s == r || *r || n > 65535)
9798
soap->error = SOAP_TYPE;
9799
*p = (unsigned short)n;
9805
/******************************************************************************/
9810
soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t)
9811
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9815
&& soap_match_tag(soap, soap->type, type)
9816
&& soap_match_tag(soap, soap->type, ":unsignedShort")
9817
&& soap_match_tag(soap, soap->type, ":unsignedByte"))
9818
{ soap->error = SOAP_TYPE;
9823
p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL);
9825
p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL);
9827
{ if (soap_s2unsignedShort(soap, soap_value(soap), p))
9830
if (soap->body && soap_element_end_in(soap, tag))
9836
/******************************************************************************/
9841
soap_unsignedInt2s(struct soap *soap, unsigned int n)
9842
{ return soap_unsignedLong2s(soap, (unsigned long)n);
9846
/******************************************************************************/
9851
soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n)
9852
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9853
|| soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0))
9855
return soap_element_end_out(soap, tag);
9859
/******************************************************************************/
9864
soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p)
9872
*p = (unsigned int)soap_strtoul(s, &r, 10);
9873
if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9876
|| soap_errno == SOAP_ERANGE
9880
soap->error = SOAP_TYPE;
9886
/******************************************************************************/
9891
soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t)
9892
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9896
&& soap_match_tag(soap, soap->type, type)
9897
&& soap_match_tag(soap, soap->type, ":unsignedInt")
9898
&& soap_match_tag(soap, soap->type, ":unsignedShort")
9899
&& soap_match_tag(soap, soap->type, ":unsignedByte"))
9900
{ soap->error = SOAP_TYPE;
9905
p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL);
9907
p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL);
9909
{ if (soap_s2unsignedInt(soap, soap_value(soap), p))
9912
if (soap->body && soap_element_end_in(soap, tag))
9918
/******************************************************************************/
9923
soap_unsignedLong2s(struct soap *soap, unsigned long n)
9924
{ sprintf(soap->tmpbuf, "%lu", n);
9925
return soap->tmpbuf;
9929
/******************************************************************************/
9934
soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n)
9935
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
9936
|| soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0))
9938
return soap_element_end_out(soap, tag);
9942
/******************************************************************************/
9947
soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p)
9955
*p = soap_strtoul(s, &r, 10);
9956
if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
9959
|| soap_errno == SOAP_ERANGE
9963
soap->error = SOAP_TYPE;
9969
/******************************************************************************/
9974
soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t)
9975
{ if (soap_element_begin_in(soap, tag, 0, NULL))
9979
&& soap_match_tag(soap, soap->type, type)
9980
&& soap_match_tag(soap, soap->type, ":unsignedInt")
9981
&& soap_match_tag(soap, soap->type, ":unsignedShort")
9982
&& soap_match_tag(soap, soap->type, ":unsignedByte"))
9983
{ soap->error = SOAP_TYPE;
9988
p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL);
9990
p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL);
9992
{ if (soap_s2unsignedLong(soap, soap_value(soap), p))
9995
if (soap->body && soap_element_end_in(soap, tag))
10001
/******************************************************************************/
10006
soap_ULONG642s(struct soap *soap, ULONG64 n)
10007
{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
10008
return soap->tmpbuf;
10012
/******************************************************************************/
10017
soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n)
10018
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
10019
|| soap_string_out(soap, soap_ULONG642s(soap, *p), 0))
10020
return soap->error;
10021
return soap_element_end_out(soap, tag);
10025
/******************************************************************************/
10030
soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p)
10033
#ifdef HAVE_STRTOULL
10040
*p = strtoull(s, &r, 10);
10041
if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r
10044
|| soap_errno == SOAP_ERANGE
10049
# ifdef HAVE_SSCANF
10050
if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1)
10053
soap->error = SOAP_TYPE;
10055
return soap->error;
10059
/******************************************************************************/
10064
soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t)
10065
{ if (soap_element_begin_in(soap, tag, 0, NULL))
10068
&& soap_match_tag(soap, soap->type, type)
10069
&& soap_match_tag(soap, soap->type, ":positiveInteger")
10070
&& soap_match_tag(soap, soap->type, ":nonNegativeInteger")
10071
&& soap_match_tag(soap, soap->type, ":unsignedLong")
10072
&& soap_match_tag(soap, soap->type, ":unsignedInt")
10073
&& soap_match_tag(soap, soap->type, ":unsignedShort")
10074
&& soap_match_tag(soap, soap->type, ":unsignedByte"))
10075
{ soap->error = SOAP_TYPE;
10079
p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL);
10081
p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL);
10083
{ if (soap_s2ULONG64(soap, soap_value(soap), p))
10086
if (soap->body && soap_element_end_in(soap, tag))
10092
/******************************************************************************/
10097
soap_s2string(struct soap *soap, const char *s, char **t)
10100
{ if (!(*t = soap_strdup(soap, s)))
10101
return soap->error = SOAP_EOM;
10102
if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING)))
10103
{ /* TODO: consider truncating UTF8 to ASCII for regular XML attribute strings? */
10106
return soap->error;
10110
/******************************************************************************/
10115
soap_s2QName(struct soap *soap, const char *s, char **t)
10117
{ struct soap_nlist *np = soap->nlist;
10119
/* if there is no namespace stack, or prefix is "xml" then pass string */
10120
if (!np || !strncmp(s, "xml:", 4))
10121
{ *t = soap_strdup(soap, s);
10124
/* else we normalize the QName by replacing its prefix */
10125
p = strchr(s, ':');
10127
{ register size_t n = p - s;
10128
while (np && (strncmp(np->id, s, n) || np->id[n]))
10133
{ while (np && *np->id)
10138
{ if (np->index >= 0 && soap->local_namespaces)
10139
{ register const char *q = soap->local_namespaces[np->index].id;
10141
{ if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2)))
10142
sprintf(*t, "%s:%s", q, p);
10147
{ if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4)))
10148
sprintf(*t, "\"%s\":%s", np->ns, p);
10151
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:""));
10152
return soap->error = SOAP_NAMESPACE;
10154
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s));
10155
if ((*t = (char*)soap_malloc(soap, strlen(p) + 4)))
10156
sprintf(*t, "\"\":%s", p);
10160
return soap->error;
10164
/******************************************************************************/
10169
soap_QName2s(struct soap *soap, const char *s)
10170
{ register struct Namespace *p;
10173
if (!s || *s != '"')
10176
if (s && (soap->mode & SOAP_XML_CANONICAL))
10177
{ t = (char*)strchr(s, ':');
10179
soap_utilize_ns(soap, s, t - s);
10185
if ((p = soap->local_namespaces))
10186
{ for (; p->id; p++)
10188
if (!soap_tag_cmp(s, p->ns))
10191
if (!soap_tag_cmp(s, p->in))
10195
{ s = strchr(s, '"');
10197
{ t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s));
10204
t = (char*)strchr(s, '"');
10209
t = soap_strdup(soap, s);
10211
sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
10212
soap_set_attr(soap, soap->tmpbuf, t);
10213
s = strchr(s, '"');
10215
{ t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6);
10216
strcpy(t, soap->tmpbuf + 6);
10223
/******************************************************************************/
10228
soap_s2wchar(struct soap *soap, const char *s, wchar_t **t)
10233
{ *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1));
10235
return soap->error;
10236
if (soap->mode & SOAP_ENC_LATIN)
10238
*r++ = (wchar_t)*s++;
10241
{ /* Convert UTF8 to wchar */
10243
{ register soap_wchar c, c1, c2, c3, c4;
10248
{ c1 = (soap_wchar)*s++ & 0x3F;
10250
*r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1);
10252
{ c2 = (soap_wchar)*s++ & 0x3F;
10254
*r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2);
10256
{ c3 = (soap_wchar)*s++ & 0x3F;
10258
*r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3);
10260
{ c4 = (soap_wchar)*s++ & 0x3F;
10262
*r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4);
10264
*r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F));
10277
/******************************************************************************/
10282
soap_wchar2s(struct soap *soap, const wchar_t *s)
10283
{ register soap_wchar c;
10284
register char *r, *t;
10285
const wchar_t *q = s;
10288
{ if (c > 0 && c < 0x80)
10293
r = t = (char*)soap_malloc(soap, n + 1);
10295
{ /* Convert wchar to UTF8 */
10297
{ if (c > 0 && c < 0x80)
10301
*t++ = (char)(0xC0 | ((c >> 6) & 0x1F));
10303
{ if (c < 0x010000)
10304
*t++ = (char)(0xE0 | ((c >> 12) & 0x0F));
10306
{ if (c < 0x200000)
10307
*t++ = (char)(0xF0 | ((c >> 18) & 0x07));
10309
{ if (c < 0x04000000)
10310
*t++ = (char)(0xF8 | ((c >> 24) & 0x03));
10312
{ *t++ = (char)(0xFC | ((c >> 30) & 0x01));
10313
*t++ = (char)(0x80 | ((c >> 24) & 0x3F));
10315
*t++ = (char)(0x80 | ((c >> 18) & 0x3F));
10317
*t++ = (char)(0x80 | ((c >> 12) & 0x3F));
10319
*t++ = (char)(0x80 | ((c >> 6) & 0x3F));
10321
*t++ = (char)(0x80 | (c & 0x3F));
10330
/******************************************************************************/
10335
soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n)
10336
{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
10338
return soap->error;
10339
if (!**p && (soap->mode & SOAP_C_NILSTRING))
10340
return soap_element_null(soap, tag, id, type);
10341
if (soap_element_begin_out(soap, tag, id, type)
10342
|| soap_string_out(soap, *p, 0)
10343
|| soap_element_end_out(soap, tag))
10344
return soap->error;
10349
/******************************************************************************/
10354
soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen)
10355
{ if (soap_element_begin_in(soap, tag, 1, NULL))
10356
{ if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
10358
soap->error = SOAP_OK;
10361
{ if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
10365
{ *p = soap_string_in(soap, flag, minlen, maxlen);
10366
if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL))
10368
if (!**p && tag && *tag == '-')
10369
{ soap->error = SOAP_NO_TAG;
10373
else if (tag && *tag == '-')
10374
{ soap->error = SOAP_NO_TAG;
10377
else if (soap->null)
10380
*p = (char*)SOAP_STR_EOS;
10382
p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0);
10383
if (soap->body && soap_element_end_in(soap, tag))
10389
/******************************************************************************/
10390
#ifndef WITH_LEANER
10395
soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n)
10396
{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n);
10398
return soap->error;
10399
if (!**p && (soap->mode & SOAP_C_NILSTRING))
10400
return soap_element_null(soap, tag, id, type);
10401
if (soap_element_begin_out(soap, tag, id, type)
10402
|| soap_wstring_out(soap, *p, 0)
10403
|| soap_element_end_out(soap, tag))
10404
return soap->error;
10410
/******************************************************************************/
10411
#ifndef WITH_LEANER
10416
soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen)
10417
{ if (soap_element_begin_in(soap, tag, 1, NULL))
10418
{ if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG)
10420
soap->error = SOAP_OK;
10423
{ if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
10427
{ *p = soap_wstring_in(soap, 1, minlen, maxlen);
10428
if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL))
10430
if (!**p && tag && *tag == '-')
10431
{ soap->error = SOAP_NO_TAG;
10435
else if (tag && *tag == '-')
10436
{ soap->error = SOAP_NO_TAG;
10439
else if (soap->null)
10442
*p = (wchar_t*)SOAP_STR_EOS;
10444
p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0);
10445
if (soap->body && soap_element_end_in(soap, tag))
10452
/******************************************************************************/
10457
soap_timegm(struct tm *T)
10459
#if defined(HAVE_TIMEGM)
10467
#ifdef HAVE_GMTIME_R
10482
/******************************************************************************/
10487
soap_dateTime2s(struct soap *soap, time_t n)
10488
{ struct tm T, *pT = &T;
10489
#if defined(HAVE_GMTIME_R)
10490
if (gmtime_r(&n, pT))
10491
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
10492
/* The following defines were added for VxWorks*/
10493
#elif defined(HAVE_PGMTIME_R)
10494
if (gmtime_r(&n, pT))
10495
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
10496
#elif defined(HAVE_PGMTIME)
10497
if (gmtime(&n, pT))
10498
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
10499
#elif defined(HAVE_GMTIME)
10500
if ((pT = gmtime(&n)))
10501
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
10502
#elif defined(HAVE_GETTIMEOFDAY)
10503
struct timezone tz;
10504
memset((void*)&tz, 0, sizeof(tz));
10505
# if defined(HAVE_LOCALTIME_R)
10506
if (localtime_r(&n, pT))
10507
{ struct timeval tv;
10508
gettimeofday(&tv, &tz);
10509
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10510
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
10513
if ((pT = localtime(&n)))
10514
{ struct timeval tv;
10515
gettimeofday(&tv, &tz);
10516
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10517
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
10520
#elif defined(HAVE_FTIME)
10522
memset((void*)&t, 0, sizeof(t));
10523
# if defined(HAVE_LOCALTIME_R)
10524
if (localtime_r(&n, pT))
10526
#ifdef __BORLANDC__
10531
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10532
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
10534
/* The following defines were added for VxWorks*/
10535
# elif defined(HAVE_PLOCALTIME_R)
10536
if (localtime_r(&n, pT))
10537
{ strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10538
sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60);
10541
if ((pT = localtime(&n)))
10543
#ifdef __BORLANDC__
10548
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10549
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
10552
#elif defined(HAVE_LOCALTIME_R)
10553
if (localtime_r(&n, pT))
10554
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10555
/* The following defines were added for VxWorks*/
10556
#elif defined(HAVE_PLOCALTIME_R)
10557
if (localtime_r(&n, pT))
10558
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10560
if ((pT = localtime(&n)))
10561
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
10564
strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z");
10565
return soap->tmpbuf;
10569
/******************************************************************************/
10574
soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n)
10575
{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type)
10576
|| soap_string_out(soap, soap_dateTime2s(soap, *p), 0))
10577
return soap->error;
10578
return soap_element_end_out(soap, tag);
10582
/******************************************************************************/
10587
soap_s2dateTime(struct soap *soap, const char *s, time_t *p)
10592
memset((void*)&T, 0, sizeof(T));
10593
zone[sizeof(zone)-1] = '\0';
10594
if (strchr(s, '-'))
10595
t = "%d-%d-%dT%d:%d:%d%31s";
10596
else if (strchr(s, ':'))
10597
t = "%4d%2d%2dT%d:%d:%d%31s";
10598
else /* parse non-XSD-standard alternative ISO 8601 format */
10599
t = "%4d%2d%2dT%2d%2d%2d%31s";
10600
sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone);
10601
if (T.tm_year == 1)
10607
{ if (*zone == '.')
10608
{ for (s = zone + 1; *s; s++)
10609
if (*s < '0' || *s > '9')
10614
if (*s == '+' || *s == '-')
10615
{ int h = 0, m = 0;
10617
{ sscanf(s, "%d:%d", &h, &m);
10622
{ m = (int)atol(s);
10630
*p = soap_timegm(&T);
10634
*p = mktime(&T); /* no time zone: suppose it is localtime? */
10637
return soap->error;
10641
/******************************************************************************/
10646
soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t)
10647
{ if (soap_element_begin_in(soap, tag, 0, NULL))
10650
&& soap_match_tag(soap, soap->type, type)
10651
&& soap_match_tag(soap, soap->type, ":dateTime"))
10652
{ soap->error = SOAP_TYPE;
10656
p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL);
10658
p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL);
10660
{ if (soap_s2dateTime(soap, soap_value(soap), p))
10663
if (soap->body && soap_element_end_in(soap, tag))
10669
/******************************************************************************/
10674
soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type)
10676
const char *t = NULL;
10677
if (tag && *tag != '-')
10678
{ if (soap->local_namespaces && (t = strchr(tag, ':')))
10679
{ strncpy(soap->tmpbuf, tag, t-tag);
10680
soap->tmpbuf[t-tag] = '\0';
10681
for (i = 0; soap->local_namespaces[i].id; i++)
10682
if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
10685
if (soap_element(soap, t, 0, type)
10686
|| soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
10687
|| soap_element_start_end_out(soap, NULL))
10688
return soap->error;
10692
if (soap_element_begin_out(soap, t, 0, type))
10693
return soap->error;
10697
{ if (soap_send(soap, *p))
10698
return soap->error;
10701
return soap_element_end_out(soap, t);
10706
/******************************************************************************/
10711
soap_inliteral(struct soap *soap, const char *tag, char **p)
10712
{ if (soap_element_begin_in(soap, tag, 1, NULL))
10713
{ if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
10715
soap->error = SOAP_OK;
10718
{ if (!(p = (char**)soap_malloc(soap, sizeof(char*))))
10722
{ *p = soap_string_in(soap, 0, -1, -1);
10725
if (!**p && tag && *tag == '-')
10726
{ soap->error = SOAP_NO_TAG;
10730
else if (tag && *tag == '-')
10731
{ soap->error = SOAP_NO_TAG;
10734
else if (soap->null)
10737
*p = (char*)SOAP_STR_EOS;
10738
if (soap->body && soap_element_end_in(soap, tag))
10744
/******************************************************************************/
10745
#ifndef WITH_LEANER
10750
soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type)
10752
const char *t = NULL;
10753
if (tag && *tag != '-')
10754
{ if (soap->local_namespaces && (t = strchr(tag, ':')))
10755
{ strncpy(soap->tmpbuf, tag, t-tag);
10756
soap->tmpbuf[t-tag] = '\0';
10757
for (i = 0; soap->local_namespaces[i].id; i++)
10758
if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
10761
if (soap_element(soap, t, 0, type)
10762
|| soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS)
10763
|| soap_element_start_end_out(soap, NULL))
10764
return soap->error;
10768
if (soap_element_begin_out(soap, t, 0, type))
10769
return soap->error;
10771
if (soap_send(soap, soap->tmpbuf))
10772
return soap->error;
10776
const wchar_t *s = *p;
10778
{ if (soap_pututf8(soap, (unsigned long)c))
10779
return soap->error;
10783
return soap_element_end_out(soap, t);
10789
/******************************************************************************/
10790
#ifndef WITH_LEANER
10795
soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p)
10796
{ if (soap_element_begin_in(soap, tag, 1, NULL))
10797
{ if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT)
10799
soap->error = SOAP_OK;
10802
{ if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*))))
10806
{ *p = soap_wstring_in(soap, 0, -1, -1);
10809
if (!**p && tag && *tag == '-')
10810
{ soap->error = SOAP_NO_TAG;
10814
else if (tag && *tag == '-')
10815
{ soap->error = SOAP_NO_TAG;
10818
else if (soap->null)
10821
*p = (wchar_t*)SOAP_STR_EOS;
10822
if (soap->body && soap_element_end_in(soap, tag))
10829
/******************************************************************************/
10834
soap_value(struct soap *soap)
10835
{ register size_t i;
10836
register soap_wchar c = 0;
10837
register char *s = soap->tmpbuf;
10839
return SOAP_STR_EOS;
10840
do c = soap_get(soap);
10841
while (soap_blank(c));
10842
for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++)
10843
{ if (c == SOAP_TT || (int)c == EOF)
10846
c = soap_get(soap);
10848
for (s--; i > 0; i--, s--)
10849
{ if (!soap_blank(*s))
10853
if ((int)c == EOF || c == SOAP_TT)
10854
soap_unget(soap, c);
10855
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
10857
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
10858
soap->dom->data = soap_strdup(soap, soap->tmpbuf);
10860
return soap->tmpbuf; /* return non-null pointer */
10864
/******************************************************************************/
10865
#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP)
10870
soap_getline(struct soap *soap, char *s, int len)
10875
{ c = soap_getchar(soap);
10876
if (c == '\r' || c == '\n')
10879
return soap->error = SOAP_EOF;
10883
c = soap_getchar(soap); /* got \r or something else, now get \n */
10886
if (i+1 == len) /* empty line: end of HTTP/MIME header */
10888
c = soap_unget(soap, soap_getchar(soap));
10889
if (c != ' ' && c != '\t') /* HTTP line continuation? */
10892
else if ((int)c == EOF)
10893
return soap->error = SOAP_EOF;
10896
return soap->error = SOAP_HDR;
10902
/******************************************************************************/
10905
soap_count_attachments(struct soap *soap)
10907
#ifndef WITH_LEANER
10908
register struct soap_multipart *content;
10909
register size_t count = soap->count;
10910
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count));
10911
if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
10912
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n"));
10913
for (content = soap->dime.first; content; content = content->next)
10914
{ count += 12 + ((content->size+3)&(~3));
10916
count += ((strlen(content->id)+3)&(~3));
10918
count += ((strlen(content->type)+3)&(~3));
10919
if (content->options)
10920
count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3);
10921
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size));
10924
if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary)
10925
{ register size_t n = strlen(soap->mime.boundary);
10926
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n"));
10927
for (content = soap->mime.first; content; content = content->next)
10928
{ register const char *s;
10929
/* count \r\n--boundary\r\n */
10931
/* count Content-Type: ...\r\n */
10933
count += 16 + strlen(content->type);
10934
/* count Content-Transfer-Encoding: ...\r\n */
10935
s = soap_code_str(mime_codes, content->encoding);
10937
count += 29 + strlen(s);
10938
/* count Content-ID: ...\r\n */
10940
count += 14 + strlen(content->id);
10941
/* count Content-Location: ...\r\n */
10942
if (content->location)
10943
count += 20 + strlen(content->location);
10944
/* count Content-Description: ...\r\n */
10945
if (content->description)
10946
count += 23 + strlen(content->description);
10947
/* count \r\n...content */
10948
count += 2 + content->size;
10949
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size));
10951
/* count \r\n--boundary-- */
10954
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count));
10957
return soap->count;
10962
/******************************************************************************/
10963
#ifndef WITH_LEANER
10966
soap_putdimefield(struct soap *soap, const char *s, size_t n)
10967
{ if (soap_send_raw(soap, s, n))
10968
return soap->error;
10969
return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3);
10974
/******************************************************************************/
10975
#ifndef WITH_LEANER
10980
soap_dime_option(struct soap *soap, unsigned short optype, const char *option)
10984
{ n = strlen(option);
10985
s = (char*)soap_malloc(soap, n + 5);
10987
{ s[0] = (char)(optype >> 8);
10988
s[1] = (char)(optype & 0xFF);
10989
s[2] = (char)(n >> 8);
10990
s[3] = (char)(n & 0xFF);
10991
strcpy(s + 4, option);
10999
/******************************************************************************/
11000
#ifndef WITH_LEANER
11005
soap_putdimehdr(struct soap *soap)
11006
{ unsigned char tmp[12];
11007
size_t optlen = 0, idlen = 0, typelen = 0;
11008
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:""));
11009
if (soap->dime.options)
11010
optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4;
11012
{ idlen = strlen(soap->dime.id);
11013
if (idlen > 0x0000FFFF)
11014
idlen = 0x0000FFFF;
11016
if (soap->dime.type)
11017
{ typelen = strlen(soap->dime.type);
11018
if (typelen > 0x0000FFFF)
11019
typelen = 0x0000FFFF;
11021
tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7);
11022
tmp[1] = soap->dime.flags & 0xF0;
11023
tmp[2] = (char)(optlen >> 8);
11024
tmp[3] = (char)(optlen & 0xFF);
11025
tmp[4] = (char)(idlen >> 8);
11026
tmp[5] = (char)(idlen & 0xFF);
11027
tmp[6] = (char)(typelen >> 8);
11028
tmp[7] = (char)(typelen & 0xFF);
11029
tmp[8] = (char)(soap->dime.size >> 24);
11030
tmp[9] = (char)((soap->dime.size >> 16) & 0xFF);
11031
tmp[10] = (char)((soap->dime.size >> 8) & 0xFF);
11032
tmp[11] = (char)(soap->dime.size & 0xFF);
11033
if (soap_send_raw(soap, (char*)tmp, 12)
11034
|| soap_putdimefield(soap, soap->dime.options, optlen)
11035
|| soap_putdimefield(soap, soap->dime.id, idlen)
11036
|| soap_putdimefield(soap, soap->dime.type, typelen))
11037
return soap->error;
11043
/******************************************************************************/
11044
#ifndef WITH_LEANER
11049
soap_putdime(struct soap *soap)
11050
{ struct soap_multipart *content;
11051
if (!(soap->mode & SOAP_ENC_DIME))
11053
for (content = soap->dime.first; content; content = content->next)
11055
soap->dime.size = content->size;
11056
soap->dime.id = content->id;
11057
soap->dime.type = content->type;
11058
soap->dime.options = content->options;
11059
soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA;
11060
if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error))
11061
{ size_t size = content->size;
11063
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n"));
11064
return soap->error;
11066
if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE))
11067
{ size_t chunksize = sizeof(soap->tmpbuf);
11068
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n"));
11070
{ size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize);
11071
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size));
11072
if (size < chunksize)
11073
{ soap->dime.flags &= ~SOAP_DIME_CF;
11074
if (!content->next)
11075
soap->dime.flags |= SOAP_DIME_ME;
11078
soap->dime.flags |= SOAP_DIME_CF;
11079
soap->dime.size = size;
11080
if (soap_putdimehdr(soap)
11081
|| soap_putdimefield(soap, soap->tmpbuf, size))
11084
{ soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA);
11085
soap->dime.id = NULL;
11086
soap->dime.type = NULL;
11087
soap->dime.options = NULL;
11089
} while (size >= chunksize);
11092
{ if (!content->next)
11093
soap->dime.flags |= SOAP_DIME_ME;
11094
if (soap_putdimehdr(soap))
11095
return soap->error;
11098
if (size < sizeof(soap->tmpbuf))
11101
bufsize = sizeof(soap->tmpbuf);
11102
if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize)))
11103
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
11104
soap->error = SOAP_EOF;
11107
if (soap_send_raw(soap, soap->tmpbuf, bufsize))
11111
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
11112
soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
11114
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n"));
11115
if (soap->fdimereadclose)
11116
soap->fdimereadclose(soap, handle);
11119
{ if (!content->next)
11120
soap->dime.flags |= SOAP_DIME_ME;
11121
if (soap_putdimehdr(soap)
11122
|| soap_putdimefield(soap, (char*)content->ptr, content->size))
11123
return soap->error;
11131
/******************************************************************************/
11132
#ifndef WITH_LEANER
11135
soap_getdimefield(struct soap *soap, size_t n)
11136
{ register soap_wchar c;
11139
register char *p = NULL;
11141
{ p = (char*)soap_malloc(soap, n + 1);
11144
for (i = n; i > 0; i--)
11145
{ if ((int)(c = soap_get1(soap)) == EOF)
11146
{ soap->error = SOAP_EOF;
11152
if ((soap->error = soap_move(soap, -(long)n&3)))
11156
soap->error = SOAP_EOM;
11163
/******************************************************************************/
11164
#ifndef WITH_LEANER
11169
soap_getdimehdr(struct soap *soap)
11170
{ register soap_wchar c;
11173
unsigned char tmp[12];
11174
size_t optlen, idlen, typelen;
11175
if (!(soap->mode & SOAP_ENC_DIME))
11176
return soap->error = SOAP_DIME_END;
11177
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
11178
if (soap->dime.buflen || soap->dime.chunksize)
11179
{ if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
11180
return soap->error = SOAP_EOF;
11181
soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
11182
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
11186
for (i = 12; i > 0; i--)
11187
{ if ((int)(c = soap_getchar(soap)) == EOF)
11188
return soap->error = SOAP_EOF;
11191
if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION)
11192
return soap->error = SOAP_DIME_MISMATCH;
11193
soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0);
11194
optlen = (tmp[2] << 8) | tmp[3];
11195
idlen = (tmp[4] << 8) | tmp[5];
11196
typelen = (tmp[6] << 8) | tmp[7];
11197
soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
11198
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
11199
if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
11200
return soap->error;
11201
if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error)
11202
return soap->error;
11203
if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
11204
return soap->error;
11205
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:""));
11206
if (soap->dime.flags & SOAP_DIME_ME)
11207
soap->mode &= ~SOAP_ENC_DIME;
11213
/******************************************************************************/
11214
#ifndef WITH_LEANER
11219
soap_getdime(struct soap *soap)
11220
{ while (soap->dime.flags & SOAP_DIME_CF)
11221
{ if (soap_getdimehdr(soap))
11222
return soap->error;
11223
if (soap_move(soap, (long)soap->dime.size))
11224
return soap->error = SOAP_EOF;
11226
if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap))))
11227
return soap->error = SOAP_EOF;
11229
{ register struct soap_multipart *content;
11230
if (soap_getdimehdr(soap))
11232
if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error))
11233
{ const char *id, *type, *options;
11235
if (!soap->dime.ptr)
11236
return soap->error;
11237
id = soap->dime.id;
11238
type = soap->dime.type;
11239
options = soap->dime.options;
11241
{ size = soap->dime.size;
11243
{ n = soap->buflen - soap->bufidx;
11246
if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n)))
11250
{ soap->bufidx += n;
11253
if (soap_recv(soap))
11254
{ soap->error = SOAP_EOF;
11258
if (soap_move(soap, -(long)soap->dime.size&3))
11259
{ soap->error = SOAP_EOF;
11262
if (!(soap->dime.flags & SOAP_DIME_CF))
11264
if (soap_getdimehdr(soap))
11268
if (soap->fdimewriteclose)
11269
soap->fdimewriteclose(soap, (void*)soap->dime.ptr);
11270
soap->dime.size = 0;
11271
soap->dime.id = id;
11272
soap->dime.type = type;
11273
soap->dime.options = options;
11275
else if (soap->dime.flags & SOAP_DIME_CF)
11276
{ const char *id, *type, *options;
11277
id = soap->dime.id;
11278
type = soap->dime.type;
11279
options = soap->dime.options;
11280
if (soap_new_block(soap))
11283
{ register soap_wchar c;
11286
s = (char*)soap_push_block(soap, soap->dime.size);
11288
return soap->error = SOAP_EOM;
11289
for (i = soap->dime.size; i > 0; i--)
11290
{ if ((int)(c = soap_get1(soap)) == EOF)
11291
return soap->error = SOAP_EOF;
11294
if (soap_move(soap, -(long)soap->dime.size&3))
11295
return soap->error = SOAP_EOF;
11296
if (!(soap->dime.flags & SOAP_DIME_CF))
11298
if (soap_getdimehdr(soap))
11299
return soap->error;
11301
soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */
11302
if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0)))
11303
return soap->error;
11304
soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */
11305
soap->dime.id = id;
11306
soap->dime.type = type;
11307
soap->dime.options = options;
11310
soap->dime.ptr = soap_getdimefield(soap, soap->dime.size);
11311
content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size);
11313
return soap->error = SOAP_EOM;
11314
content->id = soap->dime.id;
11315
content->type = soap->dime.type;
11316
content->options = soap->dime.options;
11318
return soap->error;
11319
soap_resolve_attachment(soap, content);
11321
if (soap->error != SOAP_DIME_END)
11322
return soap->error;
11323
return soap->error = SOAP_OK;
11328
/******************************************************************************/
11329
#ifndef WITH_LEANER
11334
soap_getmimehdr(struct soap *soap)
11335
{ struct soap_multipart *content;
11337
{ if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
11338
return soap->error;
11340
while (!*soap->msgbuf);
11341
if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-')
11342
{ char *s = soap->msgbuf + strlen(soap->msgbuf) - 1;
11343
/* remove white space */
11344
while (soap_blank(*s))
11347
if (soap->mime.boundary)
11348
{ if (strcmp(soap->msgbuf + 2, soap->mime.boundary))
11349
return soap->error = SOAP_MIME_ERROR;
11352
soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2);
11353
if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
11354
return soap->error;
11356
if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL))
11357
return soap->error = SOAP_EOM;
11358
content = soap->mime.last;
11360
{ register char *key = soap->msgbuf;
11361
register char *val;
11364
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key));
11365
val = strchr(soap->msgbuf, ':');
11369
while (*val && *val <= 32);
11370
if (!soap_tag_cmp(key, "Content-ID"))
11371
content->id = soap_strdup(soap, val);
11372
else if (!soap_tag_cmp(key, "Content-Location"))
11373
content->location = soap_strdup(soap, val);
11374
else if (!soap_tag_cmp(key, "Content-Disposition"))
11375
content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name"));
11376
else if (!soap_tag_cmp(key, "Content-Type"))
11377
content->type = soap_strdup(soap, val);
11378
else if (!soap_tag_cmp(key, "Content-Description"))
11379
content->description = soap_strdup(soap, val);
11380
else if (!soap_tag_cmp(key, "Content-Transfer-Encoding"))
11381
content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE);
11383
if (soap_getline(soap, key, sizeof(soap->msgbuf)))
11384
return soap->error;
11391
/******************************************************************************/
11392
#ifndef WITH_LEANER
11397
soap_getmime(struct soap *soap)
11398
{ while (soap_get_mime_attachment(soap, NULL))
11400
return soap->error;
11405
/******************************************************************************/
11406
#ifndef WITH_LEANER
11411
soap_post_check_mime_attachments(struct soap *soap)
11412
{ soap->imode |= SOAP_MIME_POSTCHECK;
11417
/******************************************************************************/
11418
#ifndef WITH_LEANER
11423
soap_check_mime_attachments(struct soap *soap)
11424
{ if (soap->mode & SOAP_MIME_POSTCHECK)
11425
return soap_get_mime_attachment(soap, NULL) != NULL;
11431
/******************************************************************************/
11432
#ifndef WITH_LEANER
11435
struct soap_multipart *
11437
soap_get_mime_attachment(struct soap *soap, void *handle)
11438
{ register soap_wchar c = 0;
11439
register size_t i, m = 0;
11440
register char *s, *t = NULL;
11441
register struct soap_multipart *content;
11442
register short flag = 0;
11443
if (!(soap->mode & SOAP_ENC_MIME))
11445
content = soap->mime.last;
11447
{ if (soap_getmimehdr(soap))
11449
content = soap->mime.last;
11451
else if (content != soap->mime.first)
11452
{ if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error))
11453
{ if (!content->ptr)
11457
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:""));
11458
if (!content->ptr && soap_new_block(soap))
11459
{ soap->error = SOAP_EOM;
11463
{ if (content->ptr)
11465
else if (!(s = (char*)soap_push_block(soap, sizeof(soap->tmpbuf))))
11466
{ soap->error = SOAP_EOM;
11469
for (i = 0; i < sizeof(soap->tmpbuf); i++)
11476
{ c = soap_get1(soap);
11478
{ soap->error = SOAP_EOF;
11482
if (flag || c == '\r')
11483
{ t = soap->msgbuf;
11484
memset(t, 0, sizeof(soap->msgbuf));
11486
if (soap->mime.boundary)
11487
strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4);
11488
do c = soap_getchar(soap);
11491
{ soap->error = SOAP_EOF;
11497
flag = (c == '\r');
11498
m = t - soap->msgbuf + 1 - flag;
11505
if (content->ptr && soap->fmimewrite)
11506
{ if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i)))
11511
*s = '\0'; /* force 0-terminated */
11513
{ if (!soap->error && soap->fmimewrite)
11514
soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
11515
if (soap->fmimewriteclose)
11516
soap->fmimewriteclose(soap, (void*)content->ptr);
11521
{ content->size = soap_size_block(soap, i+1)-1;
11522
content->ptr = soap_save_block(soap, NULL, 0);
11524
soap_resolve_attachment(soap, content);
11525
if (c == '-' && soap_getchar(soap) == '-')
11526
{ soap->mode &= ~SOAP_ENC_MIME;
11527
if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap))
11531
{ while (c != '\r' && (int)c != EOF && soap_blank(c))
11532
c = soap_getchar(soap);
11533
if (c != '\r' || soap_getchar(soap) != '\n')
11534
{ soap->error = SOAP_MIME_ERROR;
11537
if (soap_getmimehdr(soap))
11545
/******************************************************************************/
11546
#ifndef WITH_LEANER
11551
soap_match_cid(struct soap *soap, const char *s, const char *t)
11552
{ register size_t n;
11557
if (!strncmp(s, "cid:", 4))
11564
if (!strncmp(s, t, n) && !s[n])
11566
soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS);
11567
if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n])
11574
/******************************************************************************/
11575
#ifndef WITH_LEANER
11578
soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
11580
{ register struct soap_xlist **xp = &soap->xlist;
11581
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id));
11583
{ register struct soap_xlist *xq = *xp;
11584
if (!soap_match_cid(soap, xq->id, content->id))
11585
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id));
11587
*xq->ptr = (unsigned char*)content->ptr;
11588
*xq->size = (int)content->size;
11589
*xq->type = (char*)content->type;
11590
if (content->options)
11591
*xq->options = (char*)content->options;
11593
*xq->options = (char*)content->description;
11594
SOAP_FREE(soap, xq);
11604
/******************************************************************************/
11605
#ifndef WITH_LEANER
11610
soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
11612
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:""));
11613
if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
11614
return soap->error;
11615
if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
11616
return soap->error;
11617
s = soap_code_str(mime_codes, content->encoding);
11618
if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n"))
11619
return soap->error;
11620
if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n"))
11621
return soap->error;
11622
if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n"))
11623
return soap->error;
11624
if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n"))
11625
return soap->error;
11626
return soap_send_raw(soap, "\r\n", 2);
11631
/******************************************************************************/
11632
#ifndef WITH_LEANER
11637
soap_putmime(struct soap *soap)
11638
{ struct soap_multipart *content;
11639
if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary)
11641
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n"));
11642
for (content = soap->mime.first; content; content = content->next)
11644
if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error))
11645
{ size_t size = content->size;
11647
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n"));
11648
return soap->error;
11650
if (soap_putmimehdr(soap, content))
11651
return soap->error;
11653
{ if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)
11654
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n"));
11656
{ size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf));
11657
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size));
11658
if (soap_send_raw(soap, soap->tmpbuf, size))
11663
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n"));
11669
if (size < sizeof(soap->tmpbuf))
11672
bufsize = sizeof(soap->tmpbuf);
11673
if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize)))
11674
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size));
11675
soap->error = SOAP_EOF;
11678
if (soap_send_raw(soap, soap->tmpbuf, bufsize))
11683
if (soap->fmimereadclose)
11684
soap->fmimereadclose(soap, handle);
11687
{ if (soap_putmimehdr(soap, content)
11688
|| soap_send_raw(soap, content->ptr, content->size))
11689
return soap->error;
11692
return soap_send3(soap, "\r\n--", soap->mime.boundary, "--");
11697
/******************************************************************************/
11698
#ifndef WITH_LEANER
11703
soap_set_dime(struct soap *soap)
11704
{ soap->omode |= SOAP_ENC_DIME;
11705
soap->dime.first = NULL;
11706
soap->dime.last = NULL;
11711
/******************************************************************************/
11712
#ifndef WITH_LEANER
11717
soap_set_mime(struct soap *soap, const char *boundary, const char *start)
11718
{ soap->omode |= SOAP_ENC_MIME;
11719
soap->mime.first = NULL;
11720
soap->mime.last = NULL;
11721
soap->mime.boundary = soap_strdup(soap, boundary);
11722
soap->mime.start = soap_strdup(soap, start);
11727
/******************************************************************************/
11728
#ifndef WITH_LEANER
11733
soap_clr_dime(struct soap *soap)
11734
{ soap->omode &= ~SOAP_ENC_DIME;
11735
soap->dime.first = NULL;
11736
soap->dime.last = NULL;
11741
/******************************************************************************/
11742
#ifndef WITH_LEANER
11747
soap_clr_mime(struct soap *soap)
11748
{ soap->omode &= ~SOAP_ENC_MIME;
11749
soap->mime.first = NULL;
11750
soap->mime.last = NULL;
11751
soap->mime.boundary = NULL;
11752
soap->mime.start = NULL;
11757
/******************************************************************************/
11758
#ifndef WITH_LEANER
11760
static struct soap_multipart*
11761
soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size)
11762
{ struct soap_multipart *content;
11763
content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart));
11765
{ content->next = NULL;
11766
content->ptr = ptr;
11767
content->size = size;
11768
content->id = NULL;
11769
content->type = NULL;
11770
content->options = NULL;
11771
content->encoding = SOAP_MIME_NONE;
11772
content->location = NULL;
11773
content->description = NULL;
11777
(*last)->next = content;
11785
/******************************************************************************/
11786
#ifndef WITH_LEANER
11791
soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option)
11792
{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size);
11795
content->id = soap_strdup(soap, id);
11796
content->type = soap_strdup(soap, type);
11797
content->options = soap_dime_option(soap, optype, option);
11803
/******************************************************************************/
11804
#ifndef WITH_LEANER
11809
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)
11810
{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size);
11813
content->id = soap_strdup(soap, id);
11814
content->type = soap_strdup(soap, type);
11815
content->encoding = encoding;
11816
content->location = soap_strdup(soap, location);
11817
content->description = soap_strdup(soap, description);
11823
/******************************************************************************/
11824
#ifndef WITH_LEANER
11827
struct soap_multipart*
11829
soap_next_multipart(struct soap_multipart *content)
11831
return content->next;
11837
/******************************************************************************/
11838
#ifndef WITH_LEANER
11841
soap_select_mime_boundary(struct soap *soap)
11842
{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap))
11843
{ register char *s = soap->mime.boundary;
11844
register size_t n = 0;
11849
s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1);
11857
{ *s++ = soap_base64o[soap_random & 0x3F];
11862
if (!soap->mime.start)
11863
soap->mime.start = "<SOAP-ENV:Envelope>";
11868
/******************************************************************************/
11869
#ifndef WITH_LEANER
11872
soap_valid_mime_boundary(struct soap *soap)
11873
{ register struct soap_multipart *content;
11875
if (soap->fmimeread)
11877
k = strlen(soap->mime.boundary);
11878
for (content = soap->mime.first; content; content = content->next)
11879
{ if (content->ptr && content->size >= k)
11880
{ register const char *p = (const char*)content->ptr;
11882
for (i = 0; i < content->size - k; i++, p++)
11883
{ if (!strncmp(p, soap->mime.boundary, k))
11893
/******************************************************************************\
11895
* HTTP cookie handling
11897
\******************************************************************************/
11899
#ifdef WITH_COOKIES
11900
/******************************************************************************/
11904
soap_encode_cookie(const char *s, char *t, size_t len)
11906
register size_t n = len;
11907
while ((c = *s++) && --n > 0)
11908
{ if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c))
11912
*t++ = (c >> 4) + (c > 159 ? '7' : '0');
11914
*t++ = c + (c > 9 ? '7' : '0');
11924
/******************************************************************************/
11926
struct soap_cookie*
11928
soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
11929
{ struct soap_cookie *p;
11932
domain = soap->cookie_domain;
11934
path = soap->cookie_path;
11936
path = SOAP_STR_EOS;
11937
else if (*path == '/')
11940
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)"));
11941
for (p = soap->cookies; p; p = p->next)
11942
{ 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));
11943
if (!strcmp(p->name, name)
11946
&& !strcmp(p->domain, domain)
11947
&& !strncmp(p->path, path, n))
11953
/******************************************************************************/
11955
struct soap_cookie*
11957
soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path)
11958
{ struct soap_cookie **p, *q;
11961
domain = soap->cookie_domain;
11963
path = soap->cookie_path;
11965
path = SOAP_STR_EOS;
11966
else if (*path == '/')
11968
q = soap_cookie(soap, name, domain, path);
11969
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s=%s domain=%s path=%s\n", q ? "" : "new ", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)"));
11971
{ if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
11972
{ if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
11973
strcpy(q->name, name);
11982
for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--)
11983
if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0)
11990
{ SOAP_FREE(soap, q->name);
11991
SOAP_FREE(soap, q);
12000
{ SOAP_FREE(soap, q->value);
12004
{ SOAP_FREE(soap, q->domain);
12008
{ SOAP_FREE(soap, q->path);
12011
if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1)))
12012
strcpy(q->value, value);
12013
if (domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1)))
12014
strcpy(q->domain, domain);
12015
if (path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1)))
12016
strcpy(q->path, path);
12023
/******************************************************************************/
12027
soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path)
12028
{ struct soap_cookie **p, *q;
12030
domain = soap->cookie_domain;
12032
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)"));
12036
path = soap->cookie_path;
12038
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)"));
12043
for (p = &soap->cookies, q = *p; q; q = *p)
12044
{ if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path)))
12046
SOAP_FREE(soap, q->value);
12048
SOAP_FREE(soap, q->domain);
12050
SOAP_FREE(soap, q->path);
12052
SOAP_FREE(soap, q);
12059
/******************************************************************************/
12063
soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
12064
{ struct soap_cookie *p;
12065
if ((p = soap_cookie(soap, name, domain, path)))
12070
/******************************************************************************/
12074
soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path)
12075
{ struct soap_cookie *p;
12076
if ((p = soap_cookie(soap, name, domain, path)) && p->env)
12081
/******************************************************************************/
12085
soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path)
12086
{ struct soap_cookie *p;
12087
if ((p = soap_cookie(soap, name, domain, path)))
12092
/******************************************************************************/
12096
soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
12097
{ struct soap_cookie *p;
12098
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)"));
12099
if ((p = soap_cookie(soap, name, domain, path)))
12100
{ p->maxage = expire;
12107
/******************************************************************************/
12111
soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
12112
{ struct soap_cookie *p;
12113
if ((p = soap_cookie(soap, name, domain, path)))
12121
/******************************************************************************/
12125
soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path)
12126
{ struct soap_cookie *p;
12127
if ((p = soap_cookie(soap, name, domain, path)))
12135
/******************************************************************************/
12139
soap_putsetcookies(struct soap *soap)
12140
{ struct soap_cookie *p;
12141
char *s, tmp[4096];
12143
for (p = soap->cookies; p; p = p->next)
12146
#ifdef WITH_OPENSSL
12147
|| (!p->env && !soap->ssl == !p->secure)
12152
s += soap_encode_cookie(p->name, s, tmp-s+4064);
12153
if (p->value && *p->value)
12155
s += soap_encode_cookie(p->value, s, tmp-s+4064);
12157
if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
12158
{ strcpy(s, ";Domain=");
12159
strcat(s, p->domain);
12161
else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064)
12162
{ strcpy(s, ";Domain=");
12163
strcat(s, soap->cookie_domain);
12165
strcat(s, ";Path=/");
12170
t = soap->cookie_path;
12174
if ((int)strlen(t) < tmp-s+4064)
12175
{ if (strchr(t, '%')) /* already URL encoded? */
12180
s += soap_encode_cookie(t, s, tmp-s+4064);
12183
if (p->version > 0 && s-tmp < 4060)
12184
{ sprintf(s, ";Version=%u", p->version);
12187
if (p->maxage >= 0 && s-tmp < 4060)
12188
{ sprintf(s, ";Max-Age=%ld", p->maxage);
12193
#ifdef WITH_OPENSSL
12197
strcpy(s, ";Secure");
12198
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp));
12199
if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp)))
12200
return soap->error;
12206
/******************************************************************************/
12210
soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure)
12211
{ struct soap_cookie **p, *q;
12212
unsigned int version = 0;
12213
time_t now = time(NULL);
12214
char *s, tmp[4096];
12215
p = &soap->cookies;
12216
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path));
12220
{ if (q->expire && now > q->expire)
12221
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name));
12222
SOAP_FREE(soap, q->name);
12224
SOAP_FREE(soap, q->value);
12226
SOAP_FREE(soap, q->domain);
12228
SOAP_FREE(soap, q->path);
12230
SOAP_FREE(soap, q);
12234
char *t = q->domain;
12239
{ const char *r = strchr(t, ':');
12244
flag = !strncmp(t, domain, n);
12246
/* domain-level cookies */
12248
{ struct hostent *hostent = gethostbyname((char*)domain);
12250
{ char *r = strchr(hostent->h_name, '.');
12252
r = hostent->h_name;
12253
flag = !strncmp(t, r, n);
12257
&& (!q->path || !strncmp(q->path, path, strlen(q->path)))
12258
&& (!q->secure || secure))
12260
if (q->version != version)
12261
{ sprintf(s, "$Version=%u;", q->version);
12262
version = q->version;
12265
s += soap_encode_cookie(q->name, s, tmp-s+4080);
12266
if (q->value && *q->value)
12268
s += soap_encode_cookie(q->value, s, tmp-s+4080);
12270
if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080)
12271
{ sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
12274
if (q->domain && (int)strlen(q->domain) < tmp-s+4080)
12275
sprintf(s, ";$Domain=\"%s\"", q->domain);
12276
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
12277
if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
12278
return soap->error;
12286
/******************************************************************************/
12290
soap_getcookies(struct soap *soap, const char *val)
12291
{ struct soap_cookie *p = NULL, *q;
12293
char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
12294
char *domain = NULL;
12296
unsigned int version = 0;
12297
time_t now = time(NULL);
12302
{ s = soap_decode_key(tmp, sizeof(tmp), s);
12303
if (!soap_tag_cmp(tmp, "$Version"))
12304
{ if ((s = soap_decode_val(tmp, sizeof(tmp), s)))
12306
p->version = (int)atol(tmp);
12308
version = (int)atol(tmp);
12311
else if (!soap_tag_cmp(tmp, "$Path"))
12312
{ s = soap_decode_val(tmp, sizeof(tmp), s);
12314
{ if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
12321
SOAP_FREE(soap, p->path);
12326
SOAP_FREE(soap, path);
12330
else if (!soap_tag_cmp(tmp, "$Domain"))
12331
{ s = soap_decode_val(tmp, sizeof(tmp), s);
12333
{ if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
12340
SOAP_FREE(soap, p->domain);
12345
SOAP_FREE(soap, domain);
12349
else if (p && !soap_tag_cmp(tmp, "Path"))
12351
SOAP_FREE(soap, p->path);
12352
s = soap_decode_val(tmp, sizeof(tmp), s);
12354
{ if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
12355
strcpy(p->path, tmp);
12360
else if (p && !soap_tag_cmp(tmp, "Domain"))
12362
SOAP_FREE(soap, p->domain);
12363
s = soap_decode_val(tmp, sizeof(tmp), s);
12365
{ if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1)))
12366
strcpy(p->domain, tmp);
12371
else if (p && !soap_tag_cmp(tmp, "Version"))
12372
{ s = soap_decode_val(tmp, sizeof(tmp), s);
12373
p->version = (unsigned int)atol(tmp);
12375
else if (p && !soap_tag_cmp(tmp, "Max-Age"))
12376
{ s = soap_decode_val(tmp, sizeof(tmp), s);
12377
p->expire = now + atol(tmp);
12379
else if (p && !soap_tag_cmp(tmp, "Expires"))
12382
static const char mns[] = "anebarprayunulugepctovec";
12383
s = soap_decode_val(tmp, sizeof(tmp), s);
12384
if (strlen(tmp) > 20)
12385
{ memset((void*)&T, 0, sizeof(T));
12389
T.tm_mday = (int)atol(a);
12392
T.tm_mon = (int)(strstr(mns, a) - mns) / 2;
12395
T.tm_year = 100 + (int)atol(a);
12398
T.tm_hour = (int)atol(a);
12401
T.tm_min = (int)atol(a);
12404
T.tm_sec = (int)atol(a);
12405
p->expire = soap_timegm(&T);
12408
else if (p && !soap_tag_cmp(tmp, "Secure"))
12412
{ 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));
12413
if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
12414
{ q->version = p->version;
12415
q->expire = p->expire;
12416
q->secure = p->secure;
12420
SOAP_FREE(soap, p->name);
12422
SOAP_FREE(soap, p->value);
12424
SOAP_FREE(soap, p->domain);
12426
SOAP_FREE(soap, p->path);
12427
SOAP_FREE(soap, p);
12429
if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
12430
{ p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
12431
strcpy(p->name, tmp);
12432
s = soap_decode_val(tmp, sizeof(tmp), s);
12434
{ p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1);
12435
strcpy(p->value, tmp);
12440
p->domain = domain;
12441
else if (*soap->host)
12442
{ p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1);
12443
strcpy(p->domain, soap->host);
12449
else if (soap->path && *soap->path)
12450
{ p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1);
12451
strcpy(p->path, soap->path);
12454
{ p->path = (char*)SOAP_MALLOC(soap, 2);
12455
strcpy(p->path, "/");
12459
p->version = version;
12464
{ 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));
12465
if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
12466
{ q->version = p->version;
12467
q->expire = p->expire;
12468
q->secure = p->secure;
12472
SOAP_FREE(soap, p->name);
12474
SOAP_FREE(soap, p->value);
12476
SOAP_FREE(soap, p->domain);
12478
SOAP_FREE(soap, p->path);
12479
SOAP_FREE(soap, p);
12482
SOAP_FREE(soap, domain);
12484
SOAP_FREE(soap, path);
12487
/******************************************************************************/
12491
soap_getenv_cookies(struct soap *soap)
12492
{ struct soap_cookie *p;
12494
char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */
12495
if (!(s = getenv("HTTP_COOKIE")))
12498
{ s = soap_decode_key(key, sizeof(key), s);
12499
s = soap_decode_val(val, sizeof(val), s);
12500
p = soap_set_cookie(soap, key, val, NULL, NULL);
12507
/******************************************************************************/
12509
struct soap_cookie*
12511
soap_copy_cookies(struct soap *copy, struct soap *soap)
12512
{ struct soap_cookie *p, **q, *r;
12514
for (p = soap->cookies; p; p = p->next)
12515
{ if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie))))
12519
{ if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1)))
12520
strcpy((*q)->name, p->name);
12523
{ if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1)))
12524
strcpy((*q)->value, p->value);
12527
{ if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1)))
12528
strcpy((*q)->domain, p->domain);
12531
{ if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1)))
12532
strcpy((*q)->path, p->path);
12540
/******************************************************************************/
12544
soap_free_cookies(struct soap *soap)
12545
{ struct soap_cookie *p;
12546
for (p = soap->cookies; p; p = soap->cookies)
12547
{ soap->cookies = p->next;
12548
SOAP_FREE(soap, p->name);
12550
SOAP_FREE(soap, p->value);
12552
SOAP_FREE(soap, p->domain);
12554
SOAP_FREE(soap, p->path);
12555
SOAP_FREE(soap, p);
12559
/******************************************************************************/
12560
#endif /* WITH_COOKIES */
12562
/******************************************************************************/
12566
soap_getgziphdr(struct soap *soap)
12568
soap_wchar c = 0, f = 0;
12569
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n"));
12570
for (i = 0; i < 9; i++)
12571
{ if ((int)(c = soap_get1(soap) == EOF))
12572
return soap->error = SOAP_EOF;
12576
if (f & 0x04) /* FEXTRA */
12577
{ for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--)
12578
{ if ((int)soap_get1(soap) == EOF)
12579
return soap->error = SOAP_EOF;
12582
if (f & 0x08) /* FNAME */
12584
c = soap_get1(soap);
12585
while (c && (int)c != EOF);
12587
if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */
12589
c = soap_get1(soap);
12590
while (c && (int)c != EOF);
12592
if ((int)c != EOF && (f & 0x01)) /* FHCRC */
12593
{ if ((int)(c = soap_get1(soap)) != EOF)
12594
c = soap_get1(soap);
12597
return soap->error = SOAP_EOF;
12603
/******************************************************************************/
12608
soap_begin_recv(struct soap *soap)
12610
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n"));
12611
soap->error = SOAP_OK;
12612
soap_free_temp(soap);
12613
soap_set_local_namespaces(soap);
12614
soap->version = 0; /* don't assume we're parsing SOAP content by default */
12615
#ifndef WITH_NOIDREF
12616
soap_free_iht(soap);
12618
if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
12619
soap->omode |= SOAP_IO_CHUNK;
12620
soap->imode &= ~SOAP_IO;
12621
soap->mode = soap->imode;
12622
if (!soap->keep_alive)
12623
{ soap->buflen = 0;
12626
if (!(soap->mode & SOAP_IO_KEEPALIVE))
12627
soap->keep_alive = 0;
12631
soap->part = SOAP_BEGIN;
12636
*soap->endpoint = '\0';
12637
soap->action = NULL;
12639
#ifndef WITH_LEANER
12641
soap->dime.chunksize = 0;
12642
soap->dime.buflen = 0;
12643
soap->dime.list = NULL;
12644
soap->dime.first = NULL;
12645
soap->dime.last = NULL;
12646
soap->mime.list = NULL;
12647
soap->mime.first = NULL;
12648
soap->mime.last = NULL;
12649
soap->mime.boundary = NULL;
12650
soap->mime.start = NULL;
12651
soap->xlist = NULL;
12655
#ifndef WITH_FASTCGI
12656
if (!soap_valid_socket(soap->socket))
12657
#ifdef __BORLANDC__
12658
setmode(soap->recvfd, O_BINARY);
12660
_setmode(soap->recvfd, _O_BINARY);
12666
soap->mode &= ~SOAP_ENC_ZLIB;
12667
soap->zlib_in = SOAP_ZLIB_NONE;
12668
soap->zlib_out = SOAP_ZLIB_NONE;
12669
soap->d_stream.next_in = Z_NULL;
12670
soap->d_stream.avail_in = 0;
12671
soap->d_stream.next_out = (Byte*)soap->buf;
12672
soap->d_stream.avail_out = SOAP_BUFLEN;
12673
soap->z_ratio_in = 1.0;
12675
#ifndef WITH_LEANER
12676
if (soap->fprepareinit)
12677
soap->fprepareinit(soap);
12679
c = soap_getchar(soap);
12682
{ if (soap_getgziphdr(soap))
12683
return soap->error;
12684
if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
12685
return soap->error = SOAP_ZLIB_ERROR;
12686
soap->zlib_state = SOAP_ZLIB_INFLATE;
12687
soap->mode |= SOAP_ENC_ZLIB;
12688
soap->zlib_in = SOAP_ZLIB_GZIP;
12689
soap->z_crc = crc32(0L, NULL, 0);
12690
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
12691
memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
12692
/* should not chunk over plain transport, so why bother to check? */
12693
/* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */
12694
/* soap->z_buflen = soap->bufidx; */
12696
soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
12697
soap->d_stream.avail_in = soap->buflen - soap->bufidx;
12698
soap->z_buflen = soap->buflen;
12699
soap->buflen = soap->bufidx;
12700
c = soap_getchar(soap);
12703
#ifndef WITH_LEANER
12704
if (c == '-' && soap_get0(soap) == '-')
12705
soap->mode |= SOAP_ENC_MIME;
12706
else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20)
12707
soap->mode |= SOAP_ENC_DIME;
12710
{ while (soap_blank(c))
12711
c = soap_getchar(soap);
12714
return soap->error = SOAP_EOF;
12715
soap_unget(soap, c);
12716
#ifndef WITH_NOHTTP
12717
/* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */
12718
if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
12719
{ soap->mode &= ~SOAP_IO;
12720
soap->error = soap->fparse(soap);
12721
if (soap->error && soap->error < SOAP_STOP)
12722
{ soap->keep_alive = 0; /* force close later */
12723
return soap->error;
12725
if (soap->error == SOAP_STOP)
12726
return soap->error;
12727
if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
12728
{ soap->chunkbuflen = soap->buflen;
12729
soap->buflen = soap->bufidx;
12730
soap->chunksize = 0;
12732
#ifndef WITH_LEANER
12733
else if (soap->fpreparerecv && soap->buflen != soap->bufidx)
12734
soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx);
12736
/* Note: fparse should not use soap_unget to push back last char */
12737
if (soap_get0(soap) == (int)EOF)
12738
{ if (soap->status == 200)
12739
return soap->error = SOAP_NO_DATA;
12740
return soap->error = soap->status;
12743
if (soap->zlib_in != SOAP_ZLIB_NONE)
12746
if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
12747
{ c = soap_get1(soap);
12749
{ if (soap_getgziphdr(soap))
12750
return soap->error;
12751
if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK)
12752
return soap->error = SOAP_ZLIB_ERROR;
12753
soap->z_crc = crc32(0L, NULL, 0);
12754
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n"));
12757
{ soap_revget1(soap);
12758
if (inflateInit(&soap->d_stream) != Z_OK)
12759
return soap->error = SOAP_ZLIB_ERROR;
12760
soap->zlib_in = SOAP_ZLIB_DEFLATE;
12765
if (inflateInit(&soap->d_stream) != Z_OK)
12766
return soap->error = SOAP_ZLIB_ERROR;
12767
soap->zlib_state = SOAP_ZLIB_INFLATE;
12768
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n"));
12769
soap->mode |= SOAP_ENC_ZLIB;
12770
memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN);
12771
soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx);
12772
soap->d_stream.avail_in = soap->buflen - soap->bufidx;
12773
soap->z_buflen = soap->buflen;
12774
soap->buflen = soap->bufidx;
12778
{ if (soap->error == SOAP_FORM && soap->fform)
12779
{ soap->error = soap->fform(soap);
12780
if (soap->error == SOAP_OK)
12781
soap->error = SOAP_STOP; /* prevents further processing */
12783
return soap->error;
12787
#ifndef WITH_LEANER
12788
if (soap->mode & SOAP_ENC_MIME)
12789
{ if (soap_getmimehdr(soap))
12790
return soap->error;
12791
if (soap->mime.start)
12793
{ if (!soap->mime.last->id)
12795
if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id))
12797
} while (soap_get_mime_attachment(soap, NULL));
12799
if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime"))
12800
soap->mode |= SOAP_ENC_DIME;
12802
if (soap->mode & SOAP_ENC_DIME)
12803
{ if (soap_getdimehdr(soap))
12804
return soap->error;
12805
if (soap->dime.flags & SOAP_DIME_CF)
12806
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n"));
12807
soap->dime.chunksize = soap->dime.size;
12808
if (soap->buflen - soap->bufidx >= soap->dime.chunksize)
12809
{ soap->dime.buflen = soap->buflen;
12810
soap->buflen = soap->bufidx + soap->dime.chunksize;
12813
soap->dime.chunksize -= soap->buflen - soap->bufidx;
12815
soap->count = soap->buflen - soap->bufidx;
12822
/******************************************************************************/
12823
#ifndef WITH_NOHTTP
12826
http_parse(struct soap *soap)
12827
{ char header[SOAP_HDRLEN], *s;
12828
unsigned short get = 0, status = 0, k = 0;
12829
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
12830
*soap->endpoint = '\0';
12832
soap->userid = NULL;
12833
soap->passwd = NULL;
12834
soap->action = NULL;
12835
soap->authrealm = NULL;
12836
soap->proxy_from = NULL;
12837
soap->http_content = NULL;
12840
{ if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
12841
{ if (soap->error == SOAP_EOF)
12843
return soap->error = 414;
12845
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf));
12847
{ if (soap_getline(soap, header, SOAP_HDRLEN))
12848
{ if (soap->error == SOAP_EOF)
12849
{ soap->error = SOAP_OK;
12850
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n"));
12853
return soap->error;
12857
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header));
12858
s = strchr(header, ':');
12863
while (*s && *s <= 32);
12866
t = s + strlen(s) - 1;
12867
while (t > s && *t <= 32)
12869
if (t >= s && *t == '"')
12872
if ((soap->error = soap->fparsehdr(soap, header, s)))
12873
{ if (soap->error < SOAP_STOP)
12874
return soap->error;
12875
status = soap->error;
12876
soap->error = SOAP_OK;
12880
if ((s = strchr(soap->msgbuf, ' ')))
12881
{ k = (unsigned short)soap_strtoul(s, &s, 10);
12882
if (!soap_blank(*s))
12887
} while (k == 100);
12888
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", k));
12889
s = strstr(soap->msgbuf, "HTTP/");
12890
if (s && s[7] != '1')
12891
{ if (soap->keep_alive == 1)
12892
soap->keep_alive = 0;
12893
if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */
12894
{ soap->imode |= SOAP_IO_CHUNK;
12895
soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
12898
if (soap->keep_alive < 0)
12899
soap->keep_alive = 1;
12900
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive));
12902
{ if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5)))
12903
{ size_t m = strlen(soap->endpoint);
12904
size_t n = m + (s - soap->msgbuf) - 5 - (!get);
12907
if (n >= sizeof(soap->endpoint))
12908
n = sizeof(soap->endpoint) - 1;
12909
strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m);
12910
soap->path[n - m] = '\0';
12911
strcat(soap->endpoint, soap->path);
12912
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint));
12914
{ soap->error = soap->fget(soap);
12915
if (soap->error == SOAP_OK)
12916
soap->error = SOAP_STOP; /* prevents further processing */
12917
return soap->error;
12920
return soap->error = status;
12923
return soap->error = status;
12925
return soap->error = 405;
12928
/* Status OK (HTTP 200) */
12929
if (k == 0 || k == 200)
12931
/* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors.
12932
Only keep parsing HTTP body when content-length>0 or chunked is set.
12934
if (((k > 200 && k <= 299) || k == 400 || k == 500) && (soap->length > 0 || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK))
12936
/* HTTP 400 and 500 headers are supposed to set content-length or chunked.
12937
For those that don't we keep parsing the body only if content type is
12938
given and connection closes.
12940
if ((k == 400 || k == 500) && (soap->http_content || soap->keep_alive == 0))
12942
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k));
12943
return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, k);
12948
/******************************************************************************/
12949
#ifndef WITH_NOHTTP
12952
http_parse_header(struct soap *soap, const char *key, const char *val)
12953
{ if (!soap_tag_cmp(key, "Host"))
12955
#ifdef WITH_OPENSSL
12956
if (soap->imode & SOAP_ENC_SSL)
12957
strcpy(soap->endpoint, "https://");
12960
strcpy(soap->endpoint, "http://");
12961
strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
12962
soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
12964
#ifndef WITH_LEANER
12965
else if (!soap_tag_cmp(key, "Content-Type"))
12966
{ soap->http_content = soap_strdup(soap, val);
12967
if (soap_get_header_attribute(soap, val, "application/dime"))
12968
soap->mode |= SOAP_ENC_DIME;
12969
else if (soap_get_header_attribute(soap, val, "multipart/related")
12970
|| soap_get_header_attribute(soap, val, "multipart/form-data"))
12971
{ soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary"));
12972
soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start"));
12973
soap->mode |= SOAP_ENC_MIME;
12977
else if (!soap_tag_cmp(key, "Content-Length"))
12978
{ soap->length = soap_strtoul(val, NULL, 10);
12980
else if (!soap_tag_cmp(key, "Content-Encoding"))
12981
{ if (!soap_tag_cmp(val, "deflate"))
12983
soap->zlib_in = SOAP_ZLIB_DEFLATE;
12985
return SOAP_ZLIB_ERROR;
12987
else if (!soap_tag_cmp(val, "gzip"))
12989
soap->zlib_in = SOAP_ZLIB_GZIP;
12991
return SOAP_ZLIB_ERROR;
12995
else if (!soap_tag_cmp(key, "Accept-Encoding"))
12998
if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip"))
12999
soap->zlib_out = SOAP_ZLIB_GZIP;
13002
if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate"))
13003
soap->zlib_out = SOAP_ZLIB_DEFLATE;
13005
soap->zlib_out = SOAP_ZLIB_NONE;
13008
else if (!soap_tag_cmp(key, "Transfer-Encoding"))
13009
{ soap->mode &= ~SOAP_IO;
13010
if (!soap_tag_cmp(val, "chunked"))
13011
soap->mode |= SOAP_IO_CHUNK;
13013
else if (!soap_tag_cmp(key, "Connection"))
13014
{ if (!soap_tag_cmp(val, "keep-alive"))
13015
soap->keep_alive = -soap->keep_alive;
13016
else if (!soap_tag_cmp(val, "close"))
13017
soap->keep_alive = 0;
13020
else if (!soap_tag_cmp(key, "Authorization"))
13021
{ if (!soap_tag_cmp(val, "Basic *"))
13024
soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
13025
soap->tmpbuf[n] = '\0';
13026
if ((s = strchr(soap->tmpbuf, ':')))
13028
soap->userid = soap_strdup(soap, soap->tmpbuf);
13029
soap->passwd = soap_strdup(soap, s + 1);
13033
else if (!soap_tag_cmp(key, "WWW-Authenticate"))
13034
{ soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm"));
13036
else if (!soap_tag_cmp(key, "Expect"))
13037
{ if (!soap_tag_cmp(val, "100-continue"))
13038
{ if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL))
13039
|| (soap->error = soap->fposthdr(soap, NULL, NULL)))
13040
return soap->error;
13044
else if (!soap_tag_cmp(key, "SOAPAction"))
13046
{ soap->action = soap_strdup(soap, val + 1);
13047
soap->action[strlen(soap->action) - 1] = '\0';
13050
soap->action = soap_strdup(soap, val);
13052
else if (!soap_tag_cmp(key, "Location"))
13053
{ strncpy(soap->endpoint, val, sizeof(soap->endpoint));
13054
soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
13056
else if (!soap_tag_cmp(key, "X-Forwarded-For"))
13057
{ soap->proxy_from = soap_strdup(soap, val);
13059
#ifdef WITH_COOKIES
13060
else if (!soap_tag_cmp(key, "Cookie")
13061
|| !soap_tag_cmp(key, "Cookie2")
13062
|| !soap_tag_cmp(key, "Set-Cookie")
13063
|| !soap_tag_cmp(key, "Set-Cookie2"))
13064
{ soap_getcookies(soap, val);
13072
/******************************************************************************/
13073
#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
13078
soap_get_header_attribute(struct soap *soap, const char *line, const char *key)
13079
{ register const char *s = line;
13082
{ register short flag;
13083
s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s);
13084
flag = soap_tag_cmp(soap->tmpbuf, key);
13085
s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s);
13087
return soap->tmpbuf;
13095
/******************************************************************************/
13096
#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
13101
soap_decode_key(char *buf, size_t len, const char *val)
13102
{ return soap_decode(buf, len, val, "=,;");
13107
/******************************************************************************/
13108
#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
13113
soap_decode_val(char *buf, size_t len, const char *val)
13118
return soap_decode(buf, len, val + 1, ",;");
13123
/******************************************************************************/
13124
#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER)
13127
soap_decode(char *buf, size_t len, const char *val, const char *sep)
13130
for (s = val; *s; s++)
13131
if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
13135
while (*s && *s != '"' && --len)
13139
{ while (soap_notblank(*s) && !strchr(sep, *s) && --len)
13141
{ *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
13142
+ (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
13150
while (*s && !strchr(sep, *s))
13157
/******************************************************************************/
13162
soap_envelope_begin_out(struct soap *soap)
13164
#ifndef WITH_LEANER
13166
if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 )
13168
if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
13169
s = "application/dime";
13170
else if (soap->version == 2)
13171
{ if (soap->mode & SOAP_ENC_MTOM)
13172
s = "application/xop+xml; charset=utf-8; type=application/soap+xml";
13174
s = "application/soap+xml; charset=utf-8";
13177
s = "text/xml; charset=utf-8";
13178
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);
13179
n = strlen(soap->tmpbuf);
13180
if (soap_send_raw(soap, soap->tmpbuf, n))
13181
return soap->error;
13183
if (soap->mode & SOAP_IO_LENGTH)
13184
soap->dime.size = soap->count; /* DIME in MIME correction */
13185
if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME))
13186
{ if (soap_putdimehdr(soap))
13187
return soap->error;
13190
soap->part = SOAP_IN_ENVELOPE;
13191
return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
13195
/******************************************************************************/
13200
soap_envelope_end_out(struct soap *soap)
13201
{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope"))
13202
return soap->error;
13203
#ifndef WITH_LEANER
13204
if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
13205
{ soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */
13206
sprintf(soap->id, soap->dime_id_format, 0);
13207
soap->dime.id = soap->id;
13208
if (soap->local_namespaces)
13209
{ if (soap->local_namespaces[0].out)
13210
soap->dime.type = (char*)soap->local_namespaces[0].out;
13212
soap->dime.type = (char*)soap->local_namespaces[0].ns;
13214
soap->dime.options = NULL;
13215
soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI;
13216
if (!soap->dime.first)
13217
soap->dime.flags |= SOAP_DIME_ME;
13218
soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0);
13220
if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
13221
return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3);
13223
soap->part = SOAP_END_ENVELOPE;
13228
/******************************************************************************/
13233
soap_envelope_begin_in(struct soap *soap)
13234
{ register struct Namespace *p;
13235
soap->part = SOAP_IN_ENVELOPE;
13236
if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
13239
if (soap->error == SOAP_TAG_MISMATCH && !soap_element_begin_in(soap, "html", 0, NULL))
13240
{ /* get HTML from buffer, stop receiving to avoid HTML parsing issues */
13243
size_t (*f)(struct soap*, char*, size_t) = soap->frecv;
13244
soap->frecv = frecv_stop;
13247
s = soap_string_in(soap, 1, -1, -1);
13251
return soap_set_receiver_error(soap, "HTTP Error", s, SOAP_HTTP_ERROR);
13254
if (soap->error == SOAP_TAG_MISMATCH)
13255
return soap->error = SOAP_VERSIONMISMATCH;
13256
return soap->error;
13258
p = soap->local_namespaces;
13260
{ const char *ns = p[0].out;
13263
if (!strcmp(ns, soap_env1))
13264
{ soap->version = 1; /* make sure we use SOAP 1.1 */
13266
SOAP_FREE(soap, p[1].out);
13267
if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1))))
13268
strcpy(p[1].out, soap_enc1);
13270
else if (!strcmp(ns, soap_env2))
13271
{ soap->version = 2; /* make sure we use SOAP 1.2 */
13273
SOAP_FREE(soap, p[1].out);
13274
if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2))))
13275
strcpy(p[1].out, soap_enc2);
13282
/******************************************************************************/
13287
soap_envelope_end_in(struct soap *soap)
13288
{ soap->part = SOAP_END_ENVELOPE;
13289
return soap_element_end_in(soap, "SOAP-ENV:Envelope");
13293
/******************************************************************************/
13298
soap_body_begin_out(struct soap *soap)
13299
{ soap->part = SOAP_IN_BODY;
13300
if (soap->version == 1)
13301
soap->encoding = 1;
13303
if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body"))
13304
return soap->error;
13306
if (soap_element(soap, "SOAP-ENV:Body", 0, NULL))
13307
return soap->error;
13308
return soap_element_start_end_out(soap, NULL);
13312
/******************************************************************************/
13317
soap_body_end_out(struct soap *soap)
13318
{ if (soap_element_end_out(soap, "SOAP-ENV:Body"))
13319
return soap->error;
13320
soap->part = SOAP_END_BODY;
13325
/******************************************************************************/
13330
soap_body_begin_in(struct soap *soap)
13331
{ soap->part = SOAP_IN_BODY;
13332
if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
13333
return soap->error;
13335
soap->part = SOAP_NO_BODY;
13340
/******************************************************************************/
13345
soap_body_end_in(struct soap *soap)
13346
{ if (soap->part == SOAP_NO_BODY)
13348
soap->part = SOAP_END_BODY;
13349
return soap_element_end_in(soap, "SOAP-ENV:Body");
13353
/******************************************************************************/
13358
soap_recv_header(struct soap *soap)
13359
{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH)
13360
soap->error = SOAP_OK;
13361
else if (soap->error == SOAP_OK && soap->fheader)
13362
soap->error = soap->fheader(soap);
13363
return soap->error;
13367
/******************************************************************************/
13372
soap_set_endpoint(struct soap *soap, const char *endpoint)
13373
{ register const char *s;
13374
register size_t i, n;
13375
soap->endpoint[0] = '\0';
13376
soap->host[0] = '\0';
13377
soap->path[0] = '/';
13378
soap->path[1] = '\0';
13380
if (!endpoint || !*endpoint)
13382
#ifdef WITH_OPENSSL
13383
if (!soap_tag_cmp(endpoint, "https:*"))
13386
strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
13387
soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
13388
s = strchr(endpoint, ':');
13389
if (s && s[1] == '/' && s[2] == '/')
13394
if (n >= sizeof(soap->host))
13395
n = sizeof(soap->host) - 1;
13399
for (i = 0; i < n; i++)
13405
soap->host[i] = s[i];
13409
{ for (i = 0; i < n; i++)
13410
{ soap->host[i] = s[i];
13411
if (s[i] == '/' || s[i] == ':')
13416
for (i = 0; i < n; i++)
13417
{ soap->host[i] = s[i];
13418
if (s[i] == '/' || s[i] == ':')
13422
soap->host[i] = '\0';
13424
{ soap->port = (int)atol(s + i + 1);
13425
for (i++; i < n; i++)
13430
{ strncpy(soap->path, s + i, sizeof(soap->path));
13431
soap->path[sizeof(soap->path) - 1] = '\0';
13436
/******************************************************************************/
13441
soap_connect(struct soap *soap, const char *endpoint, const char *action)
13442
{ return soap_connect_command(soap, SOAP_POST, endpoint, action);
13446
/******************************************************************************/
13451
soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action)
13452
{ char host[sizeof(soap->host)];
13455
soap->error = SOAP_OK;
13456
strcpy(host, soap->host); /* save to compare */
13457
port = soap->port; /* save to compare */
13458
soap_set_endpoint(soap, endpoint);
13459
#ifndef WITH_LEANER
13460
if (soap->fconnect)
13461
{ if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port)))
13462
return soap->error;
13466
if (soap->fopen && *soap->host)
13467
{ soap->status = http_command;
13468
if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap))
13469
{ soap->keep_alive = 0; /* to force close */
13470
soap->omode &= ~SOAP_IO_UDP; /* to force close */
13471
soap_closesock(soap);
13472
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port));
13474
if (!strncmp(endpoint, "soap.udp:", 9))
13475
soap->omode |= SOAP_IO_UDP;
13477
soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port);
13479
return soap->error;
13480
soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0);
13483
count = soap_count_attachments(soap);
13484
if (soap_begin_send(soap))
13485
return soap->error;
13486
if (http_command != SOAP_POST)
13487
{ soap->mode &= ~SOAP_IO;
13488
soap->mode |= SOAP_IO_BUFFER;
13490
#ifndef WITH_NOHTTP
13491
soap->action = soap_strdup(soap, action);
13492
if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint)
13493
{ unsigned int k = soap->mode;
13494
soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
13495
if ((k & SOAP_IO) != SOAP_IO_FLUSH)
13496
soap->mode |= SOAP_IO_BUFFER;
13497
if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count)))
13498
return soap->error;
13499
#ifndef WITH_LEANER
13500
if ((k & SOAP_IO) == SOAP_IO_CHUNK)
13501
{ if (soap_flush(soap))
13502
return soap->error;
13507
if (http_command != SOAP_POST)
13508
return soap_end_send(soap);
13514
/******************************************************************************/
13519
soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
13521
register unsigned long m;
13524
t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1);
13526
{ soap->error = SOAP_EOM;
13533
for (; n > 2; n -= 3, s += 3)
13535
m = (m << 8) | s[1];
13536
m = (m << 8) | s[2];
13537
for (i = 4; i > 0; m >>= 6)
13538
t[--i] = soap_base64o[m & 0x3F];
13544
for (i = 0; i < n; i++)
13545
m = (m << 8) | *s++;
13548
for (i++; i > 0; m >>= 6)
13549
t[--i] = soap_base64o[m & 0x3F];
13550
for (i = 3; i > n; i--)
13558
/******************************************************************************/
13563
soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
13564
{ register int i, j, c;
13565
register unsigned long m;
13566
register const char *p;
13572
return SOAP_NON_NULL;
13575
{ l = (strlen(s) + 3) / 4 * 3;
13576
t = (char*)soap_malloc(soap, l);
13579
{ soap->error = SOAP_EOM;
13586
{ for (i = 0; i < SOAP_BLKLEN; i++)
13591
if (c == '=' || !c)
13595
*t++ = (char)((m >> 4) & 0xFF);
13599
*t++ = (char)((m >> 10) & 0xFF);
13600
*t++ = (char)((m >> 2) & 0xFF);
13608
if (c >= 0 && c <= 79)
13609
{ int b = soap_base64i[c];
13611
{ soap->error = SOAP_TYPE;
13617
else if (!soap_blank(c + '+'))
13618
{ soap->error = SOAP_TYPE;
13622
*t++ = (char)((m >> 16) & 0xFF);
13623
*t++ = (char)((m >> 8) & 0xFF);
13624
*t++ = (char)(m & 0xFF);
13633
*n += 3 * SOAP_BLKLEN;
13638
/******************************************************************************/
13643
soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n)
13644
{ register char *p;
13646
t = (char*)soap_malloc(soap, 2 * n + 1);
13648
{ soap->error = SOAP_EOM;
13654
{ for (; n > 0; n--)
13655
{ register int m = *s++;
13656
*t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0'));
13658
*t++ = (char)(m + (m > 9 ? 'a' - 10 : '0'));
13666
/******************************************************************************/
13671
soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n)
13672
{ register const char *p;
13678
return SOAP_NON_NULL;
13681
{ l = strlen(s) / 2;
13682
t = (char*)soap_malloc(soap, l);
13685
{ soap->error = SOAP_EOM;
13690
{ register int d1, d2;
13697
*t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0');
13706
/******************************************************************************/
13707
#ifndef WITH_NOHTTP
13712
soap_puthttphdr(struct soap *soap, int status, size_t count)
13713
{ if (soap->status != SOAP_GET)
13714
{ register const char *s = "text/xml; charset=utf-8";
13715
register int err = SOAP_OK;
13716
#ifndef WITH_LEANER
13717
register const char *r = NULL;
13719
if (status == SOAP_FILE && soap->http_content)
13720
s = soap->http_content;
13721
else if (status == SOAP_HTML)
13722
s = "text/html; charset=utf-8";
13723
else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
13724
{ if (soap->version == 2)
13725
s = "application/soap+xml; charset=utf-8";
13727
#ifndef WITH_LEANER
13728
if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM))
13729
{ if (soap->mode & SOAP_ENC_MTOM)
13731
s = "application/xop+xml; charset=utf-8";
13734
s = "application/dime";
13736
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)
13737
{ register const char *t = strchr(s, ';');
13738
sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary);
13740
strncat(soap->tmpbuf, s, t - s);
13742
strcat(soap->tmpbuf, s);
13743
if (soap->mime.start)
13744
{ strcat(soap->tmpbuf, "\"; start=\"");
13745
strcat(soap->tmpbuf, soap->mime.start);
13747
strcat(soap->tmpbuf, "\"");
13749
{ strcat(soap->tmpbuf, "; start-info=\"");
13750
strcat(soap->tmpbuf, r);
13751
strcat(soap->tmpbuf, "\"");
13756
if (s && (err = soap->fposthdr(soap, "Content-Type", s)))
13759
if (soap->omode & SOAP_ENC_ZLIB)
13762
err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip");
13764
err = soap->fposthdr(soap, "Content-Encoding", "deflate");
13770
#ifndef WITH_LEANER
13771
if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)
13772
err = soap->fposthdr(soap, "Transfer-Encoding", "chunked");
13776
{ sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
13777
err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
13782
return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close");
13787
/******************************************************************************/
13788
#ifndef WITH_NOHTTP
13791
http_get(struct soap *soap)
13792
{ return SOAP_GET_METHOD;
13797
/******************************************************************************/
13798
#ifndef WITH_NOHTTP
13801
http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count)
13802
{ register const char *s;
13804
if (soap->status == SOAP_GET)
13809
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))
13811
if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
13814
if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
13815
return soap->error = SOAP_EOM;
13816
if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*"))
13817
sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
13819
sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
13820
if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13822
#ifdef WITH_OPENSSL
13823
if ((soap->ssl && soap->port != 443) || (!soap->ssl && soap->port != 80))
13824
sprintf(soap->tmpbuf, "%s:%d", host, port);
13826
strcpy(soap->tmpbuf, host);
13829
sprintf(soap->tmpbuf, "%s:%d", host, port);
13831
strcpy(soap->tmpbuf, host);
13833
if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf))
13834
|| (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7"))
13835
|| (err = soap_puthttphdr(soap, SOAP_OK, count)))
13839
if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate")))
13841
if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate")))
13846
if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
13847
{ sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
13848
strcpy(soap->tmpbuf, "Basic ");
13849
soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
13850
if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
13853
if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
13854
{ sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
13855
strcpy(soap->tmpbuf, "Basic ");
13856
soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
13857
if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
13861
#ifdef WITH_COOKIES
13862
#ifdef WITH_OPENSSL
13863
if (soap_putcookies(soap, host, path, soap->ssl != NULL))
13864
return soap->error;
13866
if (soap_putcookies(soap, host, path, 0))
13867
return soap->error;
13870
if (soap->status != SOAP_GET && (soap->version == 1 || (action && *action && strlen(action) < sizeof(soap->tmpbuf) - 2)))
13871
{ sprintf(soap->tmpbuf, "\"%s\"", action?action:"");
13872
if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
13875
return soap->fposthdr(soap, NULL, NULL);
13880
/******************************************************************************/
13881
#ifndef WITH_NOHTTP
13884
http_send_header(struct soap *soap, const char *s)
13885
{ register const char *t;
13887
{ t = strchr(s, '\n'); /* disallow \n in HTTP headers */
13890
if (soap_send_raw(soap, s, t - s))
13891
return soap->error;
13899
/******************************************************************************/
13900
#ifndef WITH_NOHTTP
13903
http_post_header(struct soap *soap, const char *key, const char *val)
13905
{ if (http_send_header(soap, key))
13906
return soap->error;
13907
if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val)))
13908
return soap->error;
13910
return soap_send_raw(soap, "\r\n", 2);
13915
/******************************************************************************/
13916
#ifndef WITH_NOHTTP
13919
http_response(struct soap *soap, int status, size_t count)
13920
{ register int err;
13922
if (soap->rpmreqid)
13923
httpOutputEnable(soap->rpmreqid);
13925
if (strlen(soap->http_version) > 4)
13926
return soap->error = SOAP_EOM;
13927
if (!status || status == SOAP_HTML || status == SOAP_FILE)
13929
if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
13932
s = "202 ACCEPTED";
13933
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s));
13935
if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
13937
if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
13939
{ sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
13940
if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13943
else if ((err = soap->fposthdr(soap, "Status", s)))
13946
else if (status >= 200 && status < 600)
13947
{ sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
13948
if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13952
{ sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm ? strlen(soap->authrealm) : 18) < sizeof(soap->tmpbuf) - 14 ? soap->authrealm : "gSOAP Web Service");
13953
if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
13956
else if ((status >= 301 && status <= 303) || status == 307)
13957
{ if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
13963
{ const char *s = *soap_faultcode(soap);
13964
if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
13965
s = "400 Bad Request";
13967
s = "500 Internal Server Error";
13968
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
13970
if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
13972
if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
13974
{ sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
13975
if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
13978
else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */
13981
if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7"))
13982
|| (err = soap_puthttphdr(soap, status, count)))
13984
#ifdef WITH_COOKIES
13985
if (soap_putsetcookies(soap))
13986
return soap->error;
13988
return soap->fposthdr(soap, NULL, NULL);
13993
/******************************************************************************/
13998
soap_response(struct soap *soap, int status)
13999
{ register size_t count;
14000
if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */))
14001
&& (status == SOAP_HTML || status == SOAP_FILE))
14002
{ soap->omode &= ~SOAP_IO;
14003
soap->omode |= SOAP_IO_STORE;
14005
soap->status = status;
14006
count = soap_count_attachments(soap);
14007
if (soap_begin_send(soap))
14008
return soap->error;
14009
#ifndef WITH_NOHTTP
14010
if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML))
14011
{ register int n = soap->mode;
14012
soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB);
14013
if ((n & SOAP_IO) != SOAP_IO_FLUSH)
14014
soap->mode |= SOAP_IO_BUFFER;
14015
if ((soap->error = soap->fresponse(soap, status, count)))
14016
return soap->error;
14017
#ifndef WITH_LEANER
14018
if ((n & SOAP_IO) == SOAP_IO_CHUNK)
14019
{ if (soap_flush(soap))
14020
return soap->error;
14030
/******************************************************************************/
14033
soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
14035
sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag);
14037
sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS);
14038
return soap->msgbuf;
14042
/******************************************************************************/
14047
soap_set_fault(struct soap *soap)
14048
{ const char **c = soap_faultcode(soap);
14049
const char **s = soap_faultstring(soap);
14050
if (soap->fseterror)
14051
soap->fseterror(soap, c, s);
14053
{ if (soap->version == 2)
14054
*c = "SOAP-ENV:Sender";
14056
*c = "SOAP-ENV:Client";
14060
switch (soap->error)
14063
case SOAP_CLI_FAULT:
14064
*s = "Client fault";
14066
case SOAP_SVR_FAULT:
14067
*s = "Server fault";
14069
case SOAP_TAG_MISMATCH:
14070
*s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL);
14073
*s = soap_set_validation_fault(soap, "data type mismatch ", soap->type);
14075
case SOAP_SYNTAX_ERROR:
14076
*s = "Well-formedness violation";
14079
*s = "No XML element tag";
14081
case SOAP_MUSTUNDERSTAND:
14082
*c = "SOAP-ENV:MustUnderstand";
14083
sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
14086
case SOAP_VERSIONMISMATCH:
14087
*c = "SOAP-ENV:VersionMismatch";
14088
*s = "Invalid SOAP message or SOAP version mismatch";
14090
case SOAP_DATAENCODINGUNKNOWN:
14091
*c = "SOAP-ENV:DataEncodingUnknown";
14092
*s = "Unsupported SOAP data encoding";
14094
case SOAP_NAMESPACE:
14095
*s = soap_set_validation_fault(soap, "namespace error", NULL);
14097
case SOAP_USER_ERROR:
14100
case SOAP_FATAL_ERROR:
14101
*s = "Fatal error";
14103
case SOAP_NO_METHOD:
14104
sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag);
14108
*s = "Data required for operation";
14110
case SOAP_GET_METHOD:
14111
*s = "HTTP GET method not implemented";
14114
*s = "Out of memory";
14117
*s = "Memory overflow or memory corruption error";
14120
*s = "Header line too long";
14123
*s = "Array index out of bounds";
14126
*s = soap_set_validation_fault(soap, "nil not allowed", NULL);
14128
case SOAP_DUPLICATE_ID:
14129
*s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id);
14130
if (soap->version == 2)
14131
*soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
14133
case SOAP_MISSING_ID:
14134
*s = soap_set_validation_fault(soap, "missing id for ref ", soap->id);
14135
if (soap->version == 2)
14136
*soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
14139
*s = soap_set_validation_fault(soap, "incompatible object type ref/id pair ", soap->id);
14144
case SOAP_UDP_ERROR:
14145
*s = "Message too large for UDP packet";
14147
case SOAP_TCP_ERROR:
14148
*s = tcp_error(soap);
14151
case SOAP_HTTP_ERROR:
14152
*s = "An HTTP processing error occurred";
14154
case SOAP_SSL_ERROR:
14155
#ifdef WITH_OPENSSL
14158
*s = "OpenSSL not installed: recompile with -DWITH_OPENSSL";
14161
case SOAP_PLUGIN_ERROR:
14162
*s = "Plugin registry error";
14164
case SOAP_DIME_ERROR:
14165
*s = "DIME format error";
14167
case SOAP_DIME_HREF:
14168
*s = "DIME href to missing attachment";
14170
case SOAP_DIME_MISMATCH:
14171
*s = "DIME version/transmission error";
14173
case SOAP_DIME_END:
14174
*s = "End of DIME error";
14176
case SOAP_MIME_ERROR:
14177
*s = "MIME format error";
14179
case SOAP_MIME_HREF:
14180
*s = "MIME href to missing attachment";
14182
case SOAP_MIME_END:
14183
*s = "End of MIME error";
14185
case SOAP_ZLIB_ERROR:
14187
sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:"");
14190
*s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP";
14193
case SOAP_REQUIRED:
14194
*s = soap_set_validation_fault(soap, "missing required attribute", NULL);
14196
case SOAP_PROHIBITED:
14197
*s = soap_set_validation_fault(soap, "prohibited attribute present", NULL);
14200
*s = soap_set_validation_fault(soap, "occurrence violation", NULL);
14203
*s = soap_set_validation_fault(soap, "content length violation", NULL);
14205
case SOAP_FD_EXCEEDED:
14206
*s = "Maximum number of open connections was reached";
14209
*s = "Stopped: no response sent";
14214
strcpy(soap->msgbuf, soap_strerror(soap));
14216
if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
14217
{ memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
14218
memcpy(soap->msgbuf, "End of file or no input: ", 25);
14224
*s = "End of file or no input";
14228
#ifndef WITH_NOHTTP
14230
if (soap->error > 200 && soap->error < 600)
14231
{ sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error));
14237
{ sprintf(soap->msgbuf, "Error %d", soap->error);
14244
/******************************************************************************/
14249
soap_send_fault(struct soap *soap)
14250
{ register int status = soap->error;
14252
if (status == SOAP_STOP)
14254
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
14255
soap->keep_alive = 0; /* to terminate connection */
14256
soap_set_fault(soap);
14259
if (soap_valid_socket(soap->socket))
14260
{ struct timeval timeout;
14262
timeout.tv_sec = 0;
14263
timeout.tv_usec = 0;
14266
FD_SET(soap->socket, &rfd);
14267
FD_SET(soap->socket, &sfd);
14268
r = select((int)soap->socket + 1, &rfd, &sfd, NULL, &timeout);
14270
{ if (!FD_ISSET(soap->socket, &sfd)
14271
|| (FD_ISSET(soap->socket, &rfd)
14272
&& recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0))
14278
if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0)
14279
{ soap->error = SOAP_OK;
14280
soap_serializeheader(soap);
14281
soap_serializefault(soap);
14282
soap_begin_count(soap);
14283
if (soap->mode & SOAP_IO_LENGTH)
14284
{ soap_envelope_begin_out(soap);
14285
soap_putheader(soap);
14286
soap_body_begin_out(soap);
14287
soap_putfault(soap);
14288
soap_body_end_out(soap);
14289
soap_envelope_end_out(soap);
14291
soap_end_count(soap);
14292
if (soap_response(soap, status)
14293
|| soap_envelope_begin_out(soap)
14294
|| soap_putheader(soap)
14295
|| soap_body_begin_out(soap)
14296
|| soap_putfault(soap)
14297
|| soap_body_end_out(soap)
14298
|| soap_envelope_end_out(soap))
14299
return soap_closesock(soap);
14300
soap_end_send(soap);
14302
soap->error = status;
14303
return soap_closesock(soap);
14307
/******************************************************************************/
14312
soap_recv_fault(struct soap *soap)
14313
{ register int status = soap->error;
14314
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n"));
14315
soap->error = SOAP_OK;
14316
if (soap_getfault(soap))
14317
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n"));
14318
*soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client");
14319
soap->error = status;
14320
soap_set_fault(soap);
14323
{ register const char *s = *soap_faultcode(soap);
14324
if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver"))
14325
status = SOAP_SVR_FAULT;
14326
else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender"))
14327
status = SOAP_CLI_FAULT;
14328
else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand"))
14329
status = SOAP_MUSTUNDERSTAND;
14330
else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch"))
14331
status = SOAP_VERSIONMISMATCH;
14333
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s));
14334
status = SOAP_FAULT;
14336
if (soap_body_end_in(soap)
14337
|| soap_envelope_end_in(soap)
14338
|| soap_end_recv(soap))
14339
return soap_closesock(soap);
14340
soap->error = status;
14342
return soap_closesock(soap);
14346
/******************************************************************************/
14347
#ifndef WITH_NOHTTP
14352
soap_send_empty_response(struct soap *soap, int status)
14353
{ register soap_mode m = soap->omode;
14355
if ((m & SOAP_IO) == SOAP_IO_CHUNK)
14356
{ soap->omode &= ~SOAP_IO_CHUNK;
14357
soap->omode |= SOAP_IO_BUFFER;
14359
if (soap_response(soap, status) || soap_end_send(soap))
14361
return soap_closesock(soap);
14369
/******************************************************************************/
14370
#ifndef WITH_NOHTTP
14375
soap_recv_empty_response(struct soap *soap)
14376
{ if (soap_begin_recv(soap) || soap_end_recv(soap))
14377
{ if (soap->error != 202)
14378
return soap_closesock(soap);
14379
soap->error = SOAP_OK;
14386
/******************************************************************************/
14390
soap_strerror(struct soap *soap)
14391
{ register int err = soap->errnum;
14395
return strerror(err);
14399
*soap->msgbuf = '\0';
14400
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);
14403
*soap->msgbuf = '\0';
14404
len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL);
14405
for (i = 0; i <= len; i++)
14406
{ if (((TCHAR*)soap->msgbuf)[i] < 0x80)
14407
soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i];
14409
soap->msgbuf[i] = '?';
14412
return soap->msgbuf;
14415
return "Operation interrupted or timed out";
14420
/******************************************************************************/
14423
soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror)
14424
{ *soap_faultcode(soap) = faultcode;
14426
*soap_faultsubcode(soap) = faultsubcode;
14427
*soap_faultstring(soap) = faultstring;
14428
if (faultdetail && *faultdetail)
14429
{ register const char **s = soap_faultdetail(soap);
14433
return soap->error = soaperror;
14437
/******************************************************************************/
14442
soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
14443
{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror);
14447
/******************************************************************************/
14452
soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror)
14453
{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror);
14457
/******************************************************************************/
14460
soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail)
14461
{ char *r = NULL, *s = NULL, *t = NULL;
14463
r = soap_strdup(soap, faultsubcode);
14465
s = soap_strdup(soap, faultstring);
14467
t = soap_strdup(soap, faultdetail);
14468
return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT);
14472
/******************************************************************************/
14477
soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
14478
{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail);
14482
/******************************************************************************/
14487
soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
14488
{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail);
14492
/******************************************************************************/
14497
soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail)
14498
{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail);
14502
/******************************************************************************/
14507
soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail)
14508
{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail);
14512
/******************************************************************************/
14514
#ifndef WITH_NOSTDLIB
14518
soap_print_fault(struct soap *soap, FILE *fd)
14519
{ if (soap_check_state(soap))
14520
fprintf(fd, "Error: soap struct not initialized\n");
14521
else if (soap->error)
14522
{ const char *c, *v = NULL, *s, **d;
14523
d = soap_faultcode(soap);
14525
soap_set_fault(soap);
14527
if (soap->version == 2)
14528
v = *soap_faultsubcode(soap);
14529
s = *soap_faultstring(soap);
14530
d = soap_faultdetail(soap);
14531
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]");
14537
/******************************************************************************/
14539
#ifndef WITH_NOSTDLIB
14543
soap_sprint_fault(struct soap *soap, char *buf, size_t len)
14544
{ if (soap_check_state(soap))
14545
strncpy(buf, "Error: soap struct not initialized", len);
14546
else if (soap->error)
14547
{ const char *c, *v = NULL, *s, **d;
14548
d = soap_faultcode(soap);
14550
soap_set_fault(soap);
14552
if (soap->version == 2)
14553
v = *soap_faultsubcode(soap);
14554
s = *soap_faultstring(soap);
14555
d = soap_faultdetail(soap);
14561
(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]");
14568
/******************************************************************************/
14570
#ifndef WITH_NOSTDLIB
14574
soap_print_fault_location(struct soap *soap, FILE *fd)
14578
if (soap->error && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN)
14579
{ i = (int)soap->bufidx - 1;
14583
soap->buf[i] = '\0';
14584
if ((int)soap->buflen >= i + 1024)
14587
j = (int)soap->buflen - 1;
14589
soap->buf[j] = '\0';
14590
fprintf(fd, "%s%c\n<!-- ** HERE ** -->\n", soap->buf, c1);
14591
if (soap->bufidx < soap->buflen)
14592
fprintf(fd, "%s\n", soap->buf + soap->bufidx);
14601
/******************************************************************************/
14606
soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg)
14607
{ register struct soap_plugin *p;
14609
if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin))))
14610
return soap->error = SOAP_EOM;
14615
r = fcreate(soap, p, arg);
14616
if (!r && p->fdelete)
14617
{ p->next = soap->plugins;
14619
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id));
14622
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));
14623
SOAP_FREE(soap, p);
14628
/******************************************************************************/
14631
fplugin(struct soap *soap, const char *id)
14632
{ register struct soap_plugin *p;
14633
for (p = soap->plugins; p; p = p->next)
14634
if (p->id == id || !strcmp(p->id, id))
14640
/******************************************************************************/
14645
soap_lookup_plugin(struct soap *soap, const char *id)
14646
{ return soap->fplugin(soap, id);
14650
/******************************************************************************/
14655
/******************************************************************************\
14657
* C++ soap struct methods
14659
\******************************************************************************/
14669
/******************************************************************************/
14672
soap::soap(soap_mode m)
14673
{ soap_init1(this, m);
14678
/******************************************************************************/
14681
soap::soap(soap_mode im, soap_mode om)
14682
{ soap_init2(this, im, om);
14687
/******************************************************************************/
14690
soap::soap(struct soap& soap)
14691
{ soap_copy_context(this, &soap);
14696
/******************************************************************************/
14700
{ soap_destroy(this);
14707
/******************************************************************************/