aboutsummaryrefslogtreecommitdiff
path: root/dep/gsoap/stdsoap2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/gsoap/stdsoap2.cpp')
-rw-r--r--dep/gsoap/stdsoap2.cpp1758
1 files changed, 1212 insertions, 546 deletions
diff --git a/dep/gsoap/stdsoap2.cpp b/dep/gsoap/stdsoap2.cpp
index 36a8901dcab..6186f8904e3 100644
--- a/dep/gsoap/stdsoap2.cpp
+++ b/dep/gsoap/stdsoap2.cpp
@@ -1,10 +1,10 @@
/*
- stdsoap2.c[pp] 2.8.10
+ stdsoap2.c[pp] 2.8.17r
gSOAP runtime engine
gSOAP XML Web services tools
-Copyright (C) 2000-2012, Robert van Engelen, Genivia Inc., All Rights Reserved.
+Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
This part of the software is released under ONE of the following licenses:
GPL, or the gSOAP public license, or Genivia's license for commercial use.
--------------------------------------------------------------------------------
@@ -24,7 +24,7 @@ WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the License.
The Initial Developer of the Original Code is Robert A. van Engelen.
-Copyright (C) 2000-2012, Robert van Engelen, Genivia Inc., All Rights Reserved.
+Copyright (C) 2000-2013, Robert van Engelen, Genivia Inc., All Rights Reserved.
--------------------------------------------------------------------------------
GPL license.
@@ -51,13 +51,16 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com
--------------------------------------------------------------------------------
*/
-#define GSOAP_LIB_VERSION 20810
+#define GSOAP_LIB_VERSION 20817
#ifdef AS400
# pragma convert(819) /* EBCDIC to ASCII */
#endif
#include "stdsoap2.h"
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+#include <ipcom_key_db.h>
+#endif
#if GSOAP_VERSION != GSOAP_LIB_VERSION
# error "GSOAP VERSION MISMATCH IN LIBRARY: PLEASE REINSTALL PACKAGE"
#endif
@@ -76,10 +79,10 @@ A commercial use license is available from Genivia, Inc., contact@genivia.com
#endif
#ifdef __cplusplus
-SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.10 2012-08-16 00:00:00 GMT")
+SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.8.17r 2013-12-18 00:00:00 GMT")
extern "C" {
#else
-SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.10 2012-08-16 00:00:00 GMT")
+SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.8.17r 2013-12-18 00:00:00 GMT")
#endif
/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */
@@ -570,7 +573,7 @@ fsend(struct soap *soap, const char *s, size_t n)
err = soap->errnum;
if (!err)
return soap->error;
- if (err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
+ if (err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK)
return SOAP_EOF;
}
}
@@ -614,6 +617,14 @@ fsend(struct soap *soap, const char *s, size_t n)
}
while (nwritten < 0 && --udp_repeat > 0);
}
+ if (nwritten < 0)
+ { err = soap_socket_errno(sk);
+ if (err && err != SOAP_EINTR)
+ { soap->errnum = err;
+ return SOAP_EOF;
+ }
+ nwritten = 0; /* and call write() again */
+ }
}
else
#endif
@@ -654,7 +665,7 @@ fsend(struct soap *soap, const char *s, size_t n)
r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->send_timeout ? soap->send_timeout : -10000);
if (!r && soap->send_timeout)
return SOAP_EOF;
- if (r < 0 && soap->errnum != SOAP_EINTR)
+ if (r < 0)
return SOAP_EOF;
}
else if (err && err != SOAP_EINTR)
@@ -809,13 +820,18 @@ soap_flush_raw(struct soap *soap, const char *s, size_t n)
#ifndef WITH_LEANER
if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
{ char t[16];
- sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n);
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(t, sizeof(t), &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
+#else
+ sprintf(t, &"\r\n%lX\r\n"[soap->chunksize ? 0 : 2], (unsigned long)n);
+#endif
DBGMSG(SENT, t, strlen(t));
if ((soap->error = soap->fsend(soap, t, strlen(t))))
return soap->error;
soap->chunksize += n;
}
DBGMSG(SENT, s, n);
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)n, soap->socket, soap->sendfd));
#endif
return soap->error = soap->fsend(soap, s, n);
}
@@ -899,7 +915,7 @@ frecv(struct soap *soap, char *s, size_t n)
if (!r)
return 0;
r = soap->errnum;
- if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
+ if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
return 0;
}
}
@@ -955,11 +971,11 @@ frecv(struct soap *soap, char *s, size_t n)
}
#if defined(WITH_OPENSSL)
if (soap->ssl && err == SSL_ERROR_WANT_WRITE)
- r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
+ r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
else
#elif defined(WITH_GNUTLS)
if (soap->session && gnutls_record_get_direction(soap->session))
- r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
+ r = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
else
#endif
r = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, soap->recv_timeout ? soap->recv_timeout : 5);
@@ -967,7 +983,7 @@ frecv(struct soap *soap, char *s, size_t n)
return 0;
if (r < 0)
{ r = soap->errnum;
- if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
+ if (r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK)
return 0;
}
if (retries-- <= 0)
@@ -1108,12 +1124,12 @@ zlib_again:
t = tmp;
if (!soap->chunkbuflen)
{ soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN);
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket=%d\n", (unsigned int)ret, soap->socket));
DBGMSG(RECV, soap->buf, ret);
soap->bufidx = 0;
if (!ret)
{ soap->ahead = EOF;
- return EOF;
+ return EOF;
}
}
else
@@ -1123,7 +1139,7 @@ zlib_again:
while (!soap_isxdigit((int)(c = soap_getchunkchar(soap))))
{ if ((int)c == EOF)
{ soap->ahead = EOF;
- return EOF;
+ return EOF;
}
}
do
@@ -1217,6 +1233,7 @@ zlib_again:
return soap->error = r;
#endif
soap->count += ret;
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read count=%lu (+%lu)\n", (unsigned long)soap->count, (unsigned long)ret));
return !ret;
}
#endif
@@ -1637,9 +1654,9 @@ soap_get_pi(struct soap *soap)
SOAP_FMAC1
int
SOAP_FMAC2
-soap_move(struct soap *soap, long n)
-{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n));
- for (; n > 0; n--)
+soap_move(struct soap *soap, size_t n)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %lu bytes forward\n", (unsigned long)n));
+ for (; n; n--)
if ((int)soap_getchar(soap) == EOF)
return SOAP_EOF;
return SOAP_OK;
@@ -1697,8 +1714,12 @@ soap_pututf8(struct soap *soap, register unsigned long c)
*t++ = (char)(0x80 | (c & 0x3F));
*t = '\0';
}
+ else
+#endif
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(tmp, sizeof(tmp), "&#%lu;", c);
#else
- sprintf(tmp, "&#%lu;", c);
+ sprintf(tmp, "&#%lu;", c);
#endif
return soap_send(soap, tmp);
}
@@ -1712,7 +1733,7 @@ SOAP_FMAC2
soap_getutf8(struct soap *soap)
{ register soap_wchar c, c1, c2, c3, c4;
c = soap->ahead;
- if (c)
+ if (c >= 0x80)
soap->ahead = 0;
else
c = soap_get(soap);
@@ -1930,8 +1951,8 @@ soap_getbase64(struct soap *soap, int *n, int malloc_flag)
register int j = 0;
do
{ register soap_wchar c = soap_get(soap);
- if (c < SOAP_AP)
- c &= 0x7FFFFFFF;
+ if (c < SOAP_AP)
+ c &= 0x7FFFFFFF;
if (c == '=' || c < 0)
{ unsigned char *p;
switch (j)
@@ -2527,27 +2548,70 @@ SOAP_FMAC1
char *
SOAP_FMAC2
soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim)
-{ int i;
- if (!type)
+{ register int i;
+ register size_t l;
+ if (!type || strlen(type) + 13 > sizeof(soap->type)) /* prevent overruns */
return NULL;
if (soap->version == 2)
- { sprintf(soap->type, "%s[%d", type, size[0]);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
+#else
+ sprintf(soap->type, "%s[%d", type, size[0]);
+#endif
for (i = 1; i < dim; i++)
- sprintf(soap->type + strlen(soap->type), " %d", size[i]);
+ {
+#ifdef HAVE_SNPRINTF
+ l = strlen(soap->type);
+ soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, " %d", size[i]);
+#else
+ if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
+ return NULL;
+ sprintf(soap->type + l, " %d", size[i]);
+#endif
+ }
}
else
{ if (offset)
- { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0] + offset[0]);
+#else
+ sprintf(soap->type, "%s[%d", type, size[0] + offset[0]);
+#endif
for (i = 1; i < dim; i++)
- sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]);
+ {
+#ifdef HAVE_SNPRINTF
+ l = strlen(soap->type);
+ soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i] + offset[i]);
+#else
+ if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
+ return NULL;
+ sprintf(soap->type + l, ",%d", size[i] + offset[i]);
+#endif
+ }
}
else
- { sprintf(soap->type, "%s[%d", type, size[0]);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->type, sizeof(soap->type) - 1, "%s[%d", type, size[0]);
+#else
+ sprintf(soap->type, "%s[%d", type, size[0]);
+#endif
for (i = 1; i < dim; i++)
- sprintf(soap->type + strlen(soap->type), ",%d", size[i]);
+ {
+#ifdef HAVE_SNPRINTF
+ l = strlen(soap->type);
+ soap_snprintf(soap->type + l, sizeof(soap->type) - l - 1, ",%d", size[i]);
+#else
+ if ((l = strlen(soap->type)) + 13 > sizeof(soap->type))
+ return NULL;
+ sprintf(soap->type + l, ",%d", size[i]);
+#endif
+ }
}
- strcat(soap->type, "]");
}
+ strcat(soap->type, "]");
return soap->type;
}
#endif
@@ -2569,9 +2633,25 @@ char *
SOAP_FMAC2
soap_putoffsets(struct soap *soap, const int *offset, int dim)
{ register int i;
+ register size_t l;
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->arrayOffset, sizeof(soap->arrayOffset) - 1, "[%d", offset[0]);
+#else
+ if (sizeof(soap->arrayOffset) < 13) /* prevent overruns */
+ return NULL;
sprintf(soap->arrayOffset, "[%d", offset[0]);
+#endif
for (i = 1; i < dim; i++)
- sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]);
+ {
+#ifdef HAVE_SNPRINTF
+ l = strlen(soap->arrayOffset);
+ soap_snprintf(soap->arrayOffset + l, sizeof(soap->arrayOffset) - l - 1, ",%d", offset[i]);
+#else
+ if ((l = strlen(soap->arrayOffset)) + 13 > sizeof(soap->arrayOffset))
+ return NULL;
+ sprintf(soap->arrayOffset + l, ",%d", offset[i]);
+#endif
+ }
strcat(soap->arrayOffset, "]");
return soap->arrayOffset;
}
@@ -2901,6 +2981,11 @@ soap_match_tag(struct soap *soap, const char *tag1, const char *tag2)
return err;
}
}
+ else if (!t[1])
+ { err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2);
+ if (err == SOAP_NAMESPACE)
+ return SOAP_TAG_MISMATCH;
+ }
else if (SOAP_STRCMP(tag1, t + 1))
{ return SOAP_TAG_MISMATCH;
}
@@ -2970,9 +3055,16 @@ soap_rand()
SOAP_FMAC1
int
SOAP_FMAC2
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid)
+#else
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)
+#endif
{ int err;
soap->keyfile = keyfile;
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+ soap->keyid = keyid;
+#endif
soap->password = password;
soap->cafile = cafile;
soap->capath = capath;
@@ -3038,8 +3130,15 @@ soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *key
SOAP_FMAC1
int
SOAP_FMAC2
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *keyid, const char *password, const char *cafile, const char *capath, const char *randfile)
+#else
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)
+#endif
{ soap->keyfile = keyfile;
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+ soap->keyid = keyid;
+#endif
soap->password = password;
soap->cafile = cafile;
soap->capath = capath;
@@ -3130,13 +3229,16 @@ soap_ssl_error(struct soap *soap, int ret)
else
{ switch (ret)
{ case 0:
- strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information.");
+ strcpy(soap->msgbuf, "EOF was observed that violates the SSL/TLS protocol. The client probably provided invalid authentication information.");
break;
case -1:
#ifdef HAVE_SNPRINTF
- soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error observed by underlying BIO: %s", strerror(errno));
+ soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error observed by underlying SSL/TLS BIO: %s", strerror(errno));
#else
- sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno));
+ { const char *s = strerror(errno);
+ size_t l = strlen(s);
+ sprintf(soap->msgbuf, "Error observed by underlying SSL/TLS BIO: %s", l + 44 < sizeof(soap->msgbuf) ? s : SOAP_STR_EOS);
+ }
#endif
break;
}
@@ -3159,6 +3261,9 @@ ssl_auth_init(struct soap *soap)
#ifdef WITH_OPENSSL
long flags;
int mode;
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+ EVP_PKEY* pkey;
+#endif
if (!soap_ssl_init_done)
soap_ssl_init();
ERR_clear_error();
@@ -3194,7 +3299,17 @@ ssl_auth_init(struct soap *soap)
}
if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
+#ifndef WM_SECURE_KEY_STORAGE
+ if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM))
+ return soap_set_receiver_error(soap, "SSL/TLS error", "Can't read key file", SOAP_SSL_ERROR);
+#endif
}
+#if defined(VXWORKS) && defined(WM_SECURE_KEY_STORAGE)
+ if (NULL == (pkey = ipcom_key_db_pkey_get(soap->keyid)))
+ return soap_set_receiver_error(soap, "SSL error", "Can't find key", SOAP_SSL_ERROR);
+ if (0 == SSL_CTX_use_PrivateKey(soap->ctx, pkey))
+ return soap_set_receiver_error(soap, "SSL error", "Can't read key", SOAP_SSL_ERROR);
+#endif
/* Suggested alternative approach to check the key file for certs (cafile=NULL):*/
#if 0
if (soap->password)
@@ -3225,7 +3340,11 @@ ssl_auth_init(struct soap *soap)
int n = (int)soap_strtoul(soap->dhfile, &s, 10);
/* if dhfile is numeric, treat it as a key length to generate DH params which can take a while */
if (n >= 512 && s && *s == '\0')
+#if defined(VXWORKS)
+ DH_generate_parameters_ex(dh, n, 2/*or 5*/, NULL);
+#else
dh = DH_generate_parameters(n, 2/*or 5*/, NULL, NULL);
+#endif
else
{ BIO *bio;
bio = BIO_new_file(soap->dhfile, "r");
@@ -3478,7 +3597,7 @@ soap_ssl_accept(struct soap *soap)
s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
else
s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
- if (s < 0 && soap->errnum != SOAP_EINTR)
+ if (s < 0)
break;
}
else
@@ -3533,7 +3652,7 @@ soap_ssl_accept(struct soap *soap)
s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
else
s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
- if (s < 0 && soap->errnum != SOAP_EINTR)
+ if (s < 0)
break;
}
else
@@ -3611,7 +3730,12 @@ tcp_error(struct soap *soap)
msg = soap_code_str(h_error_codes, soap->errnum);
if (!msg)
#endif
- { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "TCP/UDP IP error %d", soap->errnum);
+#else
+ sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum);
+#endif
msg = soap->msgbuf;
}
}
@@ -3647,7 +3771,7 @@ tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr)
{ memcpy(inaddr, &iadd, sizeof(iadd));
return SOAP_OK;
}
-#if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__)))
+#if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) || defined(__ANDROID__)
if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0)
host = NULL;
#elif defined(_AIX43) || ((defined(TRU64) || defined(HP_UX)) && defined(HAVE_GETHOSTBYNAME_R))
@@ -3915,7 +4039,7 @@ again:
}
#endif
#endif
- DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", sk, host, port));
+ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket=%d to host='%s' port=%d\n", sk, host, port));
#ifndef WITH_IPV6
soap->peerlen = sizeof(soap->peer);
memset((void*)&soap->peer, 0, sizeof(soap->peer));
@@ -3988,7 +4112,7 @@ again:
#endif
return SOAP_INVALID_SOCKET;
}
- r = soap->errnum;
+ r = soap->errnum = soap_socket_errno(sk);
if (r != SOAP_EINTR)
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n"));
soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR);
@@ -4057,7 +4181,7 @@ again:
short keep_alive = soap->keep_alive; /* save the KA status */
soap->omode &= ~SOAP_ENC; /* mask IO and ENC */
soap->omode |= SOAP_IO_BUFFER;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server %s for destination endpoint %s\n", soap->proxy_http_version, soap->proxy_host, endpoint));
#ifdef WITH_NTLM
if (soap->ntlm_challenge)
{ if (soap_ntlm_handshake(soap, SOAP_CONNECT, endpoint, host, port))
@@ -4071,7 +4195,7 @@ again:
soap->status = SOAP_CONNECT;
soap->keep_alive = 1;
if ((soap->error = soap->fpost(soap, endpoint, host, port, NULL, NULL, 0))
- || soap_end_send(soap))
+ || soap_end_send_flush(soap))
{ soap->fclosesocket(soap, sk);
return SOAP_INVALID_SOCKET;
}
@@ -4095,7 +4219,9 @@ again:
return SOAP_INVALID_SOCKET;
}
if (endpoint)
- strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */
+ { strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)); /* restore */
+ soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
+ }
soap->mode = m;
}
#ifdef WITH_OPENSSL
@@ -4146,7 +4272,7 @@ again:
s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
else
s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
- if (s < 0 && soap->errnum != SOAP_EINTR)
+ if (s < 0)
{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "SSL_connect/select error in tcp_connect\n"));
soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL_connect failed in tcp_connect()", SOAP_TCP_ERROR);
soap->fclosesocket(soap, sk);
@@ -4178,15 +4304,20 @@ again:
}
if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK))
{ X509_NAME *subj;
+ STACK_OF(CONF_VALUE) *val = NULL;
+#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
+ GENERAL_NAMES *names = NULL;
+#else
int ext_count;
+#endif
int ok = 0;
- X509 *peer;
- peer = SSL_get_peer_certificate(soap->ssl);
+ X509 *peer = SSL_get_peer_certificate(soap->ssl);
if (!peer)
{ soap_set_sender_error(soap, "SSL/TLS error", "No SSL/TLS certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR);
soap->fclosesocket(soap, sk);
return SOAP_INVALID_SOCKET;
}
+#if (OPENSSL_VERSION_NUMBER < 0x0090800fL)
ext_count = X509_get_ext_count(peer);
if (ext_count > 0)
{ int i;
@@ -4195,36 +4326,42 @@ again:
const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
if (ext_str && !strcmp(ext_str, "subjectAltName"))
{ X509V3_EXT_METHOD *meth = (X509V3_EXT_METHOD*)X509V3_EXT_get(ext);
- void *ext_data;
-#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
- const unsigned char *data;
-#else
unsigned char *data;
-#endif
- STACK_OF(CONF_VALUE) *val;
- int j;
if (!meth)
break;
data = ext->value->data;
+ if (data)
+ {
#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
- if (meth->it)
- ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
- else
- { /* OpenSSL not perfectly portable at this point (?):
- Some compilers appear to prefer
- meth->d2i(NULL, (const unsigned char**)&data, ...
- and others prefer
- meth->d2i(NULL, &data, ext->value->length);
- */
- ext_data = meth->d2i(NULL, &data, ext->value->length);
- }
+ void *ext_data;
+ if (meth->it)
+ ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it));
+ else
+ { /* OpenSSL is not portable at this point (?):
+ Some compilers appear to prefer
+ meth->d2i(NULL, (const unsigned char**)&data, ...
+ and others prefer
+ meth->d2i(NULL, &data, ext->value->length);
+ */
+ ext_data = meth->d2i(NULL, &data, ext->value->length);
+ }
+ if (ext_data)
+ val = meth->i2v(meth, ext_data, NULL);
+ else
+ val = NULL;
+ if (meth->it)
+ ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
+ else
+ meth->ext_free(ext_data);
#else
- ext_data = meth->d2i(NULL, &data, ext->value->length);
+ void *ext_data = meth->d2i(NULL, &data, ext->value->length);
+ if (ext_data)
+ val = meth->i2v(meth, ext_data, NULL);
+ meth->ext_free(ext_data);
#endif
- if (ext_data)
- { val = meth->i2v(meth, ext_data, NULL);
if (val)
- { for (j = 0; j < sk_CONF_VALUE_num(val); j++)
+ { int j;
+ for (j = 0; j < sk_CONF_VALUE_num(val); j++)
{ CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
{ ok = 1;
@@ -4233,20 +4370,30 @@ again:
}
sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
}
-#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
- if (meth->it)
- ASN1_item_free((ASN1_VALUE*)ext_data, ASN1_ITEM_ptr(meth->it));
- else
- meth->ext_free(ext_data);
-#else
- meth->ext_free(ext_data);
-#endif
}
}
if (ok)
break;
}
}
+#else
+ names = (GENERAL_NAMES*)X509_get_ext_d2i(peer, NID_subject_alt_name, NULL, NULL);
+ if (names)
+ { val = i2v_GENERAL_NAMES(NULL, names, val);
+ sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
+ }
+ if (val)
+ { int j;
+ for (j = 0; j < sk_CONF_VALUE_num(val); j++)
+ { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j);
+ if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host))
+ { ok = 1;
+ break;
+ }
+ }
+ sk_CONF_VALUE_pop_free(val, X509V3_conf_free);
+ }
+#endif
if (!ok && (subj = X509_get_subject_name(peer)))
{ int i = -1;
do
@@ -4310,7 +4457,7 @@ again:
s = tcp_select(soap, sk, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, -100000);
else
s = tcp_select(soap, sk, SOAP_TCP_SELECT_SND | SOAP_TCP_SELECT_ERR, -100000);
- if (s < 0 && soap->errnum != SOAP_EINTR)
+ if (s < 0)
break;
}
else
@@ -4352,9 +4499,11 @@ again:
#ifndef PALM_1
static int
tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
-{ register int r;
+{ int r;
struct timeval tv;
fd_set fd[3], *rfd, *sfd, *efd;
+ int retries = 0;
+ int eintr = SOAP_MAXEINTR;
soap->errnum = 0;
#ifndef WIN32
#if !defined(FD_SETSIZE) || defined(__QNX__) || defined(QNX)
@@ -4366,7 +4515,6 @@ tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
#endif
#ifdef HAVE_POLL
{ struct pollfd pollfd;
- int retries = 0;
pollfd.fd = (int)sk;
pollfd.events = 0;
if (flags & SOAP_TCP_SELECT_RCV)
@@ -4375,16 +4523,17 @@ tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
pollfd.events |= POLLOUT;
if (flags & SOAP_TCP_SELECT_ERR)
pollfd.events |= POLLERR;
- if (timeout < 0)
+ if (timeout <= 0)
timeout /= -1000; /* -usec -> ms */
- else if (timeout <= 1000000) /* avoid overflow */
- timeout *= 1000; /* sec -> ms */
else
- { retries = timeout / 1000000;
- timeout = 1000000000;
+ { retries = timeout - 1;
+ timeout = 1000;
}
- do r = poll(&pollfd, 1, timeout);
- while (r == 0 && retries--);
+ do
+ { r = poll(&pollfd, 1, timeout);
+ if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
+ continue;
+ } while (r == 0 && retries--);
if (r > 0)
{ r = 0;
if ((flags & SOAP_TCP_SELECT_RCV) && (pollfd.revents & POLLIN))
@@ -4394,8 +4543,6 @@ tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
if ((flags & SOAP_TCP_SELECT_ERR) && (pollfd.revents & POLLERR))
r |= SOAP_TCP_SELECT_ERR;
}
- else if (r < 0)
- soap->errnum = soap_socket_errno(s);
return r;
}
#else
@@ -4404,31 +4551,37 @@ tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
}
#endif
#endif
- rfd = sfd = efd = NULL;
- if (flags & SOAP_TCP_SELECT_RCV)
- { rfd = &fd[0];
- FD_ZERO(rfd);
- FD_SET(sk, rfd);
- }
- if (flags & SOAP_TCP_SELECT_SND)
- { sfd = &fd[1];
- FD_ZERO(sfd);
- FD_SET(sk, sfd);
- }
- if (flags & SOAP_TCP_SELECT_ERR)
- { efd = &fd[2];
- FD_ZERO(efd);
- FD_SET(sk, efd);
- }
- if (timeout >= 0)
- { tv.tv_sec = timeout;
- tv.tv_usec = 0;
- }
- else
- { tv.tv_sec = -timeout / 1000000;
- tv.tv_usec = -timeout % 1000000;
- }
- r = select((int)sk + 1, rfd, sfd, efd, &tv);
+ if (timeout > 0)
+ retries = timeout - 1;
+ do
+ { rfd = sfd = efd = NULL;
+ if (flags & SOAP_TCP_SELECT_RCV)
+ { rfd = &fd[0];
+ FD_ZERO(rfd);
+ FD_SET(sk, rfd);
+ }
+ if (flags & SOAP_TCP_SELECT_SND)
+ { sfd = &fd[1];
+ FD_ZERO(sfd);
+ FD_SET(sk, sfd);
+ }
+ if (flags & SOAP_TCP_SELECT_ERR)
+ { efd = &fd[2];
+ FD_ZERO(efd);
+ FD_SET(sk, efd);
+ }
+ if (timeout <= 0)
+ { tv.tv_sec = -timeout / 1000000;
+ tv.tv_usec = -timeout % 1000000;
+ }
+ else
+ { tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ }
+ r = select((int)sk + 1, rfd, sfd, efd, &tv);
+ if (r < 0 && (soap->errnum = soap_socket_errno(sk)) == SOAP_EINTR && eintr--)
+ continue;
+ } while (r == 0 && retries--);
if (r > 0)
{ r = 0;
if ((flags & SOAP_TCP_SELECT_RCV) && FD_ISSET(sk, rfd))
@@ -4438,8 +4591,6 @@ tcp_select(struct soap *soap, SOAP_SOCKET sk, int flags, int timeout)
if ((flags & SOAP_TCP_SELECT_ERR) && FD_ISSET(sk, efd))
r |= SOAP_TCP_SELECT_ERR;
}
- else if (r < 0)
- soap->errnum = soap_socket_errno(s);
return r;
}
#endif
@@ -4509,7 +4660,7 @@ tcp_disconnect(struct soap *soap)
timeout)
*/
r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_ERR, 5);
- if (r <= 0 && soap->errnum != SOAP_EINTR)
+ if (r <= 0)
{ soap->errnum = 0;
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n"));
soap->fclosesocket(soap, soap->socket);
@@ -4565,7 +4716,7 @@ tcp_disconnect(struct soap *soap)
static int
tcp_closesocket(struct soap *soap, SOAP_SOCKET sk)
{ (void)soap;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)sk));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket=%d\n", (int)sk));
return soap_closesocket(sk);
}
#endif
@@ -4577,7 +4728,7 @@ tcp_closesocket(struct soap *soap, SOAP_SOCKET sk)
static int
tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET sk, int how)
{ (void)soap;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)sk, how));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket=%d how=%d\n", (int)sk, how));
return shutdown(sk, how);
}
#endif
@@ -4788,11 +4939,13 @@ soap_poll(struct soap *soap)
}
else
#endif
+ { int t;
if (soap_valid_socket(soap->socket)
&& (r & SOAP_TCP_SELECT_SND)
&& (!(r & SOAP_TCP_SELECT_RCV)
- || recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0))
+ || recv(soap->socket, (char*)&t, 1, MSG_PEEK) > 0))
return SOAP_OK;
+ }
}
else if (r < 0)
{ if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR)
@@ -4878,10 +5031,14 @@ soap_accept(struct soap *soap)
soap->port = soap_strtol(port, NULL, 10);
#else
soap->ip = ntohl(soap->peer.sin_addr.s_addr);
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->host, sizeof(soap->host), "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
+#else
sprintf(soap->host, "%u.%u.%u.%u", (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
+#endif
soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */
#endif
- DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %s\n", soap->socket, soap->port, soap->host));
+ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket=%d at port=%d from IP='%s'\n", soap->socket, soap->port, soap->host));
#ifndef WITH_LEAN
if (soap->accept_flags == SO_LINGER)
{ struct linger linger;
@@ -4971,17 +5128,20 @@ soap_closesock(struct soap *soap)
soap->keep_alive = 0;
}
#ifdef WITH_ZLIB
- if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
- deflateEnd(soap->d_stream);
- else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
- inflateEnd(soap->d_stream);
- soap->zlib_state = SOAP_ZLIB_NONE;
+ if (!(soap->mode & SOAP_MIME_POSTCHECK))
+ { if (soap->zlib_state == SOAP_ZLIB_DEFLATE)
+ deflateEnd(soap->d_stream);
+ else if (soap->zlib_state == SOAP_ZLIB_INFLATE)
+ inflateEnd(soap->d_stream);
+ soap->zlib_state = SOAP_ZLIB_NONE;
+ }
#endif
return soap->error = status;
}
#endif
/******************************************************************************/
+#ifndef WITH_NOIO
#ifndef PALM_1
SOAP_FMAC1
int
@@ -4993,6 +5153,7 @@ soap_force_closesock(struct soap *soap)
return SOAP_OK;
}
#endif
+#endif
/******************************************************************************/
#ifndef WITH_NOIO
@@ -5024,7 +5185,7 @@ soap_done(struct soap *soap)
#endif
if (soap_check_state(soap))
return;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n"));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context%s\n", soap->state == SOAP_COPY ? " copy" : ""));
soap_free_temp(soap);
while (soap->clist)
{ struct soap_clist *p = soap->clist->next;
@@ -5034,6 +5195,8 @@ soap_done(struct soap *soap)
if (soap->state == SOAP_INIT)
soap->omode &= ~SOAP_IO_UDP; /* to force close the socket */
soap->keep_alive = 0; /* to force close the socket */
+ if (soap->master == soap->socket) /* do not close twice */
+ soap->master = SOAP_INVALID_SOCKET;
soap_closesock(soap);
#ifdef WITH_COOKIES
soap_free_cookies(soap);
@@ -5194,14 +5357,13 @@ soap_done(struct soap *soap)
/******************************************************************************/
#ifndef WITH_NOHTTP
#ifndef PALM_1
-int
+static int
http_parse(struct soap *soap)
{ char header[SOAP_HDRLEN], *s;
unsigned short httpcmd = 0;
int status = 0;
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n"));
*soap->endpoint = '\0';
- soap->length = 0;
#ifdef WITH_NTLM
if (!soap->ntlm_challenge)
#endif
@@ -5213,11 +5375,13 @@ http_parse(struct soap *soap)
soap->ntlm_challenge = NULL;
#endif
soap->proxy_from = NULL;
- soap->http_content = NULL;
- soap->action = NULL;
- soap->status = 0;
do
- { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
+ { soap->length = 0;
+ soap->http_content = NULL;
+ soap->action = NULL;
+ soap->status = 0;
+ soap->body = 1;
+ if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf)))
{ if (soap->error == SOAP_EOF)
return SOAP_EOF;
return soap->error = 414;
@@ -5271,9 +5435,7 @@ http_parse(struct soap *soap)
{ if (soap->keep_alive == 1)
soap->keep_alive = 0;
if (soap->status == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* soap->status == 0 for HTTP request */
- { soap->imode |= SOAP_IO_CHUNK;
- soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE;
- }
+ soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; /* HTTP 1.0 does not support chunked transfers */
}
if (soap->keep_alive < 0)
soap->keep_alive = 1;
@@ -5297,12 +5459,16 @@ http_parse(struct soap *soap)
if (s && httpcmd)
{ size_t m = strlen(soap->endpoint);
size_t n = m + (s - soap->msgbuf) - l - 1;
- if (m > n)
- m = n;
+ size_t k;
if (n >= sizeof(soap->endpoint))
n = sizeof(soap->endpoint) - 1;
- strncpy(soap->path, soap->msgbuf + l, n - m);
- soap->path[n - m] = '\0';
+ if (m > n)
+ m = n;
+ k = n - m + 1;
+ if (k > sizeof(soap->path))
+ k = sizeof(soap->path);
+ strncpy(soap->path, soap->msgbuf + l, k);
+ soap->path[k - 1] = '\0';
if (*soap->path && *soap->path != '/')
*soap->endpoint = '\0';
strcat(soap->endpoint, soap->path);
@@ -5329,28 +5495,27 @@ http_parse(struct soap *soap)
return soap->error = status;
else if (s)
return soap->error = 405;
- }
- /* Status OK (HTTP 200) */
- if (soap->status == 0 || soap->status == 200)
return SOAP_OK;
- /* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors
- may not have a body. When content length, content type, or chunking is
- used assume there is a message to parse, either XML or HTTP.
- */
+ }
+#if 0
if (soap->length > 0 || (soap->http_content && (!soap->keep_alive || soap->recv_timeout)) || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)
- { if ((soap->status > 200 && soap->status <= 299)
- || soap->status == 400
- || soap->status == 500)
+#endif
+ if (soap->body)
+ { if ((soap->status >= 200 && soap->status <= 299) /* OK, Accepted, etc */
+ || soap->status == 400 /* Bad Request */
+ || soap->status == 500) /* Internal Server Error */
return SOAP_OK;
/* force close afterwards in soap_closesock() */
soap->keep_alive = 0;
#ifndef WITH_LEAN
/* read HTTP body for error details */
- s = soap_get_http_body(soap);
+ s = soap_get_http_body(soap, NULL);
if (s)
return soap_set_receiver_error(soap, soap->msgbuf, s, soap->status);
#endif
}
+ else if (soap->status >= 200 && soap->status <= 299)
+ return soap->error = soap->status;
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", soap->status));
return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, soap->status);
}
@@ -5371,7 +5536,6 @@ http_parse_header(struct soap *soap, const char *key, const char *val)
#endif
strcpy(soap->endpoint, "http://");
strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8);
- soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
}
#ifndef WITH_LEANER
else if (!soap_tag_cmp(key, "Content-Type"))
@@ -5389,7 +5553,8 @@ http_parse_header(struct soap *soap, const char *key, const char *val)
if (action)
{ if (*action == '"')
{ soap->action = soap_strdup(soap, action + 1);
- soap->action[strlen(soap->action) - 1] = '\0';
+ if (*soap->action)
+ soap->action[strlen(soap->action) - 1] = '\0';
}
else
soap->action = soap_strdup(soap, action);
@@ -5398,6 +5563,8 @@ http_parse_header(struct soap *soap, const char *key, const char *val)
#endif
else if (!soap_tag_cmp(key, "Content-Length"))
{ soap->length = soap_strtoul(val, NULL, 10);
+ if (!soap->length)
+ soap->body = 0;
}
else if (!soap_tag_cmp(key, "Content-Encoding"))
{ if (!soap_tag_cmp(val, "deflate"))
@@ -5439,8 +5606,14 @@ http_parse_header(struct soap *soap, const char *key, const char *val)
soap->keep_alive = 0;
}
#ifndef WITH_LEAN
- else if (!soap_tag_cmp(key, "Authorization"))
- { if (!soap_tag_cmp(val, "Basic *"))
+ else if (!soap_tag_cmp(key, "Authorization") || !soap_tag_cmp(key, "Proxy-Authorization"))
+ {
+#ifdef WITH_NTLM
+ if (!soap_tag_cmp(val, "NTLM*"))
+ soap->ntlm_challenge = soap_strdup(soap, val + 4);
+ else
+#endif
+ if (!soap_tag_cmp(val, "Basic *"))
{ int n;
char *s;
soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n);
@@ -5472,7 +5645,8 @@ http_parse_header(struct soap *soap, const char *key, const char *val)
else if (!soap_tag_cmp(key, "SOAPAction"))
{ if (*val == '"')
{ soap->action = soap_strdup(soap, val + 1);
- soap->action[strlen(soap->action) - 1] = '\0';
+ if (*soap->action)
+ soap->action[strlen(soap->action) - 1] = '\0';
}
else
soap->action = soap_strdup(soap, val);
@@ -5555,24 +5729,28 @@ static const char*
soap_decode(char *buf, size_t len, const char *val, const char *sep)
{ const char *s;
char *t = buf;
+ size_t i = len;
for (s = val; *s; s++)
if (*s != ' ' && *s != '\t' && !strchr(sep, *s))
break;
- if (*s == '"')
- { s++;
- while (*s && *s != '"' && --len)
- *t++ = *s++;
- }
- else
- { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --len)
- { if (*s == '%')
- { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
- + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
- s += 3;
- }
- else
+ if (len > 0)
+ { if (*s == '"')
+ { s++;
+ while (*s && *s != '"' && --i)
*t++ = *s++;
}
+ else
+ { while (*s && !soap_blank((soap_wchar)*s) && !strchr(sep, *s) && --i)
+ { if (*s == '%' && s[1] && s[2])
+ { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4)
+ + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0');
+ s += 3;
+ }
+ else
+ *t++ = *s++;
+ }
+ }
+ buf[len - 1] = '\0'; /* appease */
}
*t = '\0';
while (*s && !strchr(sep, *s))
@@ -5617,8 +5795,8 @@ http_get(struct soap *soap)
#ifndef PALM_1
static int
http_405(struct soap *soap)
-{ return 405;
- (void)soap;
+{ (void)soap;
+ return 405;
}
#endif
#endif
@@ -5663,14 +5841,33 @@ http_post(struct soap *soap, const char *endpoint, const char *host, int port, c
if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)))
#endif
return SOAP_OK;
- if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
- return soap->error = SOAP_EOM; /* prevent overrun */
+ if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80
+ || strlen(host) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80)
+ return soap->error = SOAP_EOM; /* prevent overrun (note that 'host' and 'soap->host' are substrings of 'endpoint') */
if (soap->status == SOAP_CONNECT)
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
+#else
sprintf(soap->tmpbuf, "%s %s:%d HTTP/%s", s, soap->host, soap->port, soap->http_version);
+#endif
+ }
else if (soap->proxy_host && endpoint)
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %s HTTP/%s", s, endpoint, soap->http_version);
+#else
sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version);
+#endif
+ }
else
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
+#else
sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version);
+#endif
+ }
if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
return err;
#ifdef WITH_OPENSSL
@@ -5681,13 +5878,38 @@ http_post(struct soap *soap, const char *endpoint, const char *host, int port, c
{
#ifdef WITH_IPV6
if (*host != '[' && strchr(host, ':'))
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]:%d", host, port); /* RFC 2732 */
+#else
sprintf(soap->tmpbuf, "[%s]:%d", host, port); /* RFC 2732 */
+#endif
+ }
else
#endif
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s:%d", host, port);
+#else
sprintf(soap->tmpbuf, "%s:%d", host, port);
+#endif
+ }
}
else
- strcpy(soap->tmpbuf, host);
+ {
+#ifdef WITH_IPV6
+ if (*host != '[' && strchr(host, ':'))
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "[%s]", host); /* RFC 2732 */
+#else
+ sprintf(soap->tmpbuf, "[%s]", host); /* RFC 2732 */
+#endif
+ }
+ else
+#endif
+ strcpy(soap->tmpbuf, host);
+ }
if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)))
return err;
if ((err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.8")))
@@ -5703,34 +5925,51 @@ http_post(struct soap *soap, const char *endpoint, const char *host, int port, c
return err;
#endif
#ifndef WITH_LEAN
- if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
- {
#ifdef WITH_NTLM
- if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf))
+ if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf))
+ { if (*soap->ntlm_challenge)
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "NTLM %s", soap->ntlm_challenge);
+#else
sprintf(soap->tmpbuf, "NTLM %s", soap->ntlm_challenge);
- else
#endif
- { strcpy(soap->tmpbuf, "Basic ");
- sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
- soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
+ if (soap->proxy_host)
+ { if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
+ return err;
+ }
+ else if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
+ return err;
}
+ }
+ else
+ {
+#endif
+ if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761)
+ { strcpy(soap->tmpbuf, "Basic ");
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->userid, soap->passwd);
+#else
+ sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd);
+#endif
+ soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf)))
return err;
}
if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761)
- {
-#ifdef WITH_NTLM
- if (soap->ntlm_challenge && strlen(soap->ntlm_challenge) + 6 < sizeof(soap->tmpbuf))
- sprintf(soap->tmpbuf, "NTLM %s", soap->ntlm_challenge);
- else
+ { strcpy(soap->tmpbuf, "Basic ");
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf + 262, sizeof(soap->tmpbuf) - 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
+#else
+ sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
#endif
- { strcpy(soap->tmpbuf, "Basic ");
- sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd);
- soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
- }
+ soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262));
if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf)))
return err;
}
+#ifdef WITH_NTLM
+ }
+#endif
#endif
#ifdef WITH_COOKIES
#ifdef WITH_OPENSSL
@@ -5742,7 +5981,12 @@ http_post(struct soap *soap, const char *endpoint, const char *host, int port, c
#endif
#endif
if (action && soap->status != SOAP_GET && soap->status != SOAP_DEL)
- { sprintf(soap->tmpbuf, "\"%s\"", action && strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "\"%s\"", action);
+#else
+ sprintf(soap->tmpbuf, "\"%s\"", strlen(action) < sizeof(soap->tmpbuf) - 3 ? action : SOAP_STR_EOS);
+#endif
if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf)))
return err;
}
@@ -5792,68 +6036,69 @@ http_post_header(struct soap *soap, const char *key, const char *val)
static int
http_response(struct soap *soap, int status, size_t count)
{ register int err;
+ char http[10];
+ int code = status;
+ const char *line;
#ifdef WMW_RPM_IO
if (soap->rpmreqid)
httpOutputEnable(soap->rpmreqid);
#endif
- if (strlen(soap->http_version) > 4)
+ if (!soap->http_version || strlen(soap->http_version) > 4)
return soap->error = SOAP_EOM;
- if (!status || status == SOAP_HTML || status == SOAP_FILE)
- { const char *s;
- if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
- s = "200 OK";
- else
- s = "202 Accepted";
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s));
#ifdef WMW_RPM_IO
- if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
+ if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
#else
- if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */
+ if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application (socket) or CGI (stdin/out)? */
#endif
- { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
- if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
- return err;
- }
- else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI header */
- return err;
- }
- else if (status >= 200 && status < 600)
- { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status));
- if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
- return err;
-#ifndef WITH_LEAN
- if (status == 401)
- { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
- if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
- return err;
- }
- else if ((status >= 301 && status <= 303) || status == 307)
- { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
- return err;
- }
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(http, sizeof(http), "HTTP/%s", soap->http_version);
+#else
+ sprintf(http, "HTTP/%s", soap->http_version);
#endif
}
else
+ strcpy(http, "Status:");
+ if (!status || status == SOAP_HTML || status == SOAP_FILE)
+ { if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK))
+ code = 200;
+ else
+ code = 202;
+ }
+ else if (status < 200 || status >= 600)
{ const char *s = *soap_faultcode(soap);
if (status >= SOAP_GET_METHOD && status <= SOAP_HTTP_METHOD)
- s = "405 Method Not Allowed";
+ code = 405;
else if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender")))
- s = "400 Bad Request";
+ code = 400;
else
- s = "500 Internal Server Error";
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status));
-#ifdef WMW_RPM_IO
- if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */
+ code = 500;
+ }
+ line = http_error(soap, code);
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "HTTP Status = %d %s\n", code, line));
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%s %d %s", http, code, line);
#else
- if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */
+ sprintf(soap->tmpbuf, "%s %d %s", http, code, line);
#endif
- { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s);
- if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
- return err;
- }
- else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */
+ if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL)))
+ return err;
+#ifndef WITH_LEAN
+ if (status == 401)
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
+#else
+ sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm && strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14) ? soap->authrealm : "gSOAP Web Service");
+#endif
+ if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf)))
+ return err;
+ }
+ else if ((status >= 301 && status <= 303) || status == 307)
+ { if ((err = soap->fposthdr(soap, "Location", soap->endpoint)))
return err;
}
+#endif
if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.8"))
|| (err = soap_puthttphdr(soap, status, count)))
return err;
@@ -5901,18 +6146,26 @@ soap_response(struct soap *soap, int status)
}
#endif
-/******************************************************************************\
- *
- * HTTP Cookies
- *
-\******************************************************************************/
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_url(struct soap *soap, const char *s, const char *t)
+{ if (!t || (*t != '/' && *t != '?') || strlen(s) + strlen(t) >= sizeof(soap->msgbuf))
+ return s;
+ strcpy(soap->msgbuf, s);
+ strcat(soap->msgbuf, t);
+ return soap->msgbuf;
+}
+#endif
-#ifdef WITH_COOKIES
/******************************************************************************/
+#ifndef PALM_1
SOAP_FMAC1
size_t
SOAP_FMAC2
-soap_encode_cookie(const char *s, char *t, size_t len)
+soap_encode_url(const char *s, char *t, size_t len)
{ register int c;
register size_t n = len;
while ((c = *s++) && --n > 0)
@@ -5931,8 +6184,34 @@ soap_encode_cookie(const char *s, char *t, size_t len)
*t = '\0';
return len - n;
}
+#endif
/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+const char*
+SOAP_FMAC2
+soap_encode_url_string(struct soap *soap, const char *s)
+{ if (s)
+ { size_t n = 3*strlen(s)+1;
+ char *t = (char*)soap_malloc(soap, n);
+ if (t)
+ { soap_encode_url(s, t, n);
+ return t;
+ }
+ }
+ return SOAP_STR_EOS;
+}
+#endif
+
+/******************************************************************************\
+ *
+ * HTTP Cookies
+ *
+\******************************************************************************/
+
+#ifdef WITH_COOKIES
+/******************************************************************************/
SOAP_FMAC1
struct soap_cookie*
SOAP_FMAC2
@@ -5946,9 +6225,9 @@ soap_cookie(struct soap *soap, const char *name, const char *domain, const char
path = SOAP_STR_EOS;
else if (*path == '/')
path++;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain ? domain : "(null)", path ? path : "(null)"));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie='%s' domain='%s' path='%s'\n", name, domain ? domain : "(null)", path ? path : "(null)"));
for (p = soap->cookies; p; p = p->next)
- { 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));
+ { 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));
if (!strcmp(p->name, name)
&& p->domain
&& p->path
@@ -5975,7 +6254,7 @@ soap_set_cookie(struct soap *soap, const char *name, const char *value, const ch
else if (*path == '/')
path++;
q = soap_cookie(soap, name, domain, path);
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s=%s domain=%s path=%s\n", q ? SOAP_STR_EOS : "new ", name, value ? value : "(null)", domain ? domain : "(null)", path ? path : "(null)"));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s='%s' domain='%s' path='%s'\n", q ? SOAP_STR_EOS : "new ", name, value ? value : "(null)", domain ? domain : "(null)", path ? path : "(null)"));
if (!q)
{ if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie))))
{ if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1)))
@@ -6044,13 +6323,13 @@ soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const c
if (!domain)
domain = soap->cookie_domain;
if (!domain)
- { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name ? name : "(null)"));
+ { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie domain not set\n", name ? name : "(null)"));
return;
}
if (!path)
path = soap->cookie_path;
if (!path)
- { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name ? name : "(null)"));
+ { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie='%s': cookie path not set\n", name ? name : "(null)"));
return;
}
if (*path == '/')
@@ -6110,7 +6389,7 @@ int
SOAP_FMAC2
soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path)
{ struct soap_cookie *p;
- 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)"));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age=%ld: cookie='%s' domain='%s' path='%s'\n", expire, name, domain ? domain : "(null)", path ? path : "(null)"));
if ((p = soap_cookie(soap, name, domain, path)))
{ p->maxage = expire;
p->modified = 1;
@@ -6164,10 +6443,10 @@ soap_putsetcookies(struct soap *soap)
)
{ s = tmp;
if (p->name)
- s += soap_encode_cookie(p->name, s, tmp-s+4064);
+ s += soap_encode_url(p->name, s, tmp-s+4064);
if (p->value && *p->value)
{ *s++ = '=';
- s += soap_encode_cookie(p->value, s, tmp-s+4064);
+ s += soap_encode_url(p->value, s, tmp-s+4064);
}
if (p->domain && (int)strlen(p->domain) < tmp-s+4064)
{ strcpy(s, ";Domain=");
@@ -6192,15 +6471,25 @@ soap_putsetcookies(struct soap *soap)
s += strlen(s);
}
else
- s += soap_encode_cookie(t, s, tmp-s+4064);
+ s += soap_encode_url(t, s, tmp-s+4064);
}
}
if (p->version > 0 && s-tmp < 4060)
- { sprintf(s, ";Version=%u", p->version);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(s, 4096 - (s-tmp), ";Version=%u", p->version);
+#else
+ sprintf(s, ";Version=%u", p->version);
+#endif
s += strlen(s);
}
if (p->maxage >= 0 && s-tmp < 4060)
- { sprintf(s, ";Max-Age=%ld", p->maxage);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(s, 4096 - (s-tmp), ";Max-Age=%ld", p->maxage);
+#else
+ sprintf(s, ";Max-Age=%ld", p->maxage);
+#endif
s += strlen(s);
}
if (s-tmp < 4073
@@ -6231,7 +6520,7 @@ soap_putcookies(struct soap *soap, const char *domain, const char *path, int sec
return SOAP_OK;
s = tmp;
p = &soap->cookies;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain='%s' path='%s'\n", domain, path));
if (*path == '/')
path++;
while ((q = *p))
@@ -6277,45 +6566,60 @@ soap_putcookies(struct soap *soap, const char *domain, const char *path, int sec
&& (!q->path || !strncmp(q->path, path, strlen(q->path)))
&& (!q->secure || secure))
{ size_t n = 12;
- if (q->name)
- n += 3*strlen(q->name);
- if (q->value && *q->value)
- n += 3*strlen(q->value) + 1;
+ if (q->name)
+ n += 3*strlen(q->name);
+ if (q->value && *q->value)
+ n += 3*strlen(q->value) + 1;
if (q->path && *q->path)
- n += strlen(q->path) + 9;
- if (q->domain)
- n += strlen(q->domain) + 11;
- if (tmp - s + n > sizeof(tmp))
+ n += strlen(q->path) + 9;
+ if (q->domain)
+ n += strlen(q->domain) + 11;
+ if (tmp - s + n > sizeof(tmp))
{ if (s == tmp)
- return SOAP_OK; /* HTTP header size overflow */
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
+ return SOAP_OK; /* HTTP header size overflow */
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp));
if ((soap->error = soap->fposthdr(soap, "Cookie", tmp)))
return soap->error;
- s = tmp;
- }
- else if (s != tmp)
- { strcat(s, " ");
- s++;
- }
- if (q->version != version)
- { sprintf(s, "$Version=%u;", q->version);
+ s = tmp;
+ }
+ else if (s != tmp)
+ { strcat(s, " ");
+ s++;
+ }
+ if (q->version != version && s-tmp < 4060)
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(s, 4096 - (s-tmp), "$Version=%u;", q->version);
+#else
+ sprintf(s, "$Version=%u;", q->version);
+#endif
version = q->version;
s += strlen(s);
}
if (q->name)
- s += soap_encode_cookie(q->name, s, tmp+sizeof(tmp)-s-16);
+ s += soap_encode_url(q->name, s, tmp+sizeof(tmp)-s-16);
if (q->value && *q->value)
{ *s++ = '=';
- s += soap_encode_cookie(q->value, s, tmp+sizeof(tmp)-s-16);
+ s += soap_encode_url(q->value, s, tmp+sizeof(tmp)-s-16);
}
- if (q->path)
- { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
+ if (q->path && (s-tmp) + strlen(q->path) < 4060)
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(s, 4096 - (s-tmp), ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
+#else
+ sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path));
+#endif
s += strlen(s);
}
- if (q->domain)
- { sprintf(s, ";$Domain=\"%s\"", q->domain);
+ if (q->domain && (s-tmp) + strlen(q->domain) < 4060)
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(s, 4096 - (s-tmp), ";$Domain=\"%s\"", q->domain);
+#else
+ sprintf(s, ";$Domain=\"%s\"", q->domain);
+#endif
s += strlen(s);
- }
+ }
}
p = &q->next;
}
@@ -6452,7 +6756,7 @@ soap_getcookies(struct soap *soap, const char *val)
p->secure = 1;
else
{ if (p)
- { 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));
+ { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
{ q->version = p->version;
q->expire = p->expire;
@@ -6504,7 +6808,7 @@ soap_getcookies(struct soap *soap, const char *val)
}
}
if (p)
- { 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));
+ { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie='%s' value='%s' domain='%s' path='%s' expire=%ld secure=%d\n", p->name, p->value ? p->value : "(null)", p->domain ? p->domain : "(null)", p->path ? p->path : "(null)", p->expire, p->secure));
if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path)))
{ q->version = p->version;
q->expire = p->expire;
@@ -6694,6 +6998,7 @@ SOAP_FMAC2
soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type)
{ register int i;
struct soap_plist *pp;
+ (void)soap;
if (soap->version == 2)
soap->encoding = 1;
if (a)
@@ -6707,7 +7012,6 @@ soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n,
soap_set_embedded(soap, pp);
}
return i;
- (void)soap;
}
#endif
#endif
@@ -6745,6 +7049,7 @@ SOAP_FMAC2
soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp)
{ register size_t h;
register struct soap_plist *pp;
+ (void)n;
if (!soap->pblk || soap->pidx >= SOAP_PTRBLK)
{ register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk));
if (!pb)
@@ -6770,7 +7075,6 @@ soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a,
soap->pht[h] = pp;
pp->id = ++soap->idnum;
return pp->id;
- (void)n;
}
#endif
#endif
@@ -6840,8 +7144,6 @@ soap_begin_count(struct soap *soap)
soap->mode |= SOAP_IO_STORE;
}
#endif
- if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
- soap->mode |= SOAP_XML_TREE;
#ifndef WITH_LEANER
if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
soap->mode |= SOAP_ENC_MIME;
@@ -6863,13 +7165,13 @@ soap_begin_count(struct soap *soap)
soap->idnum = 0;
soap_clr_attr(soap);
soap_set_local_namespaces(soap);
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, (unsigned int)soap->mode, (unsigned long)soap->count));
#ifndef WITH_LEANER
soap->dime.count = 0; /* count # of attachments */
soap->dime.size = 0; /* accumulate total size of attachments */
if (soap->fprepareinitsend && (soap->mode & SOAP_IO) != SOAP_IO_STORE && (soap->error = soap->fprepareinitsend(soap)))
return soap->error;
#endif
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, (unsigned int)soap->mode, (unsigned long)soap->count));
return SOAP_OK;
}
#endif
@@ -6897,7 +7199,7 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_begin_send(struct soap *soap)
-{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n"));
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
soap_free_ns(soap);
soap->error = SOAP_OK;
soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME));
@@ -6928,8 +7230,6 @@ soap_begin_send(struct soap *soap)
return soap->error;
if (!(soap->mode & SOAP_IO_KEEPALIVE))
soap->keep_alive = 0;
- if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH))
- soap->mode |= SOAP_XML_TREE;
#ifndef WITH_LEANER
if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME))
{ soap->mode |= SOAP_ENC_MIME;
@@ -7036,7 +7336,7 @@ int
SOAP_FMAC2
soap_reference(struct soap *soap, const void *p, int t)
{ struct soap_plist *pp;
- if (!p || (soap->mode & SOAP_XML_TREE))
+ if (!p || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
return 1;
if (soap_pointer_lookup(soap, p, t, &pp))
{ if (pp->mark1 == 0)
@@ -7044,11 +7344,7 @@ soap_reference(struct soap *soap, const void *p, int t)
pp->mark2 = 2;
}
}
- else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp))
- { pp->mark1 = 0;
- pp->mark2 = 0;
- }
- else
+ else if (!soap_pointer_enter(soap, p, NULL, 0, t, &pp))
return 1;
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2));
return pp->mark1;
@@ -7063,12 +7359,10 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t)
-{ register int i;
- struct soap_plist *pp;
- if (!p || !a->__ptr)
+{ struct soap_plist *pp;
+ if (!p || !a->__ptr || (!soap->encodingStyle && !(soap->omode & (SOAP_ENC_DIME|SOAP_ENC_MIME|SOAP_ENC_MTOM|SOAP_XML_GRAPH))) || (soap->omode & SOAP_XML_TREE))
return 1;
- i = soap_array_pointer_lookup(soap, p, a, n, t, &pp);
- if (i)
+ if (soap_array_pointer_lookup(soap, p, a, n, t, &pp))
{ if (pp->mark1 == 0)
{ pp->mark1 = 2;
pp->mark2 = 2;
@@ -7076,10 +7370,6 @@ soap_array_reference(struct soap *soap, const void *p, const struct soap_array *
}
else if (!soap_pointer_enter(soap, p, a, n, t, &pp))
return 1;
- else
- { pp->mark1 = 0;
- pp->mark2 = 0;
- }
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));
return pp->mark1;
}
@@ -7094,10 +7384,10 @@ int
SOAP_FMAC2
soap_embedded_id(struct soap *soap, int id, const void *p, int t)
{ struct soap_plist *pp = NULL;
- if (soap->mode & SOAP_XML_TREE)
+ if (!id || (!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
return id;
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id));
- if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER)
+ if (soap->version == 1 && soap->part != SOAP_IN_HEADER)
{ if (id < 0)
{ id = soap_pointer_lookup(soap, p, t, &pp);
if (id)
@@ -7209,7 +7499,12 @@ soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const
if (id <= 0)
id = i;
if (!aid)
- { sprintf(soap->tmpbuf, soap->dime_id_format, id);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->dime_id_format, id);
+#else
+ sprintf(soap->tmpbuf, soap->dime_id_format, id);
+#endif
aid = soap_strdup(soap, soap->tmpbuf);
}
/* Add MTOM xop:Include element when necessary */
@@ -7325,8 +7620,8 @@ soap_enter(struct soap *soap, const char *id)
register struct soap_ilist *ip;
ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id));
if (ip)
- { h = soap_hash(id);
- strcpy((char*)ip->id, id);
+ { strcpy((char*)ip->id, id);
+ h = soap_hash(id); /* h = (HASH(id) % SOAP_IDHASH) so soap->iht[h] is safe */
ip->next = soap->iht[h];
soap->iht[h] = ip;
}
@@ -7619,6 +7914,22 @@ soap_delegate_deletion(struct soap *soap, struct soap *soap_to)
*q = (char*)soap_to->alist;
soap_to->alist = soap->alist;
soap->alist = NULL;
+#ifdef SOAP_MEM_DEBUG
+ cp = soap->clist;
+ while (cp)
+ { h = soap_hash_ptr(cp);
+ for (mp = &soap->mht[h]; *mp; mp = &(*mp)->next)
+ { if ((*mp)->ptr == cp)
+ { mq = *mp;
+ *mp = mq->next;
+ mq->next = soap_to->mht[h];
+ soap_to->mht[h] = mq;
+ break;
+ }
+ }
+ cp = cp->next;
+ }
+#endif
cp = soap_to->clist;
if (cp)
{ while (cp->next)
@@ -7950,7 +8261,17 @@ soap_end_send(struct soap *soap)
if (err)
return err;
#endif
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
+ return soap_end_send_flush(soap);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+int
+SOAP_FMAC2
+soap_end_send_flush(struct soap *soap)
+{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send mode=0x%x\n", soap->mode));
if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */
{ if (soap_flush(soap))
#ifdef WITH_ZLIB
@@ -8022,16 +8343,20 @@ soap_end_send(struct soap *soap)
#endif
for (p = soap_first_block(soap, NULL); p; p = soap_next_block(soap, NULL))
{ DBGMSG(SENT, p, soap_block_size(soap, NULL));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send %u bytes to socket=%d/fd=%d\n", (unsigned int)soap_block_size(soap, NULL), soap->socket, soap->sendfd));
if ((soap->error = soap->fsend(soap, p, soap_block_size(soap, NULL))))
{ soap_end_block(soap, NULL);
return soap->error;
}
}
soap_end_block(soap, NULL);
+ if (soap->fpreparefinalsend && (soap->error = soap->fpreparefinalsend(soap)))
+ return soap->error;
}
#ifndef WITH_LEANER
else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK)
{ DBGMSG(SENT, "\r\n0\r\n\r\n", 7);
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Send 7 bytes to socket=%d/fd=%d\n", soap->socket, soap->sendfd));
if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7)))
return soap->error;
}
@@ -8193,13 +8518,9 @@ soap_free_temp(struct soap *soap)
if (ns)
{ for (; ns->id; ns++)
{ if (ns->out)
- { if (soap->encodingStyle == ns->out)
- soap->encodingStyle = SOAP_STR_EOS;
- SOAP_FREE(soap, ns->out);
+ { SOAP_FREE(soap, ns->out);
ns->out = NULL;
}
- if (soap->encodingStyle == ns->ns)
- soap->encodingStyle = SOAP_STR_EOS;
}
SOAP_FREE(soap, soap->local_namespaces);
soap->local_namespaces = NULL;
@@ -8299,34 +8620,37 @@ soap_set_logfile(struct soap *soap, int i, const char *logfile)
#endif
/******************************************************************************/
-#ifdef SOAP_DEBUG
SOAP_FMAC1
void
SOAP_FMAC2
soap_set_recv_logfile(struct soap *soap, const char *logfile)
-{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
-}
+{
+#ifdef SOAP_DEBUG
+ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile);
#endif
+}
/******************************************************************************/
-#ifdef SOAP_DEBUG
SOAP_FMAC1
void
SOAP_FMAC2
soap_set_sent_logfile(struct soap *soap, const char *logfile)
-{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
-}
+{
+#ifdef SOAP_DEBUG
+ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile);
#endif
+}
/******************************************************************************/
-#ifdef SOAP_DEBUG
SOAP_FMAC1
void
SOAP_FMAC2
soap_set_test_logfile(struct soap *soap, const char *logfile)
-{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
-}
+{
+#ifdef SOAP_DEBUG
+ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile);
#endif
+}
/******************************************************************************/
#ifndef PALM_1
@@ -8382,12 +8706,10 @@ soap_copy_context(struct soap *copy, const struct soap *soap)
soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]);
soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]);
#endif
- copy->namespaces = NULL;
+ copy->namespaces = soap->local_namespaces;
copy->local_namespaces = NULL;
- if (soap->local_namespaces)
- soap_set_namespaces(copy, soap->local_namespaces);
- else
- soap_set_namespaces(copy, soap->namespaces);
+ soap_set_local_namespaces(copy); /* copy content of soap->local_namespaces */
+ copy->namespaces = soap->namespaces; /* point to shared read-only namespaces table */
#ifdef WITH_C_LOCALE
# ifdef WIN32
copy->c_locale = _create_locale(LC_ALL, "C");
@@ -8455,6 +8777,7 @@ soap_copy_stream(struct soap *copy, struct soap *soap)
{ struct soap_attribute *tp = NULL, *tq;
if (copy == soap)
return;
+ copy->header = soap->header;
copy->mode = soap->mode;
copy->imode = soap->imode;
copy->omode = soap->omode;
@@ -8524,6 +8847,7 @@ soap_copy_stream(struct soap *copy, struct soap *soap)
/* copy XML parser state */
soap_free_ns(copy);
soap_set_local_namespaces(copy);
+ copy->version = soap->version;
if (soap->nlist && soap->local_namespaces)
{ register struct soap_nlist *np = NULL, *nq;
/* copy reversed nlist */
@@ -8616,6 +8940,16 @@ soap_free_stream(struct soap *soap)
SOAP_FMAC1
void
SOAP_FMAC2
+soap_initialize(struct soap *soap)
+{ soap_versioning(soap_init)(soap, SOAP_IO_DEFAULT, SOAP_IO_DEFAULT);
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
+void
+SOAP_FMAC2
soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
{ size_t i;
soap->state = SOAP_INIT;
@@ -8667,8 +9001,8 @@ soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
soap->fconnect = NULL;
soap->fdisconnect = NULL;
#ifndef WITH_NOIO
- soap->ipv6_multicast_if = 0;
- soap->ipv4_multicast_if = NULL;
+ soap->ipv6_multicast_if = 0; /* in_addr_t value */
+ soap->ipv4_multicast_if = NULL; /* points to struct in_addr or in_addr_t */
soap->ipv4_multicast_ttl = 0; /* 0: use default */
#ifndef WITH_IPV6
soap->fresolve = tcp_gethost;
@@ -8746,7 +9080,7 @@ soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
soap->labbuf = NULL;
soap->lablen = 0;
soap->labidx = 0;
- soap->encodingStyle = SOAP_STR_EOS;
+ soap->encodingStyle = NULL;
#ifndef WITH_NONAMESPACES
soap->namespaces = namespaces;
#else
@@ -8835,6 +9169,7 @@ soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
soap->session = NULL;
soap->ssl_flags = SOAP_SSL_DEFAULT;
soap->keyfile = NULL;
+ soap->keyid = NULL;
soap->password = NULL;
soap->cafile = NULL;
soap->capath = NULL;
@@ -8853,6 +9188,7 @@ soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)
soap->session = NULL;
soap->ssl_flags = SOAP_SSL_DEFAULT;
soap->keyfile = NULL;
+ soap->keyid = NULL;
soap->password = NULL;
soap->cafile = NULL;
soap->capath = NULL;
@@ -8926,6 +9262,7 @@ soap_begin(struct soap *soap)
soap->idnum = 0;
soap->level = 0;
soap->endpoint[0] = '\0';
+ soap->encodingStyle = SOAP_STR_EOS;
#ifndef WITH_LEANER
soap->dime.chunksize = 0;
soap->dime.buflen = 0;
@@ -8962,6 +9299,27 @@ soap_end(struct soap *soap)
/******************************************************************************/
#ifndef PALM_1
SOAP_FMAC1
+void
+SOAP_FMAC2
+soap_set_version(struct soap *soap, short version)
+{ soap_set_local_namespaces(soap);
+ if (soap->version != version)
+ { if (version == 1)
+ { soap->local_namespaces[0].ns = soap_env1;
+ soap->local_namespaces[1].ns = soap_enc1;
+ }
+ else if (version == 2)
+ { soap->local_namespaces[0].ns = soap_env2;
+ soap->local_namespaces[1].ns = soap_enc2;
+ }
+ soap->version = version;
+ }
+}
+#endif
+
+/******************************************************************************/
+#ifndef PALM_1
+SOAP_FMAC1
int
SOAP_FMAC2
soap_set_namespaces(struct soap *soap, const struct Namespace *p)
@@ -9034,7 +9392,7 @@ soap_set_local_namespaces(struct soap *soap)
if (ns2[0].ns)
{ if (!strcmp(ns2[0].ns, soap_env1))
soap->version = 1;
- else
+ else if (!strcmp(ns2[0].ns, soap_env2))
soap->version = 2;
}
soap->local_namespaces = ns2;
@@ -9145,11 +9503,14 @@ soap_utilize_ns(struct soap *soap, const char *tag)
size_t n = 0;
const char *t = strchr(tag, ':');
if (t)
- n = t - tag;
+ { n = t - tag;
+ if (n >= sizeof(soap->tmpbuf))
+ n = sizeof(soap->tmpbuf) - 1;
+ }
np = soap_lookup_ns(soap, tag, n);
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag));
if (np)
- { if (np->index == 0)
+ { if (np->index <= 0)
soap_push_ns(soap, np->id, np->ns, 1);
}
else if (strncmp(tag, "xml", 3))
@@ -9191,8 +9552,8 @@ soap_element(struct soap *soap, const char *tag, int id, const char *type)
for (np = soap->nlist; np; np = np->next)
{ if (np->index == 2)
{ struct soap_nlist *np1 = soap_push_ns(soap, np->id, np->ns, 1);
- if (np1)
- np1->index = 0;
+ if (np1)
+ np1->index = 0;
}
}
soap->evlev = soap->level;
@@ -9268,17 +9629,34 @@ soap_element(struct soap *soap, const char *tag, int id, const char *type)
}
#endif
if (!soap->ns)
- { struct Namespace *ns;
+ { struct Namespace *ns = soap->local_namespaces;
int k = -1;
+ if (ns)
+ {
#ifndef WITH_LEAN
- if ((soap->mode & SOAP_XML_DEFAULTNS))
- k = 4; /* only produce the first four required entries */
+ if ((soap->mode & SOAP_XML_DEFAULTNS))
+ { if (soap->version)
+ k = 4; /* first four required entries */
+ else if (!(soap->mode & SOAP_XML_NOTYPE) || (soap->mode & SOAP_XML_NIL))
+ { ns += 2;
+ k = 2; /* next two entries */
+ }
+ else
+ k = 0; /* no entries */
+ }
#endif
- for (ns = soap->local_namespaces; ns && ns->id && k; ns++, k--)
- { if (*ns->id && (ns->out || ns->ns))
- { sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
- if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
- return soap->error;
+ while (k-- && ns->id)
+ { if (*ns->id && (ns->out || ns->ns))
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", ns->id);
+#else
+ sprintf(soap->tmpbuf, "xmlns:%s", ns->id);
+#endif
+ if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns))
+ return soap->error;
+ }
+ ns++;
}
}
}
@@ -9288,8 +9666,17 @@ soap_element(struct soap *soap, const char *tag, int id, const char *type)
soap_utilize_ns(soap, tag);
#endif
if (id > 0)
- { sprintf(soap->tmpbuf, "_%d", id);
- if (soap_attribute(soap, "id", soap->tmpbuf))
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "_%d", id);
+#else
+ sprintf(soap->tmpbuf, "_%d", id);
+#endif
+ if (soap->version == 2)
+ { if (soap_attribute(soap, "SOAP-ENC:id", soap->tmpbuf))
+ return soap->error;
+ }
+ else if (soap_attribute(soap, "id", soap->tmpbuf))
return soap->error;
}
if (type && *type && !(soap->mode & SOAP_XML_NOTYPE) && soap->part != SOAP_IN_HEADER)
@@ -9312,9 +9699,20 @@ soap_element(struct soap *soap, const char *tag, int id, const char *type)
}
if (soap->null && soap->position > 0)
{ register int i;
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf) - 1, "[%d", soap->positions[0]);
+#else
sprintf(soap->tmpbuf, "[%d", soap->positions[0]);
+#endif
for (i = 1; i < soap->position; i++)
- sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]);
+ { register size_t l = strlen(soap->tmpbuf);
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf)-l-1, ",%d", soap->positions[i]);
+#else
+ if (l + 13 < sizeof(soap->tmpbuf))
+ sprintf(soap->tmpbuf + l, ",%d", soap->positions[i]);
+#endif
+ }
strcat(soap->tmpbuf, "]");
if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf))
return soap->error;
@@ -9329,7 +9727,7 @@ soap_element(struct soap *soap, const char *tag, int id, const char *type)
soap->mustUnderstand = 0;
}
if (soap->encoding)
- { if (soap->encodingStyle && soap->local_namespaces)
+ { if (soap->encodingStyle && soap->local_namespaces && soap->local_namespaces[0].id && soap->local_namespaces[1].id)
{ if (!*soap->encodingStyle)
{ if (soap->local_namespaces[1].out)
soap->encodingStyle = soap->local_namespaces[1].out;
@@ -9339,6 +9737,8 @@ soap_element(struct soap *soap, const char *tag, int id, const char *type)
if (soap->encodingStyle && soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle))
return soap->error;
}
+ else
+ soap->encodingStyle = NULL;
soap->encoding = 0;
}
soap->null = 0;
@@ -9495,13 +9895,19 @@ soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *typ
if (soap->version == 2)
{ const char *s;
s = soap_strrchr(type, '[');
- if ((size_t)(s - type) < sizeof(soap->tmpbuf))
+ if (s && (size_t)(s - type) < sizeof(soap->tmpbuf))
{ strncpy(soap->tmpbuf, type, s - type);
soap->tmpbuf[s - type] = '\0';
if (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))
return soap->error;
- if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1)))
- return soap->error;
+ s++;
+ if (*s)
+ { strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
+ soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
+ soap->tmpbuf[strlen(soap->tmpbuf) - 1] = '\0';
+ if (soap_attribute(soap, "SOAP-ENC:arraySize", soap->tmpbuf))
+ return soap->error;
+ }
}
}
else
@@ -9534,7 +9940,16 @@ soap_element_start_end_out(struct soap *soap, const char *tag)
}
for (np = soap->nlist; np; np = np->next)
{ if (np->index == 1 && np->ns)
- { sprintf(soap->tmpbuf, *(np->id) ? "xmlns:%s" : "xmlns", np->id);
+ { if (*(np->id))
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:%s", np->id);
+#else
+ sprintf(soap->tmpbuf, "xmlns:%s", np->id);
+#endif
+ }
+ else
+ strcpy(soap->tmpbuf, "xmlns");
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns));
soap_set_attr(soap, soap->tmpbuf, np->ns, 1);
np->index = 2;
@@ -9658,13 +10073,19 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_element_ref(struct soap *soap, const char *tag, int id, int href)
-{ register int n = 0;
- const char *s = "href";
- if (soap->version == 2)
- { s = "SOAP-ENC:ref";
- n = 1;
+{ register const char *s = "ref";
+ register int n = 1;
+ if (soap->version == 1)
+ { s = "href";
+ n = 0;
}
+ else if (soap->version == 2)
+ s = "SOAP-ENC:ref";
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->href, sizeof(soap->href), "#_%d", href);
+#else
sprintf(soap->href, "#_%d", href);
+#endif
return soap_element_href(soap, tag, id, s, soap->href + n);
}
#endif
@@ -9714,7 +10135,7 @@ int
SOAP_FMAC2
soap_element_nil(struct soap *soap, const char *tag)
{ if (soap_element(soap, tag, -1, NULL)
- || soap_attribute(soap, "xsi:nil", "true"))
+ || ((soap->mode & SOAP_XML_NIL) && soap_attribute(soap, "xsi:nil", "true")))
return soap->error;
return soap_element_start_end_out(soap, tag);
}
@@ -9727,11 +10148,11 @@ int
SOAP_FMAC2
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)
{ if (!p)
- { soap_element_null(soap, tag, id, type);
+ { soap->error = soap_element_null(soap, tag, id, type);
return -1;
}
#ifndef WITH_NOIDREF
- if (soap->mode & SOAP_XML_TREE)
+ if ((!soap->encodingStyle && !(soap->omode & SOAP_XML_GRAPH)) || (soap->omode & SOAP_XML_TREE))
return 0;
if (id < 0)
{ struct soap_plist *pp;
@@ -9988,7 +10409,7 @@ soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
if ((soap->mode & SOAP_XML_CANONICAL))
{ struct soap_attribute **tpp = &soap->attributes;
const char *s = strchr(name, ':');
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name))
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name));
if (!strncmp(name, "xmlns", 5))
{ for (; *tpp; tpp = &(*tpp)->next)
if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0)
@@ -10054,7 +10475,7 @@ soap_set_attr(struct soap *soap, const char *name, const char *value, int flag)
if (!strcmp(name, "wsu:Id"))
{ soap->event = SOAP_SEC_BEGIN;
strncpy(soap->id, value, sizeof(soap->id));
- soap->id[sizeof(soap->id)-1] = '\0';
+ soap->id[sizeof(soap->id) - 1] = '\0';
}
#endif
}
@@ -10139,7 +10560,9 @@ soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d)
}
default:
if ((int)c == EOF)
+ { *s = '\0';
return soap->error = SOAP_CHK_EOF;
+ }
*s++ = (char)c;
}
}
@@ -10169,12 +10592,12 @@ SOAP_FMAC2
soap_append_lab(struct soap *soap, const char *s, size_t n)
{ if (soap->labidx + n >= soap->lablen)
{ register char *t = soap->labbuf;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, size=%lu\n", (unsigned long)soap->lablen));
if (soap->lablen == 0)
soap->lablen = SOAP_LABLEN;
while (soap->labidx + n >= soap->lablen)
soap->lablen <<= 1;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New look-aside buffer size=%lu\n", (unsigned long)soap->lablen));
soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen);
if (!soap->labbuf)
{ if (t)
@@ -10271,7 +10694,7 @@ soap_peek_element(struct soap *soap)
{ *soap->tag = '\0';
if ((int)c == EOF)
return soap->error = SOAP_CHK_EOF;
- soap_unget(soap, c > 0 ? c | 0x80000000 : c);
+ soap_unget(soap, c);
#ifdef WITH_DOM
/* whitespace leading to end tag is significant for DOM */
if ((soap->mode & SOAP_XML_DOM) && soap->dom)
@@ -10283,18 +10706,18 @@ soap_peek_element(struct soap *soap)
#endif
return soap->error = SOAP_NO_TAG;
}
- s = soap->tag;
do c = soap_get1(soap);
while (soap_blank(c));
+ s = soap->tag;
i = sizeof(soap->tag);
while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF)
{ if (--i > 0)
*s++ = (char)c;
c = soap_get1(soap);
}
+ *s = '\0';
while (soap_blank(c))
c = soap_get1(soap);
- *s = '\0';
#ifdef WITH_DOM
if (soap->mode & SOAP_XML_DOM)
{ register struct soap_dom_element *elt;
@@ -10503,27 +10926,35 @@ soap_peek_element(struct soap *soap)
{
#ifndef WITH_NOIDREF
if (!strcmp(tp->name, "id"))
- { if ((soap->version > 0 && !(soap->mode & SOAP_XML_TREE))
+ { if ((soap->version > 0 && !(soap->imode & SOAP_XML_TREE))
|| (soap->mode & SOAP_XML_GRAPH))
{ *soap->id = '#';
strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
- soap->id[sizeof(soap->id)-1] = '\0';
+ soap->id[sizeof(soap->id) - 1] = '\0';
}
}
else if (!strcmp(tp->name, "href"))
- { if (soap->version == 1
+ { if ((soap->version == 1 && !(soap->imode & SOAP_XML_TREE))
|| (soap->mode & SOAP_XML_GRAPH)
|| (soap->mode & SOAP_ENC_MTOM)
|| (soap->mode & SOAP_ENC_DIME))
{ strncpy(soap->href, tp->value, sizeof(soap->href) - 1);
- soap->href[sizeof(soap->href)-1] = '\0';
+ soap->href[sizeof(soap->href) - 1] = '\0';
+ }
+ }
+ else if (!strcmp(tp->name, "ref"))
+ { if ((soap->version == 2 && !(soap->imode & SOAP_XML_TREE))
+ || (soap->mode & SOAP_XML_GRAPH))
+ { *soap->href = '#';
+ strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
+ soap->href[sizeof(soap->href) - 1] = '\0';
}
}
else
#endif
if (!soap_match_tag(soap, tp->name, "xsi:type"))
{ strncpy(soap->type, tp->value, sizeof(soap->type) - 1);
- soap->type[sizeof(soap->type)-1] = '\0';
+ soap->type[sizeof(soap->type) - 1] = '\0';
}
else if ((!soap_match_tag(soap, tp->name, "xsi:null")
|| !soap_match_tag(soap, tp->name, "xsi:nil"))
@@ -10537,12 +10968,12 @@ soap_peek_element(struct soap *soap)
if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType))
{ strncpy(soap->arrayType, tp->value, s - tp->value);
soap->arrayType[s - tp->value] = '\0';
- strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1);
+ strncpy(soap->arraySize, s, sizeof(soap->arraySize));
}
else
- strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1);
- soap->arraySize[sizeof(soap->arrayType)-1] = '\0';
- soap->arrayType[sizeof(soap->arrayType)-1] = '\0';
+ strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType));
+ soap->arraySize[sizeof(soap->arraySize) - 1] = '\0';
+ soap->arrayType[sizeof(soap->arrayType) - 1] = '\0';
}
else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset"))
strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset));
@@ -10562,11 +10993,15 @@ soap_peek_element(struct soap *soap)
else if (soap->version == 2)
{
#ifndef WITH_NOIDREF
- if (!strcmp(tp->name, "ref")
- || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
+ if (!soap_match_tag(soap, tp->name, "SOAP-ENC:id"))
+ { *soap->id = '#';
+ strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2);
+ soap->id[sizeof(soap->id) - 1] = '\0';
+ }
+ else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:ref"))
{ *soap->href = '#';
- strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2);
- soap->href[sizeof(soap->href)-1] = '\0';
+ strncpy(soap->href + (*tp->value != '#'), tp->value, sizeof(soap->href) - 2);
+ soap->href[sizeof(soap->href) - 1] = '\0';
}
else
#endif
@@ -10694,7 +11129,7 @@ soap_string_out(struct soap *soap, const char *s, int flag)
{ wchar_t wc;
register int m = mbtowc(&wc, t - 1, MB_CUR_MAX);
if (m > 0 && !((soap_wchar)wc == c && m == 1 && c < 0x80))
- { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc))
+ { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned long)wc))
return soap->error;
s = t += m - 1;
continue;
@@ -10740,8 +11175,8 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String content includes tag '%s' and attributes\n", soap->tag));
t = soap->tmpbuf;
*t = '<';
- t[sizeof(soap->tmpbuf)-1] = '\0';
strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
+ t[sizeof(soap->tmpbuf) - 1] = '\0';
t += strlen(t);
for (tp = soap->attributes; tp; tp = tp->next)
{ if (tp->visible)
@@ -10810,7 +11245,7 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
{ soap_unget(soap, c);
c = soap_getutf8(soap);
}
- if ((c & 0x7FFFFFFF) >= 0x80 && (soap->mode & SOAP_C_UTFSTRING))
+ if ((c & 0x7FFFFFFF) >= 0x80 && (!flag || (soap->mode & SOAP_C_UTFSTRING)))
{ c &= 0x7FFFFFFF;
t = buf;
if (c < 0x0800)
@@ -10868,7 +11303,7 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
case 5:
if (c == '>')
state = 0;
- else
+ else if (c != ']')
state = 1;
*s++ = (char)c;
continue;
@@ -10883,7 +11318,7 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
case 7:
if (c == '>')
state = 0;
- else
+ else if (c != '-')
state = 2;
*s++ = (char)c;
continue;
@@ -10891,7 +11326,7 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
case 8:
if (c == '>')
state = 0;
- else
+ else if (c != '?')
state = 3;
*s++ = (char)c;
continue;
@@ -11039,7 +11474,12 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
m--;
continue;
}
- if (soap->mode & SOAP_C_UTFSTRING)
+#ifndef WITH_CDATA
+ if (!flag)
+ c = soap_getchar(soap);
+ else
+#endif
+ if ((soap->mode & SOAP_C_UTFSTRING))
{ if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP)
{ c &= 0x7FFFFFFF;
t = buf;
@@ -11100,9 +11540,16 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
break;
case '/':
if (n > 0)
- { c = soap_get(soap);
- if (c == SOAP_GT)
- n--;
+ { if (!flag)
+ { c = soap_getchar(soap);
+ if (c == '>')
+ n--;
+ }
+ else
+ { c = soap_get(soap);
+ if (c == SOAP_GT)
+ n--;
+ }
soap_unget(soap, c);
}
*s++ = '/';
@@ -11155,6 +11602,25 @@ soap_string_in(struct soap *soap, int flag, long minlen, long maxlen)
default:
if ((int)c == EOF)
goto end;
+#ifndef WITH_CDATA
+ if (c == '<' && !flag)
+ { if (f && n == 0)
+ goto end;
+ c = soap_getchar(soap);
+ soap_unget(soap, c);
+ if (c == '/')
+ { c = SOAP_TT;
+ if (n == 0)
+ goto end;
+ n--;
+ }
+ else
+ n++;
+ *s++ = '<';
+ break;
+ }
+ else
+#endif
#ifndef WITH_LEANER
#ifdef HAVE_WCTOMB
if (soap->mode & SOAP_C_MBSTRING)
@@ -11188,7 +11654,7 @@ end:
#ifdef WITH_FAST
t = soap_strdup(soap, soap->labbuf);
#else
- soap_size_block(soap, NULL, i+1);
+ soap_size_block(soap, NULL, i + 1);
t = soap_save_block(soap, NULL, 0);
#endif
if (l < minlen)
@@ -11275,11 +11741,12 @@ soap_wstring_out(struct soap *soap, const wchar_t *s, int flag)
if (soap_send_raw(soap, &tmp, 1))
return soap->error;
}
- else /* check UTF16 encoding when wchar_t is too small to hold UCS */
- { if (sizeof(wchar_t) < 4 && (c & 0xD800) == 0xD800)
- { /* http://unicode.org/faq/utf_bom.html#utf16-2 */
- if ((*s & 0xD800) == 0xD800)
- c = (c << 10) + *s++ + 0x10000 - (0xD800 << 10) - 0xDC00;
+ else
+ { /* check for UTF16 encoding when wchar_t is too small to hold UCS */
+ if (sizeof(wchar_t) < 4 && (c & 0xFC00) == 0xD800)
+ { register soap_wchar d = *s++;
+ if ((d & 0xFC00) == 0xDC00)
+ c = ((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000;
else
c = 0xFFFD; /* Malformed */
}
@@ -11316,8 +11783,8 @@ soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
struct soap_attribute *tp;
t = soap->tmpbuf;
*t = '<';
- t[sizeof(soap->tmpbuf)-1] = '\0';
strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2);
+ t[sizeof(soap->tmpbuf) - 1] = '\0';
t += strlen(t);
for (tp = soap->attributes; tp; tp = tp->next)
{ if (tp->visible)
@@ -11422,9 +11889,9 @@ soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen)
default:
if ((int)c == EOF)
goto end;
+ /* use UTF16 encoding when wchar_t is too small to hold UCS */
if (sizeof(wchar_t) < 4 && c > 0xFFFF)
- { soap_wchar c1, c2;
- /* http://unicode.org/faq/utf_bom.html#utf16-2 */
+ { register soap_wchar c1, c2;
c1 = 0xD800 - (0x10000 >> 10) + (c >> 10);
c2 = 0xDC00 + (c & 0x3FF);
c = c1;
@@ -11552,7 +12019,12 @@ SOAP_FMAC1
const char*
SOAP_FMAC2
soap_long2s(struct soap *soap, long n)
-{ sprintf(soap->tmpbuf, "%ld", n);
+{
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%ld", n);
+#else
+ sprintf(soap->tmpbuf, "%ld", n);
+#endif
return soap->tmpbuf;
}
#endif
@@ -11635,7 +12107,12 @@ SOAP_FMAC1
const char*
SOAP_FMAC2
soap_LONG642s(struct soap *soap, LONG64 n)
-{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
+{
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_LONG_FORMAT, n);
+#else
+ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n);
+#endif
return soap->tmpbuf;
}
#endif
@@ -11881,16 +12358,19 @@ soap_float2s(struct soap *soap, float n)
return "INF";
if (soap_isninff(n))
return "-INF";
- s = soap->tmpbuf;
#if defined(HAVE_SPRINTF_L)
# ifdef WIN32
- _sprintf_s_l(s, _countof(soap->tmpbuf), soap->float_format, soap->c_locale, n);
+ _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->float_format, soap->c_locale, n);
# else
- sprintf_l(s, soap->c_locale, soap->float_format, n);
+ sprintf_l(soap->tmpbuf, soap->c_locale, soap->float_format, n);
# endif
#else
- sprintf(s, soap->float_format, n);
- s = strchr(s, ','); /* convert decimal comma to DP */
+# ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->float_format, n);
+# else
+ sprintf(soap->tmpbuf, soap->float_format, n);
+# endif
+ s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
if (s)
*s = '.';
#endif
@@ -11954,10 +12434,10 @@ soap_s2float(struct soap *soap, const char *s, float *p)
#endif
{
#if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
- if (sscanf_l(s, soap->c_locale, "%g", p) != 1)
+ if (sscanf_l(s, soap->c_locale, "%f", p) != 1)
soap->error = SOAP_TYPE;
#elif defined(HAVE_SSCANF)
- if (sscanf(s, "%g", p) != 1)
+ if (sscanf(s, "%f", p) != 1)
soap->error = SOAP_TYPE;
#else
soap->error = SOAP_TYPE;
@@ -12035,16 +12515,19 @@ soap_double2s(struct soap *soap, double n)
return "INF";
if (soap_isninfd(n))
return "-INF";
- s = soap->tmpbuf;
#if defined(HAVE_SPRINTF_L)
# ifdef WIN32
- _sprintf_s_l(s, _countof(soap->tmpbuf), soap->double_format, soap->c_locale, n);
+ _sprintf_s_l(soap->tmpbuf, _countof(soap->tmpbuf), soap->double_format, soap->c_locale, n);
# else
- sprintf_l(s, soap->c_locale, soap->double_format, n);
+ sprintf_l(soap->tmpbuf, soap->c_locale, soap->double_format, n);
# endif
#else
- sprintf(s, soap->double_format, n);
- s = strchr(s, ','); /* convert decimal comma to DP */
+# ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), soap->double_format, n);
+#else
+ sprintf(soap->tmpbuf, soap->double_format, n);
+#endif
+ s = strchr(soap->tmpbuf, ','); /* convert decimal comma to DP */
if (s)
*s = '.';
#endif
@@ -12099,10 +12582,10 @@ soap_s2double(struct soap *soap, const char *s, double *p)
#endif
{
#if defined(HAVE_SSCANF_L) && !defined(HAVE_STRTOF_L) && !defined(HAVE_STRTOD_L)
- if (sscanf_l(s, soap->c_locale, "%lg", p) != 1)
+ if (sscanf_l(s, soap->c_locale, "%lf", p) != 1)
soap->error = SOAP_TYPE;
#elif defined(HAVE_SSCANF)
- if (sscanf(s, "%lg", p) != 1)
+ if (sscanf(s, "%lf", p) != 1)
soap->error = SOAP_TYPE;
#else
soap->error = SOAP_TYPE;
@@ -12370,7 +12853,12 @@ SOAP_FMAC1
const char*
SOAP_FMAC2
soap_unsignedLong2s(struct soap *soap, unsigned long n)
-{ sprintf(soap->tmpbuf, "%lu", n);
+{
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", n);
+#else
+ sprintf(soap->tmpbuf, "%lu", n);
+#endif
return soap->tmpbuf;
}
#endif
@@ -12453,7 +12941,12 @@ SOAP_FMAC1
const char*
SOAP_FMAC2
soap_ULONG642s(struct soap *soap, ULONG64 n)
-{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
+{
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), SOAP_ULONG_FORMAT, n);
+#else
+ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n);
+#endif
return soap->tmpbuf;
}
#endif
@@ -12590,8 +13083,8 @@ soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxle
while (s[n] && !soap_blank((soap_wchar)s[n]))
n++;
np = soap->nlist;
- /* if there is no namespace stack, or prefix is "xml" then copy string */
- if (!np || !strncmp(s, "xml:", 4))
+ /* if there is no namespace stack, or prefix is "#" or "xml" then copy string */
+ if (!np || *s == '#' || !strncmp(s, "xml:", 4))
{ soap_append_lab(soap, s, n);
}
else /* we normalize the QName by replacing its prefix */
@@ -12628,7 +13121,7 @@ soap_s2QName(struct soap *soap, const char *s, char **t, long minlen, long maxle
soap_append_lab(soap, "\"", 1);
}
else
- { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns ? np->ns : SOAP_STR_EOS));
+ { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI='%s')\n", s, np->index, np->ns ? np->ns : SOAP_STR_EOS));
return soap->error = SOAP_NAMESPACE;
}
}
@@ -12676,11 +13169,19 @@ soap_QName2s(struct soap *soap, const char *s)
n++;
/* normal prefix: pass string as is */
if (*s != '"')
- { soap_append_lab(soap, s, n);
+ {
#ifndef WITH_LEAN
if ((soap->mode & SOAP_XML_CANONICAL))
soap_utilize_ns(soap, s);
+ if ((soap->mode & SOAP_XML_DEFAULTNS))
+ { const char *r = strchr(s, ':');
+ if (r && soap->nlist && !strncmp(soap->nlist->id, s, r-s) && !soap->nlist->id[r-s])
+ { n -= r-s + 1;
+ s = r + 1;
+ }
+ }
#endif
+ soap_append_lab(soap, s, n);
}
else /* URL-based string prefix */
{ const char *q;
@@ -12700,12 +13201,22 @@ soap_QName2s(struct soap *soap, const char *s)
}
/* URL is in the namespace table? */
if (p && p->id)
- { soap_append_lab(soap, p->id, strlen(p->id));
+ { const char *r = p->id;
+#ifndef WITH_LEAN
+ if ((soap->mode & SOAP_XML_DEFAULTNS) && soap->nlist && !strcmp(soap->nlist->id, r))
+ q++;
+ else
+#endif
+ soap_append_lab(soap, r, strlen(r));
}
else /* not in namespace table: create xmlns binding */
{ char *r = soap_strdup(soap, s);
r[q-s] = '\0';
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "xmlns:_%d", soap->idnum++);
+#else
sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++);
+#endif
soap_set_attr(soap, soap->tmpbuf, r, 1);
soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6));
}
@@ -13004,6 +13515,20 @@ soap_dateTime2s(struct soap *soap, time_t n)
#elif defined(HAVE_GMTIME)
if ((pT = gmtime(&n)))
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT);
+#elif defined(HAVE_TM_GMTOFF) || defined(HAVE_STRUCT_TM_TM_GMTOFF) || defined(HAVE_STRUCT_TM___TM_GMTOFF)
+#if defined(HAVE_LOCALTIME_R)
+ if (localtime_r(&n, pT))
+ { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
+ memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
+ soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
+ }
+#else
+ if ((pT = localtime(&n)))
+ { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S%z", pT);
+ memmove(soap->tmpbuf + 23, soap->tmpbuf + 22, 3); /* 2000-03-01T02:00:00+0300 */
+ soap->tmpbuf[22] = ':'; /* 2000-03-01T02:00:00+03:00 */
+ }
+#endif
#elif defined(HAVE_GETTIMEOFDAY)
struct timezone tz;
memset((void*)&tz, 0, sizeof(tz));
@@ -13012,14 +13537,22 @@ soap_dateTime2s(struct soap *soap, time_t n)
{ struct timeval tv;
gettimeofday(&tv, &tz);
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#else
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#endif
}
#else
if ((pT = localtime(&n)))
{ struct timeval tv;
gettimeofday(&tv, &tz);
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#else
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60);
+#endif
}
#endif
#elif defined(HAVE_FTIME)
@@ -13034,7 +13567,11 @@ soap_dateTime2s(struct soap *soap, time_t n)
ftime(&t);
#endif
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#else
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#endif
}
#else
if ((pT = localtime(&n)))
@@ -13045,7 +13582,11 @@ soap_dateTime2s(struct soap *soap, time_t n)
ftime(&t);
#endif
strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT);
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf + strlen(soap->tmpbuf), sizeof(soap->tmpbuf) - strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#else
sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60);
+#endif
}
#endif
#elif defined(HAVE_LOCALTIME_R)
@@ -13189,8 +13730,11 @@ soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *t
const char *t = NULL;
if (tag && *tag != '-')
{ if (soap->local_namespaces && (t = strchr(tag, ':')))
- { strncpy(soap->tmpbuf, tag, t-tag);
- soap->tmpbuf[t-tag] = '\0';
+ { size_t n = t - tag;
+ if (n >= sizeof(soap->tmpbuf))
+ n = sizeof(soap->tmpbuf) - 1;
+ strncpy(soap->tmpbuf, tag, n);
+ soap->tmpbuf[n] = '\0';
for (i = 0; soap->local_namespaces[i].id; i++)
if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
break;
@@ -13207,7 +13751,7 @@ soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *t
}
}
if (p && *p)
- { if (soap_send(soap, *p))
+ { if (soap_send(soap, *p)) /* send as-is */
return soap->error;
}
if (t)
@@ -13261,8 +13805,11 @@ soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const cha
const char *t = NULL;
if (tag && *tag != '-')
{ if (soap->local_namespaces && (t = strchr(tag, ':')))
- { strncpy(soap->tmpbuf, tag, t-tag);
- soap->tmpbuf[t-tag] = '\0';
+ { size_t n = t - tag;
+ if (n >= sizeof(soap->tmpbuf))
+ n = sizeof(soap->tmpbuf) - 1;
+ strncpy(soap->tmpbuf, tag, n);
+ soap->tmpbuf[n] = '\0';
for (i = 0; soap->local_namespaces[i].id; i++)
if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id))
break;
@@ -13277,14 +13824,12 @@ soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const cha
if (soap_element_begin_out(soap, t, 0, type))
return soap->error;
}
- if (soap_send(soap, soap->tmpbuf))
- return soap->error;
}
if (p)
{ wchar_t c;
const wchar_t *s = *p;
while ((c = *s++))
- { if (soap_pututf8(soap, (unsigned long)c))
+ { if (soap_pututf8(soap, (unsigned long)c)) /* send as-is in UTF8 */
return soap->error;
}
}
@@ -13359,6 +13904,7 @@ soap_value(struct soap *soap)
break;
}
s[1] = '\0';
+ soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0'; /* appease */
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf));
if (c == SOAP_TT || c == SOAP_LT || (int)c == EOF)
soap_unget(soap, c);
@@ -13392,11 +13938,11 @@ soap_getline(struct soap *soap, char *s, int len)
return soap->error = SOAP_CHK_EOF;
*s++ = (char)c;
}
+ *s = '\0';
if (c != '\n')
c = soap_getchar(soap); /* got \r or something else, now get \n */
if (c == '\n')
- { *s = '\0';
- if (i+1 == len) /* empty line: end of HTTP/MIME header */
+ { if (i + 1 == len) /* empty line: end of HTTP/MIME header */
break;
c = soap_get0(soap);
if (c != ' ' && c != '\t') /* HTTP line continuation? */
@@ -13404,7 +13950,7 @@ soap_getline(struct soap *soap, char *s, int len)
}
else if ((int)c == EOF)
return soap->error = SOAP_CHK_EOF;
- if (i < 0)
+ if (i <= 0)
return soap->error = SOAP_HDR;
}
return SOAP_OK;
@@ -13464,7 +14010,7 @@ soap_count_attachments(struct soap *soap)
/* count \r\n--boundary-- */
count += 6 + n;
}
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count=%lu\n", (unsigned long)count));
return count;
#else
return soap->count;
@@ -13662,7 +14208,7 @@ soap_getdimefield(struct soap *soap, size_t n)
*s++ = (char)c;
}
*s = '\0';
- if ((soap->error = soap_move(soap, -(long)n&3)))
+ if ((soap->error = soap_move(soap, (size_t)(-(long)n&3))))
return NULL;
}
else
@@ -13689,7 +14235,7 @@ soap_getdimehdr(struct soap *soap)
return soap->error = SOAP_DIME_END;
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n"));
if (soap->dime.buflen || soap->dime.chunksize)
- { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap))))
+ { if (soap_move(soap, soap->dime.size - soap_tell(soap)))
return soap->error = SOAP_CHK_EOF;
soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n"));
@@ -13707,7 +14253,7 @@ soap_getdimehdr(struct soap *soap)
optlen = (tmp[2] << 8) | tmp[3];
idlen = (tmp[4] << 8) | tmp[5];
typelen = (tmp[6] << 8) | tmp[7];
- soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11];
+ soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]);
DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags));
if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error)
return soap->error;
@@ -13715,7 +14261,7 @@ soap_getdimehdr(struct soap *soap)
return soap->error;
if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error)
return soap->error;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "", soap->dime.options ? soap->dime.options+4 : SOAP_STR_EOS));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id='%s', type='%s', options='%s'\n", soap->dime.id ? soap->dime.id : SOAP_STR_EOS, soap->dime.type ? soap->dime.type : "", soap->dime.options ? soap->dime.options+4 : SOAP_STR_EOS));
if (soap->dime.flags & SOAP_DIME_ME)
soap->mode &= ~SOAP_ENC_DIME;
return SOAP_OK;
@@ -13733,10 +14279,10 @@ soap_getdime(struct soap *soap)
{ while (soap->dime.flags & SOAP_DIME_CF)
{ if (soap_getdimehdr(soap))
return soap->error;
- if (soap_move(soap, (long)soap->dime.size))
+ if (soap_move(soap, soap->dime.size))
return soap->error = SOAP_EOF;
}
- if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap))))
+ if (soap_move(soap, (size_t)(((soap->dime.size+3)&(~3)) - soap_tell(soap))))
return soap->error = SOAP_EOF;
for (;;)
{ register struct soap_multipart *content;
@@ -13768,7 +14314,7 @@ soap_getdime(struct soap *soap)
goto end;
}
}
- if (soap_move(soap, -(long)soap->dime.size&3))
+ if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
{ soap->error = SOAP_EOF;
break;
}
@@ -13796,6 +14342,10 @@ end:
{ register soap_wchar c;
register size_t i;
register char *s;
+ if (soap->dime.size > SOAP_MAXDIMESIZE)
+ { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu exceeds SOAP_MAXDIMESIZE=%lu\n", (unsigned long)soap->dime.size, (unsigned long)SOAP_MAXDIMESIZE));
+ return soap->error = SOAP_DIME_ERROR;
+ }
s = (char*)soap_push_block(soap, NULL, soap->dime.size);
if (!s)
return soap->error = SOAP_EOM;
@@ -13804,17 +14354,17 @@ end:
return soap->error = SOAP_EOF;
*s++ = (char)c;
}
- if (soap_move(soap, -(long)soap->dime.size&3))
+ if (soap_move(soap, (size_t)(-(long)soap->dime.size&3)))
return soap->error = SOAP_EOF;
if (!(soap->dime.flags & SOAP_DIME_CF))
break;
if (soap_getdimehdr(soap))
return soap->error;
}
- soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */
+ soap->dime.size = soap->blist->size++; /* allocate one more byte in blist for the terminating '\0' */
if (!(soap->dime.ptr = soap_save_block(soap, NULL, NULL, 0)))
return soap->error;
- soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */
+ soap->dime.ptr[soap->dime.size] = '\0'; /* make 0-terminated */
soap->dime.id = id;
soap->dime.type = type;
soap->dime.options = options;
@@ -13967,7 +14517,7 @@ soap_get_mime_attachment(struct soap *soap, void *handle)
return NULL;
}
}
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id ? content->id : SOAP_STR_EOS, content->type ? content->type : SOAP_STR_EOS));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id='%s' type='%s'\n", content->id ? content->id : SOAP_STR_EOS, content->type ? content->type : SOAP_STR_EOS));
if (!content->ptr && soap_new_block(soap) == NULL)
{ soap->error = SOAP_EOM;
return NULL;
@@ -13988,7 +14538,9 @@ soap_get_mime_attachment(struct soap *soap, void *handle)
{ if (!flag)
{ c = soap_get1(soap);
if ((int)c == EOF)
- { soap->error = SOAP_CHK_EOF;
+ { if (content->ptr && soap->fmimewriteclose)
+ soap->fmimewriteclose(soap, (void*)content->ptr);
+ soap->error = SOAP_CHK_EOF;
return NULL;
}
}
@@ -14001,7 +14553,9 @@ soap_get_mime_attachment(struct soap *soap, void *handle)
do c = soap_getchar(soap);
while (c == *t++);
if ((int)c == EOF)
- { soap->error = SOAP_CHK_EOF;
+ { if (content->ptr && soap->fmimewriteclose)
+ soap->fmimewriteclose(soap, (void*)content->ptr);
+ soap->error = SOAP_CHK_EOF;
return NULL;
}
if (!*--t)
@@ -14021,7 +14575,7 @@ soap_get_mime_attachment(struct soap *soap, void *handle)
}
}
end:
- *s = '\0'; /* force 0-terminated */
+ *s = '\0'; /* make 0-terminated */
if (content->ptr)
{ if (!soap->error && soap->fmimewrite)
soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i);
@@ -14031,7 +14585,7 @@ end:
return NULL;
}
else
- { content->size = soap_size_block(soap, NULL, i+1)-1;
+ { content->size = soap_size_block(soap, NULL, i+1) - 1; /* last block with '\0' */
content->ptr = soap_save_block(soap, NULL, NULL, 0);
}
soap_resolve_attachment(soap, content);
@@ -14095,11 +14649,11 @@ static void
soap_resolve_attachment(struct soap *soap, struct soap_multipart *content)
{ if (content->id)
{ register struct soap_xlist **xp = &soap->xlist;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id='%s'\n", content->id));
while (*xp)
{ register struct soap_xlist *xq = *xp;
if (!soap_match_cid(soap, xq->id, content->id))
- { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id));
+ { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment id='%s' for content id='%s'\n", xq->id, content->id));
*xp = xq->next;
*xq->ptr = (unsigned char*)content->ptr;
*xq->size = (int)content->size;
@@ -14126,7 +14680,7 @@ int
SOAP_FMAC2
soap_putmimehdr(struct soap *soap, struct soap_multipart *content)
{ const char *s;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type ? content->type : SOAP_STR_EOS));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type='%s'\n", content->type ? content->type : SOAP_STR_EOS));
if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n"))
return soap->error;
if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n"))
@@ -14489,7 +15043,7 @@ int
SOAP_FMAC2
soap_begin_recv(struct soap *soap)
{ register soap_wchar c;
- DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n"));
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input from socket=%d/fd=%d\n", soap->socket, soap->recvfd));
soap->error = SOAP_OK;
soap->filterstop = SOAP_OK;
soap_free_temp(soap);
@@ -14513,6 +15067,7 @@ soap_begin_recv(struct soap *soap)
soap->level = 0;
soap->part = SOAP_BEGIN;
soap->alloced = 0;
+ soap->body = 1;
soap->count = 0;
soap->length = 0;
soap->cdata = 0;
@@ -14625,8 +15180,8 @@ soap_begin_recv(struct soap *soap)
return soap->error = SOAP_CHK_EOF;
soap_unget(soap, c);
#ifndef WITH_NOHTTP
- /* if not XML or MIME/DIME/ZLIB, assume HTTP header */
- if (c != '<' && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB)))
+ /* if not XML/MIME/DIME/ZLIB, assume HTTP method or status line */
+ if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB | SOAP_ENC_XML)))
{ soap_mode m = soap->imode;
soap->mode &= ~SOAP_IO;
soap->error = soap->fparse(soap);
@@ -14653,17 +15208,19 @@ soap_begin_recv(struct soap *soap)
soap->chunksize = 0;
}
/* Note: fparse should not use soap_unget to push back last char */
- if (soap_get0(soap) == (int)EOF)
- { if (soap->status == 200)
- return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */
+#if 0
+ if (soap->status > 200 && soap->length == 0 && !(soap->http_content && (!soap->keep_alive || soap->recv_timeout)) && (soap->imode & SOAP_IO) != SOAP_IO_CHUNK)
+#endif
+ if (soap->status && !soap->body)
return soap->error = soap->status;
- }
#ifdef WITH_ZLIB
if (soap->zlib_in != SOAP_ZLIB_NONE)
{
#ifdef WITH_GZIP
if (soap->zlib_in != SOAP_ZLIB_DEFLATE)
{ c = soap_get1(soap);
+ if (c == (int)EOF)
+ return soap->error = SOAP_EOF;
if (c == 0x1F)
{ if (soap_getgziphdr(soap))
return soap->error;
@@ -14702,10 +15259,16 @@ soap_begin_recv(struct soap *soap)
#ifndef WITH_LEANER
if (soap->fpreparerecv && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK && soap->buflen > soap->bufidx)
{ int r;
+ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Invoking fpreparerecv\n"));
if ((r = soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx)))
return soap->error = r;
}
#endif
+ if (soap_get0(soap) == (int)EOF)
+ { if (soap->status == 0 || soap->status == 200)
+ return soap->error = SOAP_NO_DATA; /* HTTP OK: always expect data */
+ return soap->error = soap->status;
+ }
if (soap->error)
{ if (soap->error == SOAP_FORM && soap->fform)
{ soap->error = soap->fform(soap);
@@ -14779,7 +15342,11 @@ soap_envelope_begin_out(struct soap *soap)
s = "application/xop+xml; charset=utf-8; type=\"text/xml\"";
else
s = "text/xml; charset=utf-8";
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start);
+#else
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);
+#endif
n = strlen(soap->tmpbuf);
if (soap_send_raw(soap, soap->tmpbuf, n))
return soap->error;
@@ -14791,6 +15358,8 @@ soap_envelope_begin_out(struct soap *soap)
return soap->error;
}
#endif
+ if (soap->version == 0)
+ return SOAP_OK;
soap->part = SOAP_IN_ENVELOPE;
return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL);
}
@@ -14802,13 +15371,19 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_envelope_end_out(struct soap *soap)
-{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
+{ if (soap->version == 0)
+ return SOAP_OK;
+ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")
|| soap_send_raw(soap, "\r\n", 2)) /* 2.8: always emit \r\n */
return soap->error;
#ifndef WITH_LEANER
if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM))
{ soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->id, sizeof(soap->id), soap->dime_id_format, 0);
+#else
sprintf(soap->id, soap->dime_id_format, 0);
+#endif
soap->dime.id = soap->id;
if (soap->local_namespaces)
{ if (soap->local_namespaces[0].out)
@@ -14836,17 +15411,19 @@ soap_envelope_end_out(struct soap *soap)
SOAP_FMAC1
char*
SOAP_FMAC2
-soap_get_http_body(struct soap *soap)
-{
+soap_get_http_body(struct soap *soap, size_t *len)
+{ if (len)
+ *len = 0;
#ifndef WITH_LEAN
register size_t l = 0, n = 0;
register char *s;
- /* get HTML body of HTTP error content */
+ /* get HTTP body length */
if (!(soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) != SOAP_IO_CHUNK)
{ n = soap->length;
if (!n)
return NULL;
}
+ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Parsing HTTP body (mode=0x%x,len=%lu)\n", soap->mode, (unsigned long)n));
#ifdef WITH_FAST
soap->labidx = 0; /* use look-aside buffer */
#else
@@ -14872,7 +15449,7 @@ soap_get_http_body(struct soap *soap)
l++;
if (n > 0 && l > n)
goto end;
- c = soap_getchar(soap);
+ c = soap_get1(soap);
if ((int)c == EOF)
goto end;
*s++ = (char)(c & 0xFF);
@@ -14880,8 +15457,11 @@ soap_get_http_body(struct soap *soap)
}
end:
*s = '\0';
+ if (len)
+ *len = l - 1; /* len excludes terminating \0 */
#ifdef WITH_FAST
- s = soap_strdup(soap, soap->labbuf);
+ if ((s = (char*)soap_malloc(soap, l)))
+ memcpy(s, soap->labbuf, l);
#else
soap_size_block(soap, NULL, i+1);
s = soap_save_block(soap, NULL, 0);
@@ -14903,9 +15483,13 @@ soap_envelope_begin_in(struct soap *soap)
{ register struct Namespace *p;
soap->part = SOAP_IN_ENVELOPE;
if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL))
- { if (soap->error == SOAP_TAG_MISMATCH
- && !soap_element_begin_in(soap, "Envelope", 0, NULL))
- soap->error = SOAP_VERSIONMISMATCH;
+ { if (soap->error == SOAP_TAG_MISMATCH)
+ { if (!soap_element_begin_in(soap, "Envelope", 0, NULL))
+ soap->error = SOAP_VERSIONMISMATCH;
+ else if (soap->status == 0 || (soap->status >= 200 && soap->status <= 299))
+ return SOAP_OK; /* allow non-SOAP XML content to be captured */
+ soap->error = soap->status;
+ }
else if (soap->status)
soap->error = soap->status;
return soap->error;
@@ -14940,7 +15524,9 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_envelope_end_in(struct soap *soap)
-{ soap->part = SOAP_END_ENVELOPE;
+{ if (soap->version == 0)
+ return SOAP_OK;
+ soap->part = SOAP_END_ENVELOPE;
return soap_element_end_in(soap, "SOAP-ENV:Envelope");
}
#endif
@@ -14951,13 +15537,15 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_body_begin_out(struct soap *soap)
-{ soap->part = SOAP_IN_BODY;
- if (soap->version == 1)
+{ if (soap->version == 1)
soap->encoding = 1;
#ifndef WITH_LEAN
if ((soap->mode & SOAP_SEC_WSUID) && soap_set_attr(soap, "wsu:Id", "Body", 1))
return soap->error;
#endif
+ if (soap->version == 0)
+ return SOAP_OK;
+ soap->part = SOAP_IN_BODY;
return soap_element_begin_out(soap, "SOAP-ENV:Body", 0, NULL);
}
#endif
@@ -14968,7 +15556,9 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_body_end_out(struct soap *soap)
-{ if (soap_element_end_out(soap, "SOAP-ENV:Body"))
+{ if (soap->version == 0)
+ return SOAP_OK;
+ if (soap_element_end_out(soap, "SOAP-ENV:Body"))
return soap->error;
soap->part = SOAP_END_BODY;
return SOAP_OK;
@@ -14981,7 +15571,9 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_body_begin_in(struct soap *soap)
-{ soap->part = SOAP_IN_BODY;
+{ if (soap->version == 0)
+ return SOAP_OK;
+ soap->part = SOAP_IN_BODY;
if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL))
return soap->error;
if (!soap->body)
@@ -14996,7 +15588,9 @@ SOAP_FMAC1
int
SOAP_FMAC2
soap_body_end_in(struct soap *soap)
-{ if (soap->part == SOAP_NO_BODY)
+{ if (soap->version == 0)
+ return SOAP_OK;
+ if (soap->part == SOAP_NO_BODY)
return soap->error = SOAP_OK;
soap->part = SOAP_END_BODY;
return soap_element_end_in(soap, "SOAP-ENV:Body");
@@ -15036,7 +15630,7 @@ soap_set_endpoint(struct soap *soap, const char *endpoint)
if (!soap_tag_cmp(endpoint, "https:*"))
soap->port = 443;
#endif
- strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1);
+ strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint));
soap->endpoint[sizeof(soap->endpoint) - 1] = '\0';
s = strchr(endpoint, ':');
if (s && s[1] == '/' && s[2] == '/')
@@ -15198,7 +15792,7 @@ soap_try_connect_command(struct soap *soap, int http_command, const char *endpoi
soap->mode = k;
}
if (http_command == SOAP_GET || http_command == SOAP_DEL)
- return soap_end_send(soap);
+ return soap_end_send_flush(soap);
#endif
return SOAP_OK;
}
@@ -15222,6 +15816,8 @@ soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const
size_t c = soap->count;
soap_mode m = soap->mode, o = soap->omode;
int s = soap->status;
+ char *a = soap->action;
+ short v = soap->version;
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM '%s'\n", soap->ntlm_challenge));
if (!*soap->ntlm_challenge)
{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "NTLM S->C Type 1: received NTLM authentication challenge from server\n"));
@@ -15240,7 +15836,7 @@ soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const
soap->keep_alive = 1;
soap->status = command;
if (soap->fpost(soap, endpoint, host, port, soap->path, soap->action, 0)
- || soap_end_send(soap))
+ || soap_end_send_flush(soap))
return soap->error;
soap->mode = m;
soap->keep_alive = k;
@@ -15248,7 +15844,7 @@ soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const
oldheader = soap->header;
if (soap_begin_recv(soap))
if (soap->error == SOAP_EOF)
- return soap->error;
+ return soap->error;
soap_end_recv(soap);
soap->header = oldheader;
soap->length = l;
@@ -15266,12 +15862,18 @@ soap_ntlm_handshake(struct soap *soap, int command, const char *endpoint, const
/* C -> S GET ...
Authorization: NTLM TlRMTVNTUAADAAAAGAAYAHIAAAAYABgAigAAABQAFABAAAAADAAMAFQAAAASABIAYAAAAAAAAACiAAAAAYIAAFUAUgBTAEEALQBNAEkATgBPAFIAWgBhAHAAaABvAGQATABJAEcASABUAEMASQBUAFkArYfKbe/jRoW5xDxHeoxC1gBmfWiS5+iX4OAN4xBKG/IFPwfH3agtPEia6YnhsADT
*/
+ soap->userid = NULL;
+ soap->passwd = NULL;
+ soap->proxy_userid = NULL;
+ soap->proxy_passwd = NULL;
soap->keep_alive = k;
soap->length = l;
soap->count = c;
soap->mode = m;
soap->omode = o;
soap->status = s;
+ soap->action = a;
+ soap->version = v;
}
return SOAP_OK;
}
@@ -15304,13 +15906,13 @@ soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n)
t += 4;
}
t[0] = '\0';
- if (n > 0)
+ if (n > 0) /* 0 < n <= 2 implies that t[0..4] is allocated (base64 scaling formula) */
{ m = 0;
for (i = 0; i < n; i++)
m = (m << 8) | *s++;
for (; i < 3; i++)
m <<= 8;
- for (i++; i > 0; m >>= 6)
+ for (i = 4; i > 0; m >>= 6)
t[--i] = soap_base64o[m & 0x3F];
for (i = 3; i > n; i--)
t[i] = '=';
@@ -15346,58 +15948,57 @@ soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n)
p = t;
if (n)
*n = 0;
- for (;;)
- { for (i = 0; i < SOAP_BLKLEN; i++)
- { m = 0;
- j = 0;
- while (j < 4)
- { c = *s++;
- if (c == '=' || !c)
- { i *= 3;
- switch (j)
+ for (i = 0; ; i += 3, l -= 3)
+ { m = 0;
+ j = 0;
+ while (j < 4)
+ { c = *s++;
+ if (c == '=' || !c)
+ { if (l >= j - 1)
+ { switch (j)
{ case 2:
*t++ = (char)((m >> 4) & 0xFF);
i++;
+ l--;
break;
case 3:
*t++ = (char)((m >> 10) & 0xFF);
*t++ = (char)((m >> 2) & 0xFF);
i += 2;
+ l -= 2;
}
- if (n)
- *n += (int)i;
- if (l >= j)
- *t = '\0';
- return p;
- }
- c -= '+';
- if (c >= 0 && c <= 79)
- { int b = soap_base64i[c];
- if (b >= 64)
- { soap->error = SOAP_TYPE;
- return NULL;
- }
- m = (m << 6) + b;
- j++;
}
- else if (!soap_blank(c + '+'))
+ if (n)
+ *n = (int)i;
+ if (l)
+ *t = '\0';
+ return p;
+ }
+ c -= '+';
+ if (c >= 0 && c <= 79)
+ { int b = soap_base64i[c];
+ if (b >= 64)
{ soap->error = SOAP_TYPE;
return NULL;
}
+ m = (m << 6) + b;
+ j++;
}
- if (l < 3)
- { if (n)
- *n += (int)i;
- *t = '\0';
- return p;
+ else if (!soap_blank(c + '+'))
+ { soap->error = SOAP_TYPE;
+ return NULL;
}
- *t++ = (char)((m >> 16) & 0xFF);
- *t++ = (char)((m >> 8) & 0xFF);
- *t++ = (char)(m & 0xFF);
- l -= 3;
}
- if (n)
- *n += 3 * SOAP_BLKLEN;
+ if (l < 3)
+ { if (n)
+ *n = (int)i;
+ if (l)
+ *t = '\0';
+ return p;
+ }
+ *t++ = (char)((m >> 16) & 0xFF);
+ *t++ = (char)((m >> 8) & 0xFF);
+ *t++ = (char)(m & 0xFF);
}
}
#endif
@@ -15481,7 +16082,7 @@ soap_puthttphdr(struct soap *soap, int status, size_t count)
#ifndef WITH_LEANER
register const char *r = NULL;
#endif
- if ((status == SOAP_FILE || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE) && soap->http_content)
+ if ((status == SOAP_FILE || soap->status == SOAP_PUT || soap->status == SOAP_POST_FILE) && soap->http_content && !strchr(s, 10) && !strchr(s, 13))
s = soap->http_content;
else if (status == SOAP_HTML)
s = "text/html; charset=utf-8";
@@ -15502,31 +16103,42 @@ soap_puthttphdr(struct soap *soap, int status, size_t count)
s = "application/dime";
}
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)
- { register const char *t = strchr(s, ';');
+ { register const char *t;
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
+#else
sprintf(soap->tmpbuf, "multipart/related; charset=utf-8; boundary=\"%s\"; type=\"", soap->mime.boundary);
+#endif
+ t = strchr(s, ';');
if (t)
- { strncat(soap->tmpbuf, s, t - s);
- soap->tmpbuf[sizeof(soap->tmpbuf)-1] = '\0';
- }
+ strncat(soap->tmpbuf, s, t - s);
else
strcat(soap->tmpbuf, s);
- if (soap->mime.start)
+ if (soap->mime.start && strlen(soap->tmpbuf) + strlen(soap->mime.start) + 11 < sizeof(soap->tmpbuf))
{ strcat(soap->tmpbuf, "\"; start=\"");
strcat(soap->tmpbuf, soap->mime.start);
}
strcat(soap->tmpbuf, "\"");
- if (r)
+ if (r && strlen(soap->tmpbuf) + strlen(r) + 15 < sizeof(soap->tmpbuf))
{ strcat(soap->tmpbuf, "; start-info=\"");
strcat(soap->tmpbuf, r);
strcat(soap->tmpbuf, "\"");
}
- s = soap->tmpbuf;
}
else
- s = strcpy(soap->tmpbuf, s);
+ strncpy(soap->tmpbuf, s, sizeof(soap->tmpbuf));
+ soap->tmpbuf[sizeof(soap->tmpbuf) - 1] = '\0';
+ s = soap->tmpbuf;
if (status == SOAP_OK && soap->version == 2 && soap->action && strlen(soap->action) + strlen(s) < sizeof(soap->tmpbuf) - 80)
+ {
+#ifdef HAVE_SNPRINTF
+ size_t l = strlen(s);
+ soap_snprintf(soap->tmpbuf + l, sizeof(soap->tmpbuf) - l, "; action=\"%s\"", soap->action);
+#else
sprintf(soap->tmpbuf + strlen(s), "; action=\"%s\"", soap->action);
#endif
+ }
+#endif
if ((err = soap->fposthdr(soap, "Content-Type", s)))
return err;
#ifdef WITH_ZLIB
@@ -15547,7 +16159,12 @@ soap_puthttphdr(struct soap *soap, int status, size_t count)
else
#endif
if (s)
- { sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "%lu", (unsigned long)count);
+#else
+ sprintf(soap->tmpbuf, "%lu", (unsigned long)count);
+#endif
err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf);
}
if (err)
@@ -15562,18 +16179,30 @@ soap_puthttphdr(struct soap *soap, int status, size_t count)
#ifndef WITH_LEAN
static const char*
soap_set_validation_fault(struct soap *soap, const char *s, const char *t)
-{ if (*soap->tag)
+{ if (!t)
+ t = SOAP_STR_EOS;
+ if (*soap->tag)
+ {
#ifdef HAVE_SNPRINTF
soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s in element '%s'", s, t ? t : SOAP_STR_EOS, soap->tag);
#else
- sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t ? t : SOAP_STR_EOS, soap->tag);
+ if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
+ sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element '%s'", s, t, soap->tag);
+ else
+ sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
#endif
+ }
else
+ {
#ifdef HAVE_SNPRINTF
soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Validation constraint violation: %s%s", s, t ? t : SOAP_STR_EOS);
#else
- sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t ? t : SOAP_STR_EOS);
+ if (strlen(soap->tag) + strlen(t) < sizeof(soap->msgbuf) - 100)
+ sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t);
+ else
+ sprintf(soap->msgbuf, "Validation constraint violation: %s", s);
#endif
+ }
return soap->msgbuf;
}
#endif
@@ -15622,7 +16251,8 @@ soap_set_fault(struct soap *soap)
#ifdef HAVE_SNPRINTF
soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "The data in element '%s' must be understood but cannot be handled", soap->tag);
#else
- sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag);
+ strncpy(soap->msgbuf, soap->tag, sizeof(soap->msgbuf));
+ soap->msgbuf[sizeof(soap->msgbuf) - 1] = '\0';
#endif
*s = soap->msgbuf;
break;
@@ -15679,7 +16309,7 @@ soap_set_fault(struct soap *soap)
*s = soap_set_validation_fault(soap, "nil not allowed", NULL);
break;
case SOAP_DUPLICATE_ID:
- *s = soap_set_validation_fault(soap, "multiple definitions (use the SOAP_XML_TREE flag) of the same id ", soap->id);
+ *s = soap_set_validation_fault(soap, "multiple elements (use the SOAP_XML_TREE flag) with duplicate id ", soap->id);
if (soap->version == 2)
*soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID";
break;
@@ -15689,7 +16319,7 @@ soap_set_fault(struct soap *soap)
*soap_faultsubcode(soap) = "SOAP-ENC:MissingID";
break;
case SOAP_HREF:
- *s = soap_set_validation_fault(soap, "incompatible object type ref/id pair ", soap->id);
+ *s = soap_set_validation_fault(soap, "incompatible object type id-ref ", soap->id);
break;
case SOAP_FAULT:
break;
@@ -15718,7 +16348,7 @@ soap_set_fault(struct soap *soap)
*s = "Plugin registry error";
break;
case SOAP_DIME_ERROR:
- *s = "DIME format error";
+ *s = "DIME format error or max DIME size exceeds SOAP_MAXDIMESIZE";
break;
case SOAP_DIME_HREF:
*s = "DIME href to missing attachment";
@@ -15774,14 +16404,13 @@ soap_set_fault(struct soap *soap)
#endif
case SOAP_EOF:
#ifndef WITH_NOIO
- strcpy(soap->msgbuf, soap_strerror(soap));
+ *s = soap_strerror(soap); /* *s = soap->msgbuf */
#ifndef WITH_LEAN
if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf))
{ memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1);
memcpy(soap->msgbuf, "End of file or no input: ", 25);
}
#endif
- *s = soap->msgbuf;
break;
#else
*s = "End of file or no input";
@@ -15802,7 +16431,12 @@ soap_set_fault(struct soap *soap)
else
#endif
#endif
- { sprintf(soap->msgbuf, "Error %d", soap->error);
+ {
+#ifdef HAVE_SNPRINTF
+ soap_snprintf(soap->msgbuf, sizeof(soap->msgbuf), "Error %d", soap->error);
+#else
+ sprintf(soap->msgbuf, "Error %d", soap->error);
+#endif
*s = soap->msgbuf;
}
}
@@ -15816,7 +16450,7 @@ int
SOAP_FMAC2
soap_send_fault(struct soap *soap)
{ register int status = soap->error;
- if (status == SOAP_STOP)
+ if (status == SOAP_OK || status == SOAP_STOP)
return soap_closesock(soap);
DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error));
soap->keep_alive = 0; /* to terminate connection */
@@ -15824,7 +16458,7 @@ soap_send_fault(struct soap *soap)
if (soap->error < 200 && soap->error != SOAP_FAULT)
soap->header = NULL;
if (status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout))
- { int r = 1;
+ { register int r = 1;
#ifndef WITH_NOIO
if (soap->fpoll && soap->fpoll(soap))
r = 0;
@@ -15832,9 +16466,10 @@ soap_send_fault(struct soap *soap)
else if (soap_valid_socket(soap->socket))
{ r = tcp_select(soap, soap->socket, SOAP_TCP_SELECT_RCV | SOAP_TCP_SELECT_SND, 0);
if (r > 0)
- { if (!(r & SOAP_TCP_SELECT_SND)
+ { int t;
+ if (!(r & SOAP_TCP_SELECT_SND)
|| ((r & SOAP_TCP_SELECT_RCV)
- && recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0))
+ && recv(soap->socket, (char*)&t, 1, MSG_PEEK) < 0))
r = 0;
}
}
@@ -15842,6 +16477,7 @@ soap_send_fault(struct soap *soap)
#endif
if (r > 0)
{ soap->error = SOAP_OK;
+ soap->encodingStyle = NULL; /* no encodingStyle in Faults */
soap_serializeheader(soap);
soap_serializefault(soap);
soap_begin_count(soap);
@@ -15884,6 +16520,8 @@ soap_recv_fault(struct soap *soap, int check)
&& (soap->error != SOAP_TAG_MISMATCH || soap->level != 2))
return soap->error;
}
+ else if (soap->version == 0) /* check == 1 but no SOAP: do not parse SOAP Fault */
+ return SOAP_OK;
soap->error = SOAP_OK;
if (soap_getfault(soap))
{ /* check flag set: check if SOAP Fault is present, if not just return */
@@ -15929,8 +16567,9 @@ soap_send_empty_response(struct soap *soap, int httpstatuscode)
{ soap->count = 0;
if ((m & SOAP_IO) == SOAP_IO_CHUNK)
soap->omode = (m & ~SOAP_IO) | SOAP_IO_BUFFER;
- if (!soap_response(soap, httpstatuscode) && !soap_end_send(soap))
- soap->error = SOAP_STOP; /* stops the server's processing of request */
+ soap_response(soap, httpstatuscode);
+ soap_end_send(soap); /* force end of sends */
+ soap->error = SOAP_STOP; /* stops the server (from returning a response) */
soap->omode = m;
}
return soap_closesock(soap);
@@ -15947,7 +16586,13 @@ SOAP_FMAC2
soap_recv_empty_response(struct soap *soap)
{ if (!(soap->omode & SOAP_IO_UDP))
{ if (!soap_begin_recv(soap))
+ {
+#ifndef WITH_LEAN
+ if (soap->body)
+ soap_get_http_body(soap, NULL); /* read (empty?) HTTP body and discard */
+#endif
soap_end_recv(soap);
+ }
else if (soap->error == SOAP_NO_DATA || soap->error == 202)
soap->error = SOAP_OK;
}
@@ -15962,11 +16607,16 @@ soap_recv_empty_response(struct soap *soap)
static const char*
soap_strerror(struct soap *soap)
{ register int err = soap->errnum;
+ *soap->msgbuf = '\0';
if (err)
{
#ifndef WIN32
# ifdef HAVE_STRERROR_R
- strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf));
+# ifdef _GNU_SOURCE
+ return strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* GNU-specific */
+# else
+ strerror_r(err, soap->msgbuf, sizeof(soap->msgbuf)); /* XSI-compliant */
+# endif
# else
return strerror(err);
# endif
@@ -16005,10 +16655,24 @@ soap_strerror(struct soap *soap)
su = 'u';
}
if (rt)
- sprintf(s + strlen(s), " (%d%cs receive delay)", rt, ru);
+ {
+#ifdef HAVE_SNPRINTF
+ size_t l = strlen(s);
+ soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs recv delay)", rt, ru);
+#else
+ sprintf(s + strlen(s), " (%d%cs recv delay)", rt, ru);
+#endif
+ }
if (st)
+ {
+#ifdef HAVE_SNPRINTF
+ size_t l = strlen(s);
+ soap_snprintf(s + l, sizeof(soap->msgbuf) - l, " (%d%cs send delay)", st, su);
+#else
sprintf(s + strlen(s), " (%d%cs send delay)", st, su);
#endif
+ }
+#endif
}
return soap->msgbuf;
}
@@ -16175,7 +16839,9 @@ char*
SOAP_FMAC2
soap_sprint_fault(struct soap *soap, char *buf, size_t len)
{ if (soap_check_state(soap))
- strncpy(buf, "Error: soap struct not initialized", len);
+ { strncpy(buf, "Error: soap struct not initialized", len);
+ buf[len - 1] = '\0';
+ }
else if (soap->error)
{ const char **c, *v = NULL, *s, *d;
c = soap_faultcode(soap);