diff options
author | suranex <rian_mller@yahoo.de> | 2014-06-22 14:33:51 +0200 |
---|---|---|
committer | suranex <rian_mller@yahoo.de> | 2014-06-22 14:33:51 +0200 |
commit | b3aebb21eceb30f565da97239c5fdfa2da94d3e8 (patch) | |
tree | 4e7430dcba8448e1f1521fdda5b91e0631814d41 /dep/gsoap/stdsoap2.cpp | |
parent | 5e80f86514f27b1aab04518d56faa814093a8d3f (diff) |
Core/Dependencies: Update gsoap-library to v2.8.17r
Diffstat (limited to 'dep/gsoap/stdsoap2.cpp')
-rw-r--r-- | dep/gsoap/stdsoap2.cpp | 1758 |
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); |